Skip to content

Commit 6e67295

Browse files
committed
init
1 parent 5ce0503 commit 6e67295

File tree

12 files changed

+393
-0
lines changed

12 files changed

+393
-0
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
PLACE-REACT-SOURCE-CODE-HERE/*
2+
!PLACE-REACT-SOURCE-CODE-HERE/PLACEHOLDER_FOR_GITIGNORE.md
3+
4+
build
5+
16
# Logs
27
logs
38
*.log

.vscode/launch.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
// Use IntelliSense to learn about possible attributes.
3+
// Hover to view descriptions of existing attributes.
4+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5+
"version": "0.2.0",
6+
"configurations": [
7+
8+
{
9+
"type": "node",
10+
"request": "launch",
11+
"name": "Launch Program",
12+
"skipFiles": [
13+
"<node_internals>/**"
14+
],
15+
"program": "${workspaceFolder}/test/test.js",
16+
"cwd": "${workspaceFolder}/PLACE-REACT-SOURCE-CODE-HERE"
17+
}
18+
]
19+
}

PLACE-REACT-SOURCE-CODE-HERE/PLACEHOLDER_FOR_GITIGNORE.md

Whitespace-only changes.

dependencies/source-babel.js

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Document</title>
7+
<script src="./babel.js"></script>
8+
</head>
9+
<body>
10+
<div id="app"></div>
11+
<script>
12+
const data = window.parent.data
13+
var React = data.React
14+
var ReactDOM = data.ReactDOM
15+
</script>
16+
<script type="text/babel" src="./index.js"></script>
17+
</body>
18+
</html>

dependencies/source-index.html

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7+
<title>Debug React Source Code</title>
8+
<script>
9+
var data = {}
10+
function getData() {return data}
11+
function run(React, ReactDOM) {
12+
data.React = React
13+
data.ReactDOM = ReactDOM
14+
const iframeMain = document.createElement('iframe')
15+
iframeMain.src="dependency-main.html"
16+
iframeMain.style.cssText="width:100%; height:100%; border: none;"
17+
document.body.appendChild(iframeMain)
18+
}
19+
</script>
20+
</head>
21+
<style>html,body{width:100%;height:100%;padding:0;margin:0;}</style>
22+
<body>
23+
<iframe id="react" src="./dependency-react.html" frameborder="0" style="display: none;"></iframe>
24+
</body>
25+
26+
</html>

dependencies/source-index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
function App() {
2+
return <div>Hello, React Source Code!</div>
3+
}
4+
5+
ReactDOM.render(<App/>, document.querySelector('#app'))

index.js

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
const fs = require('fs')
2+
const path = require(`path`)
3+
const { spawn, exec } = require('child_process')
4+
const {IDENTITY_START_STR, IDENTITY_END_STR, ANNOTATION_PREFIX} = require('./shared.js')
5+
6+
const PATH_PLUGIN = path.resolve(__dirname, 'rollup-plugin-add-path-info-annoation-for-each-file.js').replace(/\\/g, '/')
7+
const PATH_BUILD = path.resolve(__dirname, 'build').replace(/\\/g, '/')
8+
const PATH_DEPENDENCIES = path.resolve(__dirname, 'dependencies').replace(/\\/g, '/')
9+
10+
11+
const PATH_REACT = path.resolve(__dirname, 'PLACE-REACT-SOURCE-CODE-HERE').replace(/\\/g, '/')
12+
const PATH_REACT_NODE_MODULES = path.resolve(PATH_REACT, 'node_modules').replace(/\\/g, '/')
13+
const PATH_REACT_ROLLUP_BUILD_JS = path.resolve(PATH_REACT, 'scripts/rollup/build.js').replace(/\\/g, '/')
14+
const PATH_NEW_REACT_ROLLUP_BUILD_JS = path.resolve(PATH_REACT, 'scripts/rollup/build.for-debug-react-code.js').replace(/\\/g, '/')
15+
const TMP = 'scripts/rollup/build.for-debug-react-code.js'
16+
const RELATIVE_PATH_NEW_REACT_ROLLUP_BUILD_JS_TO_PLUGIN = path.relative(path.resolve(PATH_REACT, 'scripts/rollup' ), PATH_PLUGIN).replace(/\\/g, '/')
17+
const RELATIVE_PATH_REACT_TO__NEW_REACT_ROLLUP_BUILD_JS = path.relative(PATH_REACT, PATH_NEW_REACT_ROLLUP_BUILD_JS).replace(/\\/g, '/')
18+
const RELATIVE_PATH_ROLLUP_BUILD_JS_TO_REACT = path.relative(PATH_REACT_ROLLUP_BUILD_JS, PATH_REACT).replace(/\\/g, '/')
19+
20+
const NAME_PLUGIN = `$$addPathInfoAnnotationForEachFilePlugin`
21+
22+
const NAME_DEPENDENCY_REACT = 'dependency-react.html'
23+
const NAME_DEPENDENCY_REACT_DOM = 'dependency-react-dom.html'
24+
const NAME_DEPENDENCY_DEFAULT_JS = `index.js`
25+
26+
const PATH_DEPENDENCY_SOURCE_BABEL = path.resolve(PATH_DEPENDENCIES, 'source-babel.js').replace(/\\/g, '/')
27+
const PATH_DEPENDENCY_SOURCE_DEPENDENCY_MAIN = path.resolve(PATH_DEPENDENCIES, 'source-dependency-main.html').replace(/\\/g, '/')
28+
const PATH_DEPENDENCY_SOURCE_DEFAULT_JS = path.resolve(PATH_DEPENDENCIES, 'source-index.js').replace(/\\/g, '/')
29+
const PATH_DEPENDENCY_SOURCE_DEFAULT = path.resolve(PATH_DEPENDENCIES, 'source-index.html').replace(/\\/g, '/')
30+
31+
// # generate a new build js
32+
function generateNewBuildJS() {
33+
const buildJsStr = fs.readFileSync(PATH_REACT_ROLLUP_BUILD_JS, {encoding: 'utf8'})
34+
const lines = buildJsStr.split('\n')
35+
const newFistLine = `const ${NAME_PLUGIN} = require('${RELATIVE_PATH_NEW_REACT_ROLLUP_BUILD_JS_TO_PLUGIN}');\n`
36+
newBuildJsStr = newFistLine + lines.map(line => {
37+
if (line.match(/if \(isWatchMode\)/)) {
38+
return `rollupConfig.plugins.push(${NAME_PLUGIN}('${PATH_REACT}'));
39+
${line}`
40+
}
41+
return line
42+
}).join('\n')
43+
fs.writeFileSync(PATH_NEW_REACT_ROLLUP_BUILD_JS, newBuildJsStr, {encoding: 'utf-8'})
44+
console.log(`$$ DEBUG REACT SOURCE CODE: generated a new build js!`)
45+
}
46+
47+
function installDependencies(cb) {
48+
const ls = spawn(`yarn.cmd`, [`install`], {cwd: PATH_REACT})
49+
ls.stdout.on('data', data => console.log(data.toString()))
50+
ls.stdout.on('close', cb)
51+
}
52+
53+
function build(cb) {
54+
const ls = spawn('node', [TMP, `react/index,react-dom/index`, `--type`, `UMD_DEV`], {cwd: PATH_REACT})
55+
ls.stdout.on('data', data => console.log(data.toString()))
56+
ls.stderr.on('data', data => console.log(data.toString()))
57+
ls.on('close', () => {
58+
console.log(`$$ DEBUG REACT SOURCE CODE: generated react.development.js and react-dom.development.js!`)
59+
cb()
60+
})
61+
}
62+
63+
function getReactOrReactDOMNamespace(reactOrReactDOMDevelopmentFile) {
64+
const isReactFile = path.parse(reactOrReactDOMDevelopmentFile).name.replace(/\..*/, '') === 'react'
65+
return isReactFile ? 'React' : 'ReactDOM'
66+
}
67+
68+
/**
69+
*
70+
* @param {*} reactOrReactDOMDevelopmentFile
71+
* @return {{outputFile, text}[]}
72+
*/
73+
function getReactOrReactDOMSplitFilesData(reactOrReactDOMDevelopmentFile) {
74+
const getFileOnEndLine = (line, lineIndex) => {
75+
const isSpecialFormat = /commonjs-proxy-/.test( line )
76+
77+
if ( isSpecialFormat ) {
78+
let path = line.replace( /.*commonjs-proxy-/, '' )
79+
path = PATH.relative( PATH_REACT, path ).replace(/\\/g,'/')
80+
81+
return `commonjs-proxy-/${ path }`
82+
// return path
83+
}
84+
return line.replace( new RegExp(`.*${ANNOTATION_PREFIX.replace('/', '\\/')}${IDENTITY_END_STR.replace(/\$/g, '\\$')} `), '' )
85+
}
86+
const isStartLine = line => new RegExp( `${IDENTITY_START_STR.replace(/\$/g, '\\$')}` ).test( line )
87+
const isEndLine = line => new RegExp( `${IDENTITY_END_STR.replace(/\$/g, '\\$')}` ).test( line )
88+
89+
const namespace = getReactOrReactDOMNamespace(reactOrReactDOMDevelopmentFile)
90+
91+
const sourceText = fs.readFileSync(reactOrReactDOMDevelopmentFile, {encoding: 'utf8'})
92+
const lines = sourceText.split( '\n' )
93+
/** @type {{outputFile, text}[]} */
94+
const data = []
95+
let hasStarted = false
96+
// resolve the content between **end** and **start**
97+
let isBetweenEndAndStart = false
98+
/** @type {string[]} */
99+
let curry = []
100+
let lineIndex = -1
101+
for (let line of lines) {
102+
lineIndex++
103+
104+
if (isStartLine(line)) {
105+
hasStarted = true
106+
}
107+
if (hasStarted) {
108+
if (isStartLine(line) || lineIndex === lines.length - 2) {
109+
if (isBetweenEndAndStart && curry.length > 0 && !(curry.every(line => line.trim() === ''))) {
110+
const outputFile = `$$umd/line-number-${lineIndex}.js`
111+
let text = curry.join('\n')
112+
text = text.replace(/exports/g, namespace)
113+
data.push({outputFile, text})
114+
}
115+
isBetweenEndAndStart = false
116+
curry = []
117+
}
118+
if (!isStartLine(line) && !isEndLine(line)) {curry.push(line)}
119+
if (isEndLine(line)) {
120+
let text = curry.join('\n')
121+
text = text.replace(/exports/g, namespace)
122+
const outputFile = getFileOnEndLine(line)
123+
data.push({outputFile, text})
124+
curry = []
125+
isBetweenEndAndStart = true
126+
}
127+
}
128+
}
129+
return data
130+
}
131+
132+
/**
133+
*
134+
* @param {{outputFile, text}[]} filesData
135+
* @param {string} reactOrReactDOMDevelopmentFile
136+
*/
137+
function generateReactOrReactDOMSplitFiles(filesData, reactOrReactDOMDevelopmentFile) {
138+
for (let {outputFile, text} of filesData) {
139+
const folderName = path.parse(reactOrReactDOMDevelopmentFile).name
140+
const targetPath = path.resolve(PATH_BUILD, `${folderName}/${outputFile}`)
141+
const folerPath = path.dirname(targetPath)
142+
!fs.existsSync(folerPath) && fs.mkdirSync(folerPath, {recursive: true})
143+
fs.writeFileSync(targetPath, text, {encoding: 'utf-8'})
144+
}
145+
}
146+
147+
function copyDependencies() {
148+
const dependencyPaths = [
149+
PATH_DEPENDENCY_SOURCE_BABEL,
150+
PATH_DEPENDENCY_SOURCE_DEPENDENCY_MAIN,
151+
PATH_DEPENDENCY_SOURCE_DEFAULT_JS,
152+
PATH_DEPENDENCY_SOURCE_DEFAULT,
153+
]
154+
for (let file of dependencyPaths) {
155+
const filename = path.parse(file).base.replace(/^source-/, '')
156+
const targetPath = path.resolve(PATH_BUILD, filename)
157+
fs.copyFileSync(file, targetPath)
158+
}
159+
}
160+
161+
162+
function generateDependencyReactDOMHTML(reactDOMFilesData, reactDOMFile) {
163+
const namespace = getReactOrReactDOMNamespace(reactDOMFile)
164+
const dependencyFolerName = path.parse(reactDOMFile).name
165+
const mainText = reactDOMFilesData.map(v => `<script src="./${dependencyFolerName}/${v.outputFile}"></script>`).join('\n')
166+
const text = `<!DOCTYPE html>
167+
<html lang="en">
168+
<head>
169+
<meta charset="UTF-8">
170+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
171+
<title>Dependency ${namespace}</title>
172+
<script>var React = window.parent.React;</script>
173+
<script>var ${namespace} = {};</script>
174+
${mainText}
175+
</head>
176+
<body>
177+
</body>
178+
</html>`
179+
const targetPath = path.resolve(PATH_BUILD, NAME_DEPENDENCY_REACT_DOM)
180+
fs.writeFileSync(targetPath, text, {encoding: 'utf-8'})
181+
}
182+
183+
function generateDependencyReactHTML(reactFilesData, reactFile) {
184+
const namespace = getReactOrReactDOMNamespace(reactFile)
185+
const dependencyFolerName = path.parse(reactFile).name
186+
const mainText = reactFilesData.map(v => `<script src="./${dependencyFolerName}/${v.outputFile}"></script>`).join('\n')
187+
const text = `<!DOCTYPE html>
188+
<html lang="en">
189+
<head>
190+
<meta charset="UTF-8">
191+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
192+
<title>Dependency ${namespace}</title>
193+
<script>var ${namespace} = {};</script>
194+
${mainText}
195+
</head>
196+
<body>
197+
<iframe id="react-dom" src="./${NAME_DEPENDENCY_REACT_DOM}" frameborder="0"></iframe>
198+
<script>
199+
const domReactDOM = document.querySelector('#react-dom')
200+
domReactDOM.contentWindow.onload = () => {
201+
window.parent.run(React, domReactDOM.contentWindow.ReactDOM)
202+
}
203+
</script>
204+
</body>
205+
</html>`
206+
const targetPath = path.resolve(PATH_BUILD, NAME_DEPENDENCY_REACT)
207+
fs.writeFileSync(targetPath, text, {encoding: 'utf-8'})
208+
}
209+
210+
211+
212+
213+
214+
module.exports.getReactOrReactDOMSplitFilesData = getReactOrReactDOMSplitFilesData
215+
module.exports.generateReactOrReactDOMSplitFiles = generateReactOrReactDOMSplitFiles
216+
module.exports.copyDependencies = copyDependencies
217+
module.exports.generateDependencyReactDOMHTML = generateDependencyReactDOMHTML
218+
module.exports.generateDependencyReactHTML = generateDependencyReactHTML
219+
module.exports.PATH_REACT = PATH_REACT

package.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"name": "debug-react-source-code",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "index.js",
6+
"scripts": {
7+
"start": "node index.js",
8+
"serve": "serve build",
9+
"test": "node test/test.js"
10+
},
11+
"repository": {
12+
"type": "git",
13+
"url": "git+https://github.com/Terry-Su/debug-react-source-code.git"
14+
},
15+
"keywords": [],
16+
"author": "",
17+
"license": "ISC",
18+
"bugs": {
19+
"url": "https://github.com/Terry-Su/debug-react-source-code/issues"
20+
},
21+
"homepage": "https://github.com/Terry-Su/debug-react-source-code#readme",
22+
"devDependencies": {
23+
"serve": "^11.3.2"
24+
}
25+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
const path = require('path')
2+
const {IDENTITY_START_STR, IDENTITY_END_STR, ANNOTATION_PREFIX} = require('./shared.js')
3+
4+
module.exports = function addPathInfoAnnotationForEachFile (root) {
5+
return {
6+
name: 'add path info annotation for each file', // this name will show up in warnings and errors
7+
transform(source, id) {
8+
let name = root == null ? path.basename( id ) : path.relative( root, id )
9+
name = name.replace(/\\/g, '/')
10+
11+
// deal with special situation
12+
const REGEXP = /commonjs\-proxy\:/
13+
const isCommonJsProxyPath = path => REGEXP.test( path )
14+
if ( isCommonJsProxyPath( id ) ) {
15+
id = id.replace( REGEXP, '/' )
16+
name = id.replace( `${root}`, '' )
17+
}
18+
return `${ANNOTATION_PREFIX}${IDENTITY_START_STR} ${ name }
19+
${source}
20+
${ANNOTATION_PREFIX}${IDENTITY_END_STR} ${ name }`
21+
}
22+
}
23+
}

0 commit comments

Comments
 (0)