From 84cb0cd25989413568c1bd280b604731777bdef8 Mon Sep 17 00:00:00 2001 From: Asumu Takikawa Date: Mon, 20 Oct 2025 08:24:55 -0700 Subject: [PATCH 1/4] Range mappings: add spec text for decoding, parsing, and lookup (#232) Adds a flag to Decoded Mapping Records which indicate if a mapping is a range mapping. Populate this field based on the decoded range mapping offsets. --- spec.emu | 211 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 196 insertions(+), 15 deletions(-) diff --git a/spec.emu b/spec.emu index 140d2df..9655dd1 100644 --- a/spec.emu +++ b/spec.emu @@ -572,6 +572,7 @@ "sourcesContent": [null, null], "names": ["src", "maps", "are", "fun"], "mappings": "A,AAAB;;ABCDE", + "rangeMappings": "C;;B", "ignoreList": [0] } @@ -583,6 +584,7 @@
  • The sourcesContent field is an optional list of source content (i.e. the original source) strings, used when the source cannot be hosted. The contents are listed in the same order as in the sources field. Entries may be *null* if some original sources should be retrieved by name.
  • The names field is an optional list of symbol names which may be used by the mappings field.
  • The mappings field is a string with the encoded mapping data (see section ).
  • +
  • The rangeMappings field is a string with the encoded range mappings data (see section ).
  • The ignoreList field is an optional list of indices of files that should be considered third party code, such as framework code or bundler-generated code. This allows developer tools to avoid code that developers likely don't want to see or step through, without requiring developers to configure this beforehand. It refers to the sources field and lists the indices of all the known third-party sources in the source map. Some browsers may also use the deprecated `x_google_ignoreList` field if `ignoreList` is not present.
  • @@ -682,7 +684,10 @@ 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. Let _rangeMappingsField_ be GetOptionalString(_json_, *"rangeMappings"*). + 1. If _rangeMappingsField_ is *null*, set _rangeMappingsField_ to *""*. + 1. Let _rangeMappings_ be DecodeRangeMappings(_rangeMappingsField_). + 1. Let _mappings_ be DecodeMappings(_mappingsField_, _namesField_, _sources_, _rangeMappings_). 1. [declared="a,b"] Sort _mappings_ in ascending order, with a Decoded Mapping Record _a_ being less than a Decoded Mapping Record _b_ if ComparePositions(_a_.[[GeneratedPosition]], _b_.[[GeneratedPosition]]) is ~lesser~. 1. Return the Decoded Source Map Record { [[File]]: _fileField_, [[Sources]]: _sources_, [[Mappings]]: _mappings_ }. @@ -834,6 +839,10 @@ [[Name]] a String or *null* + + [[IsRangeMapping]] + a Boolean + @@ -913,6 +922,10 @@ [[NameIndex]] a non-negative integer + + [[MappingIndex]] + a non-negative integer + @@ -923,6 +936,7 @@ _mappings_: a List of Decoded Mapping Records, _names_: a List of Strings, _sources_: a List of Decoded Source Records, + _rangeMappings_: a List of of Decoded Range Mapping Offset Records, )
    @@ -931,10 +945,11 @@ Line `;` LineList - 1. Perform DecodeMappingsField of |Line| with arguments _state_, _mappings_, _names_ and _sources_. + 1. Perform DecodeMappingsField of |Line| with arguments _state_, _mappings_, _names_, and _sources_ and _rangeMappings_. 1. Set _state_.[[GeneratedLine]] to _state_.[[GeneratedLine]] + 1. 1. Set _state_.[[GeneratedColumn]] to 0. - 1. Perform DecodeMappingsField of |LineList| with arguments _state_, _mappings_, _names_ and _sources_. + 1. Set _state_.[[MappingIndex]] to 0. + 1. Perform DecodeMappingsField of |LineList| with arguments _state_, _mappings_, _names_, and _sources_ and _rangeMappings_. Line : [empty] @@ -947,35 +962,36 @@ Mapping `,` MappingList - 1. Perform DecodeMappingsField of |Mapping| with arguments _state_, _mappings_, _names_ and _sources_. - 1. Perform DecodeMappingsField of |MappingList| with arguments _state_, _mappings_, _names_ and _sources_. + 1. Perform DecodeMappingsField of |Mapping| with arguments _state_, _mappings_, _names_, and _sources_ and _rangeMappings_. + 1. Perform DecodeMappingsField of |MappingList| with arguments _state_, _mappings_, _names_, and _sources_ and _rangeMappings_. Mapping : GeneratedColumn - 1. Perform DecodeMappingsField of |GeneratedColumn| with arguments _state_, _mappings_, _names_ and _sources_. + 1. Perform DecodeMappingsField of |GeneratedColumn| with arguments _state_, _mappings_, _names_, and _sources_ and _rangeMappings_. 1. If _state_.[[GeneratedColumn]] < 0, then 1. Optionally report an error. 1. Return. 1. Let _position_ be a new Position Record { [[Line]]: _state_.[[GeneratedLine]], [[Column]]: _state_.[[GeneratedColumn]] }. - 1. Let _decodedMapping_ be a new DecodedMappingRecord { [[GeneratedPosition]]: _position_, [[OriginalPosition]]: *null*, [[Name]]: *null* }. + 1. Let _decodedMapping_ be a new DecodedMappingRecord { [[GeneratedPosition]]: _position_, [[OriginalPosition]]: *null*, [[Name]]: *null*, [[IsRangeMapping]]: *false* }. 1. Append _decodedMapping_ to _mappings_. + 1. Set _state_.[[MappingIndex]] to _state_.[[MappingIndex]] + 1. Mapping : GeneratedColumn OriginalSource OriginalLine OriginalColumn Name? - 1. Perform DecodeMappingsField of |GeneratedColumn| with arguments _state_, _mappings_, _names_ and _sources_. + 1. Perform DecodeMappingsField of |GeneratedColumn| with arguments _state_, _mappings_, _names_, and _sources_ and _rangeMappings_. 1. If _state_.[[GeneratedColumn]] < 0, then 1. Optionally report an error. 1. Return. 1. Let _generatedPosition_ be a new Position Record { [[Line]]: _state_.[[GeneratedLine]], [[Column]]: _state_.[[GeneratedColumn]] }. - 1. Perform DecodeMappingsField of |OriginalSource| with arguments _state_, _mappings_, _names_ and _sources_. - 1. Perform DecodeMappingsField of |OriginalLine| with arguments _state_, _mappings_, _names_ and _sources_. - 1. Perform DecodeMappingsField of |OriginalColumn| with arguments _state_, _mappings_, _names_ and _sources_. + 1. Perform DecodeMappingsField of |OriginalSource| with arguments _state_, _mappings_, _names_, and _sources_ and _rangeMappings_. + 1. Perform DecodeMappingsField of |OriginalLine| with arguments _state_, _mappings_, _names_, and _sources_ and _rangeMappings_. + 1. Perform DecodeMappingsField of |OriginalColumn| with arguments _state_, _mappings_, _names_, and _sources_ and _rangeMappings_. 1. If _state_.[[SourceIndex]] < 0 or _state_.[[SourceIndex]] ≥ the number of elements of _sources_ or _state_.[[OriginalLine]] < 0 or _state_.[[OriginalColumn]] < 0, then 1. Optionally report an error. 1. Let _originalPosition_ be *null*. @@ -983,11 +999,13 @@ 1. Let _originalPosition_ be a new Original Position Record { [[Source]]: _sources_[_state_.[[SourceIndex]]], [[Line]]: _state_.[[OriginalLine]], [[Column]]: _state_.[[OriginalColumn]] }. 1. Let _name_ be *null*. 1. If |Name| is present, then - 1. Perform DecodeMappingsField of |Name| with arguments _state_, _mappings_, _names_ and _sources_. + 1. Perform DecodeMappingsField of |Name| with arguments _state_, _mappings_, _names_, and _sources_ and _rangeMappings_. 1. If _state_.[[NameIndex]] < 0 or _state_.[[NameIndex]] ≥ the number of elements of _names_, optionally report an error. 1. Else, set _name_ to _names_[_state_.[[NameIndex]]]. - 1. Let _decodedMapping_ be a new DecodedMappingRecord { [[GeneratedPosition]]: _generatedPosition_, [[OriginalPosition]]: _originalPosition_, [[Name]]: _name_ }. + 1. Let _isRangeMapping_ be the result of performing LookupRangeMapping with arguments _rangeMappings_, _state.[[GeneratedLine]], and _state.[[MappingIndex]]. + 1. Let _decodedMapping_ be a new DecodedMappingRecord { [[GeneratedPosition]]: _generatedPosition_, [[OriginalPosition]]: _originalPosition_, [[Name]]: _name_, [[IsRangeMapping]]: _isRangeMapping_ }. 1. Append _decodedMapping_ to _mappings_. + 1. Set _state_.[[MappingIndex]] to _state_.[[MappingIndex]] + 1. GeneratedColumn : @@ -1038,6 +1056,7 @@ _rawMappings_: a String, _names_: a List of Strings, _sources_: a List of Decoded Source Records, + _rangeMappings_: a List of Decoded Range Mapping Offset Records, ): a List of Decoded Mapping Record
    @@ -1048,7 +1067,7 @@ 1. Optionally report an error. 1. Return _mappings_. 1. Let _state_ be a new Decode Mapping State Record with all fields set to 0. - 1. Perform DecodeMappingsField of _mappingsNode_ with arguments _state_, _mappings_, _names_ and _sources_. + 1. Perform DecodeMappingsField of _mappingsNode_ with arguments _state_, _mappings_, _names_, and _sources_ and _rangeMappings_. 1. Return _mappings_. @@ -1119,6 +1138,142 @@ + + + + +

    Range mappings

    + +

    A range mapping is a mapping that specifies mapped positions in the original source for a continuous range of positions in the generated code rather than for a single position. Each mapping in a source map can be specified to be a range mapping or not based on the encoded offsets in the rangeMappings field. A range mapping maps every position starting at its generated position field and ending before the generated position field of the next mapping, where the mapped original position is the mapping's original position field offset by the generated position's distance from the start of the range.

    + +

    A Decoded Range Mapping Offset Record has the following fields:

    + + + + + + + + + + + + + + + + +
    + Field Name + + Value Type +
    [[GeneratedLine]]a non-negative integer
    [[MappingIndex]]a non-negative integer
    +
    + +

    A Decode Range Mappings State Record has the same fields as a Decoded Range Mapping Offset Record.

    + + +

    Range mappings grammar

    +

    The range mappings String must adhere to the following grammar:

    + + + RangeMappingsField : + RangeMappingLineList + + RangeMappingLineList : + RangeMappingLine + RangeMappingLine `;` RangeMappingLineList + + RangeMappingLine : + RangeMappingList? + + RangeMappingList : + RangeMapping + RangeMapping RangeMappingList + + RangeMapping : + Vlq + +
    + + +

    + DecodeRangeMappingsField ( + _state_: a Decode Range Mappings State Record, + _rangeMappings_: a List of Decoded Range Mapping Offset Records, + ) +

    +
    + + RangeMappingLineList : + RangeMappingLine `;` RangeMappingLineList + + + 1. Perform DecodeRangeMappingsField of |RangeMappingLine| with arguments _state_ and _rangeMappings_. + 1. Set _state_.[[GeneratedLine]] to _state_.[[GeneratedLine]] + 1. + 1. Set _state_.[[MappingIndex]] to 0. + 1. Perform DecodeRangeMappingsField of |RangeMappingLineList| with arguments _state_ and _rangeMappings_. + + + RangeMappingList : + RangeMapping RangeMappingList + + + 1. Perform DecodeRangeMappingsField of |RangeMapping| with arguments _state_ and _rangeMappings_. + 1. Perform DecodeRangeMappingsField of |RangeMappingList| with arguments _state_, _rangeMappings_. + + + RangeMapping : + Vlq + + + 1. Let _relativeIndex_ be the VLQUnsignedValue of |Vlq|. + 1. If _relativeIndex_ is 0, then + 1. Optionally report an error. + 1. Set _state_.[[MappingIndex]] to _state_.[[MappingIndex]] + _relativeIndex_. + 1. Let _rangeMappingOffset_ be a new Decoded Range Mapping Offset Record { [[GeneratedLine]]: _state_.[[GeneratedLine]], [[MappingIndex]]: _state_.[[MappingIndex]] - 1 }. + 1. Append _rangeMappingOffset_ to _rangeMappings_. + +
    + + +

    + DecodeRangeMappings ( + _rawRangeMappings_: a String, + ): a List of Decoded Range Mapping Offset Records +

    +
    + + 1. Let _rangeMappings_ be a new empty List. + 1. Let _rangeMappingsNode_ be the root Parse Node when parsing _rawRangeMappings_ using |RangeMappingsField| as the goal symbol. + 1. If parsing failed, then + 1. Optionally report an error. + 1. Return _rangeMappings_. + 1. Let _state_ be a new Decode Range Mappings State Record with all fields set to 0. + 1. Perform DecodeRangeMappingsField of _rangeMappingsNode_ with arguments _state_ and _rangeMappings_. + 1. Return _rangeMappings_. + +
    + + +

    + LookupRangeMapping ( + _rangeMappings_: a List of Decoded Range Mapping Offset Records, + _generatedLine_: an integral Number, + _mappingIndex_: an integral Number, + ): a Boolean +

    +
    + + 1. Let _rangeMappingOffset_ be a new Decoded Range Mapping Offset Record { [[GeneratedLine]] : _generatedLine_, [[MappingIndex]]: _mappingIndex_ }. + 1. If _rangeMappingOffset_ is an element of _rangeMappings_, then + 1. Return *true*. + 1. Else, + 1. Return *false*. + +
    +
    +
    @@ -1570,10 +1725,36 @@ return lastURL; 1. If _last_ is not *null*, then 1. For each element _mapping_ of _mappings_, do 1. If the result of performing ComparePositions(_last_.[[GeneratedPosition]], _mapping_.[[GeneratedPosition]]) is ~equal~, then - 1. Append _mapping_.[[OriginalPosition]] to _originalPositions_. + 1. If _mapping_.[[IsRangeMapping]] is true, then + 1. Append GetRangeMappedPosition(_generatedPosition_, _mapping_) to _originalPositions_. + 1. Else, + 1. Append _mapping_.[[OriginalPosition]] to _originalPositions_. 1. Return _originalPositions_. + + + + +

    + GetRangeMappedPosition ( + _lookupPosition_: a Position Record, + _mapping_: a Decoded Mapping Record, + ): an Original Position Record +

    +
    + + 1. Let _lineDelta_ be _lookupPosition_.[[Line]] - _mapping_.[[GeneratedPosition]].[[Line]]. + 1. Assert: _lineDelta_ ≥ 0. + 1. If _lineDelta_ is 0, then + 1. Let _columnDelta_ be _lookupPosition_.[[Column]] - _mapping_.[[GeneratedPosition]].[[Column]]. + 1. Else, + 1. Let _columnDelta_ be 0. + 1. Assert: _columnDelta_ ≥ 0. + 1. Return a new Original Position Record { [[Source]]: _mapping_.[[Source]], [[Line]]: _mapping_.[[OriginalPosition]].[[Line]] + _lineDelta_, [[Column]]: _mapping_.[[OriginalPosition]].[[Column]] + _columnDelta_ }. + +
    +
    From 6f1d343a0d9af8a01112a8c1aa956030c7bcbd15 Mon Sep 17 00:00:00 2001 From: Asumu Takikawa Date: Fri, 14 Nov 2025 14:13:52 -0800 Subject: [PATCH 2/4] Range mappings: quick fixes for review feedback (#234) * Address some quick fixes from review * Move null check into decode operation * Return an empty List on null range mappings --- spec.emu | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec.emu b/spec.emu index 9655dd1..e74d7e3 100644 --- a/spec.emu +++ b/spec.emu @@ -685,7 +685,6 @@ 1. Let _sources_ be DecodeSourceMapSources(_baseURL_, _sourceRootField_, _sourcesField_, _sourcesContentField_, _ignoreListField_). 1. Let _namesField_ be GetOptionalListOfStrings(_json_, *"names"*). 1. Let _rangeMappingsField_ be GetOptionalString(_json_, *"rangeMappings"*). - 1. If _rangeMappingsField_ is *null*, set _rangeMappingsField_ to *""*. 1. Let _rangeMappings_ be DecodeRangeMappings(_rangeMappingsField_). 1. Let _mappings_ be DecodeMappings(_mappingsField_, _namesField_, _sources_, _rangeMappings_). 1. [declared="a,b"] Sort _mappings_ in ascending order, with a Decoded Mapping Record _a_ being less than a Decoded Mapping Record _b_ if ComparePositions(_a_.[[GeneratedPosition]], _b_.[[GeneratedPosition]]) is ~lesser~. @@ -1002,7 +1001,7 @@ 1. Perform DecodeMappingsField of |Name| with arguments _state_, _mappings_, _names_, and _sources_ and _rangeMappings_. 1. If _state_.[[NameIndex]] < 0 or _state_.[[NameIndex]] ≥ the number of elements of _names_, optionally report an error. 1. Else, set _name_ to _names_[_state_.[[NameIndex]]]. - 1. Let _isRangeMapping_ be the result of performing LookupRangeMapping with arguments _rangeMappings_, _state.[[GeneratedLine]], and _state.[[MappingIndex]]. + 1. Let _isRangeMapping_ be the result of performing LookupRangeMapping with arguments _rangeMappings_, _state_.[[GeneratedLine]], and _state_.[[MappingIndex]]. 1. Let _decodedMapping_ be a new DecodedMappingRecord { [[GeneratedPosition]]: _generatedPosition_, [[OriginalPosition]]: _originalPosition_, [[Name]]: _name_, [[IsRangeMapping]]: _isRangeMapping_ }. 1. Append _decodedMapping_ to _mappings_. 1. Set _state_.[[MappingIndex]] to _state_.[[MappingIndex]] + 1. @@ -1220,7 +1219,7 @@
    1. Perform DecodeRangeMappingsField of |RangeMapping| with arguments _state_ and _rangeMappings_. - 1. Perform DecodeRangeMappingsField of |RangeMappingList| with arguments _state_, _rangeMappings_. + 1. Perform DecodeRangeMappingsField of |RangeMappingList| with arguments _state_ and _rangeMappings_. RangeMapping : @@ -1239,12 +1238,13 @@

    DecodeRangeMappings ( - _rawRangeMappings_: a String, + _rawRangeMappings_: a String or *null*, ): a List of Decoded Range Mapping Offset Records

    1. Let _rangeMappings_ be a new empty List. + 1. If _rawRangeMappings_ is *null*, return _rangeMappings_. 1. Let _rangeMappingsNode_ be the root Parse Node when parsing _rawRangeMappings_ using |RangeMappingsField| as the goal symbol. 1. If parsing failed, then 1. Optionally report an error. From 1f349be6cfe068a5526f580a540fa083bac93b02 Mon Sep 17 00:00:00 2001 From: Asumu Takikawa Date: Fri, 14 Nov 2025 15:11:54 -0800 Subject: [PATCH 3/4] Range mappings: refactor decoding out of mapping decoding (#235) * Refactor range mapping decoding based on feedback * Range mapping decoding happens separate of and after mapping decoding now * Mappings are updated in-place to add range mapping info * Continue if mapping is NOT-FOUND in range mapping update --- spec.emu | 84 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 50 insertions(+), 34 deletions(-) diff --git a/spec.emu b/spec.emu index e74d7e3..2a6da1e 100644 --- a/spec.emu +++ b/spec.emu @@ -684,9 +684,10 @@ 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. Let _rangeMappingsField_ be GetOptionalString(_json_, *"rangeMappings"*). 1. Let _rangeMappings_ be DecodeRangeMappings(_rangeMappingsField_). - 1. Let _mappings_ be DecodeMappings(_mappingsField_, _namesField_, _sources_, _rangeMappings_). + 1. Perform UpdateMappingsForRangeMappings(_mappings_, _rangeMappings_). 1. [declared="a,b"] Sort _mappings_ in ascending order, with a Decoded Mapping Record _a_ being less than a Decoded Mapping Record _b_ if ComparePositions(_a_.[[GeneratedPosition]], _b_.[[GeneratedPosition]]) is ~lesser~. 1. Return the Decoded Source Map Record { [[File]]: _fileField_, [[Sources]]: _sources_, [[Mappings]]: _mappings_ }. @@ -921,10 +922,6 @@ [[NameIndex]] a non-negative integer - - [[MappingIndex]] - a non-negative integer - @@ -935,7 +932,6 @@ _mappings_: a List of Decoded Mapping Records, _names_: a List of Strings, _sources_: a List of Decoded Source Records, - _rangeMappings_: a List of of Decoded Range Mapping Offset Records, )
    @@ -944,11 +940,10 @@ Line `;` LineList
    - 1. Perform DecodeMappingsField of |Line| with arguments _state_, _mappings_, _names_, and _sources_ and _rangeMappings_. + 1. Perform DecodeMappingsField of |Line| with arguments _state_, _mappings_, _names_ and _sources_. 1. Set _state_.[[GeneratedLine]] to _state_.[[GeneratedLine]] + 1. 1. Set _state_.[[GeneratedColumn]] to 0. - 1. Set _state_.[[MappingIndex]] to 0. - 1. Perform DecodeMappingsField of |LineList| with arguments _state_, _mappings_, _names_, and _sources_ and _rangeMappings_. + 1. Perform DecodeMappingsField of |LineList| with arguments _state_, _mappings_, _names_ and _sources_. Line : [empty] @@ -961,36 +956,35 @@ Mapping `,` MappingList - 1. Perform DecodeMappingsField of |Mapping| with arguments _state_, _mappings_, _names_, and _sources_ and _rangeMappings_. - 1. Perform DecodeMappingsField of |MappingList| with arguments _state_, _mappings_, _names_, and _sources_ and _rangeMappings_. + 1. Perform DecodeMappingsField of |Mapping| with arguments _state_, _mappings_, _names_ and _sources_. + 1. Perform DecodeMappingsField of |MappingList| with arguments _state_, _mappings_, _names_ and _sources_. Mapping : GeneratedColumn - 1. Perform DecodeMappingsField of |GeneratedColumn| with arguments _state_, _mappings_, _names_, and _sources_ and _rangeMappings_. + 1. Perform DecodeMappingsField of |GeneratedColumn| with arguments _state_, _mappings_, _names_ and _sources_. 1. If _state_.[[GeneratedColumn]] < 0, then 1. Optionally report an error. 1. Return. 1. Let _position_ be a new Position Record { [[Line]]: _state_.[[GeneratedLine]], [[Column]]: _state_.[[GeneratedColumn]] }. 1. Let _decodedMapping_ be a new DecodedMappingRecord { [[GeneratedPosition]]: _position_, [[OriginalPosition]]: *null*, [[Name]]: *null*, [[IsRangeMapping]]: *false* }. 1. Append _decodedMapping_ to _mappings_. - 1. Set _state_.[[MappingIndex]] to _state_.[[MappingIndex]] + 1. Mapping : GeneratedColumn OriginalSource OriginalLine OriginalColumn Name? - 1. Perform DecodeMappingsField of |GeneratedColumn| with arguments _state_, _mappings_, _names_, and _sources_ and _rangeMappings_. + 1. Perform DecodeMappingsField of |GeneratedColumn| with arguments _state_, _mappings_, _names_ and _sources_. 1. If _state_.[[GeneratedColumn]] < 0, then 1. Optionally report an error. 1. Return. 1. Let _generatedPosition_ be a new Position Record { [[Line]]: _state_.[[GeneratedLine]], [[Column]]: _state_.[[GeneratedColumn]] }. - 1. Perform DecodeMappingsField of |OriginalSource| with arguments _state_, _mappings_, _names_, and _sources_ and _rangeMappings_. - 1. Perform DecodeMappingsField of |OriginalLine| with arguments _state_, _mappings_, _names_, and _sources_ and _rangeMappings_. - 1. Perform DecodeMappingsField of |OriginalColumn| with arguments _state_, _mappings_, _names_, and _sources_ and _rangeMappings_. + 1. Perform DecodeMappingsField of |OriginalSource| with arguments _state_, _mappings_, _names_ and _sources_. + 1. Perform DecodeMappingsField of |OriginalLine| with arguments _state_, _mappings_, _names_ and _sources_. + 1. Perform DecodeMappingsField of |OriginalColumn| with arguments _state_, _mappings_, _names_ and _sources_. 1. If _state_.[[SourceIndex]] < 0 or _state_.[[SourceIndex]] ≥ the number of elements of _sources_ or _state_.[[OriginalLine]] < 0 or _state_.[[OriginalColumn]] < 0, then 1. Optionally report an error. 1. Let _originalPosition_ be *null*. @@ -998,13 +992,11 @@ 1. Let _originalPosition_ be a new Original Position Record { [[Source]]: _sources_[_state_.[[SourceIndex]]], [[Line]]: _state_.[[OriginalLine]], [[Column]]: _state_.[[OriginalColumn]] }. 1. Let _name_ be *null*. 1. If |Name| is present, then - 1. Perform DecodeMappingsField of |Name| with arguments _state_, _mappings_, _names_, and _sources_ and _rangeMappings_. + 1. Perform DecodeMappingsField of |Name| with arguments _state_, _mappings_, _names_ and _sources_. 1. If _state_.[[NameIndex]] < 0 or _state_.[[NameIndex]] ≥ the number of elements of _names_, optionally report an error. 1. Else, set _name_ to _names_[_state_.[[NameIndex]]]. - 1. Let _isRangeMapping_ be the result of performing LookupRangeMapping with arguments _rangeMappings_, _state_.[[GeneratedLine]], and _state_.[[MappingIndex]]. - 1. Let _decodedMapping_ be a new DecodedMappingRecord { [[GeneratedPosition]]: _generatedPosition_, [[OriginalPosition]]: _originalPosition_, [[Name]]: _name_, [[IsRangeMapping]]: _isRangeMapping_ }. + 1. Let _decodedMapping_ be a new DecodedMappingRecord { [[GeneratedPosition]]: _generatedPosition_, [[OriginalPosition]]: _originalPosition_, [[Name]]: _name_, [[IsRangeMapping]]: *false* }. 1. Append _decodedMapping_ to _mappings_. - 1. Set _state_.[[MappingIndex]] to _state_.[[MappingIndex]] + 1. GeneratedColumn : @@ -1055,7 +1047,6 @@ _rawMappings_: a String, _names_: a List of Strings, _sources_: a List of Decoded Source Records, - _rangeMappings_: a List of Decoded Range Mapping Offset Records, ): a List of Decoded Mapping Record
    @@ -1066,7 +1057,7 @@ 1. Optionally report an error. 1. Return _mappings_. 1. Let _state_ be a new Decode Mapping State Record with all fields set to 0. - 1. Perform DecodeMappingsField of _mappingsNode_ with arguments _state_, _mappings_, _names_, and _sources_ and _rangeMappings_. + 1. Perform DecodeMappingsField of _mappingsNode_ with arguments _state_, _mappings_, _names_ and _sources_. 1. Return _mappings_. @@ -1255,21 +1246,46 @@ - +

    - LookupRangeMapping ( - _rangeMappings_: a List of Decoded Range Mapping Offset Records, - _generatedLine_: an integral Number, - _mappingIndex_: an integral Number, - ): a Boolean + UpdateMappingsForRangeMappings ( + _mappings_: a List of Decoded Mapping Records, + _rangeMappingsOffsets_: a List of Decoded Range Mapping Offset Records, + ): ~unused~

    - 1. Let _rangeMappingOffset_ be a new Decoded Range Mapping Offset Record { [[GeneratedLine]] : _generatedLine_, [[MappingIndex]]: _mappingIndex_ }. - 1. If _rangeMappingOffset_ is an element of _rangeMappings_, then - 1. Return *true*. - 1. Else, - 1. Return *false*. + 1. For each Decoded Range Mapping Offset Record _rangeMappingOffset_ of _rangeMappingsOffsets_, do + 1. Let _mapping_ be the result of FindMappingForRangeMappingOffset(_mappings_, _rangeMappingOffset_). + 1. If _mapping_ is ~not-found~, then + 1. Optionally report an error. + 1. Else, + 1. If _mapping_.[[OriginalPosition]] is *null*, optionally report an error. + 1. Assert: _mapping_.[[IsRangeMapping]] is *false*. + 1. Set _mapping_.[[IsRangeMapping]] to *true*. + +
    + + +

    + FindMappingForRangeMappingOffset ( + _mappings_: a List of Decoded Mapping Records, + _offset_: a Decoded Range Mapping Offset Record, + ): a Decoded Mapping Record or ~not-found~ +

    +
    + + 1. Let _currentLine_ be *null*. + 1. Let _currentIndex_ be 0. + 1. For each Decoded Mapping Record _mapping_ of _mappings_, do + 1. If _currentLine_ ≠ _mapping_.[[GeneratedLine]], then + 1. Set _currentLine_ to _mapping_.[[GeneratedLine]]. + 1. Set _currentIndex_ to 0. + 1. Else, + 1. Set _currentIndex_ to _currentIndex_ + 1. + 1. If _currentLine_ = _offset_.[[GeneratedLine]] and _currentIndex_ = _offset_.[[MappingIndex]], then + 1. Return _mapping_. + 1. Return ~not-found~.
    From cd34a7821ffb8cefd845ee83f090d7987efb03da Mon Sep 17 00:00:00 2001 From: Asumu Takikawa Date: Wed, 15 Apr 2026 09:28:51 -0700 Subject: [PATCH 4/4] Range mappings: Change index encoding to start at 0 (#252) * Change range mapping index encoding to start at 0 Currently "BB" means the first and second mappings are range mappings. Instead, we'll have "AB" encode the same. "BA" will be an (optional) error because a duplicate index is encoded. * Fix detection of duplicate range mapping offsets Disallows a range mapping string like "AA" that wasn't covered by the previous attempt. * Add missing empty RangeMappingLine case * Minor fix: replace not equal sign with "is not" --- spec.emu | 45 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/spec.emu b/spec.emu index 2a6da1e..f39b635 100644 --- a/spec.emu +++ b/spec.emu @@ -572,7 +572,7 @@ "sourcesContent": [null, null], "names": ["src", "maps", "are", "fun"], "mappings": "A,AAAB;;ABCDE", - "rangeMappings": "C;;B", + "rangeMappings": "B;;A", "ignoreList": [0] } @@ -1160,7 +1160,29 @@ -

    A Decode Range Mappings State Record has the same fields as a Decoded Range Mapping Offset Record.

    +

    A Decode Range Mappings State Record has the following fields.

    + + + + + + + + + + + + + + + + +
    + Field Name + + Value Type +
    [[GeneratedLine]]a non-negative integer
    [[MappingIndex]]a non-negative integer or ~none~
    +

    Range mappings grammar

    @@ -1201,9 +1223,15 @@ 1. Perform DecodeRangeMappingsField of |RangeMappingLine| with arguments _state_ and _rangeMappings_. 1. Set _state_.[[GeneratedLine]] to _state_.[[GeneratedLine]] + 1. - 1. Set _state_.[[MappingIndex]] to 0. + 1. Set _state_.[[MappingIndex]] to ~none~. 1. Perform DecodeRangeMappingsField of |RangeMappingLineList| with arguments _state_ and _rangeMappings_. + + RangeMappingLine : [empty] + + + 1. Return. + RangeMappingList : RangeMapping RangeMappingList @@ -1218,10 +1246,13 @@ 1. Let _relativeIndex_ be the VLQUnsignedValue of |Vlq|. - 1. If _relativeIndex_ is 0, then + 1. If _relativeIndex_ = 0 and _state_.[[MappingIndex]] is not ~none~, then 1. Optionally report an error. - 1. Set _state_.[[MappingIndex]] to _state_.[[MappingIndex]] + _relativeIndex_. - 1. Let _rangeMappingOffset_ be a new Decoded Range Mapping Offset Record { [[GeneratedLine]]: _state_.[[GeneratedLine]], [[MappingIndex]]: _state_.[[MappingIndex]] - 1 }. + 1. If _state_.[[MappingIndex]] is ~none~, then + 1. Set _state_.[[MappingIndex]] to _relativeIndex_. + 1. Else, + 1. Set _state_.[[MappingIndex]] to _state_.[[MappingIndex]] + _relativeIndex_. + 1. Let _rangeMappingOffset_ be a new Decoded Range Mapping Offset Record { [[GeneratedLine]]: _state_.[[GeneratedLine]], [[MappingIndex]]: _state_.[[MappingIndex]] }. 1. Append _rangeMappingOffset_ to _rangeMappings_.
    @@ -1240,7 +1271,7 @@ 1. If parsing failed, then 1. Optionally report an error. 1. Return _rangeMappings_. - 1. Let _state_ be a new Decode Range Mappings State Record with all fields set to 0. + 1. Let _state_ be a new Decode Range Mappings State Record { [[GeneratedLine]]: 0, [[MappingIndex]]: ~none~ }. 1. Perform DecodeRangeMappingsField of _rangeMappingsNode_ with arguments _state_ and _rangeMappings_. 1. Return _rangeMappings_.