-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
[dart2wasm] Empty 'names' field in generated source maps #56718
Comments
Summary: The generated source map for Dart/Flutter web projects compiled to WASM has an empty "names" field, preventing symbol name mapping and hindering debugging. This issue occurs despite a recent commit that should have ensured function names are included in the source map. |
/cc @osa1 |
We used to generate names but wasm-opt doesn't support them and Chrome devtools doesn't use them, so I removed them in 1b1740e. I had also asked around internally before removing them to see if there are any tools that use those names but couldn't find one. @buenaflor which tool are you using that makes use of the names in source maps? |
Ah okay got it.
I was investigating the effort to use sourcemaps for flutter web wasm stacktraces for us at sentry.io. that's the main use case |
|
Could you share the instructions to generate the source map file that causes this error? We don't generate names in the mappings (as described above) so I'm not sure how you can see a reference to a name. |
Sry my bad, I tried it again and used the wrong sourcemap before. Works as intended. Dunno if it's feasible for you to re-enable generating names generally or through an additional flag? |
@buenaflor How do you plan to use the names and what how do you want the generated code to be named? (e.g. name code with the name of the function it belongs, or something else?) |
In our Javascript SDKs and Flutter Web we use it to unminify the stacktrace for crash and error reporting. Example from our Flutter Web dart2js stacktrace (don't mind the stacktrace formatting):
|
If you build your Flutter app with Example: f() {
g();
}
g() {
throw 'hi';
}
void main() {
f();
} Output:
You can see the names Flutter drops the relevant part of the .wasm files so you have to pass Does this work for you? |
It definitely works as a temporary solution (generally this issue is not a very high priority for us currently so it's fine right now), but it does impact the wasm file size quite a bit for users so imo long term it'd be more ideal to strip the symbols and leverage the sourcemaps |
Do you care about only the If you care about the whole package we could add a flag for just putting function names in the names section and avoiding the other names (names for globals, types, ...). That way the total package size would be very similar the package with no names in .wasm but names in the .map. |
We mainly care about things people are deploying to production, we don't necessarily want to force them to not strip symbol names and thus increase their app size. I think your proposed solution for adding a flag sounds good |
Just to confirm, assume that function names will add the same amount of bytes to either the .wasm files or the .wasm.map files. Is there a difference for you between adding them to the .wasm files vs. to .wasm.map files? |
At Sentry for processing it does not make a difference, but for our customers who use our Flutter SDK for error and crash reporting it does matter. When you add this flag we would set up the guide like so: So for the end user's sake it's preferrable to add them to wasm.map files. Hope that makes sense |
I still don't understand why you prefer the names to be in the .map files.. Since end users seem to be shipping both of these files (otherwise adding them to the .map files wouldn't make any difference) what is the advantage of adding function names to the .map files instead of .wasm files? |
Sry for the confusion, here would be the full process:
The advantage of having the names in the sourcemap in this case is no size overhead in production: The deployed WASM files are smaller because it is stripped. |
Thanks for the detailed explanation. I agree that for this use case it makes sense to add names to the source maps. Just for the record, I tried to disable all other names and only leave function names, but the binary size overhead is still huge. In devtools: (optimized)
So we really need to drop all names in the release builds. One question is what in the generated code give names to. AFAIK dart2js adds names to In .wasm files we could map the length prefix of each function, or first byte of the function code (i.e. the first byte after the length prefix of a function). @buenaflor Given a stack trace from a browser and a source map, how do you search for the names? Do you start with an offset in the stack trace, and scan backwards in the generated code (.js or .wasm) until you see a mapped code with a name? EDIT: I think it makes sense to just map the whole function code to a name. It adds only one byte to each mapping in the function. |
Sry for the late response, do you still need this info? I'm not too familiar with our symbolizer, I'll have to ask another team for that |
FWIW, this is common practice for JavaScript soruce-maps, and we use this in our deobfuscation techniques both internally and in the sample implementation in our dart2js_tools/lib/deobfuscate_stack_trace.dart tool. The deobfuscation method we provide does precisely the backward lookup that you just described. @osa1 - This reminds me something I wanted to ask. Does dart2wasm or wasm-opt do any method inlining? If so, it may be worth discussing mechanisms to help unwind the inlined frames in the symbolized/deobfuscated stack trace. In dart2js we had to introduce source-map extensions to support it. |
Thanks for the details @sigmundch.
Both dart2wasm and wasm-opt do it and currently we don't have a way of preserving the frames when inlining. I think a problem with this is we would have to implement a dart2wasm-specific source map feature in binaryen as well, which is a generic tool and may not be open to adding language/toolchain specific features. Is there a description of dart2js's source map extension somewhere? |
Yes, our extensions are documented in pkg/compiler/doc/sourcemap_extensions.md. I describe them briefly on this comment #52483 (comment). We also have an internal document with more background and motivation explaining the design at go/robust-dart2js-deobfuscation. It's worth noting that there is appetite for evolving the source maps spec to support inilining data and other information as part of the official source-map format. Inline data is tracked in tc39/ecma426#40. However, there is an active proposal in https://github.com/tc39/source-map/blob/main/proposals/scopes.md under consideration that includes that among other features. Depending on how that progresses, I could see this evolving in a direction where dart2wasm and binaryen could support this in a language agnostic way. |
With dart2wasm we also have the option of using DWARF instead of source maps, which supports inlining. As far as I can gather from this comment Chrome may already be supporting debugging with DWARF. Binaryen supports it as well, but with caveats. Since we are discussing debugging optimized builds (otherwise we can keep using source maps and just not inline), and for optimizations we rely on Binaryen, I don't know which one would be more feasible: (1) implementing dart2wasm-specific things in Binaryen (2) improving Binaryen's DWARF handling in optimizations. I suspect (2) makes more sense. It would help other projects that use Binaryen, too. Between tc39/ecma426#40 and DWARF, I don't know which one would be preferable for dart2wasm. |
@buenaflor we now generate function names in the mappings. You can follow the tags in the commit referenced above to see which SDK versions will have the commit. |
@osa1 thanks for the effort 🙇 |
Environment
Description
When building a project for web with wasm, the generated source map file has an empty "names" field. This won't allow mapping symbol names to stack frames, which hinders debugging capabilities.
I have checked this commit: 10742d9
which asserts the function name in the source_map_simple_test.dart so it should work (or at least used to work)
Maybe I'm also missing some setup detail.
Steps to Reproduce
Example 1: Flutter
flutter build --wasm --source-maps
main.dart.wasm.map
fileExample 2: Dart
dart create -t web mywebapp
dart compile wasm web/main.dart
main.wasm.map
fileExpected Behaviour
The "names" field in the
main.dart.wasm.map
file should contain symbol names that can be used to map to stack frames.Actual Behaviour
The "names" field in the
main.dart.wasm.map
file is empty.Example Sourcemap Snippet
The text was updated successfully, but these errors were encountered: