-
put this file at your react native project workspace root,
-
then run command:
react-native start --transformer ./transformer.js
-
then use another terminal window to run command:
react-native run-ios
orreact-native run-android
-
use menu to choose remote debug with chrome
Last active
March 18, 2018 12:48
-
-
Save frogcjn/fb33fd721e0186cc70ab47994f5c77dc to your computer and use it in GitHub Desktop.
Transformer for debugging ReactNative with TypeScript file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict" | |
const fs = require("fs") | |
const path = require("path") | |
const transformer = require("react-native/packager/transformer") | |
/* | |
1. put this file at your react native project workspace root, | |
2. then run command: | |
`react-native start --transformer ./transformer.js` | |
3. then use another terminal window to run command: | |
`react-native run-ios` | |
or | |
`react-native run-android` | |
4. use menu to choose remote debug with chrome | |
*/ | |
// This function is from https://github.com/mjmeintjes/boot-react-native/blob/master/resources/mattsum/boot_rn/js/cljs-rn-transformer.js | |
function getBasicMappings(code) { | |
//TODO: This is copied from https://github.com/facebook/react-native/blob/528e30987aba8848f8c8815f00c42ecb2ce0919a/packager/react-packager/src/Bundler/Bundle.js#L265 | |
//Therefore it is not working. But, this is only run for js files, and Chrome falls | |
//back to displaying the Javascript from the bundled file anyway when it can't understand | |
//the source mappings from here. | |
//TLDR - I don't think this does anything, and it probably needs to be fixed, but not critical. | |
var mappings = "" | |
const line = "AACA" | |
let lastCharNewLine = false | |
var moduleLines = 0 | |
for (let t = 0; t < code.length; t++) { | |
if (t === 0) { | |
mappings += "AC" | |
mappings += "A" | |
} else if (lastCharNewLine) { | |
moduleLines++ | |
mappings += line | |
} | |
lastCharNewLine = code[t] === "\n" | |
if (lastCharNewLine) { | |
mappings += ";" | |
} | |
} | |
mappings += ";" | |
return mappings | |
} | |
// This function is from https://github.com/mjmeintjes/boot-react-native/blob/master/resources/mattsum/boot_rn/js/cljs-rn-transformer.js | |
function getBasicSourceMap(filename, code) { | |
//This is supposed to just provide a fallback sourcemap | |
//If we don't provide a source map for every module, then Google Chrome | |
//starts throwing errors ('sources' could not be found on undefined) | |
//Chrome expects every section (and there is a section for each module) to | |
//have a 'map' property with an array of 'sources'. | |
var mappings = getBasicMappings(code) | |
const map = { | |
file: "bundle.js", | |
sources: [filename], | |
version: 3, | |
names: [], | |
mappings: mappings, | |
sourcesContent: [""] | |
} | |
return map | |
} | |
// most code are from | |
//https://github.com/Microsoft/vscode-node-debug/blob/master/src/node/sourceMaps.ts | |
const SOURCE_MAPPING_MATCHER = new RegExp("//[#@] ?sourceMappingURL=(.+)$") | |
/** | |
* try to find the 'sourceMappingURL' in the file with the given path. | |
* Returns null in case of errors. | |
* https://github.com/Microsoft/vscode-node-debug/blob/master/src/node/sourceMaps.ts | |
*/ | |
function _findSourceMapUrlInFile(pathToGenerated, content) { | |
try { | |
const contents = content || fs.readFileSync(pathToGenerated).toString() | |
const lines = contents.split("\n") | |
for (let line of lines) { | |
const matches = SOURCE_MAPPING_MATCHER.exec(line) | |
if (matches && matches.length === 2) { | |
const uri = matches[1].trim() | |
return uri | |
} | |
} | |
} catch (_) { | |
// ignore exception | |
} | |
return null | |
} | |
/** | |
* Loads source map from file system. | |
* If no generatedPath is given, the 'file' attribute of the source map is used. | |
* https://github.com/Microsoft/vscode-node-debug/blob/master/src/node/sourceMaps.ts | |
*/ | |
function _loadSourceMap(map_path) { | |
try { | |
const mp = path.join(map_path) | |
const contents = fs.readFileSync(mp).toString() | |
return contents | |
} catch (_) { | |
// TODO | |
} | |
return null | |
} | |
/** | |
* Tries to find a SourceMap for the given path to a generated file. | |
* This is simple if the generated file has the 'sourceMappingURL' at the end. | |
* If not, we are using some heuristics... | |
* https://github.com/Microsoft/vscode-node-debug/blob/master/src/node/sourceMaps.ts | |
*/ | |
function _findGeneratedToSourceMapping(pathToGenerated, content) { | |
if (!pathToGenerated) { | |
return null | |
} | |
// try to find a data uri, which is inline sourcemap in generated file | |
let map_path = null | |
const uri = _findSourceMapUrlInFile(pathToGenerated, content) | |
if (uri) { | |
// if uri is data url source map is inlined in generated file | |
if (uri.indexOf("data:application/json") >= 0) { | |
const pos = uri.lastIndexOf(",") | |
if (pos > 0) { | |
const data = uri.substr(pos + 1) | |
try { | |
const buffer = new Buffer(data, "base64") | |
const json = buffer.toString() | |
if (json) { | |
return json | |
} | |
}catch (_) { | |
// TODO | |
} | |
} | |
} else { | |
map_path = uri | |
} | |
} | |
// try to find a valid url marked in generated file | |
if (map_path && !path.isAbsolute(map_path)) { | |
map_path = path.resolve(path.dirname(pathToGenerated), map_path) | |
} | |
// try to find map file next to the generated source | |
if (!map_path || !fs.existsSync(map_path)) { | |
map_path = pathToGenerated + ".map" | |
} | |
if (map_path && fs.existsSync(map_path)) { | |
const map = _loadSourceMap(map_path, pathToGenerated) | |
if (map) { | |
return map | |
} | |
} | |
return null | |
} | |
function getSourceMapFromCode(pathToSource) { | |
const mapContents = _findGeneratedToSourceMapping(pathToSource) | |
return mapContents ? JSON.parse(mapContents) : null | |
} | |
module.exports = function (data, callback) { | |
const filePath = data.filename | |
const fileContents = data.sourceCode | |
transformer(data, (error, result) => { | |
result.map = result.map || getSourceMapFromCode(filePath, fileContents) || getBasicSourceMap(filePath, fileContents) | |
return callback(error, result) | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment