From 7170543e8012250b7643a960b54cce7fd6d3a1e9 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Wed, 8 Nov 2017 10:27:39 -0800 Subject: [PATCH 01/50] Make direction-aware borders work with APIs >= 17 Reviewed By: achen1 Differential Revision: D6189497 fbshipit-source-id: 848ca35540c5a4eb1581e0b7c39f8fa880540317 --- .../view/ReactViewBackgroundDrawable.java | 38 ++++++++++++++----- .../react/views/view/ReactViewGroup.java | 10 ++--- 2 files changed, 34 insertions(+), 14 deletions(-) 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..b32855b1450625 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, @@ -290,6 +291,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 +343,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 +498,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; @@ -930,8 +950,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 +1160,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..8e80168a33b29e 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); } } } @@ -589,12 +589,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 +671,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( From 1d6ce2311f6a51821b33c5473414d70c8bd34425 Mon Sep 17 00:00:00 2001 From: Yujie Liu Date: Wed, 8 Nov 2017 12:00:40 -0800 Subject: [PATCH 02/50] Rename scaledAssetURLScript function to scaledAssetURLNearBundle Reviewed By: zahanm Differential Revision: D6272905 fbshipit-source-id: bff661fcadd73a5400cea422a8a5ac5db34717a8 --- Libraries/Image/AssetSourceResolver.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Libraries/Image/AssetSourceResolver.js b/Libraries/Image/AssetSourceResolver.js index ae759c719b84e8..2183d1a98904d2 100644 --- a/Libraries/Image/AssetSourceResolver.js +++ b/Libraries/Image/AssetSourceResolver.js @@ -79,7 +79,7 @@ class AssetSourceResolver { this.drawableFolderInBundle() : this.resourceIdentifierWithoutScale(); } else { - return this.scaledAssetURLInScript(); + return this.scaledAssetURLNearBundle(); } } @@ -104,10 +104,10 @@ class AssetSourceResolver { } /** - * Resolves to where the script is running from, with a scaled asset filename + * Resolves to where the bundle is running from, with a scaled asset filename * E.g. 'file:///sdcard/bundle/assets/AwesomeModule/icon@2x.png' */ - scaledAssetURLInScript(): ResolvedAssetSource { + scaledAssetURLNearBundle(): ResolvedAssetSource { const path = this.jsbundleUrl || 'file://'; return this.fromSource(path + getScaledAssetPath(this.asset)); } From 354e1cb5088a43fd4116504a34a65ca53c4de71b Mon Sep 17 00:00:00 2001 From: Erik Behrends Date: Wed, 8 Nov 2017 12:07:30 -0800 Subject: [PATCH 03/50] Fix missing return in example Summary: Found this minor issue while reading the docs. n/a [DOCS] [BUGFIX] [Libraries/Text/Text.js] - Add return to example Closes https://github.com/facebook/react-native/pull/16752 Differential Revision: D6274215 Pulled By: hramos fbshipit-source-id: ef735eb9179ab69d2ed1bc4a8b5e921d42d88fb0 --- Libraries/Text/Text.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) 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} + * + * + * ); * } * } * ``` From e9393f694d8f0d0190a3576fd65a65f747f8cce2 Mon Sep 17 00:00:00 2001 From: Rafael Oleza Date: Wed, 8 Nov 2017 12:34:00 -0800 Subject: [PATCH 04/50] Remove old bundler code from Server class Reviewed By: mjesun Differential Revision: D6255868 fbshipit-source-id: 74695129199c8be43e13c97f2ae2ca2c03b801eb --- .../__tests__/getInverseDependencies-test.js | 57 --- local-cli/server/util/attachHMRServer.js | 459 ------------------ .../server/util/getInverseDependencies.js | 70 --- 3 files changed, 586 deletions(-) delete mode 100644 local-cli/server/util/__tests__/getInverseDependencies-test.js delete mode 100644 local-cli/server/util/attachHMRServer.js delete mode 100644 local-cli/server/util/getInverseDependencies.js diff --git a/local-cli/server/util/__tests__/getInverseDependencies-test.js b/local-cli/server/util/__tests__/getInverseDependencies-test.js deleted file mode 100644 index 5936f3e113b8dd..00000000000000 --- a/local-cli/server/util/__tests__/getInverseDependencies-test.js +++ /dev/null @@ -1,57 +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. - * - * @emails oncall+javascript_foundation - */ -'use strict'; - -jest.dontMock('../getInverseDependencies'); - -const getInverseDependencies = require('../getInverseDependencies'); - -describe('getInverseDependencies', () => { - it('', () => { - const module1 = createModule('module1', ['module2', 'module3']); - const module2 = createModule('module2', ['module3', 'module4']); - const module3 = createModule('module3', ['module4']); - const module4 = createModule('module4', []); - - const modulePairs = { - 'module1': [['module2', module2], ['module3', module3]], - 'module2': [['module3', module3], ['module4', module4]], - 'module3': [['module4', module4]], - 'module4': [], - }; - - const resolutionResponse = { - dependencies: [module1, module2, module3, module4], - getResolvedDependencyPairs: module => { - return modulePairs[module.hash()]; - }, - }; - - const dependencies = getInverseDependencies(resolutionResponse); - const actual = // jest can't compare maps and sets - Array.from(dependencies.entries()) - .map(([key, value]) => [key, Array.from(value)]); - - expect(actual).toEqual([ - [module2, [module1]], - [module3, [module1, module2]], - [module4, [module2, module3]], - ]); - }); -}); - -function createModule(name, dependencies) { - return { - hash: () => name, - getName: () => Promise.resolve(name), - getDependencies: () => Promise.resolve(dependencies), - }; -} diff --git a/local-cli/server/util/attachHMRServer.js b/local-cli/server/util/attachHMRServer.js deleted file mode 100644 index 184eb78febded2..00000000000000 --- a/local-cli/server/util/attachHMRServer.js +++ /dev/null @@ -1,459 +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. - * - * @flow - */ - -'use strict'; - -const getInverseDependencies = require('./getInverseDependencies'); -const querystring = require('querystring'); -const url = require('url'); - -import type {ResolutionResponse} from './getInverseDependencies'; -import type {Server as HTTPServer} from 'http'; -import type {Server as HTTPSServer} from 'https'; -import type {Client as WebSocketClient} from 'ws'; - -const blacklist = [ - 'Libraries/Utilities/HMRClient.js', -]; - -type HMRBundle = { - getModulesIdsAndCode(): Array<{id: string, code: string}>, - getSourceMappingURLs(): Array, - getSourceURLs(): Array, - isEmpty(): boolean, -}; - -type DependencyOptions = {| - +dev: boolean, - +entryFile: string, - +hot: boolean, - +minify: boolean, - +platform: ?string, - +recursive: boolean, - +rootEntryFile: string, - +bundlingOptions?: Object, -|}; - -/** - * This is a subset of the actual `metro-bundler`'s `Server` class, - * without all the stuff we don't need to know about. This allows us to use - * `attachHMRServer` with different versions of `metro-bundler` as long as - * this specific contract is maintained. - */ -type PackagerServer = { - buildBundleForHMR( - options: {platform: ?string}, - host: string, - port: number, - ): Promise, - getDependencies(options: DependencyOptions): Promise>, - getModuleForPath(entryFile: string): Promise, - getShallowDependencies(options: DependencyOptions): Promise>, - setHMRFileChangeListener(listener: ?(type: string, filePath: string) => mixed): void, -}; - -type HMROptions = { - httpServer: HTTPServer | HTTPSServer, - packagerServer: PackagerServer, - path: string, -}; - -type Moduleish = { - getName(): string, - isAsset(): boolean, - isJSON(): boolean, - path: string, -}; - -/** - * Attaches a WebSocket based connection to the Packager to expose - * Hot Module Replacement updates to the simulator. - */ -function attachHMRServer( - {httpServer, path, packagerServer}: HMROptions, -) { - type Client = {| - ws: WebSocketClient, - platform: string, - bundleEntry: string, - dependenciesCache: Array, - dependenciesModulesCache: {[mixed]: TModule}, - shallowDependencies: {[string]: Array}, - inverseDependenciesCache: mixed, - |}; - - const clients: Set = new Set(); - - function disconnect(client: Client) { - clients.delete(client); - - // If there are no clients connected, stop listenig for file changes - if (clients.size === 0) { - packagerServer.setHMRFileChangeListener(null); - } - } - - // For the give platform and entry file, returns a promise with: - // - The full list of dependencies. - // - The shallow dependencies each file on the dependency list has - // - Inverse shallow dependencies map - async function getDependencies(platform: string, bundleEntry: string): Promise<{ - dependenciesCache: Array, - dependenciesModulesCache: {[mixed]: TModule}, - shallowDependencies: {[string]: Array}, - inverseDependenciesCache: mixed, - /* $FlowFixMe(>=0.54.0 site=react_native_fb,react_native_oss) This comment - * suppresses an error found when Flow v0.54 was deployed. To see the error - * delete this comment and run Flow. */ - resolutionResponse: ResolutionResponse, - }> { - const response = await packagerServer.getDependencies({ - dev: true, - entryFile: bundleEntry, - rootEntryFile: bundleEntry, - hot: true, - minify: false, - platform: platform, - recursive: true, - }); - - /* $FlowFixMe: getModuleId might be null */ - const {getModuleId}: {getModuleId: () => number} = response; - - // for each dependency builds the object: - // `{path: '/a/b/c.js', deps: ['modA', 'modB', ...]}` - const deps: Array<{ - path: string, - name?: string, - deps: Array, - }> = await Promise.all(response.dependencies.map(async (dep: TModule) => { - const depName = dep.getName(); - - if (dep.isAsset() || dep.isJSON()) { - return {path: dep.path, deps: []}; - } - const dependencies = await packagerServer.getShallowDependencies({ - dev: true, - entryFile: dep.path, - rootEntryFile: bundleEntry, - hot: true, - minify: false, - platform: platform, - recursive: true, - bundlingOptions: response.options, - }); - - return { - path: dep.path, - name: depName, - deps: dependencies, - }; - })); - - // list with all the dependencies' filenames the bundle entry has - const dependenciesCache = response.dependencies.map(dep => dep.path); - - // map from module name to path - const moduleToFilenameCache = Object.create(null); - deps.forEach(dep => { - /* $FlowFixMe: `name` could be null, but `deps` would be as well. */ - moduleToFilenameCache[dep.name] = dep.path; - }); - - // map that indicates the shallow dependency each file included on the - // bundle has - const shallowDependencies = Object.create(null); - deps.forEach(dep => { - shallowDependencies[dep.path] = dep.deps; - }); - - // map from module name to the modules' dependencies the bundle entry - // has - const dependenciesModulesCache = Object.create(null); - response.dependencies.forEach(dep => { - dependenciesModulesCache[getModuleId(dep)] = dep; - }); - - const inverseDependenciesCache = Object.create(null); - const inverseDependencies = getInverseDependencies(response); - for (const [module, dependents] of inverseDependencies) { - inverseDependenciesCache[getModuleId(module)] = - Array.from(dependents).map(getModuleId); - } - - /* $FlowFixMe(>=0.56.0 site=react_native_oss) This comment suppresses an - * error found when Flow v0.56 was deployed. To see the error delete this - * comment and run Flow. */ - /* $FlowFixMe(>=0.56.0 site=react_native_fb,react_native_oss) This comment - * suppresses an error found when Flow v0.56 was deployed. To see the error - * delete this comment and run Flow. */ - return { - dependenciesCache, - dependenciesModulesCache, - shallowDependencies, - inverseDependenciesCache, - resolutionResponse: response, - }; - } - - async function prepareResponse( - client: Client, - filename: string, - ): Promise { - try { - const bundle = await generateBundle(client, filename); - - if (!bundle || bundle.isEmpty()) { - return; - } - - return { - type: 'update', - body: { - modules: bundle.getModulesIdsAndCode(), - inverseDependencies: client.inverseDependenciesCache, - sourceURLs: bundle.getSourceURLs(), - sourceMappingURLs: bundle.getSourceMappingURLs(), - }, - }; - } catch (error) { - // send errors to the client instead of killing packager server - let body; - if (error.type === 'TransformError' || - error.type === 'NotFoundError' || - error.type === 'UnableToResolveError') { - body = { - type: error.type, - description: error.description, - filename: error.filename, - lineNumber: error.lineNumber, - }; - } else { - console.error(error.stack || error); - body = { - type: 'InternalError', - description: 'react-packager has encountered an internal error, ' + - 'please check your terminal error output for more details', - }; - } - - return {type: 'error', body}; - } - } - - async function generateBundle( - client: Client, - filename: string, - ): Promise { - // If the main file is an asset, do not generate a bundle. - const moduleToUpdate = await packagerServer.getModuleForPath(filename); - if (moduleToUpdate.isAsset()) { - return; - } - - const deps = await packagerServer.getShallowDependencies({ - dev: true, - minify: false, - entryFile: filename, - rootEntryFile: client.bundleEntry, - hot: true, - platform: client.platform, - recursive: true, - }); - - // if the file dependencies have change we need to invalidate the - // dependencies caches because the list of files we need to send - // to the client may have changed - const oldDependencies = client.shallowDependencies[filename]; - - let resolutionResponse; - - if (arrayEquals(deps, oldDependencies)) { - // Need to create a resolution response to pass to the bundler - // to process requires after transform. By providing a - // specific response we can compute a non recursive one which - // is the least we need and improve performance. - const response = await packagerServer.getDependencies({ - dev: true, - entryFile: filename, - rootEntryFile: client.bundleEntry, - hot: true, - minify: false, - platform: client.platform, - recursive: true, - }); - - resolutionResponse = await response.copy({ - dependencies: [moduleToUpdate]}, - ); - } else { - // if there're new dependencies compare the full list of - // dependencies we used to have with the one we now have - const { - dependenciesCache: depsCache, - dependenciesModulesCache: depsModulesCache, - shallowDependencies: shallowDeps, - inverseDependenciesCache: inverseDepsCache, - resolutionResponse: myResolutionReponse, - } = await getDependencies(client.platform, client.bundleEntry); - - // build list of modules for which we'll send HMR updates - const modulesToUpdate = [moduleToUpdate]; - Object.keys(depsModulesCache).forEach(module => { - if (!client.dependenciesModulesCache[module]) { - modulesToUpdate.push(depsModulesCache[module]); - } - }); - - // Need to send modules to the client in an order it can - // process them: if a new dependency graph was uncovered - // because a new dependency was added, the file that was - // changed, which is the root of the dependency tree that - // will be sent, needs to be the last module that gets - // processed. Reversing the new modules makes sense - // because we get them through the resolver which returns - // a BFS ordered list. - modulesToUpdate.reverse(); - - // invalidate caches - client.dependenciesCache = depsCache; - client.dependenciesModulesCache = depsModulesCache; - client.shallowDependencies = shallowDeps; - client.inverseDependenciesCache = inverseDepsCache; - - resolutionResponse = await myResolutionReponse.copy({ - dependencies: modulesToUpdate, - }); - } - - // make sure the file was modified is part of the bundle - if (!client.shallowDependencies[filename]) { - return; - } - - const httpServerAddress = httpServer.address(); - - // Sanitize the value from the HTTP server - let packagerHost = 'localhost'; - if (httpServer.address().address && - httpServer.address().address !== '::' && - httpServer.address().address !== '') { - packagerHost = httpServerAddress.address; - } - - const bundle: HMRBundle = await packagerServer.buildBundleForHMR( - { - entryFile: client.bundleEntry, - platform: client.platform, - resolutionResponse, - }, - packagerHost, - httpServerAddress.port, - ); - - return bundle; - } - - function handleFileChange( - type: string, - filename: string, - ): void { - clients.forEach( - client => sendFileChangeToClient(client, type, filename), - ); - } - - async function sendFileChangeToClient( - client: Client, - type: string, - filename: string, - ): Promise { - const blacklisted = blacklist.find( - blacklistedPath => filename.indexOf(blacklistedPath) !== -1, - ); - if (blacklisted) { - return; - } - - if (clients.has(client)) { - client.ws.send(JSON.stringify({type: 'update-start'})); - } - - if (type !== 'delete') { - const response = await prepareResponse(client, filename); - - if (response && clients.has(client)) { - client.ws.send(JSON.stringify(response)); - } - } - - if (clients.has(client)) { - client.ws.send(JSON.stringify({type: 'update-done'})); - } - } - - /* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an - * error found when Flow v0.54 was deployed. To see the error delete this - * comment and run Flow. */ - const WebSocketServer = require('ws').Server; - const wss = new WebSocketServer({ - server: httpServer, - path: path, - }); - - wss.on('connection', async ws => { - /* $FlowFixMe: url might be null */ - const params = querystring.parse(url.parse(ws.upgradeReq.url).query); - - const { - dependenciesCache, - dependenciesModulesCache, - shallowDependencies, - inverseDependenciesCache, - } = await getDependencies(params.platform, params.bundleEntry); - - const client = { - ws, - platform: params.platform, - bundleEntry: params.bundleEntry, - dependenciesCache, - dependenciesModulesCache, - shallowDependencies, - inverseDependenciesCache, - }; - clients.add(client); - - // If this is the first client connecting, start listening to file changes - if (clients.size === 1) { - packagerServer.setHMRFileChangeListener(handleFileChange); - } - - client.ws.on('error', e => { - console.error('[Hot Module Replacement] Unexpected error', e); - disconnect(client); - }); - - client.ws.on('close', () => disconnect(client)); - }); -} - -function arrayEquals(arrayA: Array, arrayB: Array): boolean { - arrayA = arrayA || []; - arrayB = arrayB || []; - return ( - arrayA.length === arrayB.length && - arrayA.every((element, index) => { - return element === arrayB[index]; - }) - ); -} - -module.exports = attachHMRServer; diff --git a/local-cli/server/util/getInverseDependencies.js b/local-cli/server/util/getInverseDependencies.js deleted file mode 100644 index 927af924672998..00000000000000 --- a/local-cli/server/util/getInverseDependencies.js +++ /dev/null @@ -1,70 +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. - * - * @flow - * @format - */ - -'use strict'; - -/** - * This is a subset of the actual `metro-bundler`'s `ResolutionResponse` class, - * without all the stuff we don't need to know about. This allows us to use - * `getInverseDependencies` with different versions of `metro-bundler`. - */ -export type ResolutionResponse = { - copy(data: { - dependencies?: Array, - mainModuleId?: number, - mocks?: mixed, - }): ResolutionResponse, - dependencies: Array, - getResolvedDependencyPairs( - module: TModule, - ): $ReadOnlyArray<[string, TModule]>, - options: Object, -}; - -function resolveModuleRequires( - resolutionResponse: ResolutionResponse, - module: TModule, -): Array { - const pairs = resolutionResponse.getResolvedDependencyPairs(module); - return pairs ? pairs.map(([, dependencyModule]) => dependencyModule) : []; -} - -function getModuleDependents( - cache: Map>, - module: TModule, -): Set { - let dependents = cache.get(module); - if (!dependents) { - dependents = new Set(); - cache.set(module, dependents); - } - return dependents; -} - -/** - * Returns an object that indicates in which module each module is required. - */ -function getInverseDependencies( - resolutionResponse: ResolutionResponse, -): Map> { - const cache = new Map(); - - resolutionResponse.dependencies.forEach(module => { - resolveModuleRequires(resolutionResponse, module).forEach(dependency => { - getModuleDependents(cache, dependency).add(module); - }); - }); - - return cache; -} - -module.exports = getInverseDependencies; From ae5ef653cbc4c03fe5edb5d4b0002e38cbb6f458 Mon Sep 17 00:00:00 2001 From: Yujie Liu Date: Thu, 9 Nov 2017 09:01:21 -0800 Subject: [PATCH 05/50] Rename bundleSource to embeddedBundle Reviewed By: fromcelticpark Differential Revision: D6274101 fbshipit-source-id: f62da158d165cb3ce4a510ebc4eed24a8a719381 --- React/Base/RCTBridge.h | 4 ++-- React/Base/RCTBridge.m | 6 +++--- React/Base/RCTBridgeDelegate.h | 4 ++-- React/CxxBridge/RCTCxxBridge.mm | 6 +++--- React/Modules/RCTSourceCode.m | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/React/Base/RCTBridge.h b/React/Base/RCTBridge.h index 9a5fa5cd1f749d..450a0d0e38a104 100644 --- a/React/Base/RCTBridge.h +++ b/React/Base/RCTBridge.h @@ -172,9 +172,9 @@ RCT_EXTERN NSString *RCTBridgeModuleNameForClass(Class bridgeModuleClass); @property (nonatomic, strong, readonly) NSURL *bundleURL; /** - * URL of the original script (not necessarily loaded) of the bridge. + * URL of the embedded bundle of the bridge. */ -@property (nonatomic, strong, readonly) NSURL *bundledSourceURL; +@property (nonatomic, strong, readonly) NSURL *embeddedBundleURL; /** * The class of the executor currently being used. Changes to this value will diff --git a/React/Base/RCTBridge.m b/React/Base/RCTBridge.m index b69ea1d9fd5ae3..a8cef88c7bf4d9 100644 --- a/React/Base/RCTBridge.m +++ b/React/Base/RCTBridge.m @@ -329,9 +329,9 @@ - (void)setUp // Sanitize the bundle URL _bundleURL = [RCTConvert NSURL:_bundleURL.absoluteString]; - if ([self.delegate respondsToSelector:@selector(bundledSourceURLForBridge:)]) { - _bundledSourceURL = [self.delegate bundledSourceURLForBridge:self]; - _bundledSourceURL = [RCTConvert NSURL:_bundledSourceURL.absoluteString]; + if ([self.delegate respondsToSelector:@selector(embeddedBundleURLForBridge:)]) { + _embeddedBundleURL = [self.delegate embeddedBundleURLForBridge:self]; + _embeddedBundleURL = [RCTConvert NSURL:_embeddedBundleURL.absoluteString]; } self.batchedBridge = [[bridgeClass alloc] initWithParentBridge:self]; diff --git a/React/Base/RCTBridgeDelegate.h b/React/Base/RCTBridgeDelegate.h index fb048769ead2c9..f70a024188bad1 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 diff --git a/React/CxxBridge/RCTCxxBridge.mm b/React/CxxBridge/RCTCxxBridge.mm index 88eb814aceb334..871bc46071c255 100644 --- a/React/CxxBridge/RCTCxxBridge.mm +++ b/React/CxxBridge/RCTCxxBridge.mm @@ -176,8 +176,8 @@ @implementation RCTCxxBridge } @synthesize bridgeDescription = _bridgeDescription; +@synthesize embeddedBundleURL = _embeddedBundleURL; @synthesize loading = _loading; -@synthesize bundledSourceURL = _bundledSourceURL; @synthesize performanceLogger = _performanceLogger; @synthesize valid = _valid; @@ -208,8 +208,8 @@ - (instancetype)initWithParentBridge:(RCTBridge *)bridge launchOptions:bridge.launchOptions])) { _parentBridge = bridge; _performanceLogger = [bridge performanceLogger]; - if ([bridge.delegate respondsToSelector:@selector(bundledSourceURLForBridge:)]) { - _bundledSourceURL = [bridge.delegate bundledSourceURLForBridge:bridge]; + if ([bridge.delegate respondsToSelector:@selector(embeddedBundleURLForBridge:)]) { + _embeddedBundleURL = [bridge.delegate embeddedBundleURLForBridge:bridge]; } registerPerformanceLoggerHooks(_performanceLogger); diff --git a/React/Modules/RCTSourceCode.m b/React/Modules/RCTSourceCode.m index aab1692010f96b..a7c274a006fd86 100644 --- a/React/Modules/RCTSourceCode.m +++ b/React/Modules/RCTSourceCode.m @@ -26,7 +26,7 @@ + (BOOL)requiresMainQueueSetup { return @{ @"scriptURL": self.bridge.bundleURL.absoluteString ?: @"", - @"bundledScriptURL": self.bridge.bundledSourceURL.absoluteString ?: @"" + @"embeddedBundleURL": self.bridge.embeddedBundleURL.absoluteString ?: @"" }; } From e11d496e9d907abb5bf58a8300c5a8f85aa03bbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ramos?= Date: Thu, 9 Nov 2017 09:47:50 -0800 Subject: [PATCH 06/50] Additional markdown adjustments Summary: Follow up to 9ec95673909beac7798f589e0e9821b4225f8fa9 Closes https://github.com/facebook/react-native/pull/16759 Differential Revision: D6285219 Pulled By: hramos fbshipit-source-id: 7012d257a5a6cff06cb2d94203a9379e4b7e3c4e --- .circleci/config.yml | 19 +- docs/accessibilityinfo.md | 10 +- docs/actionsheetios.md | 6 +- docs/activityindicator.md | 2 +- docs/alert.md | 2 +- docs/alertios.md | 26 +- docs/android-building-from-source.md | 1 + docs/androiduiperformance.md | 8 + docs/animated.md | 30 +- docs/appregistry.md | 20 +- docs/appstate.md | 43 +- docs/asyncstorage.md | 103 ++-- docs/backandroid.md | 8 +- docs/backhandler.md | 18 +- docs/building-for-apple-tv.md | 1 + docs/cameraroll.md | 15 +- docs/checkbox.md | 2 +- docs/clipboard.md | 14 +- docs/communication-android.md | 1 + docs/communication-ios.md | 1 + docs/custom-webview-android.md | 3 +- docs/custom-webview-ios.md | 1 + docs/datepickerandroid.md | 6 +- docs/datepickerios.md | 2 +- docs/dimensions.md | 29 +- docs/drawerlayoutandroid.md | 2 +- docs/flatlist.md | 542 +++++++++++++++--- docs/geolocation.md | 12 +- docs/headless-js-android.md | 2 +- ...styleproptypes.md => image-style-props.md} | 43 +- docs/image.md | 97 +--- docs/imageeditor.md | 21 +- docs/imagepickerios.md | 8 +- docs/imagestore.md | 8 +- docs/integration-with-existing-apps.md | 2 +- docs/interactionmanager.md | 21 +- docs/keyboard.md | 8 +- docs/keyboardavoidingview.md | 4 +- docs/layout-props.md | 2 +- docs/layoutanimation.md | 6 +- docs/linking-libraries-ios.md | 1 + docs/linking.md | 16 +- docs/maskedviewios.md | 4 +- docs/modal.md | 2 +- docs/native-components-android.md | 1 + docs/native-components-ios.md | 1 + docs/native-modules-android.md | 1 + docs/native-modules-ios.md | 1 + docs/nativemethodsmixing.md | 8 + docs/navigatorios.md | 130 +++-- docs/netinfo.md | 82 ++- docs/panresponder.md | 58 +- docs/permissionsandroid.md | 87 +-- docs/picker-item.md | 57 ++ docs/picker-style-props.md | 32 ++ docs/picker.md | 55 +- docs/pickerios.md | 7 +- docs/pixelratio.md | 46 +- docs/progressbarandroid.md | 16 +- docs/progressviewios.md | 2 +- docs/pushnotificationios.md | 77 ++- docs/refreshcontrol.md | 2 +- docs/runningondeviceandroid.md | 8 + docs/runningondeviceios.md | 8 + docs/scrollview.md | 39 +- docs/sectionlist.md | 376 ++++++++++-- docs/segmentedcontrolios.md | 2 +- docs/settings.md | 8 +- docs/shadow-props.md | 2 +- docs/share.md | 18 +- docs/slider.md | 14 +- docs/snapshotviewios.md | 3 +- docs/statusbar.md | 46 +- docs/statusbarios.md | 10 +- docs/stylesheet.md | 93 ++- docs/switch.md | 10 +- docs/systrace.md | 27 +- docs/tabbarios-item.md | 11 +- docs/tabbarios.md | 14 +- ...tstyleproptypes.md => text-style-props.md} | 46 +- docs/text.md | 1 + docs/textinput.md | 2 +- docs/timepickerandroid.md | 6 +- docs/toastandroid.md | 15 +- docs/toolbarandroid.md | 2 +- docs/touchablehighlight.md | 2 +- docs/touchablenativefeedback.md | 26 +- docs/touchablewithoutfeedback.md | 10 +- docs/vibration.md | 14 +- docs/vibrationios.md | 16 +- docs/{viewproptypes.md => view-props.md} | 70 +-- ...wstyleproptypes.md => view-style-props.md} | 62 +- docs/view.md | 19 +- docs/viewpagerandroid.md | 19 +- docs/virtualizedlist.md | 427 ++++++++++++-- docs/webview.md | 32 +- 96 files changed, 2202 insertions(+), 1091 deletions(-) create mode 100644 docs/androiduiperformance.md rename docs/{imagestyleproptypes.md => image-style-props.md} (61%) create mode 100644 docs/nativemethodsmixing.md create mode 100644 docs/picker-item.md create mode 100644 docs/picker-style-props.md create mode 100644 docs/runningondeviceandroid.md create mode 100644 docs/runningondeviceios.md rename docs/{textstyleproptypes.md => text-style-props.md} (67%) rename docs/{viewproptypes.md => view-props.md} (86%) rename docs/{viewstyleproptypes.md => view-style-props.md} (58%) diff --git a/.circleci/config.yml b/.circleci/config.yml index 7ee106ab67709b..32902f12fad5e6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -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 @@ -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/docs/accessibilityinfo.md b/docs/accessibilityinfo.md index d85927eafc8040..d1d7625c21867f 100644 --- a/docs/accessibilityinfo.md +++ b/docs/accessibilityinfo.md @@ -78,7 +78,7 @@ class ScreenReaderStatusExample extends React.Component { ### `fetch()` ```javascript -static fetch() +AccessibilityInfo.fetch() ``` @@ -94,7 +94,7 @@ and `false` otherwise. ### `addEventListener()` ```javascript -static addEventListener(eventName, handler) +AccessibilityInfo.addEventListener(eventName, handler) ``` @@ -117,7 +117,7 @@ Add an event handler. Supported events: ### `setAccessibilityFocus()` ```javascript -static setAccessibilityFocus(reactTag) +AccessibilityInfo.setAccessibilityFocus(reactTag) ``` @@ -131,7 +131,7 @@ iOS-Only. Set accessibility focus to a react component. ### `announceForAccessibility()` ```javascript -static announceForAccessibility(announcement) +AccessibilityInfo.announceForAccessibility(announcement) ``` @@ -145,7 +145,7 @@ iOS-Only. Post a string to be announced by the screen reader. ### `removeEventListener()` ```javascript -static removeEventListener(eventName, handler) +AccessibilityInfo.removeEventListener(eventName, handler) ``` diff --git a/docs/actionsheetios.md b/docs/actionsheetios.md index 2d998d3f167c95..0f97351edd9331 100644 --- a/docs/actionsheetios.md +++ b/docs/actionsheetios.md @@ -8,7 +8,7 @@ next: alert previous: accessibilityinfo --- - +Display action sheets and share sheets on iOS. ### Methods @@ -27,7 +27,7 @@ previous: accessibilityinfo ### `showActionSheetWithOptions()` ```javascript -static showActionSheetWithOptions(options, callback) +ActionSheetIOS.showActionSheetWithOptions(options, callback) ``` @@ -65,7 +65,7 @@ ActionSheetIOS.showActionSheetWithOptions({ ### `showShareActionSheetWithOptions()` ```javascript -static showShareActionSheetWithOptions(options, failureCallback, successCallback) +ActionSheetIOS.showShareActionSheetWithOptions(options, failureCallback, successCallback) ``` diff --git a/docs/activityindicator.md b/docs/activityindicator.md index f00406d2911b00..4b6f22d9046ca6 100644 --- a/docs/activityindicator.md +++ b/docs/activityindicator.md @@ -51,7 +51,7 @@ AppRegistry.registerComponent('App', () => App) ### Props -* [ViewPropTypes props...](docs/viewproptypes.html#props) +- [View props...](docs/view-props.html) - [`animating`](docs/activityindicator.html#animating) - [`color`](docs/activityindicator.html#color) - [`size`](docs/activityindicator.html#size) diff --git a/docs/alert.md b/docs/alert.md index 87f67237581991..63de1f42d8bc9a 100644 --- a/docs/alert.md +++ b/docs/alert.md @@ -72,7 +72,7 @@ Alert.alert( ### `alert()` ```javascript -static alert(title, message?, buttons?, options?, type?) +Alert.alert(title, message?, buttons?, options?, type?) ``` diff --git a/docs/alertios.md b/docs/alertios.md index 7079e67bfde6ca..ffd4e51e08cd48 100644 --- a/docs/alertios.md +++ b/docs/alertios.md @@ -56,7 +56,7 @@ cross-platform support if you don't need to create iOS-only prompts. ### `alert()` ```javascript -static alert(title: string, [message]: string, [callbackOrButtons]: ?(() => void), ButtonsArray, [type]: AlertType): [object Object] +AlertIOS.alert(title: string, [message]: string, [callbackOrButtons]: ?(() => void), ButtonsArray, [type]: AlertType): [object Object] ``` Create and display a popup alert. @@ -65,10 +65,10 @@ Create and display a popup alert. | Name | Type | Required | Description | | - | - | - | - | -| title | string | No | The dialog's title. Passing null or '' will hide the title. | -| message | string | Yes | An optional message that appears below the dialog's title. | -| callbackOrButtons | ?(() => void),[ButtonsArray](docs/alertios.html#buttonsarray) | Yes | 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'. | -| type | [AlertType](docs/alertios.html#alerttype) | Yes | Deprecated, do not use. | +| 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 | ?(() => void),[ButtonsArray](docs/alertios.html#buttonsarray) | No | 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'. | +| type | [AlertType](docs/alertios.html#alerttype) | No | Deprecated, do not use. | @@ -93,7 +93,7 @@ AlertIOS.alert( ### `prompt()` ```javascript -static prompt(title: string, [message]: string, [callbackOrButtons]: ?((text: string) => void), ButtonsArray, [type]: AlertType, [defaultValue]: string, [keyboardType]: string): [object Object] +AlertIOS.prompt(title: string, [message]: string, [callbackOrButtons]: ?((text: string) => void), ButtonsArray, [type]: AlertType, [defaultValue]: string, [keyboardType]: string): [object Object] ``` Create and display a prompt to enter some text. @@ -102,12 +102,12 @@ Create and display a prompt to enter some text. | Name | Type | Required | Description | | - | - | - | - | -| title | string | No | The dialog's title. | -| message | string | Yes | An optional message that appears above the text input. | -| callbackOrButtons | ?((text: string) => void),[ButtonsArray](docs/alertios.html#buttonsarray) | Yes | 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'. | -| type | [AlertType](docs/alertios.html#alerttype) | Yes | This configures the text input. One of 'plain-text', 'secure-text' or 'login-password'. | -| defaultValue | string | Yes | The default text in text input. | -| keyboardType | string | Yes | 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'. | +| title | string | Yes | The dialog's title. | +| message | string | No | An optional message that appears above the text input. | +| callbackOrButtons | ?((text: string) => void),[ButtonsArray](docs/alertios.html#buttonsarray) | No | 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'. | +| type | [AlertType](docs/alertios.html#alerttype) | No | This configures the text input. One of 'plain-text', 'secure-text' or 'login-password'. | +| 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'. | @@ -191,7 +191,7 @@ An Alert button style ### ButtonsArray -Array or buttons +Array of buttons | Type | | - | diff --git a/docs/android-building-from-source.md b/docs/android-building-from-source.md index 62b7d37d9f5f31..d88c46cdef5340 100644 --- a/docs/android-building-from-source.md +++ b/docs/android-building-from-source.md @@ -4,6 +4,7 @@ title: Building React Native from source layout: docs category: Guides (Android) permalink: docs/android-building-from-source.html +banner: ejected next: communication-android previous: android-ui-performance --- 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 index aa6b6ae915d17a..a18f4cb2857317 100644 --- a/docs/animated.md +++ b/docs/animated.md @@ -533,25 +533,51 @@ static unforkEvent(event, listener) ## Properties +### Value +Standard value class for driving animations. Typically initialized with `new Animated.Value(0);` ---- +See also `AnimatedValue.js`. +| Type | +| - | +| AnimatedValue | --- +### ValueXY +2D value class for driving 2D animations, such as pan gestures. ---- +See also `AnimatedValueXY.js`. + +| Type | +| - | +| AnimatedValueXY | --- +### Interpolation + +Exported to use the Interpolation type in flow + +See also `AnimatedInterpolation.js`. +| Type | +| - | +| AnimatedInterpolation | --- +### Node + +Exported for ease of type checking. All animated values derive from this class. + +| Type | +| - | +| AnimatedNode | diff --git a/docs/appregistry.md b/docs/appregistry.md index 83d119244601d6..81b5129441f520 100644 --- a/docs/appregistry.md +++ b/docs/appregistry.md @@ -199,12 +199,13 @@ static registerHeadlessTask(taskKey, task) 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. +**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. | --- @@ -215,12 +216,15 @@ Register a headless task. A headless task is a bit of code that runs without a U static startHeadlessTask(taskId, taskKey, data) ``` - 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 +**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 | diff --git a/docs/appstate.md b/docs/appstate.md index ee208e3d0f9906..efe0e1274d33a2 100644 --- a/docs/appstate.md +++ b/docs/appstate.md @@ -16,23 +16,18 @@ 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 +- `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) +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. +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' @@ -66,14 +61,11 @@ class AppStateExample extends Component { } ``` -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. +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 -- [`=`](docs/appstate.html#) - [`addEventListener`](docs/appstate.html#addeventlistener) - [`removeEventListener`](docs/appstate.html#removeeventlistener) @@ -86,16 +78,6 @@ state will happen only momentarily. ## Methods -### `=()` - -```javascript -=(;, () -``` - - - ---- - ### `addEventListener()` ```javascript @@ -106,15 +88,6 @@ addEventListener(type, handler) 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). - - - - --- ### `removeEventListener()` diff --git a/docs/asyncstorage.md b/docs/asyncstorage.md index 2a88f2d47d0b1e..01c18672285dc4 100644 --- a/docs/asyncstorage.md +++ b/docs/asyncstorage.md @@ -7,24 +7,17 @@ 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. +`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. +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. +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. +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) { @@ -33,7 +26,8 @@ try { ``` Fetching data: -``` + +```javascript try { const value = await AsyncStorage.getItem('@MySuperStore:key'); if (value !== null){ @@ -53,6 +47,11 @@ try { - [`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) @@ -81,8 +80,8 @@ Returns a `Promise` object. | Name | Type | Required | Description | | - | - | - | - | -| key | string | No | Key of the item to fetch. | -| callback | ?(error: ?Error, result: ?string) => void | Yes | Function that will be called with a result if found or any error. | +| key | string | Yes | Key of the item to fetch. | +| callback | ?(error: ?Error, result: ?string) => void | No | Function that will be called with a result if found or any error. | @@ -95,16 +94,17 @@ Returns a `Promise` object. static setItem(key: string, value: string, [callback]: ?(error: ?Error) => void) ``` -Sets the value for a `key` and invokes a callback upon completion. +Sets the value for a `key` and invokes a callback upon completion. + Returns a `Promise` object. **Parameters:** | Name | Type | Required | Description | | - | - | - | - | -| key | string | No | Key of the item to set. | -| value | string | No | Value to set for the `key`. | -| callback | ?(error: ?Error) => void | Yes | Function that will be called with any error. | +| key | string | Yes | Key of the item to set. | +| value | string | Yes | Value to set for the `key`. | +| callback | ?(error: ?Error) => void | No | Function that will be called with any error. | @@ -124,8 +124,8 @@ Returns a `Promise` object. | Name | Type | Required | Description | | - | - | - | - | -| key | string | No | Key of the item to remove. | -| callback | ?(error: ?Error) => void | Yes | Function that will be called with any error. | +| key | string | Yes | Key of the item to remove. | +| callback | ?(error: ?Error) => void | No | Function that will be called with any error. | @@ -138,35 +138,32 @@ Returns a `Promise` object. static mergeItem(key: string, value: string, [callback]: ?(error: ?Error) => void) ``` -Merges an existing `key` value with an input value, assuming both values -are stringified JSON. Returns a `Promise` object. +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. +> Note: +> This is not supported by all native implementations. **Parameters:** | Name | Type | Required | Description | | - | - | - | - | -| key | string | No | Key of the item to modify. | -| value | string | No | New value to merge for the `key`. | -| callback | ?(error: ?Error) => void | Yes | Function that will be called with any error. | - - +| key | string | Yes | Key of the item to modify. | +| value | string | Yes | New value to merge for the `key`. | +| callback | ?(error: ?Error) => void | No | Function that will be called with any error. | Example: ```javascript - let UID123_object = { - name: 'Chris', - age: 30, - traits: {hair: 'brown', eyes: 'brown'}, + 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} + age: 31, + traits: {eyes: 'blue', shoe_size: 10} }; AsyncStorage.setItem('UID123', JSON.stringify(UID123_object), () => { @@ -182,8 +179,6 @@ AsyncStorage.setItem('UID123', JSON.stringify(UID123_object), () => { // {'shoe_size':10,'hair':'brown','eyes':'blue'}} ``` - - --- ### `clear()` @@ -192,15 +187,13 @@ AsyncStorage.setItem('UID123', JSON.stringify(UID123_object), () => { static clear([callback]: ?(error: ?Error) => void) ``` -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. +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: ?Error) => void | Yes | Function that will be called with any error. | +| callback | ?(error: ?Error) => void | No | Function that will be called with any error. | @@ -220,7 +213,7 @@ Returns a `Promise` object. | Name | Type | Required | Description | | - | - | - | - | -| callback | ?(error: ?Error, keys: ?Array) => void | Yes | Function that will be called the keys found and any error. | +| callback | ?(error: ?Error, keys: ?Array) => void | No | Function that will be called the keys found and any error. | @@ -235,8 +228,6 @@ static flushGetRequests(): [object Object] Flushes any pending requests using a single batch call to get the data. - - --- ### `multiGet()` @@ -245,9 +236,7 @@ Flushes any pending requests using a single batch call to get the data. static multiGet(keys: Array, [callback]: ?(errors: ?Array, result: ?Array>) => void) ``` -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: +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']]) @@ -259,10 +248,8 @@ The method returns a `Promise` object. | Name | Type | Required | Description | | - | - | - | - | -| keys | Array | No | Array of key for the items to get. | -| callback | ?(errors: ?Array, result: ?Array>) => void | Yes | Function that will be called with a key-value array of the results, plus an array of any key-specific errors found. | - - +| keys | Array | Yes | Array of key for the items to get. | +| callback | ?(errors: ?Array, result: ?Array>) => void | No | Function that will be called with a key-value array of the results, plus an array of any key-specific errors found. | Example: @@ -302,8 +289,8 @@ The method returns a `Promise` object. | Name | Type | Required | Description | | - | - | - | - | -| keyValuePairs | Array> | No | Array of key-value array for the items to set. | -| callback | ?(errors: ?Array) => void | Yes | Function that will be called with an array of any key-specific errors found. | +| keyValuePairs | Array> | Yes | Array of key-value array for the items to set. | +| callback | ?(errors: ?Array) => void | No | Function that will be called with an array of any key-specific errors found. | @@ -323,8 +310,8 @@ a `Promise` object. | Name | Type | Required | Description | | - | - | - | - | -| keys | Array | No | Array of key for the items to delete. | -| callback | ?(errors: ?Array) => void | Yes | Function that will be called an array of any key-specific errors found. | +| keys | Array | Yes | Array of key for the items to delete. | +| callback | ?(errors: ?Array) => void | No | Function that will be called an array of any key-specific errors found. | @@ -360,8 +347,8 @@ keys. This assumes that the values are stringified JSON. Returns a | Name | Type | Required | Description | | - | - | - | - | -| keyValuePairs | Array> | No | Array of key-value array for the items to merge. | -| callback | ?(errors: ?Array) => void | Yes | Function that will be called with an array of any key-specific errors found. | +| keyValuePairs | Array> | Yes | Array of key-value array for the items to merge. | +| callback | ?(errors: ?Array) => 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 index 0ee553c67bc16c..0dd040cd3525c7 100644 --- a/docs/backandroid.md +++ b/docs/backandroid.md @@ -8,7 +8,7 @@ next: backhandler previous: asyncstorage --- -Deprecated. Use BackHandler instead. +**Deprecated.** Use [BackHandler](docs/backhandler.html) instead. ### Methods @@ -29,7 +29,7 @@ Deprecated. Use BackHandler instead. ### `exitApp()` ```javascript -static exitApp() +BackAndroid.exitApp() ``` @@ -39,7 +39,7 @@ static exitApp() ### `addEventListener()` ```javascript -static addEventListener(eventName, handler) +BackAndroid.addEventListener(eventName, handler) ``` @@ -49,7 +49,7 @@ static addEventListener(eventName, handler) ### `removeEventListener()` ```javascript -static removeEventListener(eventName, handler) +BackAndroid.removeEventListener(eventName, handler) ``` diff --git a/docs/backhandler.md b/docs/backhandler.md index 890a9325ca6ca6..57f2a8b9e46805 100644 --- a/docs/backhandler.md +++ b/docs/backhandler.md @@ -10,17 +10,13 @@ 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. +**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.) +**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. +**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. +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: @@ -56,7 +52,7 @@ BackHandler.addEventListener('hardwareBackPress', function() { ### `exitApp()` ```javascript -static exitApp() +BackHandler.exitApp() ``` @@ -66,7 +62,7 @@ static exitApp() ### `addEventListener()` ```javascript -static addEventListener(eventName, handler) +BackHandler.addEventListener(eventName, handler) ``` @@ -76,7 +72,7 @@ static addEventListener(eventName, handler) ### `removeEventListener()` ```javascript -static removeEventListener(eventName, handler) +BackHandler.removeEventListener(eventName, handler) ``` diff --git a/docs/building-for-apple-tv.md b/docs/building-for-apple-tv.md index 1692353f2ca1eb..0dc6128cb97c9b 100644 --- a/docs/building-for-apple-tv.md +++ b/docs/building-for-apple-tv.md @@ -4,6 +4,7 @@ title: Building For Apple TV layout: docs category: Guides (iOS) permalink: docs/building-for-apple-tv.html +banner: ejected next: app-extensions previous: communication-ios --- diff --git a/docs/cameraroll.md b/docs/cameraroll.md index 15741c80375f8c..127aecd7cbeb6f 100644 --- a/docs/cameraroll.md +++ b/docs/cameraroll.md @@ -21,7 +21,6 @@ app will use this data. This key will appear as `Privacy - Photo Library Usage D ### Methods -- [`=`](docs/cameraroll.html#) - [`saveToCameraRoll`](docs/cameraroll.html#savetocameraroll) - [`getPhotos`](docs/cameraroll.html#getphotos) @@ -34,20 +33,10 @@ app will use this data. This key will appear as `Privacy - Photo Library Usage D ## Methods -### `=()` - -```javascript -=(;, AssetTypeOptions, static, (, :) -``` - - - ---- - ### `saveToCameraRoll()` ```javascript -static saveToCameraRoll(tag, type?) +CameraRoll.saveToCameraRoll(tag, type?) ``` @@ -72,7 +61,7 @@ Returns a Promise which will resolve with the new URI. ### `getPhotos()` ```javascript -static getPhotos(params) +CameraRoll.getPhotos(params) ``` diff --git a/docs/checkbox.md b/docs/checkbox.md index 100d67434b6bb4..679b5df885a98c 100644 --- a/docs/checkbox.md +++ b/docs/checkbox.md @@ -19,7 +19,7 @@ the supplied `value` prop instead of the expected result of any user actions. ### Props -* [ViewPropTypes props...](docs/viewproptypes.html#props) +- [View props...](docs/view-props.html) - [`disabled`](docs/checkbox.html#disabled) - [`onChange`](docs/checkbox.html#onchange) - [`onValueChange`](docs/checkbox.html#onvaluechange) diff --git a/docs/clipboard.md b/docs/clipboard.md index 5d6dd7af1e1ec4..47a9e3488359dd 100644 --- a/docs/clipboard.md +++ b/docs/clipboard.md @@ -28,7 +28,7 @@ previous: cameraroll ### `getString()` ```javascript -static getString() +Clipboard.getString() ``` @@ -47,17 +47,23 @@ async _getContent() { ### `setString()` ```javascript -static setString(content) +Clipboard.setString(content) ``` -Set content of string type. You can use following code to set clipboard content +Set content of string type. You can use following code to set clipboard content: + ```javascript _setContent() { Clipboard.setString('hello world'); } ``` -@param the content to be stored in the clipboard. + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| content | string | yes | The content to be stored in the clipboard. | diff --git a/docs/communication-android.md b/docs/communication-android.md index 675d2eba940a1b..133be47408c753 100644 --- a/docs/communication-android.md +++ b/docs/communication-android.md @@ -4,6 +4,7 @@ title: Communication between native and React Native layout: docs category: Guides (Android) permalink: docs/communication-android.html +banner: ejected next: contributing previous: android-building-from-source --- diff --git a/docs/communication-ios.md b/docs/communication-ios.md index 16851169e1b752..7be7fb4a914ea4 100644 --- a/docs/communication-ios.md +++ b/docs/communication-ios.md @@ -4,6 +4,7 @@ title: Communication between native and React Native layout: docs category: Guides (iOS) permalink: docs/communication-ios.html +banner: ejected next: building-for-apple-tv previous: linking-libraries-ios --- diff --git a/docs/custom-webview-android.md b/docs/custom-webview-android.md index f3dcf7e76f24ce..73dbfaf5621052 100644 --- a/docs/custom-webview-android.md +++ b/docs/custom-webview-android.md @@ -4,6 +4,7 @@ title: Custom WebView layout: docs category: Guides (Android) permalink: docs/custom-webview-android.html +banner: ejected next: headless-js-android previous: native-components-android --- @@ -213,7 +214,7 @@ For events, the event handler must always be set to a function. This means it is If you are unsure how something should be implemented from the JS side, look at [WebView.android.js](https://github.com/facebook/react-native/blob/master/Libraries/Components/WebView/WebView.android.js) in the React Native source. -```js +```javascript export default class CustomWebView extends Component { static propTypes = { ...WebView.propTypes, diff --git a/docs/custom-webview-ios.md b/docs/custom-webview-ios.md index 8f4de9fdff6b69..8c2d51f80c88fe 100644 --- a/docs/custom-webview-ios.md +++ b/docs/custom-webview-ios.md @@ -4,6 +4,7 @@ title: Custom WebView layout: docs category: Guides (iOS) permalink: docs/custom-webview-ios.html +banner: ejected next: linking-libraries-ios previous: native-components-ios --- diff --git a/docs/datepickerandroid.md b/docs/datepickerandroid.md index 7b16e10c166ee1..55f2819f6d239f 100644 --- a/docs/datepickerandroid.md +++ b/docs/datepickerandroid.md @@ -46,7 +46,7 @@ try { ### `open()` ```javascript -static open(options) +DatePickerAndroid.open(options) ``` @@ -78,7 +78,7 @@ when using the `minDate` and `maxDate` options. ### `dateSetAction()` ```javascript -static dateSetAction() +DatePickerAndroid.dateSetAction() ``` @@ -92,7 +92,7 @@ A date has been selected. ### `dismissedAction()` ```javascript -static dismissedAction() +DatePickerAndroid.dismissedAction() ``` diff --git a/docs/datepickerios.md b/docs/datepickerios.md index 60c6dc70bc8972..43795a3321d6f6 100644 --- a/docs/datepickerios.md +++ b/docs/datepickerios.md @@ -15,7 +15,7 @@ source of truth. ### Props -* [ViewPropTypes props...](docs/viewproptypes.html#props) +- [View props...](docs/view-props.html) - [`date`](docs/datepickerios.html#date) - [`onDateChange`](docs/datepickerios.html#ondatechange) - [`maximumDate`](docs/datepickerios.html#maximumdate) diff --git a/docs/dimensions.md b/docs/dimensions.md index 4e57aaf445598c..65db7d95ecf4ca 100644 --- a/docs/dimensions.md +++ b/docs/dimensions.md @@ -29,14 +29,18 @@ previous: datepickerandroid ### `set()` ```javascript -static set(dims) +Dimensions.set(dims) ``` This should only be called from native code by sending the didUpdateDimensions event. -@param {object} dims Simple string-keyed object of dimensions to set +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| dims | object | Yes | Simple string-keyed object of dimensions to set | @@ -46,23 +50,24 @@ didUpdateDimensions event. ### `get()` ```javascript -static get(dim) +Dimensions.get(dim) ``` Initial dimensions are set before `runApplication` is called so they should be available before any other require's are run, but may be updated later. -Note: Although dimensions are available immediately, they may change (e.g -due to device rotation) so any rendering logic or styles that depend on -these constants should try to call this function on every render, rather -than caching the value (for example, using inline styles rather than -setting a value in a `StyleSheet`). +> Note: +> Although dimensions are available immediately, they may change (e.g due to device rotation) so any rendering logic or styles that depend on these constants should try to call this function on every render, rather than caching the value (for example, using inline styles rather than setting a value in a `StyleSheet`). Example: `var {height, width} = Dimensions.get('window');` -@param {string} dim Name of dimension as defined when calling `set`. -@returns {Object?} Value for the dimension. +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| dim | string | Yes | Name of dimension as defined when calling `set`. | + @@ -72,7 +77,7 @@ Example: `var {height, width} = Dimensions.get('window');` ### `addEventListener()` ```javascript -static addEventListener(type, handler) +Dimensions.addEventListener(type, handler) ``` @@ -91,7 +96,7 @@ Add an event handler. Supported events: ### `removeEventListener()` ```javascript -static removeEventListener(type, handler) +Dimensions.removeEventListener(type, handler) ``` diff --git a/docs/drawerlayoutandroid.md b/docs/drawerlayoutandroid.md index b9ae9809148ce6..0a2a393f0635f3 100644 --- a/docs/drawerlayoutandroid.md +++ b/docs/drawerlayoutandroid.md @@ -39,7 +39,7 @@ render: function() { ### Props -* [ViewPropTypes props...](docs/viewproptypes.html#props) +- [View props...](docs/view-props.html) - [`renderNavigationView`](docs/drawerlayoutandroid.html#rendernavigationview) - [`onDrawerClose`](docs/drawerlayoutandroid.html#ondrawerclose) - [`drawerPosition`](docs/drawerlayoutandroid.html#drawerposition) diff --git a/docs/flatlist.md b/docs/flatlist.md index 6ab1309ccd0039..617363de60e20a 100644 --- a/docs/flatlist.md +++ b/docs/flatlist.md @@ -23,10 +23,12 @@ If you need section support, use [``](docs/sectionlist.html). Minimal Example: +```javascript {item.key}} /> +``` More complex, multi-select example demonstrating `PureComponent` usage for perf optimization and avoiding bugs. @@ -39,87 +41,101 @@ More complex, multi-select example demonstrating `PureComponent` usage for perf not show any changes. - `keyExtractor` tells the list to use the `id`s for the react keys instead of the default `key` property. +```javascript +class MyListItem extends React.PureComponent { + _onPress = () => { + this.props.onPressItem(this.props.id); + }; + + render() { + const textColor = this.props.selected ? "red" : "black"; + return ( + + + + {this.props.title} + + + + ); + } +} + +class MultiSelectList extends React.PureComponent { + state = {selected: (new Map(): Map)}; + + _keyExtractor = (item, index) => item.id; + + _onPressItem = (id: string) => { + // updater functions are preferred for transactional updates + this.setState((state) => { + // copy the map rather than modifying state. + const selected = new Map(state.selected); + selected.set(id, !selected.get(id)); // toggle + return {selected}; + }); + }; + + _renderItem = ({item}) => ( + + ); + + render() { + return ( + + ); + } +} +``` - class MyListItem extends React.PureComponent { - _onPress = () => { - this.props.onPressItem(this.props.id); - }; - - render() { - const textColor = this.props.selected ? "red" : "black"; - return ( - - - - {this.props.title} - - - - ); - } - } - - class MultiSelectList extends React.PureComponent { - state = {selected: (new Map(): Map)}; - - _keyExtractor = (item, index) => item.id; - - _onPressItem = (id: string) => { - // updater functions are preferred for transactional updates - this.setState((state) => { - // copy the map rather than modifying state. - const selected = new Map(state.selected); - selected.set(id, !selected.get(id)); // toggle - return {selected}; - }); - }; - - _renderItem = ({item}) => ( - - ); - - render() { - return ( - - ); - } - } - -This is a convenience wrapper around [``](docs/virtualizedlist.html), -and thus inherits its props (as well as those of `ScrollView`) that aren't explicitly listed -here, along with the following caveats: - -- Internal state is not preserved when content scrolls out of the render window. Make sure all - your data is captured in the item data or external stores like Flux, Redux, or Relay. -- This is a `PureComponent` which means that it will not re-render if `props` remain shallow- - equal. Make sure that everything your `renderItem` function depends on is passed as a prop - (e.g. `extraData`) that is not `===` after updates, otherwise your UI may not update on - changes. This includes the `data` prop and parent component state. -- In order to constrain memory and enable smooth scrolling, content is rendered asynchronously - offscreen. This means it's possible to scroll faster than the fill rate ands momentarily see - blank content. This is a tradeoff that can be adjusted to suit the needs of each application, - and we are working on improving it behind the scenes. -- By default, the list looks for a `key` prop on each item and uses that for the React key. - Alternatively, you can provide a custom `keyExtractor` prop. - -Also inherits [ScrollView Props](docs/scrollview.html#props), unless it is nested in another FlatList of same orientation. - -### Props +This is a convenience wrapper around [`VirtualizedList`](docs/virtualizedlist.html), and thus inherits its props (as well as those of `ScrollView`) that aren't explicitly listed here, along with the following caveats: -- [`numColumns`](docs/flatlist.html#numcolumns) +- Internal state is not preserved when content scrolls out of the render window. Make sure all your data is captured in the item data or external stores like Flux, Redux, or Relay. +- This is a `PureComponent` which means that it will not re-render if `props` remain shallow- equal. Make sure that everything your `renderItem` function depends on is passed as a prop (e.g. `extraData`) that is not `===` after updates, otherwise your UI may not update on changes. This includes the `data` prop and parent component state. +- In order to constrain memory and enable smooth scrolling, content is rendered asynchronously offscreen. This means it's possible to scroll faster than the fill rate ands momentarily see blank content. This is a tradeoff that can be adjusted to suit the needs of each application, and we are working on improving it behind the scenes. +- By default, the list looks for a `key` prop on each item and uses that for the React key. Alternatively, you can provide a custom `keyExtractor` prop. +Also inherits [ScrollView props](docs/scrollview.html#props), unless it is nested in another `FlatList` of same orientation. +### Props +- [`ScrollView` props...](docs/scrollview.html#props) +- [`VirtualizedList` props...](docs/virtualizedlist.html#props) +- [`renderItem`](docs/flatlist.html#renderitem) +- [`data`](docs/flatlist.html#data) +- [`ItemSeparatorComponent`](docs/flatlist.html#itemseparatorcomponent) +- [`ListEmptyComponent`](docs/flatlist.html#listemptycomponent) +- [`ListFooterComponent`](docs/flatlist.html#listgootercomponent) +- [`ListHeaderComponent`](docs/flatlist.html#listheadercomponent) +- [`columnwrapperstyle`](docs/flatlist.html#columnwrapperstyle) +- [`extraData`](docs/flatlist.html#extradata) +- [`getItemLayout`](docs/flatlist.html#getitemlayout) +- [`horizontal`](docs/flatlist.html#horizontal) +- [`initialNumToRender`](docs/flatlist.html#initialnumtorender) +- [`initialScrollIndex`](docs/flatlist.html#initialscrollindex) +- [`inverted`](docs/flatlist.html#inverted) +- [`keyExtractor`](docs/flatlist.html#keyextractor) +- [`numColumns`](docs/flatlist.html#numcolumns) +- [`onEndReached`](docs/flatlist.html#onendreached) +- [`onEndReachedThreshold`](docs/flatlist.html#onendreachedthreshold) +- [`onRefresh`](docs/flatlist.html#onrefresh) +- [`onViewableItemsChanged`](docs/flatlist.html#onviewableitemschanged) +- [`progressViewOffset`](docs/flatlist.html#progressviewoffset) +- [`legacyImplementation`](docs/flatlist.html#legacyimplementation) +- [`refreshing`](docs/flatlist.html#refreshing) +- [`removeClippedSubviews`](docs/flatlist.html#removeclippedsubviews) +- [`viewabilityConfig`](docs/flatlist.html#viewabilityconfig) +- [`viewabilityConfigCallbackPairs`](docs/flatlist.html#viewabilityconfigcallbackpairs) ### Methods @@ -145,18 +161,390 @@ Also inherits [ScrollView Props](docs/scrollview.html#props), unless it is neste ## Props +### `renderItem` + +```javascript +renderItem({ item: object, index: number, separators: { highlight: function, unhighlight: function, updateProps: function(select: string, newProps: object) } }): [element] +``` + +Takes an item from `data` and renders it into the list. + +Provides additional metadata like `index` if you need it, as well as a more generic `separators.updateProps` function which let's you set whatever props you want to change the rendering of either the leading separator or trailing separator in case the more common `highlight` and `unhighlight` (which set the `highlighted: boolean` prop) are insufficient for your use case. + +| Type | Required | +| - | - | +| function | Yes | + + +Example usage: + +```javascript + ( + + )} + data={[{title: 'Title Text', key: 'item1'}]} + renderItem={({item, separators}) => ( + this._onPress(item)} + onShowUnderlay={separators.highlight} + onHideUnderlay={separators.unhighlight}> + + {item.title} + + + )} + /> +``` + + +--- + + +### `data` + +For simplicity, data is just a plain array. If you want to use something else, like an immutable list, use the underlying [`VirtualizedList`](docs/virtualizedlist.html) directly. + +| Type | Required | +| - | - | +| array | Yes | + + + +--- + + +### `ItemSeparatorComponent` + +Rendered in between each item, but not at the top or bottom. By default, `highlighted` and `leadingItem` props are provided. `renderItem` provides `separators.highlight`/`unhighlight` which will update the `highlighted` prop, but you can also add custom props with `separators.updateProps`. + +| Type | Required | +| - | - | +| component | No | + + + +--- + + +### `ListEmptyComponent` + +Rendered when the list is empty. Can be a React Component Class, a render function, or a rendered element. + +| Type | Required | +| - | - | +| component, function, element | No | + + + +--- + + +### `ListFooterComponent` + +Rendered at the bottom of all the items. Can be a React Component Class, a render function, or a rendered element. + +| Type | Required | +| - | - | +| component, function, element | No | + + + +--- + + +### `ListHeaderComponent` + +Rendered at the top of all the items. Can be a React Component Class, a render function, or a rendered element. + +| Type | Required | +| - | - | +| component, function, element | No | + + + +--- + + +### `columnWrapperStyle` + +Optional custom style for multi-item rows generated when `numColumns > 1`. + +| Type | Required | +| - | - | +| style object | No | + + + +--- + + +### `extraData` + +A marker property for telling the list to re-render (since it implements `PureComponent`). If any of your `renderItem`, Header, Footer, etc. functions depend on anything outside of the `data` prop, stick it here and treat it immutably. + +| Type | Required | +| - | - | +| any | No | + + + + +--- + + +### `getItemLayout` + +```javascript +(data, index) => {length: number, offset: number, index: number} +``` + +`getItemLayout` is an optional optimization that let us skip measurement of dynamic content if you know the height of items a priori. `getItemLayout` is the most efficient, and is easy to use if you have fixed height items, for example: + +```javascript + getItemLayout={(data, index) => ( + {length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index} + )} +``` + +Adding `getItemLayout` can be a great performance boost for lists of several hundred items. Remember to include separator length (height or width) in your offset calculation if you specify `ItemSeparatorComponent`. + +| Type | Required | +| - | - | +| function | No | + + + +--- + + +### `horizontal` + +If true, renders items next to each other horizontally instead of stacked vertically. + +| Type | Required | +| - | - | +| boolean | No | + + + +--- + + +### `initialNumToRender` + +How many items to render in the initial batch. This should be enough to fill the screen but not much more. Note these items will never be unmounted as part of the windowed rendering in order to improve perceived performance of scroll-to-top actions. + +| Type | Required | +| - | - | +| number | No | + + + +--- + + +### `initialScrollIndex` + +Instead of starting at the top with the first item, start at `initialScrollIndex`. This disables the "scroll to top" optimization that keeps the first `initialNumToRender` items always rendered and immediately renders the items starting at this initial index. Requires `getItemLayout` to be implemented. + +| Type | Required | +| - | - | +| number | No | + + + +--- + + +### `inverted` + +Reverses the direction of scroll. Uses scale transforms of `-1`. + +| Type | Required | +| - | - | +| boolean | No | + + + +--- + + +### `keyExtractor` + +```javascript +(item: object, index: number) => string +``` + +Used to extract a unique key for a given item at the specified index. Key is used for caching and as the react key to track item re-ordering. The default extractor checks `item.key`, then falls back to using the index, like React does. + +| Type | Required | +| - | - | +| function | No | + + + + +--- + + ### `numColumns` +Multiple columns can only be rendered with `horizontal={false}` and will zig-zag like a `flexWrap` layout. Items should all be the same height - masonry layouts are not supported. +| Type | Required | +| - | - | +| number | No | + + + + +--- + + +### `onEndReached` + +```javascript +(info: {distanceFromEnd: number}) => void +``` + +Called once when the scroll position gets within `onEndReachedThreshold` of the rendered content. + +| Type | Required | +| - | - | +| function | No | + + + +--- + + +### `onEndReachedThreshold` + + How far from the end (in units of visible length of the list) the bottom edge of the list must be from the end of the content to trigger the `onEndReached` callback. Thus a value of 0.5 will trigger `onEndReached` when the end of the content is within half the visible length of the list. | Type | Required | | - | - | -| | No | +| number | No | +--- +### `onRefresh` + +```javascript +() => void +``` + +If provided, a standard RefreshControl will be added for "Pull to Refresh" functionality. Make sure to also set the `refreshing` prop correctly. + +| Type | Required | +| - | - | +| function | No | + + + +--- + + +### `onViewableItemsChanged` + +```javascript +(info: { + viewableItems: array, + changed: array, + }) => void +``` + +Called when the viewability of rows changes, as defined by the `viewabilityConfig` prop. + +| Type | Required | +| - | - | +| function | No | + + + +--- + + +### `progressViewOffset` + +Set this when offset is needed for the loading indicator to show correctly. + +| Type | Required | Platform | +| - | - | - | +| number | No | Android | + + + +--- + + +### `legacyImplementation` + +May not have full feature parity and is meant for debugging and performance comparison. + +| Type | Required | +| - | - | +| boolean | No | + + + +--- + + +### `refreshing` + +Set this true while waiting for new data from a refresh. + +| Type | Required | +| - | - | +| boolean | No | + + + +--- + + +### `removeClippedSubviews` + +This may improve scroll performance for large lists. + +> Note: +> May have bugs (missing content) in some circumstances - use at your own risk. + +| Type | Required | +| - | - | +| boolean | No | + + + +--- + + +### `viewabilityConfig` + +See `ViewabilityHelper.js` for flow type and further documentation. + +| Type | Required | +| - | - | +| ViewabilityConfig | No | + + + +--- + + +### `viewabilityConfigCallbackPairs` + +List of `ViewabilityConfig`/`onViewableItemsChanged` pairs. A specific `onViewableItemsChanged` will be called when its corresponding `ViewabilityConfig`'s conditions are met. See `ViewabilityHelper.js` for flow type and further documentation. + +| Type | Required | +| - | - | +| array of ViewabilityConfigCallbackPair | No | + ## Methods diff --git a/docs/geolocation.md b/docs/geolocation.md index 09bb454687d037..ab83e0d54637f9 100644 --- a/docs/geolocation.md +++ b/docs/geolocation.md @@ -74,7 +74,7 @@ was created from a mock provider. ### `setRNConfiguration()` ```javascript -static setRNConfiguration(config) +Geolocation.setRNConfiguration(config) ``` @@ -96,7 +96,7 @@ before using Geolocation APIs. ### `requestAuthorization()` ```javascript -static requestAuthorization() +Geolocation.requestAuthorization() ``` @@ -113,7 +113,7 @@ authorization. ### `getCurrentPosition()` ```javascript -static getCurrentPosition(geo_success, geo_error?, geo_options?) +Geolocation.getCurrentPosition(geo_success, geo_error?, geo_options?) ``` @@ -130,7 +130,7 @@ or it will request an update which might take a while. ### `watchPosition()` ```javascript -static watchPosition(success, error?, options?) +Geolocation.watchPosition(success, error?, options?) ``` @@ -145,7 +145,7 @@ options: timeout (ms), maximumAge (ms), enableHighAccuracy (bool), distanceFilte ### `clearWatch()` ```javascript -static clearWatch(watchID) +Geolocation.clearWatch(watchID) ``` @@ -155,7 +155,7 @@ static clearWatch(watchID) ### `stopObserving()` ```javascript -static stopObserving() +Geolocation.stopObserving() ``` diff --git a/docs/headless-js-android.md b/docs/headless-js-android.md index 99aa333484ba6e..4f51a232fceab4 100644 --- a/docs/headless-js-android.md +++ b/docs/headless-js-android.md @@ -89,7 +89,7 @@ Following lines shows part of Android manifest file for registering broadcast re ``` -Broadcast receiver then handles intent that was broadcasted in onReceive function. This is a great place to check whether your app is on foreground or not. If app is not on foreground we can prepare our intent to be started, with no information or additional information bundled using putExta (keep in mind bundle can handle only parcelable values). In the end service is started and wakelock is acquired. +Broadcast receiver then handles intent that was broadcasted in onReceive function. This is a great place to check whether your app is on foreground or not. If app is not on foreground we can prepare our intent to be started, with no information or additional information bundled using `putExtra` (keep in mind bundle can handle only parcelable values). In the end service is started and wakelock is acquired. ```java public class NetworkChangeReceiver extends BroadcastReceiver { diff --git a/docs/imagestyleproptypes.md b/docs/image-style-props.md similarity index 61% rename from docs/imagestyleproptypes.md rename to docs/image-style-props.md index eaac32b31f1ee9..1aff1d5091cc14 100644 --- a/docs/imagestyleproptypes.md +++ b/docs/image-style-props.md @@ -1,31 +1,34 @@ --- -id: imagestyleproptypes -title: ImageStylePropTypes +id: image-style-props +title: Image Style Props layout: docs category: APIs -permalink: docs/imagestyleproptypes.html +permalink: docs/image-style-props.html next: null -previous: textstyleproptypes +previous: text-style-props --- -### Props - -- [`borderTopRightRadius`](docs/imagestyleproptypes.html#bordertoprightradius) -- [`backfaceVisibility`](docs/imagestyleproptypes.html#backfacevisibility) -- [`borderBottomLeftRadius`](docs/imagestyleproptypes.html#borderbottomleftradius) -- [`borderBottomRightRadius`](docs/imagestyleproptypes.html#borderbottomrightradius) -- [`borderColor`](docs/imagestyleproptypes.html#bordercolor) -- [`borderRadius`](docs/imagestyleproptypes.html#borderradius) -- [`borderTopLeftRadius`](docs/imagestyleproptypes.html#bordertopleftradius) -- [`backgroundColor`](docs/imagestyleproptypes.html#backgroundcolor) -- [`borderWidth`](docs/imagestyleproptypes.html#borderwidth) -- [`opacity`](docs/imagestyleproptypes.html#opacity) -- [`overflow`](docs/imagestyleproptypes.html#overflow) -- [`resizeMode`](docs/imagestyleproptypes.html#resizemode) -- [`tintColor`](docs/imagestyleproptypes.html#tintcolor) -- [`overlayColor`](docs/imagestyleproptypes.html#overlaycolor) +[Image](docs/image.html) style props. +### Props +- [Layout Props...](docs/layout-props.html#props) +- [Shadow Props...](docs/shadow-props.html#props) +- [Transforms...](docs/transforms.html#props) +- [`borderTopRightRadius`](docs/image-style-props.html#bordertoprightradius) +- [`backfaceVisibility`](docs/image-style-props.html#backfacevisibility) +- [`borderBottomLeftRadius`](docs/image-style-props.html#borderbottomleftradius) +- [`borderBottomRightRadius`](docs/image-style-props.html#borderbottomrightradius) +- [`borderColor`](docs/image-style-props.html#bordercolor) +- [`borderRadius`](docs/image-style-props.html#borderradius) +- [`borderTopLeftRadius`](docs/image-style-props.html#bordertopleftradius) +- [`backgroundColor`](docs/image-style-props.html#backgroundcolor) +- [`borderWidth`](docs/image-style-props.html#borderwidth) +- [`opacity`](docs/image-style-props.html#opacity) +- [`overflow`](docs/image-style-props.html#overflow) +- [`resizeMode`](docs/image-style-props.html#resizemode) +- [`tintColor`](docs/image-style-props.html#tintcolor) +- [`overlayColor`](docs/image-style-props.html#overlaycolor) diff --git a/docs/image.md b/docs/image.md index 804262a25622d0..d60304e4f03c98 100644 --- a/docs/image.md +++ b/docs/image.md @@ -109,7 +109,6 @@ Also, if you use GIF with ProGuard, you will need to add this rule in `proguard- ### Props -- [`style`](docs/image.html#style) - [`blurRadius`](docs/image.html#blurradius) - [`onLayout`](docs/image.html#onlayout) - [`onLoad`](docs/image.html#onload) @@ -126,6 +125,7 @@ Also, if you use GIF with ProGuard, you will need to add this rule in `proguard- - [`defaultSource`](docs/image.html#defaultsource) - [`onPartialLoad`](docs/image.html#onpartialload) - [`onProgress`](docs/image.html#onprogress) +- [`style`](docs/image.html#style) @@ -144,73 +144,6 @@ Also, if you use GIF with ProGuard, you will need to add this rule in `proguard- ## Props -### `style` - -> `ImageResizeMode` is an `Enum` for different image resizing modes, set via the -> `resizeMode` style property on `Image` components. The values are `contain`, `cover`, -> `stretch`, `center`, `repeat`. - -| Type | Required | -| - | - | -| style | No | - - - - [Layout Props...](docs/layout-props.html#props) - - - [Shadow Props...](docs/shadow-props.html#props) - - - [Transforms...](docs/transforms.html#props) - - - **`borderTopRightRadius`**: number - - - **`backfaceVisibility`**: enum('visible', 'hidden') - - - **`borderBottomLeftRadius`**: number - - - **`borderBottomRightRadius`**: number - - - **`borderColor`**: [color](docs/colors.html) - - - **`borderRadius`**: number - - - **`borderTopLeftRadius`**: number - - - **`backgroundColor`**: [color](docs/colors.html) - - - **`borderWidth`**: number - - - **`opacity`**: number - - - **`overflow`**: enum('visible', 'hidden') - - - **`resizeMode`**: Object.keys(ImageResizeMode) - - - **`tintColor`**: [color](docs/colors.html) - - Changes the color of all the non-transparent pixels to the tintColor. - - - **`overlayColor`**: string (_Android_) - - When the image has rounded corners, specifying an overlayColor will - cause the remaining space in the corners to be filled with a solid color. - This is useful in cases which are not supported by the Android - implementation of rounded corners: - - Certain resize modes, such as 'contain' - - Animated GIFs - - A typical way to use this prop is with images displayed on a solid - background and setting the `overlayColor` to the same color - as the background. - - For details of how this works under the hood, see - http://frescolib.org/docs/rounded-corners-and-circles.html - - - - - ---- - ### `blurRadius` blurRadius: the blur radius of the blur filter added to the image @@ -483,27 +416,25 @@ Invoked on download progress with `{nativeEvent: {loaded, total}}`. | function | No | iOS | +--- +### `style` - +| Type | Required | +| - | - | +| [style](docs/imagestyleproptypes.html) | No | ## Methods ### `getSize()` ```javascript -static getSize(uri: string, success: function, [failure]: function): +static getSize(uri: string, success: function, [failure]: function): void ``` -Retrieve the width and height (in pixels) of an image prior to displaying it. -This method can fail if the image cannot be found, or fails to download. +Retrieve the width and height (in pixels) of an image prior to displaying it. This method can fail if the image cannot be found, or fails to download. -In order to retrieve the image dimensions, the image may first need to be -loaded or downloaded, after which it will be cached. This means that in -principle you could use this method to preload images, however it is not -optimized for that purpose, and may in future be implemented in a way that -does not fully load/download the image data. A proper, supported way to -preload images will be provided as a separate API. +In order to retrieve the image dimensions, the image may first need to be loaded or downloaded, after which it will be cached. This means that in principle you could use this method to preload images, however it is not optimized for that purpose, and may in future be implemented in a way that does not fully load/download the image data. A proper, supported way to preload images will be provided as a separate API. Does not work for static image resources. @@ -511,9 +442,9 @@ Does not work for static image resources. | Name | Type | Required | Description | | - | - | - | - | -| uri | string | No | The location of the image. | -| success | function | No | The function that will be called if the image was successfully found and widthand height retrieved. | -| failure | function | Yes | The function that will be called if there was an error, such as failing toto retrieve the image. | +| uri | string | Yes | The location of the image. | +| success | function | Yes | The function that will be called if the image was successfully found and widthand height retrieved. | +| failure | function | No | The function that will be called if there was an error, such as failing toto retrieve the image. | @@ -523,7 +454,7 @@ Does not work for static image resources. ### `prefetch()` ```javascript -static prefetch(url: string): +Image.prefetch(url: string): ``` Prefetches a remote image for later use by downloading it to the disk @@ -533,7 +464,7 @@ cache | Name | Type | Required | Description | | - | - | - | - | -| url | string | No | The remote location of the image. | +| url | string | Yes | The remote location of the image. | diff --git a/docs/imageeditor.md b/docs/imageeditor.md index d0ec17a2fbe079..6495335866c3b8 100644 --- a/docs/imageeditor.md +++ b/docs/imageeditor.md @@ -26,19 +26,20 @@ previous: geolocation ### `cropImage()` ```javascript -static cropImage(uri, cropData, success, failure) +ImageEditor.cropImage(uri, cropData, success, failure) ``` +Crop the image specified by the URI param. If URI points to a remote image, it will be downloaded automatically. If the image cannot be loaded/downloaded, the failure callback will be called. -Crop the image specified by the URI param. If URI points to a remote -image, it will be downloaded automatically. If the image cannot be -loaded/downloaded, the failure callback will be called. - -If the cropping process is successful, the resultant cropped image -will be stored in the ImageStore, and the URI returned in the success -callback will point to the image in the store. Remember to delete the -cropped image from the ImageStore when you are done with it. - +If the cropping process is successful, the resultant cropped image will be stored in the ImageStore, and the URI returned in the success callback will point to the image in the store. Remember to delete the cropped image from the ImageStore when you are done with it. +**Crop Data Options:** +The following options can be used with the `cropData` parameter: +| Name | Type | Required | Description | +| - | - | - | - | +| offset | `{ x: number, y: number}` | Yes | The top-left corner of the cropped image, specified in the original image's coordinate space. | +| size | `{ width: number, height: number }` | Yes | The size (dimensions) of the cropped image, specified in the original image's coordinate space. | +| displaySize | `{ width: number, height: number }` | No | Size to scale the cropped image to. | +| resizeMode | `enum( contain: string, cover: string, stretch: string }` | No | The resizing mode to use when scaling the image. If the `displaySize` param is not specified, this has no effect. | diff --git a/docs/imagepickerios.md b/docs/imagepickerios.md index 238f2437239a7e..52670059309f6b 100644 --- a/docs/imagepickerios.md +++ b/docs/imagepickerios.md @@ -29,7 +29,7 @@ previous: imageeditor ### `canRecordVideos()` ```javascript -static canRecordVideos(callback) +ImagePickerIOS.canRecordVideos(callback) ``` @@ -39,7 +39,7 @@ static canRecordVideos(callback) ### `canUseCamera()` ```javascript -static canUseCamera(callback) +ImagePickerIOS.canUseCamera(callback) ``` @@ -49,7 +49,7 @@ static canUseCamera(callback) ### `openCameraDialog()` ```javascript -static openCameraDialog(config, successCallback, cancelCallback) +ImagePickerIOS.openCameraDialog(config, successCallback, cancelCallback) ``` @@ -59,7 +59,7 @@ static openCameraDialog(config, successCallback, cancelCallback) ### `openSelectDialog()` ```javascript -static openSelectDialog(config, successCallback, cancelCallback) +ImagePickerIOS.openSelectDialog(config, successCallback, cancelCallback) ``` diff --git a/docs/imagestore.md b/docs/imagestore.md index 910ec25907fd42..a0210206c9a09e 100644 --- a/docs/imagestore.md +++ b/docs/imagestore.md @@ -29,7 +29,7 @@ previous: imagepickerios ### `hasImageForTag()` ```javascript -static hasImageForTag(uri, callback) +ImageStore.hasImageForTag(uri, callback) ``` @@ -44,7 +44,7 @@ Check if the ImageStore contains image data for the specified URI. ### `removeImageForTag()` ```javascript -static removeImageForTag(uri) +ImageStore.removeImageForTag(uri) ``` @@ -63,7 +63,7 @@ will simply fail silently. ### `addImageFromBase64()` ```javascript -static addImageFromBase64(base64ImageData, success, failure) +ImageStore.addImageFromBase64(base64ImageData, success, failure) ``` @@ -85,7 +85,7 @@ than necessary. ### `getBase64ForTag()` ```javascript -static getBase64ForTag(uri, success, failure) +ImageStore.getBase64ForTag(uri, success, failure) ``` diff --git a/docs/integration-with-existing-apps.md b/docs/integration-with-existing-apps.md index 8f708c9b79116a..3aebba0fceb78e 100644 --- a/docs/integration-with-existing-apps.md +++ b/docs/integration-with-existing-apps.md @@ -361,7 +361,7 @@ const styles = StyleSheet.create({ }); // Module name -AppRegistry.registerComponent('MyReactNativeApp', () => RNHighScores); +AppRegistry.registerComponent('RNHighScores', () => RNHighScores); ``` > `RNHighScores` is the name of your module that will be used when you add a view to React Native from within your iOS application. diff --git a/docs/interactionmanager.md b/docs/interactionmanager.md index cb034edc4e9372..e76e85a64bfc82 100644 --- a/docs/interactionmanager.md +++ b/docs/interactionmanager.md @@ -63,12 +63,12 @@ from executing, making apps more responsive. - [`createInteractionHandle`](docs/interactionmanager.html#createinteractionhandle) - [`clearInteractionHandle`](docs/interactionmanager.html#clearinteractionhandle) - [`setDeadline`](docs/interactionmanager.html#setdeadline) +- [`addListener`](docs/interactionmanager.html#addlistener) ### Properties - [`Events`](docs/interactionmanager.html#events) -- [`addListener`](docs/interactionmanager.html#addlistener) @@ -82,7 +82,7 @@ from executing, making apps more responsive. ### `runAfterInteractions()` ```javascript -static runAfterInteractions(task) +InteractionManager.runAfterInteractions(task) ``` @@ -97,7 +97,7 @@ Schedule a function to run after all interactions have completed. Returns a canc ### `createInteractionHandle()` ```javascript -static createInteractionHandle() +InteractionManager.createInteractionHandle() ``` @@ -111,7 +111,7 @@ Notify manager that an interaction has started. ### `clearInteractionHandle()` ```javascript -static clearInteractionHandle(handle) +InteractionManager.clearInteractionHandle(handle) ``` @@ -125,7 +125,7 @@ Notify manager that an interaction has completed. ### `setDeadline()` ```javascript -static setDeadline(deadline) +InteractionManager.setDeadline(deadline) ``` @@ -133,14 +133,21 @@ A positive number will use setTimeout to schedule any tasks after the eventLoopRunningTime hits the deadline value, otherwise all tasks will be executed in one setImmediate batch (default). +--- +### `addListener()` +```javascript +InteractionManager.addListener(EventEmitter) +``` -## Properties +## Properties ---- +### `Events` +- `interactionStart` +- `interactionComplete` diff --git a/docs/keyboard.md b/docs/keyboard.md index 374a7e588d167e..418611d31f6dc6 100644 --- a/docs/keyboard.md +++ b/docs/keyboard.md @@ -68,7 +68,7 @@ class Example extends Component { ### `addListener()` ```javascript -static addListener(eventName, callback) +Keyboard.addListener(eventName, callback) ``` @@ -102,7 +102,7 @@ since there is no native corresponding event. ### `removeListener()` ```javascript -static removeListener(eventName, callback) +Keyboard.removeListener(eventName, callback) ``` @@ -119,7 +119,7 @@ Removes a specific listener. ### `removeAllListeners()` ```javascript -static removeAllListeners(eventName) +Keyboard.removeAllListeners(eventName) ``` @@ -135,7 +135,7 @@ Removes all listeners for a specific event type. ### `dismiss()` ```javascript -static dismiss() +Keyboard.dismiss() ``` diff --git a/docs/keyboardavoidingview.md b/docs/keyboardavoidingview.md index b13b3ff9c7f2a6..b5e0fdff23aa7a 100644 --- a/docs/keyboardavoidingview.md +++ b/docs/keyboardavoidingview.md @@ -12,7 +12,7 @@ It can automatically adjust either its position or bottom padding based on the p ### Props -* [ViewPropTypes props...](docs/viewproptypes.html#props) +- [ViewPropTypes props...](docs/viewproptypes.html#props) - [`keyboardVerticalOffset`](docs/keyboardavoidingview.html#keyboardverticaloffset) - [`behavior`](docs/keyboardavoidingview.html#behavior) - [`contentContainerStyle`](docs/keyboardavoidingview.html#contentcontainerstyle) @@ -68,7 +68,7 @@ The style of the content container(View) when behavior is 'position'. | Type | Required | | - | - | -| ViewPropTypes.style | No | +| [ViewPropTypes.style](docs/viewproptypes.html#style) | No | diff --git a/docs/layout-props.md b/docs/layout-props.md index 6e5e919c523c62..90d4d39c92443b 100644 --- a/docs/layout-props.md +++ b/docs/layout-props.md @@ -4,7 +4,7 @@ title: Layout Props layout: docs category: APIs permalink: docs/layout-props.html -next: shadow-props +next: picker-style-props previous: vibrationios --- ### Props diff --git a/docs/layoutanimation.md b/docs/layoutanimation.md index 5e4255938d3da6..31a92f2c6b9244 100644 --- a/docs/layoutanimation.md +++ b/docs/layoutanimation.md @@ -46,7 +46,7 @@ Note that in order to get this to work on **Android** you need to set the follow ### `configureNext()` ```javascript -static configureNext(config, onAnimationDidEnd?) +LayoutAnimation.configureNext(config, onAnimationDidEnd?) ``` @@ -71,7 +71,7 @@ Only supported on iOS. ### `create()` ```javascript -static create(duration, type, creationProp) +LayoutAnimation.create(duration, type, creationProp) ``` @@ -85,7 +85,7 @@ Helper for creating a config for `configureNext`. ### `checkConfig()` ```javascript -static checkConfig(config, location, name) +LayoutAnimation.checkConfig(config, location, name) ``` diff --git a/docs/linking-libraries-ios.md b/docs/linking-libraries-ios.md index 672eadbcfaff10..ad15d09db6e05e 100644 --- a/docs/linking-libraries-ios.md +++ b/docs/linking-libraries-ios.md @@ -4,6 +4,7 @@ title: Linking Libraries layout: docs category: Guides (iOS) permalink: docs/linking-libraries-ios.html +banner: ejected next: running-on-simulator-ios previous: custom-webview-ios --- diff --git a/docs/linking.md b/docs/linking.md index 6eed2276e6e8ae..a3194bfb2dd3aa 100644 --- a/docs/linking.md +++ b/docs/linking.md @@ -206,10 +206,9 @@ The method returns a `Promise` object. If the user confirms the open dialog or t url automatically opens, the promise is resolved. If the user cancels the open dialog or there are no registered applications for the url, the promise is rejected. -NOTE: This method will fail if the system doesn't know how to open the specified URL. -If you're passing in a non-http(s) URL, it's best to check {@code canOpenURL} first. +> This method will fail if the system doesn't know how to open the specified URL. If you're passing in a non-http(s) URL, it's best to check {@code canOpenURL} first. -NOTE: For web URLs, the protocol ("http://", "https://") must be set accordingly! +> For web URLs, the protocol ("http://", "https://") must be set accordingly! @@ -225,13 +224,16 @@ canOpenURL(url) Determine whether or not an installed app can handle a given URL. -NOTE: For web URLs, the protocol ("http://", "https://") must be set accordingly! +> For web URLs, the protocol ("http://", "https://") must be set accordingly! -NOTE: As of iOS 9, your app needs to provide the `LSApplicationQueriesSchemes` key +> As of iOS 9, your app needs to provide the `LSApplicationQueriesSchemes` key inside `Info.plist` or canOpenURL will always return false. -@param URL the URL to open +**Parameters:** +| Name | Type | Required | Description | +| - | - | - | - | +| url | string | Yes | The URL to open | @@ -247,7 +249,7 @@ getInitialURL() If the app launch was triggered by an app link, it will give the link url, otherwise it will give `null` -NOTE: To support deep linking on Android, refer http://developer.android.com/training/app-indexing/deep-linking.html#handling-intents +> To support deep linking on Android, refer http://developer.android.com/training/app-indexing/deep-linking.html#handling-intents diff --git a/docs/maskedviewios.md b/docs/maskedviewios.md index 91ca93b1e331f1..0de578a532ef64 100644 --- a/docs/maskedviewios.md +++ b/docs/maskedviewios.md @@ -43,7 +43,7 @@ transparent pixels block that content. ### Props -* [ViewPropTypes props...](docs/viewproptypes.html#props) +- [View props...](docs/view-props.html) - [`maskElement`](docs/maskedviewios.html#maskelement) @@ -59,7 +59,7 @@ transparent pixels block that content. ### `maskElement` - +Should be a React element to be rendered and applied as the mask for the child element. | Type | Required | | - | - | diff --git a/docs/modal.md b/docs/modal.md index ac2255d9b32aa7..673fb545932f04 100644 --- a/docs/modal.md +++ b/docs/modal.md @@ -67,7 +67,7 @@ The `onRequestClose` callback is called when the user taps the hardware back but | Type | Required | | - | - | -| (Platform.isTVOS || Platform.OS === 'android') ? PropTypes.func.isRequired : PropTypes.func | No | +| function | Required on Android and Apple TV | diff --git a/docs/native-components-android.md b/docs/native-components-android.md index fdee7e4dcf879a..5d0a96e2fc8087 100644 --- a/docs/native-components-android.md +++ b/docs/native-components-android.md @@ -4,6 +4,7 @@ title: Native UI Components layout: docs category: Guides (Android) permalink: docs/native-components-android.html +banner: ejected next: custom-webview-android previous: native-modules-android --- diff --git a/docs/native-components-ios.md b/docs/native-components-ios.md index 85ca430ca72b8a..231f78df6f5197 100644 --- a/docs/native-components-ios.md +++ b/docs/native-components-ios.md @@ -4,6 +4,7 @@ title: Native UI Components layout: docs category: Guides (iOS) permalink: docs/native-components-ios.html +banner: ejected next: custom-webview-ios previous: native-modules-ios --- diff --git a/docs/native-modules-android.md b/docs/native-modules-android.md index 7ff9adacba677e..e4365f187c9f83 100644 --- a/docs/native-modules-android.md +++ b/docs/native-modules-android.md @@ -4,6 +4,7 @@ title: Native Modules layout: docs category: Guides (Android) permalink: docs/native-modules-android.html +banner: ejected next: native-components-android previous: app-extensions --- diff --git a/docs/native-modules-ios.md b/docs/native-modules-ios.md index fa2f760808ab91..de8fe85fe0336d 100644 --- a/docs/native-modules-ios.md +++ b/docs/native-modules-ios.md @@ -4,6 +4,7 @@ title: Native Modules layout: docs category: Guides (iOS) permalink: docs/native-modules-ios.html +banner: ejected next: native-components-ios previous: testing --- diff --git a/docs/nativemethodsmixing.md b/docs/nativemethodsmixing.md new file mode 100644 index 00000000000000..59e87a89ccd4a5 --- /dev/null +++ b/docs/nativemethodsmixing.md @@ -0,0 +1,8 @@ +--- +id: NativeMethodsMixin +title: NativeMethodsMixin +layout: redirect +permalink: docs/nativemethodsmixin.html +destinationUrl: direct-manipulation.html#other-native-methods +--- +Redirecting... \ No newline at end of file diff --git a/docs/navigatorios.md b/docs/navigatorios.md index 342902885fdd7a..893e2ad32b42b5 100644 --- a/docs/navigatorios.md +++ b/docs/navigatorios.md @@ -7,21 +7,11 @@ permalink: docs/navigatorios.html next: picker previous: modal --- -`NavigatorIOS` is a wrapper around -[`UINavigationController`](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UINavigationController_Class/), -enabling you to implement a navigation stack. It works exactly the same as it -would on a native app using `UINavigationController`, providing the same -animations and behavior from UIKit. - -As the name implies, it is only available on iOS. Take a look at -[`React Navigation`](https://reactnavigation.org/) for a cross-platform -solution in JavaScript, or check out either of these components for native -solutions: [native-navigation](http://airbnb.io/native-navigation/), -[react-native-navigation](https://github.com/wix/react-native-navigation). - -To set up the navigator, provide the `initialRoute` prop with a route -object. A route object is used to describe each scene that your app -navigates to. `initialRoute` represents the first route in your navigator. +`NavigatorIOS` is a wrapper around [`UINavigationController`](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UINavigationController_Class/), enabling you to implement a navigation stack. It works exactly the same as it would on a native app using `UINavigationController`, providing the same animations and behavior from UIKit. + +As the name implies, it is only available on iOS. Take a look at [`React Navigation`](https://reactnavigation.org/) for a cross-platform solution in JavaScript, or check out either of these components for native solutions: [native-navigation](http://airbnb.io/native-navigation/), [react-native-navigation](https://github.com/wix/react-native-navigation). + +To set up the navigator, provide the `initialRoute` prop with a route object. A route object is used to describe each scene that your app navigates to. `initialRoute` represents the first route in your navigator. ``` import PropTypes from 'prop-types'; @@ -67,13 +57,9 @@ class MyScene extends Component { } ``` -In this code, the navigator renders the component specified in initialRoute, -which in this case is `MyScene`. This component will receive a `route` prop -and a `navigator` prop representing the navigator. The navigator's navigation -bar will render the title for the current scene, "My Initial Scene". +In this code, the navigator renders the component specified in initialRoute, which in this case is `MyScene`. This component will receive a `route` prop and a `navigator` prop representing the navigator. The navigator's navigation bar will render the title for the current scene, "My Initial Scene". -You can optionally pass in a `passProps` property to your `initialRoute`. -`NavigatorIOS` passes this in as props to the rendered component: +You can optionally pass in a `passProps` property to your `initialRoute`. `NavigatorIOS` passes this in as props to the rendered component: ``` initialRoute={{ @@ -87,10 +73,7 @@ You can then access the props passed in via `{this.props.myProp}`. #### Handling Navigation -To trigger navigation functionality such as pushing or popping a view, you -have access to a `navigator` object. The object is passed in as a prop to any -component that is rendered by `NavigatorIOS`. You can then call the -relevant methods to perform the navigation action you need: +To trigger navigation functionality such as pushing or popping a view, you have access to a `navigator` object. The object is passed in as a prop to any component that is rendered by `NavigatorIOS`. You can then call the relevant methods to perform the navigation action you need: ``` class MyView extends Component { @@ -119,8 +102,7 @@ class MyView extends Component { } ``` -You can also trigger navigator functionality from the `NavigatorIOS` -component: +You can also trigger navigator functionality from the `NavigatorIOS` component: ``` class NavvyIOS extends Component { @@ -150,18 +132,11 @@ class NavvyIOS extends Component { } ``` -The code above adds a `_handleNavigationRequest` private method that is -invoked from the `NavigatorIOS` component when the right navigation bar item -is pressed. To get access to the navigator functionality, a reference to it -is saved in the `ref` prop and later referenced to push a new scene into the -navigation stack. +The code above adds a `_handleNavigationRequest` private method that is invoked from the `NavigatorIOS` component when the right navigation bar item is pressed. To get access to the navigator functionality, a reference to it is saved in the `ref` prop and later referenced to push a new scene into the navigation stack. #### Navigation Bar Configuration -Props passed to `NavigatorIOS` will set the default configuration -for the navigation bar. Props passed as properties to a route object will set -the configuration for that route's navigation bar, overriding any props -passed to the `NavigatorIOS` component. +Props passed to `NavigatorIOS` will set the default configuration for the navigation bar. Props passed as properties to a route object will set the configuration for that route's navigation bar, overriding any props passed to the `NavigatorIOS` component. ``` _handleNavigationRequest() { @@ -183,8 +158,7 @@ render() { } ``` -In the example above the navigation bar color is changed when the new route -is pushed. +In the example above the navigation bar color is changed when the new route is pushed. ### Props @@ -228,14 +202,64 @@ is pushed. NavigatorIOS uses `route` objects to identify child views, their props, and navigation bar configuration. Navigation operations such as push -operations expect routes to look like this the `initialRoute`. +operations expect routes to look like this. | Type | Required | | - | - | -| object: {component: function,title: string,titleImage: Image.propTypes.source,passProps: object,backButtonIcon: Image.propTypes.source,backButtonTitle: string,leftButtonIcon: Image.propTypes.source,leftButtonTitle: string,leftButtonSystemIcon: Object.keys(SystemIcons),onLeftButtonPress: function,rightButtonIcon: Image.propTypes.source,rightButtonTitle: string,rightButtonSystemIcon: Object.keys(SystemIcons),onRightButtonPress: function,wrapperStyle: ViewPropTypes.style,navigationBarHidden: bool,shadowHidden: bool,tintColor: string,barTintColor: string,barStyle: enum('default', 'black'),titleTextColor: string,translucent: bool} | Yes | - - - +| object | Yes | + +**Routes:** + +The following parameters can be used to define a route: + +* `**component**`: function + The React Class to render for this route. +* `**title**`: string + The title displayed in the navigation bar and the back button for this route. +* `**titleImage**`: [Image](docs/image.html) + If set, a title image will appear instead of the text title. +* `**passProps**`: object + Use this to specify additional props to pass to the rendered component. `NavigatorIOS` will automatically pass in `route` and `navigator` props to the comoponent. +* `**backButtonIcon**`: [Image](docs/image.html) + If set, the left navigation button image will be displayed using this source. Note that this doesn't apply to the header of the current view, but to those views that are subsequently pushed. +* `**backButtonTitle**`: string + If set, the left navigation button text will be set to this. Note that this doesn't apply to the left button of the current view, but to those views that are subsequently pushed. +* `**leftButtonIcon**`: [Image](docs/image.html) + If set, the left navigation button image will be displayed using this source. +* `**leftButtonTitle**`: string + If set, the left navigation button will display this text. +* `**leftButtonSystemIcon**`: [SystemIcon](docs/navigatorios.html#system-icons) + If set, the left header button will appear with this system icon. See below for supported icons. +* `**onLeftButtonPress**`: function + This function will be invoked when the left navigation bar item is pressed. +* `**rightButtonIcon**`: [Image](docs/image.html) + If set, the right navigation button image will be displayed using this source. +* `**rightButtonTitle**`: string + If set, the right navigation button will display this text. +* `**rightButtonSystemIcon**`: [SystemIcon](docs/navigatorios.html#system-icons) + If set, the right header button will appear with this system icon. See below for supported icons. +* `**onRightButtonPress**`: function + This function will be invoked when the right navigation bar item is pressed. +* `**wrapperStyle**`: [ViewPropTypes.style](docs/viewproptypes.html#style) + Styles for the navigation item containing the component. +* `**navigationBarHidden**`: boolean + Boolean value that indicates whether the navigation bar is hidden. +* `**shadowHidden**`: boolean + Boolean value that indicates whether to hide the 1px hairline shadow. +* `**tintColor**`: string + The color used for the buttons in the navigation bar. +* `**barTintColor**`: string + The background color of the navigation bar. +* `**barStyle**`: enum('default', 'black') + The style of the navigation bar. Supported values are 'default', 'black'. Use 'black' instead of setting `barTintColor` to black. This produces a navigation bar with the native iOS style with higher translucency. +* `**titleTextColor**`: string + The text color of the navigation bar title. +* `**translucent**`: boolean + Boolean value that indicates whether the navigation bar is translucent. + +#### System Icons + +Used in `leftButtonSystemIcon` and `rightButtonSystemIcon`. Supported icons are `done`, `cancel`, `edit`, `save`, `add`, `compose`, `reply`, `action`, `organize`, `bookmarks`, `search`, `refresh`, `stop`, `camera`, `trash`, `play`, `pause`, `rewind`, `fast-forward`, `undo`, `redo`, and `page-curl`. --- @@ -295,7 +319,7 @@ A common use case is to set the `backgroundColor` for every scene. | Type | Required | | - | - | -| ViewPropTypes.style | No | +| [ViewPropTypes.style](docs/viewproptypes.html#style) | No | @@ -384,7 +408,7 @@ Navigate forward to a new route. | Name | Type | Required | Description | | - | - | - | - | -| route | object | No | The new route to navigate to. | +| route | object | Yes | The new route to navigate to. | @@ -403,7 +427,7 @@ Go back N scenes at once. When N=1, behavior matches `pop()`. | Name | Type | Required | Description | | - | - | - | - | -| n | number | No | The number of scenes to pop. | +| n | number | Yes | The number of scenes to pop. | @@ -434,8 +458,8 @@ Replace a route in the navigation stack. | Name | Type | Required | Description | | - | - | - | - | -| route | object | No | The new route that will replace the specified one. | -| index | number | No | The route into the stack that should be replaced. If it is negative, it counts from the back of the stack. | +| route | object | Yes | The new route that will replace the specified one. | +| index | number | Yes | The route into the stack that should be replaced. If it is negative, it counts from the back of the stack. | @@ -455,7 +479,7 @@ load the view for the new route. | Name | Type | Required | Description | | - | - | - | - | -| route | object | No | The new route to navigate to. | +| route | object | Yes | The new route to navigate to. | @@ -474,7 +498,7 @@ Replace the route/view for the previous scene. | Name | Type | Required | Description | | - | - | - | - | -| route | object | No | The new route to will replace the previous scene. | +| route | object | Yes | The new route to will replace the previous scene. | @@ -505,7 +529,7 @@ Go back to the item for a particular route object. | Name | Type | Required | Description | | - | - | - | - | -| route | object | No | The new route to navigate to. | +| route | object | Yes | The new route to navigate to. | @@ -524,7 +548,7 @@ Replaces the previous route/view and transitions back to it. | Name | Type | Required | Description | | - | - | - | - | -| route | object | No | The new route that replaces the previous scene. | +| route | object | Yes | The new route that replaces the previous scene. | @@ -543,7 +567,7 @@ Replaces the top item and pop to it. | Name | Type | Required | Description | | - | - | - | - | -| route | object | No | The new route that will replace the topmost item. | +| route | object | Yes | The new route that will replace the topmost item. | diff --git a/docs/netinfo.md b/docs/netinfo.md index 4f8cd6c6d111a8..2d7eb73e44c029 100644 --- a/docs/netinfo.md +++ b/docs/netinfo.md @@ -8,7 +8,7 @@ next: panresponder previous: linking --- -NetInfo exposes info about online/offline status +NetInfo exposes info about online/offline status. ``` NetInfo.getConnectionInfo().then((connectionInfo) => { @@ -57,44 +57,6 @@ app's `AndroidManifest.xml`: `` -### isConnectionExpensive - -Available on Android. Detect if the current active connection is metered or not. A network is -classified as metered when the user is sensitive to heavy data usage on that connection due to -monetary costs, data limitations or battery/performance issues. - -``` -NetInfo.isConnectionExpensive() -.then(isConnectionExpensive => { - console.log('Connection is ' + (isConnectionExpensive ? 'Expensive' : 'Not Expensive')); -}) -.catch(error => { - console.error(error); -}); -``` - -### isConnected - -Available on all platforms. Asynchronously fetch a boolean to determine -internet connectivity. - -``` -NetInfo.isConnected.fetch().then(isConnected => { - console.log('First, is ' + (isConnected ? 'online' : 'offline')); -}); -function handleFirstConnectivityChange(isConnected) { - console.log('Then, is ' + (isConnected ? 'online' : 'offline')); - NetInfo.isConnected.removeEventListener( - 'connectionChange', - handleFirstConnectivityChange - ); -} -NetInfo.isConnected.addEventListener( - 'connectionChange', - handleFirstConnectivityChange -); -``` - ### Connectivity Types (deprecated) The following connectivity types are deprecated. They're used by the deprecated APIs `fetch` and the `change` event. @@ -148,7 +110,7 @@ The rest of the connectivity types are hidden by the Android API, but can be use ### `addEventListener()` ```javascript -static addEventListener(eventName, handler) +NetInfo.addEventListener(eventName, handler) ``` @@ -170,7 +132,7 @@ Adds an event handler. Supported events: ### `removeEventListener()` ```javascript -static removeEventListener(eventName, handler) +NetInfo.removeEventListener(eventName, handler) ``` @@ -184,7 +146,7 @@ Removes the listener for network status changes. ### `fetch()` ```javascript -static fetch() +NetInfo.fetch() ``` @@ -199,7 +161,7 @@ resolves with one of the deprecated connectivity types listed above. ### `getConnectionInfo()` ```javascript -static getConnectionInfo() +NetInfo.getConnectionInfo() ``` @@ -215,12 +177,44 @@ respectively. ### `isConnectionExpensive()` ```javascript -static isConnectionExpensive() +NetInfo.isConnectionExpensive() +``` + +Available on Android. Detect if the current active connection is metered or not. A network is +classified as metered when the user is sensitive to heavy data usage on that connection due to +monetary costs, data limitations or battery/performance issues. + +``` +NetInfo.isConnectionExpensive() +.then(isConnectionExpensive => { + console.log('Connection is ' + (isConnectionExpensive ? 'Expensive' : 'Not Expensive')); +}) +.catch(error => { + console.error(error); +}); ``` ## Properties +### `isConnected` +Available on all platforms. Asynchronously fetch a boolean to determine internet connectivity. +``` +NetInfo.isConnected.fetch().then(isConnected => { + console.log('First, is ' + (isConnected ? 'online' : 'offline')); +}); +function handleFirstConnectivityChange(isConnected) { + console.log('Then, is ' + (isConnected ? 'online' : 'offline')); + NetInfo.isConnected.removeEventListener( + 'connectionChange', + handleFirstConnectivityChange + ); +} +NetInfo.isConnected.addEventListener( + 'connectionChange', + handleFirstConnectivityChange +); +``` diff --git a/docs/panresponder.md b/docs/panresponder.md index 5bb6d7b71de810..35ed082b31c5fd 100644 --- a/docs/panresponder.md +++ b/docs/panresponder.md @@ -121,41 +121,31 @@ To see it in action, try the ### `create()` ```javascript -static create(config) +PanResponder.create(config) ``` - -@param {object} config Enhanced versions of all of the responder callbacks -that provide not only the typical `ResponderSyntheticEvent`, but also the -`PanResponder` gesture state. Simply replace the word `Responder` with -`PanResponder` in each of the typical `onResponder*` callbacks. For -example, the `config` object would look like: - - - `onMoveShouldSetPanResponder: (e, gestureState) => {...}` - - `onMoveShouldSetPanResponderCapture: (e, gestureState) => {...}` - - `onStartShouldSetPanResponder: (e, gestureState) => {...}` - - `onStartShouldSetPanResponderCapture: (e, gestureState) => {...}` - - `onPanResponderReject: (e, gestureState) => {...}` - - `onPanResponderGrant: (e, gestureState) => {...}` - - `onPanResponderStart: (e, gestureState) => {...}` - - `onPanResponderEnd: (e, gestureState) => {...}` - - `onPanResponderRelease: (e, gestureState) => {...}` - - `onPanResponderMove: (e, gestureState) => {...}` - - `onPanResponderTerminate: (e, gestureState) => {...}` - - `onPanResponderTerminationRequest: (e, gestureState) => {...}` - - `onShouldBlockNativeResponder: (e, gestureState) => {...}` - - In general, for events that have capture equivalents, we update the - gestureState once in the capture phase and can use it in the bubble phase - as well. - - Be careful with onStartShould* callbacks. They only reflect updated - `gestureState` for start/end events that bubble/capture to the Node. - Once the node is the responder, you can rely on every start/end event - being processed by the gesture and `gestureState` being updated - accordingly. (numberActiveTouches) may not be totally accurate unless you - are the responder. - - +Enhanced versions of all of the responder callbacks +that provide not only the typical `ResponderSyntheticEvent`, but also the `PanResponder` gesture state. Simply replace the word `Responder` with +`PanResponder` in each of the typical `onResponder*` callbacks. + +For example, the `config` object would look like: + +- `onMoveShouldSetPanResponder: (e, gestureState) => {...}` +- `onMoveShouldSetPanResponderCapture: (e, gestureState) => {...}` +- `onStartShouldSetPanResponder: (e, gestureState) => {...}` +- `onStartShouldSetPanResponderCapture: (e, gestureState) => {...}` +- `onPanResponderReject: (e, gestureState) => {...}` +- `onPanResponderGrant: (e, gestureState) => {...}` +- `onPanResponderStart: (e, gestureState) => {...}` +- `onPanResponderEnd: (e, gestureState) => {...}` +- `onPanResponderRelease: (e, gestureState) => {...}` +- `onPanResponderMove: (e, gestureState) => {...}` +- `onPanResponderTerminate: (e, gestureState) => {...}` +- `onPanResponderTerminationRequest: (e, gestureState) => {...}` +- `onShouldBlockNativeResponder: (e, gestureState) => {...}` + +In general, for events that have capture equivalents, we update the gestureState once in the capture phase and can use it in the bubble phase as well. + +Be careful with onStartShould* callbacks. They only reflect updated `gestureState` for start/end events that bubble/capture to the Node. Once the node is the responder, you can rely on every start/end event being processed by the gesture and `gestureState` being updated accordingly. (numberActiveTouches) may not be totally accurate unless you are the responder. diff --git a/docs/permissionsandroid.md b/docs/permissionsandroid.md index e136da5a555019..e56db936decfa1 100644 --- a/docs/permissionsandroid.md +++ b/docs/permissionsandroid.md @@ -19,23 +19,16 @@ previous: panresponder

-`PermissionsAndroid` provides access to Android M's new permissions model. -Some permissions are granted by default when the application is installed -so long as they appear in `AndroidManifest.xml`. However, "dangerous" -permissions require a dialog prompt. You should use this module for those +`PermissionsAndroid` provides access to Android M's new permissions model. Some permissions are granted by default when the application is installed so long as they appear in `AndroidManifest.xml`. However, "dangerous" permissions require a dialog prompt. You should use this module for those permissions. -On devices before SDK version 23, the permissions are automatically granted -if they appear in the manifest, so `check` and `request` -should always be true. +On devices before SDK version 23, the permissions are automatically granted if they appear in the manifest, so `check` and `request` should always be true. -If a user has previously turned off a permission that you prompt for, the OS -will advise your app to show a rationale for needing the permission. The -optional `rationale` argument will show a dialog prompt only if -necessary - otherwise the normal permission prompt will appear. +If a user has previously turned off a permission that you prompt for, the OS will advise your app to show a rationale for needing the permission. The optional `rationale` argument will show a dialog prompt only if necessary - otherwise the normal permission prompt will appear. ### Example -``` + +```javascript import { PermissionsAndroid } from 'react-native'; async function requestCameraPermission() { @@ -63,11 +56,11 @@ async function requestCameraPermission() { ### Methods - [`constructor`](docs/permissionsandroid.html#constructor) -- [`checkPermission`](docs/permissionsandroid.html#checkpermission) - [`check`](docs/permissionsandroid.html#check) -- [`requestPermission`](docs/permissionsandroid.html#requestpermission) - [`request`](docs/permissionsandroid.html#request) - [`requestMultiple`](docs/permissionsandroid.html#requestmultiple) +- [`requestPermission`](docs/permissionsandroid.html#requestpermission) +- [`checkPermission`](docs/permissionsandroid.html#checkpermission) @@ -88,97 +81,71 @@ constructor() --- -### `checkPermission()` +### `check()` ```javascript -checkPermission(permission) +check(permission) ``` -DEPRECATED - use check - -Returns a promise resolving to a boolean value as to whether the specified -permissions has been granted - -@deprecated - - +Returns a promise resolving to a boolean value as to whether the specified permissions has been granted --- -### `check()` +### `request()` ```javascript -check(permission) +request(permission, rationale?) ``` -Returns a promise resolving to a boolean value as to whether the specified -permissions has been granted +Prompts the user to enable a permission and returns a promise resolving to a string value indicating whether the user allowed or denied the request. + +If the optional rationale argument is included (which is an object with a `title` and `message`), this function checks with the OS whether it is necessary to show a dialog [explaining why the permission is needed](https://developer.android.com/training/permissions/requesting.html#explain) and then shows the system permission dialog --- -### `requestPermission()` +### `requestMultiple()` ```javascript -requestPermission(permission, rationale?) +requestMultiple(permissions) ``` -DEPRECATED - use request - -Prompts the user to enable a permission and returns a promise resolving to a -boolean value indicating whether the user allowed or denied the request - -If the optional rationale argument is included (which is an object with a -`title` and `message`), this function checks with the OS whether it is -necessary to show a dialog explaining why the permission is needed -(https://developer.android.com/training/permissions/requesting.html#explain) -and then shows the system permission dialog - -@deprecated - - +Prompts the user to enable multiple permissions in the same dialog and returns an object with the permissions as keys and strings as values indicating whether the user allowed or denied the request --- -### `request()` +### `checkPermission()` ```javascript -request(permission, rationale?) +checkPermission(permission) ``` -Prompts the user to enable a permission and returns a promise resolving to a -string value indicating whether the user allowed or denied the request - -If the optional rationale argument is included (which is an object with a -`title` and `message`), this function checks with the OS whether it is -necessary to show a dialog explaining why the permission is needed -(https://developer.android.com/training/permissions/requesting.html#explain) -and then shows the system permission dialog +**DEPRECATED** - use [check](docs/permissionsandroid.html#check) +Returns a promise resolving to a boolean value as to whether the specified permissions has been granted --- -### `requestMultiple()` +### `requestPermission()` ```javascript -requestMultiple(permissions) +requestPermission(permission, rationale?) ``` -Prompts the user to enable multiple permissions in the same dialog and -returns an object with the permissions as keys and strings as values -indicating whether the user allowed or denied the request - +**DEPRECATED** - use [request](docs/permissionsandroid.html#request) +Prompts the user to enable a permission and returns a promise resolving to a boolean value indicating whether the user allowed or denied the request. +If the optional rationale argument is included (which is an object with a `title` and `message`), this function checks with the OS whether it is necessary to show a dialog [explaining why the permission is needed](https://developer.android.com/training/permissions/requesting.html#explain) and then shows the system permission dialog diff --git a/docs/picker-item.md b/docs/picker-item.md new file mode 100644 index 00000000000000..6e1481d153c9ae --- /dev/null +++ b/docs/picker-item.md @@ -0,0 +1,57 @@ +--- +id: picker-item +title: Picker.Item +layout: docs +category: components +permalink: docs/picker-item.html +next: pickerios +previous: picker +--- + +Individual selectable item in a [Picker](docs/picker.html). + +### Props + +- [`label`](docs/picker-item.html#label) +- [`color`](docs/picker-item.html#color) +- [`testID`](docs/picker-item.html#testid) +- [`value`](docs/picker-item.html#value) + +--- + +# Reference + +## Props + +### `label` + +Text to display for this item. + +| Type | Required | +| - | - | +| string | Yes | + +### `color` + +The value to be passed to picker's `onValueChange` callback when this item is selected. Can be a string or an integer. + +| Type | Required | +| - | - | +| [color](docs/colors.html) | No | + +### `testID` + +Used to locate the item in end-to-end tests. + +| Type | Required | +| - | - | +| string | No | + +### `value` + +Color of this item's text. + +| Type | Required | Platform | +| - | - | - | +| any | No | Android | + diff --git a/docs/picker-style-props.md b/docs/picker-style-props.md new file mode 100644 index 00000000000000..b9df932a5ba5d0 --- /dev/null +++ b/docs/picker-style-props.md @@ -0,0 +1,32 @@ +--- +id: picker-style-props +title: Picker Style Props +layout: docs +category: APIs +permalink: docs/picker-style-props.html +next: shadow-props +previous: layout-props +--- + +[Picker](docs/picker.html) style props. + +### Props + +- [View Style Props...](docs/view-style-props.html) +- [`color`](docs/picker-style-props.html#color) + + + +--- + +# Reference + +## Props + +### `color` + + + +| Type | Required | +| - | - | +| [color](docs/color.html) | No | diff --git a/docs/picker.md b/docs/picker.md index 94918d361edb3e..3ce067f96643c3 100644 --- a/docs/picker.md +++ b/docs/picker.md @@ -4,9 +4,10 @@ title: Picker layout: docs category: components permalink: docs/picker.html -next: pickerios +next: picker-item previous: navigatorios --- + Renders the native picker component on iOS and Android. Example: Display > Font size, on iOS it will always return the default pixel ratio. -@platform android - +Currently this is only implemented on Android and reflects the user preference set in Settings > Display > Font size, on iOS it will always return the default pixel ratio. +| Platform | +| - | +| Android | --- @@ -123,10 +122,9 @@ Settings > Display > Font size, on iOS it will always return the default pixel r ### `getPixelSizeForLayoutSize()` ```javascript -static getPixelSizeForLayoutSize(layoutSize) +PixelRatio.getPixelSizeForLayoutSize(layoutSize) ``` - Converts a layout size (dp) to pixel size (px). Guaranteed to return an integer number. @@ -139,27 +137,9 @@ Guaranteed to return an integer number. ### `roundToNearestPixel()` ```javascript -static roundToNearestPixel(layoutSize) -``` - - -Rounds a layout size (dp) to the nearest layout size that corresponds to -an integer number of pixels. For example, on a device with a PixelRatio -of 3, `PixelRatio.roundToNearestPixel(8.4) = 8.33`, which corresponds to -exactly (8.33 * 3) = 25 pixels. - - - - ---- - -### `startDetecting()` - -```javascript -static startDetecting() +PixelRatio.roundToNearestPixel(layoutSize) ``` -// No-op for iOS, but used on the web. Should not be documented. - +Rounds a layout size (dp) to the nearest layout size that corresponds to an integer number of pixels. For example, on a device with a PixelRatio of 3, `PixelRatio.roundToNearestPixel(8.4) = 8.33`, which corresponds to exactly (8.33 * 3) = 25 pixels. diff --git a/docs/progressbarandroid.md b/docs/progressbarandroid.md index ba0232410c0df3..b316ea1224130a 100644 --- a/docs/progressbarandroid.md +++ b/docs/progressbarandroid.md @@ -31,7 +31,7 @@ render: function() { ### Props -* [ViewPropTypes props...](docs/viewproptypes.html#props) +- [View props...](docs/view-props.html) - [`animating`](docs/progressbarandroid.html#animating) - [`color`](docs/progressbarandroid.html#color) - [`indeterminate`](docs/progressbarandroid.html#indeterminate) @@ -107,13 +107,13 @@ The progress value (between 0 and 1). Style of the ProgressBar. One of: -- Horizontal -- Normal (default) -- Small -- Large -- Inverse -- SmallInverse -- LargeInverse +- `Horizontal` +- `Normal` (default) +- `Small` +- `Large` +- `Inverse` +- `SmallInverse` +- `LargeInverse` | Type | Required | | - | - | diff --git a/docs/progressviewios.md b/docs/progressviewios.md index bc8cd300b2f25f..b9c9bdedb27ece 100644 --- a/docs/progressviewios.md +++ b/docs/progressviewios.md @@ -11,7 +11,7 @@ Use `ProgressViewIOS` to render a UIProgressView on iOS. ### Props -* [ViewPropTypes props...](docs/viewproptypes.html#props) +- [View props...](docs/view-props.html) - [`progress`](docs/progressviewios.html#progress) - [`progressImage`](docs/progressviewios.html#progressimage) - [`progressTintColor`](docs/progressviewios.html#progresstintcolor) diff --git a/docs/pushnotificationios.md b/docs/pushnotificationios.md index b452ffdcdb4e23..1093e3da9d5e69 100644 --- a/docs/pushnotificationios.md +++ b/docs/pushnotificationios.md @@ -70,7 +70,7 @@ And then in your AppDelegate implementation add the following: ### Methods -- [`=`](docs/pushnotificationios.html#) +- [`presentLocalNotification`](docs/pushnotificationios.html#presentlocalnotification) - [`scheduleLocalNotification`](docs/pushnotificationios.html#schedulelocalnotification) - [`cancelAllLocalNotifications`](docs/pushnotificationios.html#cancelalllocalnotifications) - [`removeAllDeliveredNotifications`](docs/pushnotificationios.html#removealldeliverednotifications) @@ -96,8 +96,9 @@ And then in your AppDelegate implementation add the following: - [`getBadgeCount`](docs/pushnotificationios.html#getbadgecount) - [`getData`](docs/pushnotificationios.html#getdata) +## Events - +- [PushNotificationEventName](docs/pushnotificationios.html#pushnotificationeventname) --- @@ -105,12 +106,23 @@ And then in your AppDelegate implementation add the following: ## Methods -### `=()` +### `presentLocalNotification()` ```javascript -=(NewData, NoData, ResultFailed, }, static, (, :) +presentLocalNotification(details) ``` +Schedules the localNotification for immediate presentation. + +`details` is an object containing: + +- `alertBody` : The message displayed in the notification alert. +- `alertAction` : The "action" displayed beneath an actionable notification. Defaults to "view"; +- `soundName` : The sound played when the notification is fired (optional). +- `isSilent` : If true, the notification will appear without sound (optional). +- `category` : The category of this notification, required for actionable notifications (optional). +- `userInfo` : An optional object containing additional notification data. +- `applicationIconBadgeNumber` (optional) : The number to display as the app's icon badge. The default value of this property is 0, which means that no badge is displayed. --- @@ -177,18 +189,22 @@ static getDeliveredNotifications(callback) ``` -Provides you with a list of the app’s notifications that are still displayed in Notification Center +Provides you with a list of the app’s notifications that are still displayed in Notification Center. -@param callback Function which receive an array of delivered notifications +A delivered notification is an object containing: - A delivered notification is an object containing: +- `identifier`: The identifier of this notification. +- `title`: The title of this notification. +- `body`: The body of this notification. +- `category`: The category of this notification, if has one. +- `userInfo`: An optional object containing additional notification data. +- `thread-id`: The thread identifier of this notification, if has one. -- `identifier` : The identifier of this notification. -- `title` : The title of this notification. -- `body` : The body of this notification. -- `category` : The category of this notification, if has one. -- `userInfo` : An optional object containing additional notification data. -- `thread-id` : The thread identifier of this notification, if has one. +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| callback | function | Yes | Function which receives an array of delivered notifications. | @@ -201,11 +217,13 @@ Provides you with a list of the app’s notifications that are still displayed i static removeDeliveredNotifications(identifiers) ``` +Removes the specified notifications from Notification Center. -Removes the specified notifications from Notification Center - -@param identifiers Array of notification identifiers +**Parameters:** +| Name | Type | Required | Description | +| - | - | - | - | +| identifiers | array | Yes | Array of notification identifiers | @@ -403,9 +421,7 @@ constructor(nativeNotif) ``` -You will never need to instantiate `PushNotificationIOS` yourself. -Listening to the `notification` event and invoking -`getInitialNotification` is sufficient +You will never need to instantiate `PushNotificationIOS` yourself. Listening to the `notification` event and invoking `getInitialNotification` is sufficient. @@ -419,19 +435,11 @@ finish(fetchResult) ``` -This method is available for remote notifications that have been received via: -`application:didReceiveRemoteNotification:fetchCompletionHandler:` -https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/#//apple_ref/occ/intfm/UIApplicationDelegate/application:didReceiveRemoteNotification:fetchCompletionHandler: - -Call this to execute when the remote notification handling is complete. When -calling this block, pass in the fetch result value that best describes -the results of your operation. You *must* call this handler and should do so -as soon as possible. For a list of possible values, see `PushNotificationIOS.FetchResult`. - -If you do not call this method your background remote notifications could -be throttled, to read more about it see the above documentation link. +This method is available for remote notifications that have been received via [`application:didReceiveRemoteNotification:fetchCompletionHandler:`](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623013-application). +Call this to execute when the remote notification handling is complete. When calling this block, pass in the fetch result value that best describes the results of your operation. You *must* call this handler and should do so as soon as possible. For a list of possible values, see `PushNotificationIOS.FetchResult`. +If you do not call this method your background remote notifications could be throttled, to read more about it see the above documentation link. --- @@ -531,4 +539,13 @@ Gets the data object on the notif +## Events + +### `PushNotificationEventName` + +An event emitted by PushNotificationIOS. +- `notification` - Fired when a remote notification is received. The handler will be invoked with an instance of `PushNotificationIOS`. +- `localNotification` - Fired when a local notification is received. The handler will be invoked with an instance of `PushNotificationIOS`. +- `register` - Fired when the user registers for remote notifications. The handler will be invoked with a hex string representing the deviceToken. +- `registrationError` - Fired when the user fails to register for remote notifications. Typically occurs when APNS is having issues, or the device is a emulator. The handler will be invoked with `{message: string, code: number, details: any}`. \ No newline at end of file diff --git a/docs/refreshcontrol.md b/docs/refreshcontrol.md index d6ec9ce66827ec..6302f46297bb9e 100644 --- a/docs/refreshcontrol.md +++ b/docs/refreshcontrol.md @@ -53,7 +53,7 @@ in the `onRefresh` function otherwise the refresh indicator will stop immediatel ### Props -* [ViewPropTypes props...](docs/viewproptypes.html#props) +- [View props...](docs/view-props.html) - [`refreshing`](docs/refreshcontrol.html#refreshing) - [`onRefresh`](docs/refreshcontrol.html#onrefresh) - [`colors`](docs/refreshcontrol.html#colors) diff --git a/docs/runningondeviceandroid.md b/docs/runningondeviceandroid.md new file mode 100644 index 00000000000000..7af98dc23aaa57 --- /dev/null +++ b/docs/runningondeviceandroid.md @@ -0,0 +1,8 @@ +--- +id: running-on-device-android +title: Running On Device +layout: redirect +permalink: docs/running-on-device-android.html +destinationUrl: running-on-device.html +--- +Redirecting... \ No newline at end of file diff --git a/docs/runningondeviceios.md b/docs/runningondeviceios.md new file mode 100644 index 00000000000000..3b367bc049a82b --- /dev/null +++ b/docs/runningondeviceios.md @@ -0,0 +1,8 @@ +--- +id: running-on-device-ios +title: Running On Device +layout: redirect +permalink: docs/running-on-device-ios.html +destinationUrl: running-on-device.html +--- +Redirecting... \ No newline at end of file diff --git a/docs/scrollview.md b/docs/scrollview.md index 276582ca01f113..c73e45955333b0 100644 --- a/docs/scrollview.md +++ b/docs/scrollview.md @@ -43,7 +43,7 @@ supports out of the box. ### Props -* [ViewPropTypes props...](docs/viewproptypes.html#props) +- [View props...](docs/view-props.html) - [`alwaysBounceVertical`](docs/scrollview.html#alwaysbouncevertical) - [`contentContainerStyle`](docs/scrollview.html#contentcontainerstyle) - [`keyboardDismissMode`](docs/scrollview.html#keyboarddismissmode) @@ -62,7 +62,6 @@ supports out of the box. - [`endFillColor`](docs/scrollview.html#endfillcolor) - [`overScrollMode`](docs/scrollview.html#overscrollmode) - [`scrollPerfTag`](docs/scrollview.html#scrollperftag) -- [`DEPRECATED_sendUpdatedChildFrames`](docs/scrollview.html#deprecated-sendupdatedchildframes) - [`alwaysBounceHorizontal`](docs/scrollview.html#alwaysbouncehorizontal) - [`horizontal`](docs/scrollview.html#horizontal) - [`automaticallyAdjustContentInsets`](docs/scrollview.html#automaticallyadjustcontentinsets) @@ -85,6 +84,7 @@ supports out of the box. - [`snapToAlignment`](docs/scrollview.html#snaptoalignment) - [`snapToInterval`](docs/scrollview.html#snaptointerval) - [`zoomScale`](docs/scrollview.html#zoomscale) +- [`DEPRECATED_sendUpdatedChildFrames`](docs/scrollview.html#deprecated-sendupdatedchildframes) @@ -141,7 +141,7 @@ const styles = StyleSheet.create({ | Type | Required | | - | - | -| StyleSheetPropType(ViewStylePropTypes) | No | +| [style](docs/view-style-props.html) | No | @@ -417,25 +417,6 @@ FpsListener for it to be useful. - ---- - -### `DEPRECATED_sendUpdatedChildFrames` - -When true, ScrollView will emit updateChildFrames data in scroll events, -otherwise will not compute or emit child frame data. This only exists -to support legacy issues, `onLayout` should be used instead to retrieve -frame data. -The default value is false. - - -| Type | Required | Platform | -| - | - | - | -| bool | No | iOS | - - - - --- ### `alwaysBounceHorizontal` @@ -796,6 +777,20 @@ The current scale of the scroll view content. The default value is 1.0. | number | No | iOS | +--- + +### `DEPRECATED_sendUpdatedChildFrames` + +**Deprecated.** When true, ScrollView will emit updateChildFrames data in scroll events, +otherwise will not compute or emit child frame data. This only exists +to support legacy issues, `onLayout` should be used instead to retrieve +frame data. +The default value is false. + + +| Type | Required | Platform | +| - | - | - | +| bool | No | iOS | diff --git a/docs/sectionlist.md b/docs/sectionlist.md index b6dced3898c348..d7bca81aa9ce96 100644 --- a/docs/sectionlist.md +++ b/docs/sectionlist.md @@ -7,6 +7,7 @@ permalink: docs/sectionlist.html next: segmentedcontrolios previous: scrollview --- + A performant interface for rendering sectioned lists, supporting the most handy features: - Fully cross-platform. @@ -25,46 +26,60 @@ If you don't need section support and want a simpler interface, use Simple Examples: - } - renderSectionHeader={({section}) =>
} - sections={[ // homogeneous rendering between sections - {data: [...], title: ...}, - {data: [...], title: ...}, - {data: [...], title: ...}, - ]} - /> - - - -This is a convenience wrapper around [``](docs/virtualizedlist.html), +```javascript + } + renderSectionHeader={({section}) =>
} + sections={[ // homogeneous rendering between sections + {data: [...], title: ...}, + {data: [...], title: ...}, + {data: [...], title: ...}, + ]} +/> + + +``` + +This is a convenience wrapper around [`VirtualizedList`](docs/virtualizedlist.html), and thus inherits its props (as well as those of `ScrollView`) that aren't explicitly listed here, along with the following caveats: -- Internal state is not preserved when content scrolls out of the render window. Make sure all - your data is captured in the item data or external stores like Flux, Redux, or Relay. -- This is a `PureComponent` which means that it will not re-render if `props` remain shallow- - equal. Make sure that everything your `renderItem` function depends on is passed as a prop - (e.g. `extraData`) that is not `===` after updates, otherwise your UI may not update on - changes. This includes the `data` prop and parent component state. -- In order to constrain memory and enable smooth scrolling, content is rendered asynchronously - offscreen. This means it's possible to scroll faster than the fill rate and momentarily see - blank content. This is a tradeoff that can be adjusted to suit the needs of each application, - and we are working on improving it behind the scenes. -- By default, the list looks for a `key` prop on each item and uses that for the React key. - Alternatively, you can provide a custom `keyExtractor` prop. +- Internal state is not preserved when content scrolls out of the render window. Make sure all your data is captured in the item data or external stores like Flux, Redux, or Relay. +- This is a `PureComponent` which means that it will not re-render if `props` remain shallow- equal. Make sure that everything your `renderItem` function depends on is passed as a prop (e.g. `extraData`) that is not `===` after updates, otherwise your UI may not update on changes. This includes the `data` prop and parent component state. +- In order to constrain memory and enable smooth scrolling, content is rendered asynchronously offscreen. This means it's possible to scroll faster than the fill rate and momentarily see blank content. This is a tradeoff that can be adjusted to suit the needs of each application, and we are working on improving it behind the scenes. +- By default, the list looks for a `key` prop on each item and uses that for the React key. Alternatively, you can provide a custom `keyExtractor` prop. ### Props +- [`ScrollView` props...](docs/scrollview.html#props) +- [`VirtualizedList` props...](docs/virtualizedlist.html#props) +- [`sections`](docs/virtualizedlist.html#sections) +- [`renderItem`](docs/virtualizedlist.html#renderitem) +- [`ItemSeparatorComponent`](docs/virtualizedlist.html#itemseparatorcomponent) +- [`ItemSeparatorComponent`](docs/virtualizedlist.html#itemseparatorcomponent) +- [`ListEmptyComponent`](docs/virtualizedlist.html#listemptycomponent) +- [`ListFooterComponent`](docs/virtualizedlist.html#listgootercomponent) +SectionSeparatorComponent +- [`extradata`](docs/virtualizedlist.html#extradata) +- [`initialNumToRender`](docs/virtualizedlist.html#initialnumtorender) +- [`inverted`](docs/virtualizedlist.html#inverted) +- [`keyExtractor`](docs/virtualizedlist.html#keyextractor) +- [`onEndReached`](docs/virtualizedlist.html#onendreached) +- [`onEndReachedThreshold`](docs/virtualizedlist.html#onendreachedthreshold) +- [`onRefresh`](docs/virtualizedlist.html#onrefresh) +- [`onViewableItemsChanged`](docs/virtualizedlist.html#onviewableitemschanged) +- [`refreshing`](docs/virtualizedlist.html#refreshing) +- [`removeClippedSubviews`](docs/virtualizedlist.html#removeclippedsubviews) +- [`renderSectionHeader`](docs/virtualizedlist.html#removeclippedsubviews) +- [`renderSectionFooter`](docs/virtualizedlist.html#rendersectionfooter) - [`stickySectionHeadersEnabled`](docs/sectionlist.html#stickysectionheadersenabled) - - +- [`legacyImplementation`](docs/virtualizedlist.html#legacyimplementation) ### Methods @@ -88,9 +103,302 @@ here, along with the following caveats: ## Props -### `stickySectionHeadersEnabled` +### `sections` + +The actual data to render, akin to the `data` prop in [`FlatList`](/docs/flatlist.html#data). + +**General shape:** + +``` +sections: [{ + data: array, + [renderItem]: ({item: SectionItem, ...}) => element, + [ItemSeparatorComponent]: React Class Component | function | element, +}] +``` + +| Type | Required | +| - | - | +| array of objects | Yes | + + + +--- + + +### `renderItem` + +```javascript +renderItem({ item: object, index: number, section: object, separators: { highlight: function, unhighlight: function, updateProps: function(select: string, newProps: object) } }): [element] +``` + +Default renderer for every item in every section. Can be over-ridden on a per-section basis. + +Provides additional metadata like `index` if you need it, as well as a more generic `separators.updateProps` function which let's you set whatever props you want to change the rendering of either the leading separator or trailing separator in case the more common `highlight` and `unhighlight` (which set the `highlighted: boolean` prop) are insufficient for your use case. + +| Type | Required | +| - | - | +| function | No | + + + +--- + + +### `ItemSeparatorComponent` + +Rendered in between each item, but not at the top or bottom. By default, `highlighted`, `section`, and `[leading/trailing][Item/Separator]` props are provided. `renderItem` provides `separators.highlight`/`unhighlight` which will update the `highlighted` prop, but you can also add custom props with `separators.updateProps`. + +| Type | Required | +| - | - | +| component | No | + + + +--- + + +### `ListHeaderComponent` + +Rendered at the top of all the items. Can be a React Component Class, a render function, or a rendered element. + +| Type | Required | +| - | - | +| component, function, element | No | + + + +--- + + +### `ListEmptyComponent` + +Rendered when the list is empty. Can be a React Component Class, a render function, or a rendered element. + +| Type | Required | +| - | - | +| component, function, element | No | + + + +--- + + +### `ListFooterComponent` + +Rendered at the very end of the list. Can be a React Component Class, a render function, or a rendered element. + +| Type | Required | +| - | - | +| component, function, element | No | + + + +--- + + +### `SectionSeparatorComponent` + +Rendered at the top and bottom of each section (note this is different from `ItemSeparatorComponent` which is only rendered between items). These are intended to separate sections from the headers above and below and typically have the same highlight response as `ItemSeparatorComponent`. Also receives `highlighted`, `[leading/trailing][Item/Separator]`, and any custom props from `separators.updateProps`. + +| Type | Required | +| - | - | +| any | No | + + + +--- + + +### `extraData` + +A marker property for telling the list to re-render (since it implements `PureComponent`). If any of your `renderItem`, Header, Footer, etc. functions depend on anything outside of the `data` prop, stick it here and treat it immutably. + +| Type | Required | +| - | - | +| any | No | + + + +--- + + +### `initialNumToRender` + +How many items to render in the initial batch. This should be enough to fill the screen but not much more. Note these items will never be unmounted as part of the windowed rendering in order to improve perceived performance of scroll-to-top actions. + +| Type | Required | +| - | - | +| number | No | + + + +--- + + +### `inverted` + +Reverses the direction of scroll. Uses scale transforms of `-1`. + +| Type | Required | +| - | - | +| boolean | No | + + + +--- + + +### `keyExtractor` + +```javascript +(item: object, index: number) => string +``` + +Used to extract a unique key for a given item at the specified index. Key is used for caching and as the react key to track item re-ordering. The default extractor checks item.key, then falls back to using the index, like react does. Note that this sets keys for each item, but each overall section still needs its own key. + +| Type | Required | +| - | - | +| function | No | + + + +--- + + +### `onEndReached` + +```javascript +(info: {distanceFromEnd: number}) => void +``` + +Called once when the scroll position gets within `onEndReachedThreshold` of the rendered content. + +| Type | Required | +| - | - | +| function | No | + + + +--- + + +### `onEndReachedThreshold` + + How far from the end (in units of visible length of the list) the bottom edge of the list must be from the end of the content to trigger the `onEndReached` callback. Thus a value of 0.5 will trigger `onEndReached` when the end of the content is within half the visible length of the list. + +| Type | Required | +| - | - | +| number | No | + + + +--- + + +### `onRefresh` + +```javascript +() => void +``` + +If provided, a standard RefreshControl will be added for "Pull to Refresh" functionality. Make sure to also set the `refreshing` prop correctly. + +| Type | Required | +| - | - | +| function | No | + + + +--- + + +### `onViewableItemsChanged` + +```javascript +(info: { + viewableItems: array, + changed: array, + }) => void +``` + +Called when the viewability of rows changes, as defined by the `viewabilityConfig` prop. +| Type | Required | +| - | - | +| function | No | + + + +--- + + +### `refreshing` + +Set this true while waiting for new data from a refresh. + +| Type | Required | +| - | - | +| boolean | No | + + + +--- + + +### `removeClippedSubviews` + +This may improve scroll performance for large lists. + +> Note: +> May have bugs (missing content) in some circumstances - use at your own risk. + +| Type | Required | +| - | - | +| boolean | No | + + + +--- + + +### `renderSectionHeader` + +``` +(info: {section}) => [element] +``` + +Rendered at the top of each section. These stick to the top of the `ScrollView` by default on iOS. See `stickySectionHeadersEnabled`. + +| Type | Required | +| - | - | +| element | No | + + + +--- + + +### `renderSectionFooter` + +``` +(info: {section}) => [element] +``` + +React element rendered at the bottom of each section. + +| Type | Required | +| - | - | +| element | No | + + + +--- + + +### `stickySectionHeadersEnabled` +Makes section headers stick to the top of the screen until the next one pushes it off. Only enabled by default on iOS because that is the platform standard there. | Type | Required | | - | - | diff --git a/docs/segmentedcontrolios.md b/docs/segmentedcontrolios.md index 749517a97a4d4b..65d764193094a3 100644 --- a/docs/segmentedcontrolios.md +++ b/docs/segmentedcontrolios.md @@ -28,7 +28,7 @@ selects a value and changes the index, as shown in the example below. ### Props -* [ViewPropTypes props...](docs/viewproptypes.html#props) +- [View props...](docs/view-props.html) - [`enabled`](docs/segmentedcontrolios.html#enabled) - [`momentary`](docs/segmentedcontrolios.html#momentary) - [`onChange`](docs/segmentedcontrolios.html#onchange) diff --git a/docs/settings.md b/docs/settings.md index 61b539f0bfb43e..9dc2b7e3aa4372 100644 --- a/docs/settings.md +++ b/docs/settings.md @@ -33,7 +33,7 @@ previous: pushnotificationios ### `get()` ```javascript -static get(key) +Settings.get(key) ``` @@ -43,7 +43,7 @@ static get(key) ### `set()` ```javascript -static set(settings) +Settings.set(settings) ``` @@ -53,7 +53,7 @@ static set(settings) ### `watchKeys()` ```javascript -static watchKeys(keys, callback) +Settings.watchKeys(keys, callback) ``` @@ -63,7 +63,7 @@ static watchKeys(keys, callback) ### `clearWatch()` ```javascript -static clearWatch(watchId) +Settings.clearWatch(watchId) ``` diff --git a/docs/shadow-props.md b/docs/shadow-props.md index 3514190c4d5f8d..9616d4108aedcd 100644 --- a/docs/shadow-props.md +++ b/docs/shadow-props.md @@ -4,7 +4,7 @@ title: Shadow Props layout: docs category: APIs permalink: docs/shadow-props.html -next: viewproptypes +next: view-props previous: layout-props --- ### Props diff --git a/docs/share.md b/docs/share.md index 8ae16335289b0f..14c359bb6e16fd 100644 --- a/docs/share.md +++ b/docs/share.md @@ -28,15 +28,13 @@ previous: settings ### `share()` ```javascript -static share(content, options) +Share.share(content, options) ``` Open a dialog to share text content. -In iOS, Returns a Promise which will be invoked an object containing `action`, `activityType`. -If the user dismissed the dialog, the Promise will still be resolved with action being `Share.dismissedAction` -and all the other keys being undefined. +In iOS, Returns a Promise which will be invoked an object containing `action`, `activityType`. If the user dismissed the dialog, the Promise will still be resolved with action being `Share.dismissedAction` and all the other keys being undefined. In Android, Returns a Promise which always be resolved with action being `Share.sharedAction`. @@ -64,15 +62,12 @@ At least one of URL and message is required. - `dialogTitle` - - - --- ### `sharedAction()` ```javascript -static sharedAction() +Share.sharedAction() ``` @@ -86,12 +81,15 @@ The content was successfully shared. ### `dismissedAction()` ```javascript -static dismissedAction() +Share.dismissedAction() ``` The dialog has been dismissed. -@platform ios + +| Platform | +| - | +| iOS | diff --git a/docs/slider.md b/docs/slider.md index 32f8eecdcf2d17..c3768149ccfa1a 100644 --- a/docs/slider.md +++ b/docs/slider.md @@ -17,7 +17,7 @@ the state of the root component (`App`). The same component subscribes to the `onValueChange` of `Slider` and changes the value using `setState`. -``` +```javascript import React from 'react'; import { StyleSheet, Text, View, Slider } from 'react-native'; @@ -67,7 +67,7 @@ const styles = StyleSheet.create({ ### Props -* [ViewPropTypes props...](docs/viewproptypes.html#props) +- [View props...](docs/view-props.html) - [`style`](docs/slider.html#style) - [`disabled`](docs/slider.html#disabled) - [`maximumValue`](docs/slider.html#maximumvalue) @@ -103,7 +103,7 @@ Used to style and layout the `Slider`. See `StyleSheet.js` and | Type | Required | | - | - | -| ViewPropTypes.style | No | +| [ViewPropTypes.style](docs/viewproptypes.html#style) | No | @@ -274,7 +274,7 @@ leftmost pixel of the image will be stretched to fill the track. | Type | Required | Platform | | - | - | - | -| Image.propTypes.source | No | iOS | +| [Image.propTypes.source](docs/image.html#source) | No | iOS | @@ -289,7 +289,7 @@ rightmost pixel of the image will be stretched to fill the track. | Type | Required | Platform | | - | - | - | -| Image.propTypes.source | No | iOS | +| [Image.propTypes.source](docs/image.html#source) | No | iOS | @@ -303,7 +303,7 @@ Sets an image for the thumb. Only static images are supported. | Type | Required | Platform | | - | - | - | -| Image.propTypes.source | No | iOS | +| [Image.propTypes.source](docs/image.html#source) | No | iOS | @@ -318,7 +318,7 @@ The center pixel of the image will be stretched to fill the track. | Type | Required | Platform | | - | - | - | -| Image.propTypes.source | No | iOS | +| [Image.propTypes.source](docs/image.html#source) | No | iOS | diff --git a/docs/snapshotviewios.md b/docs/snapshotviewios.md index d11f73bb0fb8b4..7048f257a266db 100644 --- a/docs/snapshotviewios.md +++ b/docs/snapshotviewios.md @@ -7,9 +7,10 @@ permalink: docs/snapshotviewios.html next: statusbar previous: slider --- + ### Props -* [ViewPropTypes props...](docs/viewproptypes.html#props) +- [View props...](docs/view-props.html) - [`onSnapshotReady`](docs/snapshotviewios.html#onsnapshotready) - [`testIdentifier`](docs/snapshotviewios.html#testidentifier) diff --git a/docs/statusbar.md b/docs/statusbar.md index ee78f4c85afaa3..e670011c7201df 100644 --- a/docs/statusbar.md +++ b/docs/statusbar.md @@ -35,15 +35,11 @@ mounted. One use case is to specify status bar styles per route using `Navigator ### Imperative API -For cases where using a component is not ideal, there is also an imperative -API exposed as static functions on the component. It is however not recommended -to use the static API and the component for the same prop because any value -set by the static API will get overriden by the one set by the component in -the next render. +For cases where using a component is not ideal, there is also an imperative API exposed as static functions on the component. It is however not recommended to use the static API and the component for the same prop because any value set by the static API will get overriden by the one set by the component in the next render. ### Constants -`currentHeight` (Android only) The height of the status bar. +`currentHeight` (Android only) The current height of the status bar on the device. ### Props @@ -188,17 +184,17 @@ prop. Defaults to 'fade'. ### `setHidden()` ```javascript -static setHidden(hidden: boolean, [animation]: StatusBarAnimation) +StatusBar.setHidden(hidden: boolean, [animation]: StatusBarAnimation) ``` -Show or hide the status bar +Show or hide the status bar. **Parameters:** | Name | Type | Required | Description | | - | - | - | - | -| hidden | boolean | No | Hide the status bar. | -| animation | [StatusBarAnimation](docs/statusbar.html#statusbaranimation) | Yes | Optional animation when changing the status bar hidden property. | +| hidden | boolean | Yes | Hide the status bar. | +| animation | [StatusBarAnimation](docs/statusbar.html#statusbaranimation) | No | Optional animation when changing the status bar hidden property. | @@ -208,17 +204,17 @@ Show or hide the status bar ### `setBarStyle()` ```javascript -static setBarStyle(style: StatusBarStyle, [animated]: boolean) +StatusBar.setBarStyle(style: StatusBarStyle, [animated]: boolean) ``` -Set the status bar style +Set the status bar style. **Parameters:** | Name | Type | Required | Description | | - | - | - | - | -| style | [StatusBarStyle](docs/statusbar.html#statusbarstyle) | No | Status bar style to set | -| animated | boolean | Yes | Animate the style change. | +| style | [StatusBarStyle](docs/statusbar.html#statusbarstyle) | Yes | Status bar style to set | +| animated | boolean | No | Animate the style change. | @@ -228,16 +224,16 @@ Set the status bar style ### `setNetworkActivityIndicatorVisible()` ```javascript -static setNetworkActivityIndicatorVisible(visible: boolean) +StatusBar.setNetworkActivityIndicatorVisible(visible: boolean) ``` -Control the visibility of the network activity indicator +Control the visibility of the network activity indicator. **Parameters:** | Name | Type | Required | Description | | - | - | - | - | -| visible | boolean | No | Show the indicator. | +| visible | boolean | Yes | Show the indicator. | @@ -247,17 +243,17 @@ Control the visibility of the network activity indicator ### `setBackgroundColor()` ```javascript -static setBackgroundColor(color: string, [animated]: boolean) +StatusBar.setBackgroundColor(color: string, [animated]: boolean) ``` -Set the background color for the status bar +Set the background color for the status bar. **Parameters:** | Name | Type | Required | Description | | - | - | - | - | -| color | string | No | Background color. | -| animated | boolean | Yes | Animate the style change. | +| color | string | Yes | Background color. | +| animated | boolean | No | Animate the style change. | @@ -267,16 +263,16 @@ Set the background color for the status bar ### `setTranslucent()` ```javascript -static setTranslucent(translucent: boolean) +StatusBar.setTranslucent(translucent: boolean) ``` -Control the translucency of the status bar +Control the translucency of the status bar. **Parameters:** | Name | Type | Required | Description | | - | - | - | - | -| translucent | boolean | No | Set as translucent. | +| translucent | boolean | Yes | Set as translucent. | @@ -307,7 +303,7 @@ Status bar style ### StatusBarAnimation -Status bar animation +Status bar animation. | Type | | - | diff --git a/docs/statusbarios.md b/docs/statusbarios.md index 793f5f4f8db9fe..c0c6d2204bf48d 100644 --- a/docs/statusbarios.md +++ b/docs/statusbarios.md @@ -8,12 +8,4 @@ next: stylesheet previous: share --- -Use `StatusBar` for mutating the status bar. - - - - ---- - -# Reference - +Use [`StatusBar`](docs/statusbar.html) for mutating the status bar. diff --git a/docs/stylesheet.md b/docs/stylesheet.md index 3d3ef03c45ad43..adf546b92ce1d8 100644 --- a/docs/stylesheet.md +++ b/docs/stylesheet.md @@ -54,8 +54,9 @@ subsequent uses are going to refer an id (not implemented yet). ### Methods -- [`setStyleAttributePreprocessor`](docs/stylesheet.html#setstyleattributepreprocessor) - [`create`](docs/stylesheet.html#create) +- [`flatten`](docs/stylesheet.html#flatten) +- [`setStyleAttributePreprocessor`](docs/stylesheet.html#setstyleattributepreprocessor) ### Properties @@ -63,7 +64,6 @@ subsequent uses are going to refer an id (not implemented yet). - [`hairlineWidth`](docs/stylesheet.html#hairlinewidth) - [`absoluteFill`](docs/stylesheet.html#absolutefill) - [`absoluteFillObject`](docs/stylesheet.html#absolutefillobject) -- [`flatten`](docs/stylesheet.html#flatten) @@ -74,51 +74,114 @@ subsequent uses are going to refer an id (not implemented yet). ## Methods -### `setStyleAttributePreprocessor()` +### `create()` ```javascript -static setStyleAttributePreprocessor(property, process) +StyleSheet.create(obj) ``` -WARNING: EXPERIMENTAL. Breaking changes will probably happen a lot and will -not be reliably announced. The whole thing might be deleted, who knows? Use -at your own risk. +Creates a StyleSheet style reference from the given object. -Sets a function to use to pre-process a style property value. This is used -internally to process color and transform values. You should not use this -unless you really know what you are doing and have exhausted other options. +--- +### `flatten()` +```javascript +StyleSheet.flatten(styles) +``` +Flattens an array of style objects, into one aggregated style object. Alternatively, this method can be used to lookup IDs, returned by StyleSheet.register. ---- +> **Note**: +> Exercise caution as abusing this can tax you in terms of optimizations. +> +> IDs enable optimizations through the bridge and memory in general. Refering to style objects directly will deprive you of these optimizations. -### `create()` +Example: ```javascript -static create(obj) +const styles = StyleSheet.create({ + listItem: { + flex: 1, + fontSize: 16, + color: 'white' + }, + selectedListItem: { + color: 'green' + } +}); + +StyleSheet.flatten([styles.listItem, styles.selectedListItem]) +// returns { flex: 1, fontSize: 16, color: 'green' } ``` +Alternative use: -Creates a StyleSheet style reference from the given object. +```javascript +StyleSheet.flatten(styles.listItem); +// return { flex: 1, fontSize: 16, color: 'white' } +// Simply styles.listItem would return its ID (number) +``` + +This method internally uses `StyleSheetRegistry.getStyleByID(style)` to resolve style objects represented by IDs. Thus, an array of style objects (instances of StyleSheet.create), are individually resolved to, their respective objects, merged as one and then returned. This also explains the alternative use. +--- + +### `setStyleAttributePreprocessor()` + +```javascript +StyleSheet.setStyleAttributePreprocessor(property, process) +``` + +> WARNING: EXPERIMENTAL. +> Breaking changes will probably happen a lot and will not be reliably announced. The whole thing might be deleted, who knows? Use at your own risk. + +Sets a function to use to pre-process a style property value. This is used internally to process color and transform values. You should not use this unless you really know what you are doing and have exhausted other options. ## Properties +### `hairlineWidth` +This is defined as the width of a thin line on the platform. It can be used as the thickness of a border or division between two elements. ---- +Example: + +```json +{ + borderBottomColor: '#bbb', + borderBottomWidth: StyleSheet.hairlineWidth +} +``` +This constant will always be a round number of pixels (so a line defined by it look crisp) and will try to match the standard width of a thin line on the underlying platform. However, you should not rely on it being a constant size, because on different platforms and screen densities its value may be calculated differently. +A line with hairline width may not be visible if your simulator is downscaled. --- +### `absoluteFill` + +A very common pattern is to create overlays with position absolute and zero positioning, so `absoluteFill` can be used for convenience and to reduce duplication of these repeated styles. + --- +### `absoluteFillObject` + +Sometimes you may want `absoluteFill` but with a couple tweaks - `absoluteFillObject` can be used to create a customized entry in a `StyleSheet`, e.g.: + +```javascript +const styles = StyleSheet.create({ + wrapper: { + ...StyleSheet.absoluteFillObject, + top: 10, + backgroundColor: 'transparent', + }, +}); +``` diff --git a/docs/switch.md b/docs/switch.md index 6ce1a6f0204fe3..bac4b702f5aab5 100644 --- a/docs/switch.md +++ b/docs/switch.md @@ -9,17 +9,14 @@ previous: statusbar --- Renders a boolean input. -This is a controlled component that requires an `onValueChange` callback that -updates the `value` prop in order for the component to reflect user actions. -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. +This is a controlled component that requires an `onValueChange` callback that updates the `value` prop in order for the component to reflect user actions. 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. @keyword checkbox @keyword toggle ### Props -* [ViewPropTypes props...](docs/viewproptypes.html#props) +- [View props...](docs/view-props.html) - [`disabled`](docs/switch.html#disabled) - [`onTintColor`](docs/switch.html#ontintcolor) - [`onValueChange`](docs/switch.html#onvaluechange) @@ -30,9 +27,6 @@ the supplied `value` prop instead of the expected result of any user actions. - - - --- # Reference diff --git a/docs/systrace.md b/docs/systrace.md index 5e0cd57a6c1f56..30867f5943738a 100644 --- a/docs/systrace.md +++ b/docs/systrace.md @@ -164,12 +164,18 @@ static measureMethods(object, objectName, methodNames) Measures multiple methods of a class. For example, you can do: + +```javascript Systrace.measureMethods(JSON, 'JSON', ['parse', 'stringify']); +``` -@param object -@param objectName -@param methodNames Map from method names to method display names. +**Parameters:** +| Name | Type | Required | Description | +| - | - | - | - | +| object | any | Yes | | +| objectName | string | Yes | | +| methodNames | array | Yes| Map from method names to method display names. | @@ -183,12 +189,19 @@ static measure(objName, fnName, func) Returns an profiled version of the input function. For example, you can: + +```javascript JSON.parse = Systrace.measure('JSON', 'parse', JSON.parse); +``` + +**Parameters:** + +| Name | Type | Required | Description | +| - | - | - | - | +| objName | string | Yes | | +| fnName | string | Yes | | +| func | function | Yes | | -@param objName -@param fnName -@param {function} func -@return {function} replacement function diff --git a/docs/tabbarios-item.md b/docs/tabbarios-item.md index 687ebe1db154a4..981476b16485d1 100644 --- a/docs/tabbarios-item.md +++ b/docs/tabbarios-item.md @@ -7,9 +7,10 @@ permalink: docs/tabbarios-item.html next: text previous: tabbarios --- + ### Props -* [ViewPropTypes props...](docs/viewproptypes.html#props) +- [ViewPropTypes props...](docs/viewproptypes.html#props) - [`selected`](docs/tabbarios-item.html#selected) - [`badge`](docs/tabbarios-item.html#badge) - [`icon`](docs/tabbarios-item.html#icon) @@ -53,7 +54,7 @@ Little red bubble that sits at the top right of the icon. | Type | Required | | - | - | -| string, ,number | No | +| string, number | No | @@ -121,7 +122,7 @@ icon is defined. If left empty, the icon will be tinted in blue. | Type | Required | | - | - | -| Image.propTypes.source | No | +| [Image.propTypes.source](docs/image.html#source) | No | @@ -134,7 +135,7 @@ React style object. | Type | Required | | - | - | -| ViewPropTypes.style | No | +| [ViewPropTypes.style](docs/viewproptypes.html#style) | No | @@ -152,8 +153,6 @@ system ones. | enum('bookmarks', 'contacts', 'downloads', 'favorites', 'featured', 'history', 'more', 'most-recent', 'most-viewed', 'recents', 'search', 'top-rated') | No | - - --- ### `title` diff --git a/docs/tabbarios.md b/docs/tabbarios.md index e8385e0a54dbaf..8c1d83a5321dc1 100644 --- a/docs/tabbarios.md +++ b/docs/tabbarios.md @@ -9,7 +9,7 @@ previous: switch --- ### Props -* [ViewPropTypes props...](docs/viewproptypes.html#props) +- [View props...](docs/view-props.html) - [`barStyle`](docs/tabbarios.html#barstyle) - [`barTintColor`](docs/tabbarios.html#bartintcolor) - [`itemPositioning`](docs/tabbarios.html#itempositioning) @@ -61,12 +61,10 @@ Background color of the tab bar ### `itemPositioning` Specifies tab bar item positioning. Available values are: -- fill - distributes items across the entire width of the tab bar -- center - centers item in the available tab bar space -- auto (default) - distributes items dynamically according to the -user interface idiom. In a horizontally compact environment (e.g. iPhone 5) -this value defaults to `fill`, in a horizontally regular one (e.g. iPad) -it defaults to center. + +- `fill` - distributes items across the entire width of the tab bar +- `center` - centers item in the available tab bar space +- `auto` (default) - distributes items dynamically according to the user interface idiom. In a horizontally compact environment (e.g. iPhone 5) this value defaults to `fill`, in a horizontally regular one (e.g. iPad) it defaults to center. | Type | Required | | - | - | @@ -83,7 +81,7 @@ it defaults to center. | Type | Required | | - | - | -| ViewPropTypes.style | No | +| [ViewPropTypes.style](docs/viewproptypes.html#style) | No | diff --git a/docs/textstyleproptypes.md b/docs/text-style-props.md similarity index 67% rename from docs/textstyleproptypes.md rename to docs/text-style-props.md index c4f6def481bda1..72bf702655e0fb 100644 --- a/docs/textstyleproptypes.md +++ b/docs/text-style-props.md @@ -1,32 +1,32 @@ --- -id: textstyleproptypes -title: TextStylePropTypes +id: text-style-props +title: Text Style Props layout: docs category: APIs -permalink: docs/textstyleproptypes.html -next: imagestyleproptypes -previous: viewstyleproptypes +permalink: docs/text-style-props.html +next: image-style-props +previous: view-style-props --- ### Props -- [`textShadowOffset`](docs/textstyleproptypes.html#textshadowoffset) -- [`color`](docs/textstyleproptypes.html#color) -- [`fontSize`](docs/textstyleproptypes.html#fontsize) -- [`fontStyle`](docs/textstyleproptypes.html#fontstyle) -- [`fontWeight`](docs/textstyleproptypes.html#fontweight) -- [`lineHeight`](docs/textstyleproptypes.html#lineheight) -- [`textAlign`](docs/textstyleproptypes.html#textalign) -- [`textDecorationLine`](docs/textstyleproptypes.html#textdecorationline) -- [`textShadowColor`](docs/textstyleproptypes.html#textshadowcolor) -- [`fontFamily`](docs/textstyleproptypes.html#fontfamily) -- [`textShadowRadius`](docs/textstyleproptypes.html#textshadowradius) -- [`includeFontPadding`](docs/textstyleproptypes.html#includefontpadding) -- [`textAlignVertical`](docs/textstyleproptypes.html#textalignvertical) -- [`fontVariant`](docs/textstyleproptypes.html#fontvariant) -- [`letterSpacing`](docs/textstyleproptypes.html#letterspacing) -- [`textDecorationColor`](docs/textstyleproptypes.html#textdecorationcolor) -- [`textDecorationStyle`](docs/textstyleproptypes.html#textdecorationstyle) -- [`writingDirection`](docs/textstyleproptypes.html#writingdirection) +- [`textShadowOffset`](docs/text-style-props.html#textshadowoffset) +- [`color`](docs/text-style-props.html#color) +- [`fontSize`](docs/text-style-props.html#fontsize) +- [`fontStyle`](docs/text-style-props.html#fontstyle) +- [`fontWeight`](docs/text-style-props.html#fontweight) +- [`lineHeight`](docs/text-style-props.html#lineheight) +- [`textAlign`](docs/text-style-props.html#textalign) +- [`textDecorationLine`](docs/text-style-props.html#textdecorationline) +- [`textShadowColor`](docs/text-style-props.html#textshadowcolor) +- [`fontFamily`](docs/text-style-props.html#fontfamily) +- [`textShadowRadius`](docs/text-style-props.html#textshadowradius) +- [`includeFontPadding`](docs/text-style-props.html#includefontpadding) +- [`textAlignVertical`](docs/text-style-props.html#textalignvertical) +- [`fontVariant`](docs/text-style-props.html#fontvariant) +- [`letterSpacing`](docs/text-style-props.html#letterspacing) +- [`textDecorationColor`](docs/text-style-props.html#textdecorationcolor) +- [`textDecorationStyle`](docs/text-style-props.html#textdecorationstyle) +- [`writingDirection`](docs/text-style-props.html#writingdirection) diff --git a/docs/text.md b/docs/text.md index 2f43c52ede2cd9..b64199adea98d4 100644 --- a/docs/text.md +++ b/docs/text.md @@ -7,6 +7,7 @@ permalink: docs/text.html next: textinput previous: tabbarios-item --- + A React component for displaying text. `Text` supports nesting, styling, and touch handling. diff --git a/docs/textinput.md b/docs/textinput.md index 75ad2ca91c2ced..e032d386c703bb 100644 --- a/docs/textinput.md +++ b/docs/textinput.md @@ -118,7 +118,7 @@ or control this param programmatically with native code. ### Props -* [ViewPropTypes props...](docs/viewproptypes.html#props) +- [View props...](docs/view-props.html) - [`placeholderTextColor`](docs/textinput.html#placeholdertextcolor) - [`allowFontScaling`](docs/textinput.html#allowfontscaling) - [`autoCorrect`](docs/textinput.html#autocorrect) diff --git a/docs/timepickerandroid.md b/docs/timepickerandroid.md index 570dfc1566e363..24e877aa8e2506 100644 --- a/docs/timepickerandroid.md +++ b/docs/timepickerandroid.md @@ -46,7 +46,7 @@ try { ### `open()` ```javascript -static open(options) +TimePickerAndroid.open(options) ``` @@ -76,7 +76,7 @@ being undefined. **Always** check whether the `action` before reading the values ### `timeSetAction()` ```javascript -static timeSetAction() +TimePickerAndroid.timeSetAction() ``` @@ -90,7 +90,7 @@ A time has been selected. ### `dismissedAction()` ```javascript -static dismissedAction() +TimePickerAndroid.dismissedAction() ``` diff --git a/docs/toastandroid.md b/docs/toastandroid.md index a8408b17e98559..ecb15135bf148d 100644 --- a/docs/toastandroid.md +++ b/docs/toastandroid.md @@ -21,6 +21,7 @@ The 'showWithGravityAndOffset' function adds on the ability to specify offset These offset values will translate to pixels. Basic usage: + ```javascript ToastAndroid.show('A pikachu appeared nearby !', ToastAndroid.SHORT); ToastAndroid.showWithGravity('All Your Base Are Belong To Us', ToastAndroid.SHORT, ToastAndroid.CENTER); @@ -55,7 +56,7 @@ ToastAndroid.showWithGravityAndOffset('A wild toast appeared!', ToastAndroid.LON ### `show()` ```javascript -static show(message, duration) +ToastAndroid.show(message, duration) ``` @@ -65,7 +66,7 @@ static show(message, duration) ### `showWithGravity()` ```javascript -static showWithGravity(message, duration, gravity) +ToastAndroid.showWithGravity(message, duration, gravity) ``` @@ -75,28 +76,30 @@ static showWithGravity(message, duration, gravity) ### `showWithGravityAndOffset()` ```javascript -static showWithGravityAndOffset(message, duration, gravity, xOffset, yOffset) +ToastAndroid.showWithGravityAndOffset(message, duration, gravity, xOffset, yOffset) ``` ## Properties - +### `SHORT` --- - +### `LONG` --- - +### `TOP` --- +### `BOTTOM` --- +### `CENTER` diff --git a/docs/toolbarandroid.md b/docs/toolbarandroid.md index 17bdc46c6e75fa..ba37cb65c903e9 100644 --- a/docs/toolbarandroid.md +++ b/docs/toolbarandroid.md @@ -43,7 +43,7 @@ onActionSelected: function(position) { ### Props -* [ViewPropTypes props...](docs/viewproptypes.html#props) +- [View props...](docs/view-props.html) - [`overflowIcon`](docs/toolbarandroid.html#overflowicon) - [`actions`](docs/toolbarandroid.html#actions) - [`contentInsetStart`](docs/toolbarandroid.html#contentinsetstart) diff --git a/docs/touchablehighlight.md b/docs/touchablehighlight.md index cbaaf3222d27b9..2842c41a2f3282 100644 --- a/docs/touchablehighlight.md +++ b/docs/touchablehighlight.md @@ -169,7 +169,7 @@ Called immediately after the underlay is shown | Type | Required | | - | - | -| ViewPropTypes.style | No | +| [ViewPropTypes.style](docs/viewproptypes.html#style) | No | diff --git a/docs/touchablenativefeedback.md b/docs/touchablenativefeedback.md index 1e21ad203017be..a821eebeb31b06 100644 --- a/docs/touchablenativefeedback.md +++ b/docs/touchablenativefeedback.md @@ -99,11 +99,10 @@ fallback to background. ### `SelectableBackground()` ```javascript -static SelectableBackground() +TouchableNativeFeedback.SelectableBackground() ``` -Creates an object that represents android theme's default background for -selectable elements (?android:attr/selectableItemBackground). +Creates an object that represents android theme's default background for selectable elements (?android:attr/selectableItemBackground). @@ -112,11 +111,10 @@ selectable elements (?android:attr/selectableItemBackground). ### `SelectableBackgroundBorderless()` ```javascript -static SelectableBackgroundBorderless() +TouchableNativeFeedback.SelectableBackgroundBorderless() ``` -Creates an object that represent android theme's default background for borderless -selectable elements (?android:attr/selectableItemBackgroundBorderless). +Creates an object that represent android theme's default background for borderless selectable elements (?android:attr/selectableItemBackgroundBorderless). Available on android API level 21+. @@ -126,21 +124,17 @@ Available on android API level 21+. ### `Ripple()` ```javascript -static Ripple(color: string, borderless: boolean) +TouchableNativeFeedback.Ripple(color: string, borderless: boolean) ``` -Creates an object that represents ripple drawable with specified color (as a -string). If property `borderless` evaluates to true the ripple will -render outside of the view bounds (see native actionbar buttons as an -example of that behavior). This background type is available on Android -API level 21+. +Creates an object that represents ripple drawable with specified color (as a string). If property `borderless` evaluates to true the ripple will render outside of the view bounds (see native actionbar buttons as an example of that behavior). This background type is available on Android API level 21+. **Parameters:** | Name | Type | Required | Description | | - | - | - | - | -| color | string | No | The ripple color | -| borderless | boolean | No | If the ripple can render outside it's bounds | +| color | string | Yes | The ripple color | +| borderless | boolean | Yes | If the ripple can render outside its bounds | @@ -150,8 +144,8 @@ API level 21+. ### `canUseNativeForeground()` ```javascript -static canUseNativeForeground() +TouchableNativeFeedback.canUseNativeForeground() ``` - +Whether native foreground ripple is available on the current version of Android. diff --git a/docs/touchablewithoutfeedback.md b/docs/touchablewithoutfeedback.md index 6ac830f1ffdf02..e352798d791378 100644 --- a/docs/touchablewithoutfeedback.md +++ b/docs/touchablewithoutfeedback.md @@ -48,12 +48,10 @@ If you wish to have several child components, wrap them in a View. ### `hitSlop` -This defines how far your touch can start away from the button. This is -added to `pressRetentionOffset` when moving off of the button. -** NOTE ** -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. +This defines how far your touch can start away from the button. This is added to `pressRetentionOffset` when moving off of the button. + +> Note: +> 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. | Type | Required | | - | - | diff --git a/docs/vibration.md b/docs/vibration.md index c19e27c2d9e380..ca49bab23ac532 100644 --- a/docs/vibration.md +++ b/docs/vibration.md @@ -63,7 +63,7 @@ Vibration.cancel() ### `vibrate()` ```javascript -static vibrate(pattern: number, Array, repeat: boolean) +Vibration.vibrate(pattern: number, Array, repeat: boolean) ``` Trigger a vibration with specified `pattern`. @@ -72,8 +72,8 @@ Trigger a vibration with specified `pattern`. | Name | Type | Required | Description | | - | - | - | - | -| pattern | number,Array | No | Vibration pattern, accept a number or an array of number. Default to 400ms. | -| repeat | boolean | No | Optional. Repeat vibration pattern until cancel(), default to false. | +| pattern | number, Array | Yes | Vibration pattern, accept a number or an array of number. Default to 400ms. | +| repeat | boolean | Yes | Optional. Repeat vibration pattern until cancel(), default to false. | @@ -83,13 +83,11 @@ Trigger a vibration with specified `pattern`. ### `cancel()` ```javascript -static cancel() -``` - -Stop vibration -``` Vibration.cancel() ``` +Stop vibration. + + diff --git a/docs/vibrationios.md b/docs/vibrationios.md index ba4a175a67e64d..e2452907caaabd 100644 --- a/docs/vibrationios.md +++ b/docs/vibrationios.md @@ -8,18 +8,15 @@ next: layout-props previous: vibration --- -NOTE: `VibrationIOS` is being deprecated. Use `Vibration` instead. +> NOTE: +> `VibrationIOS` is deprecated. Use [`Vibration`](docs/vibration.html) instead. -The Vibration API is exposed at `VibrationIOS.vibrate()`. On iOS, calling this -function will trigger a one second vibration. The vibration is asynchronous -so this method will return immediately. +The Vibration API is exposed at `VibrationIOS.vibrate()`. On iOS, calling this function will trigger a one second vibration. The vibration is asynchronous so this method will return immediately. -There will be no effect on devices that do not support Vibration, eg. the iOS -simulator. +There will be no effect on devices that do not support Vibration, eg. the iOS simulator. Vibration patterns are currently unsupported. - ### Methods - [`vibrate`](docs/vibrationios.html#vibrate) @@ -36,11 +33,10 @@ Vibration patterns are currently unsupported. ### `vibrate()` ```javascript -static vibrate() +VibrationIOS.vibrate() ``` - -@deprecated +**Deprecated.** diff --git a/docs/viewproptypes.md b/docs/view-props.md similarity index 86% rename from docs/viewproptypes.md rename to docs/view-props.md index 304ebc34a7c84c..3ab3c2b3cd1c4e 100644 --- a/docs/viewproptypes.md +++ b/docs/view-props.md @@ -1,44 +1,44 @@ --- -id: viewproptypes -title: ViewPropTypes +id: view-props +title: View Props layout: docs category: APIs -permalink: docs/viewproptypes.html -next: viewstyleproptypes +permalink: docs/view-props.html +next: view-style-props previous: shadow-props --- ### Props -- [`onStartShouldSetResponder`](docs/viewproptypes.html#onstartshouldsetresponder) -- [`accessibilityLabel`](docs/viewproptypes.html#accessibilitylabel) -- [`hitSlop`](docs/viewproptypes.html#hitslop) -- [`nativeID`](docs/viewproptypes.html#nativeid) -- [`onAccessibilityTap`](docs/viewproptypes.html#onaccessibilitytap) -- [`onLayout`](docs/viewproptypes.html#onlayout) -- [`onMagicTap`](docs/viewproptypes.html#onmagictap) -- [`onMoveShouldSetResponder`](docs/viewproptypes.html#onmoveshouldsetresponder) -- [`onMoveShouldSetResponderCapture`](docs/viewproptypes.html#onmoveshouldsetrespondercapture) -- [`onResponderGrant`](docs/viewproptypes.html#onrespondergrant) -- [`onResponderMove`](docs/viewproptypes.html#onrespondermove) -- [`onResponderReject`](docs/viewproptypes.html#onresponderreject) -- [`onResponderRelease`](docs/viewproptypes.html#onresponderrelease) -- [`onResponderTerminate`](docs/viewproptypes.html#onresponderterminate) -- [`onResponderTerminationRequest`](docs/viewproptypes.html#onresponderterminationrequest) -- [`accessible`](docs/viewproptypes.html#accessible) -- [`onStartShouldSetResponderCapture`](docs/viewproptypes.html#onstartshouldsetrespondercapture) -- [`pointerEvents`](docs/viewproptypes.html#pointerevents) -- [`removeClippedSubviews`](docs/viewproptypes.html#removeclippedsubviews) -- [`style`](docs/viewproptypes.html#style) -- [`testID`](docs/viewproptypes.html#testid) -- [`accessibilityComponentType`](docs/viewproptypes.html#accessibilitycomponenttype) -- [`accessibilityLiveRegion`](docs/viewproptypes.html#accessibilityliveregion) -- [`collapsable`](docs/viewproptypes.html#collapsable) -- [`importantForAccessibility`](docs/viewproptypes.html#importantforaccessibility) -- [`needsOffscreenAlphaCompositing`](docs/viewproptypes.html#needsoffscreenalphacompositing) -- [`renderToHardwareTextureAndroid`](docs/viewproptypes.html#rendertohardwaretextureandroid) -- [`accessibilityTraits`](docs/viewproptypes.html#accessibilitytraits) -- [`accessibilityViewIsModal`](docs/viewproptypes.html#accessibilityviewismodal) -- [`shouldRasterizeIOS`](docs/viewproptypes.html#shouldrasterizeios) +- [`onStartShouldSetResponder`](docs/view-props.html#onstartshouldsetresponder) +- [`accessibilityLabel`](docs/view-props.html#accessibilitylabel) +- [`hitSlop`](docs/view-props.html#hitslop) +- [`nativeID`](docs/view-props.html#nativeid) +- [`onAccessibilityTap`](docs/view-props.html#onaccessibilitytap) +- [`onLayout`](docs/view-props.html#onlayout) +- [`onMagicTap`](docs/view-props.html#onmagictap) +- [`onMoveShouldSetResponder`](docs/view-props.html#onmoveshouldsetresponder) +- [`onMoveShouldSetResponderCapture`](docs/view-props.html#onmoveshouldsetrespondercapture) +- [`onResponderGrant`](docs/view-props.html#onrespondergrant) +- [`onResponderMove`](docs/view-props.html#onrespondermove) +- [`onResponderReject`](docs/view-props.html#onresponderreject) +- [`onResponderRelease`](docs/view-props.html#onresponderrelease) +- [`onResponderTerminate`](docs/view-props.html#onresponderterminate) +- [`onResponderTerminationRequest`](docs/view-props.html#onresponderterminationrequest) +- [`accessible`](docs/view-props.html#accessible) +- [`onStartShouldSetResponderCapture`](docs/view-props.html#onstartshouldsetrespondercapture) +- [`pointerEvents`](docs/view-props.html#pointerevents) +- [`removeClippedSubviews`](docs/view-props.html#removeclippedsubviews) +- [`style`](docs/view-props.html#style) +- [`testID`](docs/view-props.html#testid) +- [`accessibilityComponentType`](docs/view-props.html#accessibilitycomponenttype) +- [`accessibilityLiveRegion`](docs/view-props.html#accessibilityliveregion) +- [`collapsable`](docs/view-props.html#collapsable) +- [`importantForAccessibility`](docs/view-props.html#importantforaccessibility) +- [`needsOffscreenAlphaCompositing`](docs/view-props.html#needsoffscreenalphacompositing) +- [`renderToHardwareTextureAndroid`](docs/view-props.html#rendertohardwaretextureandroid) +- [`accessibilityTraits`](docs/view-props.html#accessibilitytraits) +- [`accessibilityViewIsModal`](docs/view-props.html#accessibilityviewismodal) +- [`shouldRasterizeIOS`](docs/view-props.html#shouldrasterizeios) @@ -399,7 +399,7 @@ subviews must also have `overflow: hidden`, as should the containing view | Type | Required | | - | - | -| stylePropType | No | +| style | No | diff --git a/docs/viewstyleproptypes.md b/docs/view-style-props.md similarity index 58% rename from docs/viewstyleproptypes.md rename to docs/view-style-props.md index 08bd57386e8035..b369582d5c4960 100644 --- a/docs/viewstyleproptypes.md +++ b/docs/view-style-props.md @@ -1,40 +1,40 @@ --- -id: viewstyleproptypes -title: ViewStylePropTypes +id: view-style-props +title: View Style Props layout: docs category: APIs -permalink: docs/viewstyleproptypes.html -next: textstyleproptypes -previous: viewproptypes +permalink: docs/view-style-props.html +next: text-style-props +previous: view-props --- ### Props -- [`borderRightColor`](docs/viewstyleproptypes.html#borderrightcolor) -- [`backfaceVisibility`](docs/viewstyleproptypes.html#backfacevisibility) -- [`borderBottomColor`](docs/viewstyleproptypes.html#borderbottomcolor) -- [`borderBottomEndRadius`](docs/viewstyleproptypes.html#borderbottomendradius) -- [`borderBottomLeftRadius`](docs/viewstyleproptypes.html#borderbottomleftradius) -- [`borderBottomRightRadius`](docs/viewstyleproptypes.html#borderbottomrightradius) -- [`borderBottomStartRadius`](docs/viewstyleproptypes.html#borderbottomstartradius) -- [`borderBottomWidth`](docs/viewstyleproptypes.html#borderbottomwidth) -- [`borderColor`](docs/viewstyleproptypes.html#bordercolor) -- [`borderEndColor`](docs/viewstyleproptypes.html#borderendcolor) -- [`borderLeftColor`](docs/viewstyleproptypes.html#borderleftcolor) -- [`borderLeftWidth`](docs/viewstyleproptypes.html#borderleftwidth) -- [`borderRadius`](docs/viewstyleproptypes.html#borderradius) -- [`backgroundColor`](docs/viewstyleproptypes.html#backgroundcolor) -- [`borderRightWidth`](docs/viewstyleproptypes.html#borderrightwidth) -- [`borderStartColor`](docs/viewstyleproptypes.html#borderstartcolor) -- [`borderStyle`](docs/viewstyleproptypes.html#borderstyle) -- [`borderTopColor`](docs/viewstyleproptypes.html#bordertopcolor) -- [`borderTopEndRadius`](docs/viewstyleproptypes.html#bordertopendradius) -- [`borderTopLeftRadius`](docs/viewstyleproptypes.html#bordertopleftradius) -- [`borderTopRightRadius`](docs/viewstyleproptypes.html#bordertoprightradius) -- [`borderTopStartRadius`](docs/viewstyleproptypes.html#bordertopstartradius) -- [`borderTopWidth`](docs/viewstyleproptypes.html#bordertopwidth) -- [`borderWidth`](docs/viewstyleproptypes.html#borderwidth) -- [`opacity`](docs/viewstyleproptypes.html#opacity) -- [`elevation`](docs/viewstyleproptypes.html#elevation) +- [`borderRightColor`](docs/view-style-props.html#borderrightcolor) +- [`backfaceVisibility`](docs/view-style-props.html#backfacevisibility) +- [`borderBottomColor`](docs/view-style-props.html#borderbottomcolor) +- [`borderBottomEndRadius`](docs/view-style-props.html#borderbottomendradius) +- [`borderBottomLeftRadius`](docs/view-style-props.html#borderbottomleftradius) +- [`borderBottomRightRadius`](docs/view-style-props.html#borderbottomrightradius) +- [`borderBottomStartRadius`](docs/view-style-props.html#borderbottomstartradius) +- [`borderBottomWidth`](docs/view-style-props.html#borderbottomwidth) +- [`borderColor`](docs/view-style-props.html#bordercolor) +- [`borderEndColor`](docs/view-style-props.html#borderendcolor) +- [`borderLeftColor`](docs/view-style-props.html#borderleftcolor) +- [`borderLeftWidth`](docs/view-style-props.html#borderleftwidth) +- [`borderRadius`](docs/view-style-props.html#borderradius) +- [`backgroundColor`](docs/view-style-props.html#backgroundcolor) +- [`borderRightWidth`](docs/view-style-props.html#borderrightwidth) +- [`borderStartColor`](docs/view-style-props.html#borderstartcolor) +- [`borderStyle`](docs/view-style-props.html#borderstyle) +- [`borderTopColor`](docs/view-style-props.html#bordertopcolor) +- [`borderTopEndRadius`](docs/view-style-props.html#bordertopendradius) +- [`borderTopLeftRadius`](docs/view-style-props.html#bordertopleftradius) +- [`borderTopRightRadius`](docs/view-style-props.html#bordertoprightradius) +- [`borderTopStartRadius`](docs/view-style-props.html#bordertopstartradius) +- [`borderTopWidth`](docs/view-style-props.html#bordertopwidth) +- [`borderWidth`](docs/view-style-props.html#borderwidth) +- [`opacity`](docs/view-style-props.html#opacity) +- [`elevation`](docs/view-style-props.html#elevation) diff --git a/docs/view.md b/docs/view.md index f381c132b1836e..c00b327a440a68 100644 --- a/docs/view.md +++ b/docs/view.md @@ -7,17 +7,12 @@ permalink: docs/view.html next: viewpagerandroid previous: touchablewithoutfeedback --- -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 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. `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. +This example creates a `View` that wraps two colored boxes and a text component in a row with padding. ```javascript class ViewColoredBoxesWithText extends Component { @@ -33,13 +28,11 @@ class ViewColoredBoxesWithText extends Component { } ``` -> `View`s are designed to be used with [`StyleSheet`](docs/style.html) for clarity -> and performance, although inline styles are also supported. +> `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: +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. @@ -54,7 +47,7 @@ are of the following form: ### Props -* [ViewPropTypes props...](docs/viewproptypes.html#props) +- [View props...](docs/view-props.html) - [`onStartShouldSetResponder`](docs/view.html#onstartshouldsetresponder) - [`accessibilityLabel`](docs/view.html#accessibilitylabel) - [`hitSlop`](docs/view.html#hitslop) diff --git a/docs/viewpagerandroid.md b/docs/viewpagerandroid.md index 0288ea25b6a6f2..8b4006445f33db 100644 --- a/docs/viewpagerandroid.md +++ b/docs/viewpagerandroid.md @@ -49,7 +49,7 @@ var styles = { ### Props -* [ViewPropTypes props...](docs/viewproptypes.html#props) +- [View props...](docs/view-props.html) - [`initialPage`](docs/viewpagerandroid.html#initialpage) - [`keyboardDismissMode`](docs/viewpagerandroid.html#keyboarddismissmode) - [`onPageScroll`](docs/viewpagerandroid.html#onpagescroll) @@ -92,8 +92,9 @@ update the page, and `onPageSelected` to monitor page changes ### `keyboardDismissMode` Determines whether the keyboard gets dismissed in response to a drag. - - 'none' (the default), drags do not dismiss the keyboard. - - 'on-drag', the keyboard is dismissed when a drag begins. + +- 'none' (the default), drags do not dismiss the keyboard. +- 'on-drag', the keyboard is dismissed when a drag begins. | Type | Required | | - | - | @@ -106,13 +107,11 @@ Determines whether the keyboard gets dismissed in response to a drag. ### `onPageScroll` -Executed when transitioning between pages (ether because of animation for -the requested page change or when user is swiping/dragging between pages) -The `event.nativeEvent` object for this callback will carry following data: - - position - index of first page from the left that is currently visible - - offset - value from range [0,1) describing stage between page transitions. - Value x means that (1 - x) fraction of the page at "position" index is - visible, and x fraction of the next page is visible. +Executed when transitioning between pages (ether because of animation for the requested page change or when user is swiping/dragging between pages) The `event.nativeEvent` object for this callback will carry following data: + +- position - index of first page from the left that is currently visible +- offset - value from range [0,1) describing stage between page transitions. + Value x means that (1 - x) fraction of the page at "position" index is visible, and x fraction of the next page is visible. | Type | Required | | - | - | diff --git a/docs/virtualizedlist.md b/docs/virtualizedlist.md index 6d4054ba18c76b..016eee879545ff 100644 --- a/docs/virtualizedlist.md +++ b/docs/virtualizedlist.md @@ -7,48 +7,59 @@ permalink: docs/virtualizedlist.html next: webview previous: viewpagerandroid --- -Base implementation for the more convenient [``](/react-native/docs/flatlist.html) -and [``](/react-native/docs/sectionlist.html) components, which are also better -documented. In general, this should only really be used if you need more flexibility than -`FlatList` provides, e.g. for use with immutable data instead of plain arrays. -Virtualization massively improves memory consumption and performance of large lists by -maintaining a finite render window of active items and replacing all items outside of the render -window with appropriately sized blank space. The window adapts to scrolling behavior, and items -are rendered incrementally with low-pri (after any running interactions) if they are far from the -visible area, or with hi-pri otherwise to minimize the potential of seeing blank space. +Base implementation for the more convenient [``](/react-native/docs/flatlist.html) and [``](/react-native/docs/sectionlist.html) components, which are also better documented. In general, this should only really be used if you need more flexibility than `FlatList` provides, e.g. for use with immutable data instead of plain arrays. + +Virtualization massively improves memory consumption and performance of large lists by maintaining a finite render window of active items and replacing all items outside of the render window with appropriately sized blank space. The window adapts to scrolling behavior, and items are rendered incrementally with low-pri (after any running interactions) if they are far from the visible area, or with hi-pri otherwise to minimize the potential of seeing blank space. Some caveats: -- Internal state is not preserved when content scrolls out of the render window. Make sure all - your data is captured in the item data or external stores like Flux, Redux, or Relay. -- This is a `PureComponent` which means that it will not re-render if `props` remain shallow- - equal. Make sure that everything your `renderItem` function depends on is passed as a prop - (e.g. `extraData`) that is not `===` after updates, otherwise your UI may not update on - changes. This includes the `data` prop and parent component state. -- In order to constrain memory and enable smooth scrolling, content is rendered asynchronously - offscreen. This means it's possible to scroll faster than the fill rate ands momentarily see - blank content. This is a tradeoff that can be adjusted to suit the needs of each application, - and we are working on improving it behind the scenes. -- By default, the list looks for a `key` prop on each item and uses that for the React key. - Alternatively, you can provide a custom `keyExtractor` prop. +- Internal state is not preserved when content scrolls out of the render window. Make sure all your data is captured in the item data or external stores like Flux, Redux, or Relay. +- This is a `PureComponent` which means that it will not re-render if `props` remain shallow-equal. Make sure that everything your `renderItem` function depends on is passed as a prop (e.g. `extraData`) that is not `===` after updates, otherwise your UI may not update on changes. This includes the `data` prop and parent component state. +- In order to constrain memory and enable smooth scrolling, content is rendered asynchronously offscreen. This means it's possible to scroll faster than the fill rate ands momentarily see blank content. This is a tradeoff that can be adjusted to suit the needs of each application, and we are working on improving it behind the scenes. +- By default, the list looks for a `key` prop on each item and uses that for the React key. Alternatively, you can provide a custom `keyExtractor` prop. ### Props -- [`last`](docs/virtualizedlist.html#last) -- [`first`](docs/virtualizedlist.html#first) +- [`ScrollView` props...](docs/scrollview.html#props) +- [`renderItem`](docs/virtualizedlist.html#renderitem) +- [`data`](docs/virtualizedlist.html#data) +- [`getItem`](docs/virtualizedlist.html#getitem) +- [`getItemCount`](docs/virtualizedlist.html#getitemcount) +- [`debug`](docs/virtualizedlist.html#debug) +- [`extraData`](docs/virtualizedlist.html#extradata) +- [`getItemLayout`](docs/virtualizedlist.html#getitemlayout) +- [`initialScrollIndex`](docs/virtualizedlist.html#initialscrollindex) +- [`inverted`](docs/virtualizedlist.html#inverted) +- [`CellRendererComponent`](docs/virtualizedlist.html#cellrenderercomponent) +- [`ListEmptyComponent`](docs/virtualizedlist.html#listemptycomponent) +- [`ListFooterComponent`](docs/virtualizedlist.html#listfootercomponent) +- [`ListHeaderComponent`](docs/virtualizedlist.html#listheadercomponent) +- [`onEndReached`](docs/virtualizedlist.html#onendreached) +- [`onLayout`](docs/virtualizedlist.html#onlayout) +- [`onRefresh`](docs/virtualizedlist.html#onrefresh) +- [`onScrollToIndexFailed`](docs/virtualizedlist.html#onscrolltoindexfailed) +- [`onViewableItemsChanged`](docs/virtualizedlist.html#onviewableitemschanged) +- [`refreshing`](docs/virtualizedlist.html#refreshing) +- [`removeClippedSubviews`](docs/virtualizedlist.html#removeclippedsubviews) +- [`renderScrollComponent`](docs/virtualizedlist.html#renderscrollcomponent) +- [`viewabilityConfig`](docs/virtualizedlist.html#viewabilityconfig) +- [`viewabilityConfigCallbackPairs`](docs/virtualizedlist.html#viewabilityconfigcallbackpairs) - [`horizontal`](docs/virtualizedlist.html#horizontal) - [`initialNumToRender`](docs/virtualizedlist.html#initialnumtorender) - [`keyExtractor`](docs/virtualizedlist.html#keyextractor) -- [`disableVirtualization`](docs/virtualizedlist.html#disablevirtualization) - [`maxToRenderPerBatch`](docs/virtualizedlist.html#maxtorenderperbatch) - [`onEndReachedThreshold`](docs/virtualizedlist.html#onendreachedthreshold) - [`scrollEventThrottle`](docs/virtualizedlist.html#scrolleventthrottle) - [`updateCellsBatchingPeriod`](docs/virtualizedlist.html#updatecellsbatchingperiod) - [`windowSize`](docs/virtualizedlist.html#windowsize) +- [`disableVirtualization`](docs/virtualizedlist.html#disablevirtualization) +- [`progressViewOffset`](docs/virtualizedlist.html#progressviewoffset) +### State - +- [`first`](docs/virtualizedlist.html#first) +- [`last`](docs/virtualizedlist.html#last) ### Methods @@ -74,104 +85,384 @@ Some caveats: ## Props -### `last` +### `renderItem` + +| Type | Required | +| - | - | +| number | Yes | + + +--- +### `data` + +The default accessor functions assume this is an array of objects with shape `{key: string}` but you can override `getItem`, `getItemCount`, and `keyExtractor` to handle any type of index-based data. | Type | Required | | - | - | -| number | Yes | +| any | Yes | + + +--- + + +### `getItem` + +```javascript +(data: any, index: number) => object +``` +A generic accessor for extracting an item from any sort of data blob. +| Type | Required | +| - | - | +| function | Yes | --- -### `first` +### `getItemCount` + +```javascript +(data: any) => number +``` +Determines how many items are in the data blob. | Type | Required | | - | - | -| number | Yes | +| function | Yes | + + +--- +### `debug` + +`debug` will turn on extra logging and visual overlays to aid with debugging both usage and implementation, but with a significant perf hit. + +| Type | Required | +| - | - | +| boolean | No | + --- -### `horizontal` +### `extraData` +A marker property for telling the list to re-render (since it implements `PureComponent`). If any of your `renderItem`, Header, Footer, etc. functions depend on anything outside of the `data` prop, stick it here and treat it immutably. | Type | Required | | - | - | -| | No | +| any | No | + + +--- + + +### `getItemLayout` +```javascript +( + data: any, + index: number, + ) => {length: number, offset: number, index: number} +``` +| Type | Required | +| - | - | +| function | No | --- -### `initialNumToRender` +### `initialScrollIndex` +Instead of starting at the top with the first item, start at `initialScrollIndex`. This disables the "scroll to top" optimization that keeps the first `initialNumToRender` items always rendered and immediately renders the items starting at this initial index. Requires `getItemLayout` to be implemented. | Type | Required | | - | - | -| | No | +| number | No | + + +--- + +### `inverted` +Reverses the direction of scroll. Uses scale transforms of -1. + +| Type | Required | +| - | - | +| boolean | No | --- -### `keyExtractor` +### `CellRendererComponent` +Each cell is rendered using this element. Can be a React Component Class,or a render function. Defaults to using [`View`](docs/view.html). | Type | Required | | - | - | -| | No | +| component, function | No | + +--- + + +### `ListEmptyComponent` + +Rendered when the list is empty. Can be a React Component Class, a render function, or a rendered element. +| Type | Required | +| - | - | +| component, function, element | No | --- -### `disableVirtualization` +### `ListFooterComponent` +Rendered at the bottom of all the items. Can be a React Component Class, a render function, or a rendered element. | Type | Required | | - | - | -| | No | +| component, function, element | No | +--- + + +### `ListHeaderComponent` + +Rendered at the top of all the items. Can be a React Component Class, a render function, or a rendered element. + +| Type | Required | +| - | - | +| component, function, element | No | --- -### `maxToRenderPerBatch` +### `onLayout` +| Type | Required | +| - | - | +| function | No | + + +--- + + +### `onRefresh` + +```javascript +() => void +``` + +If provided, a standard `RefreshControl` will be added for "Pull to Refresh" functionality. Make sure to also set the `refreshing` prop correctly. | Type | Required | | - | - | -| | No | +| function | No | + + +--- + +### `onScrollToIndexFailed` +```javascript +(info: { + index: number, + highestMeasuredFrameIndex: number, + averageItemLength: number, + }) => void +``` + +Used to handle failures when scrolling to an index that has not been measured yet. Recommended action is to either compute your own offset and `scrollTo` it, or scroll as far as possible and then try again after more items have been rendered. + +| Type | Required | +| - | - | +| function | No | --- -### `onEndReachedThreshold` +### `onViewableItemsChanged` + +```javascript +(info: { + viewableItems: array, + changed: array, + }) => void +``` +Called when the viewability of rows changes, as defined by the `viewabilityConfig` prop. | Type | Required | | - | - | -| | No | +| function | No | + + + +--- + + +### `refreshing` + +Set this true while waiting for new data from a refresh. + +| Type | Required | +| - | - | +| boolean | No | + + +--- + + +### `removeClippedSubviews` + +This may improve scroll performance for large lists. + +> Note: +> May have bugs (missing content) in some circumstances - use at your own risk. + +| Type | Required | +| - | - | +| boolean | No | + + +--- + + +### `renderScrollComponent` + +```javascript +(props: object) => element +``` + +Render a custom scroll component, e.g. with a differently styled `RefreshControl`. + +| Type | Required | +| - | - | +| function | No | + + +--- + + +### `viewabilityConfig` + +See `ViewabilityHelper.js` for flow type and further documentation. + +| Type | Required | +| - | - | +| ViewabilityConfig | No | + + + +--- + + +### `viewabilityConfigCallbackPairs` + +List of `ViewabilityConfig`/`onViewableItemsChanged` pairs. A specific `onViewableItemsChanged` will be called when its corresponding `ViewabilityConfig`'s conditions are met. See `ViewabilityHelper.js` for flow type and further documentation. + +| Type | Required | +| - | - | +| array of ViewabilityConfigCallbackPair | No | + + +--- + + + +### `horizontal` + + + +| Type | Required | +| - | - | +| boolean | No | + + + + +--- + +### `initialNumToRender` + +How many items to render in the initial batch. This should be enough to fill the screen but not much more. Note these items will never be unmounted as part of the windowed rendering in order to improve perceived performance of scroll-to-top actions. + +| Type | Required | +| - | - | +| number | No | + + + + +--- + +### `keyExtractor` + +```javascript +(item: object, index: number) => string +``` + +Used to extract a unique key for a given item at the specified index. Key is used for caching and as the react key to track item re-ordering. The default extractor checks `item.key`, then falls back to using the index, like React does. + +| Type | Required | +| - | - | +| function | No | + + + +--- + +### `maxToRenderPerBatch` + +The maximum number of items to render in each incremental render batch. The more rendered at once, the better the fill rate, but responsiveness my suffer because rendering content may interfere with responding to button taps or other interactions. + +| Type | Required | +| - | - | +| number | No | + + +--- + +### `onEndReached` + +```javascript +(info: {distanceFromEnd: number}) => void +``` + +Called once when the scroll position gets within `onEndReachedThreshold` of the rendered content. + +| Type | Required | +| - | - | +| function | No | + +--- + +### `onEndReachedThreshold` + + How far from the end (in units of visible length of the list) the bottom edge of the list must be from the end of the content to trigger the `onEndReached` callback. Thus a value of 0.5 will trigger `onEndReached` when the end of the content is within half the visible length of the list. + +| Type | Required | +| - | - | +| number | No | + @@ -193,11 +484,11 @@ Some caveats: ### `updateCellsBatchingPeriod` - +Amount of time between low-pri item render batches, e.g. for rendering items quite a ways off screen. Similar fill rate/responsiveness tradeoff as `maxToRenderPerBatch`. | Type | Required | | - | - | -| | No | +| number | No | @@ -206,15 +497,56 @@ Some caveats: ### `windowSize` +Determines the maximum number of items rendered outside of the visible area, in units of visible lengths. So if your list fills the screen, then `windowSize={21}` (the default) will render the visible screen area plus up to 10 screens above and 10 below the viewport. Reducing this number will reduce memory consumption and may improve performance, but will increase the chance that fast scrolling may reveal momentary blank areas of unrendered content. + + +| Type | Required | +| - | - | +| number | No | + + +--- + +### `disableVirtualization` + +**DEPRECATED.** Virtualization provides significant performance and memory optimizations, but fully unmounts react instances that are outside of the render window. You should only need to disable this for debugging purposes. | Type | Required | | - | - | | | No | +--- + + +### `progressViewOffset` + +Set this when offset is needed for the loading indicator to show correctly. +| Type | Required | Platform | +| - | - | - | +| number | No | Android | +## State + +### `first` + + + +| Type | +| - | +| number | + +--- + +### `last` + + +| Type | +| - | +| number | + ## Methods @@ -257,12 +589,11 @@ scrollToOffset(params: object) Scroll to a specific content pixel offset in the list. -Param `offset` expects the offset to scroll to. -In case of `horizontal` is true, the offset is the x-value, -in any other case the offset is the y-value. +**Parameters:** -Param `animated` (`true` by default) defines whether the list -should do an animation while scrolling. +- `offset` expects the offset to scroll to. + In case of `horizontal` is true, the offset is the x-value, in any other case the offset is the y-value. +- `animated` (`true` by default) defines whether the list should do an animation while scrolling. diff --git a/docs/webview.md b/docs/webview.md index 60071707742ba1..bb2b5eea59160e 100644 --- a/docs/webview.md +++ b/docs/webview.md @@ -30,7 +30,7 @@ history and configure various properties for the web content. ### Props -* [ViewPropTypes props...](docs/viewproptypes.html#props) +- [View props...](docs/view-props.html) - [`source`](docs/webview.html#source) - [`automaticallyAdjustContentInsets`](docs/webview.html#automaticallyadjustcontentinsets) - [`injectJavaScript`](docs/webview.html#injectjavascript) @@ -85,8 +85,23 @@ Loads static html or a uri (with optional headers) in the WebView. | Type | Required | | - | - | -| object: {uri: string,method: string,headers: object,body: string}, ,object: {html: string,baseUrl: string}, ,number | No | +| object: {uri: string, method: string, headers: object, body: string},object: {html: string, baseUrl: string}, number | No | +**Keys:** + +An object with either set of keys can be used. Shape: + +- `uri` - The URI to load in the `WebView`. Can be a local or remote file. +- `method` - The HTTP Method to use. Defaults to GET if not specified. On Android, only GET and POST are supported. +- `headers` - Additional HTTP headers to send with the request. On Android, this can only be used with GET requests. +- `body` - The HTTP body to send with the request. This must be a valid UTF-8 string, and will be sent exactly as specified, with no additional encoding (e.g. URL-escaping or base64) applied. On Android, this can only be used with POST requests. + +Shape: + +- `html` - A static HTML page to display in the WebView. +- `baseUrl` - The base URL to be used for any relative links in the HTML. + +The packager uses a third type, `number`, internally. @@ -151,14 +166,17 @@ to tap them before they start playing. The default value is `true`. ### `nativeConfig` -Override the native component used to render the WebView. Enables a custom native -WebView which uses the same JavaScript as the original WebView. +Override the native component used to render the WebView. Enables a custom native WebView which uses the same JavaScript as the original WebView. | Type | Required | | - | - | | object: {component: any,props: object,viewManager: object} | No | +**Keys:** +- `component` - The native component used to render the WebView. +- `props` - Set props directly on the native component WebView. Enables custom props which the original WebView doesn't pass through. +- `viewManager` - Set the ViewManager to use for communication with the native side. iOS only. --- @@ -324,7 +342,7 @@ The style to apply to the `WebView`. | Type | Required | | - | - | -| ViewPropTypes.style | No | +| [ViewPropTypes.style](docs/viewproptypes.html#style) | No | @@ -501,7 +519,7 @@ Possible values for `dataDetectorTypes` are: | Type | Required | Platform | | - | - | - | -| enum('phoneNumber', 'link', 'address', 'calendarEvent', 'none', 'all'), ,array of enum('phoneNumber', 'link', 'address', 'calendarEvent', 'none', 'all') | No | iOS | +| enum('phoneNumber', 'link', 'address', 'calendarEvent', 'none', 'all'), array of enum('phoneNumber', 'link', 'address', 'calendarEvent', 'none', 'all') | No | iOS | @@ -558,7 +576,7 @@ Boolean value that determines whether scrolling is enabled in the ### `extraNativeComponentConfig()` ```javascript -static extraNativeComponentConfig() +WebView.extraNativeComponentConfig() ``` From 260e6d23554a8e7f1743263894c9ca9a0cfbf01e Mon Sep 17 00:00:00 2001 From: Dmitry Zakharov Date: Thu, 9 Nov 2017 09:49:34 -0800 Subject: [PATCH 07/50] Remove shared bridge experiment Reviewed By: kathryngray Differential Revision: D6284437 fbshipit-source-id: 14e0516f22dde04c0bbc4eb8fac603590d32d66a --- .../facebook/react/ReactInstanceManager.java | 35 ++++++------------- .../react/ReactInstanceManagerBuilder.java | 14 -------- 2 files changed, 10 insertions(+), 39 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index ab850f9cf521fe..aa317e7503bb4a 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -236,8 +236,6 @@ public static ReactInstanceManagerBuilder builder() { @Nullable DevBundleDownloadListener devBundleDownloadListener, boolean useSeparateUIBackgroundThread, int minNumShakes, - boolean splitPackagesEnabled, - boolean useOnlyDefaultPackages, int minTimeLeftInFrameForNonBatchedOperationMs) { Log.d(ReactConstants.TAG, "ReactInstanceManager.ctor()"); initializeSoLoaderIfNecessary(applicationContext); @@ -273,30 +271,17 @@ public static ReactInstanceManagerBuilder builder() { 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 BridgeCorePackage(this, mBackBtnHandler)); + if (mUseDeveloperSupport) { + mPackages.add(new DebugCorePackage()); } + mPackages.add( + new ReactNativeCorePackage( + this, + mUIImplementationProvider, + mLazyViewManagersEnabled, + mMinTimeLeftInFrameForNonBatchedOperationMs)); mPackages.addAll(packages); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java index 59eaa71e724161..2fbaaa2b80c339 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java @@ -48,8 +48,6 @@ public class ReactInstanceManagerBuilder { private @Nullable JavaScriptExecutorFactory mJavaScriptExecutorFactory; private boolean mUseSeparateUIBackgroundThread; private int mMinNumShakes = 1; - private boolean mEnableSplitPackage; - private boolean mUseOnlyDefaultPackages; private int mMinTimeLeftInFrameForNonBatchedOperationMs = -1; /* package protected */ ReactInstanceManagerBuilder() { @@ -227,16 +225,6 @@ public ReactInstanceManagerBuilder setMinNumShakes(int 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; @@ -300,8 +288,6 @@ public ReactInstanceManager build() { mDevBundleDownloadListener, mUseSeparateUIBackgroundThread, mMinNumShakes, - mEnableSplitPackage, - mUseOnlyDefaultPackages, mMinTimeLeftInFrameForNonBatchedOperationMs); } } From e5a4ea97d9e1b13509a3f36d0b469a6a88a90dc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ramos?= <165856+hramos@users.noreply.github.com> Date: Thu, 9 Nov 2017 10:56:52 -0800 Subject: [PATCH 08/50] Restore missing ejected banner Summary: A few more docs where the ejected metadata was lost in the autodocs flattening transition that happened in 9ec95673909beac7798f589e0e9821b4225f8fa9. Closes https://github.com/facebook/react-native/pull/16773 Differential Revision: D6286368 Pulled By: hramos fbshipit-source-id: bb7c032ca386e473c393821ce031714168d31719 --- docs/running-on-device.md | 1 + docs/running-on-simulator-ios.md | 1 + docs/signed-apk-android.md | 1 + docs/understanding-cli.md | 1 + 4 files changed, 4 insertions(+) diff --git a/docs/running-on-device.md b/docs/running-on-device.md index 1ecaf330931985..e4ef2dff9ee258 100644 --- a/docs/running-on-device.md +++ b/docs/running-on-device.md @@ -4,6 +4,7 @@ title: Running On Device layout: docs category: Guides permalink: docs/running-on-device.html +banner: ejected next: upgrading previous: integration-with-existing-apps --- diff --git a/docs/running-on-simulator-ios.md b/docs/running-on-simulator-ios.md index 8005ea17283455..950412009f6032 100644 --- a/docs/running-on-simulator-ios.md +++ b/docs/running-on-simulator-ios.md @@ -4,6 +4,7 @@ title: Running On Simulator layout: docs category: Guides (iOS) permalink: docs/running-on-simulator-ios.html +banner: ejected next: communication-ios previous: linking-libraries-ios --- diff --git a/docs/signed-apk-android.md b/docs/signed-apk-android.md index 21ba2ec3e79087..b96bbbf68f6304 100644 --- a/docs/signed-apk-android.md +++ b/docs/signed-apk-android.md @@ -4,6 +4,7 @@ title: Generating Signed APK layout: docs category: Guides (Android) permalink: docs/signed-apk-android.html +banner: ejected next: android-building-from-source previous: headless-js-android --- diff --git a/docs/understanding-cli.md b/docs/understanding-cli.md index 6b728506a2008f..6831b545303262 100644 --- a/docs/understanding-cli.md +++ b/docs/understanding-cli.md @@ -4,6 +4,7 @@ title: Understanding the CLI layout: docs category: Contributing permalink: docs/understanding-cli.html +banner: ejected next: activityindicator previous: testing --- From 820cfa1f3b79406e47cb873773cadafefe0effb1 Mon Sep 17 00:00:00 2001 From: James Isaac Date: Thu, 9 Nov 2017 11:41:08 -0800 Subject: [PATCH 09/50] Refine StyleSheet Flow types Summary: Nice addition of the recent Flow types for style props in 9c29ee1504a66979d7e87f60e42d437e044a1ada, however I think there are some slight issues in the definition. `type Styles = {[key: string]: Object}` makes sense, as it's referring to the set of named style groups a user creates a `StyleSheet` from, e.g. ```javascript const styles: StyleSheet = StyleSheet.create({ container: { height: 20 }, text: { color: '#999', fontSize: 12, }, }: Styles) ``` However `type StyleValue = {[key: string]: Object}` doesn't make sense. You actually want only the `Object` portion of that definition, presuming it's meant to be used like below: ```javascript type MyTextProps = { style: StyleProp, } Hello ``` --- I've also added `void` to the `StyleValue`, as undefined seems to be handled fine, and can be a useful shorthand in JSX. --- And finally, I've allowed nesting of style prop arrays, by making StyleProp self-referencing, as RN seems to flatten those without issue. This can be important if you're passing in a style prop quite high up the component tree, and sticking it in an array with other styles at several points while it's passed down. N/A (These types aren't referenced anywhere else) [INTERNAL] [MINOR] [StyleSheet] - Refine Flow types Closes https://github.com/facebook/react-native/pull/16741 Reviewed By: frantic Differential Revision: D6278010 Pulled By: TheSavior fbshipit-source-id: 0170a233ab71d29f445786f5e695463f9730db3a --- Libraries/StyleSheet/StyleSheet.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Libraries/StyleSheet/StyleSheet.js b/Libraries/StyleSheet/StyleSheet.js index 8fd9b1f6cd5141..411cad91b7c44d 100644 --- a/Libraries/StyleSheet/StyleSheet.js +++ b/Libraries/StyleSheet/StyleSheet.js @@ -20,8 +20,8 @@ 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; +export type StyleValue = Object | number | false | null | void | ''; +export type StyleProp = StyleValue | Array; let hairlineWidth = PixelRatio.roundToNearestPixel(0.4); if (hairlineWidth === 0) { From cff0d8e0e599d1ab21b36779b41fbb26512874aa Mon Sep 17 00:00:00 2001 From: Alex Dvornikov Date: Thu, 9 Nov 2017 11:55:37 -0800 Subject: [PATCH 10/50] Register split segment paths with RAMBundleRegistry Differential Revision: D6284466 fbshipit-source-id: c80cf929af38f92f06cca5b366c58785ae992d83 --- React/CxxBridge/RCTCxxBridge.mm | 2 +- React/CxxBridge/RCTObjcExecutor.mm | 4 ++++ .../main/jni/react/jni/CatalystInstanceImpl.cpp | 2 +- .../src/main/jni/react/jni/ProxyExecutor.cpp | 6 ++++++ .../src/main/jni/react/jni/ProxyExecutor.h | 2 ++ ReactCommon/cxxreact/Instance.cpp | 4 ++++ ReactCommon/cxxreact/Instance.h | 3 +++ ReactCommon/cxxreact/JSCExecutor.cpp | 6 ++++++ ReactCommon/cxxreact/JSCExecutor.h | 1 + ReactCommon/cxxreact/JSExecutor.h | 5 +++++ ReactCommon/cxxreact/JSIndexedRAMBundle.cpp | 7 +++---- ReactCommon/cxxreact/JSIndexedRAMBundle.h | 2 +- ReactCommon/cxxreact/NativeToJsBridge.cpp | 6 ++++++ ReactCommon/cxxreact/NativeToJsBridge.h | 1 + ReactCommon/cxxreact/RAMBundleRegistry.cpp | 15 ++++++++++++--- ReactCommon/cxxreact/RAMBundleRegistry.h | 9 ++++++--- 16 files changed, 62 insertions(+), 13 deletions(-) diff --git a/React/CxxBridge/RCTCxxBridge.mm b/React/CxxBridge/RCTCxxBridge.mm index 871bc46071c255..b5ce3026b2553a 100644 --- a/React/CxxBridge/RCTCxxBridge.mm +++ b/React/CxxBridge/RCTCxxBridge.mm @@ -1152,7 +1152,7 @@ - (void)executeApplicationScript:(NSData *)script ? [[self.delegate jsSegmentsDirectory].path stringByAppendingString:@"/"] : nil; auto registry = jsSegmentsDirectory != nil - ? RAMBundleRegistry::multipleBundlesRegistry(std::move(ramBundle), JSIndexedRAMBundle::buildFactory(jsSegmentsDirectory.UTF8String)) + ? RAMBundleRegistry::multipleBundlesRegistry(std::move(ramBundle), JSIndexedRAMBundle::buildFactory()) : RAMBundleRegistry::singleBundleRegistry(std::move(ramBundle)); self->_reactInstance->loadRAMBundle(std::move(registry), std::move(scriptStr), sourceUrlStr.UTF8String, !async); 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/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp index 3bcc53aa8318e9..4ca32b7b9c44b5 100644 --- a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp +++ b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp @@ -212,7 +212,7 @@ void CatalystInstanceImpl::jniLoadScriptFromFile(const std::string& fileName, auto script = bundle->getStartupCode(); auto registry = jsSegmentsDirectory_.empty() ? RAMBundleRegistry::singleBundleRegistry(std::move(bundle)) - : RAMBundleRegistry::multipleBundlesRegistry(std::move(bundle), JSIndexedRAMBundle::buildFactory(jsSegmentsDirectory_)); + : RAMBundleRegistry::multipleBundlesRegistry(std::move(bundle), JSIndexedRAMBundle::buildFactory()); instance_->loadRAMBundle( std::move(registry), std::move(script), 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/ReactCommon/cxxreact/Instance.cpp b/ReactCommon/cxxreact/Instance.cpp index 271dc85815d291..bdf1fce1eee280 100644 --- a/ReactCommon/cxxreact/Instance.cpp +++ b/ReactCommon/cxxreact/Instance.cpp @@ -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 51672048570e99..b5db5203fa74ad 100644 --- a/ReactCommon/cxxreact/JSIndexedRAMBundle.cpp +++ b/ReactCommon/cxxreact/JSIndexedRAMBundle.cpp @@ -9,10 +9,9 @@ namespace facebook { namespace react { -std::function(uint32_t)> JSIndexedRAMBundle::buildFactory(const std::string& baseDirectoryPath) { - return [baseDirectoryPath](uint32_t index){ - std::string bundlePathById = baseDirectoryPath + toString(index) + ".jsbundle"; - return folly::make_unique(bundlePathById.c_str()); +std::function(std::string)> JSIndexedRAMBundle::buildFactory() { + return [](const std::string& bundlePath){ + return folly::make_unique(bundlePath.c_str()); }; } diff --git a/ReactCommon/cxxreact/JSIndexedRAMBundle.h b/ReactCommon/cxxreact/JSIndexedRAMBundle.h index 3d4341b4a40a1b..6467977279fa53 100644 --- a/ReactCommon/cxxreact/JSIndexedRAMBundle.h +++ b/ReactCommon/cxxreact/JSIndexedRAMBundle.h @@ -17,7 +17,7 @@ namespace react { class RN_EXPORT JSIndexedRAMBundle : public JSModulesUnbundle { public: - static std::function(uint32_t)> buildFactory(const std::string& baseDirectoryPath); + static std::function(std::string)> buildFactory(); // Throws std::runtime_error on failure. JSIndexedRAMBundle(const char *sourceURL); 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 896eeb5f649c15..635875b3b79cbe 100644 --- a/ReactCommon/cxxreact/RAMBundleRegistry.cpp +++ b/ReactCommon/cxxreact/RAMBundleRegistry.cpp @@ -16,21 +16,30 @@ std::unique_ptr RAMBundleRegistry::singleBundleRegistry(std:: return std::unique_ptr(registry); } -std::unique_ptr RAMBundleRegistry::multipleBundlesRegistry(std::unique_ptr mainBundle, std::function(uint32_t)> factory) { +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(uint32_t)> factory): m_factory(factory) { +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()) { if (!m_factory) { throw std::runtime_error("You need to register factory function in order to support multiple RAM bundles."); } - m_bundles.emplace(bundleId, m_factory(bundleId)); + + 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 cb845a4751e29f..2d628f22c35d7c 100644 --- a/ReactCommon/cxxreact/RAMBundleRegistry.h +++ b/ReactCommon/cxxreact/RAMBundleRegistry.h @@ -21,21 +21,24 @@ 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; static std::unique_ptr singleBundleRegistry(unique_ram_bundle mainBundle); - static std::unique_ptr multipleBundlesRegistry(unique_ram_bundle mainBundle, std::function factory); + 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() {}; private: - explicit RAMBundleRegistry(unique_ram_bundle mainBundle, std::function factory = {}); + explicit RAMBundleRegistry(unique_ram_bundle mainBundle, std::function factory = {}); JSModulesUnbundle *getBundle(uint32_t bundleId) const; - std::function m_factory; + std::function m_factory; + std::unordered_map m_bundlePaths; std::unordered_map m_bundles; }; From 681278947eb4039a1d7a65f1edfeef25ae055a4f Mon Sep 17 00:00:00 2001 From: Alex Dvornikov Date: Thu, 9 Nov 2017 11:55:39 -0800 Subject: [PATCH 11/50] Adopt new split segments registration approach on iOS Differential Revision: D6284479 fbshipit-source-id: d0d7e8c6a6ce4ecab63739149be69f25df7fbe6f --- React/Base/RCTBridge.h | 7 +++++++ React/Base/RCTBridge.m | 5 +++++ React/Base/RCTBridgeDelegate.h | 7 ------- React/CxxBridge/RCTCxxBridge.mm | 14 ++++++++------ 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/React/Base/RCTBridge.h b/React/Base/RCTBridge.h index 450a0d0e38a104..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 diff --git a/React/Base/RCTBridge.m b/React/Base/RCTBridge.m index a8cef88c7bf4d9..33d8c977a9ea33 100644 --- a/React/Base/RCTBridge.m +++ b/React/Base/RCTBridge.m @@ -398,6 +398,11 @@ - (JSValue *)callFunctionOnModule:(NSString *)module return [self.batchedBridge callFunctionOnModule:module method:method arguments:arguments error:error]; } +- (void)registerSegmentWithId:(NSUInteger)segmentId path:(NSString *)path +{ + [self.batchedBridge registerSegmentWithId:segmentId path:path]; +} + @end @implementation RCTBridge (JavaScriptCore) diff --git a/React/Base/RCTBridgeDelegate.h b/React/Base/RCTBridgeDelegate.h index f70a024188bad1..1609544a94ff3c 100644 --- a/React/Base/RCTBridgeDelegate.h +++ b/React/Base/RCTBridgeDelegate.h @@ -94,11 +94,4 @@ - (void)loadSourceForBridge:(RCTBridge *)bridge withBlock:(RCTSourceLoadBlock)loadCallback; -/** - * Specifies the path to folder where additional bundles are located - * - * @experimental - */ -- (NSURL *)jsSegmentsDirectory; - @end diff --git a/React/CxxBridge/RCTCxxBridge.mm b/React/CxxBridge/RCTCxxBridge.mm index b5ce3026b2553a..e87196886cf1d8 100644 --- a/React/CxxBridge/RCTCxxBridge.mm +++ b/React/CxxBridge/RCTCxxBridge.mm @@ -1148,12 +1148,7 @@ - (void)executeApplicationScript:(NSData *)script [self->_performanceLogger markStopForTag:RCTPLRAMBundleLoad]; [self->_performanceLogger setValue:scriptStr->size() forTag:RCTPLRAMStartupCodeSize]; if (self->_reactInstance) { - NSString *jsSegmentsDirectory = [self.delegate respondsToSelector:@selector(jsSegmentsDirectory)] - ? [[self.delegate jsSegmentsDirectory].path stringByAppendingString:@"/"] - : nil; - auto registry = jsSegmentsDirectory != nil - ? RAMBundleRegistry::multipleBundlesRegistry(std::move(ramBundle), JSIndexedRAMBundle::buildFactory()) - : RAMBundleRegistry::singleBundleRegistry(std::move(ramBundle)); + auto registry = RAMBundleRegistry::multipleBundlesRegistry(std::move(ramBundle), JSIndexedRAMBundle::buildFactory()); self->_reactInstance->loadRAMBundle(std::move(registry), std::move(scriptStr), sourceUrlStr.UTF8String, !async); } @@ -1214,6 +1209,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 From a47431ed74f0b7b2a03ca48e84f2243d08ef3bdd Mon Sep 17 00:00:00 2001 From: Alex Dvornikov Date: Thu, 9 Nov 2017 11:55:41 -0800 Subject: [PATCH 12/50] Adopt split segments registration approach on Android Differential Revision: D6284863 fbshipit-source-id: 0df6b90eb0cbeab4c8a2b11f1e4dcbd5d5dfab72 --- .../facebook/react/bridge/CatalystInstance.java | 3 +++ .../react/bridge/CatalystInstanceImpl.java | 7 ++++--- .../facebook/react/bridge/JSBundleLoader.java | 15 --------------- .../main/jni/react/jni/CatalystInstanceImpl.cpp | 17 ++++------------- .../main/jni/react/jni/CatalystInstanceImpl.h | 8 +++----- ReactCommon/cxxreact/Instance.cpp | 2 +- 6 files changed, 15 insertions(+), 37 deletions(-) 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 960f252917cc76..f9b883c3532a2f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java @@ -210,8 +210,9 @@ private native void initializeBridge( jniSetSourceURL(remoteURL); } - /* package */ void setJsSegmentsDirectory(String directoryPath) { - jniSetJsSegmentsDirectory(directoryPath); + @Override + public void registerSegment(int segmentId, String path) { + jniRegisterSegment(segmentId, path); } /* package */ void loadScriptFromAssets(AssetManager assetManager, String assetURL, boolean loadSynchronously) { @@ -225,7 +226,7 @@ private native void initializeBridge( } private native void jniSetSourceURL(String sourceURL); - private native void jniSetJsSegmentsDirectory(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 d2f3aa566d7367..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 segments directory before executing - * application script. - */ - public static JSBundleLoader createSplitBundlesLoader( - final String jsSegmentsDirectory, final JSBundleLoader delegate) { - return new JSBundleLoader() { - @Override - public String loadScript(CatalystInstanceImpl instance) { - instance.setJsSegmentsDirectory(jsSegmentsDirectory); - 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/jni/react/jni/CatalystInstanceImpl.cpp b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp index 4ca32b7b9c44b5..abac4d1b19e081 100644 --- a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp +++ b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp @@ -100,7 +100,7 @@ void CatalystInstanceImpl::registerNatives() { makeNativeMethod("initializeBridge", CatalystInstanceImpl::initializeBridge), makeNativeMethod("jniExtendNativeModules", CatalystInstanceImpl::extendNativeModules), makeNativeMethod("jniSetSourceURL", CatalystInstanceImpl::jniSetSourceURL), - makeNativeMethod("jniSetJsSegmentsDirectory", CatalystInstanceImpl::jniSetJsSegmentsDirectory), + makeNativeMethod("jniRegisterSegment", CatalystInstanceImpl::jniRegisterSegment), makeNativeMethod("jniLoadScriptFromAssets", CatalystInstanceImpl::jniLoadScriptFromAssets), makeNativeMethod("jniLoadScriptFromFile", CatalystInstanceImpl::jniLoadScriptFromFile), makeNativeMethod("jniCallJSFunction", CatalystInstanceImpl::jniCallJSFunction), @@ -177,8 +177,8 @@ void CatalystInstanceImpl::jniSetSourceURL(const std::string& sourceURL) { instance_->setSourceURL(sourceURL); } -void CatalystInstanceImpl::jniSetJsSegmentsDirectory(const std::string& directoryPath) { - jsSegmentsDirectory_ = directoryPath; +void CatalystInstanceImpl::jniRegisterSegment(int segmentId, const std::string& path) { + instance_->registerBundle((uint32_t)segmentId, path); } void CatalystInstanceImpl::jniLoadScriptFromAssets( @@ -208,16 +208,7 @@ void CatalystInstanceImpl::jniLoadScriptFromFile(const std::string& fileName, const std::string& sourceURL, bool loadSynchronously) { if (Instance::isIndexedRAMBundle(fileName.c_str())) { - auto bundle = folly::make_unique(fileName.c_str()); - auto script = bundle->getStartupCode(); - auto registry = jsSegmentsDirectory_.empty() - ? RAMBundleRegistry::singleBundleRegistry(std::move(bundle)) - : RAMBundleRegistry::multipleBundlesRegistry(std::move(bundle), JSIndexedRAMBundle::buildFactory()); - instance_->loadRAMBundle( - std::move(registry), - std::move(script), - sourceURL, - loadSynchronously); + instance_->loadRAMBundleFromFile(fileName, sourceURL, loadSynchronously); } else { std::unique_ptr script; RecoverableError::runRethrowingAsRecoverable( diff --git a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h index 01abcd87136ec7..8a94c8cc9f3807 100644 --- a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h +++ b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h @@ -60,10 +60,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 jniSetJsSegmentsDirectory(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,8 +74,6 @@ class CatalystInstanceImpl : public jni::HybridClass { jlong getJavaScriptContext(); void handleMemoryPressure(int pressureLevel); - std::string jsSegmentsDirectory_; - // This should be the only long-lived strong reference, but every C++ class // will have a weak reference. std::shared_ptr instance_; diff --git a/ReactCommon/cxxreact/Instance.cpp b/ReactCommon/cxxreact/Instance.cpp index bdf1fce1eee280..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 = RAMBundleRegistry::singleBundleRegistry(std::move(bundle)); + auto registry = RAMBundleRegistry::multipleBundlesRegistry(std::move(bundle), JSIndexedRAMBundle::buildFactory()); loadRAMBundle( std::move(registry), std::move(startupScript), From 780938170b0add35e6a4151892154fa0aa5f6b57 Mon Sep 17 00:00:00 2001 From: Jessica Cao Date: Thu, 9 Nov 2017 12:45:12 -0800 Subject: [PATCH 13/50] Backed out changeset eadb184eacdf Reviewed By: fkgozali, hramos Differential Revision: D6287083 fbshipit-source-id: 43c6e43a9d5411e71f51824f9443559b4e0a47e2 --- Libraries/Alert/Alert.js | 9 ++++----- Libraries/Alert/AlertIOS.js | 12 +++++------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/Libraries/Alert/Alert.js b/Libraries/Alert/Alert.js index 6598175c0825d3..40666f70e35076 100644 --- a/Libraries/Alert/Alert.js +++ b/Libraries/Alert/Alert.js @@ -16,7 +16,6 @@ const NativeModules = require('NativeModules'); const Platform = require('Platform'); import type { AlertType, AlertButtonStyle } from 'AlertIOS'; -import type { Fbt } from 'fbt'; export type Buttons = Array<{ text?: string, @@ -80,8 +79,8 @@ type Options = { class Alert { static alert( - title: ?string | ?Fbt, - message?: ?string | ?Fbt, + title: ?string, + message?: ?string, buttons?: Buttons, options?: Options, type?: AlertType, @@ -105,8 +104,8 @@ class Alert { class AlertAndroid { static alert( - title: ?string | ?Fbt, - message?: ?string | ?Fbt, + title: ?string, + message?: ?string, buttons?: Buttons, options?: Options, ): void { diff --git a/Libraries/Alert/AlertIOS.js b/Libraries/Alert/AlertIOS.js index 933df8512a3b95..375a4db56c96a2 100644 --- a/Libraries/Alert/AlertIOS.js +++ b/Libraries/Alert/AlertIOS.js @@ -12,9 +12,7 @@ */ 'use strict'; -const RCTAlertManager = require('NativeModules').AlertManager; - -import type { Fbt } from 'fbt'; +var RCTAlertManager = require('NativeModules').AlertManager; /** * An Alert button type @@ -135,8 +133,8 @@ class AlertIOS { * ); */ static alert( - title: ?string | ?Fbt, - message?: ?string | ?Fbt, + title: ?string, + message?: ?string, callbackOrButtons?: ?(() => void) | ButtonsArray, type?: AlertType, ): void { @@ -194,8 +192,8 @@ class AlertIOS { * ); */ static prompt( - title: ?string | ?Fbt, - message?: ?string | ?Fbt, + title: ?string, + message?: ?string, callbackOrButtons?: ?((text: string) => void) | ButtonsArray, type?: ?AlertType = 'plain-text', defaultValue?: string, From 1f40c95076297258a4194fd9c1b5af7002187c99 Mon Sep 17 00:00:00 2001 From: Alexey Lang Date: Thu, 9 Nov 2017 12:58:05 -0800 Subject: [PATCH 14/50] Fix sections that come from React Fiber Reviewed By: fkgozali Differential Revision: D6235187 fbshipit-source-id: 55a49da9d81204f7a6199420beca1b096f7ea212 --- Libraries/Core/InitializeCore.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Libraries/Core/InitializeCore.js b/Libraries/Core/InitializeCore.js index 8a4e2218767836..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); } From e04f82ce2b482124121d8845fcdd8f94b8850d64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ramos?= Date: Thu, 9 Nov 2017 13:18:53 -0800 Subject: [PATCH 15/50] Fix website deploys on master Summary: Use newer CircleCI 2.0 environment variable names, being consistent with CircleCI config. Closes https://github.com/facebook/react-native/pull/16778 Differential Revision: D6288751 Pulled By: hramos fbshipit-source-id: 079ffaaea1ed3b715a12b07ed7738750672eee4e --- website/publish-gh-pages.js | 177 +++++++++++++++++++----------------- 1 file changed, 94 insertions(+), 83 deletions(-) diff --git a/website/publish-gh-pages.js b/website/publish-gh-pages.js index d31c683c17a171..7ceea38ebb3d7a 100644 --- a/website/publish-gh-pages.js +++ b/website/publish-gh-pages.js @@ -25,6 +25,7 @@ const { const CIRCLE_BRANCH = process.env.CIRCLE_BRANCH; const CIRCLE_PROJECT_USERNAME = process.env.CIRCLE_PROJECT_USERNAME; const CI_PULL_REQUEST = process.env.CI_PULL_REQUEST; +const CIRCLE_PR_USERNAME = process.env.CIRCLE_PR_USERNAME; const GIT_USER = process.env.GIT_USER; const remoteBranch = `https://${GIT_USER}@github.com/facebook/react-native.git`; @@ -33,6 +34,16 @@ if (!which('git')) { exit(1); } +if (CIRCLE_PR_USERNAME) { + echo('Skipping website deployment, this build was triggered from a commit in a pull request.'); + exit(0); +} + +if (CIRCLE_PROJECT_USERNAME !== 'facebook') { + echo('Skipping website deployment, this build was not triggered by a commit on the Facebook org.'); + exit(0); +} + let version; let areVersionlessSectionsToBeDeployed = false; if (CIRCLE_BRANCH.indexOf('-stable') !== -1) { @@ -45,107 +56,107 @@ if (CIRCLE_BRANCH.indexOf('-stable') !== -1) { rm('-rf', 'build'); mkdir('-p', 'build'); // if current commit is tagged "latest" we do a release to gh-pages root +echo('Current commit:'); const currentCommit = exec('git rev-parse HEAD').stdout.trim(); +echo('Searching for commit tagged "latest"...'); const latestTagCommit = exec('git ls-remote origin latest').stdout.split(/\s/)[0]; // pass along which branch contains latest version so that gh-pages root could mark it as latest +echo(`Searching for branch that contains commit ${latestTagCommit}...`); const branchWithLatestTag = exec(`git branch -r --contains ${latestTagCommit}`).stdout.split('/')[1]; let latestVersion = ''; if (branchWithLatestTag.indexOf('-stable') !== -1) { latestVersion = branchWithLatestTag.slice(0, branchWithLatestTag.indexOf('-stable')); } -if (!CI_PULL_REQUEST && CIRCLE_PROJECT_USERNAME === 'facebook') { - echo(`Building branch ${version}, preparing to push to gh-pages`); - // if code is running in a branch in CI, commit changes to gh-pages branch - cd('build'); - rm('-rf', 'react-native-gh-pages'); +echo(`Building static website based on the ${version === 'next' ? 'master' : version} branch, preparing to push assets to GitHub Pages via the 'gh-pages' branch)...`); +// if code is running in a branch in CI, commit changes to gh-pages branch +cd('build'); +rm('-rf', 'react-native-gh-pages'); - if (exec(`git clone ${remoteBranch} react-native-gh-pages`).code !== 0) { - echo('Error: Git clone failed'); - exit(1); - } +if (exec(`git clone ${remoteBranch} react-native-gh-pages`).code !== 0) { + echo('Error: Git clone failed'); + exit(1); +} + +cd('react-native-gh-pages'); + +if (exec('git checkout origin/gh-pages').code + + exec('git checkout -b gh-pages').code + + exec('git branch --set-upstream-to=origin/gh-pages').code !== 0 + ) { + echo('Error: Git checkout gh-pages failed'); + exit(1); +} +cd('releases'); +let releasesFolders = ls('-d', '*'); +cd('..'); +let versions = releasesFolders.filter(name => name !== 'next'); +if (version !== 'next' && versions.indexOf(version) === -1) { + versions.push(version); +} - cd('react-native-gh-pages'); +versions.sort(semverCmp).reverse(); - if (exec('git checkout origin/gh-pages').code + - exec('git checkout -b gh-pages').code + - exec('git branch --set-upstream-to=origin/gh-pages').code !== 0 - ) { - echo('Error: Git checkout gh-pages failed'); +// generate to releases/XX when branch name indicates that it is some sort of release +if (version) { + echo(`------------ DEPLOYING /releases/${version}`); + rm('-rf', `releases/${version}`); + mkdir('-p', `releases/${version}`); + cd('../..'); + if (exec(`RN_DEPLOYMENT_PATH=releases/${version} RN_VERSION=${version} RN_LATEST_VERSION=${latestVersion} \ + RN_AVAILABLE_DOCS_VERSIONS=${versions.join(',')} node server/generate.js`).code !== 0) { + echo('Error: Generating HTML failed'); exit(1); } - cd('releases'); - let releasesFolders = ls('-d', '*'); - cd('..'); - let versions = releasesFolders.filter(name => name !== 'next'); - if (version !== 'next' && versions.indexOf(version) === -1) { - versions.push(version); + cd('build/react-native-gh-pages'); + // blog, showcase, support are copied separately + let toCopy = ls('../react-native') + .filter(file => (file !== 'blog') && (file !== 'showcase.html') && (file !== 'support.html')) + .map(file => `../react-native/${file}`); + cp('-R', toCopy, `releases/${version}`); + // versions.html is located in root of website and updated with every release + cp('../react-native/versions.html', '.'); +} +// generate to root folder when commit is tagged as latest, i.e. stable and needs to be shown at the root of repo +if (currentCommit === latestTagCommit) { + echo('------------ DEPLOYING latest'); + // leave only releases and blog folder + rm('-rf', ls('*').filter(name => (name !== 'releases') && (name !== 'blog') && (name !== 'showcase.html') && (name !== 'support.html'))); + cd('../..'); + if (exec(`RN_VERSION=${version} RN_LATEST_VERSION=${latestVersion} \ + RN_AVAILABLE_DOCS_VERSIONS=${versions} node server/generate.js`).code !== 0) { + echo('Error: Generating HTML failed'); + exit(1); } - - versions.sort(semverCmp).reverse(); - - // generate to releases/XX when branch name indicates that it is some sort of release - if (version) { - echo(`------------ DEPLOYING /releases/${version}`); - rm('-rf', `releases/${version}`); - mkdir('-p', `releases/${version}`); - cd('../..'); - if (exec(`RN_DEPLOYMENT_PATH=releases/${version} RN_VERSION=${version} RN_LATEST_VERSION=${latestVersion} \ - RN_AVAILABLE_DOCS_VERSIONS=${versions.join(',')} node server/generate.js`).code !== 0) { - echo('Error: Generating HTML failed'); + cd('build/react-native-gh-pages'); + // blog, showcase, support are copied separately + let toCopy = ls('../react-native') + .filter(file => (file !== 'blog') && (file !== 'showcase.html') && (file !== 'support.html')) + .map(file => `../react-native/${file}`); + cp('-R', toCopy, '.'); +} +// blog, showcase, support are versionless, we always build them in root file +if (areVersionlessSectionsToBeDeployed) { + echo('------------ COPYING blog'); + rm('-rf', 'blog'); + cp('-R', '../react-native/blog', '.'); + echo('------------ COPYING showcase'); + cp('../react-native/showcase.html', '.'); + echo('------------ COPYING support'); + cp('../react-native/support.html', '.'); +} +if (currentCommit === latestTagCommit || version) { + exec('git status'); + exec('git add -A .'); + if (exec('git diff-index --quiet HEAD --').code !== 0) { + if (exec(`git commit -m "Updated docs for ${version}"`).code !== 0) { + echo('Error: Git commit gh-pages failed'); exit(1); } - cd('build/react-native-gh-pages'); - // blog, showcase, support are copied separately - let toCopy = ls('../react-native') - .filter(file => (file !== 'blog') && (file !== 'showcase.html') && (file !== 'support.html')) - .map(file => `../react-native/${file}`); - cp('-R', toCopy, `releases/${version}`); - // versions.html is located in root of website and updated with every release - cp('../react-native/versions.html', '.'); - } - // generate to root folder when commit is tagged as latest, i.e. stable and needs to be shown at the root of repo - if (currentCommit === latestTagCommit) { - echo('------------ DEPLOYING latest'); - // leave only releases and blog folder - rm('-rf', ls('*').filter(name => (name !== 'releases') && (name !== 'blog') && (name !== 'showcase.html') && (name !== 'support.html'))); - cd('../..'); - if (exec(`RN_VERSION=${version} RN_LATEST_VERSION=${latestVersion} \ - RN_AVAILABLE_DOCS_VERSIONS=${versions} node server/generate.js`).code !== 0) { - echo('Error: Generating HTML failed'); + if (exec('git push origin gh-pages').code !== 0) { + echo('Error: Git push gh-pages failed'); exit(1); } - cd('build/react-native-gh-pages'); - // blog, showcase, support are copied separately - let toCopy = ls('../react-native') - .filter(file => (file !== 'blog') && (file !== 'showcase.html') && (file !== 'support.html')) - .map(file => `../react-native/${file}`); - cp('-R', toCopy, '.'); - } - // blog, showcase, support are versionless, we always build them in root file - if (areVersionlessSectionsToBeDeployed) { - echo('------------ COPYING blog'); - rm('-rf', 'blog'); - cp('-R', '../react-native/blog', '.'); - echo('------------ COPYING showcase'); - cp('../react-native/showcase.html', '.'); - echo('------------ COPYING support'); - cp('../react-native/support.html', '.'); - } - if (currentCommit === latestTagCommit || version) { - exec('git status'); - exec('git add -A .'); - if (exec('git diff-index --quiet HEAD --').code !== 0) { - if (exec(`git commit -m "Updated docs for ${version}"`).code !== 0) { - echo('Error: Git commit gh-pages failed'); - exit(1); - } - if (exec('git push origin gh-pages').code !== 0) { - echo('Error: Git push gh-pages failed'); - exit(1); - } - } - echo('------------ gh-pages updated'); } - + echo('------------ gh-pages updated'); } From 45185947ee5f1672fb00765a8b32a7100fd0c1bd Mon Sep 17 00:00:00 2001 From: Douglas Date: Thu, 9 Nov 2017 13:41:29 -0800 Subject: [PATCH 16/50] Fix tvOS compile issues; enable TVEventHandler in Modal (fix #15389) Summary: **Motivation** Fix an issue (#15389) where `TVEventHandler` would not work when a modal was visible. The solution adds the gesture recognizers from the native `RCTTVRemoteHandler` to the native modal view (except for the menu button recognizer, which still needs special handling in modals). This PR also fixes some breakages in compiling React Native for tvOS. **Test plan** Compilation fixes should enable tvOS compile test to pass in Travis CI. The modal fix can be tested with the following component, modified from the original source in #15389 . ``` javascript import React, { Component } from 'react'; import ReactNative from 'ReactNative'; import { Text, View, StyleSheet, TouchableHighlight, TVEventHandler, Modal, } from 'react-native'; export default class Events extends Component { constructor(props) { super(props); this.state = { modalVisible: false, }; this._tvEventHandler = new TVEventHandler(); } _enableTVEventHandler() { this._tvEventHandler.enable(this, (cmp, evt) => { const myTag = ReactNative.findNodeHandle(cmp); console.log('Event.js TVEventHandler: ', evt.eventType); // if (evt.eventType !== 'blur' && evt.eventType !== 'focus') { // console.log('Event.js TVEventHandler: ', evt.eventType); // } }); } _disableTVEventHandler() { if (this._tvEventHandler) { this._tvEventHandler.disable(); delete this._tvEventHandler; } } componentDidMount() { this._enableTVEventHandler(); } componentWillUnmount() { this._disableTVEventHandler(); } _renderRow() { return ( { Array.from({ length: 7 }).map((_, index) => { return ( { this.setState({ modalVisible: !this.state.modalVisible }); }} > { index } ); }) } ); } onTVEvent(cmp, evt) { console.log('Modal.js TVEventHandler: ', evt.eventType); } hideModal() { this.setState({ modalVisible: false }); } render() { return ( this.hideModal()}> { this._renderRow() } { this._renderRow() } { this._renderRow() } { this._renderRow() } ); } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: 'darkslategrey', }, row: { flexDirection: 'row', padding: 30, }, item: { width: 200, height: 100, borderColor: 'cyan', borderWidth: 2, margin: 30, alignItems: 'center', justifyContent: 'center', }, itemText: { fontSize: 40, color: 'cyan', }, modal: { flex: 1, backgroundColor: 'steelblue', }, }); ``` **Release Notes** After this change, the `onRequestClose` property will be required for a `Modal` in Apple TV. Closes https://github.com/facebook/react-native/pull/16076 Differential Revision: D6288801 Pulled By: hramos fbshipit-source-id: 446ae94a060387324aa9e528bd93cdabc9b5b37f --- .../Text/RCTText.xcodeproj/project.pbxproj | 1 + RNTester/RNTester.xcodeproj/project.pbxproj | 97 +++++++++++++------ .../AppIcon.appiconset/Contents.json | 5 + RNTester/js/ListExampleShared.js | 3 + RNTester/js/ModalExample.js | 31 ++++-- React/Base/RCTRootView.m | 4 +- React/Base/RCTTVRemoteHandler.h | 20 +++- React/Base/RCTTVRemoteHandler.m | 91 +++++++++++------ React/React.xcodeproj/project.pbxproj | 10 +- React/Views/RCTModalHostView.h | 2 + React/Views/RCTModalHostView.m | 10 ++ .../ios/HelloWorld.xcodeproj/project.pbxproj | 70 +++++++++++-- 12 files changed, 266 insertions(+), 78 deletions(-) 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/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/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/React/Base/RCTRootView.m b/React/Base/RCTRootView.m index 980e9e01ee8fda..4a5e53c650ce51 100644 --- a/React/Base/RCTRootView.m +++ b/React/Base/RCTRootView.m @@ -91,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 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/React.xcodeproj/project.pbxproj b/React/React.xcodeproj/project.pbxproj index 0c7f8e3c2f2559..b64ab270c76787 100644 --- a/React/React.xcodeproj/project.pbxproj +++ b/React/React.xcodeproj/project.pbxproj @@ -263,6 +263,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,7 +524,6 @@ 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 */; }; @@ -1299,6 +1302,7 @@ 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 */, @@ -2210,7 +2214,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 */, @@ -3997,6 +4002,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 */, 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/local-cli/templates/HelloWorld/ios/HelloWorld.xcodeproj/project.pbxproj b/local-cli/templates/HelloWorld/ios/HelloWorld.xcodeproj/project.pbxproj index 606ef9c915635c..a7c51152b93bbf 100644 --- a/local-cli/templates/HelloWorld/ios/HelloWorld.xcodeproj/project.pbxproj +++ b/local-cli/templates/HelloWorld/ios/HelloWorld.xcodeproj/project.pbxproj @@ -25,14 +25,14 @@ 2D02E4BC1E0B4A80006451C7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; 2D02E4BD1E0B4A84006451C7 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 2D02E4BF1E0B4AB3006451C7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; - 2D02E4C21E0B4AEC006451C7 /* libRCTAnimation-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation-tvOS.a */; }; + 2D02E4C21E0B4AEC006451C7 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation.a */; }; 2D02E4C31E0B4AEC006451C7 /* libRCTImage-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E841DF850E9000B6D8A /* libRCTImage-tvOS.a */; }; 2D02E4C41E0B4AEC006451C7 /* libRCTLinking-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E881DF850E9000B6D8A /* libRCTLinking-tvOS.a */; }; 2D02E4C51E0B4AEC006451C7 /* libRCTNetwork-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E8C1DF850E9000B6D8A /* libRCTNetwork-tvOS.a */; }; 2D02E4C61E0B4AEC006451C7 /* libRCTSettings-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E901DF850E9000B6D8A /* libRCTSettings-tvOS.a */; }; 2D02E4C71E0B4AEC006451C7 /* libRCTText-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E941DF850E9000B6D8A /* libRCTText-tvOS.a */; }; 2D02E4C81E0B4AEC006451C7 /* libRCTWebSocket-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E991DF850E9000B6D8A /* libRCTWebSocket-tvOS.a */; }; - 2D02E4C91E0B4AEC006451C7 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3EA31DF850E9000B6D8A /* libReact.a */; }; + 2D16E6881FA4F8E400B85C8A /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2D16E6891FA4F8E400B85C8A /* libReact.a */; }; 2DCD954D1E0B4F2C00145EB5 /* HelloWorldTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* HelloWorldTests.m */; }; 5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */; }; 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; }; @@ -110,6 +110,27 @@ remoteGlobalIDString = 2D02E47A1E0B4A5D006451C7; remoteInfo = "HelloWorld-tvOS"; }; + 2D16E6711FA4F8DC00B85C8A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = ADD01A681E09402E00F6D226; + remoteInfo = "RCTBlob-tvOS"; + }; + 2D16E6831FA4F8DC00B85C8A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3DBE0D001F3B181A0099AA32; + remoteInfo = fishhook; + }; + 2D16E6851FA4F8DC00B85C8A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3DBE0D0D1F3B181C0099AA32; + remoteInfo = "fishhook-tvOS"; + }; 3DAD3E831DF850E9000B6D8A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; @@ -260,6 +281,7 @@ 146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = ""; }; 2D02E47B1E0B4A5D006451C7 /* HelloWorld-tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "HelloWorld-tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 2D02E4901E0B4A5D006451C7 /* HelloWorld-tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "HelloWorld-tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 2D16E6891FA4F8E400B85C8A /* libReact.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libReact.a; sourceTree = BUILT_PRODUCTS_DIR; }; 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = ""; }; 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = ""; }; 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = ""; }; @@ -299,8 +321,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 2D02E4C91E0B4AEC006451C7 /* libReact.a in Frameworks */, - 2D02E4C21E0B4AEC006451C7 /* libRCTAnimation-tvOS.a in Frameworks */, + 2D16E6881FA4F8E400B85C8A /* libReact.a in Frameworks */, + 2D02E4C21E0B4AEC006451C7 /* libRCTAnimation.a in Frameworks */, 2D02E4C31E0B4AEC006451C7 /* libRCTImage-tvOS.a in Frameworks */, 2D02E4C41E0B4AEC006451C7 /* libRCTLinking-tvOS.a in Frameworks */, 2D02E4C51E0B4AEC006451C7 /* libRCTNetwork-tvOS.a in Frameworks */, @@ -393,6 +415,8 @@ children = ( 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */, 3DAD3E991DF850E9000B6D8A /* libRCTWebSocket-tvOS.a */, + 2D16E6841FA4F8DC00B85C8A /* libfishhook.a */, + 2D16E6861FA4F8DC00B85C8A /* libfishhook-tvOS.a */, ); name = Products; sourceTree = ""; @@ -415,7 +439,6 @@ isa = PBXGroup; children = ( 146834041AC3E56700842450 /* libReact.a */, - 3DAD3EA31DF850E9000B6D8A /* libReact.a */, 3DAD3EA51DF850E9000B6D8A /* libyoga.a */, 3DAD3EA71DF850E9000B6D8A /* libyoga.a */, 3DAD3EA91DF850E9000B6D8A /* libcxxreact.a */, @@ -427,11 +450,19 @@ name = Products; sourceTree = ""; }; + 2D16E6871FA4F8E400B85C8A /* Frameworks */ = { + isa = PBXGroup; + children = ( + 2D16E6891FA4F8E400B85C8A /* libReact.a */, + ); + name = Frameworks; + sourceTree = ""; + }; 5E91572E1DD0AC6500FF2AA8 /* Products */ = { isa = PBXGroup; children = ( 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */, - 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation-tvOS.a */, + 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation.a */, ); name = Products; sourceTree = ""; @@ -480,6 +511,7 @@ 832341AE1AAA6A7D00B99B32 /* Libraries */, 00E356EF1AD99517003FC87E /* HelloWorldTests */, 83CBBA001A601CBA00E9B192 /* Products */, + 2D16E6871FA4F8E400B85C8A /* Frameworks */, ); indentWidth = 2; sourceTree = ""; @@ -501,6 +533,7 @@ isa = PBXGroup; children = ( ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */, + 2D16E6721FA4F8DC00B85C8A /* libRCTBlob-tvOS.a */, ); name = Products; sourceTree = ""; @@ -732,6 +765,27 @@ remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + 2D16E6721FA4F8DC00B85C8A /* libRCTBlob-tvOS.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libRCTBlob-tvOS.a"; + remoteRef = 2D16E6711FA4F8DC00B85C8A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 2D16E6841FA4F8DC00B85C8A /* libfishhook.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libfishhook.a; + remoteRef = 2D16E6831FA4F8DC00B85C8A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 2D16E6861FA4F8DC00B85C8A /* libfishhook-tvOS.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libfishhook-tvOS.a"; + remoteRef = 2D16E6851FA4F8DC00B85C8A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; 3DAD3E841DF850E9000B6D8A /* libRCTImage-tvOS.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -830,10 +884,10 @@ remoteRef = 5E9157321DD0AC6500FF2AA8 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation-tvOS.a */ = { + 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = "libRCTAnimation-tvOS.a"; + path = libRCTAnimation.a; remoteRef = 5E9157341DD0AC6500FF2AA8 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; From a329e968fc3c67732e23ec6ff93a9bfe4530f61c Mon Sep 17 00:00:00 2001 From: Yujie Liu Date: Thu, 9 Nov 2017 18:48:11 -0800 Subject: [PATCH 17/50] resolve iOS assets from embedded bundle path for iOS platform Reviewed By: zahanm Differential Revision: D6193907 fbshipit-source-id: 09c76a5c3d6a7777a9a823c21bfcc0fe344bc83e --- Libraries/Image/AssetSourceResolver.js | 22 +++++++++++++- Libraries/Image/resolveAssetSource.js | 41 +++++++++++++++++--------- 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/Libraries/Image/AssetSourceResolver.js b/Libraries/Image/AssetSourceResolver.js index 2183d1a98904d2..a240b5af71601e 100644 --- a/Libraries/Image/AssetSourceResolver.js +++ b/Libraries/Image/AssetSourceResolver.js @@ -52,12 +52,19 @@ class AssetSourceResolver { serverUrl: ?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, jsbundleUrl: ?string, asset: PackagerAsset) { + constructor(serverUrl: ?string, + jsbundleUrl: ?string, + embeddedBundleUrl: ?string, + asset: PackagerAsset + ) { this.serverUrl = serverUrl; this.jsbundleUrl = jsbundleUrl; + this.embeddedBundleUrl = embeddedBundleUrl; this.asset = asset; } @@ -69,6 +76,10 @@ class AssetSourceResolver { return !!this.jsbundleUrl; } + canLoadFromEmbeddedBundledLocation(): boolean { + return !!this.embeddedBundleUrl; + } + defaultAsset(): ResolvedAssetSource { if (this.isLoadedFromServer()) { return this.assetServerURL(); @@ -112,6 +123,15 @@ class AssetSourceResolver { 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)); + } + /** * The default location of assets bundled with the app, located by * resource identifier diff --git a/Libraries/Image/resolveAssetSource.js b/Libraries/Image/resolveAssetSource.js index 18350ce2c53493..aba63045e4d18b 100644 --- a/Libraries/Image/resolveAssetSource.js +++ b/Libraries/Image/resolveAssetSource.js @@ -19,7 +19,7 @@ const NativeModules = require('NativeModules'); import type { ResolvedAssetSource } from 'AssetSourceResolver'; -let _customSourceTransformer, _serverURL, _scriptURL; +let _customSourceTransformer, _serverURL, _scriptURL, _embeddedBundleURL; function getDevServerURL(): ?string { if (_serverURL === undefined) { @@ -36,30 +36,38 @@ function getDevServerURL(): ?string { return _serverURL; } -function getScriptURL(): ?string { - if (_scriptURL === undefined) { - const scriptURL = NativeModules.SourceCode.scriptURL; - if (!scriptURL) { - // scriptURL is falsy, we have nothing to go on here - _scriptURL = null; - return _scriptURL; - } +function _coerceLocalScriptURL(scriptURL: ?string): ?string { + if (scriptURL) { if (scriptURL.startsWith('assets://')) { // android: running from within assets, no offline path to use - _scriptURL = null; - return _scriptURL; + return null; } - _scriptURL = scriptURL.substring(0, scriptURL.lastIndexOf('/') + 1); + scriptURL = scriptURL.substring(0, scriptURL.lastIndexOf('/') + 1); if (!scriptURL.startsWith('file://')) { // 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. - _scriptURL = 'file://' + _scriptURL; + scriptURL = 'file://' + scriptURL; } } + return scriptURL; +} +function getScriptURL(): ?string { + if (_scriptURL === undefined) { + const scriptURL = NativeModules.SourceCode.scriptURL; + _scriptURL = _coerceLocalScriptURL(scriptURL); + } return _scriptURL; } +function getEmbeddedBundledURL(): ?string { + if (_embeddedBundleURL === undefined) { + const scriptURL = NativeModules.SourceCode.embeddedBundleURL; + _embeddedBundleURL = _coerceLocalScriptURL(scriptURL); + } + return _embeddedBundleURL; +} + function setCustomSourceTransformer( transformer: (resolver: AssetSourceResolver) => ResolvedAssetSource, ): void { @@ -80,7 +88,12 @@ function resolveAssetSource(source: any): ?ResolvedAssetSource { return null; } - const resolver = new AssetSourceResolver(getDevServerURL(), getScriptURL(), asset); + const resolver = new AssetSourceResolver( + getDevServerURL(), + getScriptURL(), + getEmbeddedBundledURL(), + asset, + ); if (_customSourceTransformer) { return _customSourceTransformer(resolver); } From 58c3bc490143b8d7831a00289e2565f49f5389ef Mon Sep 17 00:00:00 2001 From: Brian Solon Date: Thu, 9 Nov 2017 22:18:02 -0800 Subject: [PATCH 18/50] Fix typo in Image.android.js & Image.ios.js Summary: Fixing a typo. N/A [IOS] [MINOR] [Image] - Fixed a typo in an error message [ANDROID] [MINOR] [Image] - Fixed a typo in an error message Closes https://github.com/facebook/react-native/pull/16777 Differential Revision: D6295564 Pulled By: shergin fbshipit-source-id: eb6274701b6406f26b9eda1c35632cb2ce0392d7 --- Libraries/Image/Image.android.js | 2 +- Libraries/Image/Image.ios.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Libraries/Image/Image.android.js b/Libraries/Image/Image.android.js index b953d085515074..d0169794642f61 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 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..cc7aeec42430c7 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 absolute positioning.'); } return ( From 7fb3a9229df52bd45076470d059f245a8147cd2a Mon Sep 17 00:00:00 2001 From: Tim Wang Date: Fri, 10 Nov 2017 09:56:38 -0800 Subject: [PATCH 19/50] Fix Jest mocks for NetInfo module. Summary: Jest mock for `NetInfo.getConnectionInfo()` is missing. Tests are fail with error message: ``` TypeError: _reactNative.NetInfo.getConnectionInfo is not a function ``` And cleaned code in this files for unified code styles. Run test with usage of `NetInfo.getConnectionInfo()` [GENERAL] [BUGFIX] [jest/setup.js] - Fix Jest mocks for NetInfo module Closes https://github.com/facebook/react-native/pull/16722 Differential Revision: D6298133 Pulled By: hramos fbshipit-source-id: 589cf6fed93965e7a09823015f2793f5c68a9c3b --- jest/setup.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/jest/setup.js b/jest/setup.js index 9a04acb2316421..2f55f2bd2fc068 100644 --- a/jest/setup.js +++ b/jest/setup.js @@ -162,7 +162,7 @@ const mockNativeModules = { }, ImageLoader: { getSize: jest.fn( - (url) => new Promise(() => ({width: 320, height: 240})) + (url) => Promise.resolve({width: 320, height: 240}) ), prefetchImage: jest.fn(), }, @@ -179,11 +179,11 @@ const mockNativeModules = { Linking: { openURL: jest.fn(), canOpenURL: jest.fn( - () => new Promise((resolve) => resolve(true)) + () => Promise.resolve(true) ), addEventListener: jest.fn(), getInitialURL: jest.fn( - () => new Promise((resolve) => resolve()) + () => Promise.resolve() ), removeEventListener: jest.fn(), }, @@ -195,15 +195,23 @@ const mockNativeModules = { ModalFullscreenViewManager: {}, NetInfo: { fetch: jest.fn( - () => new Promise((resolve) => resolve()) + () => Promise.resolve() + ), + getConnectionInfo: jest.fn( + () => Promise.resolve() ), addEventListener: jest.fn(), + removeEventListener: jest.fn(), isConnected: { fetch: jest.fn( - () => new Promise((resolve) => resolve()) + () => Promise.resolve() ), addEventListener: jest.fn(), + removeEventListener: jest.fn(), }, + isConnectionExpensive: jest.fn( + () => Promise.resolve() + ), }, Networking: { sendRequest: jest.fn(), From eb0d6470e54663538610a70ab0bae9847eb33673 Mon Sep 17 00:00:00 2001 From: Caleb Meredith Date: Fri, 10 Nov 2017 21:03:52 -0800 Subject: [PATCH 20/50] Flow 0.59 xplat/js deploy Reviewed By: avikchaudhuri Differential Revision: D6300238 fbshipit-source-id: a6839fa2a9bbc50c3832a3f5b1cac2a6d2bd96b7 --- .flowconfig | 6 +-- Libraries/Animated/src/Easing.js | 41 +++++++++++++++++++ Libraries/CameraRoll/CameraRoll.js | 4 ++ Libraries/Experimental/WindowedListView.js | 5 +++ .../Lists/ListView/__mocks__/ListViewMock.js | 5 +++ Libraries/Share/Share.js | 4 +- Libraries/StyleSheet/StyleSheetValidation.js | 8 ++++ local-cli/templates/HelloWorld/_flowconfig | 6 +-- package.json | 2 +- 9 files changed, 72 insertions(+), 9 deletions(-) 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/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/CameraRoll/CameraRoll.js b/Libraries/CameraRoll/CameraRoll.js index 66d8bd3eb2bf81..b9da61a56db4b8 100644 --- a/Libraries/CameraRoll/CameraRoll.js +++ b/Libraries/CameraRoll/CameraRoll.js @@ -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/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/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/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/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/local-cli/templates/HelloWorld/_flowconfig b/local-cli/templates/HelloWorld/_flowconfig index d834b93707e493..9a069e497282f3 100644 --- a/local-cli/templates/HelloWorld/_flowconfig +++ b/local-cli/templates/HelloWorld/_flowconfig @@ -37,12 +37,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[a-z,_]*\\)?)\\) -suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(5[0-8]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[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[a-z,_]*\\)?)\\) +suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(5[0-9]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[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/package.json b/package.json index 364ce0fa0c1dd4..22e3f8ad30e9cd 100644 --- a/package.json +++ b/package.json @@ -208,7 +208,7 @@ "eslint-plugin-flowtype": "^2.33.0", "eslint-plugin-prettier": "2.1.1", "eslint-plugin-react": "^7.2.1", - "flow-bin": "^0.58.0", + "flow-bin": "^0.59.0", "jest": "21.3.0-beta.8", "prettier": "1.7.0", "react": "16.0.0", From 6d92046c56794a6a62bc07598545a23a7b53cdc0 Mon Sep 17 00:00:00 2001 From: Rafael Oleza Date: Sat, 11 Nov 2017 07:03:08 -0800 Subject: [PATCH 21/50] Fix dependencies script when its running with dev=false Reviewed By: alp Differential Revision: D6307190 fbshipit-source-id: 21f339ff9c24d58df2630cd6b957e7539880f001 --- local-cli/dependencies/dependencies.js | 1 + 1 file changed, 1 insertion(+) diff --git a/local-cli/dependencies/dependencies.js b/local-cli/dependencies/dependencies.js index f491e7f011f095..fc6b22c7b96cc6 100644 --- a/local-cli/dependencies/dependencies.js +++ b/local-cli/dependencies/dependencies.js @@ -34,6 +34,7 @@ function dependencies(argv, config, args, packagerInstance) { getPolyfills: config.getPolyfills, getTransformOptions: config.getTransformOptions, hasteImpl: config.hasteImpl, + postMinifyProcess: config.postMinifyProcess, transformModulePath: transformModulePath, extraNodeModules: config.extraNodeModules, verbose: config.verbose, From e75bd87a76726a9b075061ef76156705b3c1e872 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Sat, 11 Nov 2017 21:15:17 -0800 Subject: [PATCH 22/50] Introducing RCTSurfaceHostingComponent Summary: RCTSurfaceHostingComponent is ComponentKit component represents given Surface instance. Differential Revision: D6217104 fbshipit-source-id: 50805d97e744de24a188bc97b33de4709e785aae --- .../RCTSurfaceHostingComponent+Internal.h | 22 +++ .../RCTSurfaceHostingComponent.h | 22 +++ .../RCTSurfaceHostingComponent.mm | 104 +++++++++++++ .../RCTSurfaceHostingComponentController.h | 14 ++ .../RCTSurfaceHostingComponentController.mm | 143 ++++++++++++++++++ .../RCTSurfaceHostingComponentOptions.h | 22 +++ .../RCTSurfaceHostingComponentState.h | 22 +++ .../RCTSurfaceHostingComponentState.mm | 43 ++++++ 8 files changed, 392 insertions(+) create mode 100644 Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponent+Internal.h create mode 100644 Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponent.h create mode 100644 Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponent.mm create mode 100644 Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponentController.h create mode 100644 Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponentController.mm create mode 100644 Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponentOptions.h create mode 100644 Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponentState.h create mode 100644 Libraries/SurfaceHostingComponent/RCTSurfaceHostingComponentState.mm 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 From aa83b5a0ca30736b2800833bcc6149dcbe8436fa Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Sat, 11 Nov 2017 21:15:20 -0800 Subject: [PATCH 23/50] Introducing RCTSurfaceBackedComponent Summary: RCTSurfaceBackedComponent is ComponentKit component represents a React Native Surface created (and stored in the state) with given `bridge`, `moduleName`, and `properties`. Differential Revision: D6217103 fbshipit-source-id: 2849f68e1975562cd47851bda232e389705b4229 --- .../RCTSurfaceBackedComponent.h | 28 ++++++++ .../RCTSurfaceBackedComponent.mm | 68 +++++++++++++++++++ .../RCTSurfaceBackedComponentState.h | 20 ++++++ .../RCTSurfaceBackedComponentState.mm | 30 ++++++++ 4 files changed, 146 insertions(+) create mode 100644 Libraries/SurfaceBackedComponent/RCTSurfaceBackedComponent.h create mode 100644 Libraries/SurfaceBackedComponent/RCTSurfaceBackedComponent.mm create mode 100644 Libraries/SurfaceBackedComponent/RCTSurfaceBackedComponentState.h create mode 100644 Libraries/SurfaceBackedComponent/RCTSurfaceBackedComponentState.mm 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/Libraries/SurfaceBackedComponent/RCTSurfaceBackedComponentState.h b/Libraries/SurfaceBackedComponent/RCTSurfaceBackedComponentState.h new file mode 100644 index 00000000000000..819d927d0ea444 --- /dev/null +++ b/Libraries/SurfaceBackedComponent/RCTSurfaceBackedComponentState.h @@ -0,0 +1,20 @@ +/** + * 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 RCTSurface; + +@interface RCTSurfaceBackedComponentState: NSObject + +@property (atomic, readonly, strong) RCTSurface *surface; + ++ (instancetype)newWithSurface:(RCTSurface *)surface; + +@end 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 From d79e245d19f7f246322bc657b407198b15cb1b98 Mon Sep 17 00:00:00 2001 From: Wenjing Wang Date: Sun, 12 Nov 2017 12:52:19 -0800 Subject: [PATCH 24/50] AMA changes to support disk cache Reviewed By: fred2028 Differential Revision: D6295287 fbshipit-source-id: 70ae7dfba2edb36e758ad0e22916015038108d36 --- .../SwipeableRow/SwipeableListViewDataSource.js | 10 ++++++++++ 1 file changed, 10 insertions(+) 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; From 266ab7a0061c11c4da7ccde9e0d461c0d7331563 Mon Sep 17 00:00:00 2001 From: Chris Zheng Date: Sun, 12 Nov 2017 13:30:13 -0800 Subject: [PATCH 25/50] Pass scriptURL to RCTTestRunner Summary: Pass scriptURL to RCTTestRunner. If the scriptURL passed to RCTTestRunner is not nil, then RCTTestRunner will use it. else, RCTTestRunner will use whatever it has before. Differential Revision: D6215186 fbshipit-source-id: c3a5643021d60579fc8e60a69de150f6a4a39237 --- Libraries/RCTTest/RCTTestRunner.h | 8 +++++--- Libraries/RCTTest/RCTTestRunner.m | 8 +++++++- .../RCTRootViewIntegrationTests.m | 2 +- .../RNTesterIntegrationTests/RNTesterIntegrationTests.m | 2 +- RNTester/RNTesterIntegrationTests/RNTesterSnapshotTests.m | 2 +- 5 files changed, 15 insertions(+), 7 deletions(-) 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/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) { From 28d5d6baf1e6ac52e8672a653f56c3898e4e11d2 Mon Sep 17 00:00:00 2001 From: Kevin Gozali Date: Sun, 12 Nov 2017 22:48:56 -0800 Subject: [PATCH 26/50] Fix asset resolver url handling Summary: 1. file:// may get prepended to an http:// source URL during dev mode, making an invalid URL 2. the logic to detect `isLoadedFromFileSystem()` should've checked for file:// protocol to not get confused by http:// URL Reviewed By: zahanm Differential Revision: D6307187 fbshipit-source-id: e7e7a41bf721dd0601b0c1877e278e1e435ef5e2 --- Libraries/Image/AssetSourceResolver.js | 2 +- Libraries/Image/resolveAssetSource.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Libraries/Image/AssetSourceResolver.js b/Libraries/Image/AssetSourceResolver.js index a240b5af71601e..4b4e4117f35cba 100644 --- a/Libraries/Image/AssetSourceResolver.js +++ b/Libraries/Image/AssetSourceResolver.js @@ -73,7 +73,7 @@ class AssetSourceResolver { } isLoadedFromFileSystem(): boolean { - return !!this.jsbundleUrl; + return !!(this.jsbundleUrl && this.jsbundleUrl.startsWith('file://')); } canLoadFromEmbeddedBundledLocation(): boolean { diff --git a/Libraries/Image/resolveAssetSource.js b/Libraries/Image/resolveAssetSource.js index aba63045e4d18b..bb46279af4df3c 100644 --- a/Libraries/Image/resolveAssetSource.js +++ b/Libraries/Image/resolveAssetSource.js @@ -43,7 +43,7 @@ function _coerceLocalScriptURL(scriptURL: ?string): ?string { return null; } scriptURL = scriptURL.substring(0, scriptURL.lastIndexOf('/') + 1); - if (!scriptURL.startsWith('file://')) { + 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. scriptURL = 'file://' + scriptURL; From 4894ac430d6df1118ce48f644fd8cf5bfce6344f Mon Sep 17 00:00:00 2001 From: Dmitry Zakharov Date: Tue, 14 Nov 2017 04:35:52 -0800 Subject: [PATCH 27/50] Remove splitting to BridgeCorePackage and ReactNativePackage. Reviewed By: kathryngray Differential Revision: D6286129 fbshipit-source-id: 8d75e610291402ccbffb137ce46e64d11826b950 --- .../com/facebook/react/BridgeCorePackage.java | 132 ------------------ .../facebook/react/CoreModulesPackage.java | 81 ++--------- .../facebook/react/ReactInstanceManager.java | 10 +- .../react/ReactNativeCorePackage.java | 114 --------------- 4 files changed, 17 insertions(+), 320 deletions(-) delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/BridgeCorePackage.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/ReactNativeCorePackage.java 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 aa317e7503bb4a..0e06dd854916b9 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -272,16 +272,16 @@ public static ReactInstanceManagerBuilder builder() { mMinNumShakes = minNumShakes; synchronized (mPackages) { PrinterHolder.getPrinter().logMessage(ReactDebugOverlayTags.RN_CORE, "RNCore: Use Split Packages"); - mPackages.add(new BridgeCorePackage(this, mBackBtnHandler)); - if (mUseDeveloperSupport) { - mPackages.add(new DebugCorePackage()); - } mPackages.add( - new ReactNativeCorePackage( + new CoreModulesPackage( this, + mBackBtnHandler, mUIImplementationProvider, mLazyViewManagersEnabled, mMinTimeLeftInFrameForNonBatchedOperationMs)); + if (mUseDeveloperSupport) { + mPackages.add(new DebugCorePackage()); + } mPackages.addAll(packages); } 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); - } - } -} From 053776338ea44c31f3671cb4502853da0c88e55a Mon Sep 17 00:00:00 2001 From: Dmitry Zakharov Date: Tue, 14 Nov 2017 05:43:55 -0800 Subject: [PATCH 28/50] Cleanup ReactInstanceManager Reviewed By: kathryngray Differential Revision: D6296922 fbshipit-source-id: 2fbf11f09a3c25ff3e7c222edc2e01b81e687943 --- .../facebook/react/ReactInstanceManager.java | 85 +++++++++---------- 1 file changed, 39 insertions(+), 46 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index 0e06dd854916b9..6bb07f30f1d958 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -152,42 +152,12 @@ 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; @@ -251,34 +221,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) { - PrinterHolder.getPrinter().logMessage(ReactDebugOverlayTags.RN_CORE, "RNCore: Use Split Packages"); + PrinterHolder.getPrinter() + .logMessage(ReactDebugOverlayTags.RN_CORE, "RNCore: Use Split Packages"); mPackages.add( new CoreModulesPackage( this, - mBackBtnHandler, - mUIImplementationProvider, - mLazyViewManagersEnabled, - mMinTimeLeftInFrameForNonBatchedOperationMs)); + new DefaultHardwareBackBtnHandler() { + @Override + public void invokeDefaultOnBackPressed() { + ReactInstanceManager.this.invokeDefaultOnBackPressed(); + } + }, + uiImplementationProvider, + lazyViewManagersEnabled, + minTimeLeftInFrameForNonBatchedOperationMs)); if (mUseDeveloperSupport) { mPackages.add(new DebugCorePackage()); } @@ -292,6 +266,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; } From 4f886a29a1234c967deae2354bbc5092e0e6595e Mon Sep 17 00:00:00 2001 From: Dmitry Zakharov Date: Tue, 14 Nov 2017 06:39:22 -0800 Subject: [PATCH 29/50] Remove android_react_native_perf.use_separate_ui_bg_thread experiment. Reviewed By: AaaChiuuu Differential Revision: D6313250 fbshipit-source-id: 583a729a157a2053827631a43e38917753e78477 --- .../facebook/react/ReactInstanceManager.java | 16 +--------- .../react/ReactInstanceManagerBuilder.java | 8 ----- .../com/facebook/react/ReactRootView.java | 2 +- .../react/bridge/CatalystInstanceImpl.java | 4 --- .../facebook/react/bridge/ReactContext.java | 30 ------------------- .../bridge/queue/ReactQueueConfiguration.java | 3 -- .../queue/ReactQueueConfigurationImpl.java | 28 ++--------------- .../queue/ReactQueueConfigurationSpec.java | 29 ------------------ .../react/uimanager/UIManagerModule.java | 6 ++-- .../react/views/modal/ReactModalHostView.java | 2 +- .../jni/react/jni/CatalystInstanceImpl.cpp | 15 ++-------- .../main/jni/react/jni/CatalystInstanceImpl.h | 2 -- .../jni/react/jni/ModuleRegistryBuilder.cpp | 19 ++---------- .../jni/react/jni/ModuleRegistryBuilder.h | 3 +- 14 files changed, 16 insertions(+), 151 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index 6bb07f30f1d958..a891b327d20028 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -156,7 +156,6 @@ public interface ReactInstanceEventListener { private final @Nullable NativeModuleCallExceptionHandler mNativeModuleCallExceptionHandler; private final boolean mLazyNativeModulesEnabled; private final boolean mDelayViewManagerClassLoadsEnabled; - private final boolean mUseSeparateUIBackgroundThread; private final int mMinNumShakes; private class ReactContextInitParams { @@ -204,7 +203,6 @@ public static ReactInstanceManagerBuilder builder() { boolean lazyViewManagersEnabled, boolean delayViewManagerClassLoadsEnabled, @Nullable DevBundleDownloadListener devBundleDownloadListener, - boolean useSeparateUIBackgroundThread, int minNumShakes, int minTimeLeftInFrameForNonBatchedOperationMs) { Log.d(ReactConstants.TAG, "ReactInstanceManager.ctor()"); @@ -236,7 +234,6 @@ public static ReactInstanceManagerBuilder builder() { mNativeModuleCallExceptionHandler = nativeModuleCallExceptionHandler; mLazyNativeModulesEnabled = lazyNativeModulesEnabled; mDelayViewManagerClassLoadsEnabled = delayViewManagerClassLoadsEnabled; - mUseSeparateUIBackgroundThread = useSeparateUIBackgroundThread; mMinNumShakes = minNumShakes; synchronized (mPackages) { PrinterHolder.getPrinter() @@ -995,15 +992,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( @@ -1080,9 +1068,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 2fbaaa2b80c339..f7fc31e2c62d77 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java @@ -46,7 +46,6 @@ public class ReactInstanceManagerBuilder { private boolean mDelayViewManagerClassLoadsEnabled; private @Nullable DevBundleDownloadListener mDevBundleDownloadListener; private @Nullable JavaScriptExecutorFactory mJavaScriptExecutorFactory; - private boolean mUseSeparateUIBackgroundThread; private int mMinNumShakes = 1; private int mMinTimeLeftInFrameForNonBatchedOperationMs = -1; @@ -214,12 +213,6 @@ public ReactInstanceManagerBuilder setDevBundleDownloadListener( return this; } - public ReactInstanceManagerBuilder setUseSeparateUIBackgroundThread( - boolean useSeparateUIBackgroundThread) { - mUseSeparateUIBackgroundThread = useSeparateUIBackgroundThread; - return this; - } - public ReactInstanceManagerBuilder setMinNumShakes(int minNumShakes) { mMinNumShakes = minNumShakes; return this; @@ -286,7 +279,6 @@ public ReactInstanceManager build() { mLazyViewManagersEnabled, mDelayViewManagerClassLoadsEnabled, mDevBundleDownloadListener, - mUseSeparateUIBackgroundThread, mMinNumShakes, mMinTimeLeftInFrameForNonBatchedOperationMs); } 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/bridge/CatalystInstanceImpl.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java index f9b883c3532a2f..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); 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..85959c84547055 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(); } @@ -269,14 +267,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 +295,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/uimanager/UIManagerModule.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java index 1591127cf97479..7becf4ad48f221 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java @@ -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/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/jni/react/jni/CatalystInstanceImpl.cpp b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp index abac4d1b19e081..7b136f0d0cdf14 100644 --- a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp +++ b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp @@ -89,9 +89,6 @@ CatalystInstanceImpl::~CatalystInstanceImpl() { if (moduleMessageQueue_ != NULL) { moduleMessageQueue_->quitSynchronous(); } - if (uiBackgroundMessageQueue_ != NULL) { - uiBackgroundMessageQueue_->quitSynchronous(); - } } void CatalystInstanceImpl::registerNatives() { @@ -119,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: // @@ -150,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_); @@ -169,8 +161,7 @@ void CatalystInstanceImpl::extendNativeModules( std::weak_ptr(instance_), javaModules, cxxModules, - moduleMessageQueue_, - uiBackgroundMessageQueue_)); + moduleMessageQueue_)); } void CatalystInstanceImpl::jniSetSourceURL(const std::string& sourceURL) { diff --git a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h index 8a94c8cc9f3807..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); @@ -79,7 +78,6 @@ class CatalystInstanceImpl : public jni::HybridClass { 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/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); } } From cfa2bbf2f692d0bc5600d7e369a9a91272930ca6 Mon Sep 17 00:00:00 2001 From: Dmitry Zakharov Date: Tue, 14 Nov 2017 09:23:28 -0800 Subject: [PATCH 30/50] Remove minNumShakes from ReactInstaneManager Reviewed By: kathryngray Differential Revision: D6313521 fbshipit-source-id: ffef1f96fbec88cdcc7597fa81505aee59e10bb8 --- .../main/java/com/facebook/react/ReactInstanceManager.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index a891b327d20028..d9f4975fb20ca2 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -156,7 +156,6 @@ public interface ReactInstanceEventListener { private final @Nullable NativeModuleCallExceptionHandler mNativeModuleCallExceptionHandler; private final boolean mLazyNativeModulesEnabled; private final boolean mDelayViewManagerClassLoadsEnabled; - private final int mMinNumShakes; private class ReactContextInitParams { private final JavaScriptExecutorFactory mJsExecutorFactory; @@ -234,7 +233,6 @@ public static ReactInstanceManagerBuilder builder() { mNativeModuleCallExceptionHandler = nativeModuleCallExceptionHandler; mLazyNativeModulesEnabled = lazyNativeModulesEnabled; mDelayViewManagerClassLoadsEnabled = delayViewManagerClassLoadsEnabled; - mMinNumShakes = minNumShakes; synchronized (mPackages) { PrinterHolder.getPrinter() .logMessage(ReactDebugOverlayTags.RN_CORE, "RNCore: Use Split Packages"); @@ -827,10 +825,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()"); From 58edf024a1ed3a71ef04f124546ee97496b6502f Mon Sep 17 00:00:00 2001 From: Wei Yeh Date: Tue, 14 Nov 2017 10:08:23 -0800 Subject: [PATCH 31/50] Fix typo in SafeArea documentation Reviewed By: shergin Differential Revision: D6316656 fbshipit-source-id: 12d37f9d8ad2481b7f6685c8d675ce84234bd814 --- Libraries/Components/SafeAreaView/SafeAreaView.ios.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 { From 3e4cf0e8d278d3c9fdb4d3aec981a257baf4d24d Mon Sep 17 00:00:00 2001 From: allengleyzer Date: Tue, 14 Nov 2017 10:50:52 -0800 Subject: [PATCH 32/50] Added progress updates for all XMLHttpRequest upload types Summary: Previously, only form-data request bodies emitted upload progress updates. Now, other request body types will also emit updates. Addresses issues: https://github.com/facebook/react-native/issues/15724 https://github.com/facebook/react-native/issues/11853 This is a bug fix for functionality that's missing on Android. These events are already working correctly on iOS. Run the following code on Android, and ensure that events are being sent: ``` const fileUri = 'file:///my_file.dat'; const url = 'http://my_post_url.com/'; const xhr = new XMLHttpRequest(); xhr.upload.onprogress = (event) => { console.log('progress: ' + event.loaded + ' / ' + event.total); } xhr.onreadystatechange = () => {if (xhr.readyState === 4) console.log('done');} console.log('start'); xhr.open('POST', url); xhr.send({ uri: fileUri }); // sending a file (wasn't sending progress) xhr.send("some big string"); // sending a string (wasn't sending progress) const formData = new FormData(); formData.set('test', 'data'); xhr.send(formData); // sending form data (was already working) ``` [ANDROID] [BUGFIX] [XMLHttpRequest] - Added progress updates for all XMLHttpRequest upload types Previously, only form-data request bodies emitted upload progress updates. Now, other request body types will also emit updates. Addresses issues: https://github.com/facebook/react-native/issues/15724 https://github.com/facebook/react-native/issues/11853 Closes https://github.com/facebook/react-native/pull/16541 Differential Revision: D6325252 Pulled By: hramos fbshipit-source-id: 4fe617216293e6f451e2a1af4fa872e8f56d4f93 --- .../modules/network/NetworkingModule.java | 63 ++++++++++--------- .../modules/network/NetworkingModuleTest.java | 9 ++- 2 files changed, 42 insertions(+), 30 deletions(-) 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/test/java/com/facebook/react/modules/network/NetworkingModuleTest.java b/ReactAndroid/src/test/java/com/facebook/react/modules/network/NetworkingModuleTest.java index 7b512bc252a5ed..8ad39cd16e2070 100644 --- a/ReactAndroid/src/test/java/com/facebook/react/modules/network/NetworkingModuleTest.java +++ b/ReactAndroid/src/test/java/com/facebook/react/modules/network/NetworkingModuleTest.java @@ -200,6 +200,10 @@ public WritableMap answer(InvocationOnMock invocation) throws Throwable { @Test public void testSuccessfulPostRequest() throws Exception { + RCTDeviceEventEmitter emitter = mock(RCTDeviceEventEmitter.class); + ReactApplicationContext context = mock(ReactApplicationContext.class); + when(context.getJSModule(any(Class.class))).thenReturn(emitter); + OkHttpClient httpClient = mock(OkHttpClient.class); when(httpClient.newCall(any(Request.class))).thenAnswer(new Answer() { @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", From da047966e4c2064a48e02ff74830c99808d8194b Mon Sep 17 00:00:00 2001 From: Naman Goel Date: Tue, 14 Nov 2017 13:13:40 -0800 Subject: [PATCH 33/50] Improve types for React Native styles. Reviewed By: TheSavior Differential Revision: D6226807 fbshipit-source-id: b64a77383e6e685f4017c47fc9a5095ed63b062c --- Libraries/Inspector/ElementProperties.js | 4 +- Libraries/StyleSheet/StyleSheet.js | 24 ++- Libraries/StyleSheet/StyleSheetTypes.js | 237 ++++++++++++++++++++++- 3 files changed, 255 insertions(+), 10 deletions(-) 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/StyleSheet/StyleSheet.js b/Libraries/StyleSheet/StyleSheet.js index 411cad91b7c44d..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 = Object | number | false | null | void | ''; -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>; From c7f37074ac89f7e568ca26a6bad3bdb02812c39f Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Wed, 15 Nov 2017 09:05:34 -0800 Subject: [PATCH 34/50] React sync for revisions 589c0a2...2d23a45 Reviewed By: acdlite Differential Revision: D6328351 fbshipit-source-id: 88dc0f6ec9947e4a908c21f3a3df46bca5a7fdbc --- Libraries/Renderer/REVISION | 2 +- Libraries/Renderer/ReactNativeFiber-dev.js | 3997 ----- Libraries/Renderer/ReactNativeFiber-prod.js | 3666 ----- Libraries/Renderer/ReactNativeRenderer-dev.js | 12927 ++++++++++++++++ .../Renderer/ReactNativeRenderer-prod.js | 5806 +++++++ Libraries/Renderer/shims/ReactNative.js | 4 +- Libraries/Renderer/shims/ReactNativeTypes.js | 3 +- Libraries/Renderer/shims/ReactTypes.js | 16 +- package.json | 6 +- 9 files changed, 18747 insertions(+), 7680 deletions(-) delete mode 100644 Libraries/Renderer/ReactNativeFiber-dev.js delete mode 100644 Libraries/Renderer/ReactNativeFiber-prod.js create mode 100644 Libraries/Renderer/ReactNativeRenderer-dev.js create mode 100644 Libraries/Renderer/ReactNativeRenderer-prod.js 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/package.json b/package.json index 22e3f8ad30e9cd..1f4ff6e2239d43 100644 --- a/package.json +++ b/package.json @@ -142,7 +142,7 @@ "react-native": "local-cli/wrong-react-native.js" }, "peerDependencies": { - "react": "16.0.0" + "react": "16.1.1" }, "dependencies": { "absolute-path": "^0.0.0", @@ -211,8 +211,8 @@ "flow-bin": "^0.59.0", "jest": "21.3.0-beta.8", "prettier": "1.7.0", - "react": "16.0.0", - "react-test-renderer": "16.0.0", + "react": "16.1.1", + "react-test-renderer": "16.1.1", "shelljs": "^0.7.8", "sinon": "^2.2.0" } From 6c70975689d0f0839e6c2db9a9a25c3023f5be7b Mon Sep 17 00:00:00 2001 From: Pritesh Nandgaonkar Date: Thu, 16 Nov 2017 05:15:59 -0800 Subject: [PATCH 35/50] Replace printf with YGLog calls Reviewed By: gkassabli Differential Revision: D6297015 fbshipit-source-id: 6a67bdf33ef121785ac14938f5d3ed6e9d6f2656 --- ReactCommon/yoga/yoga/Yoga.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ReactCommon/yoga/yoga/Yoga.c b/ReactCommon/yoga/yoga/Yoga.c index 45b37b9d8d0ce1..ac7fb11102e6d0 100644 --- a/ReactCommon/yoga/yoga/Yoga.c +++ b/ReactCommon/yoga/yoga/Yoga.c @@ -3503,11 +3503,11 @@ bool YGLayoutNodeInternal(const YGNodeRef node, 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", + YGLog(node, YGLogLevelVerbose, "wm: %s, hm: %s, aw: %f ah: %f => d: (%f, %f) %s\n", YGMeasureModeName(widthMeasureMode, performLayout), YGMeasureModeName(heightMeasureMode, performLayout), availableWidth, @@ -3518,11 +3518,11 @@ bool YGLayoutNodeInternal(const YGNodeRef node, } } 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", + YGLog(node, YGLogLevelVerbose, "wm: %s, hm: %s, aw: %f ah: %f %s\n", YGMeasureModeName(widthMeasureMode, performLayout), YGMeasureModeName(heightMeasureMode, performLayout), availableWidth, @@ -3542,11 +3542,11 @@ 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", + YGLog(node, YGLogLevelVerbose, "wm: %s, hm: %s, d: (%f, %f) %s\n", YGMeasureModeName(widthMeasureMode, performLayout), YGMeasureModeName(heightMeasureMode, performLayout), layout->measuredDimensions[YGDimensionWidth], @@ -3559,7 +3559,7 @@ bool YGLayoutNodeInternal(const YGNodeRef node, if (cachedResults == NULL) { 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; } From 52e3ae9063705bac53bad99ffe23976c29c8f1b2 Mon Sep 17 00:00:00 2001 From: Ashok Menon Date: Thu, 16 Nov 2017 07:46:59 -0800 Subject: [PATCH 36/50] Unify Systrace native hook argument passing. Reviewed By: javache Differential Revision: D6316024 fbshipit-source-id: c1b315fac2c3cf8558d0c9eb0eb2c7d3efe5c64f --- Libraries/Performance/Systrace.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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); } }, From 018208635069311c1a7c7776c6f359f7ded45362 Mon Sep 17 00:00:00 2001 From: Adrien Thiery Date: Thu, 16 Nov 2017 16:16:30 -0800 Subject: [PATCH 37/50] Disable git hooks for the upgrade process MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: I'm loving `react-native-git-upgrade`, such a life and time saver, but when doing the upgrade, if git hooks are defined globally to be applied, `react-native-git-upgrade` uses these git hooks, although they might not be relevant to the upgrade process (and potentially make it way longer). Btw, thanks ncuillery for the great tool 😄 To test, I : * cloned my project * upgraded it with the npm published `react-native-git-upgrade` version : Git hooks are running during the upgrade * cloned the `react-native` repo * did my modifications on the `react-native-git-upgrade/cliEntry.js` file * `npm i -g react-native-git-upgrade/` after running `yarn` in that folder * Re-cloned my project in another folder * Upgraded it with `react-native-git-upgrade` : The hooks are not running anymore, yay! [CLI] [ENHANCEMENT] [react-native/react-native-git-upgrade] - Do not run git hooks in the upgrade process I plan to add an option to the cli so you can pass `--verify` or `--use-git-hooks` if you DO want your git hooks to run, but don't have the time right now and I think the default should be to not run them. Closes https://github.com/facebook/react-native/pull/16855 Differential Revision: D6353781 Pulled By: hramos fbshipit-source-id: e4b0f55d10c37bc805b32cb4c0fe3c863346482d --- react-native-git-upgrade/cliEntry.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/react-native-git-upgrade/cliEntry.js b/react-native-git-upgrade/cliEntry.js index 11542a946e9892..59b271b37bb07f 100644 --- a/react-native-git-upgrade/cliEntry.js +++ b/react-native-git-upgrade/cliEntry.js @@ -278,7 +278,7 @@ async function run(requestedVersion, cliArgs) { await exec('git add .', verbose); log.info('Commit current project sources'); - await exec('git commit -m "Project snapshot"', verbose); + await exec('git commit -m "Project snapshot" --no-verify', verbose); log.info('Create a tag before updating sources'); await exec('git tag project-snapshot', verbose); @@ -291,7 +291,7 @@ async function run(requestedVersion, cliArgs) { await exec('git add .', verbose); log.info('Commit old version template'); - await exec('git commit -m "Old version" --allow-empty', verbose); + await exec('git commit -m "Old version" --allow-empty --no-verify', verbose); log.info('Install the new version'); let installCommand; @@ -314,7 +314,7 @@ async function run(requestedVersion, cliArgs) { await exec('git add .', verbose); log.info('Commit new version template'); - await exec('git commit -m "New version" --allow-empty', verbose); + await exec('git commit -m "New version" --allow-empty --no-verify', verbose); log.info('Generate the patch between the 2 versions'); const diffOutput = await exec('git diff --binary --no-color HEAD~1 HEAD', verbose); @@ -345,7 +345,7 @@ async function run(requestedVersion, cliArgs) { log.error(err.stack); if (projectBackupCreated) { log.error('Restore initial sources'); - await exec('git checkout project-snapshot', true); + await exec('git checkout project-snapshot --no-verify', true); } } } From 64d80b13db3dd28bb5d93cbedf511ae8f91e2127 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ramos?= Date: Thu, 16 Nov 2017 16:44:29 -0800 Subject: [PATCH 38/50] Migrate to new documentation format Summary: Now that the Component and API docs are no longer auto-generated, we need to consolidate on a new format for our jsdoc comments. Any help from the community will be appreciated. In this initial pull request, we'll be tackling the following docs: - `AccessibilityInfo`, an API doc. - `ActivityIndicator`, a Component doc. - `View`, a Component doc. This top comment will serve as a style guide, and when in doubt, please refer to the individual commits in this PR. Each commit should update a single component or API, along with any relevant markdown files. - Documentation in the JavaScript source files should be succinct. Any verbosity should be moved over to the markdown docs in the website... - ...by adding a link to the relevant method/prop on the website to every comment block. - Avoid markdown style links in JavaScript source files, opt for plain old URIs. Let code document itself: - If a method is Flow typed, the comment block does not need to repeat this information. - If a param can be one of several values, and the type definition is easily determined from the code, the values should not be repeated in the comment block. Again, move this to the markdown doc if not present already. Closes https://github.com/facebook/react-native/pull/16790 Differential Revision: D6353840 Pulled By: hramos fbshipit-source-id: 9712c459acc33092aae9909f3dd0b58a00b26afc --- .../AccessibilityInfo.android.js | 10 + .../AccessibilityInfo.ios.js | 85 +-- .../ActivityIndicator/ActivityIndicator.js | 48 +- Libraries/Components/View/View.js | 45 +- Libraries/Components/View/ViewPropTypes.js | 267 +++---- docs/accessibilityinfo.md | 52 +- docs/activityindicator.md | 29 +- docs/checkbox.md | 2 +- docs/datepickerios.md | 2 +- docs/drawerlayoutandroid.md | 2 +- docs/maskedviewios.md | 2 +- docs/picker.md | 2 +- docs/pickerios.md | 2 +- docs/progressbarandroid.md | 2 +- docs/progressviewios.md | 2 +- docs/refreshcontrol.md | 2 +- docs/scrollview.md | 2 +- docs/segmentedcontrolios.md | 2 +- docs/slider.md | 2 +- docs/snapshotviewios.md | 2 +- docs/switch.md | 2 +- docs/tabbarios.md | 2 +- docs/textinput.md | 2 +- docs/toolbarandroid.md | 2 +- docs/view-props.md | 657 +----------------- docs/view.md | 76 +- docs/viewpagerandroid.md | 2 +- docs/webview.md | 2 +- 28 files changed, 248 insertions(+), 1059 deletions(-) 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/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/docs/accessibilityinfo.md b/docs/accessibilityinfo.md index d1d7625c21867f..1e0e0559bb93ff 100644 --- a/docs/accessibilityinfo.md +++ b/docs/accessibilityinfo.md @@ -78,7 +78,7 @@ class ScreenReaderStatusExample extends React.Component { ### `fetch()` ```javascript -AccessibilityInfo.fetch() +AccessibilityInfo.fetch(): Promise ``` @@ -94,22 +94,10 @@ and `false` otherwise. ### `addEventListener()` ```javascript -AccessibilityInfo.addEventListener(eventName, handler) +AccessibilityInfo.addEventListener(eventName: ChangeEventName, handler: Function): Object ``` - -Add an 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. - - +Add an event handler. See [Change Event Names](docs/accessibilityinfo.html#changeeventnames). --- @@ -117,11 +105,15 @@ Add an event handler. Supported events: ### `setAccessibilityFocus()` ```javascript -AccessibilityInfo.setAccessibilityFocus(reactTag) +AccessibilityInfo.setAccessibilityFocus(reactTag: number): void ``` +Set accessibility focus to a React component. + -iOS-Only. Set accessibility focus to a react component. +| Platform | +| - | +| iOS | @@ -131,12 +123,14 @@ iOS-Only. Set accessibility focus to a react component. ### `announceForAccessibility()` ```javascript -AccessibilityInfo.announceForAccessibility(announcement) +AccessibilityInfo.announceForAccessibility(announcement: string): void ``` +Post a string to be announced by the screen reader. -iOS-Only. Post a string to be announced by the screen reader. - +| Platform | +| - | +| iOS | @@ -145,12 +139,26 @@ iOS-Only. Post a string to be announced by the screen reader. ### `removeEventListener()` ```javascript -AccessibilityInfo.removeEventListener(eventName, handler) +AccessibilityInfo.removeEventListener(eventName: ChangeEventName, handler) ``` +Remove an event handler. See [Change Event Names](docs/accessibilityinfo.html#changeeventnames). + + + +## Change Event Names + +### `change` -Remove an event handler. +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` +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. +| Platform | +| - | +| iOS | diff --git a/docs/activityindicator.md b/docs/activityindicator.md index 4b6f22d9046ca6..4cb00f56312deb 100644 --- a/docs/activityindicator.md +++ b/docs/activityindicator.md @@ -5,8 +5,8 @@ layout: docs category: components permalink: docs/activityindicator.html next: button -previous: null --- + Displays a circular loading indicator. ### Example @@ -51,17 +51,13 @@ AppRegistry.registerComponent('App', () => App) ### Props -- [View props...](docs/view-props.html) +- [`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 @@ -70,15 +66,12 @@ AppRegistry.registerComponent('App', () => App) ### `animating` -Whether to show the indicator (true, the default) or hide it (false). +Whether to show the indicator (`true`, the default) or hide it (`false`). | Type | Required | | - | - | | bool | No | - - - --- ### `color` @@ -89,22 +82,17 @@ The foreground color of the spinner (default is gray). | - | - | | [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 | - - - +| enum('small', 'large'), number | No | --- @@ -113,13 +101,6 @@ Passing a number to the size prop is only supported on Android. Whether the indicator should hide when not animating (true by default). - | Type | Required | Platform | | - | - | - | | bool | No | iOS | - - - - - - diff --git a/docs/checkbox.md b/docs/checkbox.md index 679b5df885a98c..08f047949183a6 100644 --- a/docs/checkbox.md +++ b/docs/checkbox.md @@ -19,7 +19,7 @@ the supplied `value` prop instead of the expected result of any user actions. ### Props -- [View props...](docs/view-props.html) +- [View props...](docs/view.html#props) - [`disabled`](docs/checkbox.html#disabled) - [`onChange`](docs/checkbox.html#onchange) - [`onValueChange`](docs/checkbox.html#onvaluechange) diff --git a/docs/datepickerios.md b/docs/datepickerios.md index 43795a3321d6f6..fbd98fdf3e6460 100644 --- a/docs/datepickerios.md +++ b/docs/datepickerios.md @@ -15,7 +15,7 @@ source of truth. ### Props -- [View props...](docs/view-props.html) +- [View props...](docs/view.html#props) - [`date`](docs/datepickerios.html#date) - [`onDateChange`](docs/datepickerios.html#ondatechange) - [`maximumDate`](docs/datepickerios.html#maximumdate) diff --git a/docs/drawerlayoutandroid.md b/docs/drawerlayoutandroid.md index 0a2a393f0635f3..6bde444af6d3de 100644 --- a/docs/drawerlayoutandroid.md +++ b/docs/drawerlayoutandroid.md @@ -39,7 +39,7 @@ render: function() { ### Props -- [View props...](docs/view-props.html) +- [View props...](docs/view.html#props) - [`renderNavigationView`](docs/drawerlayoutandroid.html#rendernavigationview) - [`onDrawerClose`](docs/drawerlayoutandroid.html#ondrawerclose) - [`drawerPosition`](docs/drawerlayoutandroid.html#drawerposition) diff --git a/docs/maskedviewios.md b/docs/maskedviewios.md index 0de578a532ef64..c566ed0195627d 100644 --- a/docs/maskedviewios.md +++ b/docs/maskedviewios.md @@ -43,7 +43,7 @@ transparent pixels block that content. ### Props -- [View props...](docs/view-props.html) +- [View props...](docs/view.html#props) - [`maskElement`](docs/maskedviewios.html#maskelement) diff --git a/docs/picker.md b/docs/picker.md index 3ce067f96643c3..f2914f03fb0a65 100644 --- a/docs/picker.md +++ b/docs/picker.md @@ -19,7 +19,7 @@ Renders the native picker component on iOS and Android. Example: ### Props -- [View props...](docs/view-props.html) +- [View props...](docs/view.html#props) - [`onValueChange`](docs/picker.html#onvaluechange) - [`selectedValue`](docs/picker.html#selectedvalue) - [`enabled`](docs/picker.html#enabled) diff --git a/docs/pickerios.md b/docs/pickerios.md index 75734e46f530e8..6a8394fa78d142 100644 --- a/docs/pickerios.md +++ b/docs/pickerios.md @@ -10,7 +10,7 @@ previous: picker ### Props -- [View props...](docs/view-props.html) +- [View props...](docs/view.html#props) - [`itemStyle`](docs/pickerios.html#itemstyle) - [`onValueChange`](docs/pickerios.html#onvaluechange) - [`selectedValue`](docs/pickerios.html#selectedvalue) diff --git a/docs/progressbarandroid.md b/docs/progressbarandroid.md index b316ea1224130a..d5e27ec15c12f0 100644 --- a/docs/progressbarandroid.md +++ b/docs/progressbarandroid.md @@ -31,7 +31,7 @@ render: function() { ### Props -- [View props...](docs/view-props.html) +- [View props...](docs/view.html#props) - [`animating`](docs/progressbarandroid.html#animating) - [`color`](docs/progressbarandroid.html#color) - [`indeterminate`](docs/progressbarandroid.html#indeterminate) diff --git a/docs/progressviewios.md b/docs/progressviewios.md index b9c9bdedb27ece..ed6ff075042bb9 100644 --- a/docs/progressviewios.md +++ b/docs/progressviewios.md @@ -11,7 +11,7 @@ Use `ProgressViewIOS` to render a UIProgressView on iOS. ### Props -- [View props...](docs/view-props.html) +- [View props...](docs/view.html#props) - [`progress`](docs/progressviewios.html#progress) - [`progressImage`](docs/progressviewios.html#progressimage) - [`progressTintColor`](docs/progressviewios.html#progresstintcolor) diff --git a/docs/refreshcontrol.md b/docs/refreshcontrol.md index 6302f46297bb9e..1ac7c4d7bd7ad0 100644 --- a/docs/refreshcontrol.md +++ b/docs/refreshcontrol.md @@ -53,7 +53,7 @@ in the `onRefresh` function otherwise the refresh indicator will stop immediatel ### Props -- [View props...](docs/view-props.html) +- [View props...](docs/view.html#props) - [`refreshing`](docs/refreshcontrol.html#refreshing) - [`onRefresh`](docs/refreshcontrol.html#onrefresh) - [`colors`](docs/refreshcontrol.html#colors) diff --git a/docs/scrollview.md b/docs/scrollview.md index c73e45955333b0..9af144cf93d31a 100644 --- a/docs/scrollview.md +++ b/docs/scrollview.md @@ -43,7 +43,7 @@ supports out of the box. ### Props -- [View props...](docs/view-props.html) +- [View props...](docs/view.html#props) - [`alwaysBounceVertical`](docs/scrollview.html#alwaysbouncevertical) - [`contentContainerStyle`](docs/scrollview.html#contentcontainerstyle) - [`keyboardDismissMode`](docs/scrollview.html#keyboarddismissmode) diff --git a/docs/segmentedcontrolios.md b/docs/segmentedcontrolios.md index 65d764193094a3..a0d38d9c6f7b3e 100644 --- a/docs/segmentedcontrolios.md +++ b/docs/segmentedcontrolios.md @@ -28,7 +28,7 @@ selects a value and changes the index, as shown in the example below. ### Props -- [View props...](docs/view-props.html) +- [View props...](docs/view.html#props) - [`enabled`](docs/segmentedcontrolios.html#enabled) - [`momentary`](docs/segmentedcontrolios.html#momentary) - [`onChange`](docs/segmentedcontrolios.html#onchange) diff --git a/docs/slider.md b/docs/slider.md index c3768149ccfa1a..815248749caf6f 100644 --- a/docs/slider.md +++ b/docs/slider.md @@ -67,7 +67,7 @@ const styles = StyleSheet.create({ ### Props -- [View props...](docs/view-props.html) +- [View props...](docs/view.html#props) - [`style`](docs/slider.html#style) - [`disabled`](docs/slider.html#disabled) - [`maximumValue`](docs/slider.html#maximumvalue) diff --git a/docs/snapshotviewios.md b/docs/snapshotviewios.md index 7048f257a266db..e8dfd235e4c4d1 100644 --- a/docs/snapshotviewios.md +++ b/docs/snapshotviewios.md @@ -10,7 +10,7 @@ previous: slider ### Props -- [View props...](docs/view-props.html) +- [View props...](docs/view.html#props) - [`onSnapshotReady`](docs/snapshotviewios.html#onsnapshotready) - [`testIdentifier`](docs/snapshotviewios.html#testidentifier) diff --git a/docs/switch.md b/docs/switch.md index bac4b702f5aab5..a4bc3c33fafd9b 100644 --- a/docs/switch.md +++ b/docs/switch.md @@ -16,7 +16,7 @@ This is a controlled component that requires an `onValueChange` callback that up ### Props -- [View props...](docs/view-props.html) +- [View props...](docs/view.html#props) - [`disabled`](docs/switch.html#disabled) - [`onTintColor`](docs/switch.html#ontintcolor) - [`onValueChange`](docs/switch.html#onvaluechange) diff --git a/docs/tabbarios.md b/docs/tabbarios.md index 8c1d83a5321dc1..122a6eaa7ad23b 100644 --- a/docs/tabbarios.md +++ b/docs/tabbarios.md @@ -9,7 +9,7 @@ previous: switch --- ### Props -- [View props...](docs/view-props.html) +- [View props...](docs/view.html#props) - [`barStyle`](docs/tabbarios.html#barstyle) - [`barTintColor`](docs/tabbarios.html#bartintcolor) - [`itemPositioning`](docs/tabbarios.html#itempositioning) diff --git a/docs/textinput.md b/docs/textinput.md index e032d386c703bb..f14556a7ff1208 100644 --- a/docs/textinput.md +++ b/docs/textinput.md @@ -118,7 +118,7 @@ or control this param programmatically with native code. ### Props -- [View props...](docs/view-props.html) +- [View props...](docs/view.html#props) - [`placeholderTextColor`](docs/textinput.html#placeholdertextcolor) - [`allowFontScaling`](docs/textinput.html#allowfontscaling) - [`autoCorrect`](docs/textinput.html#autocorrect) diff --git a/docs/toolbarandroid.md b/docs/toolbarandroid.md index ba37cb65c903e9..ee9be291b7caf2 100644 --- a/docs/toolbarandroid.md +++ b/docs/toolbarandroid.md @@ -43,7 +43,7 @@ onActionSelected: function(position) { ### Props -- [View props...](docs/view-props.html) +- [View props...](docs/view.html#props) - [`overflowIcon`](docs/toolbarandroid.html#overflowicon) - [`actions`](docs/toolbarandroid.html#actions) - [`contentInsetStart`](docs/toolbarandroid.html#contentinsetstart) diff --git a/docs/view-props.md b/docs/view-props.md index 3ab3c2b3cd1c4e..65f14ceb564443 100644 --- a/docs/view-props.md +++ b/docs/view-props.md @@ -1,657 +1,8 @@ ---- +--- id: view-props title: View Props -layout: docs -category: APIs +layout: redirect permalink: docs/view-props.html -next: view-style-props -previous: shadow-props ---- -### Props - -- [`onStartShouldSetResponder`](docs/view-props.html#onstartshouldsetresponder) -- [`accessibilityLabel`](docs/view-props.html#accessibilitylabel) -- [`hitSlop`](docs/view-props.html#hitslop) -- [`nativeID`](docs/view-props.html#nativeid) -- [`onAccessibilityTap`](docs/view-props.html#onaccessibilitytap) -- [`onLayout`](docs/view-props.html#onlayout) -- [`onMagicTap`](docs/view-props.html#onmagictap) -- [`onMoveShouldSetResponder`](docs/view-props.html#onmoveshouldsetresponder) -- [`onMoveShouldSetResponderCapture`](docs/view-props.html#onmoveshouldsetrespondercapture) -- [`onResponderGrant`](docs/view-props.html#onrespondergrant) -- [`onResponderMove`](docs/view-props.html#onrespondermove) -- [`onResponderReject`](docs/view-props.html#onresponderreject) -- [`onResponderRelease`](docs/view-props.html#onresponderrelease) -- [`onResponderTerminate`](docs/view-props.html#onresponderterminate) -- [`onResponderTerminationRequest`](docs/view-props.html#onresponderterminationrequest) -- [`accessible`](docs/view-props.html#accessible) -- [`onStartShouldSetResponderCapture`](docs/view-props.html#onstartshouldsetrespondercapture) -- [`pointerEvents`](docs/view-props.html#pointerevents) -- [`removeClippedSubviews`](docs/view-props.html#removeclippedsubviews) -- [`style`](docs/view-props.html#style) -- [`testID`](docs/view-props.html#testid) -- [`accessibilityComponentType`](docs/view-props.html#accessibilitycomponenttype) -- [`accessibilityLiveRegion`](docs/view-props.html#accessibilityliveregion) -- [`collapsable`](docs/view-props.html#collapsable) -- [`importantForAccessibility`](docs/view-props.html#importantforaccessibility) -- [`needsOffscreenAlphaCompositing`](docs/view-props.html#needsoffscreenalphacompositing) -- [`renderToHardwareTextureAndroid`](docs/view-props.html#rendertohardwaretextureandroid) -- [`accessibilityTraits`](docs/view-props.html#accessibilitytraits) -- [`accessibilityViewIsModal`](docs/view-props.html#accessibilityviewismodal) -- [`shouldRasterizeIOS`](docs/view-props.html#shouldrasterizeios) - - - - - - ---- - -# Reference - -## Props - -### `onStartShouldSetResponder` - -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. - -| Type | Required | -| - | - | -| function | No | - - - - ---- - -### `accessibilityLabel` - -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. - -| Type | Required | -| - | - | -| node | No | - - - - ---- - -### `hitSlop` - -This defines how far a touch event can start away from the view. -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. - -| Type | Required | -| - | - | -| object: {top: number, left: number, bottom: number, right: number} | No | - - - - ---- - -### `nativeID` - -Used to locate this view from native classes. - -> This disables the 'layout-only view removal' optimization for this view! - -| Type | Required | -| - | - | -| string | No | - - - - ---- - -### `onAccessibilityTap` - -When `accessible` is true, the system will try to invoke this function -when the user performs accessibility tap gesture. - -| Type | Required | -| - | - | -| function | No | - - - - ---- - -### `onLayout` - -Invoked on mount and layout changes with: - -`{nativeEvent: { layout: {x, y, width, height}}}` - -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. - -| Type | Required | -| - | - | -| function | No | - - - - ---- - -### `onMagicTap` - -When `accessible` is `true`, the system will invoke this function when the -user performs the magic tap gesture. - -| Type | Required | -| - | - | -| function | No | - - - - ---- - -### `onMoveShouldSetResponder` - -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. - -| Type | Required | -| - | - | -| function | No | - - - - ---- - -### `onMoveShouldSetResponderCapture` - -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. - -| Type | Required | -| - | - | -| function | No | - - - - ---- - -### `onResponderGrant` - -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. - -| Type | Required | -| - | - | -| function | No | - - - - ---- - -### `onResponderMove` - -The user is moving their finger. - -`View.props.onResponderMove: (event) => {}`, where `event` is a synthetic touch event as -described above. - -| Type | Required | -| - | - | -| function | No | - - - - ---- - -### `onResponderReject` - -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. - -| Type | Required | -| - | - | -| function | No | - - - - ---- - -### `onResponderRelease` - -Fired at the end of the touch. - -`View.props.onResponderRelease: (event) => {}`, where `event` is a synthetic touch event as -described above. - -| Type | Required | -| - | - | -| function | No | - - - - ---- - -### `onResponderTerminate` - -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. - -| Type | Required | -| - | - | -| function | No | - - - - ---- - -### `onResponderTerminationRequest` - -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. - -| Type | Required | -| - | - | -| function | No | - - - - ---- - -### `accessible` - -When `true`, indicates that the view is an accessibility element. By default, -all the touchable elements are accessible. - -| Type | Required | -| - | - | -| bool | No | - - - - ---- - -### `onStartShouldSetResponderCapture` - -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. - -| Type | Required | -| - | - | -| function | No | - - - - ---- - -### `pointerEvents` - -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. - -| Type | Required | -| - | - | -| enum('box-none', 'none', 'box-only', 'auto') | No | - - - - ---- - -### `removeClippedSubviews` - -This is a special performance property exposed by `RCTView` and is useful -for scrolling content when there are many subviews, most of which are -offscreen. For this property to be effective, it must be applied to a -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). - -| Type | Required | -| - | - | -| bool | No | - - - - ---- - -### `style` - - - -| Type | Required | -| - | - | -| style | No | - - - - ---- - -### `testID` - -Used to locate this view in end-to-end tests. - -> This disables the 'layout-only view removal' optimization for this view! - -| Type | Required | -| - | - | -| string | No | - - - - ---- - -### `accessibilityComponentType` - -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'` - - - -| Type | Required | Platform | -| - | - | - | -| AccessibilityComponentTypes | No | Android | - - - - ---- - -### `accessibilityLiveRegion` - -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. - - - -| Type | Required | Platform | -| - | - | - | -| enum('none', 'polite', 'assertive') | No | Android | - - - - ---- - -### `collapsable` - -Views that are only used to layout their children or otherwise don't draw -anything may be automatically removed from the native hierarchy as an -optimization. Set this property to `false` to disable this optimization and -ensure that this `View` exists in the native view hierarchy. - - - -| Type | Required | Platform | -| - | - | - | -| bool | No | Android | - - - - ---- - -### `importantForAccessibility` - -Controls how view is important for accessibility which is if it -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. - - - -| Type | Required | Platform | -| - | - | - | -| enum('auto', 'yes', 'no', 'no-hide-descendants') | No | Android | - - - - ---- - -### `needsOffscreenAlphaCompositing` - -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. - - - -| Type | Required | Platform | -| - | - | - | -| bool | No | Android | - - - - ---- - -### `renderToHardwareTextureAndroid` - -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. - - - -| Type | Required | Platform | -| - | - | - | -| bool | No | Android | - - - - ---- - -### `accessibilityTraits` - -Provides additional traits to screen reader. By default no traits are -provided unless specified otherwise in element. - -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. - - - -| Type | Required | Platform | -| - | - | - | -| AccessibilityTraits, ,array of AccessibilityTraits | No | iOS | - - - - ---- - -### `accessibilityViewIsModal` - -A value indicating whether VoiceOver should ignore the elements -within views that are siblings of the receiver. -Default is `false`. - -See the [Accessibility guide](docs/accessibility.html#accessibilitytraits-ios) -for more information. - - - -| Type | Required | Platform | -| - | - | - | -| bool | No | iOS | - - - - +destinationUrl: view.html --- - -### `shouldRasterizeIOS` - -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. - - - -| Type | Required | Platform | -| - | - | - | -| bool | No | iOS | - - - - - - +Redirecting... diff --git a/docs/view.md b/docs/view.md index c00b327a440a68..6d252759e9752a 100644 --- a/docs/view.md +++ b/docs/view.md @@ -33,7 +33,7 @@ class ViewColoredBoxesWithText extends Component { ### 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. @@ -45,9 +45,11 @@ For `View` responder props (e.g., `onResponderMove`), the synthetic touch event - `timestamp` - A time identifier for the touch, useful for velocity calculation. - `touches` - Array of all current touches on the screen. +For most touch interactions, you'll simply want to wrap your component in [`TouchableHighlight`](docs/touchablehighlight.html) or [`TouchableOpacity`](docs/touchableopacity.html). + + ### Props -- [View props...](docs/view-props.html) - [`onStartShouldSetResponder`](docs/view.html#onstartshouldsetresponder) - [`accessibilityLabel`](docs/view.html#accessibilitylabel) - [`hitSlop`](docs/view.html#hitslop) @@ -385,30 +387,27 @@ Controls whether the `View` can be 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-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. + ``` + .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. | Type | Required | | - | - | @@ -421,12 +420,7 @@ Controls whether the `View` can be the target of touch events. ### `removeClippedSubviews` -This is a special performance property exposed by `RCTView` and is useful -for scrolling content when there are many subviews, most of which are -offscreen. For this property to be effective, it must be applied to a -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). +This is a special performance property exposed by `RCTView` and is useful for scrolling content when there are many subviews, most of which are offscreen. For this property to be effective, it must be applied to a 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). | Type | Required | | - | - | @@ -443,7 +437,7 @@ subviews must also have `overflow: hidden`, as should the containing view | Type | Required | | - | - | -| stylePropType | No | +| [style](docs/style.html) | No | @@ -470,7 +464,7 @@ Used to locate this view in end-to-end tests. Indicates to accessibility services to treat UI component like a native one. Works for Android only. -Possible values are one of: +Possible values for `AccessibilityComponentTypes`: - `'none'` - `'button'` @@ -538,15 +532,12 @@ 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. +- `'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. +See the [Android `importantForAccessibility` docs](http://developer.android.com/reference/android/R.attr.html#importantForAccessibility) for reference. @@ -648,7 +639,7 @@ for more information. | Type | Required | Platform | | - | - | - | -| AccessibilityTraits, ,array of AccessibilityTraits | No | iOS | +| AccessibilityTraits, array of AccessibilityTraits | No | iOS | @@ -697,15 +688,14 @@ memory. Test and measure when using this property. - - ## Type Definitions ### Props | Type | | - | -| ViewProps | +| [ViewProps](docs/view.html#props) | + diff --git a/docs/viewpagerandroid.md b/docs/viewpagerandroid.md index 8b4006445f33db..d9df7651c93b69 100644 --- a/docs/viewpagerandroid.md +++ b/docs/viewpagerandroid.md @@ -49,7 +49,7 @@ var styles = { ### Props -- [View props...](docs/view-props.html) +- [View props...](docs/view.html#props) - [`initialPage`](docs/viewpagerandroid.html#initialpage) - [`keyboardDismissMode`](docs/viewpagerandroid.html#keyboarddismissmode) - [`onPageScroll`](docs/viewpagerandroid.html#onpagescroll) diff --git a/docs/webview.md b/docs/webview.md index bb2b5eea59160e..0675c3f5666203 100644 --- a/docs/webview.md +++ b/docs/webview.md @@ -30,7 +30,7 @@ history and configure various properties for the web content. ### Props -- [View props...](docs/view-props.html) +- [View props...](docs/view.html#props) - [`source`](docs/webview.html#source) - [`automaticallyAdjustContentInsets`](docs/webview.html#automaticallyadjustcontentinsets) - [`injectJavaScript`](docs/webview.html#injectjavascript) From bd9cb37ccf908e0ab6e03d3499c3b899e7116ff0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ramos?= <165856+hramos@users.noreply.github.com> Date: Thu, 16 Nov 2017 17:49:56 -0800 Subject: [PATCH 39/50] Update buck to v2017.11.16.01 Summary: Android tests on CI have been failing since late October due to dd016f334cef26f393b1a3c1e052e89a69502a56 which makes use of a new Buck feature, `required_for_source_only_abi`. Circle was using an older September release. In this PR, we update to the latest release. Green is good. Red is bad. Wait for Circle to run. [INTERNAL][BUGFIX][./circleci/config.yml] - Update Buck version Closes https://github.com/facebook/react-native/pull/16861 Differential Revision: D6355335 Pulled By: hramos fbshipit-source-id: 411d0b229f0dfb7e9dfc07c300b6546bf7afcdfe --- .circleci/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 32902f12fad5e6..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: @@ -334,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 From d19d137cc18f10957b5ac64ac727d15fde57f018 Mon Sep 17 00:00:00 2001 From: Logan Daniels Date: Thu, 16 Nov 2017 20:03:07 -0800 Subject: [PATCH 40/50] Fix minimumViewTime in ViewabilityHelper Reviewed By: sahrens Differential Revision: D6350352 fbshipit-source-id: e909600875156127eb3144726981ab62e0015e6e --- Libraries/Lists/ViewabilityHelper.js | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) 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( From 0ac5a5230c4b5dd44db6a8dd7bb7752aff64d71c Mon Sep 17 00:00:00 2001 From: Alex Dvornikov Date: Fri, 17 Nov 2017 03:12:59 -0800 Subject: [PATCH 41/50] Make RCTNativeModule::invokeInner explicitely return folly::none in case of error Differential Revision: D6347967 fbshipit-source-id: 88788da321ca75d20b6c1a8e3d41642af7c6155e --- React/Base/RCTAssert.m | 2 +- React/CxxModule/RCTNativeModule.mm | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) 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/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; } } From 231c7a03043b9fb3c4bf81251ad099bab0ba05c2 Mon Sep 17 00:00:00 2001 From: Rafael Oleza Date: Fri, 17 Nov 2017 07:30:13 -0800 Subject: [PATCH 42/50] Add end to end Delta support to Android devices Reviewed By: davidaurelio Differential Revision: D6338677 fbshipit-source-id: 8fa8f618bf8d6cb2291ce4405093cad23bd47fc3 --- Libraries/Utilities/HMRClient.js | 4 +- .../react/devsupport/BundleDownloader.java | 183 +++++++++++++++--- .../react/devsupport/DevInternalSettings.java | 24 ++- .../react/devsupport/DevServerHelper.java | 36 ++-- .../main/res/devsupport/xml/preferences.xml | 6 + 5 files changed, 202 insertions(+), 51 deletions(-) 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/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/res/devsupport/xml/preferences.xml b/ReactAndroid/src/main/res/devsupport/xml/preferences.xml index 4e69a0e5a648ed..b334730b57282a 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" /> + Date: Fri, 17 Nov 2017 11:17:10 -0800 Subject: [PATCH 43/50] check if listener is still in the set before calling onHostResume Reviewed By: achen1 Differential Revision: D6341419 fbshipit-source-id: e49188803bbf3641bad6a9cc8c497d453798bbce --- .../facebook/react/bridge/ReactContext.java | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) 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 85959c84547055..bac4fdf8a885bb 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java @@ -141,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."); From 1b22d49ae8945680dee4fd01e3fbb78b1e443e01 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Fri, 17 Nov 2017 13:30:06 -0800 Subject: [PATCH 44/50] renderApplication() supports async initial render Reviewed By: sahrens Differential Revision: D6339469 fbshipit-source-id: d832de936c50edcdc6953b72b5ad18ce1b652187 --- Libraries/ReactNative/renderApplication.js | 26 +++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/Libraries/ReactNative/renderApplication.js b/Libraries/ReactNative/renderApplication.js index a1e96f30dbb3ca..41e25c1c1ccc7f 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://fburl.com/tjpe0gpx + 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; From 44c16499fdc4665298f6c88b9ffee626fa1fc969 Mon Sep 17 00:00:00 2001 From: Nathan Brown Date: Sat, 18 Nov 2017 17:15:24 -0800 Subject: [PATCH 45/50] Mention when error is thrown Summary: Improve the error message shown when you try to nest components in an `` component by referencing the `` component. It would be helpful if the error message displayed when you try to nest components in an `` component mentioned the `` component. Especially since this component is not yet well documented. [IOS][MINOR][Libraries/Image/Image.ios.js] - Surfaced `` in error message [ANDROID][MINOR][Libraries/Image/Image.android.js] - Surfaced `` in error message Closes https://github.com/facebook/react-native/pull/16880 Differential Revision: D6369396 Pulled By: shergin fbshipit-source-id: c4ae4dbb77d0fce6cbd7a42d1957d16112b24549 --- Libraries/Image/Image.android.js | 2 +- Libraries/Image/Image.ios.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Libraries/Image/Image.android.js b/Libraries/Image/Image.android.js index d0169794642f61..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 absolute 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 cc7aeec42430c7..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 absolute 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 ( From 3aa38564f7b91c8588c8484140bc4221d50d55e0 Mon Sep 17 00:00:00 2001 From: John Wilson Date: Sun, 19 Nov 2017 09:24:01 -0800 Subject: [PATCH 46/50] Correcting the redirection link. Summary: Correcting the redirection link to the right section ID for ListFooterComponent. (Making the site flow better.) (Just fixed a small typo!) Closes https://github.com/facebook/react-native/pull/16873 Differential Revision: D6370785 Pulled By: hramos fbshipit-source-id: bb6e5ca4e9bb585f94670c233258d602136e3097 --- docs/sectionlist.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sectionlist.md b/docs/sectionlist.md index d7bca81aa9ce96..dfa53d6fc7d43e 100644 --- a/docs/sectionlist.md +++ b/docs/sectionlist.md @@ -64,7 +64,7 @@ here, along with the following caveats: - [`ItemSeparatorComponent`](docs/virtualizedlist.html#itemseparatorcomponent) - [`ItemSeparatorComponent`](docs/virtualizedlist.html#itemseparatorcomponent) - [`ListEmptyComponent`](docs/virtualizedlist.html#listemptycomponent) -- [`ListFooterComponent`](docs/virtualizedlist.html#listgootercomponent) +- [`ListFooterComponent`](docs/virtualizedlist.html#listfootercomponent) SectionSeparatorComponent - [`extradata`](docs/virtualizedlist.html#extradata) - [`initialNumToRender`](docs/virtualizedlist.html#initialnumtorender) From 6b26971a56fdd919d11cc338893d0b7a3f7a45ba Mon Sep 17 00:00:00 2001 From: John Wilson Date: Sun, 19 Nov 2017 09:46:53 -0800 Subject: [PATCH 47/50] Removed Duplicate data. Summary: Prop for SectionList 'ItemSeperatorComponent' was repeated twice. (Write your motivation here.) (Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work. Bonus points for screenshots and videos!) Closes https://github.com/facebook/react-native/pull/16872 Differential Revision: D6370787 Pulled By: hramos fbshipit-source-id: f5b53376b6c169d96089e8706612587cc50d8669 --- docs/sectionlist.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/sectionlist.md b/docs/sectionlist.md index dfa53d6fc7d43e..327a34261b2e9f 100644 --- a/docs/sectionlist.md +++ b/docs/sectionlist.md @@ -62,7 +62,6 @@ here, along with the following caveats: - [`sections`](docs/virtualizedlist.html#sections) - [`renderItem`](docs/virtualizedlist.html#renderitem) - [`ItemSeparatorComponent`](docs/virtualizedlist.html#itemseparatorcomponent) -- [`ItemSeparatorComponent`](docs/virtualizedlist.html#itemseparatorcomponent) - [`ListEmptyComponent`](docs/virtualizedlist.html#listemptycomponent) - [`ListFooterComponent`](docs/virtualizedlist.html#listfootercomponent) SectionSeparatorComponent From 766f020e68abfc121ea6a9f92e0640368d69dae7 Mon Sep 17 00:00:00 2001 From: Eric Rozell Date: Sun, 19 Nov 2017 17:09:53 -0800 Subject: [PATCH 48/50] Minor bug in random generator for `selection` prop Summary: `.sort()` will sort on the string value by default, so if you generate [18, 8], they will stay in that order. Adding comparer to ensure values are sorted numerically. Found a bug in RNTester. Ran RNTester and confirmed that bug could be reproduced. [IOS][BUGFIX][RNTester] - patch test to implement desired behavior. Closes https://github.com/facebook/react-native/pull/16871 Differential Revision: D6371550 Pulled By: shergin fbshipit-source-id: 84866d1eb02c2be51cd15a60490604d28fa18973 --- RNTester/js/TextInputExample.ios.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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); } From 0ff576081b156ea26c4e7886f7266f3e4d8e3d5e Mon Sep 17 00:00:00 2001 From: Kevin Brown Date: Sun, 19 Nov 2017 17:39:38 -0800 Subject: [PATCH 49/50] Corrected types of page_info return value in documentation. Summary: I was confused by the current documentation, as it was requesting me to pass the previously received `end_cursor` into the next fetch but it was declared as a boolean. I checked in the debugger and it's just mislabeled in the docs, so this PR fixes the docs. I tried to push this change back in #15472 but wasn't able to undo the borked rebase, so I'm submitting a new PR. This is a change to documentation only. [DOCS] [BUGFIX] [Libraries/CameralRoll/CameraRoll.js] - Corrected return type in the documentation for the `start_cursor` and `end_cursor` values. Closes https://github.com/facebook/react-native/pull/16830 Differential Revision: D6371585 Pulled By: hramos fbshipit-source-id: 5038041e95a04ea4c2de8d2b535a8a4e019289f6 --- Libraries/CameraRoll/CameraRoll.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Libraries/CameraRoll/CameraRoll.js b/Libraries/CameraRoll/CameraRoll.js index b9da61a56db4b8..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: * ``` From f1015664e92f02c33417a591a2438db7c0cd3811 Mon Sep 17 00:00:00 2001 From: Dmitry Zakharov Date: Mon, 20 Nov 2017 07:27:47 -0800 Subject: [PATCH 50/50] Fix crash when destroying catalyst Reviewed By: fromcelticpark Differential Revision: D6373275 fbshipit-source-id: c36b53f023800097b301d530250b05e5b2a4dfca --- .../facebook/react/ReactInstanceManager.java | 22 ++++++++++++++----- .../ViewManagerOnDemandReactPackage.java | 2 +- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index d9f4975fb20ca2..bc2a500ac818dc 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -764,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) { @@ -781,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) { 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.