Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Debugging TypeScript Source Files? #240

Closed
joewood opened this issue May 31, 2016 · 17 comments
Closed

Debugging TypeScript Source Files? #240

joewood opened this issue May 31, 2016 · 17 comments

Comments

@joewood
Copy link

@joewood joewood commented May 31, 2016

The source map issue has been discussed in the React Native repo a fair bit. The RN packager seems to consume source maps with a custom Transformer see here. My question is, is it possible to set-up the VS Code Extension so that TypeScript source files can be used through the debugger (e.g. set breakpoints etc.)?

If this is possible, could you describe what source map settings need to be used (e.g. inline source maps etc..)?

I'm using 0.1.4 of the React Native Extension with VS code 1.1.1.

@ghost
Copy link

@ghost ghost commented Jun 1, 2016

@joewood we don't currently have a solution for this, we'll need to spend some time looking at it. Currently the team is busy with some non-related work, we'll add this to our backlog and get back to it when we can.

@ghost ghost added help wanted question labels Jun 1, 2016
@joewood
Copy link
Author

@joewood joewood commented Jun 1, 2016

Thanks for the response. It may be necessary to use a custom transformer for TypeScript. I'll keep investigating and post anything I find here.

@joewood
Copy link
Author

@joewood joewood commented Jun 3, 2016

Hi @hamiltonia
I've had some limited success in getting this to work. The approach I'm looking at is to replace the react-native transformer with a version that supplies the babel option inputSourceMap. I patched the transform.js file from RN's packager in two places, one to set the option for Babel and the other to read in the map file:

/**
 * Copyright (c) 2015-present, Facebook, Inc.
  */
'use strict';

const babel = require('babel-core');
const externalHelpersPlugin = require('babel-plugin-external-helpers');
const fs = require('fs');
const makeHMRConfig = require('babel-preset-react-native/configs/hmr');
const resolvePlugins = require('babel-preset-react-native/lib/resolvePlugins');
const inlineRequiresPlugin = require('fbjs-scripts/babel-6/inline-requires');
const json5 = require('json5');
const path = require('path');

const getBabelRC = (function () {
  let babelRC = null;

  return function _getBabelRC(projectRoots) {
    if (babelRC !== null) {
      return babelRC;
    }

    babelRC = { plugins: [] }; // empty babelrc

    let projectBabelRCPath;
    if (projectRoots && projectRoots.length > 0) {
      projectBabelRCPath = path.resolve(projectRoots[0], '.babelrc');
    }

    if (!projectBabelRCPath || !fs.existsSync(projectBabelRCPath)) {
      babelRC = json5.parse(
        fs.readFileSync(
          path.resolve(__dirname, 'node_modules/react-native/packager/react-packager', 'rn-babelrc.json'))
      );

      // Require the babel-preset's listed in the default babel config
      babelRC.presets = babelRC.presets.map((preset) => require('babel-preset-' + preset));
      babelRC.plugins = resolvePlugins(babelRC.plugins);
    }

    return babelRC;
  };
})();

/**
 * Given a filename and options, build a Babel
 * config object with the appropriate plugins.
 */
function buildBabelConfig(filename, options) {
  const babelRC = getBabelRC(options.projectRoots);

  const extraConfig = {
    filename,
    sourceFileName: filename,
    // ADDED PATCH FOR INPUT SOURCE MAPS
    inputSourceMap: options.inputSourceMap
  };
  let config = Object.assign({}, babelRC, extraConfig);

  // Add extra plugins
  const extraPlugins = [externalHelpersPlugin];

  var inlineRequires = options.inlineRequires;
  var blacklist = inlineRequires && inlineRequires.blacklist;
  if (inlineRequires && !(blacklist && filename in blacklist)) {
    extraPlugins.push(inlineRequiresPlugin);
  }

  config.plugins = extraPlugins.concat(config.plugins);

  if (options.hot) {
    const hmrConfig = makeHMRConfig(options, filename);
    config = Object.assign({}, config, hmrConfig);
  }

  return Object.assign({}, babelRC, config);
}

function transform(src, filename, options) {
  options = options || {};

  const babelConfig = buildBabelConfig(filename, options);

  const result = babel.transform(src, babelConfig);

  return {
    ast: result.ast,
    code: result.code,
    map: result.map,
    filename: filename,
  };
}

module.exports = function (data, callback) {
  // ADDED PATCH FOR INPUT SOURCE MAPS
  if (fs.existsSync(data.filename + ".map")) {
    console.log("Adding Map for " + data.filename);
    data.options = data.options || {};
    data.options.inputSourceMap = JSON.parse(fs.readFileSync(data.filename + ".map").toString());
    data.options.sourceMaps = true;
  }
  // END PATCH
  let result;
  try {
    result = transform(data.sourceCode, data.filename, data.options);
  } catch (e) {
    callback(e);
    return;
  }

  callback(null, result);
};

// export for use in jest
module.exports.transform = transform;

All this is doing is sending the mapfile data to babel if it exists as a .js.map file (bit of an assumption, but this is just for testing). I can use this transform with VSCode if I change the RN Native Extension's Packager.start function. I simply add the arguments for the command line:

    .then(function () {
        var args = ["--port", Packager.PORT,"--transformer","c:\\code\\app\\transform.js"];
        var childEnvForDebugging = Object.assign({}, process.env, { REACT_DEBUGGER: "echo A debugger is not needed: " });

Note, there's a bug in RN where the transform module needs to specified with a full path.

This all seems to work OK, in that when I browse to look at the .map file in the browser the TypeScript source files are referenced correctly. However, the problem is that VSCode doesn't seem to be picking them up and loading the source files. Injecting a "debugger" statement just opens up the main bundle file. I've tried using sourceRoot and relative paths, but without success. So, it seems to be failing at the last step.

Any suggestions would be appreciated. Thanks.

@joewood
Copy link
Author

@joewood joewood commented Jun 3, 2016

FYI - I tried debugging in DevTools, but I see the error "Failed to Parse SourceMap". However, this error could be related to the Chrome 51 bug logged here: https://bugs.chromium.org/p/chromium/issues/detail?id=611328

@frogcjn
Copy link
Contributor

@frogcjn frogcjn commented Jun 4, 2016

So recently we cannot debug in typescript?

@frogcjn
Copy link
Contributor

@frogcjn frogcjn commented Jun 5, 2016

@joewood
Here is my post to explain how to deal with this debugger problem with typescript:
make_VSCode_debug_RN_TS.md

Also refer to these two issues
facebook/react-native#393
facebook/react-native#7083

@frogcjn
Copy link
Contributor

@frogcjn frogcjn commented Jun 7, 2016

I have make some progress on debugging typescript in vscode
2016-06-07 16 43 04

@frogcjn
Copy link
Contributor

@frogcjn frogcjn commented Jun 7, 2016

Success! I'll write a post to explain how to debug typescript file with react native in vscode.
2016-06-07 19 31 45

@frogcjn
Copy link
Contributor

@frogcjn frogcjn commented Jun 9, 2016

@joewood

Here is my post to explain how to debug ReactNative project in VSCode with typescript:
make_VSCode_debug_RN_TS.md

@MSLaguana
Copy link
Member

@MSLaguana MSLaguana commented Jun 9, 2016

Thanks a lot for looking into that and providing a detailed explanation @frogcjn!
We've been a bit busy on other projects so we haven't had a chance to look over your PR closely yet, but we'll try to get to that soon. We definitely want to get this working.

@MSLaguana
Copy link
Member

@MSLaguana MSLaguana commented Jul 13, 2016

Thanks to @frogcjn for his PR implementing this: #259

Support will be in the next release.

@forki
Copy link

@forki forki commented Aug 6, 2016

when will we see the next release?

@MSLaguana
Copy link
Member

@MSLaguana MSLaguana commented Aug 9, 2016

Soon™

While you wait for the official release, you can check out this repo and build it yourself.

@forki
Copy link

@forki forki commented Aug 9, 2016

Thanks that's good enough for me. I'm way to deep down the wrong rabbit
hole already ;-)

On Aug 9, 2016 8:07 PM, "Jimmy Thomson" notifications@github.com wrote:

Soon™

While you wait for the official release, you can check out this repo and
build it yourself.


You are receiving this because you commented.
Reply to this email directly, view it on GitHub
#240 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AADgNBjffQiAqErR92LgPodAOFr9zpl8ks5qeMHVgaJpZM4Iqn0T
.

@mbraude
Copy link
Contributor

@mbraude mbraude commented Aug 23, 2016

Thanks @joewood - this change is in the repo and will go out in the next release.

@mbraude mbraude closed this Aug 23, 2016
@Flavien
Copy link

@Flavien Flavien commented Dec 23, 2016

I'm still struggling to get breakpoints to light up in VS Code with TypeScript on a react-native project. I followed the instructions and set sourceMap to true in .babelrc.

Am I missing something?

@vladimir-kotikov
Copy link
Contributor

@vladimir-kotikov vladimir-kotikov commented Jan 10, 2017

@Flavien, what instructions are you referring to? Could you please describe exact steps you have tried?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
8 participants
@forki @Flavien @joewood @frogcjn @vladimir-kotikov @mbraude @MSLaguana and others
You can’t perform that action at this time.