From 17b4867a351ffe057b5499af928b66d02bccdf64 Mon Sep 17 00:00:00 2001 From: Asumu Takikawa Date: Fri, 27 Sep 2024 14:05:07 -0700 Subject: [PATCH 01/11] Add a decoding algorithm for index maps --- source-map.bs | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/source-map.bs b/source-map.bs index 8794776..01e8464 100644 --- a/source-map.bs +++ b/source-map.bs @@ -42,6 +42,7 @@ spec:url; type:dfn; for:/; text:url spec:infra; type:dfn; text:list for:list; text:for each + for:list; text:is not empty
 urlPrefix:https://tc39.es/ecma262/#; type:dfn; spec:ECMA-262
@@ -363,7 +364,8 @@ following steps:
 1. Let |jsonMap| be the result of [=parse a JSON string to an Infra value|parsing a JSON string to
     an Infra value=] |str|.
 1. If |jsonMap| is not a [=/map=], report an error and abort these steps.
-1. [=Decode a source map=] given |jsonMap| and |baseURL|, and return its result if any.
+1. If |jsonMap|[`"sections"`] [=map/exists=], [=decode an index source map=] given |jsonMap| and |baseURL|, and return its result if any.
+1. Otherwise, [=decode a source map=] given |jsonMap| and |baseURL|, and return its result if any.
 
 To decode a source map given a [=string=]-keyed [=/map=] |jsonMap| and a [=/URL=]
 |baseURL|, run the following steps:
@@ -797,6 +799,68 @@ Section objects have the following fields:
 The sections shall be sorted by starting position and the represented sections
 shall not overlap.
 
+## Decoding an Index Map ## {#decoding-index-map}
+
+To decode an index source map given a [=string=]-keyed [=/map=] |jsonMap| and a [=/URL=]
+|baseURL|, run the following steps:
+1. 

Assert: |jsonMap|[`"sections"`] [=map/exists=].

+1. If |jsonMap|[`"sections"`] is not a [=list=], report an error. +1. If |jsonMap|[`"version"`] does not [=map/exist=] or |jsonMap|[`"version"`] is not 3, + [=optionally report an error=]. +1. Let |sourceMap| be a new [=decoded source map=]. +1. Set |sourceMap|'s [=decoded source map/file=] to [=optionally get a string=] `"file"` from |jsonMap|. +1. Let |previousOffset| be null. +1. Let |previousLastMapping| be null. +1. [=For each=] |section| of |jsonMap|[`"sections"`]: + 1. If |section| is not a [=/map=], [=optionally report an error=] and continue with the next iteration. + 1. If |section|[`"offset"`] does not [=map/exist=], then report an error. + 1. Let |offsetLine| be |section|[`"offset"`][`"line"`]. + 1. Let |offsetColumn| be |section|[`"offset"`][`"column"`]. + 1. If |offsetLine| is not a number, [=optionally report an error=]. + 1. If |offsetColumn| is not a number, [=optionally report an error=]. + 1. If |previousOffset| is not null, + 1. If |previousLastMapping| is not null, + 1. If |offsetLine| is less than |previousLastMapping|'s [=decoded mapping/generatedLine=], [=optionally report an error=]. + 1. If |offsetLine| is equal to |previousLastMapping|'s [=decoded mapping/generatedLine=] and |offsetColumn| is less than |previousLastMapping|'s [=decoded mapping/generatedColumn=], [=optionally report an error=]. + 1. Otherwise, + 1. If |offsetLine| is less than |previousOffset|[`"line"`], [=optionally report an error=]. + 1. If |offsetLine| is equal to |previousOffset|[`"line"`] and |offsetColumn| is less than |previousOffset|[`"column"`], [=optionally report an error=]. + + Note: This part of the decoding algorithm checks that index source map sections do not overlap. While it is + expected that generators should not produce index source maps with overlapping sections, source map + consumers may choose instead to only check the simpler condition that the sections are ordered and therefore + that offsets appear in increasing order. + + 1. If |section|[`"map"`] does not [=map/exist=], then report an error. + 1. Let |decodedSection| be the result of [=decoding a source map=] given |section|[`"map"`] and |baseURL|. + 1. If the previous step reported an error, [=optionally report an error=] and continue with the next iteration. + 1. Set |sourceMap|'s [=decoded source map/sources=] to the result of [=list/extending=] |sourceMap|'s [=decoded source map/sources=] with |decodedSection|'s [=decoded source map/sources=]. + 1. Let |offsetMappings| be a new [=list=]. + 1. [=For each=] |mapping| of |decodedSection|'s [=decoded source map/mappings=]: + 1. Let |offsetMapping| be a new [=decoded mapping=]. + 1. Set |offsetMapping|'s [=decoded mapping/generatedLine=] to |mapping|'s [=decoded mapping/generatedLine=] + |offsetLine|. + 1. Set |offsetMapping|'s [=decoded mapping/generatedColumn=] to |mapping|'s [=decoded mapping/generatedColumn=] + |offsetColumn|. + 1. Set |offsetMapping|'s [=decoded mapping/originalSource=] to |mapping|'s [=decoded mapping/originalSource=]. + 1. Set |offsetMapping|'s [=decoded mapping/originalLine=] to |mapping|'s [=decoded mapping/originalLine=]. + 1. Set |offsetMapping|'s [=decoded mapping/originalColumn=] to |mapping|'s [=decoded mapping/originalColumn=]. + 1. Set |offsetMapping|'s [=decoded mapping/name=] to |mapping|'s [=decoded mapping/name=]. + 1. [=list/Append=] |offsetMapping| to |offsetMappings|. + 1. Set |sourceMap|'s [=decoded source map/mappings=] to the result of [=list/extending=] |sourceMap|'s [=decoded source map/mappings=] with |offsetMappings|. + 1. Set |previousOffset| to |section|[`"offset"`]. + 1. Let |sortedMappings| be the result of [=list/sorting=] |offsetMappings| in ascending order, with an item |a| being less than |b| if |a| is [=generated position less than=] |b|. + 1. Set |previousLastMapping| to the last item of |sortedMappings| if |sortedMappings| [=is not empty=] and to null otherwise. + + Note: See the above note about section overlap and order. These last two steps of storing the last mapping of each + section are only necessary to enforce the conditions concerning section overlap. + +1. Return |sourceMap|. + +A [=decoded mapping=] |a| is generated position less than a [=decoded mapping=] b if the following steps return true: + +1. If |a|'s [=decoded mapping/generatedLine=] is less than |b|'s [=decoded mapping/generatedLine=], return true. +1. If |a|'s [=decoded mapping/generatedLine=] is equal to |b|'s [=decoded mapping/generatedLine=] and |a|'s [=decoded mapping/generatedColumn=] is less than |b|'s [=decoded mapping/generatedColumn=], return true. +1. Otherwise, return false. + Retrieving source maps {#linking-and-fetching} ======================================================== From 5800e4c92f26030fc91fef2ad36a2a6719e3c1bd Mon Sep 17 00:00:00 2001 From: Asumu Takikawa Date: Fri, 27 Sep 2024 17:00:45 -0700 Subject: [PATCH 02/11] Index map algorithm: fix generatedColumn on lines after the first --- source-map.bs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source-map.bs b/source-map.bs index 01e8464..86ccc61 100644 --- a/source-map.bs +++ b/source-map.bs @@ -836,10 +836,13 @@ To decode an index source map given a [=string=]-keyed [=/map= 1. If the previous step reported an error, [=optionally report an error=] and continue with the next iteration. 1. Set |sourceMap|'s [=decoded source map/sources=] to the result of [=list/extending=] |sourceMap|'s [=decoded source map/sources=] with |decodedSection|'s [=decoded source map/sources=]. 1. Let |offsetMappings| be a new [=list=]. + 1. Let |firstLine| be null. 1. [=For each=] |mapping| of |decodedSection|'s [=decoded source map/mappings=]: 1. Let |offsetMapping| be a new [=decoded mapping=]. 1. Set |offsetMapping|'s [=decoded mapping/generatedLine=] to |mapping|'s [=decoded mapping/generatedLine=] + |offsetLine|. - 1. Set |offsetMapping|'s [=decoded mapping/generatedColumn=] to |mapping|'s [=decoded mapping/generatedColumn=] + |offsetColumn|. + 1. If |firstLine| is null, set |firstLine| to |offsetMapping|'s [=decoded mapping/generatedLine=]. + 1. If |offsetMapping|'s [=decoded mapping/generatedLine=] is equal to |firstLine|, set |offsetMapping|'s [=decoded mapping/generatedColumn=] to |mapping|'s [=decoded mapping/generatedColumn=] + |offsetColumn|. + 1. Otherwise, set |offsetMapping|'s [=decoded mapping/generatedColumn=] to |mapping|'s [=decoded mapping/generatedColumn=]. 1. Set |offsetMapping|'s [=decoded mapping/originalSource=] to |mapping|'s [=decoded mapping/originalSource=]. 1. Set |offsetMapping|'s [=decoded mapping/originalLine=] to |mapping|'s [=decoded mapping/originalLine=]. 1. Set |offsetMapping|'s [=decoded mapping/originalColumn=] to |mapping|'s [=decoded mapping/originalColumn=]. From d0e802e1590b09b766e12ce1233f34933e87dc4a Mon Sep 17 00:00:00 2001 From: Asumu Takikawa Date: Sat, 5 Oct 2024 13:06:25 -0700 Subject: [PATCH 03/11] Fix uses of "extend" (it's in-place not functional) --- source-map.bs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source-map.bs b/source-map.bs index 86ccc61..b782035 100644 --- a/source-map.bs +++ b/source-map.bs @@ -834,7 +834,7 @@ To decode an index source map given a [=string=]-keyed [=/map= 1. If |section|[`"map"`] does not [=map/exist=], then report an error. 1. Let |decodedSection| be the result of [=decoding a source map=] given |section|[`"map"`] and |baseURL|. 1. If the previous step reported an error, [=optionally report an error=] and continue with the next iteration. - 1. Set |sourceMap|'s [=decoded source map/sources=] to the result of [=list/extending=] |sourceMap|'s [=decoded source map/sources=] with |decodedSection|'s [=decoded source map/sources=]. + 1. [=list/Extend=] |sourceMap|'s [=decoded source map/sources=] with |decodedSection|'s [=decoded source map/sources=]. 1. Let |offsetMappings| be a new [=list=]. 1. Let |firstLine| be null. 1. [=For each=] |mapping| of |decodedSection|'s [=decoded source map/mappings=]: @@ -848,7 +848,7 @@ To decode an index source map given a [=string=]-keyed [=/map= 1. Set |offsetMapping|'s [=decoded mapping/originalColumn=] to |mapping|'s [=decoded mapping/originalColumn=]. 1. Set |offsetMapping|'s [=decoded mapping/name=] to |mapping|'s [=decoded mapping/name=]. 1. [=list/Append=] |offsetMapping| to |offsetMappings|. - 1. Set |sourceMap|'s [=decoded source map/mappings=] to the result of [=list/extending=] |sourceMap|'s [=decoded source map/mappings=] with |offsetMappings|. + 1. [=list/Extend=] |sourceMap|'s [=decoded source map/mappings=] with |offsetMappings|. 1. Set |previousOffset| to |section|[`"offset"`]. 1. Let |sortedMappings| be the result of [=list/sorting=] |offsetMappings| in ascending order, with an item |a| being less than |b| if |a| is [=generated position less than=] |b|. 1. Set |previousLastMapping| to the last item of |sortedMappings| if |sortedMappings| [=is not empty=] and to null otherwise. From 83b6cc78f6f9ff89af48f85779c0cfca61bcb765 Mon Sep 17 00:00:00 2001 From: Asumu Takikawa Date: Sat, 5 Oct 2024 13:14:23 -0700 Subject: [PATCH 04/11] Address feedback about column offset --- source-map.bs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/source-map.bs b/source-map.bs index b782035..1162ee1 100644 --- a/source-map.bs +++ b/source-map.bs @@ -836,12 +836,10 @@ To decode an index source map given a [=string=]-keyed [=/map= 1. If the previous step reported an error, [=optionally report an error=] and continue with the next iteration. 1. [=list/Extend=] |sourceMap|'s [=decoded source map/sources=] with |decodedSection|'s [=decoded source map/sources=]. 1. Let |offsetMappings| be a new [=list=]. - 1. Let |firstLine| be null. 1. [=For each=] |mapping| of |decodedSection|'s [=decoded source map/mappings=]: 1. Let |offsetMapping| be a new [=decoded mapping=]. 1. Set |offsetMapping|'s [=decoded mapping/generatedLine=] to |mapping|'s [=decoded mapping/generatedLine=] + |offsetLine|. - 1. If |firstLine| is null, set |firstLine| to |offsetMapping|'s [=decoded mapping/generatedLine=]. - 1. If |offsetMapping|'s [=decoded mapping/generatedLine=] is equal to |firstLine|, set |offsetMapping|'s [=decoded mapping/generatedColumn=] to |mapping|'s [=decoded mapping/generatedColumn=] + |offsetColumn|. + 1. If |offsetMapping|'s [=decoded mapping/generatedLine=] is equal to 1, set |offsetMapping|'s [=decoded mapping/generatedColumn=] to |mapping|'s [=decoded mapping/generatedColumn=] + |offsetColumn|. 1. Otherwise, set |offsetMapping|'s [=decoded mapping/generatedColumn=] to |mapping|'s [=decoded mapping/generatedColumn=]. 1. Set |offsetMapping|'s [=decoded mapping/originalSource=] to |mapping|'s [=decoded mapping/originalSource=]. 1. Set |offsetMapping|'s [=decoded mapping/originalLine=] to |mapping|'s [=decoded mapping/originalLine=]. From 5c6b0d83134990e4669ce3c1459a4cdc14462a89 Mon Sep 17 00:00:00 2001 From: Asumu Takikawa Date: Fri, 8 Nov 2024 14:20:51 -0800 Subject: [PATCH 05/11] Use set union instead of list extend --- source-map.bs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source-map.bs b/source-map.bs index 1162ee1..8452f7c 100644 --- a/source-map.bs +++ b/source-map.bs @@ -834,7 +834,7 @@ To decode an index source map given a [=string=]-keyed [=/map= 1. If |section|[`"map"`] does not [=map/exist=], then report an error. 1. Let |decodedSection| be the result of [=decoding a source map=] given |section|[`"map"`] and |baseURL|. 1. If the previous step reported an error, [=optionally report an error=] and continue with the next iteration. - 1. [=list/Extend=] |sourceMap|'s [=decoded source map/sources=] with |decodedSection|'s [=decoded source map/sources=]. + 1. Set |sourceMap|'s [=decoded source map/sources=] to the [=set/union=] of |sourceMap|'s [=decoded source map/sources=] and |decodedSection|'s [=decoded source map/sources=]. 1. Let |offsetMappings| be a new [=list=]. 1. [=For each=] |mapping| of |decodedSection|'s [=decoded source map/mappings=]: 1. Let |offsetMapping| be a new [=decoded mapping=]. @@ -846,7 +846,7 @@ To decode an index source map given a [=string=]-keyed [=/map= 1. Set |offsetMapping|'s [=decoded mapping/originalColumn=] to |mapping|'s [=decoded mapping/originalColumn=]. 1. Set |offsetMapping|'s [=decoded mapping/name=] to |mapping|'s [=decoded mapping/name=]. 1. [=list/Append=] |offsetMapping| to |offsetMappings|. - 1. [=list/Extend=] |sourceMap|'s [=decoded source map/mappings=] with |offsetMappings|. + 1. Set |sourceMap|'s [=decoded source map/mappings=] to the [=set/union=] of |sourceMap|'s [=decoded source map/mappings=] and |offsetMappings|. 1. Set |previousOffset| to |section|[`"offset"`]. 1. Let |sortedMappings| be the result of [=list/sorting=] |offsetMappings| in ascending order, with an item |a| being less than |b| if |a| is [=generated position less than=] |b|. 1. Set |previousLastMapping| to the last item of |sortedMappings| if |sortedMappings| [=is not empty=] and to null otherwise. From bcf6e38746893ea6749e0786f9a04c4c2c7de5fd Mon Sep 17 00:00:00 2001 From: Asumu Takikawa Date: Fri, 8 Nov 2024 14:39:46 -0800 Subject: [PATCH 06/11] Editorial: avoid warnings by removing dfns for index map These aren't linked to so they don't need the tags --- source-map.bs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source-map.bs b/source-map.bs index 8452f7c..d0cd39c 100644 --- a/source-map.bs +++ b/source-map.bs @@ -789,11 +789,11 @@ the file format is JSON with a top-level object. It shares the [=json/version=] Section objects have the following fields: -* offset is an object with two fields, `line` and `column`, +* offset is an object with two fields, `line` and `column`, that represent the offset into generated code that the referenced source map represents. -* map is an embedded complete source map object. +* map is an embedded complete source map object. An embedded map does not inherit any values from the containing index map. The sections shall be sorted by starting position and the represented sections From b82928d41d98a755fb557cb3f38208d26a182818 Mon Sep 17 00:00:00 2001 From: Asumu Takikawa Date: Wed, 13 Nov 2024 08:57:16 -0800 Subject: [PATCH 07/11] Address more PR feedback * Fix first line issue * Use extend again for new mappings --- source-map.bs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source-map.bs b/source-map.bs index d0cd39c..e5ff4dc 100644 --- a/source-map.bs +++ b/source-map.bs @@ -839,14 +839,14 @@ To decode an index source map given a [=string=]-keyed [=/map= 1. [=For each=] |mapping| of |decodedSection|'s [=decoded source map/mappings=]: 1. Let |offsetMapping| be a new [=decoded mapping=]. 1. Set |offsetMapping|'s [=decoded mapping/generatedLine=] to |mapping|'s [=decoded mapping/generatedLine=] + |offsetLine|. - 1. If |offsetMapping|'s [=decoded mapping/generatedLine=] is equal to 1, set |offsetMapping|'s [=decoded mapping/generatedColumn=] to |mapping|'s [=decoded mapping/generatedColumn=] + |offsetColumn|. + 1. If |offsetMapping|'s [=decoded mapping/generatedLine=] is equal to 0, set |offsetMapping|'s [=decoded mapping/generatedColumn=] to |mapping|'s [=decoded mapping/generatedColumn=] + |offsetColumn|. 1. Otherwise, set |offsetMapping|'s [=decoded mapping/generatedColumn=] to |mapping|'s [=decoded mapping/generatedColumn=]. 1. Set |offsetMapping|'s [=decoded mapping/originalSource=] to |mapping|'s [=decoded mapping/originalSource=]. 1. Set |offsetMapping|'s [=decoded mapping/originalLine=] to |mapping|'s [=decoded mapping/originalLine=]. 1. Set |offsetMapping|'s [=decoded mapping/originalColumn=] to |mapping|'s [=decoded mapping/originalColumn=]. 1. Set |offsetMapping|'s [=decoded mapping/name=] to |mapping|'s [=decoded mapping/name=]. 1. [=list/Append=] |offsetMapping| to |offsetMappings|. - 1. Set |sourceMap|'s [=decoded source map/mappings=] to the [=set/union=] of |sourceMap|'s [=decoded source map/mappings=] and |offsetMappings|. + 1. [=list/Extend=] |sourceMap|'s [=decoded source map/mappings=] with |offsetMappings|. 1. Set |previousOffset| to |section|[`"offset"`]. 1. Let |sortedMappings| be the result of [=list/sorting=] |offsetMappings| in ascending order, with an item |a| being less than |b| if |a| is [=generated position less than=] |b|. 1. Set |previousLastMapping| to the last item of |sortedMappings| if |sortedMappings| [=is not empty=] and to null otherwise. From e6fb97ae2b392d4a6cafe15062e72ca4893b43a6 Mon Sep 17 00:00:00 2001 From: Asumu Takikawa Date: Wed, 13 Nov 2024 14:19:37 -0800 Subject: [PATCH 08/11] Refactor the overlap check * Check the overlap of ranges {lastFirst, lastPrev} and the {first, last} of the current source map section instead of current more complicated steps. * The overlap check also ensures the order of the ranges, beyond the ordering of the offsets (which itself doesn't guarantee range order) * Some editorial changes for the check --- source-map.bs | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/source-map.bs b/source-map.bs index e5ff4dc..98c54e5 100644 --- a/source-map.bs +++ b/source-map.bs @@ -810,6 +810,7 @@ To decode an index source map given a [=string=]-keyed [=/map= 1. Let |sourceMap| be a new [=decoded source map=]. 1. Set |sourceMap|'s [=decoded source map/file=] to [=optionally get a string=] `"file"` from |jsonMap|. 1. Let |previousOffset| be null. +1. Let |previousFirstMapping| be null. 1. Let |previousLastMapping| be null. 1. [=For each=] |section| of |jsonMap|[`"sections"`]: 1. If |section| is not a [=/map=], [=optionally report an error=] and continue with the next iteration. @@ -819,18 +820,8 @@ To decode an index source map given a [=string=]-keyed [=/map= 1. If |offsetLine| is not a number, [=optionally report an error=]. 1. If |offsetColumn| is not a number, [=optionally report an error=]. 1. If |previousOffset| is not null, - 1. If |previousLastMapping| is not null, - 1. If |offsetLine| is less than |previousLastMapping|'s [=decoded mapping/generatedLine=], [=optionally report an error=]. - 1. If |offsetLine| is equal to |previousLastMapping|'s [=decoded mapping/generatedLine=] and |offsetColumn| is less than |previousLastMapping|'s [=decoded mapping/generatedColumn=], [=optionally report an error=]. - 1. Otherwise, - 1. If |offsetLine| is less than |previousOffset|[`"line"`], [=optionally report an error=]. - 1. If |offsetLine| is equal to |previousOffset|[`"line"`] and |offsetColumn| is less than |previousOffset|[`"column"`], [=optionally report an error=]. - - Note: This part of the decoding algorithm checks that index source map sections do not overlap. While it is - expected that generators should not produce index source maps with overlapping sections, source map - consumers may choose instead to only check the simpler condition that the sections are ordered and therefore - that offsets appear in increasing order. - + 1. If |offsetLine| is less than |previousOffset|[`"line"`], [=optionally report an error=]. + 1. If |offsetLine| is equal to |previousOffset|[`"line"`] and |offsetColumn| is less than |previousOffset|[`"column"`], [=optionally report an error=]. 1. If |section|[`"map"`] does not [=map/exist=], then report an error. 1. Let |decodedSection| be the result of [=decoding a source map=] given |section|[`"map"`] and |baseURL|. 1. If the previous step reported an error, [=optionally report an error=] and continue with the next iteration. @@ -846,13 +837,20 @@ To decode an index source map given a [=string=]-keyed [=/map= 1. Set |offsetMapping|'s [=decoded mapping/originalColumn=] to |mapping|'s [=decoded mapping/originalColumn=]. 1. Set |offsetMapping|'s [=decoded mapping/name=] to |mapping|'s [=decoded mapping/name=]. 1. [=list/Append=] |offsetMapping| to |offsetMappings|. + + Note: Implementations may choose to represent index source map sections without appending the mappings together, + for example, by storing each section separately and conducting a binary search. 1. [=list/Extend=] |sourceMap|'s [=decoded source map/mappings=] with |offsetMappings|. 1. Set |previousOffset| to |section|[`"offset"`]. 1. Let |sortedMappings| be the result of [=list/sorting=] |offsetMappings| in ascending order, with an item |a| being less than |b| if |a| is [=generated position less than=] |b|. - 1. Set |previousLastMapping| to the last item of |sortedMappings| if |sortedMappings| [=is not empty=] and to null otherwise. - - Note: See the above note about section overlap and order. These last two steps of storing the last mapping of each - section are only necessary to enforce the conditions concerning section overlap. + 1. If |previousFirstMapping| and |previousLastMapping| are not null, + 1. If |previousLastMapping| is not [=generated position less than=] the first [=decoded mapping=] of |sortedMappings|, [=optionally report an error=]. + + Note: This part of the decoding algorithm checks that index source map sections are ordered and do not overlap. + While it is expected that generators should not produce index source maps with overlapping sections, source map + consumers may, for example, only check the simpler condition that the section offsets are ordered. + 1. Set |previousFirstMapping| to the first item of |sortedMappings| if |sortedMappings| [=is not empty=]. + 1. Set |previousLastMapping| to the last item of |sortedMappings| if |sortedMappings| [=is not empty=]. 1. Return |sourceMap|. From 57b3f37e4f727307f5430c9f67b0834a97599d95 Mon Sep 17 00:00:00 2001 From: Asumu Takikawa Date: Wed, 13 Nov 2024 14:38:06 -0800 Subject: [PATCH 09/11] Change offset checks to "integral Number" Also set a default value so the algorithm continues --- source-map.bs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source-map.bs b/source-map.bs index 98c54e5..d253043 100644 --- a/source-map.bs +++ b/source-map.bs @@ -92,6 +92,7 @@ urlPrefix:https://tc39.es/ecma262/#; type:dfn; spec:ECMA-262 url:prod-VariableStatement; text:VariableStatement url:sec-parameter-lists; text:Parameter List url:sec-syntactic-grammar; text:Syntactic Grammar + url:integral-number; text:integral Number urlPrefix:https://webassembly.github.io/spec/core/; type:dfn; spec:wasm url:binary/modules.html#binary-customsec; text:custom section @@ -817,8 +818,8 @@ To decode an index source map given a [=string=]-keyed [=/map= 1. If |section|[`"offset"`] does not [=map/exist=], then report an error. 1. Let |offsetLine| be |section|[`"offset"`][`"line"`]. 1. Let |offsetColumn| be |section|[`"offset"`][`"column"`]. - 1. If |offsetLine| is not a number, [=optionally report an error=]. - 1. If |offsetColumn| is not a number, [=optionally report an error=]. + 1. If |offsetLine| is not an [=integral Number=], [=optionally report an error=] and set |offsetLine| to 0. + 1. If |offsetColumn| is not an [=integral Number=], [=optionally report an error=] and set |offsetColumn| to 0. 1. If |previousOffset| is not null, 1. If |offsetLine| is less than |previousOffset|[`"line"`], [=optionally report an error=]. 1. If |offsetLine| is equal to |previousOffset|[`"line"`] and |offsetColumn| is less than |previousOffset|[`"column"`], [=optionally report an error=]. From d90fcb00e08399aff3a9063a936e04dcd1f8f9ce Mon Sep 17 00:00:00 2001 From: Asumu Takikawa Date: Tue, 10 Dec 2024 13:36:56 -0800 Subject: [PATCH 10/11] Add additional constraint to ensure mappings stay between offsets An implementation may do a generated->original lookup in an index map by first searching through the sections by their offset and looking in only the section where the position is within the range {offset, nextOffset}. This is only valid if all mappings in a given section are contained in that range, rather than going into the next section's range. Also simplifies the check by removing the firstPreviousMapping variable and its use. The algorithm checks that the (1) the offsets are ordered (in 8g) (2) the last mapping of the previous section is before the current offset (in 8h) (3) it doesn't check that the first mapping is after the current offset because that is true by construction --- source-map.bs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/source-map.bs b/source-map.bs index d253043..fc8435d 100644 --- a/source-map.bs +++ b/source-map.bs @@ -811,7 +811,6 @@ To decode an index source map given a [=string=]-keyed [=/map= 1. Let |sourceMap| be a new [=decoded source map=]. 1. Set |sourceMap|'s [=decoded source map/file=] to [=optionally get a string=] `"file"` from |jsonMap|. 1. Let |previousOffset| be null. -1. Let |previousFirstMapping| be null. 1. Let |previousLastMapping| be null. 1. [=For each=] |section| of |jsonMap|[`"sections"`]: 1. If |section| is not a [=/map=], [=optionally report an error=] and continue with the next iteration. @@ -823,6 +822,13 @@ To decode an index source map given a [=string=]-keyed [=/map= 1. If |previousOffset| is not null, 1. If |offsetLine| is less than |previousOffset|[`"line"`], [=optionally report an error=]. 1. If |offsetLine| is equal to |previousOffset|[`"line"`] and |offsetColumn| is less than |previousOffset|[`"column"`], [=optionally report an error=]. + 1. If |previousLastMapping| is not null, + 1. If |offsetLine| is less than |previousLastMapping|'s [=decoded mapping/generatedLine=], [=optionally report an error=]. + 1. If |offsetLine| is equal to |previousLastMapping|'s [=decoded mapping/generatedLine=] and |offsetColumn| is less than |previousLastMapping|'s [=decoded mapping/generatedColumn=], [=optionally report an error=]. + + Note: This part of the decoding algorithm checks that index source map sections are ordered and do not overlap. + While it is expected that generators should not produce index source maps with overlapping sections, source map + consumers may, for example, only check the simpler condition that the section offsets are ordered. 1. If |section|[`"map"`] does not [=map/exist=], then report an error. 1. Let |decodedSection| be the result of [=decoding a source map=] given |section|[`"map"`] and |baseURL|. 1. If the previous step reported an error, [=optionally report an error=] and continue with the next iteration. @@ -844,15 +850,7 @@ To decode an index source map given a [=string=]-keyed [=/map= 1. [=list/Extend=] |sourceMap|'s [=decoded source map/mappings=] with |offsetMappings|. 1. Set |previousOffset| to |section|[`"offset"`]. 1. Let |sortedMappings| be the result of [=list/sorting=] |offsetMappings| in ascending order, with an item |a| being less than |b| if |a| is [=generated position less than=] |b|. - 1. If |previousFirstMapping| and |previousLastMapping| are not null, - 1. If |previousLastMapping| is not [=generated position less than=] the first [=decoded mapping=] of |sortedMappings|, [=optionally report an error=]. - - Note: This part of the decoding algorithm checks that index source map sections are ordered and do not overlap. - While it is expected that generators should not produce index source maps with overlapping sections, source map - consumers may, for example, only check the simpler condition that the section offsets are ordered. - 1. Set |previousFirstMapping| to the first item of |sortedMappings| if |sortedMappings| [=is not empty=]. 1. Set |previousLastMapping| to the last item of |sortedMappings| if |sortedMappings| [=is not empty=]. - 1. Return |sourceMap|. A [=decoded mapping=] |a| is generated position less than a [=decoded mapping=] b if the following steps return true: From 0d6ffb278dacb7191608298c308ecdadb9dfd287 Mon Sep 17 00:00:00 2001 From: Asumu Takikawa Date: Tue, 10 Dec 2024 15:14:45 -0800 Subject: [PATCH 11/11] Lowercase the title to match recent changes --- source-map.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source-map.bs b/source-map.bs index fc8435d..9f73890 100644 --- a/source-map.bs +++ b/source-map.bs @@ -800,7 +800,7 @@ Section objects have the following fields: The sections shall be sorted by starting position and the represented sections shall not overlap. -## Decoding an Index Map ## {#decoding-index-map} +## Decoding an index map ## {#decoding-index-map} To decode an index source map given a [=string=]-keyed [=/map=] |jsonMap| and a [=/URL=] |baseURL|, run the following steps: