From 8bc7b3d821a7fbf89e604dc9a264506f04a80964 Mon Sep 17 00:00:00 2001 From: kiacolbert Date: Fri, 1 Mar 2019 15:21:02 -0500 Subject: [PATCH 1/4] Parses react.development.js find, injects our method body into useReducer, and generates genCode.js file. --- src/app/package-lock.json | 80 +++++++++++++++++++++++++++++++++++++++ src/app/package.json | 3 ++ src/app/parser.js | 51 +++++++++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 src/app/parser.js diff --git a/src/app/package-lock.json b/src/app/package-lock.json index 09283ed..35f43d0 100644 --- a/src/app/package-lock.json +++ b/src/app/package-lock.json @@ -2040,6 +2040,11 @@ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, "default-gateway": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.1.2.tgz", @@ -2350,6 +2355,31 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, + "escodegen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz", + "integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==", + "requires": { + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true + } + } + }, "eslint-scope": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", @@ -2359,6 +2389,11 @@ "estraverse": "^4.1.1" } }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, "esrecurse": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", @@ -2626,6 +2661,11 @@ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, "fastparse": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", @@ -4158,6 +4198,15 @@ "invert-kv": "^2.0.0" } }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, "loader-runner": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", @@ -4747,6 +4796,19 @@ "is-wsl": "^1.1.0" } }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, "original": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", @@ -5076,6 +5138,11 @@ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, "pretty-error": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", @@ -6376,6 +6443,14 @@ "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=" }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "~1.1.2" + } + }, "type-is": { "version": "1.6.16", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", @@ -6907,6 +6982,11 @@ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, "worker-farm": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz", diff --git a/src/app/package.json b/src/app/package.json index eb7277b..214444a 100644 --- a/src/app/package.json +++ b/src/app/package.json @@ -23,6 +23,9 @@ "@babel/register": "^7.0.0", "babel-loader": "^8.0.5", "css-loader": "^2.1.0", + "escodegen": "^1.11.1", + "esprima": "^4.0.1", + "estraverse": "^4.2.0", "html-webpack-plugin": "^3.2.0", "react": "^16.8.3", "react-dom": "^16.8.3", diff --git a/src/app/parser.js b/src/app/parser.js new file mode 100644 index 0000000..c2ab899 --- /dev/null +++ b/src/app/parser.js @@ -0,0 +1,51 @@ +const esprima = require('esprima'); +const fs = require('fs'); +const estraverse = require('estraverse'); +const escodegen = require('escodegen'); +const path = require('path'); +// contains useReducer +const file = '/node_modules/react/cjs/react.development.js'; +// 20k lines +// const file = '/node_modules/react-dom/cjs/react-dom.development.js'; + +// convert file to string and parse +const dir = path.join(__dirname, file); +const fileString = fs.readFileSync(dir, { encoding: 'utf-8' }); +const ast = esprima.parseModule(fileString); + + +// declare function to insert +// TODO: Un-comment timeTravelTracker +function replacer() { + let dispatcher = resolveDispatcher(); + function reducerWithTracker(state, action) { + const newState = reducer(state, action); + // timeTravelTracker[timeTravelTracker.length - 1].actionDispatched = true; + window.postMessage({ + type: 'DISPATCH', + data: { + state: newState, + action, + }, + }); + return newState; + } + return dispatcher.useReducer(reducerWithTracker, initialArg, init); +} + +const replacerNode = esprima.parseScript(replacer.toString()); + +// traverse ast to find method and replace body with our node's body +estraverse.replace(ast, { + enter(node) { + if (node.type === 'FunctionDeclaration') { + if (node.id.name === 'useReducer') { + node.body = replacerNode.body[0].body; + } + } + }, +}); +const code = escodegen.generate(ast); +fs.writeFileSync('genCode.js', code, (err) => { + if (err) throw new Error(err.message); +}); From c9a41f05bcb286eb64a245ef42e69be3e1c1ee8c Mon Sep 17 00:00:00 2001 From: kiacolbert Date: Fri, 1 Mar 2019 16:20:55 -0500 Subject: [PATCH 2/4] Created functions. --- src/app/parser.js | 75 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 24 deletions(-) diff --git a/src/app/parser.js b/src/app/parser.js index c2ab899..22abb7c 100644 --- a/src/app/parser.js +++ b/src/app/parser.js @@ -3,20 +3,25 @@ const fs = require('fs'); const estraverse = require('estraverse'); const escodegen = require('escodegen'); const path = require('path'); -// contains useReducer -const file = '/node_modules/react/cjs/react.development.js'; -// 20k lines -// const file = '/node_modules/react-dom/cjs/react-dom.development.js'; -// convert file to string and parse -const dir = path.join(__dirname, file); -const fileString = fs.readFileSync(dir, { encoding: 'utf-8' }); -const ast = esprima.parseModule(fileString); +// react files +const useReducerfile = '/node_modules/react/cjs/react.development.js'; +const commitAllHostEffectsfile = '/node_modules/react-dom/cjs/react-dom.development.js'; +// generated file names +const genReactDev = 'generatedReact.development.js'; +const genReactDom = 'generatedReact-dom.development.js'; -// declare function to insert +// convert file to string and parse +function parseFile(file) { + const dir = path.join(__dirname, file); + const fileString = fs.readFileSync(dir, { encoding: 'utf-8' }); + const ast = esprima.parseModule(fileString); + return ast; +} +// declare functions to insert // TODO: Un-comment timeTravelTracker -function replacer() { +function useReducerReplacement() { let dispatcher = resolveDispatcher(); function reducerWithTracker(state, action) { const newState = reducer(state, action); @@ -32,20 +37,42 @@ function replacer() { } return dispatcher.useReducer(reducerWithTracker, initialArg, init); } - -const replacerNode = esprima.parseScript(replacer.toString()); +function commitAllHostEffectsReplacement() { + console.log('You just got swapped!'); +} // traverse ast to find method and replace body with our node's body -estraverse.replace(ast, { - enter(node) { - if (node.type === 'FunctionDeclaration') { - if (node.id.name === 'useReducer') { - node.body = replacerNode.body[0].body; +function traverseTree(replacementNode, functionName, ast) { + estraverse.replace(ast, { + enter(node) { + if (node.type === 'FunctionDeclaration') { + if (node.id.name === functionName) { + node.body = replacementNode.body[0].body; + } } - } - }, -}); -const code = escodegen.generate(ast); -fs.writeFileSync('genCode.js', code, (err) => { - if (err) throw new Error(err.message); -}); + }, + }); +} + +function generateFile(filename, ast) { + const code = escodegen.generate(ast); + fs.writeFileSync(filename, code, (err) => { + if (err) throw new Error(err.message); + }); +} + +const parseAndGenerate = () => { + const ast = parseFile(useReducerfile); + // const ast = parseFile(commitAllHostEffectsfile); + + const injectableUseReducer = esprima.parseScript(useReducerReplacement.toString()); + // const injectablecommitAllHostEffects = esprima.parseScript(useReducerReplacement.toString()); + + traverseTree(injectableUseReducer, 'useReducer', ast); + // traverseTree(injectablecommitAllHostEffects, 'commitAllHostEffects'); + + generateFile(genReactDev, ast); + // generateFile(genReactDom); +}; +// parseAndGenerate(); +module.exports = parseAndGenerate; From 371245fde88afc3c412e81ab2aa0d19b8ce9e4a0 Mon Sep 17 00:00:00 2001 From: kiacolbert Date: Fri, 1 Mar 2019 16:45:13 -0500 Subject: [PATCH 3/4] Add commitAllHostEffects code and functionality. --- src/app/parser.js | 113 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 104 insertions(+), 9 deletions(-) diff --git a/src/app/parser.js b/src/app/parser.js index 22abb7c..9c777fe 100644 --- a/src/app/parser.js +++ b/src/app/parser.js @@ -3,6 +3,7 @@ const fs = require('fs'); const estraverse = require('estraverse'); const escodegen = require('escodegen'); const path = require('path'); +const _ = require('lodash'); // react files const useReducerfile = '/node_modules/react/cjs/react.development.js'; @@ -38,7 +39,101 @@ function useReducerReplacement() { return dispatcher.useReducer(reducerWithTracker, initialArg, init); } function commitAllHostEffectsReplacement() { - console.log('You just got swapped!'); + while (nextEffect !== null) { + { + setCurrentFiber(nextEffect); + } + recordEffect(); + + var effectTag = nextEffect.effectTag; + + if (effectTag & ContentReset) { + commitResetTextContent(nextEffect); + } + + if (effectTag & Ref) { + var current$$1 = nextEffect.alternate; + if (current$$1 !== null) { + commitDetachRef(current$$1); + } + } + + // The following switch statement is only concerned about placement, + // updates, and deletions. To avoid needing to add a case for every + // possible bitmap value, we remove the secondary effects from the + // effect tag and switch on that value. + var primaryEffectTag = effectTag & (Placement | Update | Deletion); + switch (primaryEffectTag) { + case Placement: + { + //editbyme + window.postMessage({ + type: 'EFFECT', + data: { + primaryEffectTag: 'PLACEMENT', + effect: _.cloneDeep(nextEffect) + } + }); + + commitPlacement(nextEffect); + // Clear the "placement" from effect tag so that we know that this is inserted, before + // any life-cycles like componentDidMount gets called. + // TODO: findDOMNode doesn't rely on this any more but isMounted + // does and isMounted is deprecated anyway so we should be able + // to kill this. + nextEffect.effectTag &= ~Placement; + break; + } + case PlacementAndUpdate: + { + // Placement + commitPlacement(nextEffect); + // Clear the "placement" from effect tag so that we know that this is inserted, before + // any life-cycles like componentDidMount gets called. + nextEffect.effectTag &= ~Placement; + + // Update + var _current = nextEffect.alternate; + commitWork(_current, nextEffect); + break; + } + case Update: + { + //editbyme + window.postMessage({ + type: 'EFFECT', + data: { + primaryEffectTag: 'UPDATE', + effect: _.cloneDeep(nextEffect), + current: _.cloneDeep(nextEffect.alternate), + }, + }); + + var _current2 = nextEffect.alternate; + commitWork(_current2, nextEffect); + break; + } + case Deletion: + { + //editbyme + window.postMessage({ + type: 'EFFECT', + data: { + primaryEffectTag: 'DELETION', + effect: _.cloneDeep(nextEffect), + }, + }); + + commitDeletion(nextEffect); + break; + } + } + nextEffect = nextEffect.nextEffect; + } + + { + resetCurrentFiber(); + } } // traverse ast to find method and replace body with our node's body @@ -62,17 +157,17 @@ function generateFile(filename, ast) { } const parseAndGenerate = () => { - const ast = parseFile(useReducerfile); - // const ast = parseFile(commitAllHostEffectsfile); - + // first file + let ast = parseFile(useReducerfile); const injectableUseReducer = esprima.parseScript(useReducerReplacement.toString()); - // const injectablecommitAllHostEffects = esprima.parseScript(useReducerReplacement.toString()); - traverseTree(injectableUseReducer, 'useReducer', ast); - // traverseTree(injectablecommitAllHostEffects, 'commitAllHostEffects'); - generateFile(genReactDev, ast); - // generateFile(genReactDom); + // second file + ast = parseFile(commitAllHostEffectsfile); + const injectableCommitAllHostEffects = esprima.parseScript(commitAllHostEffectsReplacement.toString()); + traverseTree(injectableCommitAllHostEffects, 'commitAllHostEffects', ast); + generateFile(genReactDom, ast); }; + // parseAndGenerate(); module.exports = parseAndGenerate; From 7e8f492ea7155e639b7f839c54d647746605d491 Mon Sep 17 00:00:00 2001 From: kiacolbert Date: Fri, 1 Mar 2019 17:13:06 -0500 Subject: [PATCH 4/4] Removed comment. --- src/app/parser.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/parser.js b/src/app/parser.js index 9c777fe..338b03d 100644 --- a/src/app/parser.js +++ b/src/app/parser.js @@ -169,5 +169,4 @@ const parseAndGenerate = () => { generateFile(genReactDom, ast); }; -// parseAndGenerate(); module.exports = parseAndGenerate;