diff --git a/spec.emu b/spec.emu index cffd8bc..63fb3db 100644 --- a/spec.emu +++ b/spec.emu @@ -272,6 +272,19 @@

zero-based indexed offset within a line of the generated code, computed as UTF-16 code units for JavaScript and CSS source maps, and as byte indices in the binary content (represented as a single line) for WebAssembly source maps.

That means that "A" (`LATIN CAPITAL LETTER A`) measures as 1 code unit, and "🔥" (`FIRE`) measures as 2 code units. Source maps for other content types may diverge from this. + + +
original scope
+
+

a lexical scope in an original source file.

+
+ +
generated range
+
+

a code range in generated code.

+ The term range is chosen deliberately: a range does not necessarily correspond to a lexical JavaScript/WASM scope, e.g. when function bodies were inlined by a compiler. +
+
@@ -563,7 +576,8 @@

Source map format

A source map is a JSON document containing a top-level JSON object with the following structure:

-

+  
+    

   {
     "version" : 3,
     "file": "out.js",
@@ -572,9 +586,11 @@
     "sourcesContent": [null, null],
     "names": ["src", "maps", "are", "fun"],
     "mappings": "A,AAAB;;ABCDE",
-    "ignoreList": [0]
+    "ignoreList": [0],
+    "scopes":"BCCAQ,BHAAAC,BCCaC,CDC,CCA,CCY,EDBAA,EGAC,ECvBC,FW,FJ,FI"
   }
   
+
@@ -614,6 +631,10 @@ [[Mappings]] a List of Decoded Mapping Records + + [[Ranges]] + a List of Generated Range Records + @@ -642,6 +663,10 @@ [[Ignored]] a Boolean + + [[Scope]] + a Original Scope Record or *null* + @@ -680,10 +705,12 @@ 1. Let _sourcesField_ be GetOptionalListOfOptionalStrings(_json_, *"sources"*). 1. Let _sourcesContentField_ be GetOptionalListOfOptionalStrings(_json_, *"sourcesContent"*). 1. Let _ignoreListField_ be GetOptionalListOfArrayIndexes(_json_, *"ignoreList"*). - 1. Let _sources_ be DecodeSourceMapSources(_baseURL_, _sourceRootField_, _sourcesField_, _sourcesContentField_, _ignoreListField_). 1. Let _namesField_ be GetOptionalListOfStrings(_json_, *"names"*). - 1. Let _mappings_ be DecodeMappings(_mappingsField_, _namesField_, _sources_). - 1. Return the Decoded Source Map Record { [[File]]: _fileField_, [[Sources]]: _sources_, [[Mappings]]: _mappings_ }. + 1. Let _scopesField_ be GetOptionalString(_json_, *"scopes"*). + 1. Let _scopesAndRanges_ be DecodeScopesInfo(_scopesField_, _namesField_). + 1. Let _sources_ be DecodeSourceMapSources(_baseURL_, _sourceRootField_, _sourcesField_, _sourcesContentField_, _ignoreListField_, _scopesAndRanges_.[[Scopes]]). + 1. Let _mappings_ be DecodeMappings(_mappingsField_, _namesField_, _sources_). + 1. Return the Decoded Source Map Record { [[File]]: _fileField_, [[Sources]]: _sources_, [[Mappings]]: _mappings_, [[Ranges]]: _scopesAndRanges_.[[Ranges]] }. @@ -1114,6 +1141,969 @@ + +

Scopes structure

+ +

The scope information is split across two data structures: original scopes and generated ranges. Original scopes describe the scope tree for original sources. Generated ranges describe where these scopes are found in the generated code. The scope information includes location information, for both original scopes and generated ranges, the type and name of a scope, as well as the original names of variables and how to retrieve their values in the generated code.

+ +

The scopes field is a comma (`,`) separated list of items. Each item is a list of base64 VLQs. The first base64 VLQ in each item is a tag that specifies which item is described by the rest of the VLQs. Both original scopes and generated ranges are trees. Each node in these trees are described by a respective "start" and "end" item. "start" items appear in pre-order and "end" items appear in post-order. Any items other then "start" or "end" describe the "current" scope or range. The "current" scope or range is defined by the last seen "start" item.

+ + +

Original Scope Record

+

A original scope is described by a Original Scope Record:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Field NameValueMeaning
[[Start]]a Position RecordThe line and column (inclusive) where this scope starts.
[[End]]a Position RecordThe line and column (exclusive) where this scope ends.
[[Name]]a String or *null*The original name of this scope. E.g. the original class or function name.
[[Kind]]a String or *null*Debuggers may use [[Kind]] to label this scope in a scope view UI. It is purely informative for users.
[[IsStackFrame]]a BooleanSignifies whether this scope is something that when run would introduce a new frame in the call stack, such as a function or method.
[[Variables]]a List of StringsThe original variable names declared in this scope.
[[Children]]a List of Original Scope RecordsThe child scopes of this scope.
+
+

A root Original Scope Record describes the lexical scope tree of a original source file.

+ + In case the original source language is JavaScript or JavaScript-like, source map generators are encouraged to use the terms Block, Function, Script/Module and Global for the [[Kind]] field where it makes sense. + +
+ + +

Generated Range Record

+

A generated range is described by a Generated Range Record:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Field NameValueMeaning
[[Start]]a Position RecordThe line and column (inclusive) where this range starts.
[[End]]a Position RecordThe line and column (exclusive) where this range ends.
[[Definition]]a Original Scope Record or *null*The corresponding original scope
[[StackFrameType]]~none~, ~original~, or ~hidden~~original~ signifies that this generated range is a JavaScript/Wasm function. ~hidden~ signifies that this generated range is a compiler/transpiler inserted JavaScript/Wasm function even though [[Definition]] is not *null*. E.g. a original block scope was transpiled to a JS function. ~none~ signifies that this generated range is not a JavaScript/WASM function.
[[Bindings]]a List of Lists of Binding Records[[Bindings]] contains one or more JavaScript expressions for each variable, that when evaluated in this generated range, retrieves the value for that variable.
[[CallSite]]a Original Position Record or *null*[[CallSite]] is not *null* when this generated range represents an inlined original scope body.
[[Children]]a List of Generated Range RecordsThe child ranges of this range.
+
+

A root Generated Range Record describes a distinct part of the generated code. Each Generated Range Record may be associated with a Original Scope Record as indicated by the presence of the [[Definition]] field.

+

[[Bindings]] are intended for debuggers to retrieve the values of original variables. The length of [[Bindings]] must be equal to [[Variables]] of the corresponding Original Scope Record. Given an index _i_, [[Binding]][_i_] describes how to retrieve the value for the original variable [[Variables]][_i_].

+

[[Binding]][_i_] is a List of Binding Records, as there might be different expressions required in different parts of the generated range to retrieve a variables' value. In the common case, [[Binding]][_i_] will either be an empty List, in which case the variable is unavailable throughout the range. Or a single element list where [[Binding]][_i_][0].[[From]] matches [[Start]] and [[Binding]][_i_][0].[[Binding]] is JavaScript expression.

+ + Let _range_ be a Generated Range Record that starts at "0:0" (line 0, column 0) and ends at "0:30". The corresponding Original Scope Record contains a single variable "foo". The value of "foo" can be retrieved via the expression "a" in the range ["0:0", "0:10"). "foo" is unavailable in the range ["0:10", "0:20") and in the range ["0:20", "0:30") the expression "b" must be used. Then _range_ looks like: +

+          {
+            [[Start]]: { [[Line]]: 0, [[Column]]: 0 },
+            [[End]]: { [[Line]]: 0, [[Column]]: 30 },
+            [[Definition]]: { ... }
+            [[Bindings]]: [[
+              {
+                [{From]]: { [[Line]]: 0, [[Column]]: 0 },
+                [[Binding]]: "a",
+              },
+              {
+                [[From]]: { [[Line]]: 0, [[Column]]: 10 },
+                [[Binding]]: *null*,
+              },
+              {
+                [[From]]: { [[Line]]: 0, [[Column]]: 20 },
+                [[Binding]]: "b",
+              },
+            ]],
+          }
+        
+
+

A non-*null* [[CallSite]] field marks the generated range as an inlined scope. If the [[CallSite]] field of a generated range is not *null*, then:

+
    +
  • [[Definition]] must not be *null*.
  • +
  • [[Definition]].[[IsStackFrame]] must be *true*.
  • +
  • [[StackFrameType]] must be ~NONE~.
  • +
+ + +

The Binding Record

+

The Binding Record describes a JavaScript expression that must be used for the given position to retrieve a specific variables' value.

+ + + + + + + + + + + + + + + + + + + +
Field NameValueMeaning
[[From]]a Position RecordUse [[Binding]] from this position until either the next [[From]] or the ranges' [[End]] position to retrieve this variables' value.
[[Binding]]a String or *null*The expression to use to retrieve this variables' value, or *null* if the variable is unavailable.
+
+
+
+ + +

Scopes grammar

+

The scopes field is described by the following context-sensitive grammar starting at the |Scopes| goal symbol:

+ + Scopes : + OriginalScopeTreeList + TopLevelItemList + OriginalScopeTreeList `,` TopLevelItemList + + OriginalScopeTreeList : + OriginalScopeTreeItem + OriginalScopeTreeList `,` OriginalScopeTreeItem + + OriginalScopeTreeItem : + OriginalScopeTree + [empty] + + TopLevelItemList : + TopLevelItem + TopLevelItemList `,` TopLevelItem + + TopLevelItem : + GeneratedRangeTree + UnknownItem + + +

The number of |OriginalScopeTreeItem|s in the |OriginalScopeTreeList| is expected to match the length of the sources field. The n-th |OriginalScopeTreeItem| describes the scope tree of the n-th authored source file in the sources field. If no scope information is available for a particular source URL, an empty item can be used.

+ + +

A source map with three authored sources where only the first and third source file have scope information available would be encoded as:

+
+          "scopes": "<OriginalScopeTree>,,<OriginalScopeTree>,<GeneratedRangeTree>"
+        
+
+ + +

Original scope grammar

+

Each original scope consists of:

+
    +
  • a |OriginalScopeStart| item describing the start location and general scope information.
  • +
  • an optional |OriginalScopeVariablesItem| describing the original names of the variables this scope declares.
  • +
  • an optional list of |OriginalScopeTree|s describing child scopes.
  • +
  • a |OriginalScopeEnd| item describing the end location.
  • +
+

In grammar form:

+ + OriginalScopeTree : + OriginalScopeStart OriginalScopeVariablesItem? OriginalScopeItemList? `,` OriginalScopeEnd + + OriginalScopeVariablesItem : + `,` OriginalScopeVariables + + OriginalScopeItemList : + `,` OriginalScopeItem + OriginalScopeItemList `,` OriginalScopeItem + + OriginalScopeItem : + OriginalScopeTree + UnknownItem + + OriginalScopeStart : + `B` ScopeFlags ScopeLine ScopeColumn ScopeNameOrKind? ScopeKind? + + OriginalScopeEnd : + `C` ScopeLine ScopeColumn + + OriginalScopeVariables : + `D` ScopeVariableList + + ScopeVariableList : + ScopeVariable + ScopeVariableList ScopeVariable + + ScopeFlags : + Vlq + + ScopeLine : + Vlq + + ScopeColumn : + Vlq + + ScopeNameOrKind : + Vlq + + ScopeKind : + Vlq + + ScopeVariable : + Vlq + +

The VLQUnsignedValue of |ScopeFlags| encodes the presence of |ScopeNameOrKind| and |ScopeKind| and marks the scope as a function:

+ + + + + + + + + + + + + + + + + + + + +
Bit MaskMeaning
0x1|ScopeNameOrKind| is present and contains the scope's name.
0x2If 0x1 is also set, |ScopeKind| is present and contains the scope's kind. If 0x1 is not set, then |ScopeNameOrKind| is present and contains the scope's kind.
0x4Mark this scope as something callable. That is the [[IsStackFrame]] field is set to *true*.
+
+
+ + +

Generated range grammar

+

Each generated range consists of:

+
    +
  • a |GeneratedRangeStart| item describing the start location and general range information.
  • +
  • an optional |GeneratedRangeCallSiteItem|. The presence marks this generated range as an inlined function body and the |GeneratedRangeCallSite| describes the location where this function was called in the original source.
  • +
  • an optional |GeneratedRangeBindingsItem| containing the JavaScript expressions to retrieve the values of the corresponding scopes' variables.
  • +
  • an optional list of |GeneratedSubRangeBinding|s. A variable might require different JavaScript expression to retrieve its value throughout this generated range. Or a variable might not be available in only parts of a range.
  • +
  • an optional list of |GeneratedRangeTree|s describing child ranges.
  • +
+

In grammar form:

+ + GeneratedRangeTree : + GeneratedRangeStart GeneratedRangeBindingsItem? GeneratedRangeCallSiteItem? GeneratedRangeItemList? `,` GeneratedRangeEnd + + GeneratedRangeBindingsItem : + `,` GeneratedRangeBindings + + GeneratedRangeCallSiteItem : + `,` GeneratedRangeCallSite + + GeneratedRangeItemList : + `,` GeneratedRangeItem + GeneratedRangeItemList `,` GeneratedRangeItem + + GeneratedRangeItem : + GeneratedSubRangeBinding + GeneratedRangeTree + UnknownItem + + GeneratedRangeStart : + `E` RangeFlags RangeLine? RangeColumn RangeDefinition? + + GeneratedRangeEnd : + `F` RangeLine? RangeColumn + + GeneratedRangeBindings : + `G` RangeBindingsList + + RangeBindingsList : + RangeBinding + RangeBindingsList RangeBinding + + GeneratedSubRangeBinding : + `H` VariableIndex BindingFromList + + BindingFromList : + BindingFrom + BindingFromList BindingFrom + + BindingFrom : + BindingLine BindingColumn BindingExpression + + GeneratedRangeCallSite : + `I` CallSiteSourceIdx CallSiteLine CallSiteColumn + + RangeFlags : + Vlq + + RangeLine : + Vlq + + RangeColumn : + Vlq + + RangeDefinition : + Vlq + + RangeBinding : + Vlq + + VariableIndex : + Vlq + + BindingLine : + Vlq + + BindingColumn : + Vlq + + BindingExpression : + Vlq + + CallSiteSourceIdx : + Vlq + + CallSiteLine : + Vlq + + CallSiteColumn : + Vlq + +

The VLQUnsignedValue of |RangeFlags| encodes the presence of |RangeLine| and |RangeDefinition|. All used bits:

+ + + + + + + + + + + + + + + + + + + + + + + + +
Bit MaskMeaning
0x1Set if |RangeLine| is present.
0x2Set if |RangeDefinition| is present.
0x4If set, then this range as a JavaScript/WASM function in the generated code. This includes methods, accessors, arrow functions, constructors, etc. Any JavaScript language construct that can be called and will result in a stack frame. If set, the [[StackFrameType]] field is set to either ~original~ or ~hidden~, depending on the bit 0x8.
0x8Only valid if the bit 0x4 is also set. Marks this range as a outlined function. E.g. a transpiler translated a block scope into a function. Any call to this range should be hidden in translated stack traces. If set, the [[StackFrameType]] field is set to ~hidden~. If not set, but the bit 0x4 is set, then the [[StackFrameType]] field is set to ~original~.
+
+
+ + +

Unknown item grammar

+

Complying implementations are expected to decode but ignore items with unknown tags. This allows the specification to add new items in the future, without breaking existing decoders.

+ + UnknownItem : + Tag + Tag UnknownVlqList + + Tag : + Vlq but not `B` `C` `D` `E` `F` `G` `H` `I` + + UnknownVlqList : + Vlq + UnknownVlqList Vlq + + + The specification reserves all tags for future use. Vendors wanting to experiment are encouraged to use high enough tag numbers for vendor specific items. + +
+
+ + +

Decoding scopes

+

The scopes grammar defined in is context-sensitive and heavily utilizes relative numbers to reduce the bytes required for the encoded scope information. As such, the grammar alone is not enough to describe how a |Scopes| parse node is turned into Original Scope Records and Generated Range Records.

+ + +

Scope Info Record

+

The Scope Info Record is a specification type and is the result of decoding the scopes field.

+ + + + + + + + + + + + + + + + +
Field NameValue Type
[[Scopes]]a List of either Original Scope Records or *null*
[[Ranges]]a List of Generated Range Records
+
+
+ + +

Decode Scope State Record

+

The Decode Scope State Record is a specification type that tracks absolute values of decoded fields.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Field NameValueMeaning / Production
[[FlatOriginalScopes]]a List of Original Scope RecordsThis is a list of Original Scope Records in order as seen while decoding. This is equivalent to a prefix walk of the [[Scopes]] field in the Scope Info Record. The |RangeDefinition| is an index into this List.
[[ScopeLine]]a non-negative Number|ScopeLine|
[[ScopeColumn]]a non-negative Number|ScopeColumn|
[[ScopeNameIndex]]a non-negative Number|ScopeNameOrKind|
[[ScopeKindIndex]]a non-negative Number|ScopeNameOrKind| and |ScopeKind|
[[ScopeVariableIndex]]a non-negative Number|ScopeVariable|
[[RangeLine]]a non-negative Number|RangeLine|
[[RangeColumn]]a non-negative Number|RangeColumn|
[[RangeDefinitionIndex]]a non-negative Number|RangeDefinition|
[[SubRangeLine]]a non-negative Number|BindingLine|
[[SubRangeColumn]]a non-negative Number|BindingColumn|
[[SubRangeVariableIndex]]a non-negative NumberTracks the variable while decoding sub-range bindings.
+
+
+ + +

+ DecodeScopesInfo ( + _scopes_: a String or *null*, + _names_: a List of Strings, + ): a Scope Info Record +

+
+ + 1. Let _result_ be a new Scope Info Record { [[Scopes]]: « », [[Records]]: « » }. + 1. If _scopes_ is *null*, return _result_. + 1. Let _parsedScopes_ be the root Parse Node when parsing _scopes_ using |Scopes| as the goal symbol. + 1. If parsing failed, then + 1. Optionally report an error. + 1. Return _result_. + 1. Let _state_ be a new Decode Scope State Record { [[FlatScopes]]: « », [[ScopeLine]]: 0, [[ScopeColumn]]: 0, [[ScopeNameIndex]]: 0, [[ScopeKindIndex]]: 0, [[ScopeVariableIndex]]: 0, [[RangeLine]]: 0, [[RangeColumn]]: 0, [[RangeDefinitionIndex]]: 0, [[SubRangeLine]]: 0, [[SubRangeColumn]]: 0 }. + 1. Perform DecodeScopesInfoItem of _parsedScopes_ with arguments _result_, _state_ and _names_. + 1. Return _result_. + + + +

+ DecodeScopesInfoItem ( + _info_: a Scope Info Record, + _state_: a Decode Scope State Record, + _names_: a List of Strings, + ) +

+
+ + Scopes : + OriginalScopeTreeList `,` TopLevelItemList + + + 1. Perform DecodeScopesInfoItem of |OriginalScopeTreeList| with arguments _info_, _state_ and _names_. + 1. Perform DecodeScopesInfoItem of |TopLevelItemList| with arguments _info_, _state_ and _names_. + + + OriginalScopeTreeList : + OriginalScopeTreeList `,` OriginalScopeTreeItem + + + 1. Perform DecodeScopesInfoItem of |OriginalScopeTreeList| with arguments _info_, _state_ and _names_. + 1. Perform DecodeScopesInfoItem of |OriginalScopeTreeItem| with arguments _info_, _state_ and _names_. + + + OriginalScopeTreeItem : + OriginalScopeTree + + + 1. Set _state_.[[ScopeLine]] to 0. + 1. Set _state_.[[ScopeColumn]] to 0. + 1. Let _scope_ be DecodeOriginalScope(|OriginalScopeTree|, _state_, _names_). + 1. Append _scope_ to _info_.[[Scopes]]. + + + OriginalScopeTreeItem : + [empty] + + + 1. Append *null* to _info_.[[Scopes]]. + + + TopLevelItemList : + TopLevelItemList `,` TopLevelItem + + + 1. Perform DecodeScopesInfoItem of |TopLevelItemList| with arguments _info_, _state_ and _names_. + 1. Perform DecodeScopesInfoItem of |TopLevelItem| with arguments _info_, _state_ and _names_. + + + TopLevelItem : + GeneratedRangeTree + + + 1. Let _range_ be DecodeGeneratedRange(|GeneratedRangeTree|, _state_, _names_). + 1. Append _range_ to _info_.[[Ranges]]. + +
+
+ + +

+ DecodeOriginalScope ( + _scopeTree_: a |OriginalScopeTree| Parse Node, + _state_: a Decode Scope State Record, + _names_: a List of Strings, + ): a Original Scope Record +

+
+ + 1. Let _scope_ be a new Original Scope Record with all fields default initialized. + 1. Perform DecodeOriginalScopeItem of _scopeTree_ with arguments _scope_, _state_ and _names_. + 1. Append _scope_ to _state_.[[FlatScopes]]. + 1. Return _scope_. + + + +

+ DecodeOriginalScopeItem ( + _scope_: a Original Scope Record, + _state_: a Decode Scope State Record, + _names_: a List of Strings, + ) +

+
+ + OriginalScopeTree : + OriginalScopeStart OriginalScopeVariablesItem? OriginalScopeItemList? `,` OriginalScopeEnd + + + 1. Perform DecodeOriginalScopeItem of |OriginalScopeStart| with arguments _scope_, _state_ and _names_. + 1. If |OriginalScopeVariablesItem| is present, perform DecodeOriginalScopeItem of |OriginalScopeVariablesItem| with arguments _scope_, _state_ and _names_. + 1. If |OriginalScopeItemList| is present, perform DecodeOriginalScopeItem of |OriginalScopeItemList| with arguments _scope_, _state_ and _names_. + 1. Perform DecodeOriginalScopeItem of |OriginalScopeEnd| with arguments _scope_, _state_ and _names_. + + + OriginalScopeStart : + `B` ScopeFlags ScopeLine ScopeColumn ScopeNameOrKind? ScopeKind? + + + 1. Perform DecodeOriginalScopeItem of |ScopeLine| with arguments _scope_, _state_ and _names_. + 1. Set _scope_.[[Start]].[[Line]] to _state_.[[ScopeLine]]. + 1. Perform DecodeOriginalScopeItem of |ScopeColumn| with arguments _scope_, _state_ and _names_. + 1. Set _scope_.[[Start]].[[Column]] to _state_.[[ScopeColumn]]. + 1. Let _flags_ be the VLQUnsignedValue of |ScopeFlags|. + 1. If _flags_ & 0x3 = 0x1, then + 1. Assert: |ScopeNameOrKind| is present and |ScopeKind| is not present. + 1. DecodeOriginalScopeName(|ScopeNameOrKind|, _scope_, _state_, _names_). + 1. Else if _flags_ & 0x3 = 0x2, then + 1. Assert: |ScopeNameOrKind| is present and |ScopeKind| is not present. + 1. DecodeOriginalScopeKind(|ScopeNameOrKind|, _scope_, _state_, _names_). + 1. Else if _flags_ & 0x3 = 0x3, then + 1. Assert: |ScopeNameOrKind| is present and |ScopeKind| is present. + 1. DecodeOriginalScopeName(|ScopeNameOrKind|, _scope_, _state_, _names_). + 1. DecodeOriginalScopeKind(|ScopeKind|, _scope_, _state_, _names_). + 1. If _flags_ & 0x4 = 0x4, set _scope_.[[IsStackFrame]] to *true*. + + + ScopeVariableList : + ScopeVariableList ScopeVariable + + + 1. Perform DecodeOriginalScopeItem of |ScopeVariableList| with arguments _scope_, _state_ and _names_. + 1. Perform DecodeOriginalScopeItem of |ScopeVariable| with arguments _scope_, _state_ and _names_. + + + OriginalScopeItemList : + OriginalScopeItemList `,` OriginalScopeItem + + + 1. Perform DecodeOriginalScopeItem of |OriginalScopeItemList| with arguments _scope_, _state_ and _names_. + 1. Perform DecodeOriginalScopeItem of |OriginalScopeItem| with arguments _scope_, _state_ and _names_. + + + OriginalScopeItem : + OriginalScopeTree + + + 1. Let _childScope_ be DecodeOriginalScope(|OriginalScopeTree|, _state_, _names_). + 1. Append _childScope_ to _scope_.[[Children]]. + + + OriginalScopeEnd : + `C` ScopeLine ScopeColumn + + + 1. Perform DecodeOriginalScopeItem of |ScopeLine| with arguments _scope_, _state_ and _names_. + 1. Set _scope_.[[End]].[[Line]] to _state_.[[ScopeLine]]. + 1. Perform DecodeOriginalScopeItem of |ScopeColumn| with arguments _scope_, _state_ and _names_. + 1. Set _scope_.[[End]].[[Column]] to _state_.[[ScopeColumn]]. + + + ScopeLine : + Vlq + + + 1. Let _relativeLine_ be the VLQUnsignedValue of |Vlq|. + 1. Set _state_.[[ScopeLine]] to _state_.[[ScopeLine]] + _relativeLine_. + 1. [id="step-reset-scope-column"] If _relativeLine_ > 0, set _state_.[[ScopeColumn]] to 0. + + + Step makes it so |ScopeColumn| is encoded relative if the preceding |OriginalScopeStart| or |OriginalScopeEnd| is on the same line (i.e. _relativeLine_ is 0), or absolute otherwise. + + + ScopeColumn : + Vlq + + + 1. Let _relativeColumn_ be the VLQUnsignedValue of |Vlq|. + 1. Set _state_.[[ScopeColumn]] to _state_.[[ScopeColumn]] + _relativeColumn_. + + + ScopeVariable : + Vlq + + + 1. Let _relativeVariable_ be the VLQSignedValue of |Vlq|. + 1. Set _state_.[[ScopeVariableIndex]] to _state_.[[ScopeVariableIndex]] + _relativeVariable_. + 1. Append _names_[_state_.[[ScopeVariableIndex]]] to _scope_.[[Variables]]. + +
+ + +

+ DecodeOriginalScopeName ( + _name_: a |Vlq| Parse Node, + _scope_: a Original Scope Record, + _state_: a Decode Scope State Record, + _names_: a List of Strings, + ) +

+
+ + 1. Let _relativeName_ be the VLQSignedValue of _name_. + 1. Set _state_.[[ScopeNameIndex]] to _state_.[[ScopeNameIndex]] + _relativeName_. + 1. Set _scope_.[[Name]] to _names_[_state_.[[ScopeNameIndex]]]. + +
+ + +

+ DecodeOriginalScopeKind ( + _kind_: a |Vlq| Parse Node, + _scope_: a Original Scope Record, + _state_: a Decode Scope State Record, + _names_: a List of Strings, + ) +

+
+ + 1. Let _relativeKind_ be the VLQSignedValue of _kind_. + 1. Set _state_.[[ScopeKindIndex]] to _state_.[[ScopeKindIndex]] + _relativeKind_. + 1. Set _scope_.[[Kind]] to _names_[_state_.[[ScopeKindIndex]]]. + +
+
+ + +

+ DecodeGeneratedRange ( + _rangeTree_: a |GeneratedRangeTree| Parse Node, + _state_: a Decode Scope State Record, + _names_: a List of Strings, + ): a Generated Range Record +

+
+ + 1. Let _range_ be a new Generated Range Record with all fields default initialized. + 1. Perform DecodeGeneratedRangeItem of _rangeTree_ with arguments _range_, _state_ and _names_. + 1. Return _range_. + + + +

+ DecodeGeneratedRangeItem ( + _range_: a Generated Range Record, + _state_: a Decode Scope State Record, + _names_: a List of Strings, + ) +

+
+ + GeneratedRangeTree : + GeneratedRangeStart GeneratedRangeBindingsItem? GeneratedRangeCallSiteItem? GeneratedRangeItemList? `,` GeneratedRangeEnd + + + 1. Perform DecodeGeneratedRangeItem of |GeneratedRangeStart| with arguments _range_, _state_ and _names_. + 1. If |GeneratedRangeBindingsItem| is present, perform DecodeGeneratedRangeItem of |GeneratedRangeBindingsItem| with arguments _range_, _state_ and _names_. + 1. If |GeneratedRangeCallSiteItem| is present, perform DecodeGeneratedRangeItem of |GeneratedRangeCallSiteItem| with arguments _range_, _state_ and _names_. + 1. If |GeneratedRangeItemList| is present, perform DecodeGeneratedRangeItem of |GeneratedRangeItemList| with arguments _range_, _state_ and _names_. + 1. Perform DecodeGeneratedRangeItem of |GeneratedRangeEnd| with arguments _range_, _state_ and _names_. + + + GeneratedRangeItemList : + GeneratedRangeItemList `,` GeneratedRangeItem + + + 1. Perform DecodeGeneratedRangeItem of |GeneratedRangeItemList| with arguments _range_, _state_ and _names_. + 1. Perform DecodeGeneratedRangeItem of |GeneratedRangeItem| with arguments _range_, _state_ and _names_. + + + GeneratedRangeItem : + GeneratedRangeTree + + + 1. Let _childRange_ be DecodeGeneratedRange(|GeneratedRangeTree|, _state_, _names_). + 1. Append _childRange_ to _range_.[[Children]]. + + + GeneratedRangeStart : + `E` RangeFlags RangeLine? RangeColumn RangeDefinition? + + + 1. Let _flags_ be the VLQUnsignedValue of |RangeFlags|. + 1. Assert: |RangeLine| is present if and only if, _flags_ & 0x1 = 0x1. + 1. If |RangeLine| is present, perform DecodeGeneratedRangeItem of |RangeLine| with arguments _range_, _state_ and _names_. + 1. Set _range_.[[Start]].[[Line]] to _state_.[[RangeLine]]. + 1. Perform DecodeGeneratedRangeItem of |RangeColumn| with arguments _range_, _state_ and _names_. + 1. Set _range_.[[Start]].[[Column]] to _state_.[[RangeColumn]]. + 1. Assert: |RangeDefinition| is present if and only if, _flags_ & 0x2 = 0x2. + 1. If |RangeDefinition| is present, perform DecodeGeneratedRangeItem of |RangeDefinition| with arguments _range_, _state_ and _names_. + 1. If _flags_ & 0x4 = 0x4 and _flags_ & 0x8 = 0x8, set _range_.[[StackFrameType]] to ~hidden~. + 1. Else if _flags_ & 0x8 = 0x8, optionally report an error. + 1. Else if _flags_ & 0x4 = 0x4, set _range_.[[StackFrameType]] to ~original~. + 1. Else, set _range_.[[StackFrameType]] to ~none~. + + + GeneratedRangeEnd : + `F` RangeLine? RangeColumn + + + 1. If |RangeLine| is present, perform DecodeGeneratedRangeItem of |RangeLine| with arguments _range_, _state_ and _names_. + 1. Set _range_.[[End]].[[Line]] to _state_.[[RangeLine]]. + 1. Perform DecodeGeneratedRangeItem of |RangeColumn| with arguments _range_, _state_ and _names_. + 1. Set _range_.[[End]].[[Column]] to _state_.[[RangeColumn]]. + + + RangeBindingsList : + RangeBindingsList RangeBinding + + + 1. Perform DecodeGeneratedRangeItem of |RangeBindingsList| with arguments _range_, _state_ and _names_. + 1. Perform DecodeGeneratedRangeItem of |RangeBindingsList| with arguments _range_, _state_ and _names_. + + + GeneratedSubRangeBinding : + `H` VariableIndex BindingFromList + + + 1. [id="step-reset-subrange-line"] Set _state_.[[SubRangeLine]] to _range_.[[Start]].[[Line]]. + 1. [id="step-reset-subrange-column"] Set _state_.[[SubRangeColumn]] to _range_.[[Start]].[[Column]]. + 1. Let _variableIndex_ be the VLQUnsignedValue of |VariableIndex|. + 1. Set _state_.[[SubRangeVariableIndex]] to _variableIndex_. + 1. Perform DecodeGeneratedRangeItem of |BindingFromList| with arguments _range_, _state_ and _names_. + + + Sub-range "from" positions are encoded relative to each other. Step and make it so that the first sub-range is relative to the ranges' start position. + + + GeneratedRangeCallSite : + `I` CallSiteSourceIdx CallSiteLine CallSiteColumn + + + 1. Let _sourceIndex_ be the VLQUnsignedValue of |CallSiteSourceIdx|. + 1. Let _line_ be the VLQUnsignedValue of |CallSiteLine|. + 1. Let _column_ be the VLQUnsignedValue of |CallSiteColumn|. + 1. Set _range_.[[CallSite]] to a new Original Position Record { [[SourceIndex]]: _sourceIndex_, [[Line]]: _line_, [[Column]]: _column_ }. + + + RangeLine : + Vlq + + + 1. Let _relativeLine_ be the VLQUnsignedValue of |Vlq|. + 1. Set _state_.[[RangeLine]] to _state_.[[RangeLine]] + _relativeLine_. + 1. [id="step-reset-range-column"] If _relativeLine_ > 0, set _state_.[[RangeColumn]] to 0. + + + Step makes it so |RangeColumn| is encoded relative if the preceding |GeneratedRangeStart| or |GeneratedRangeEnd| is on the same line (i.e. _relativeLine_ is 0), or absolute otherwise. + + + RangeColumn : + Vlq + + + 1. Let _relativeColumn_ be the VLQUnsignedValue of |Vlq|. + 1. Set _state_.[[RangeColumn]] to _state_.[[RangeColumn]] + _relativeColumn_. + + + RangeDefinition : + Vlq + + + 1. Let _relativeDefinition_ be the VLQSignedValue of |Vlq|. + 1. Set _state_.[[RangeDefinitionIndex]] to _state_.[[RangeDefinitionIndex]] + _relativeDefinition_. + 1. Set _range_.[[Definition]] to _state_.[[FlatOriginalScopes]][_state_.[[RangeDefinitionIndex]]]. + + + RangeBinding : + Vlq + + + 1. Let _bindings_ be a new empty List. + 1. Let _binding_ be the VLQUnsignedValue of |Vlq|. + 1. If _binding_ > 0, append { [[From]]: _range_.[[Start]], [[Binding]]: _names_[_binding_ - 1] } to _bindings_. + 1. Append _bindings_ to _range_.[[Bindings]]. + + + BindingFromList : + BindingFromList BindingFrom + + + 1. Perform DecodeGeneratedRangeItem of |BindingFromList| with arguments _range_, _state_ and _names_. + 1. Perform DecodeGeneratedRangeItem of |BindingFrom| with arguments _range_, _state_ and _names_. + + + BindingFrom : + BindingLine BindingColumn BindingExpression + + + 1. Perform DecodeGeneratedRangeItem of |BindingLine| with arguments _range_, _state_ and _names_. + 1. Perform DecodeGeneratedRangeItem of |BindingColumn| with arguments _range_, _state_ and _names_. + 1. Let _bindingIndex_ be the VLQUnsignedValue of |BindingExpression|. + 1. If _bindingIndex_ > 0, let _binding_ be _names_[_bindingIndex_ - 1]. + 1. Else, let _binding_ be *null*. + 1. Append { [[From]]: { [[Line]]: _state_.[[SubRangeLine]], [[Column]]: _state_.[[SubRangeColumn]] }, [[Binding]]: _binding_ } to _range_.[[Bindings]][_state_.[[SubRangeVariableIndex]]]. + + + BindingLine : + Vlq + + + 1. Let _relativeLine_ be the VLQUnsignedValue of |Vlq|. + 1. Set _state_.[[SubRangeLine]] to _state_.[[SubRangeLine]] + _relativeLine_. + 1. If _relativeLine_ > 0, set _state_.[[SubRangeColumn]] to 0. + + + BindingColumn : + Vlq + + + 1. Let _relativeColumn_ be the VLQUnsignedValue of |Vlq|. + 1. Set _state_.[[SubRangeColumn]] to _state_.[[SubRangeColumn]] + _relativeColumn_. + +
+
+
+
+

Resolving sources

@@ -1127,6 +2117,7 @@ _sources_: a List of either Strings or *null*, _sourcesContent_: a List of either Strings or *null*, _ignoreList_: a List of non-negative integers, + _scopes_: a List of either Original Scope Records or *null*, ): a Decoded Source Record
@@ -1142,7 +2133,7 @@ 1. Let _index_ be 0. 1. Repeat, while _index_ < _sources_' length, 1. Let _source_ be _sources_[_index_]. - 1. Let _decodedSource_ be the Decoded Source Record { [[URL]]: *null*, [[Content]]: *null*, [[Ignored]]: *false* }. + 1. Let _decodedSource_ be the Decoded Source Record { [[URL]]: *null*, [[Content]]: *null*, [[Ignored]]: *false*, [[Scope]]: *null* }. 1. If _source_ ≠ *null*, then 1. Set _source_ to the string-concatenation of _sourceUrlPrefix_ and _source_. 1. Let _sourceURL_ be the result of URL parsing _source_ with _baseURL_. @@ -1150,6 +2141,8 @@ 1. Else, set _decodedSource_.[[URL]] to _sourceURL_. 1. If _ignoreList_ contains _index_, set _decodedSource_.[[Ignored]] to *true*. 1. If _sourcesContentCount_ > _index_, set _decodedSource_.[[Content]] to _sourcesContent_[_index_]. + 1. If _index_ < _scopes_' length, then + 1. Set _decodedSource_.[[Scope]] to _scopes_.[_index_]. 1. Append _decodedSource_ to _decodedSources_. 1. Return _decodedSources_.