ds300/react-native-typescript-transformer

Minified code gives wrong line of code

hffmnn opened this issue ยท 9 comments

Hi there,

I tried out the transformer and it works perfect in dev mode, so first: thanks a lot for that :) ๐Ÿ‘

Nonetheless:
When not running in debug mode and let the code crash somewhere, the lines and colums are a little bit off.

Steps to reproduce (I forked git clone https://github.com/cbrevik/react-native-typescript-starter and did some changes to illustrate the problem):

https://github.com/hffmnn/react-native-typescript-starter
cd react-native-typescript-starter
git checkout --track origin/feature/ts_map
yarn
yarn bundle:ios:release

Open the iOS project with Xcode and press run.I modified:

  • index.tsx to crash after 3 seconds
  • the Xcode scheme to run in Release mode
  • the Xcode Build Phase to not start the bundling.

The app will crash. Press continue until Xcode spits out something useful like:

Exception: Can't find variable: doSomethingStupid, stack:
<unknown>@365:441
callTimer@31:626
callTimers@31:1010
value@29:2893
<unknown>@29:832
value@29:2294
value@29:804

Run

./symbolicate.js ios/main.jsbundle.map 365 441

Expected:
The output is: <some_user_specific_path>/react-native-typescript-starter/src/index.tsx:19

Experienced:
The output is: <some_user_specific_path>/react-native-typescript-starter/src/index.tsx:13 (Note the difference in the line number)

To verify that it has something to do with dev mode or maybe minify:

  • Delete the app from simulator!!!
  • Clean the Xcode project!!!
  • Run yarn bundle:ios:dev
  • Rerun the application

Experienced:
The output is (as expected): <some_user_specific_path>/react-native-typescript-starter/src/index.tsx:19

I already verified, that the generated sourcemaps for JS based projects (so e.g. a default RN project) work in dev and release mode, so this issue is only valid for how we create the source maps for TS.

I already checked the docs for source-map (https://www.npmjs.com/package/source-map) but could not find any hint, why that should not work.

Any ideas what else might be the problem?

ds300 commented

Can't think of any reason off the top of my head. Will have to do some debugging. Thanks for the detailed report!

ds300 commented

Progress update: I think I've nailed down the source of the problem, but it seems to be an issue with react-native or babel.

The packager does constant folding and function inlining on transform results in release mode. It gets invoked here: https://github.com/facebook/react-native/blob/0.45-stable/packager/src/JSTransformer/worker/worker.js#L119 (permalink)

If you comment out that and the surrounding lines so that it always takes the else branch, the minified bundle source maps are fine.

Will keep working on this to find out what the issue is.

ds300 commented

More notekeeping (still unresolved):

I tried using the TypeScript transformer by @orta and co here: https://github.com/artsy/emission/tree/master/transformer but had the same issue (even off by the same number of lines), despite that transformer being quite different in it's approach to both leveraging babel and creating source maps

I also suspected that it might be something to do with the fact that the babel AST in the compile result emitted by my transformer was created by babel without an inputSourceMap for context. So I tried removing the ast from the result. Same issue. Then I tried patching the upstream transformer to accept a fourth argument, inputSourceMap and to pass it along to babel for context. That didn't work either.

Next I think I'll try testing the [inlining->constant folding] part of the pipeline in isolation, and will submit a bug report to Metro if I can show it's producing wonky results.

ds300 commented

Metro issue over here facebook/metro#10 ๐Ÿคž

Thanks a lot for looking into it. And: Great issue on metro-bundler! โค๏ธ

Maybe this is fixed now?

No problems here with react-native@0.53.0 and react-native-typescript-transformer@1.2.3 in production.

ds300 commented

Cool beans. I'm gonna close this. Thanks @quincycs and @skellock

I have tried to test this issue with new version of React Native and I am still able to reproduce it on both android and iOS. I have forked https://github.com/hffmnn/react-native-typescript-starter which is itself a fork of https://github.com/cbrevik/react-native-typescript-starter.

My changes just include changing various versions of dependencies in package.json

So here are the steps

git clone https://github.com/ankitmittal000/react-native-typescript-starter.git
cd react-native-typescript-starter
git checkout --track origin/feature/ts_map_with_new_version
yarn
yarn bundle:ios:release
yarn bundle:android:release

Once you get the bundle generated using above commands, you run the respective android and iOS projects.

For Android project

You will get the following exception which is right

 com.facebook.react.common.JavascriptException: undefined is not an object (evaluating '(void 0).value'), stack:
                                                                       <unknown>@346:460
                                                                       <unknown>@61:2003
                                                                       y@61:1110
                                                                       callTimers@61:3501
                                                                       value@27:4401
                                                                       <unknown>@27:1151
                                                                       value@27:3828
                                                                       value@27:1123

When you try

./symbolicate.js android/main.jsbundle.map 346 460

it will give you

/react_native/react-native-typescript-starter/src/index.tsx:20:10

However this is wrong. The correct result should be

/react_native/react-native-typescript-starter/src/index.tsx:22:10

For iPhone

When you run the app on iPhone you will get the following

typescriptStarter[81082:2398433] *** Terminating app due to uncaught exception 'RCTFatalException: Unhandled JS Exception: undefined is not an object (evaluating '(void 0).value')', reason: 'Unhandled JS Exception: undefined is not an object (evaluating '(void 0).va..., stack:
<unknown>@349:437
y@61:1110
callTimers@61:3501
value@27:4290
<unknown>@27:1040
value@27:3717
value@27:1012

When you try

./symbolicate.js ios/main.jsbundle.map 349 437

you get the following

/react_native/react-native-typescript-starter/src/index.tsx:18:0

However this is wrong. The correct result should be

/react_native/react-native-typescript-starter/src/index.tsx:22:10

Its worth mentioning here that the results generated with bundle using --dev true are correct. The issue reproduces only with --dev false.

From the other comments, it looks like this issue is resolved. Could somebody point to me where am I going wrong?
Thanks for the help.