diff --git a/.vscode/launch.json b/.vscode/launch.json index 124dfd3..e591f8a 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-18.1.0" } ] } \ 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/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..6f0f5c1 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-18.1.0 && 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-18.1.0/babel.js similarity index 100% rename from dependencies/source-babel.js rename to react-18.1.0/babel.js diff --git a/dependencies/source-dependency-main.html b/react-18.1.0/dependency-main.html similarity index 100% rename from dependencies/source-dependency-main.html rename to react-18.1.0/dependency-main.html diff --git a/react-18.1.0/dependency-react-dom.html b/react-18.1.0/dependency-react-dom.html new file mode 100644 index 0000000..4366789 --- /dev/null +++ b/react-18.1.0/dependency-react-dom.html @@ -0,0 +1,151 @@ + + + + + + Dependency ReactDOM + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/react-18.1.0/dependency-react.html b/react-18.1.0/dependency-react.html new file mode 100644 index 0000000..bd29ae9 --- /dev/null +++ b/react-18.1.0/dependency-react.html @@ -0,0 +1,63 @@ + + + + + + Dependency React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dependencies/source-index.html b/react-18.1.0/index.html similarity index 100% rename from dependencies/source-index.html rename to react-18.1.0/index.html diff --git a/dependencies/source-index.js b/react-18.1.0/index.js similarity index 100% rename from dependencies/source-index.js rename to react-18.1.0/index.js diff --git a/react-18.1.0/react-dom.development/$$umd/line-number-30946.js b/react-18.1.0/react-dom.development/$$umd/line-number-30946.js new file mode 100644 index 0000000..8daa7ff --- /dev/null +++ b/react-18.1.0/react-dom.development/$$umd/line-number-30946.js @@ -0,0 +1,14 @@ + + ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = Internals; + ReactDOM.createPortal = createPortal$1; + ReactDOM.createRoot = createRoot$1; + ReactDOM.findDOMNode = findDOMNode; + ReactDOM.flushSync = flushSync$1; + ReactDOM.hydrate = hydrate; + ReactDOM.hydrateRoot = hydrateRoot$1; + ReactDOM.render = render; + ReactDOM.unmountComponentAtNode = unmountComponentAtNode; + ReactDOM.unstable_batchedUpdates = batchedUpdates$1; + ReactDOM.unstable_renderSubtreeIntoContainer = renderSubtreeIntoContainer; + ReactDOM.unstable_runWithPriority = runWithPriority; + ReactDOM.version = ReactVersion; diff --git a/react-18.1.0/react-dom.development/packages/react-dom/src/client/CSSPropertyOperations.js b/react-18.1.0/react-dom.development/packages/react-dom/src/client/CSSPropertyOperations.js new file mode 100644 index 0000000..185cfb4 --- /dev/null +++ b/react-18.1.0/react-dom.development/packages/react-dom/src/client/CSSPropertyOperations.js @@ -0,0 +1,142 @@ + /** + * Operations for dealing with CSS properties. + */ + + /** + * This creates a string that is expected to be equivalent to the style + * attribute generated by server-side rendering. It by-passes warnings and + * security checks so it's not safe to use this value for anything other than + * comparison. It is only used in DEV for SSR validation. + */ + + function createDangerousStringForStyles(styles) { + { + var serialized = ''; + var delimiter = ''; + + for (var styleName in styles) { + if (!styles.hasOwnProperty(styleName)) { + continue; + } + + var styleValue = styles[styleName]; + + if (styleValue != null) { + var isCustomProperty = styleName.indexOf('--') === 0; + serialized += delimiter + (isCustomProperty ? styleName : hyphenateStyleName(styleName)) + ':'; + serialized += dangerousStyleValue(styleName, styleValue, isCustomProperty); + delimiter = ';'; + } + } + + return serialized || null; + } + } + /** + * Sets the value for multiple styles on a node. If a value is specified as + * '' (empty string), the corresponding style property will be unset. + * + * @param {DOMElement} node + * @param {object} styles + */ + + function setValueForStyles(node, styles) { + var style = node.style; + + for (var styleName in styles) { + if (!styles.hasOwnProperty(styleName)) { + continue; + } + + var isCustomProperty = styleName.indexOf('--') === 0; + + { + if (!isCustomProperty) { + warnValidStyle$1(styleName, styles[styleName]); + } + } + + var styleValue = dangerousStyleValue(styleName, styles[styleName], isCustomProperty); + + if (styleName === 'float') { + styleName = 'cssFloat'; + } + + if (isCustomProperty) { + style.setProperty(styleName, styleValue); + } else { + style[styleName] = styleValue; + } + } + } + + function isValueEmpty(value) { + return value == null || typeof value === 'boolean' || value === ''; + } + /** + * Given {color: 'red', overflow: 'hidden'} returns { + * color: 'color', + * overflowX: 'overflow', + * overflowY: 'overflow', + * }. This can be read as "the overflowY property was set by the overflow + * shorthand". That is, the values are the property that each was derived from. + */ + + + function expandShorthandMap(styles) { + var expanded = {}; + + for (var key in styles) { + var longhands = shorthandToLonghand[key] || [key]; + + for (var i = 0; i < longhands.length; i++) { + expanded[longhands[i]] = key; + } + } + + return expanded; + } + /** + * When mixing shorthand and longhand property names, we warn during updates if + * we expect an incorrect result to occur. In particular, we warn for: + * + * Updating a shorthand property (longhand gets overwritten): + * {font: 'foo', fontVariant: 'bar'} -> {font: 'baz', fontVariant: 'bar'} + * becomes .style.font = 'baz' + * Removing a shorthand property (longhand gets lost too): + * {font: 'foo', fontVariant: 'bar'} -> {fontVariant: 'bar'} + * becomes .style.font = '' + * Removing a longhand property (should revert to shorthand; doesn't): + * {font: 'foo', fontVariant: 'bar'} -> {font: 'foo'} + * becomes .style.fontVariant = '' + */ + + + function validateShorthandPropertyCollisionInDev(styleUpdates, nextStyles) { + { + if (!nextStyles) { + return; + } + + var expandedUpdates = expandShorthandMap(styleUpdates); + var expandedStyles = expandShorthandMap(nextStyles); + var warnedAbout = {}; + + for (var key in expandedUpdates) { + var originalKey = expandedUpdates[key]; + var correctOriginalKey = expandedStyles[key]; + + if (correctOriginalKey && originalKey !== correctOriginalKey) { + var warningKey = originalKey + ',' + correctOriginalKey; + + if (warnedAbout[warningKey]) { + continue; + } + + warnedAbout[warningKey] = true; + + error('%s a style property during rerender (%s) when a ' + 'conflicting property is set (%s) can lead to styling bugs. To ' + "avoid this, don't mix shorthand and non-shorthand properties " + 'for the same value; instead, replace the shorthand with ' + 'separate values.', isValueEmpty(styleUpdates[originalKey]) ? 'Removing' : 'Updating', originalKey, correctOriginalKey); + } + } + } + } \ No newline at end of file diff --git a/react-18.1.0/react-dom.development/packages/react-dom/src/client/CSSShorthandProperty.js b/react-18.1.0/react-dom.development/packages/react-dom/src/client/CSSShorthandProperty.js new file mode 100644 index 0000000..cd7a145 --- /dev/null +++ b/react-18.1.0/react-dom.development/packages/react-dom/src/client/CSSShorthandProperty.js @@ -0,0 +1,51 @@ + // List derived from Gecko source code: + // https://github.com/mozilla/gecko-dev/blob/4e638efc71/layout/style/test/property_database.js + var shorthandToLonghand = { + animation: ['animationDelay', 'animationDirection', 'animationDuration', 'animationFillMode', 'animationIterationCount', 'animationName', 'animationPlayState', 'animationTimingFunction'], + background: ['backgroundAttachment', 'backgroundClip', 'backgroundColor', 'backgroundImage', 'backgroundOrigin', 'backgroundPositionX', 'backgroundPositionY', 'backgroundRepeat', 'backgroundSize'], + backgroundPosition: ['backgroundPositionX', 'backgroundPositionY'], + border: ['borderBottomColor', 'borderBottomStyle', 'borderBottomWidth', 'borderImageOutset', 'borderImageRepeat', 'borderImageSlice', 'borderImageSource', 'borderImageWidth', 'borderLeftColor', 'borderLeftStyle', 'borderLeftWidth', 'borderRightColor', 'borderRightStyle', 'borderRightWidth', 'borderTopColor', 'borderTopStyle', 'borderTopWidth'], + borderBlockEnd: ['borderBlockEndColor', 'borderBlockEndStyle', 'borderBlockEndWidth'], + borderBlockStart: ['borderBlockStartColor', 'borderBlockStartStyle', 'borderBlockStartWidth'], + borderBottom: ['borderBottomColor', 'borderBottomStyle', 'borderBottomWidth'], + borderColor: ['borderBottomColor', 'borderLeftColor', 'borderRightColor', 'borderTopColor'], + borderImage: ['borderImageOutset', 'borderImageRepeat', 'borderImageSlice', 'borderImageSource', 'borderImageWidth'], + borderInlineEnd: ['borderInlineEndColor', 'borderInlineEndStyle', 'borderInlineEndWidth'], + borderInlineStart: ['borderInlineStartColor', 'borderInlineStartStyle', 'borderInlineStartWidth'], + borderLeft: ['borderLeftColor', 'borderLeftStyle', 'borderLeftWidth'], + borderRadius: ['borderBottomLeftRadius', 'borderBottomRightRadius', 'borderTopLeftRadius', 'borderTopRightRadius'], + borderRight: ['borderRightColor', 'borderRightStyle', 'borderRightWidth'], + borderStyle: ['borderBottomStyle', 'borderLeftStyle', 'borderRightStyle', 'borderTopStyle'], + borderTop: ['borderTopColor', 'borderTopStyle', 'borderTopWidth'], + borderWidth: ['borderBottomWidth', 'borderLeftWidth', 'borderRightWidth', 'borderTopWidth'], + columnRule: ['columnRuleColor', 'columnRuleStyle', 'columnRuleWidth'], + columns: ['columnCount', 'columnWidth'], + flex: ['flexBasis', 'flexGrow', 'flexShrink'], + flexFlow: ['flexDirection', 'flexWrap'], + font: ['fontFamily', 'fontFeatureSettings', 'fontKerning', 'fontLanguageOverride', 'fontSize', 'fontSizeAdjust', 'fontStretch', 'fontStyle', 'fontVariant', 'fontVariantAlternates', 'fontVariantCaps', 'fontVariantEastAsian', 'fontVariantLigatures', 'fontVariantNumeric', 'fontVariantPosition', 'fontWeight', 'lineHeight'], + fontVariant: ['fontVariantAlternates', 'fontVariantCaps', 'fontVariantEastAsian', 'fontVariantLigatures', 'fontVariantNumeric', 'fontVariantPosition'], + gap: ['columnGap', 'rowGap'], + grid: ['gridAutoColumns', 'gridAutoFlow', 'gridAutoRows', 'gridTemplateAreas', 'gridTemplateColumns', 'gridTemplateRows'], + gridArea: ['gridColumnEnd', 'gridColumnStart', 'gridRowEnd', 'gridRowStart'], + gridColumn: ['gridColumnEnd', 'gridColumnStart'], + gridColumnGap: ['columnGap'], + gridGap: ['columnGap', 'rowGap'], + gridRow: ['gridRowEnd', 'gridRowStart'], + gridRowGap: ['rowGap'], + gridTemplate: ['gridTemplateAreas', 'gridTemplateColumns', 'gridTemplateRows'], + listStyle: ['listStyleImage', 'listStylePosition', 'listStyleType'], + margin: ['marginBottom', 'marginLeft', 'marginRight', 'marginTop'], + marker: ['markerEnd', 'markerMid', 'markerStart'], + mask: ['maskClip', 'maskComposite', 'maskImage', 'maskMode', 'maskOrigin', 'maskPositionX', 'maskPositionY', 'maskRepeat', 'maskSize'], + maskPosition: ['maskPositionX', 'maskPositionY'], + outline: ['outlineColor', 'outlineStyle', 'outlineWidth'], + overflow: ['overflowX', 'overflowY'], + padding: ['paddingBottom', 'paddingLeft', 'paddingRight', 'paddingTop'], + placeContent: ['alignContent', 'justifyContent'], + placeItems: ['alignItems', 'justifyItems'], + placeSelf: ['alignSelf', 'justifySelf'], + textDecoration: ['textDecorationColor', 'textDecorationLine', 'textDecorationStyle'], + textEmphasis: ['textEmphasisColor', 'textEmphasisStyle'], + transition: ['transitionDelay', 'transitionDuration', 'transitionProperty', 'transitionTimingFunction'], + wordWrap: ['overflowWrap'] + }; \ No newline at end of file diff --git a/react-18.1.0/react-dom.development/packages/react-dom/src/client/DOMPropertyOperations.js b/react-18.1.0/react-dom.development/packages/react-dom/src/client/DOMPropertyOperations.js new file mode 100644 index 0000000..e31901a --- /dev/null +++ b/react-18.1.0/react-dom.development/packages/react-dom/src/client/DOMPropertyOperations.js @@ -0,0 +1,233 @@ + + /** + * 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 { + // This check protects multiple uses of `expected`, which is why the + // react-internal/safe-string-coercion rule is disabled in several spots + // below. + { + checkAttributeStringCoercion(expected, name); + } + + 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. + // eslint-disable-next-line react-internal/safe-string-coercion + 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; + } // eslint-disable-next-line react-internal/safe-string-coercion + + + 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; // eslint-disable-next-line react-internal/safe-string-coercion + } 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 (!node.hasAttribute(name)) { + return expected === undefined ? undefined : null; + } + + var value = node.getAttribute(name); + + { + checkAttributeStringCoercion(expected, 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 ( isCustomComponentTag && name[0] === 'o' && name[1] === 'n') { + var eventName = name.replace(/Capture$/, ''); + var useCapture = name !== eventName; + eventName = eventName.slice(2); + var prevProps = getFiberCurrentPropsFromNode(node); + var prevValue = prevProps != null ? prevProps[name] : null; + + if (typeof prevValue === 'function') { + node.removeEventListener(eventName, prevValue, useCapture); + } + + if (typeof value === 'function') { + if (typeof prevValue !== 'function' && prevValue !== null) { + // If we previously assigned a non-function type into this node, then + // remove it when switching to event listener mode. + if (name in node) { + node[name] = null; + } else if (node.hasAttribute(name)) { + node.removeAttribute(name); + } + } // $FlowFixMe value can't be casted to EventListener. + + + node.addEventListener(eventName, value, useCapture); + return; + } + } + + if ( isCustomComponentTag && name in node) { + node[name] = value; + 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 { + { + checkAttributeStringCoercion(value, name); + } + + 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. + { + { + checkAttributeStringCoercion(value, attributeName); + } + + 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-18.1.0/react-dom.development/packages/react-dom/src/client/ReactDOM.js b/react-18.1.0/react-dom.development/packages/react-dom/src/client/ReactDOM.js new file mode 100644 index 0000000..6c66a25 --- /dev/null +++ b/react-18.1.0/react-dom.development/packages/react-dom/src/client/ReactDOM.js @@ -0,0 +1,92 @@ + setAttemptSynchronousHydration(attemptSynchronousHydration$1); + setAttemptContinuousHydration(attemptContinuousHydration$1); + setAttemptHydrationAtCurrentPriority(attemptHydrationAtCurrentPriority$1); + setGetCurrentUpdatePriority(getCurrentUpdatePriority); + setAttemptHydrationAtPriority(runWithPriority); + + { + 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, flushSync); + + function createPortal$1(children, container) { + var key = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; + + if (!isValidContainer(container)) { + throw new 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 renderSubtreeIntoContainer(parentComponent, element, containerNode, callback) { + return unstable_renderSubtreeIntoContainer(parentComponent, element, containerNode, callback); + } + + var Internals = { + usingClientEntryPoint: false, + // Keep in sync with ReactTestUtils.js. + // This is an array for better minification. + Events: [getInstanceFromNode, getNodeFromInstance, getFiberCurrentPropsFromNode, enqueueStateRestore, restoreStateIfNeeded, batchedUpdates$1] + }; + + function createRoot$1(container, options) { + { + if (!Internals.usingClientEntryPoint && !true) { + error('You are importing createRoot from "react-dom" which is not supported. ' + 'You should instead import it from "react-dom/client".'); + } + } + + return createRoot(container, options); + } + + function hydrateRoot$1(container, initialChildren, options) { + { + if (!Internals.usingClientEntryPoint && !true) { + error('You are importing hydrateRoot from "react-dom" which is not supported. ' + 'You should instead import it from "react-dom/client".'); + } + } + + return hydrateRoot(container, initialChildren, options); + } // Overload the definition to the two valid signatures. + // Warning, this opts-out of checking the function body. + + + // eslint-disable-next-line no-redeclare + function flushSync$1(fn) { + { + if (isAlreadyRendering()) { + error('flushSync was called from inside a lifecycle method. React cannot ' + 'flush when React is already rendering. Consider moving this call to ' + 'a scheduler task or micro task.'); + } + } + + return flushSync(fn); + } + 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-18.1.0/react-dom.development/packages/react-dom/src/client/ReactDOMComponent.js b/react-18.1.0/react-dom.development/packages/react-dom/src/client/ReactDOMComponent.js new file mode 100644 index 0000000..0865240 --- /dev/null +++ b/react-18.1.0/react-dom.development/packages/react-dom/src/client/ReactDOMComponent.js @@ -0,0 +1,1033 @@ + 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 warnedUnknownTags; + var validatePropertiesInDevelopment; + var warnForPropDifference; + var warnForExtraAttributes; + var warnForInvalidEventListener; + var canDiffStyleForHydrationWarning; + 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; + + 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