Description
Hello! At a recent TC-39 JS Tools meeting we decided to bring the proposal for v4 here as a neutral discussion point.
The proposal document is here: MicrosoftEdge/MSEdgeExplainers#538
(I'd be happy to stage a Pull Request against this or another repo where appropriate. We discussed whether to update the Google Doc which is the "official" standard, but given it's been 8-9 years since that document was last updated, I'm not sure what the best way is to formalize and/or collaborate on that document, vs. treating it as an "artifact").
TL;DR
The proposal is to add (one or two) new field(s) to the existing Source Maps document. This would map text ranges of the source files to a "scope", which would describe the lexical subroutine from the source language. For example:
1 class Example {
2 constructor() {
3 document.addEventListener('ready', () => {
4 });
5 }
6 }
This would produce the following list of scopes:
- 2:2 ... 5:2 named
constructor for class Example
- 3:46 ... 4:4 names
anonymous callback for document.addEventListener
(Please note: the names of these scopes is up for discussion).
This would enable a series of improvements wherever tooling exposes minified code artifacts related to the call stack:
- Call stack window
- Output call stacks (
Error.stack
) - Performance traces
- Memory snapshots
- Exported HARs
Primary Points of Discussion
While the discussion group believes that solving these problems is valuable, there have been the following major points of discussion:
Storing function names
Option 1: Store in the existing “names”
field
Option 2: Introduce a new “scopeNames”
field
The main benefit of Option 1 is that it reduces sourcemap size and avoids duplication. This is because many tools already populate the “names” field with many of the function names and they can be directly referenced in the “scopes”
field.
The main downside is that if any tool modifies the “names”
field by removing an element or changing the order, they will need to become “scopes”-aware and update it accordingly.
Recommendation: Option 1 is preferred unless there is evidence that the “names”
field is tampered with by tools in practice.
Keying “scopes”
by generated index VS source index
Option 1: Key in “scopes”
is source line and column
Option 2: Key in “scopes”
is generated line and column
The main benefit of Option 1 is that only the first tool in a pipeline, and any tool that combines sources, needs to support the new “scopes”
field. Other tools can ignore it. Note that the use case for decoding a function name will always involve decoding back to the original source location anyway, so this option does not add extra complexity.
Option 2 has a benefit of using the same approach as the existing “mappings”
field so can feel more consistent.
Recommendation: Option 1 is preferred
Nested scopes VS linear scopes
Option 1: Scopes are nested
Option 2: Scopes are linear
Option 1 has the benefit of representing the logical structure of the code, as well as requiring only one VLQ per function. With Option 2, a function with many inner functions will need to be repeatedly referenced every time an inner function ends.
Recommendation: Option 1 is preferred
Format of “scopes”
field
Option 1: Starting points
Option 2: Ranges
Option 1 has the benefit of being consistent with the existing “mappings”
field and tools can reuse implementation. It also has the benefit of resulting in smaller sourcemaps due to only specifying starting locations and a scope name index.
Option 2 results in larger sourcemaps. However, it has the benefit of representing the logical structure of the code better with a 1-1 mapping between a function and its VLQ.
Recommendation: Option 2 is preferred
Relative VS absolute indices
This will very much depend on the format chosen in the decision point above.
Versioning
Option 1: Version 4
Option 2: Version 3.1
Option 3: Retain version 3, but just add new fields
Option 1 has the benefit of indicating a major version update. Option 2 has the benefit of indicating a minor version update but that the update is non-breaking (conforming to semver). Option 3 has the benefit of being very JavaScripty, in that new fields can just be detected and light up, but might break strict compliance testers.
Recommendation: Option 1 or 2 is preferred; Option 3 is likely to break one or more validators.
Naming of functions
This decision point relates to the naming convention of functions. While a free function f()
will of course be named f
, there are more choices available for other types of functions. For example, does a class member function get Class.prototype.f
or Class.f
as its name, or how do you name an anonymous function? These decisions probably don’t belong in the spec, but it would be useful to have a common naming convention across tools.
Other things that might be nice to solve in the future
This section was added by an edit
[ ] Information about functions that were inlined during compilation (surfaced by @ldarbi below)
[ ] Direct information about aliasing of variables (this was mentioned by @rbuckton during the call and @sokra below)