From b406853e8f39680012c5268ec184bae5acec461f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Simon=20Z=C3=BCnd?=
Date: Mon, 26 Aug 2024 11:56:42 +0200
Subject: [PATCH 1/8] [names] Add a section that clarifies how to emit names
for JS
---
source-map.bs | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
diff --git a/source-map.bs b/source-map.bs
index 4aa5427..23e1cfc 100644
--- a/source-map.bs
+++ b/source-map.bs
@@ -43,6 +43,22 @@ urlPrefix:https://tc39.es/ecma262/#; type:dfn; spec:ecmascript
url:prod-MultiLineComment; text:multi-line comment
url:prod-MultiLineComment; text:multi-line comment
url:sec-regexpbuiltinexec; text:RegExpBuiltinExec
+ url:prod-FunctionDeclaration; text:FunctionDeclaration
+ url:prod-FunctionExpression; text:FunctionExpression
+ url:prod-AsyncFunctionDeclaration; text:AsyncFunctionDeclaration
+ url:prod-AsyncFunctionExpression; text:AsyncFunctionExpression
+ url:prod-ArrowParameters; text:ArrowParameters
+ url:prod-AsyncArrowFunction; text:AsyncArrowFunction
+ url:prod-GeneratorDeclaration; text:GeneratorDeclaration
+ url:prod-GeneratorExpression; text:GeneratorExpression
+ url:prod-MethodDefinition; text:MethodDefinition
+ url:prod-AsyncGeneratorDeclaration; text:AsyncGeneratorDeclaration
+ url:prod-AsyncGeneratorExpression; text:AsyncGeneratorExpression
+ url:prod-Identifier; text:Identifier
+ url:prod-LexicalDeclaration; text:LexicalDeclaration
+ url:prod-VariableStatement; text:VariableStatement
+ url:sec-parameter-lists; text:Parameter List
+ url:sec-environment-records; text:Environment Record
urlPrefix:https://webassembly.github.io/spec/core/; type:dfn; spec:wasm
url:binary/modules.html#binary-customsec; text:custom section
@@ -274,6 +290,44 @@ fields represent mapped code that also has a mapped name.
Note: Using file offsets was considered but rejected in favor of using line/column data to avoid becoming
misaligned with the original due to platform-specific line endings.
+### [=names=] for generated JavaScript code
+
+Source map generators should create a [=mapping=] entry with a [=name=] field for
+the following JavaScript tokens, if
+
+1. The original source language construct maps semantically to the generated
+ JavaScript code.
+
+1. The original source language construct has a name.
+
+Then the [=name=] of the [=mapping=] entry should be the name of the original
+source language construct.
+
+Example: A TypeScript arrow function compiled to a JavaScript function, or a
+local variable that was renamed.
+
+1. The opening parenthesis `(` of [=FunctionDeclaration=], [=FunctionExpression=],
+ [=AsyncFunctionDeclaration=] and [=AsyncFunctionExpression=] for (async) functions.
+
+1. The opening parenthesis `(` or the first letter of the *BindingExpression*
+ of [=ArrowParameters=] and [=AsyncArrowFunction=] for (async) arrow functions.
+
+1. The opening parenthesis `(` of [=MethodDefinition=] for class methods. For the
+ [=MethodDefinition=] where *PropName* is "constructor", the [=name=] should be
+ the original class name.
+
+1. The opening parenthesis `(` of [=GeneratorDeclaration=], [=GeneratorExpression=],
+ [=AsyncGeneratorDeclaration=] and [=AsyncGeneratorExpression=] for (async) generator functions.
+
+1. The first letter of [=Identifier=] for variables. This includes (but is not limited to)
+ [=LexicalDeclaration=], [=VariableStatement=] and arguments in [=Parameter List=].
+ Source map generators may choose to only emit a [=mapping=] entry with a [=name=] at a
+ variable's definition site and may choose to omit such a mapping for further use-sites
+ in the same [=Environment Record=].
+
+Note: The opening parenthesis is chosen because it is present in all styles of function
+definition except arrow functions with a single parameter.
+
Resolving Sources {#resolving-sources}
--------------------------------------
From 9069f532b744b46d228888ba8078c1ca56585529 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Simon=20Z=C3=BCnd?=
Date: Fri, 27 Sep 2024 11:24:48 +0200
Subject: [PATCH 2/8] Names: Incorporate results from TG4 meeting
In particular:
* For functions/methods/generators emit the named mapping on the
binding identifier by default (or opening parenthesis).
* Special case single argument arrow functions that have neither
a binding identifier or an opening parenthesis.
* Introduce a definition for "named mapping". I.e. a decoded
mapping entry where the name field is not null.
* Call out that generators may emit additional "named mappings"
as they require. Either to support existing tools or to fit
their requirements.
---
source-map.bs | 82 +++++++++++++++++++++++++++++++++------------------
1 file changed, 54 insertions(+), 28 deletions(-)
diff --git a/source-map.bs b/source-map.bs
index 61b59af..eb59d46 100644
--- a/source-map.bs
+++ b/source-map.bs
@@ -66,22 +66,27 @@ urlPrefix:https://tc39.es/ecma262/#; type:dfn; spec:ecmascript
url:prod-TemplateSubstitutionTail; text:TemplateSubstitutionTail
url:prod-WhiteSpace; text:WhiteSpace
url:sec-ecmascript-language-lexical-grammar; text:ECMAScript Lexical Grammar
+ url:prod-Arguments; text:Arguments
+ url:prod-BindingIdentifier; text:BindingIdentifier
+ url:prod-ClassElementName; text:ClassElementName
+ url:prod-FormalParameters; text:FormalParameters
url:prod-FunctionDeclaration; text:FunctionDeclaration
url:prod-FunctionExpression; text:FunctionExpression
+ url:prod-Expression; text:Expression
url:prod-AsyncFunctionDeclaration; text:AsyncFunctionDeclaration
url:prod-AsyncFunctionExpression; text:AsyncFunctionExpression
- url:prod-ArrowParameters; text:ArrowParameters
+ url:prod-ArrowFunction; text:ArrowFunction
url:prod-AsyncArrowFunction; text:AsyncArrowFunction
url:prod-GeneratorDeclaration; text:GeneratorDeclaration
url:prod-GeneratorExpression; text:GeneratorExpression
url:prod-MethodDefinition; text:MethodDefinition
url:prod-AsyncGeneratorDeclaration; text:AsyncGeneratorDeclaration
url:prod-AsyncGeneratorExpression; text:AsyncGeneratorExpression
- url:prod-Identifier; text:Identifier
+ url:prod-IdentifierReference; text:IdentifierReference
url:prod-LexicalDeclaration; text:LexicalDeclaration
url:prod-VariableStatement; text:VariableStatement
url:sec-parameter-lists; text:Parameter List
- url:sec-environment-records; text:Environment Record
+ url:sec-syntactic-grammar; text:Syntactic Grammar
urlPrefix:https://webassembly.github.io/spec/core/; type:dfn; spec:wasm
url:binary/modules.html#binary-customsec; text:custom section
@@ -593,10 +598,10 @@ To decode a base64 VLQ from a [=string=] |segment| given a [=position
NOTE: In addition to returning the decoded value, this algorithm updates the [=position variable=]
in the calling algorithm.
-### [=Mappings=] for generated JavaScript code
+### [=decoded mapping|Mappings=] for generated JavaScript code ### {#mappings-javascript}
-Generated code positions that may have [=Mapping=] entries are defined in terms of *input elements*
-as per [=ECMAScript Lexical Grammar=]. [=Mapping=] entries must point to either:
+Generated code positions that may have [=decoded mapping|mapping=] entries are defined in terms of *input elements*
+as per [=ECMAScript Lexical Grammar=]. [=decoded mapping|Mapping=] entries must point to either:
1. the first code point of the source text matched by
[=IdentifierName=], [=PrivateIdentifier=], [=Punctuator=], [=DivPunctuator=], [=RightBracePunctuator=],
@@ -606,43 +611,64 @@ as per [=ECMAScript Lexical Grammar=]. [=Mapping=] entries must point to either:
[=Comment=], [=HashbangComment=], [=StringLiteral=], [=Template=],
[=TemplateSubstitutionTail=], [=WhiteSpace=] and [=LineTerminator=].
-### [=names=] for generated JavaScript code
+### [=decoded mapping/Names=] for generated JavaScript code
-Source map generators should create a [=mapping=] entry with a [=name=] field for
-the following JavaScript tokens, if
+Source map generators should create a [=decoded mapping|mapping=] entry with a
+[=decoded mapping/name=] field for a JavaScript token, if
1. The original source language construct maps semantically to the generated
JavaScript code.
1. The original source language construct has a name.
-Then the [=name=] of the [=mapping=] entry should be the name of the original
-source language construct.
+Then the [=decoded mapping/name=] of the [=decoded mapping|mapping=] entry should be
+the name of the original source language construct. A [=decoded mapping|mapping=] with
+a non-null [=decoded mapping/name=] is called a named mapping.
-Example: A TypeScript arrow function compiled to a JavaScript function, or a
+Example: A TypeScript function compiled to a JavaScript arrow function, or a
local variable that was renamed.
-1. The opening parenthesis `(` of [=FunctionDeclaration=], [=FunctionExpression=],
- [=AsyncFunctionDeclaration=] and [=AsyncFunctionExpression=] for (async) functions.
+The following enumeration lists productions of the ECMAScript [=Syntactic Grammar=]
+and the respective token or non-terminal (on the right-hand side of the production)
+for which source map generators should emit a [=named mapping=].
+The [=decoded mapping|mapping=] entry created for such tokens must follow [[#mappings-javascript]].
-1. The opening parenthesis `(` or the first letter of the *BindingExpression*
- of [=ArrowParameters=] and [=AsyncArrowFunction=] for (async) arrow functions.
+The enumeration should be understood as the "minimum". In general,
+source map generators are free to emit any additional [=named mappings=].
-1. The opening parenthesis `(` of [=MethodDefinition=] for class methods. For the
- [=MethodDefinition=] where *PropName* is "constructor", the [=name=] should be
- the original class name.
+Note: The enumeration also lists tokens where generators "may" emit named [=decoded mapping|mappings=] in addition
+to the tokens where they "should". These reflect the reality where existing tooling emits or
+expects [=named mappings=]. The duplicated [=named mapping=] is comparably cheap: Indices into
+[=json/names=] are encoded relative to each other so subsequent mappings to the same name are
+encoded as 0 (`A`).
-1. The opening parenthesis `(` of [=GeneratorDeclaration=], [=GeneratorExpression=],
- [=AsyncGeneratorDeclaration=] and [=AsyncGeneratorExpression=] for (async) generator functions.
+1. The [=BindingIdentifier=](s) for [=LexicalDeclaration=], [=VariableStatement=]
+ and [=Parameter List=].
-1. The first letter of [=Identifier=] for variables. This includes (but is not limited to)
- [=LexicalDeclaration=], [=VariableStatement=] and arguments in [=Parameter List=].
- Source map generators may choose to only emit a [=mapping=] entry with a [=name=] at a
- variable's definition site and may choose to omit such a mapping for further use-sites
- in the same [=Environment Record=].
+1. The [=BindingIdentifier=] for [=FunctionDeclaration=], [=FunctionExpression=],
+ [=AsyncFunctionDeclaration=], [=AsyncFunctionExpression=], [=GeneratorDeclaration=],
+ [=GeneratorExpression=], [=AsyncGeneratorDeclaration=], and [=AsyncGeneratorExpression=] if it
+ exists, or the opening parenthesis `(` preceding the [=FormalParameters=] otherwise.
-Note: The opening parenthesis is chosen because it is present in all styles of function
-definition except arrow functions with a single parameter.
+ Source map generators may chose to emit a [=named mapping=] on the opening parenthesis regardless of
+ the presence of the [=BindingIdentifier=].
+
+1. The [=BindingIdentifier=] for [=ArrowFunction=], and [=AsyncArrowFunction=] if it
+ exists, or the opening parenthesis `(` of the [=Arguments=] production otherwise.
+ For single argument (async) arrow functions that have neither a [=BindingIdentifier=]
+ nor [=Arguments=], generators should emit a named [=decoded mapping|mappings=] for the `=>` token.
+
+ Source map generators may chose to emit a named [=decoded mapping|mapping=] on the opening parenthesis regardless of
+ the presence of the [=BindingIdentifier=].
+
+1. The [=ClassElementName=] for [=MethodDefinition=]. This includes generators, async
+ methods, async generators and accessors. For [=MethodDefinition=] where
+ [=ClassElementName=] is "constructor", the [=decoded mapping/name=] should be the original
+ class name if applicable.
+
+ Source map generators may chose to additionally emit a named [=decoded mapping|mapping=] on the opening parenthesis `(`.
+
+1. Source map generators may emit named [=decoded mapping|mappings=] for [=IdentifierReference=] in [=Expression=].
Resolving Sources {#resolving-sources}
--------------------------------------
From 944bcd983c6dd64d20b6ca3800bf93cf91d4211c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Simon=20Z=C3=BCnd?=
Date: Wed, 2 Oct 2024 08:03:27 +0200
Subject: [PATCH 3/8] Fix arrow function named mappings
---
source-map.bs | 24 ++++++++++++++++--------
1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/source-map.bs b/source-map.bs
index eb59d46..bbc620e 100644
--- a/source-map.bs
+++ b/source-map.bs
@@ -75,8 +75,11 @@ urlPrefix:https://tc39.es/ecma262/#; type:dfn; spec:ecmascript
url:prod-Expression; text:Expression
url:prod-AsyncFunctionDeclaration; text:AsyncFunctionDeclaration
url:prod-AsyncFunctionExpression; text:AsyncFunctionExpression
+ url:prod-ArrowFormalParameters; text:ArrowFormalParameters
url:prod-ArrowFunction; text:ArrowFunction
+ url:prod-ArrowParameters; text:ArrowParameters
url:prod-AsyncArrowFunction; text:AsyncArrowFunction
+ url:prod-AsyncArrowBindingIdentifier; text:AsyncArrowBindingIdentifier
url:prod-GeneratorDeclaration; text:GeneratorDeclaration
url:prod-GeneratorExpression; text:GeneratorExpression
url:prod-MethodDefinition; text:MethodDefinition
@@ -625,8 +628,8 @@ Then the [=decoded mapping/name=] of the [=decoded mapping|mapping=] entry shoul
the name of the original source language construct. A [=decoded mapping|mapping=] with
a non-null [=decoded mapping/name=] is called a named mapping.
-Example: A TypeScript function compiled to a JavaScript arrow function, or a
-local variable that was renamed.
+Example: A minifier renaming functions and variables or removing function names
+from immediately invoked function expressions.
The following enumeration lists productions of the ECMAScript [=Syntactic Grammar=]
and the respective token or non-terminal (on the right-hand side of the production)
@@ -653,13 +656,18 @@ encoded as 0 (`A`).
Source map generators may chose to emit a [=named mapping=] on the opening parenthesis regardless of
the presence of the [=BindingIdentifier=].
-1. The [=BindingIdentifier=] for [=ArrowFunction=], and [=AsyncArrowFunction=] if it
- exists, or the opening parenthesis `(` of the [=Arguments=] production otherwise.
- For single argument (async) arrow functions that have neither a [=BindingIdentifier=]
- nor [=Arguments=], generators should emit a named [=decoded mapping|mappings=] for the `=>` token.
+1. For an [=ArrowFunction=] or [=AsyncArrowFunction=]:
+ 1. The `=>` token where [=ArrowFunction=] is produced with a single [=BindingIdentifier=] for
+ [=ArrowParameters=]. Or [=AsyncArrowFunction=] is produced with an [=AsyncArrowBindingIdentifier=].
- Source map generators may chose to emit a named [=decoded mapping|mapping=] on the opening parenthesis regardless of
- the presence of the [=BindingIdentifier=].
+ Note: This describes the case of (async) arrow functions with a single parameter, where
+ that single parameter is not wrapped in parenthesis.
+
+ 1. The opening parenthesis `(` where [=ArrowFunction=] or [=AsyncArrowFunction=] is produced
+ with [=ArrowFormalParameters=].
+
+ Source map generators may chose to additionally emit a named [=decoded mapping|mapping=]
+ on the `=>` token for consistency with (1).
1. The [=ClassElementName=] for [=MethodDefinition=]. This includes generators, async
methods, async generators and accessors. For [=MethodDefinition=] where
From e201e9869ff7e7f8454c281ba6b39f58f9c4e79d Mon Sep 17 00:00:00 2001
From: Asumu Takikawa
Date: Wed, 23 Oct 2024 12:43:34 -0700
Subject: [PATCH 4/8] Editorial: make changes requested by ECMA ExeCom
* Adjust the title
* Moved "about this specification" to the introduction section
* Add new scope language
* Re-ordered sections: Scope, Conformance, References, Term and Definitions
* Manually generate the references section
- It doesn't seem possible to generate the references as a normal
numbered section without this manual approach, which is a hack.
---
source-map.bs | 88 ++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 77 insertions(+), 11 deletions(-)
diff --git a/source-map.bs b/source-map.bs
index 7ef7d67..5f753c0 100644
--- a/source-map.bs
+++ b/source-map.bs
@@ -1,5 +1,5 @@
-Title: Source Map
+Title: Source Map Format Specification
H1: Source Map
Shortname: source-map
Level: none
@@ -19,6 +19,7 @@ Abstract: This Ecma standard defines the Source Map format, used for mapping tra
No Abstract: true
Markup Shorthands: markdown yes
Group: tc39
+Boilerplate: references no
@@ -120,15 +121,6 @@ urlPrefix:https://webassembly.github.io/spec/core/; type:dfn; spec:wasm
}
-About this Specification
-
-The document at [https://tc39.es/source-map/](https://tc39.es/source-map/) is the most accurate and
-up-to-date source map specification. It contains the content of the most recently published snapshot
-plus any modifications that will be included in the next snapshot.
-
-If you want to get involved you will find more information at the [specification
-repository](https://github.com/tc39/source-map).
-
Introduction
This Ecma Standard defines the Source Map Format, used for mapping transpiled source code back to the original sources.
@@ -137,6 +129,13 @@ The source map format has the following goals:
* Support source-level debugging allowing bidirectional mapping
* Support server-side stack trace deobfuscation
+The document at [https://tc39.es/source-map/](https://tc39.es/source-map/) is the most accurate and
+up-to-date source map specification. It contains the content of the most recently published snapshot
+plus any modifications that will be included in the next snapshot.
+
+If you want to get involved you will find more information at the [specification
+repository](https://github.com/tc39/source-map).
+
The original source map format (v1) was created by Joseph Schorr for use by
Closure Inspector to enable source-level debugging of optimized JavaScript code
(although the format itself is language agnostic). However, as the size of the
@@ -197,7 +196,74 @@ IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Scope {#scope}
==============
-This Standard defines the Source Map Format.
+This Standard defines the source map format, used by different types of
+developer tools to improve the debugging experience of code compiled to
+JavaScript, WebAssembly, and CSS.
+
+Conformance {#conformance}
+==========================
+
+A conforming source map document is a JSON document that conforms to the
+structure detailed in this specification.
+
+A conforming source map generator should generate documents which are
+conforming source map documents, and can be decoded by the algorithms in this
+specification without reporting any errors (even those which are specified as
+optional).
+
+A conforming source map consumer should implement the algorithms specified in this
+specification for retrieving (where applicable) and decoding source map documents.
+A conforming consumer is permitted to accept non-conforming source map documents,
+and is permitted to ignore errors or report them without terminating where the
+specification indicates that an algorithm may [=optionally report an error=].
+
+References {#references}
+========================
+
+
+
+Normative References
+
Terms and definitions {#terminology}
====================================
From efc38d1b96282480419a89e1f43c850a1b54307c Mon Sep 17 00:00:00 2001
From: Asumu Takikawa
Date: Sun, 27 Oct 2024 16:00:34 -0700
Subject: [PATCH 5/8] Address feedback (don't mentioning non-conforming maps)
---
source-map.bs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/source-map.bs b/source-map.bs
index 5f753c0..7c831c9 100644
--- a/source-map.bs
+++ b/source-map.bs
@@ -213,9 +213,9 @@ optional).
A conforming source map consumer should implement the algorithms specified in this
specification for retrieving (where applicable) and decoding source map documents.
-A conforming consumer is permitted to accept non-conforming source map documents,
-and is permitted to ignore errors or report them without terminating where the
-specification indicates that an algorithm may [=optionally report an error=].
+A conforming consumer is permitted to ignore errors or report them without
+terminating where the specification indicates that an algorithm may
+[=optionally report an error=].
References {#references}
========================
From 41e21329b5fdef9504c98a6f860cc09a67e32b5d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Simon=20Z=C3=BCnd?=
Date: Tue, 12 Nov 2024 09:12:28 +0100
Subject: [PATCH 6/8] [scopes] Add isStackFrame/isHidden bits and make
'OriginalScope.kind' optional (#147)
---
proposals/scopes.md | 37 +++++++++++++++++++++++++++++--------
1 file changed, 29 insertions(+), 8 deletions(-)
diff --git a/proposals/scopes.md b/proposals/scopes.md
index fd6a333..0ea5a78 100644
--- a/proposals/scopes.md
+++ b/proposals/scopes.md
@@ -132,9 +132,15 @@ interface SourceMap {
interface OriginalScope {
start: OriginalPosition;
end: OriginalPosition;
- kind: string;
+ /** Serves as a label in source-map consumers */
+ kind?: string;
/** Class/module/function name. Can be used for stack traces or naming scopes in a debugger's scope view */
name?: string;
+ /**
+ * Whether this scope corresponds to the semantic equivalent of a function call in
+ * the authored language, and as such can show up in stack traces.
+ */
+ isStackFrame: boolean;
/** Symbols defined in this scope */
variables?: string[];
children?: OriginalScope[];
@@ -143,7 +149,18 @@ interface OriginalScope {
interface GeneratedRange {
start: GeneratedPosition;
end: GeneratedPosition;
- isScope: boolean;
+ /**
+ * Whether this range is a JavaScript function/method/generator/constructor and can show
+ * up in Error.stack as a stack frame.
+ */
+ isStackFrame: boolean;
+ /**
+ * Whether calls to this range should be removed from stack traces.
+ * Intended for outlined functions or transpiler inserted function that correspond
+ * to an original scope, but should be hidden from stack traces (e.g. an original block
+ * scope outlined into a function).
+ */
+ isHidden: boolean;
originalScope?: OriginalScope;
/** If this scope corresponds to an inlined function body, record the callsite of the inlined function in the original code */
callsite?: OriginalPosition;
@@ -199,17 +216,20 @@ Note: Each DATA represents one VLQ number.
* Note: this is the point in the original code where the scope starts. `line` is relative to the `line` of the preceding "start/end original scope" item.
* DATA column in the original code
* Note: Column is always absolute.
-* DATA kind offset into `names` field
- * Note: This offset is relative to the offset of the last `kind` or absolute if this is the first `kind`.
- * Note: This is type of the scope.
- * Note: JavaScript implementations should use `'global'`, `'class'`, `'function'`, and `'block'`.
-* DATA field flags
+* DATA flags
* Note: binary flags that specify if a field is used for this scope.
* Note: Unknown flags would skip the whole scope.
* 0x1 has name
+ * 0x2 has kind
+ * 0x4 is stack frame
* name: (only exists if `has name` flag is set)
* DATA offset into `names` field
* Note: This name should be shown as function name in the stack trace for function scopes.
+* kind: (only exists if `has kind` flag is set)
+ * DATA offset into `names` field
+ * Note: This offset is relative to the offset of the last `kind` or absolute if this is the first `kind`.
+ * Note: This is type of the scope.
+ * Note: JavaScript implementations should use `'global'`, `'class'`, `'function'`, and `'block'`.
* variables:
* for each variable:
* DATA offset into `names` field for the original symbol name defined in this scope
@@ -231,7 +251,8 @@ Note: Each DATA represents one VLQ number.
* Note: Unknown flags would skip the whole scope.
* 0x1 has definition
* 0x2 has callsite
- * 0x4 is scope
+ * 0x4 is stack frame
+ * 0x8 is hidden
* definition: (only existing if `has definition` flag is set)
* DATA offset into `sources`
* Note: This offset is relative to the offset of the last definition or absolute if this is the first definition
From 726cc560a54b5d09e62c0662a45fb9f73ad40cba Mon Sep 17 00:00:00 2001
From: Luca Forstner
Date: Wed, 13 Nov 2024 18:14:52 +0100
Subject: [PATCH 7/8] Debug IDs: Format proposal text (#141)
---
proposals/debug-id.md | 166 ++++++++++++++----------------------------
1 file changed, 54 insertions(+), 112 deletions(-)
diff --git a/proposals/debug-id.md b/proposals/debug-id.md
index d266463..9c7947e 100644
--- a/proposals/debug-id.md
+++ b/proposals/debug-id.md
@@ -1,7 +1,6 @@
# Source Map Debug ID Proposal
-This document presents a proposal to add globally unique build or debug IDs to
-source maps and generated code, making build artifacts self-identifying.
+This document presents a proposal to add globally unique build or debug IDs to source maps and generated code, making build artifacts self-identifying.
## Current Status
@@ -13,96 +12,66 @@ Luca Forstner
## Background
-Source maps play a crucial role in debugging by
-providing a mapping between generated code and the original source code.
-However, the current source map specification lacks important properties such as
-self-describing and self-identifying capabilities for both the generated code
-as well as the source map. This results in a subpar user experience and numerous
-practical problems. To address these issues, we propose an extension to the
-source map format: the addition of globally unique Debug IDs.
+Source maps play a crucial role in debugging by providing a mapping between generated code and the original source code.
+However, the current source map specification lacks important properties such as self-describing and self-identifying capabilities for both the generated code as well as the source map.
+This results in a subpar user experience and numerous practical problems.
+To address these issues, we propose an extension to the source map format: the addition of globally unique Debug IDs.
## Objective and Benefits
-The primary objective of this proposal is to enhance the source map format by
-introducing globally unique Debug IDs, enabling better identification and
-organization of generated code and their corresponding source maps.
-This improvement will streamline the debugging process and reduce the likelihood
-of errors arising from misidentification or misassociation of files.
+The primary objective of this proposal is to enhance the source map format by introducing globally unique Debug IDs, enabling better identification and organization of generated code and their corresponding source maps.
+This improvement will streamline the debugging process and reduce the likelihood of errors arising from misidentification or misassociation of files.
-Debug IDs (also sometimes called Build IDs) are already used in the native language
-ecosystem and supported by native container formats such as PE, ELF, MachO or
-WASM.
+Debug IDs (also sometimes called Build IDs) are already used in the native language ecosystem and supported by native container formats such as PE, ELF, MachO or WASM.
The proposed solution offers the following benefits:
-1. Improved File Identification: The introduction of globally unique Debug IDs
- will make it easier to identify and associate generated code with its
- corresponding source map.
+1. Improved File Identification: The introduction of globally unique Debug IDs will make it easier to identify and associate generated code with its corresponding source map.
-2. Self-Identifying Files: This specification changes both, source maps and
- generated code so that they become self-identifying, eliminating the
- need for external information to reference them.
+2. Self-Identifying Files: This specification changes both, source maps and generated code so that they become self-identifying, eliminating the need for external information to reference them.
-3. Streamlined Debugging Process: The implementation of Debug IDs will simplify
- and streamline the debugging process by reducing the likelihood of errors
- resulting from misidentification or misassociation of files.
+3. Streamlined Debugging Process: The implementation of Debug IDs will simplify and streamline the debugging process by reducing the likelihood of errors resulting from misidentification or misassociation of files.
-4. Standardization: The adoption of this proposal as a web standard will
- encourage a consistent and unified approach to handling source maps and
- generated code across the industry.
+4. Standardization: The adoption of this proposal as a web standard will encourage a consistent and unified approach to handling source maps and generated code across the industry.
-5. Guaranteed bidirectionality: Today source maps do not provide the ability to
- reliably resolve back to the generated file they are from. However in
- practice tools often require this as they are often leveraging the
- generated artifact to resolve scope information by parsing the source.
+5. Guaranteed bidirectionality: Today source maps do not provide the ability to reliably resolve back to the generated file they are from. However in practice tools often require this as they are often leveraging the generated artifact to resolve scope information by parsing the source.
-6. Symbol server support: with Debug IDs and source maps with embedded sources
- it becomes possible to support symbol server lookup from symbol servers.
+6. Symbol server support: with Debug IDs and source maps with embedded sources it becomes possible to support symbol server lookup from symbol servers.
## Scope
-This proposal sets some specific limitations on source maps to simplify the
-processing in the wider ecosystem. Debug IDs are at present only specified to
-source maps with embedded sources or where sources are categorically not
-available. The lookup for original sources from a source map identified by a
-debug ID is not defined.
+This proposal sets some specific limitations on source maps to simplify the processing in the wider ecosystem.
+Debug IDs are at present only specified to source maps with embedded sources or where sources are categorically not available.
+The lookup for original sources from a source map identified by a debug ID is not defined.
-Additionally, this specification applies only to non-indexed source maps and
-currently specifies references only for JavaScript.
+Additionally, this specification applies only to non-indexed source maps and currently specifies references only for JavaScript.
## Terms
In the context of this document:
- **Source Map:** Refers to a non-indexed, standard source map.
-- **Generated Code:** Refers to a code generated by a compiler, for example a
- JavaScript minifier.
+- **Generated Code:** Refers to a code generated by a compiler, for example a JavaScript minifier.
- **Debug ID:** Refers to a UUID as described in this document.
## Debug IDs
-Debug IDs are globally unique identifiers for build artifacts. They are
-specified to be UUIDs. In the context of this proposal, they are represented in
-hexadecimal characters. When comparing debug IDs they must be normalized. This
-means that `85314830-023f-4cf1-a267-535f4e37bb17` and
-`85314830023F4CF1A267535F4E37BB17` are equivalent but the former representation
-is the canonical format.
+Debug IDs are globally unique identifiers for build artifacts. They are specified to be UUIDs.
+In the context of this proposal, they are represented in hexadecimal characters.
+When comparing debug IDs they must be normalized.
+This means that `85314830-023f-4cf1-a267-535f4e37bb17` and `85314830023F4CF1A267535F4E37BB17` are equivalent but the former representation is the canonical format.
-The way a debug ID is generated is specific to the toolchain and no requirements
-are placed on it. It is however recommended to generate deterministic debug IDs
-(UUID v3 or v5) so that rebuilding the same artifacts yields stable IDs.
+The way a debug ID is generated is specific to the toolchain and no requirements are placed on it.
+It is however recommended to generate deterministic debug IDs (UUID v3 or v5) so that rebuilding the same artifacts yields stable IDs.
-Debug IDs are embedded in both source maps and transformed files, allowing a
-bidirectional mapping between them. The linking of source maps and transformed
-files via HTTP headers is explicitly not desired. A file identified by a Debug
-ID must have that Debug ID embedded to ensure the file is self-identifying.
+Debug IDs are embedded in both source maps and transformed files, allowing a bidirectional mapping between them.
+The linking of source maps and transformed files via HTTP headers is explicitly not desired.
+A file identified by a Debug ID must have that Debug ID embedded to ensure the file is self-identifying.
### Debug IDs in Source Maps
-We propose adding a `debugId` property to the source map at the top level of
-the source map object. This property should be a string value representing
-the Debug ID in hexadecimal characters, preferably in the canonical UUID
-format:
+We propose adding a `debugId` property to the source map at the top level of the source map object.
+This property should be a string value representing the Debug ID in hexadecimal characters, preferably in the canonical UUID format:
```json
{
@@ -117,67 +86,45 @@ format:
### Debug IDs in JavaScript Artifacts
-Generated JavaScript files containing a Debug ID must embed the ID near the end
-of the source, ideally on the last line, in the format `//# debugId=`:
+Generated JavaScript files containing a Debug ID must embed the ID near the end of the source, ideally on the last line, in the format `//# debugId=`:
```javascript
//# debugId=85314830-023f-4cf1-a267-535f4e37bb17
```
-If the special `//# sourceMappingURL=` comment already exists in the file, it is
-recommended to place the `debugId` comment in the line above to maintain
-compatibility with existing tools. Because the last line already has meaning in
-the existing specification for the `sourceMappingURL` comment, tools are
-required to examine the last 5 lines to discover the Debug ID.
+If the special `//# sourceMappingURL=` comment already exists in the file, it is recommended to place the `debugId` comment in the line above to maintain compatibility with existing tools.
+Because the last line already has meaning in the existing specification for the `sourceMappingURL` comment, tools are required to examine the last 5 lines to discover the Debug ID.
-**Note on the end of file:** for all intents and purposes having the Debug ID at
-the top of the file would be preferrable. However this has the disadvantage that
-a tool could not add a Debug ID to a file without having to adjust all the tokens
-in the source map by the offset that this line adds. Having it at the end of the
-file means it's after all tokens which would allow a separate tool to add Debug IDs
-to generated files and source maps.
+**Note on the end of file:** for all intents and purposes having the Debug ID at the top of the file would be preferable.
+However this has the disadvantage that a tool could not add a Debug ID to a file without having to adjust all the tokens in the source map by the offset that this line adds.
+Having it at the end of the file means it's after all tokens which would allow a separate tool to add Debug IDs to generated files and source maps.
## JavaScript API for Debug ID Resolution
-Today `error.stack` in most runtimes only returns the URLs of the files referenced
-by the stack trace. For Debug IDs to be useful, a solution would need to be added
-to enable mapping of JavaScript file URLs to Debug IDs.
+Today `error.stack` in most engines only returns the URLs of the files referenced by the stack trace.
+For Debug IDs to be useful, a solution would need to be added to enable mapping of JavaScript file URLs to Debug IDs.
The strawman proposal is to add the Debug ID in two locations:
-- `import.meta.debugId`: a new property that should return the debug ID as a string
- of the current module if it has one, in the canonical UUID format
-- A Function property in the global scope `getDebugIdForUrl(url)` that looks up
- the debug ID for a given script file by URL that has already been loaded by
- the browser in the current context.
+- `import.meta.debugId`: a new property that should return the debug ID as a string of the current module if it has one, in the canonical UUID format.
+- A Function property in the global scope `getDebugIdForUrl(url)` that looks up the debug ID for a given script file by URL that has already been loaded by the browser in the current context.
## Appendix A: Self-Description of Source Maps and JavaScript Files
-Unfortunately, neither generated JavaScript files nor source maps can be easily
-identified without employing heuristics. Unlike formats like ELF binaries, they
-lack a distinctive header for identification purposes. When batch processing
-files, the ability to differentiate between various files is invaluable, but
-this capability is not fully realized in the context of source maps or
-generated JavaScript files. Although solving this issue is beyond the scope of
-this document, addressing it would significantly aid in distinguishing different
-files without relying on intricate heuristics.
-
-Nevertheless, we recommend that tools utilize the following heuristics to
-determine self-identifying JavaScript files and source maps:
-
-- a JSON file containing a toplevel object with the keys `mapping`, `version`,
- `debugId` and `sourcesContent` should be considered to be a self-identifying
- source map.
-- a UTF-8 encoded text file matching the regular expression
- `(?m)^//# debugId=([a-fA-F0-9-]{12,})$` should be considered a generated
- JavaScript file.
+Unfortunately, neither generated JavaScript files nor source maps can be easily identified without employing heuristics.
+Unlike formats like ELF binaries, they lack a distinctive header for identification purposes.
+When batch processing files, the ability to differentiate between various files is invaluable, but this capability is not fully realized in the context of source maps or generated JavaScript files.
+Although solving this issue is beyond the scope of this document, addressing it would significantly aid in distinguishing different files without relying on intricate heuristics.
+
+Nevertheless, we recommend that tools utilize the following heuristics to determine self-identifying JavaScript files and source maps:
+
+- A JSON file containing a top-level object with the keys `mapping`, `version`, `debugId` and `sourcesContent` should be considered to be a self-identifying source map.
+- A UTF-8 encoded text file matching the regular expression `(?m)^//# debugId=([a-fA-F0-9-]{12,})$` should be considered a generated JavaScript file.
## Appendix B: Symbol Server Support
-With debug IDs it becomes possible to resolve source maps and generated code
-from the server. That way a tool such as a browser or a crash reporter could
-be pointed to a S3, GCS bucket or an HTTP server that can serve up source maps and
-build artifacts keyed by debug id.
+With debug IDs it becomes possible to resolve source maps and generated code from the server.
+That way a tool such as a browser or a crash reporter could be pointed to a S3, GCS bucket or an HTTP server that can serve up source maps and build artifacts keyed by debug id.
The structure itself is inspired by [debuginfod](https://sourceware.org/elfutils/Debuginfod.html):
@@ -189,15 +136,11 @@ with the following variables:
- `DebugIdFirstTwo`: the first two characters in lowercase of the hexadecimal Debug ID
- `DebugIdRest`: the remaining characters in lowercase of the hexadecimal Debug ID without dashes
-Note that debuginfod usually does not use extensions on the path lookup syntax so the
-more natural filenames woudl just be `source` and `sourcemap`.
+Note that debuginfod usually does not use extensions on the path lookup syntax so the more natural filenames would just be `source` and `sourcemap`.
## Appendix C: Emulating Debug IDs in JavaScript
-In the absence of browser support for loading debug IDs of particular stack
-frames, code transformers can inject a snippet into _all_ individual generated
-JavaScript files to maintain a global dictionary that maps from resource URL to
-Debug ID:
+In the absence of browser support for loading debug IDs of particular stack frames, code transformers can inject a snippet into _all_ individual generated JavaScript files to maintain a global dictionary that maps from resource URL to Debug ID:
```javascript
(function () {
@@ -218,8 +161,7 @@ function getDebugIdForUrl(url) {
## Appendix D: Parsing Debug IDs
-The following Python code shows how Debug IDs are to be extracted from
-generated JavaScript and source map files:
+The following Python code shows how Debug IDs are to be extracted from generated JavaScript and source map files:
```python
import re
From 51c6bdb37aa75c66ad5e9b70a77702f3300bda27 Mon Sep 17 00:00:00 2001
From: Asumu Takikawa
Date: Wed, 13 Nov 2024 18:03:03 +0000
Subject: [PATCH 8/8] Use "greater than or equal to" for nameIndex (#150)
Addresses https://github.com/tc39/source-map-tests/issues/25
---
source-map.bs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/source-map.bs b/source-map.bs
index a9be927..45f74f5 100644
--- a/source-map.bs
+++ b/source-map.bs
@@ -616,7 +616,7 @@ sources=] |sources|, run the followi
be the result.
1. If |relativeNameIndex| is not null, then:
1. Increase |nameIndex| by |relativeNameIndex|.
- 1. If |nameIndex| is negative or greater than |names|'s [=list/size=], [=optionally
+ 1. If |nameIndex| is negative or greater than or equal to |names|'s [=list/size=], [=optionally
report an error=].
1. Else, set |decodedMapping|'s [=decoded mapping/name=] to |names|[|nameIndex|].
1. If |position| does not point to the end of |segment|, [=optionally report an