How to open main.jsbundle?

SDK 45 on iOS.

I build my Expo app using EAS, then I download the IPA and submit it using Fastlane. This works great.

Now I’m debugging some spurious bug and I would like to symbolize a stack trace which more or less looks like this:

/Users/expo/Library/Developer/Xcode/DerivedData/MyApp-gpsqmqnllkfoiqhaxsihdohdumjy/Build/Intermediates.noindex/ArchiveIntermediates/MyApp/BuildProductsPath/Release-iphoneos/main.jsbundle:47206:40)
 at anonymous (/Users/expo/Library/Developer/Xcode/DerivedData/MyApp-gpsqmqnllkfoiqhaxsihdohdumjy/Build/Intermediates.noindex/ArchiveIntermediates/MyApp/BuildProductsPath/Release-iphoneos/main.jsbundle:225745:51)
 at tryCallTwo (/Users/expo/Library/Developer/Xcode/DerivedData/MyApp-gpsqmqnllkfoiqhaxsihdohdumjy/Build/Intermediates.noindex/ArchiveIntermediates/MyApp/BuildProductsPath/Release-iphoneos/main.jsbundle:10069:9)
 at doResolve (/Users/expo/Library/Developer/Xcode/DerivedData/MyApp-gpsqmqnllkfoiqhaxsihdohdumjy/Build/Intermediates.noindex/ArchiveIntermediates/MyApp/BuildProductsPath/Release-iphoneos/main.jsbundle:10233:25)
 at Promise (/Users/expo/Library/Developer/Xcode/DerivedData/MyApp-gpsqmqnllkfoiqhaxsihdohdumjy/Build/Intermediates.noindex/ArchiveIntermediates/MyApp/BuildProductsPath/Release-iphoneos/main.jsbundle:10092:14)
 at loadAsync$ (/Users/expo/Library/Developer/Xcode/DerivedData/MyApp-gpsqmqnllkfoiqhaxsihdohdumjy/Build/Intermediates.noindex/ArchiveIntermediates/MyApp/BuildProductsPath/Release-iphoneos/main.jsbundle:225723:62)
 at call (native)
 at tryCatch (/Users/expo/Library/Developer/Xcode/DerivedData/MyApp-gpsqmqnllkfoiqhaxsihdohdumjy/Build/Intermediates.noindex/ArchiveIntermediates/MyApp/BuildProductsPath/Release-iphoneos/main.jsbundle:10408:23)
 at anonymous (/Users/expo/Library/Developer/Xcode/DerivedData/MyApp-gpsqmqnllkfoiqhaxsihdohdumjy/Build/Intermediates.noindex/ArchiveIntermediates/MyApp/BuildProductsPath/Release-iphoneos/main.jsbundle:10388:34)
 at anonymous (/Users/expo/Library/Developer/Xcode/DerivedData/MyApp-gpsqmqnllkfoiqhaxsihdohdumjy/Build/Intermediates.noindex/ArchiveIntermediates/MyApp/BuildProductsPath/Release-iphoneos/main.jsbundle:10439:30)
 at call (native)
 at tryCatch (/Users/expo/Library/Developer/Xcode/DerivedData/MyApp-gpsqmqnllkfoiqhaxsihdohdumjy/Build/Intermediates.noindex/ArchiveIntermediates/MyApp/BuildProductsPath/Release-iphoneos/main.jsbundle:10408:23)
 at invoke (/Users/expo/Library/Developer/Xcode/DerivedData/MyApp-gpsqmqnllkfoiqhaxsihdohdumjy/Build/Intermediates.noindex/ArchiveIntermediates/MyApp/BuildProductsPath/Release-iphoneos/main.jsbundle:10446:30)
 at anonymous (/Users/expo/Library/Developer/Xcode/DerivedData/MyApp-gpsqmqnllkfoiqhaxsihdohdumjy/Build/Intermediates.noindex/ArchiveIntermediates/MyApp/BuildProductsPath/Release-iphoneos/main.jsbundle:10452:19)
 ...

So I unzipped the IPA file and opened the main.jsbundle in VSCode. However, VSCode says the file is binary, and no matter whether I open it with the text or hex editor, it looks like total gibberish. I cannot find a single line of code.

Is that file encrypted or obfuscated in some way?

How can I open it to see the code the stacktrace refers to?

Thanks

Hi @yolpsoftware

I’ve not tried it yet myself, but I believe something like Sentry will do what you need. Basically, during the build process you upload the sourcemaps to Sentry, then the stack traces shown in Sentry should point to the original source files instead of the app bundle.

See also: Debugging - Expo Documentation

Hi @wodin

Thanks for your response. I am already using Sentry, but in the case of that bug, Sentry does not show the original stack trace, even though the source maps are uploaded. With other errors, I see the original stack trace, but not with that one. In fact, the stack trace I posted above was from Sentry.

Does anybody have an idea how to open main.jsbundle?

Thanks!

Yes, it’s minified and bundled. Basically all of your JavaScript/TypeScript files are translated to a version of JavaScript understood by JSC or Hermes. Also, all the unnecessary whitespace is removed and variables and functions are renamed to shorter names so that they take up less space. All of the code is also bundled into a single file.

Try opening the file as text and going to line 47206. Then go 40 characters from the start of the line.

Oh of course. The file is compiled for Hermes, and Hermes does not use Javascript, but some kind of optimized bytecode Javascript equivalent.

Yes I tried to open the file as text. Gibberish as well. Some of the line numbers do not even exist.

How can I back-convert a Hermes bytecode file to normal Javascript?

Ah, I see. Then I think you might be out of luck. I don’t know the solution.

Well, to answer that question, I suppose you’d need to disassemble/decompile it. Maybe this question would help with that:

However, I think that’s probably the wrong question for you to ask. Even if you can disassemble/decompile it to something intelligible, I doubt you’d be able to map the line/character numbers in the stack trace to something in the decompiled code.

I think you might have more luck asking Sentry about the problem. Or else asking on Stack Overflow. If you do this, mention that you’ve set up Sentry and how you’ve done that and that normally you get stack traces referring to the source code, but that this time the stack trace is referring to the main.jsbundle. Also mention that you’re using Hermes.

Thanks. Luckily the problem seems to be upstream, not in our code, so it’s not me who needs to look at that stacktrace :smiling_face:

Thanks for your help!

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.