diff --git a/.vscode/launch.json b/.vscode/launch.json index 124dfd3..8324457 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,17 +4,12 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ - { - "type": "node", + "type": "chrome", "request": "launch", - "name": "Launch Program", - "skipFiles": [ - "/**" - ], - "program": "${workspaceFolder}/index.js", - // "program": "${workspaceFolder}/test/test.js", - "cwd": "${workspaceFolder}/PLACE-REACT-SOURCE-CODE-HERE" + "name": "Launch Chrome against localhost", + "url": "http://localhost:6001", + "webRoot": "${workspaceFolder}/react-17.0.2" } ] } \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index 8829373..0000000 --- a/README.md +++ /dev/null @@ -1 +0,0 @@ -# debug-react-source-code \ No newline at end of file diff --git a/dependencies/source-index.js b/dependencies/source-index.js deleted file mode 100644 index 7ccec15..0000000 --- a/dependencies/source-index.js +++ /dev/null @@ -1,5 +0,0 @@ -function App() { - return
Hello, React Source Code!
-} - -ReactDOM.render(, document.querySelector('#app')) \ No newline at end of file diff --git a/index.js b/index.js deleted file mode 100644 index 5a65466..0000000 --- a/index.js +++ /dev/null @@ -1,246 +0,0 @@ -const fs = require('fs') -const path = require(`path`) -const trash = require(`trash`) -const { spawn, exec } = require('child_process') -const {IDENTITY_START_STR, IDENTITY_END_STR, ANNOTATION_PREFIX} = require('./shared.js') - -const PATH_PLUGIN = path.resolve(__dirname, 'rollup-plugin-add-path-info-annoation-for-each-file.js').replace(/\\/g, '/') -const PATH_DEPENDENCIES = path.resolve(__dirname, 'dependencies').replace(/\\/g, '/') -const PATH_BUILD = path.resolve(__dirname, 'build').replace(/\\/g, '/') - - -const PATH_REACT_CONTAINER = path.resolve(__dirname, 'PLACE-REACT-SOURCE-CODE-HERE').replace(/\\/g, '/') -const dirs = fs.readdirSync(PATH_REACT_CONTAINER).filter(v => fs.lstatSync( path.resolve(PATH_REACT_CONTAINER, v).replace(/\\/g, '/') ).isDirectory()) -if (dirs.length === 0) { throw new Error('No React Source Code Directory Found!') } -const PATH_REACT = path.resolve(PATH_REACT_CONTAINER, dirs[0]).replace(/\\/g, '/') -const PATH_BUILD_REACT = path.resolve(PATH_BUILD, path.basename(PATH_REACT).replace(/\.js/, '')).replace(/\\/g, '/') - - -const PATH_REACT_NODE_MODULES = path.resolve(PATH_REACT, 'node_modules').replace(/\\/g, '/') -const PATH_REACT_ROLLUP_BUILD_JS = path.resolve(PATH_REACT, 'scripts/rollup/build.js').replace(/\\/g, '/') -const PATH_NEW_REACT_ROLLUP_BUILD_JS = path.resolve(PATH_REACT, 'scripts/rollup/build.for-debug-react-code.js').replace(/\\/g, '/') -const TMP = 'scripts/rollup/build.for-debug-react-code.js' -const RELATIVE_PATH_NEW_REACT_ROLLUP_BUILD_JS_TO_PLUGIN = path.relative(path.resolve(PATH_REACT, 'scripts/rollup' ), PATH_PLUGIN).replace(/\\/g, '/') -const RELATIVE_PATH_REACT_TO__NEW_REACT_ROLLUP_BUILD_JS = path.relative(PATH_REACT, PATH_NEW_REACT_ROLLUP_BUILD_JS).replace(/\\/g, '/') -const RELATIVE_PATH_ROLLUP_BUILD_JS_TO_REACT = path.relative(PATH_REACT_ROLLUP_BUILD_JS, PATH_REACT).replace(/\\/g, '/') - -const NAME_PLUGIN = `$$addPathInfoAnnotationForEachFilePlugin` - -const NAME_DEPENDENCY_REACT = 'dependency-react.html' -const NAME_DEPENDENCY_REACT_DOM = 'dependency-react-dom.html' -const NAME_DEPENDENCY_DEFAULT_JS = `index.js` - -const PATH_DEPENDENCY_SOURCE_BABEL = path.resolve(PATH_DEPENDENCIES, 'source-babel.js').replace(/\\/g, '/') -const PATH_DEPENDENCY_SOURCE_DEPENDENCY_MAIN = path.resolve(PATH_DEPENDENCIES, 'source-dependency-main.html').replace(/\\/g, '/') -const PATH_DEPENDENCY_SOURCE_DEFAULT_JS = path.resolve(PATH_DEPENDENCIES, 'source-index.js').replace(/\\/g, '/') -const PATH_DEPENDENCY_SOURCE_DEFAULT = path.resolve(PATH_DEPENDENCIES, 'source-index.html').replace(/\\/g, '/') - -// # generate a new build js -function generateNewBuildJS() { - const buildJsStr = fs.readFileSync(PATH_REACT_ROLLUP_BUILD_JS, {encoding: 'utf8'}) - const lines = buildJsStr.split('\n') - const newFistLine = `const ${NAME_PLUGIN} = require('${RELATIVE_PATH_NEW_REACT_ROLLUP_BUILD_JS_TO_PLUGIN}');\n` - newBuildJsStr = newFistLine + lines.map(line => { - if (line.match(/rollup\(/)) { - return `rollupConfig.plugins.push(${NAME_PLUGIN}('${PATH_REACT}')); - ${line}` - } - return line - }).join('\n') - fs.writeFileSync(PATH_NEW_REACT_ROLLUP_BUILD_JS, newBuildJsStr, {encoding: 'utf-8'}) - console.log(`$$ DEBUG REACT SOURCE CODE: generated a new build js!`) -} - -function installDependencies(cb) { - const ls = spawn(`yarn.cmd`, [`install`], {cwd: PATH_REACT}) - ls.stdout.on('data', data => console.log(data.toString())) - ls.stdout.on('close', cb) -} - -function build(cb) { - const ls = spawn('node', [TMP, `react/index,react-dom/index`, `--type`, `UMD_DEV`], {cwd: PATH_REACT}) - // const ls = spawn('node', [TMP], {cwd: PATH_REACT}) - ls.stdout.on('data', data => console.log(data.toString())) - ls.stderr.on('data', data => console.log(data.toString())) - ls.on('close', () => { - console.log(`$$ DEBUG REACT SOURCE CODE: generated react.development.js and react-dom.development.js!`) - cb && cb() - }) -} - -function getReactOrReactDOMNamespace(reactOrReactDOMDevelopmentFile) { - const isReactFile = path.parse(reactOrReactDOMDevelopmentFile).name.replace(/\..*/, '') === 'react' - return isReactFile ? 'React' : 'ReactDOM' -} - -/** - * - * @param {*} reactOrReactDOMDevelopmentFile - * @return {{outputFile, text}[]} - */ -function getReactOrReactDOMSplitFilesData(reactOrReactDOMDevelopmentFile) { - const getFileOnEndLine = (line) => { - const isSpecialFormat = /commonjs-proxy-/.test( line ) - - if ( isSpecialFormat ) { - let tmpPath = line.replace( /.*commonjs-proxy-/, '' ) - tmpPath = path.relative( PATH_REACT, tmpPath ).replace(/\\/g,'/') - - return `commonjs-proxy-/${ tmpPath }` - // return path - } - return line.replace( new RegExp(`.*${ANNOTATION_PREFIX.replace('/', '\\/')}${IDENTITY_END_STR.replace(/\$/g, '\\$')} `), '' ) - } - const isStartLine = line => new RegExp( `${IDENTITY_START_STR.replace(/\$/g, '\\$')}` ).test( line ) - const isEndLine = line => new RegExp( `${IDENTITY_END_STR.replace(/\$/g, '\\$')}` ).test( line ) - - const namespace = getReactOrReactDOMNamespace(reactOrReactDOMDevelopmentFile) - - const sourceText = fs.readFileSync(reactOrReactDOMDevelopmentFile, {encoding: 'utf8'}) - const lines = sourceText.split( '\n' ) - /** @type {{outputFile, text}[]} */ - const data = [] - let hasStarted = false - // resolve the content between **end** and **start** - let isBetweenEndAndStart = false - /** @type {string[]} */ - let curry = [] - let lineIndex = -1 - for (let line of lines) { - lineIndex++ - - if (isStartLine(line)) { - hasStarted = true - } - if (hasStarted) { - if (isStartLine(line) || lineIndex === lines.length - 2) { - if (isBetweenEndAndStart && curry.length > 0 && !(curry.every(line => line.trim() === ''))) { - const outputFile = `$$umd/line-number-${lineIndex}.js` - let text = curry.join('\n') - text = text.replace(/exports/g, namespace) - data.push({outputFile, text}) - } - isBetweenEndAndStart = false - curry = [] - } - if (!isStartLine(line) && !isEndLine(line)) {curry.push(line)} - if (isEndLine(line)) { - let text = curry.join('\n') - text = text.replace(/exports/g, namespace) - const outputFile = getFileOnEndLine(line) - data.push({outputFile, text}) - curry = [] - isBetweenEndAndStart = true - } - } - } - return data -} - -/** - * - * @param {{outputFile, text}[]} filesData - * @param {string} reactOrReactDOMDevelopmentFile - */ -function generateReactOrReactDOMSplitFiles(filesData, reactOrReactDOMDevelopmentFile) { - for (let {outputFile, text} of filesData) { - const folderName = path.parse(reactOrReactDOMDevelopmentFile).name - const targetPath = path.resolve(PATH_BUILD_REACT, `${folderName}/${outputFile}`) - const folerPath = path.dirname(targetPath) - !fs.existsSync(folerPath) && fs.mkdirSync(folerPath, {recursive: true}) - fs.writeFileSync(targetPath, text, {encoding: 'utf-8'}) - } -} - -function copyDependencies() { - const dependencyPaths = [ - PATH_DEPENDENCY_SOURCE_BABEL, - PATH_DEPENDENCY_SOURCE_DEPENDENCY_MAIN, - PATH_DEPENDENCY_SOURCE_DEFAULT_JS, - PATH_DEPENDENCY_SOURCE_DEFAULT, - ] - for (let file of dependencyPaths) { - const filename = path.parse(file).base.replace(/^source-/, '') - const targetPath = path.resolve(PATH_BUILD_REACT, filename) - fs.copyFileSync(file, targetPath) - } -} - - -function generateDependencyReactDOMHTML(reactDOMFilesData, reactDOMFile) { - const namespace = getReactOrReactDOMNamespace(reactDOMFile) - const dependencyFolerName = path.parse(reactDOMFile).name - const mainText = reactDOMFilesData.map(v => ``).join('\n') - const text = ` - - - - - Dependency ${namespace} - - - ${mainText} - - - - ` - const targetPath = path.resolve(PATH_BUILD_REACT, NAME_DEPENDENCY_REACT_DOM) - fs.writeFileSync(targetPath, text, {encoding: 'utf-8'}) -} - -function generateDependencyReactHTML(reactFilesData, reactFile) { - const namespace = getReactOrReactDOMNamespace(reactFile) - const dependencyFolerName = path.parse(reactFile).name - const mainText = reactFilesData.map(v => ``).join('\n') - const text = ` - - - - - Dependency ${namespace} - - ${mainText} - - - - - - ` - const targetPath = path.resolve(PATH_BUILD_REACT, NAME_DEPENDENCY_REACT) - fs.writeFileSync(targetPath, text, {encoding: 'utf-8'}) -} - -async function takeOnReactReactDOMFiles() { - await trash(PATH_BUILD_REACT) - const PATH_REACT_DEVELOPMENT = path.resolve(PATH_REACT, `build/node_modules/react/umd/react.development.js`) - const PATH_REACT_DOM_DEVELOPMENT = path.resolve(PATH_REACT, `build/node_modules/react-dom/umd/react-dom.development.js`) - - const reactFilesData = getReactOrReactDOMSplitFilesData(PATH_REACT_DEVELOPMENT) - generateReactOrReactDOMSplitFiles(reactFilesData, PATH_REACT_DEVELOPMENT) - generateDependencyReactHTML(reactFilesData, PATH_REACT_DEVELOPMENT) - - const reactDOMFilesData = getReactOrReactDOMSplitFilesData(PATH_REACT_DOM_DEVELOPMENT) - generateReactOrReactDOMSplitFiles(reactDOMFilesData, PATH_REACT_DOM_DEVELOPMENT) - generateDependencyReactDOMHTML(reactDOMFilesData, PATH_REACT_DOM_DEVELOPMENT) - - copyDependencies() - console.log(`$$ DEBUG REACT SOURCE CODE: built ${path.parse(PATH_BUILD_REACT).name} to ${PATH_BUILD_REACT}!`) -} - - -generateNewBuildJS();installDependencies( () => build( takeOnReactReactDOMFiles )) -// build() -// takeOnReactReactDOMFiles() - - -module.exports.getReactOrReactDOMSplitFilesData = getReactOrReactDOMSplitFilesData -module.exports.generateReactOrReactDOMSplitFiles = generateReactOrReactDOMSplitFiles -module.exports.copyDependencies = copyDependencies -module.exports.generateDependencyReactDOMHTML = generateDependencyReactDOMHTML -module.exports.generateDependencyReactHTML = generateDependencyReactHTML -module.exports.PATH_REACT = PATH_REACT diff --git a/package.json b/package.json index bab0bf3..5706ae4 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,7 @@ "description": "", "main": "index.js", "scripts": { - "start": "node index.js", - "serve": "serve build", - "test": "node test/test.js" + "start": "cd ./react-17.0.2 && http-server -p 6001" }, "repository": { "type": "git", @@ -20,7 +18,6 @@ }, "homepage": "https://github.com/Terry-Su/debug-react-source-code#readme", "devDependencies": { - "serve": "^11.3.2", - "trash": "^6.1.1" + "http-server": "^0.12.3" } } diff --git a/dependencies/source-babel.js b/react-17.0.2/babel.js similarity index 100% rename from dependencies/source-babel.js rename to react-17.0.2/babel.js diff --git a/dependencies/source-dependency-main.html b/react-17.0.2/dependency-main.html similarity index 100% rename from dependencies/source-dependency-main.html rename to react-17.0.2/dependency-main.html diff --git a/react-17.0.2/dependency-react-dom.html b/react-17.0.2/dependency-react-dom.html new file mode 100644 index 0000000..4dc23d8 --- /dev/null +++ b/react-17.0.2/dependency-react-dom.html @@ -0,0 +1,144 @@ + + + + + + Dependency ReactDOM + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/react-17.0.2/dependency-react.html b/react-17.0.2/dependency-react.html new file mode 100644 index 0000000..969dc17 --- /dev/null +++ b/react-17.0.2/dependency-react.html @@ -0,0 +1,64 @@ + + + + + + Dependency React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dependencies/source-index.html b/react-17.0.2/index.html similarity index 100% rename from dependencies/source-index.html rename to react-17.0.2/index.html diff --git a/react-17.0.2/index.js b/react-17.0.2/index.js new file mode 100644 index 0000000..d9e350f --- /dev/null +++ b/react-17.0.2/index.js @@ -0,0 +1,10 @@ +function App() { + const [count, setCount] = React.useState(0) + return
+
Hello, React Source Code!
+
Number: {count}
+ +
+} + +ReactDOM.render(, document.querySelector('#app')) \ No newline at end of file diff --git a/react-17.0.2/react-dom.development/$$umd/line-number-27652.js b/react-17.0.2/react-dom.development/$$umd/line-number-27652.js new file mode 100644 index 0000000..9e15102 --- /dev/null +++ b/react-17.0.2/react-dom.development/$$umd/line-number-27652.js @@ -0,0 +1,17 @@ + + ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = Internals; + ReactDOM.createPortal = createPortal$1; + ReactDOM.findDOMNode = findDOMNode; + ReactDOM.flushSync = flushSync; + ReactDOM.hydrate = hydrate; + ReactDOM.render = render; + ReactDOM.unmountComponentAtNode = unmountComponentAtNode; + ReactDOM.unstable_batchedUpdates = batchedUpdates$1; + ReactDOM.unstable_createBlockingRoot = createBlockingRoot; + ReactDOM.unstable_createPortal = unstable_createPortal; + ReactDOM.unstable_createRoot = createRoot; + ReactDOM.unstable_flushControlled = flushControlled; + ReactDOM.unstable_renderSubtreeIntoContainer = renderSubtreeIntoContainer; + ReactDOM.unstable_runWithPriority = runWithPriority$2; + ReactDOM.unstable_scheduleHydration = scheduleHydration; + ReactDOM.version = ReactVersion; diff --git a/react-17.0.2/react-dom.development/packages/react-dom/src/client/DOMPropertyOperations.js b/react-17.0.2/react-dom.development/packages/react-dom/src/client/DOMPropertyOperations.js new file mode 100644 index 0000000..64d4363 --- /dev/null +++ b/react-17.0.2/react-dom.development/packages/react-dom/src/client/DOMPropertyOperations.js @@ -0,0 +1,186 @@ + + /** + * Get the value for a property on a node. Only used in DEV for SSR validation. + * The "expected" argument is used as a hint of what the expected value is. + * Some properties have multiple equivalent values. + */ + function getValueForProperty(node, name, expected, propertyInfo) { + { + if (propertyInfo.mustUseProperty) { + var propertyName = propertyInfo.propertyName; + return node[propertyName]; + } else { + if ( propertyInfo.sanitizeURL) { + // If we haven't fully disabled javascript: URLs, and if + // the hydration is successful of a javascript: URL, we + // still want to warn on the client. + sanitizeURL('' + expected); + } + + var attributeName = propertyInfo.attributeName; + var stringValue = null; + + if (propertyInfo.type === OVERLOADED_BOOLEAN) { + if (node.hasAttribute(attributeName)) { + var value = node.getAttribute(attributeName); + + if (value === '') { + return true; + } + + if (shouldRemoveAttribute(name, expected, propertyInfo, false)) { + return value; + } + + if (value === '' + expected) { + return expected; + } + + return value; + } + } else if (node.hasAttribute(attributeName)) { + if (shouldRemoveAttribute(name, expected, propertyInfo, false)) { + // We had an attribute but shouldn't have had one, so read it + // for the error message. + return node.getAttribute(attributeName); + } + + if (propertyInfo.type === BOOLEAN) { + // If this was a boolean, it doesn't matter what the value is + // the fact that we have it is the same as the expected. + return expected; + } // Even if this property uses a namespace we use getAttribute + // because we assume its namespaced name is the same as our config. + // To use getAttributeNS we need the local name which we don't have + // in our config atm. + + + stringValue = node.getAttribute(attributeName); + } + + if (shouldRemoveAttribute(name, expected, propertyInfo, false)) { + return stringValue === null ? expected : stringValue; + } else if (stringValue === '' + expected) { + return expected; + } else { + return stringValue; + } + } + } + } + /** + * Get the value for a attribute on a node. Only used in DEV for SSR validation. + * The third argument is used as a hint of what the expected value is. Some + * attributes have multiple equivalent values. + */ + + function getValueForAttribute(node, name, expected) { + { + if (!isAttributeNameSafe(name)) { + return; + } // If the object is an opaque reference ID, it's expected that + // the next prop is different than the server value, so just return + // expected + + + if (isOpaqueHydratingObject(expected)) { + return expected; + } + + if (!node.hasAttribute(name)) { + return expected === undefined ? undefined : null; + } + + var value = node.getAttribute(name); + + if (value === '' + expected) { + return expected; + } + + return value; + } + } + /** + * Sets the value for a property on a node. + * + * @param {DOMElement} node + * @param {string} name + * @param {*} value + */ + + function setValueForProperty(node, name, value, isCustomComponentTag) { + var propertyInfo = getPropertyInfo(name); + + if (shouldIgnoreAttribute(name, propertyInfo, isCustomComponentTag)) { + return; + } + + if (shouldRemoveAttribute(name, value, propertyInfo, isCustomComponentTag)) { + value = null; + } // If the prop isn't in the special list, treat it as a simple attribute. + + + if (isCustomComponentTag || propertyInfo === null) { + if (isAttributeNameSafe(name)) { + var _attributeName = name; + + if (value === null) { + node.removeAttribute(_attributeName); + } else { + node.setAttribute(_attributeName, '' + value); + } + } + + return; + } + + var mustUseProperty = propertyInfo.mustUseProperty; + + if (mustUseProperty) { + var propertyName = propertyInfo.propertyName; + + if (value === null) { + var type = propertyInfo.type; + node[propertyName] = type === BOOLEAN ? false : ''; + } else { + // Contrary to `setAttribute`, object properties are properly + // `toString`ed by IE8/9. + node[propertyName] = value; + } + + return; + } // The rest are treated as attributes with special cases. + + + var attributeName = propertyInfo.attributeName, + attributeNamespace = propertyInfo.attributeNamespace; + + if (value === null) { + node.removeAttribute(attributeName); + } else { + var _type = propertyInfo.type; + var attributeValue; + + if (_type === BOOLEAN || _type === OVERLOADED_BOOLEAN && value === true) { + // If attribute type is boolean, we know for sure it won't be an execution sink + // and we won't require Trusted Type here. + attributeValue = ''; + } else { + // `setAttribute` with objects becomes only `[object]` in IE8/9, + // ('' + value) makes it output the correct toString()-value. + { + attributeValue = '' + value; + } + + if (propertyInfo.sanitizeURL) { + sanitizeURL(attributeValue.toString()); + } + } + + if (attributeNamespace) { + node.setAttributeNS(attributeNamespace, attributeName, attributeValue); + } else { + node.setAttribute(attributeName, attributeValue); + } + } + } \ No newline at end of file diff --git a/react-17.0.2/react-dom.development/packages/react-dom/src/client/ReactDOM.js b/react-17.0.2/react-dom.development/packages/react-dom/src/client/ReactDOM.js new file mode 100644 index 0000000..b53f8c5 --- /dev/null +++ b/react-17.0.2/react-dom.development/packages/react-dom/src/client/ReactDOM.js @@ -0,0 +1,84 @@ + setAttemptSynchronousHydration(attemptSynchronousHydration$1); + setAttemptUserBlockingHydration(attemptUserBlockingHydration$1); + setAttemptContinuousHydration(attemptContinuousHydration$1); + setAttemptHydrationAtCurrentPriority(attemptHydrationAtCurrentPriority$1); + setGetCurrentUpdatePriority(getCurrentUpdateLanePriority); + setAttemptHydrationAtPriority(runWithPriority$2); + var didWarnAboutUnstableCreatePortal = false; + + { + if (typeof Map !== 'function' || // $FlowIssue Flow incorrectly thinks Map has no prototype + Map.prototype == null || typeof Map.prototype.forEach !== 'function' || typeof Set !== 'function' || // $FlowIssue Flow incorrectly thinks Set has no prototype + Set.prototype == null || typeof Set.prototype.clear !== 'function' || typeof Set.prototype.forEach !== 'function') { + error('React depends on Map and Set built-in types. Make sure that you load a ' + 'polyfill in older browsers. https://reactjs.org/link/react-polyfills'); + } + } + + setRestoreImplementation(restoreControlledState$3); + setBatchingImplementation(batchedUpdates$1, discreteUpdates$1, flushDiscreteUpdates, batchedEventUpdates$1); + + function createPortal$1(children, container) { + var key = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; + + if (!isValidContainer(container)) { + { + throw Error( "Target container is not a DOM element." ); + } + } // TODO: pass ReactDOM portal implementation as third argument + // $FlowFixMe The Flow type is opaque but there's no way to actually create it. + + + return createPortal(children, container, null, key); + } + + function scheduleHydration(target) { + if (target) { + queueExplicitHydrationTarget(target); + } + } + + function renderSubtreeIntoContainer(parentComponent, element, containerNode, callback) { + + return unstable_renderSubtreeIntoContainer(parentComponent, element, containerNode, callback); + } + + function unstable_createPortal(children, container) { + var key = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; + + { + if (!didWarnAboutUnstableCreatePortal) { + didWarnAboutUnstableCreatePortal = true; + + warn('The ReactDOM.unstable_createPortal() alias has been deprecated, ' + 'and will be removed in React 18+. Update your code to use ' + 'ReactDOM.createPortal() instead. It has the exact same API, ' + 'but without the "unstable_" prefix.'); + } + } + + return createPortal$1(children, container, key); + } + + var Internals = { + // Keep in sync with ReactTestUtils.js, and ReactTestUtilsAct.js. + // This is an array for better minification. + Events: [getInstanceFromNode, getNodeFromInstance, getFiberCurrentPropsFromNode, enqueueStateRestore, restoreStateIfNeeded, flushPassiveEffects, // TODO: This is related to `act`, not events. Move to separate key? + IsThisRendererActing] + }; + var foundDevTools = injectIntoDevTools({ + findFiberByHostInstance: getClosestInstanceFromNode, + bundleType: 1 , + version: ReactVersion, + rendererPackageName: 'react-dom' + }); + + { + if (!foundDevTools && canUseDOM && window.top === window.self) { + // 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) { + var protocol = window.location.protocol; // Don't warn in exotic cases like chrome-extension://. + + if (/^(https?|file):$/.test(protocol)) { + // eslint-disable-next-line react-internal/no-production-logging + console.info('%cDownload the React DevTools ' + 'for a better development experience: ' + 'https://reactjs.org/link/react-devtools' + (protocol === 'file:' ? '\nYou might need to use a local HTTP server (instead of file://): ' + 'https://reactjs.org/link/react-devtools-faq' : ''), 'font-weight:bold'); + } + } + } + } \ No newline at end of file diff --git a/react-17.0.2/react-dom.development/packages/react-dom/src/client/ReactDOMComponent.js b/react-17.0.2/react-dom.development/packages/react-dom/src/client/ReactDOMComponent.js new file mode 100644 index 0000000..f58d7a6 --- /dev/null +++ b/react-17.0.2/react-dom.development/packages/react-dom/src/client/ReactDOMComponent.js @@ -0,0 +1,1040 @@ + var didWarnInvalidHydration = false; + var DANGEROUSLY_SET_INNER_HTML = 'dangerouslySetInnerHTML'; + var SUPPRESS_CONTENT_EDITABLE_WARNING = 'suppressContentEditableWarning'; + var SUPPRESS_HYDRATION_WARNING = 'suppressHydrationWarning'; + var AUTOFOCUS = 'autoFocus'; + var CHILDREN = 'children'; + var STYLE = 'style'; + var HTML$1 = '__html'; + var HTML_NAMESPACE$1 = Namespaces.html; + var warnedUnknownTags; + var suppressHydrationWarning; + var validatePropertiesInDevelopment; + var warnForTextDifference; + var warnForPropDifference; + var warnForExtraAttributes; + var warnForInvalidEventListener; + var canDiffStyleForHydrationWarning; + var normalizeMarkupForTextOrAttribute; + var normalizeHTML; + + { + warnedUnknownTags = { + // There are working polyfills for . Let people use it. + dialog: true, + // Electron ships a custom tag to display external web content in + // an isolated frame and process. + // This tag is not present in non Electron environments such as JSDom which + // is often used for testing purposes. + // @see https://electronjs.org/docs/api/webview-tag + webview: true + }; + + validatePropertiesInDevelopment = function (type, props) { + validateProperties(type, props); + validateProperties$1(type, props); + validateProperties$2(type, props, { + registrationNameDependencies: registrationNameDependencies, + possibleRegistrationNames: possibleRegistrationNames + }); + }; // IE 11 parses & normalizes the style attribute as opposed to other + // browsers. It adds spaces and sorts the properties in some + // non-alphabetical order. Handling that would require sorting CSS + // properties in the client & server versions or applying + // `expectedStyle` to a temporary DOM node to read its `style` attribute + // normalized. Since it only affects IE, we're skipping style warnings + // in that browser completely in favor of doing all that work. + // See https://github.com/facebook/react/issues/11807 + + + canDiffStyleForHydrationWarning = canUseDOM && !document.documentMode; // HTML parsing normalizes CR and CRLF to LF. + // It also can turn \u0000 into \uFFFD inside attributes. + // https://www.w3.org/TR/html5/single-page.html#preprocessing-the-input-stream + // If we have a mismatch, it might be caused by that. + // We will still patch up in this case but not fire the warning. + + var NORMALIZE_NEWLINES_REGEX = /\r\n?/g; + var NORMALIZE_NULL_AND_REPLACEMENT_REGEX = /\u0000|\uFFFD/g; + + normalizeMarkupForTextOrAttribute = function (markup) { + var markupString = typeof markup === 'string' ? markup : '' + markup; + return markupString.replace(NORMALIZE_NEWLINES_REGEX, '\n').replace(NORMALIZE_NULL_AND_REPLACEMENT_REGEX, ''); + }; + + warnForTextDifference = function (serverText, clientText) { + if (didWarnInvalidHydration) { + return; + } + + var normalizedClientText = normalizeMarkupForTextOrAttribute(clientText); + var normalizedServerText = normalizeMarkupForTextOrAttribute(serverText); + + if (normalizedServerText === normalizedClientText) { + return; + } + + didWarnInvalidHydration = true; + + error('Text content did not match. Server: "%s" Client: "%s"', normalizedServerText, normalizedClientText); + }; + + warnForPropDifference = function (propName, serverValue, clientValue) { + if (didWarnInvalidHydration) { + return; + } + + var normalizedClientValue = normalizeMarkupForTextOrAttribute(clientValue); + var normalizedServerValue = normalizeMarkupForTextOrAttribute(serverValue); + + if (normalizedServerValue === normalizedClientValue) { + return; + } + + didWarnInvalidHydration = true; + + error('Prop `%s` did not match. Server: %s Client: %s', propName, JSON.stringify(normalizedServerValue), JSON.stringify(normalizedClientValue)); + }; + + warnForExtraAttributes = function (attributeNames) { + if (didWarnInvalidHydration) { + return; + } + + didWarnInvalidHydration = true; + var names = []; + attributeNames.forEach(function (name) { + names.push(name); + }); + + error('Extra attributes from the server: %s', names); + }; + + warnForInvalidEventListener = function (registrationName, listener) { + if (listener === false) { + error('Expected `%s` listener to be a function, instead got `false`.\n\n' + 'If you used to conditionally omit it with %s={condition && value}, ' + 'pass %s={condition ? value : undefined} instead.', registrationName, registrationName, registrationName); + } else { + error('Expected `%s` listener to be a function, instead got a value of `%s` type.', registrationName, typeof listener); + } + }; // Parse the HTML and read it back to normalize the HTML string so that it + // can be used for comparison. + + + normalizeHTML = function (parent, html) { + // We could have created a separate document here to avoid + // re-initializing custom elements if they exist. But this breaks + // how