From 4e3dd541f9d23ea3325f23615a172c291a745b81 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Wed, 23 Aug 2017 10:58:38 +0100 Subject: [PATCH 1/5] Remove Fiber Jest project --- package.json | 39 ++++++++++++++++++++--- scripts/jest/fiber.config.json | 38 ---------------------- scripts/jest/{fiber.setup.js => setup.js} | 6 ---- scripts/jest/stack.config.json | 38 ---------------------- scripts/jest/stack.setup.js | 14 -------- 5 files changed, 35 insertions(+), 100 deletions(-) delete mode 100644 scripts/jest/fiber.config.json rename scripts/jest/{fiber.setup.js => setup.js} (74%) delete mode 100644 scripts/jest/stack.config.json delete mode 100644 scripts/jest/stack.setup.js diff --git a/package.json b/package.json index c019a7d717f..c831eee727c 100644 --- a/package.json +++ b/package.json @@ -108,9 +108,40 @@ "version-check": "node ./scripts/tasks/version-check.js" }, "jest": { - "projects": [ - "/scripts/jest/stack.config.json", - "/scripts/jest/fiber.config.json" - ] + "modulePathIgnorePatterns": [ + "/.module-cache/", + "/build/", + "/scripts/rollup/shims/", + "/scripts/bench/" + ], + "transform": { + ".*": "./scripts/jest/preprocessor.js" + }, + "setupFiles": [ + "./scripts/jest/setup.js", + "./scripts/jest/environment.js" + ], + "setupTestFrameworkScriptFile": "./scripts/jest/test-framework-setup.js", + "testRegex": "/__tests__/.*(\\.js|coffee|ts)$", + "moduleFileExtensions": [ + "js", + "json", + "node", + "coffee", + "ts" + ], + "roots": [ + "/eslint-rules", + "/mocks", + "/scripts", + "/src", + "node_modules/fbjs" + ], + "collectCoverageFrom": [ + "src/**/*.js", + "!src/__mocks__/vendor/third_party/*.js", + "!src/test/*.js" + ], + "timers": "fake" } } diff --git a/scripts/jest/fiber.config.json b/scripts/jest/fiber.config.json deleted file mode 100644 index c6f47bf86cd..00000000000 --- a/scripts/jest/fiber.config.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "modulePathIgnorePatterns": [ - "/.module-cache/", - "/build/", - "/scripts/rollup/shims/", - "/scripts/bench/" - ], - "rootDir": "../../", - "transform": { - ".*": "./scripts/jest/preprocessor.js" - }, - "setupFiles": [ - "./scripts/jest/fiber.setup.js", - "./scripts/jest/environment.js" - ], - "setupTestFrameworkScriptFile": "./scripts/jest/test-framework-setup.js", - "testRegex": "/__tests__/.*(\\.js|coffee|ts)$", - "moduleFileExtensions": [ - "js", - "json", - "node", - "coffee", - "ts" - ], - "roots": [ - "/eslint-rules", - "/mocks", - "/scripts", - "/src", - "node_modules/fbjs" - ], - "collectCoverageFrom": [ - "src/**/*.js", - "!src/__mocks__/vendor/third_party/*.js", - "!src/test/*.js" - ], - "timers": "fake" -} diff --git a/scripts/jest/fiber.setup.js b/scripts/jest/setup.js similarity index 74% rename from scripts/jest/fiber.setup.js rename to scripts/jest/setup.js index 9972f16fff8..a0fbd78530a 100644 --- a/scripts/jest/fiber.setup.js +++ b/scripts/jest/setup.js @@ -2,12 +2,6 @@ // We want to globally mock this but jest doesn't let us do that by default // for a file that already exists. So we have to explicitly mock it. -jest.mock('ReactDOMFeatureFlags', () => { - const flags = require.requireActual('ReactDOMFeatureFlags'); - return Object.assign({}, flags, { - useFiber: true, - }); -}); jest.mock('ReactFeatureFlags', () => { const flags = require.requireActual('ReactFeatureFlags'); return Object.assign({}, flags, { diff --git a/scripts/jest/stack.config.json b/scripts/jest/stack.config.json deleted file mode 100644 index 77972ca00cb..00000000000 --- a/scripts/jest/stack.config.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "modulePathIgnorePatterns": [ - "/.module-cache/", - "/build/", - "/scripts/rollup/shims/", - "/scripts/bench/" - ], - "rootDir": "../../", - "transform": { - ".*": "./scripts/jest/preprocessor.js" - }, - "setupFiles": [ - "./scripts/jest/stack.setup.js", - "./scripts/jest/environment.js" - ], - "setupTestFrameworkScriptFile": "./scripts/jest/test-framework-setup.js", - "testRegex": "/__tests__/.*(\\.js|coffee|ts)$", - "moduleFileExtensions": [ - "js", - "json", - "node", - "coffee", - "ts" - ], - "roots": [ - "/eslint-rules", - "/mocks", - "/scripts", - "/src", - "node_modules/fbjs" - ], - "collectCoverageFrom": [ - "src/**/*.js", - "!src/__mocks__/vendor/third_party/*.js", - "!src/test/*.js" - ], - "timers": "fake" -} diff --git a/scripts/jest/stack.setup.js b/scripts/jest/stack.setup.js deleted file mode 100644 index 820ad8c5c0e..00000000000 --- a/scripts/jest/stack.setup.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; - -// We want to globally mock this but jest doesn't let us do that by default -// for a file that already exists. So we have to explicitly mock it. -jest.mock('ReactDOMFeatureFlags', () => { - const flags = require.requireActual('ReactDOMFeatureFlags'); - return Object.assign({}, flags, { - useFiber: false, - }); -}); - -// Error logging varies between Fiber and Stack; -// Rather than fork dozens of tests, mock the error-logging file by default. -jest.mock('ReactFiberErrorLogger'); From f3c1f234d71d5bd9a8d0884ab02040438e9a72dc Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Wed, 23 Aug 2017 11:07:56 +0100 Subject: [PATCH 2/5] Remove Stack reconciler and ReactDOMStack code --- scripts/rollup/packaging.js | 2 +- src/renderers/dom/ReactDOMServerStackEntry.js | 37 - src/renderers/dom/ReactDOMStackEntry.js | 170 --- .../dom/stack/client/DOMChildrenOperations.js | 250 --- src/renderers/dom/stack/client/DOMLazyTree.js | 130 -- src/renderers/dom/stack/client/Danger.js | 56 - .../ReactComponentBrowserEnvironment.js | 28 - .../dom/stack/client/ReactDOMComponent.js | 1197 --------------- .../dom/stack/client/ReactDOMContainerInfo.js | 36 - .../stack/client/ReactDOMEmptyComponent.js | 63 - .../dom/stack/client/ReactDOMIDOperations.js | 33 - .../stack/client/ReactDOMStackInjection.js | 54 - .../dom/stack/client/ReactDOMTextComponent.js | 187 --- src/renderers/dom/stack/client/ReactMount.js | 780 ---------- .../stack/client/ReactReconcileTransaction.js | 180 --- .../stack/client/wrappers/ReactDOMInput.js | 339 ----- .../stack/client/wrappers/ReactDOMOption.js | 130 -- .../stack/client/wrappers/ReactDOMSelect.js | 205 --- .../stack/client/wrappers/ReactDOMTextarea.js | 175 --- .../dom/stack/server/ReactMarkupChecksum.js | 55 - .../server/ReactServerBatchingStrategy.js | 22 - .../dom/stack/server/ReactServerRendering.js | 104 -- .../server/ReactServerRenderingTransaction.js | 88 -- .../stack/server/ReactServerUpdateQueue.js | 152 -- .../{shared/stack => native}/PooledClass.js | 0 .../__tests__/PooledClass-test.js | 0 .../shared/shouldUpdateReactComponent.js | 45 - .../shared/stack/reconciler/CallbackQueue.js | 108 -- .../shared/stack/reconciler/KeyEscapeUtils.js | 65 - .../stack/reconciler/ReactChildReconciler.js | 214 --- .../reconciler/ReactComponentEnvironment.js | 55 - .../reconciler/ReactCompositeComponent.js | 1349 ----------------- .../ReactCompositeComponentTypes.js | 19 - .../reconciler/ReactDebugCurrentStack.js | 38 - .../ReactDefaultBatchingStrategy.js | 66 - .../stack/reconciler/ReactEmptyComponent.js | 30 - .../stack/reconciler/ReactHostComponent.js | 70 - .../stack/reconciler/ReactInstanceType.js | 49 - .../stack/reconciler/ReactMultiChild.js | 546 ------- .../reconciler/ReactMultiChildUpdateTypes.js | 25 - .../shared/stack/reconciler/ReactNodeTypes.js | 40 - .../shared/stack/reconciler/ReactOwner.js | 135 -- .../stack/reconciler/ReactReconciler.js | 225 --- .../shared/stack/reconciler/ReactRef.js | 146 -- .../reconciler/ReactSimpleEmptyComponent.js | 51 - .../stack/reconciler/ReactUpdateQueue.js | 257 ---- .../shared/stack/reconciler/ReactUpdates.js | 222 --- .../shared/stack/reconciler/Transaction.js | 243 --- .../reconciler/__tests__/Transaction-test.js | 308 ---- .../stack/reconciler/flattenStackChildren.js | 111 -- .../getHostComponentFromComposite.js | 30 - .../reconciler/instantiateReactComponent.js | 158 -- .../stack/reconciler/traverseStackChildren.js | 200 --- 53 files changed, 1 insertion(+), 9277 deletions(-) delete mode 100644 src/renderers/dom/ReactDOMServerStackEntry.js delete mode 100644 src/renderers/dom/ReactDOMStackEntry.js delete mode 100644 src/renderers/dom/stack/client/DOMChildrenOperations.js delete mode 100644 src/renderers/dom/stack/client/DOMLazyTree.js delete mode 100644 src/renderers/dom/stack/client/Danger.js delete mode 100644 src/renderers/dom/stack/client/ReactComponentBrowserEnvironment.js delete mode 100644 src/renderers/dom/stack/client/ReactDOMComponent.js delete mode 100644 src/renderers/dom/stack/client/ReactDOMContainerInfo.js delete mode 100644 src/renderers/dom/stack/client/ReactDOMEmptyComponent.js delete mode 100644 src/renderers/dom/stack/client/ReactDOMIDOperations.js delete mode 100644 src/renderers/dom/stack/client/ReactDOMStackInjection.js delete mode 100644 src/renderers/dom/stack/client/ReactDOMTextComponent.js delete mode 100644 src/renderers/dom/stack/client/ReactMount.js delete mode 100644 src/renderers/dom/stack/client/ReactReconcileTransaction.js delete mode 100644 src/renderers/dom/stack/client/wrappers/ReactDOMInput.js delete mode 100644 src/renderers/dom/stack/client/wrappers/ReactDOMOption.js delete mode 100644 src/renderers/dom/stack/client/wrappers/ReactDOMSelect.js delete mode 100644 src/renderers/dom/stack/client/wrappers/ReactDOMTextarea.js delete mode 100644 src/renderers/dom/stack/server/ReactMarkupChecksum.js delete mode 100644 src/renderers/dom/stack/server/ReactServerBatchingStrategy.js delete mode 100644 src/renderers/dom/stack/server/ReactServerRendering.js delete mode 100644 src/renderers/dom/stack/server/ReactServerRenderingTransaction.js delete mode 100644 src/renderers/dom/stack/server/ReactServerUpdateQueue.js rename src/renderers/{shared/stack => native}/PooledClass.js (100%) rename src/renderers/{shared/stack => native}/__tests__/PooledClass-test.js (100%) delete mode 100644 src/renderers/shared/shared/shouldUpdateReactComponent.js delete mode 100644 src/renderers/shared/stack/reconciler/CallbackQueue.js delete mode 100644 src/renderers/shared/stack/reconciler/KeyEscapeUtils.js delete mode 100644 src/renderers/shared/stack/reconciler/ReactChildReconciler.js delete mode 100644 src/renderers/shared/stack/reconciler/ReactComponentEnvironment.js delete mode 100644 src/renderers/shared/stack/reconciler/ReactCompositeComponent.js delete mode 100644 src/renderers/shared/stack/reconciler/ReactCompositeComponentTypes.js delete mode 100644 src/renderers/shared/stack/reconciler/ReactDebugCurrentStack.js delete mode 100644 src/renderers/shared/stack/reconciler/ReactDefaultBatchingStrategy.js delete mode 100644 src/renderers/shared/stack/reconciler/ReactEmptyComponent.js delete mode 100644 src/renderers/shared/stack/reconciler/ReactHostComponent.js delete mode 100644 src/renderers/shared/stack/reconciler/ReactInstanceType.js delete mode 100644 src/renderers/shared/stack/reconciler/ReactMultiChild.js delete mode 100644 src/renderers/shared/stack/reconciler/ReactMultiChildUpdateTypes.js delete mode 100644 src/renderers/shared/stack/reconciler/ReactNodeTypes.js delete mode 100644 src/renderers/shared/stack/reconciler/ReactOwner.js delete mode 100644 src/renderers/shared/stack/reconciler/ReactReconciler.js delete mode 100644 src/renderers/shared/stack/reconciler/ReactRef.js delete mode 100644 src/renderers/shared/stack/reconciler/ReactSimpleEmptyComponent.js delete mode 100644 src/renderers/shared/stack/reconciler/ReactUpdateQueue.js delete mode 100644 src/renderers/shared/stack/reconciler/ReactUpdates.js delete mode 100644 src/renderers/shared/stack/reconciler/Transaction.js delete mode 100644 src/renderers/shared/stack/reconciler/__tests__/Transaction-test.js delete mode 100644 src/renderers/shared/stack/reconciler/flattenStackChildren.js delete mode 100644 src/renderers/shared/stack/reconciler/getHostComponentFromComposite.js delete mode 100644 src/renderers/shared/stack/reconciler/instantiateReactComponent.js delete mode 100644 src/renderers/shared/stack/reconciler/traverseStackChildren.js diff --git a/scripts/rollup/packaging.js b/scripts/rollup/packaging.js index e5cf6f7eae6..caa09834c50 100644 --- a/scripts/rollup/packaging.js +++ b/scripts/rollup/packaging.js @@ -25,7 +25,7 @@ const facebookWWWSrcDependencies = [ // these files need to be copied to the react-native build const reactNativeSrcDependencies = [ // TODO: copy this to RN repository and delete from React - 'src/renderers/shared/stack/PooledClass.js', + 'src/renderers/native/PooledClass.js', 'src/renderers/shared/fiber/isomorphic/ReactTypes.js', 'src/renderers/native/ReactNativeTypes.js', ]; diff --git a/src/renderers/dom/ReactDOMServerStackEntry.js b/src/renderers/dom/ReactDOMServerStackEntry.js deleted file mode 100644 index 67ca724da8f..00000000000 --- a/src/renderers/dom/ReactDOMServerStackEntry.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright 2013-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. - * - * @providesModule ReactDOMServerStackEntry - */ - -'use strict'; - -var ReactServerRendering = require('ReactServerRendering'); -var ReactVersion = require('ReactVersion'); - -require('ReactDOMInjection'); -require('ReactDOMStackInjection'); - -var ReactDOMServerStack = { - renderToString: ReactServerRendering.renderToString, - renderToStaticMarkup: ReactServerRendering.renderToStaticMarkup, - version: ReactVersion, -}; - -if (__DEV__) { - var ReactInstrumentation = require('ReactInstrumentation'); - var ReactDOMUnknownPropertyHook = require('ReactDOMUnknownPropertyHook'); - var ReactDOMNullInputValuePropHook = require('ReactDOMNullInputValuePropHook'); - var ReactDOMInvalidARIAHook = require('ReactDOMInvalidARIAHook'); - - ReactInstrumentation.debugTool.addHook(ReactDOMUnknownPropertyHook); - ReactInstrumentation.debugTool.addHook(ReactDOMNullInputValuePropHook); - ReactInstrumentation.debugTool.addHook(ReactDOMInvalidARIAHook); -} - -module.exports = ReactDOMServerStack; diff --git a/src/renderers/dom/ReactDOMStackEntry.js b/src/renderers/dom/ReactDOMStackEntry.js deleted file mode 100644 index fe12a60eb07..00000000000 --- a/src/renderers/dom/ReactDOMStackEntry.js +++ /dev/null @@ -1,170 +0,0 @@ -/** - * Copyright 2013-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. - * - * @providesModule ReactDOMStackEntry - */ - -/* globals __REACT_DEVTOOLS_GLOBAL_HOOK__*/ - -'use strict'; - -require('checkReact'); -var ReactDOMComponentTree = require('ReactDOMComponentTree'); -var ReactGenericBatching = require('ReactGenericBatching'); -var ReactMount = require('ReactMount'); -var ReactUpdates = require('ReactUpdates'); -var ReactReconciler = require('ReactReconciler'); -var ReactVersion = require('ReactVersion'); - -var findDOMNode = require('findDOMNode'); -var getHostComponentFromComposite = require('getHostComponentFromComposite'); - -if (__DEV__) { - var warning = require('fbjs/lib/warning'); -} - -require('ReactDOMInjection'); -require('ReactDOMClientInjection'); -require('ReactDOMStackInjection'); - -var ReactDOMStack = { - findDOMNode: findDOMNode, - render: ReactMount.render, - unmountComponentAtNode: ReactMount.unmountComponentAtNode, - version: ReactVersion, - - /* eslint-disable camelcase */ - unstable_batchedUpdates: ReactGenericBatching.batchedUpdates, - unstable_renderSubtreeIntoContainer: ReactMount.renderSubtreeIntoContainer, - /* eslint-enable camelcase */ - - __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: { - // For TapEventPlugin which is popular in open source - EventPluginHub: require('EventPluginHub'), - // Used by test-utils - EventPluginRegistry: require('EventPluginRegistry'), - EventPropagators: require('EventPropagators'), - ReactControlledComponent: require('ReactControlledComponent'), - ReactDOMComponentTree, - ReactDOMEventListener: require('ReactDOMEventListener'), - ReactUpdates: ReactUpdates, - }, -}; - -// Inject the runtime into a devtools global hook regardless of browser. -// Allows for debugging when the hook is injected on the page. -if ( - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.inject === 'function' -) { - __REACT_DEVTOOLS_GLOBAL_HOOK__.inject({ - ComponentTree: { - getClosestInstanceFromNode: ReactDOMComponentTree.getClosestInstanceFromNode, - getNodeFromInstance: function(inst) { - // inst is an internal instance (but could be a composite) - if (inst._renderedComponent) { - inst = getHostComponentFromComposite(inst); - } - if (inst) { - return ReactDOMComponentTree.getNodeFromInstance(inst); - } else { - return null; - } - }, - }, - Mount: ReactMount, - Reconciler: ReactReconciler, - rendererPackageName: 'react-dom', - }); -} - -if (__DEV__) { - var ExecutionEnvironment = require('fbjs/lib/ExecutionEnvironment'); - if (ExecutionEnvironment.canUseDOM && window.top === window.self) { - // First check if devtools is not installed - if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') { - // If we're in Chrome or Firefox, provide a download link if not installed. - if ( - (navigator.userAgent.indexOf('Chrome') > -1 && - navigator.userAgent.indexOf('Edge') === -1) || - navigator.userAgent.indexOf('Firefox') > -1 - ) { - // Firefox does not have the issue with devtools loaded over file:// - var showFileUrlMessage = - window.location.protocol.indexOf('http') === -1 && - navigator.userAgent.indexOf('Firefox') === -1; - console.debug( - 'Download the React DevTools ' + - (showFileUrlMessage - ? 'and use an HTTP server (instead of a file: URL) ' - : '') + - 'for a better development experience: ' + - 'https://fb.me/react-devtools', - ); - } - } - - var testFunc = function testFn() {}; - warning( - (testFunc.name || testFunc.toString()).indexOf('testFn') !== -1, - "It looks like you're using a minified copy of the development build " + - 'of React. When deploying React apps to production, make sure to use ' + - 'the production build which skips development warnings and is faster. ' + - 'See https://fb.me/react-minification for more details.', - ); - - // If we're in IE8, check to see if we are in compatibility mode and provide - // information on preventing compatibility mode - var ieCompatibilityMode = - document.documentMode && document.documentMode < 8; - - warning( - !ieCompatibilityMode, - 'Internet Explorer is running in compatibility mode; please add the ' + - 'following tag to your HTML to prevent this from happening: ' + - '', - ); - - var expectedFeatures = [ - // shims - Array.isArray, - Array.prototype.every, - Array.prototype.forEach, - Array.prototype.indexOf, - Array.prototype.map, - Date.now, - Function.prototype.bind, - Object.keys, - String.prototype.trim, - ]; - - for (var i = 0; i < expectedFeatures.length; i++) { - if (!expectedFeatures[i]) { - warning( - false, - 'One or more ES5 shims expected by React are not available: ' + - 'https://fb.me/react-warning-polyfills', - ); - break; - } - } - } -} - -if (__DEV__) { - var ReactInstrumentation = require('ReactInstrumentation'); - var ReactDOMUnknownPropertyHook = require('ReactDOMUnknownPropertyHook'); - var ReactDOMNullInputValuePropHook = require('ReactDOMNullInputValuePropHook'); - var ReactDOMInvalidARIAHook = require('ReactDOMInvalidARIAHook'); - - ReactInstrumentation.debugTool.addHook(ReactDOMUnknownPropertyHook); - ReactInstrumentation.debugTool.addHook(ReactDOMNullInputValuePropHook); - ReactInstrumentation.debugTool.addHook(ReactDOMInvalidARIAHook); -} - -module.exports = ReactDOMStack; diff --git a/src/renderers/dom/stack/client/DOMChildrenOperations.js b/src/renderers/dom/stack/client/DOMChildrenOperations.js deleted file mode 100644 index b7e4e1e105d..00000000000 --- a/src/renderers/dom/stack/client/DOMChildrenOperations.js +++ /dev/null @@ -1,250 +0,0 @@ -/** - * Copyright 2013-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. - * - * @providesModule DOMChildrenOperations - */ - -'use strict'; - -var DOMLazyTree = require('DOMLazyTree'); -var Danger = require('Danger'); -var ReactDOMComponentTree = require('ReactDOMComponentTree'); -var ReactInstrumentation = require('ReactInstrumentation'); - -var createMicrosoftUnsafeLocalFunction = require('createMicrosoftUnsafeLocalFunction'); -var setInnerHTML = require('setInnerHTML'); -var setTextContent = require('setTextContent'); - -function getNodeAfter(parentNode, node) { - // Special case for text components, which return [open, close] comments - // from getHostNode. - if (Array.isArray(node)) { - node = node[1]; - } - return node ? node.nextSibling : parentNode.firstChild; -} - -/** - * Inserts `childNode` as a child of `parentNode` at the `index`. - * - * @param {DOMElement} parentNode Parent node in which to insert. - * @param {DOMElement} childNode Child node to insert. - * @param {number} index Index at which to insert the child. - * @internal - */ -var insertChildAt = createMicrosoftUnsafeLocalFunction(function( - parentNode, - childNode, - referenceNode, -) { - // We rely exclusively on `insertBefore(node, null)` instead of also using - // `appendChild(node)`. (Using `undefined` is not allowed by all browsers so - // we are careful to use `null`.) - parentNode.insertBefore(childNode, referenceNode); -}); - -function insertLazyTreeChildAt(parentNode, childTree, referenceNode) { - DOMLazyTree.insertTreeBefore(parentNode, childTree, referenceNode); -} - -function moveChild(parentNode, childNode, referenceNode) { - if (Array.isArray(childNode)) { - moveDelimitedText(parentNode, childNode[0], childNode[1], referenceNode); - } else { - insertChildAt(parentNode, childNode, referenceNode); - } -} - -function removeChild(parentNode, childNode) { - if (Array.isArray(childNode)) { - var closingComment = childNode[1]; - childNode = childNode[0]; - removeDelimitedText(parentNode, childNode, closingComment); - parentNode.removeChild(closingComment); - } - parentNode.removeChild(childNode); -} - -function moveDelimitedText( - parentNode, - openingComment, - closingComment, - referenceNode, -) { - var node = openingComment; - while (true) { - var nextNode = node.nextSibling; - insertChildAt(parentNode, node, referenceNode); - if (node === closingComment) { - break; - } - node = nextNode; - } -} - -function removeDelimitedText(parentNode, startNode, closingComment) { - while (true) { - var node = startNode.nextSibling; - if (node === closingComment) { - // The closing comment is removed by ReactMultiChild. - break; - } else { - parentNode.removeChild(node); - } - } -} - -function replaceDelimitedText(openingComment, closingComment, stringText) { - var parentNode = openingComment.parentNode; - var nodeAfterComment = openingComment.nextSibling; - if (nodeAfterComment === closingComment) { - // There are no text nodes between the opening and closing comments; insert - // a new one if stringText isn't empty. - if (stringText) { - insertChildAt( - parentNode, - document.createTextNode(stringText), - nodeAfterComment, - ); - } - } else { - if (stringText) { - // Set the text content of the first node after the opening comment, and - // remove all following nodes up until the closing comment. - setTextContent(nodeAfterComment, stringText); - removeDelimitedText(parentNode, nodeAfterComment, closingComment); - } else { - removeDelimitedText(parentNode, openingComment, closingComment); - } - } - - if (__DEV__) { - ReactInstrumentation.debugTool.onHostOperation({ - instanceID: ReactDOMComponentTree.getInstanceFromNode(openingComment) - ._debugID, - type: 'replace text', - payload: stringText, - }); - } -} - -var dangerouslyReplaceNodeWithMarkup = Danger.dangerouslyReplaceNodeWithMarkup; -if (__DEV__) { - dangerouslyReplaceNodeWithMarkup = function(oldChild, markup, prevInstance) { - Danger.dangerouslyReplaceNodeWithMarkup(oldChild, markup); - if (prevInstance._debugID !== 0) { - ReactInstrumentation.debugTool.onHostOperation({ - instanceID: prevInstance._debugID, - type: 'replace with', - payload: markup.toString(), - }); - } else { - var nextInstance = ReactDOMComponentTree.getInstanceFromNode(markup.node); - if (nextInstance._debugID !== 0) { - ReactInstrumentation.debugTool.onHostOperation({ - instanceID: nextInstance._debugID, - type: 'mount', - payload: markup.toString(), - }); - } - } - }; -} - -/** - * Operations for updating with DOM children. - */ -var DOMChildrenOperations = { - dangerouslyReplaceNodeWithMarkup: dangerouslyReplaceNodeWithMarkup, - - replaceDelimitedText: replaceDelimitedText, - - /** - * Updates a component's children by processing a series of updates. The - * update configurations are each expected to have a `parentNode` property. - * - * @param {array} updates List of update configurations. - * @internal - */ - processUpdates: function(parentNode, updates) { - if (__DEV__) { - var parentNodeDebugID = ReactDOMComponentTree.getInstanceFromNode( - parentNode, - )._debugID; - } - - for (var k = 0; k < updates.length; k++) { - var update = updates[k]; - switch (update.type) { - case 'INSERT_MARKUP': - insertLazyTreeChildAt( - parentNode, - update.content, - getNodeAfter(parentNode, update.afterNode), - ); - if (__DEV__) { - ReactInstrumentation.debugTool.onHostOperation({ - instanceID: parentNodeDebugID, - type: 'insert child', - payload: { - toIndex: update.toIndex, - content: update.content.toString(), - }, - }); - } - break; - case 'MOVE_EXISTING': - moveChild( - parentNode, - update.fromNode, - getNodeAfter(parentNode, update.afterNode), - ); - if (__DEV__) { - ReactInstrumentation.debugTool.onHostOperation({ - instanceID: parentNodeDebugID, - type: 'move child', - payload: {fromIndex: update.fromIndex, toIndex: update.toIndex}, - }); - } - break; - case 'SET_MARKUP': - setInnerHTML(parentNode, update.content); - if (__DEV__) { - ReactInstrumentation.debugTool.onHostOperation({ - instanceID: parentNodeDebugID, - type: 'replace children', - payload: update.content.toString(), - }); - } - break; - case 'TEXT_CONTENT': - setTextContent(parentNode, update.content); - if (__DEV__) { - ReactInstrumentation.debugTool.onHostOperation({ - instanceID: parentNodeDebugID, - type: 'replace text', - payload: update.content.toString(), - }); - } - break; - case 'REMOVE_NODE': - removeChild(parentNode, update.fromNode); - if (__DEV__) { - ReactInstrumentation.debugTool.onHostOperation({ - instanceID: parentNodeDebugID, - type: 'remove child', - payload: {fromIndex: update.fromIndex}, - }); - } - break; - } - } - }, -}; - -module.exports = DOMChildrenOperations; diff --git a/src/renderers/dom/stack/client/DOMLazyTree.js b/src/renderers/dom/stack/client/DOMLazyTree.js deleted file mode 100644 index c1533ace2fa..00000000000 --- a/src/renderers/dom/stack/client/DOMLazyTree.js +++ /dev/null @@ -1,130 +0,0 @@ -/** - * Copyright 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. - * - * @providesModule DOMLazyTree - */ - -'use strict'; - -var Namespaces = require('DOMNamespaces').Namespaces; -var setInnerHTML = require('setInnerHTML'); -var {DOCUMENT_FRAGMENT_NODE, ELEMENT_NODE} = require('HTMLNodeType'); -var createMicrosoftUnsafeLocalFunction = require('createMicrosoftUnsafeLocalFunction'); -var setTextContent = require('setTextContent'); - -/** - * In IE (8-11) and Edge, appending nodes with no children is dramatically - * faster than appending a full subtree, so we essentially queue up the - * .appendChild calls here and apply them so each node is added to its parent - * before any children are added. - * - * In other browsers, doing so is slower or neutral compared to the other order - * (in Firefox, twice as slow) so we only do this inversion in IE. - * - * See https://github.com/sophiebits/innerhtml-vs-createelement-vs-clonenode. - */ -var enableLazy = - (typeof document !== 'undefined' && - typeof document.documentMode === 'number') || - (typeof navigator !== 'undefined' && - typeof navigator.userAgent === 'string' && - /\bEdge\/\d/.test(navigator.userAgent)); - -function insertTreeChildren(tree) { - if (!enableLazy) { - return; - } - var node = tree.node; - var children = tree.children; - if (children.length) { - for (var i = 0; i < children.length; i++) { - insertTreeBefore(node, children[i], null); - } - } else if (tree.html != null) { - setInnerHTML(node, tree.html); - } else if (tree.text != null) { - setTextContent(node, tree.text); - } -} - -var insertTreeBefore = createMicrosoftUnsafeLocalFunction(function( - parentNode, - tree, - referenceNode, -) { - // DocumentFragments aren't actually part of the DOM after insertion so - // appending children won't update the DOM. We need to ensure the fragment - // is properly populated first, breaking out of our lazy approach for just - // this level. Also, some plugins (like Flash Player) will read - // nodes immediately upon insertion into the DOM, so - // must also be populated prior to insertion into the DOM. - if ( - tree.node.nodeType === DOCUMENT_FRAGMENT_NODE || - (tree.node.nodeType === ELEMENT_NODE && - tree.node.nodeName.toLowerCase() === 'object' && - (tree.node.namespaceURI == null || - tree.node.namespaceURI === Namespaces.html)) - ) { - insertTreeChildren(tree); - parentNode.insertBefore(tree.node, referenceNode); - } else { - parentNode.insertBefore(tree.node, referenceNode); - insertTreeChildren(tree); - } -}); - -function replaceChildWithTree(oldNode, newTree) { - oldNode.parentNode.replaceChild(newTree.node, oldNode); - insertTreeChildren(newTree); -} - -function queueChild(parentTree, childTree) { - if (enableLazy) { - parentTree.children.push(childTree); - } else { - parentTree.node.appendChild(childTree.node); - } -} - -function queueHTML(tree, html) { - if (enableLazy) { - tree.html = html; - } else { - setInnerHTML(tree.node, html); - } -} - -function queueText(tree, text) { - if (enableLazy) { - tree.text = text; - } else { - setTextContent(tree.node, text); - } -} - -function toString() { - return this.node.nodeName; -} - -function DOMLazyTree(node) { - return { - node: node, - children: [], - html: null, - text: null, - toString, - }; -} - -DOMLazyTree.insertTreeBefore = insertTreeBefore; -DOMLazyTree.replaceChildWithTree = replaceChildWithTree; -DOMLazyTree.queueChild = queueChild; -DOMLazyTree.queueHTML = queueHTML; -DOMLazyTree.queueText = queueText; - -module.exports = DOMLazyTree; diff --git a/src/renderers/dom/stack/client/Danger.js b/src/renderers/dom/stack/client/Danger.js deleted file mode 100644 index 77542e52c88..00000000000 --- a/src/renderers/dom/stack/client/Danger.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright 2013-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. - * - * @providesModule Danger - */ - -'use strict'; - -var DOMLazyTree = require('DOMLazyTree'); -var ExecutionEnvironment = require('fbjs/lib/ExecutionEnvironment'); - -var createNodesFromMarkup = require('fbjs/lib/createNodesFromMarkup'); -var emptyFunction = require('fbjs/lib/emptyFunction'); -var invariant = require('fbjs/lib/invariant'); - -var Danger = { - /** - * Replaces a node with a string of markup at its current position within its - * parent. The markup must render into a single root node. - * - * @param {DOMElement} oldChild Child node to replace. - * @param {string} markup Markup to render in place of the child node. - * @internal - */ - dangerouslyReplaceNodeWithMarkup: function(oldChild, markup) { - invariant( - ExecutionEnvironment.canUseDOM, - 'dangerouslyReplaceNodeWithMarkup(...): Cannot render markup in a ' + - 'worker thread. Make sure `window` and `document` are available ' + - 'globally before requiring React when unit testing or use ' + - 'ReactDOMServer.renderToString() for server rendering.', - ); - invariant(markup, 'dangerouslyReplaceNodeWithMarkup(...): Missing markup.'); - invariant( - oldChild.nodeName !== 'HTML', - 'dangerouslyReplaceNodeWithMarkup(...): Cannot replace markup of the ' + - ' node. This is because browser quirks make this unreliable ' + - 'and/or slow. If you want to render to the root you must use ' + - 'server rendering. See ReactDOMServer.renderToString().', - ); - - if (typeof markup === 'string') { - var newChild = createNodesFromMarkup(markup, emptyFunction)[0]; - oldChild.parentNode.replaceChild(newChild, oldChild); - } else { - DOMLazyTree.replaceChildWithTree(oldChild, markup); - } - }, -}; - -module.exports = Danger; diff --git a/src/renderers/dom/stack/client/ReactComponentBrowserEnvironment.js b/src/renderers/dom/stack/client/ReactComponentBrowserEnvironment.js deleted file mode 100644 index fe874cdc6c4..00000000000 --- a/src/renderers/dom/stack/client/ReactComponentBrowserEnvironment.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Copyright 2013-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. - * - * @providesModule ReactComponentBrowserEnvironment - */ - -'use strict'; - -var DOMChildrenOperations = require('DOMChildrenOperations'); -var ReactDOMIDOperations = require('ReactDOMIDOperations'); - -/** - * Abstracts away all functionality of the reconciler that requires knowledge of - * the browser context. TODO: These callers should be refactored to avoid the - * need for this injection. - */ -var ReactComponentBrowserEnvironment = { - processChildrenUpdates: ReactDOMIDOperations.dangerouslyProcessChildrenUpdates, - - replaceNodeWithMarkup: DOMChildrenOperations.dangerouslyReplaceNodeWithMarkup, -}; - -module.exports = ReactComponentBrowserEnvironment; diff --git a/src/renderers/dom/stack/client/ReactDOMComponent.js b/src/renderers/dom/stack/client/ReactDOMComponent.js deleted file mode 100644 index daf427fcc9e..00000000000 --- a/src/renderers/dom/stack/client/ReactDOMComponent.js +++ /dev/null @@ -1,1197 +0,0 @@ -/** - * Copyright 2013-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. - * - * @providesModule ReactDOMComponent - */ - -'use strict'; - -var AutoFocusUtils = require('AutoFocusUtils'); -var CSSPropertyOperations = require('CSSPropertyOperations'); -var DOMLazyTree = require('DOMLazyTree'); -var Namespaces = require('DOMNamespaces').Namespaces; -var DOMMarkupOperations = require('DOMMarkupOperations'); -var DOMProperty = require('DOMProperty'); -var DOMPropertyOperations = require('DOMPropertyOperations'); -var EventPluginRegistry = require('EventPluginRegistry'); -var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter'); -var ReactDOMComponentFlags = require('ReactDOMComponentFlags'); -var ReactDOMComponentTree = require('ReactDOMComponentTree'); -var ReactDOMInput = require('ReactDOMInput'); -var ReactDOMOption = require('ReactDOMOption'); -var ReactDOMSelect = require('ReactDOMSelect'); -var ReactDOMTextarea = require('ReactDOMTextarea'); -var ReactInstrumentation = require('ReactInstrumentation'); -var ReactMultiChild = require('ReactMultiChild'); -var ReactServerRenderingTransaction = require('ReactServerRenderingTransaction'); -var {DOCUMENT_FRAGMENT_NODE} = require('HTMLNodeType'); - -var dangerousStyleValue = require('dangerousStyleValue'); -var emptyFunction = require('fbjs/lib/emptyFunction'); -var escapeTextContentForBrowser = require('escapeTextContentForBrowser'); -var hyphenateStyleName = require('fbjs/lib/hyphenateStyleName'); -var inputValueTracking = require('inputValueTracking'); -var invariant = require('fbjs/lib/invariant'); -var isCustomComponent = require('isCustomComponent'); -var memoizeStringOnly = require('fbjs/lib/memoizeStringOnly'); -var omittedCloseTags = require('omittedCloseTags'); -var validateDOMNesting = require('validateDOMNesting'); -var voidElementTags = require('voidElementTags'); -var warnValidStyle = require('warnValidStyle'); - -if (__DEV__) { - var warning = require('fbjs/lib/warning'); -} - -var didWarnShadyDOM = false; - -var Flags = ReactDOMComponentFlags; -var getNode = ReactDOMComponentTree.getNodeFromInstance; -var listenTo = ReactBrowserEventEmitter.listenTo; -var registrationNameModules = EventPluginRegistry.registrationNameModules; - -// For quickly matching children type, to test if can be treated as content. -var CONTENT_TYPES = {string: true, number: true}; - -var STYLE = 'style'; -var HTML = '__html'; - -function getDeclarationErrorAddendum(internalInstance) { - if (internalInstance) { - var owner = internalInstance._currentElement._owner || null; - if (owner) { - var name = owner.getName(); - if (name) { - return '\n\nThis DOM node was rendered by `' + name + '`.'; - } - } - } - return ''; -} - -/** - * @param {object} component - * @param {?object} props - */ -function assertValidProps(component, props) { - if (!props) { - return; - } - // Note the use of `==` which checks for null or undefined. - if (voidElementTags[component._tag]) { - invariant( - props.children == null && props.dangerouslySetInnerHTML == null, - '%s is a void element tag and must neither have `children` nor ' + - 'use `dangerouslySetInnerHTML`.%s', - component._tag, - getDeclarationErrorAddendum(component), - ); - } - if (props.dangerouslySetInnerHTML != null) { - invariant( - props.children == null, - 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.', - ); - invariant( - typeof props.dangerouslySetInnerHTML === 'object' && - HTML in props.dangerouslySetInnerHTML, - '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' + - 'Please visit https://fb.me/react-invariant-dangerously-set-inner-html ' + - 'for more information.', - ); - } - if (__DEV__) { - warning( - props.suppressContentEditableWarning || - !props.contentEditable || - props.children == null, - 'A component is `contentEditable` and contains `children` managed by ' + - 'React. It is now your responsibility to guarantee that none of ' + - 'those nodes are unexpectedly modified or duplicated. This is ' + - 'probably not intentional.', - ); - } - invariant( - props.style == null || typeof props.style === 'object', - 'The `style` prop expects a mapping from style properties to values, ' + - "not a string. For example, style={{marginRight: spacing + 'em'}} when " + - 'using JSX.%s', - getDeclarationErrorAddendum(component), - ); -} - -function ensureListeningTo(inst, registrationName, transaction) { - if (transaction instanceof ReactServerRenderingTransaction) { - return; - } - var containerInfo = inst._hostContainerInfo; - var isDocumentFragment = - containerInfo._node && - containerInfo._node.nodeType === DOCUMENT_FRAGMENT_NODE; - var doc = isDocumentFragment - ? containerInfo._node - : containerInfo._ownerDocument; - listenTo(registrationName, doc); -} - -function inputPostMount() { - var inst = this; - ReactDOMInput.postMountWrapper(inst); -} - -function textareaPostMount() { - var inst = this; - ReactDOMTextarea.postMountWrapper(inst); -} - -function optionPostMount() { - var inst = this; - ReactDOMOption.postMountWrapper(inst); -} - -var processStyleName = memoizeStringOnly(function(styleName) { - return hyphenateStyleName(styleName); -}); - -function createMarkupForStyles(styles, component) { - var serialized = ''; - var delimiter = ''; - for (var styleName in styles) { - if (!styles.hasOwnProperty(styleName)) { - continue; - } - var isCustomProperty = styleName.indexOf('--') === 0; - var styleValue = styles[styleName]; - if (__DEV__) { - if (!isCustomProperty) { - warnValidStyle(styleName, styleValue, component); - } - } - if (styleValue != null) { - serialized += delimiter + processStyleName(styleName) + ':'; - serialized += dangerousStyleValue( - styleName, - styleValue, - isCustomProperty, - ); - - delimiter = ';'; - } - } - return serialized || null; -} - -var setAndValidateContentChildDev = emptyFunction; -if (__DEV__) { - setAndValidateContentChildDev = function(content) { - var hasExistingContent = this._contentDebugID != null; - var debugID = this._debugID; - // This ID represents the inlined child that has no backing instance: - var contentDebugID = -debugID; - - if (content == null) { - if (hasExistingContent) { - ReactInstrumentation.debugTool.onUnmountComponent(this._contentDebugID); - } - this._contentDebugID = null; - return; - } - - validateDOMNesting(null, '' + content, this, this._ancestorInfo); - this._contentDebugID = contentDebugID; - if (hasExistingContent) { - ReactInstrumentation.debugTool.onBeforeUpdateComponent( - contentDebugID, - content, - ); - ReactInstrumentation.debugTool.onUpdateComponent(contentDebugID); - } else { - ReactInstrumentation.debugTool.onBeforeMountComponent( - contentDebugID, - content, - debugID, - ); - ReactInstrumentation.debugTool.onMountComponent(contentDebugID); - ReactInstrumentation.debugTool.onSetChildren(debugID, [contentDebugID]); - } - }; -} - -// There are so many media events, it makes sense to just -// maintain a list rather than create a `trapBubbledEvent` for each -var mediaEvents = { - topAbort: 'abort', - topCanPlay: 'canplay', - topCanPlayThrough: 'canplaythrough', - topDurationChange: 'durationchange', - topEmptied: 'emptied', - topEncrypted: 'encrypted', - topEnded: 'ended', - topError: 'error', - topLoadedData: 'loadeddata', - topLoadedMetadata: 'loadedmetadata', - topLoadStart: 'loadstart', - topPause: 'pause', - topPlay: 'play', - topPlaying: 'playing', - topProgress: 'progress', - topRateChange: 'ratechange', - topSeeked: 'seeked', - topSeeking: 'seeking', - topStalled: 'stalled', - topSuspend: 'suspend', - topTimeUpdate: 'timeupdate', - topVolumeChange: 'volumechange', - topWaiting: 'waiting', -}; - -function trackInputValue() { - inputValueTracking.track(getNode(this)); -} - -function trapClickOnNonInteractiveElement() { - // Mobile Safari does not fire properly bubble click events on - // non-interactive elements, which means delegated click listeners do not - // fire. The workaround for this bug involves attaching an empty click - // listener on the target node. - // http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html - // Just set it using the onclick property so that we don't have to manage any - // bookkeeping for it. Not sure if we need to clear it when the listener is - // removed. - // TODO: Only do this for the relevant Safaris maybe? - var node = getNode(this); - node.onclick = emptyFunction; -} - -function trapBubbledEventsLocal() { - var inst = this; - // If a component renders to null or if another component fatals and causes - // the state of the tree to be corrupted, `node` here can be null. - invariant(inst._rootNodeID, 'Must be mounted to trap events'); - var node = getNode(inst); - invariant(node, 'trapBubbledEvent(...): Requires node to be rendered.'); - - switch (inst._tag) { - case 'iframe': - case 'object': - inst._wrapperState.listeners = [ - ReactBrowserEventEmitter.trapBubbledEvent('topLoad', 'load', node), - ]; - break; - case 'video': - case 'audio': - inst._wrapperState.listeners = []; - // Create listener for each media event - for (var event in mediaEvents) { - if (mediaEvents.hasOwnProperty(event)) { - inst._wrapperState.listeners.push( - ReactBrowserEventEmitter.trapBubbledEvent( - event, - mediaEvents[event], - node, - ), - ); - } - } - break; - case 'source': - inst._wrapperState.listeners = [ - ReactBrowserEventEmitter.trapBubbledEvent('topError', 'error', node), - ]; - break; - case 'img': - case 'image': - inst._wrapperState.listeners = [ - ReactBrowserEventEmitter.trapBubbledEvent('topError', 'error', node), - ReactBrowserEventEmitter.trapBubbledEvent('topLoad', 'load', node), - ]; - break; - case 'form': - inst._wrapperState.listeners = [ - ReactBrowserEventEmitter.trapBubbledEvent('topReset', 'reset', node), - ReactBrowserEventEmitter.trapBubbledEvent('topSubmit', 'submit', node), - ]; - break; - case 'input': - case 'select': - case 'textarea': - inst._wrapperState.listeners = [ - ReactBrowserEventEmitter.trapBubbledEvent( - 'topInvalid', - 'invalid', - node, - ), - ]; - break; - case 'details': - inst._wrapperState.listeners = [ - ReactBrowserEventEmitter.trapBubbledEvent('topToggle', 'toggle', node), - ]; - break; - } -} - -function postUpdateSelectWrapper() { - ReactDOMSelect.postUpdateWrapper(this); -} - -var newlineEatingTags = { - listing: true, - pre: true, - textarea: true, -}; - -// We accept any tag to be rendered but since this gets injected into arbitrary -// HTML, we want to make sure that it's a safe tag. -// http://www.w3.org/TR/REC-xml/#NT-Name - -var VALID_TAG_REGEX = /^[a-zA-Z][a-zA-Z:_\.\-\d]*$/; // Simplified subset -var validatedTagCache = {}; - -function validateDangerousTag(tag) { - if (!validatedTagCache.hasOwnProperty(tag)) { - invariant(VALID_TAG_REGEX.test(tag), 'Invalid tag: %s', tag); - validatedTagCache[tag] = true; - } -} - -var globalIdCounter = 1; -var warnedUnknownTags = { - // Chrome is the only major browser not shipping