Skip to content

Commit 4ee031a

Browse files
authored
Range Mappings: Allow multi-line ranges
This update changes the semantics of the Range Mapping such that it applies to character sequences that include newlines. The encoding format/syntax is unchanged. This is a purely semantic change. It is motivated by cases where most or all of a file contents could be expressed via a single range mapping, e.g. to concisely produce an identity range mapping. Source: https://issues.chromium.org/issues/364917746
1 parent 5bf2e0e commit 4ee031a

File tree

1 file changed

+18
-15
lines changed

1 file changed

+18
-15
lines changed

proposals/range-mappings.md

+18-15
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ Tobias Koppers
1515
## Motiviation
1616

1717
Currently mappings map locations in the source code to other locations in the source code.
18-
This works well when trying to access a location that is defined in the SourceMap, but one looses percision when accessing locations that are not directly defined in the SourceMap.
18+
This works well when trying to access a location that is defined in the SourceMap, but one loses precision when accessing locations that are not directly defined in the SourceMap.
1919
In these cases tools usually fallback to next lower column that is actually mapped in the SourceMap.
20-
So we are either loosing information or we need many mappings in the SourceMap to cover all possible locations.
20+
So we are either losing information or we need many mappings in the SourceMap to cover all possible locations.
2121

2222
These information problem is especially problematic when applying a SourceMap to another SourceMap.
2323
Here we can only use locations that are specified in both SourceMaps. We have to be lucky that locations match up.
@@ -26,7 +26,7 @@ Here we can only use locations that are specified in both SourceMaps. We have to
2626

2727
As an example let's look at a build process when a TypeScript file is converted to JavaScript first and that is minified afterwards.
2828

29-
The TypeScript to JavaScript transformation is mostly keeping code identical, but removing type annotations.
29+
A simplistic TypeScript to JavaScript transformation such as SWC's [`strip_types`](https://play.swc.rs/?version=1.10.7&code=H4sIAAAAAAAAA0WMQQqDMBBF93OKv6wgPYBpu5HewAvEQTA0Tcpkggvx7k2E4OrD%2B4%2FH3qaE0epjemEn4Jdn7xjb6tJnkTQg5O%2B8iLkutc4PmAwVxDEklcwa5cYxB21%2B37TurAJagvdWxROnba6r6gXXqfSgg0hXiRveIqXemT8eTB9GqwAAAA%3D%3D&config=H4sIAAAAAAAAA1VPOw7DIAzdOQXy3KFi6NA79BCIOhERAYQdqSjK3QsJpM1mv4%2Ff8yqkhIkMPOVaxrJEnQjTuReEsmf9KQhwjkgm2chw6yxTpQbtCHdoOxhgnUbk6kJSd6WaA1wIhN3RsNl6O%2BT%2FTBPmmJDoKqxS7UeH10TRUmEO72Un2y%2B179HgAT9RDzsPg6VXd3JaUGxfBMLf3xcBAAA%3D&strip-types=) keeps the runtime code identical, whilst removing type annotations.
3030
Theoretically only a few SourceMap mappings are needs, as most code stays identical.
3131

3232
Minifying is a bigger transformation of the code, which one it's own would result in a lot of SourceMap mappings to be generated.
@@ -40,7 +40,7 @@ The TypeScript SourceMap would behave identical to a SourceMap mapping every sin
4040
## Proposal
4141

4242
Add a boolean flag for each mapping to convert it into a "range mapping".
43-
For a range mapping, tools should assume that every char that follows the mapping (until the next mapping), is mapped to the specified original location plus the offset in the generated code.
43+
For a range mapping, tools should assume that every char (including newlines) that follows the mapping (until the next mapping), is mapped to the specified original location plus the offset in the generated code.
4444
This means all chars in the generated code that is covered by the range mapping, are mapped char by char to the same range in the original code.
4545
(Usually this only makes sense when generated and original are identical for that range)
4646

@@ -49,27 +49,30 @@ This means all chars in the generated code that is covered by the range mapping,
4949
Generated Code:
5050

5151
``` js
52-
console.log("hello world");
52+
console.log(
53+
"hello world");
5354
```
5455

5556
Original Code:
5657

5758
``` js
58-
// Copyright 2023
59-
console.log("hello world");
59+
// Copyright 2023
60+
console.log(
61+
"hello world");
6062
```
6163

6264
With a normal mapping:
6365

6466
```
6567
Source Map:
6668
Generate Line 1 Column 0 -> Original Line 2 Column 2
69+
Generate Line 2 Column 0 -> Original Line 3 Column 0
6770
```
6871

6972
``` js
70-
console.log("hello world");
71-
^ ^ ^
72-
| | + maps to Original Line 2 Column 2
73+
console.log(\n"hello world");
74+
^ ^ ^
75+
| | + maps to Original Line 3 Column 0
7376
| + maps to Original Line 2 Column 2
7477
+ maps to Original Line 2 Column 2
7578
```
@@ -82,17 +85,17 @@ Generate Line 1 Column 0 -> Original Line 2 Column 2 (range mapping)
8285
```
8386

8487
``` js
85-
console.log("hello world");
86-
^ ^ ^
87-
| | + maps to Original Line 2 Column 14
88+
console.log(\n"hello world");
89+
^ ^ ^
90+
| | + maps to Original Line 3 Column 0
8891
| + maps to Original Line 2 Column 10
8992
+ maps to Original Line 2 Column 2
9093
```
9194

9295
### Encoding
9396

9497
To avoid a breaking change to the `mappings` field, a new field named `rangeMappings` is added.
95-
It contains encoded data per line in the generated code.
98+
It contains encoded data per-line in the generated code.
9699
Each line is separated by `;`.
97100
The data contains a bit per mapping in that line.
98101
When the bit is set, the mapping is a range mapping, otherwise it is a normal mapping.
@@ -111,5 +114,5 @@ Line 1: 0b000000 0b000000 0b000001 => the 13th mapping is a range mapping
111114
Line 3: 0b100000 => the 6th mapping is a range mapping
112115
```
113116

114-
> Note: The per line encoding is chosen to make it easier to generate SourceMap line by line.
117+
> Note: The per-line encoding is chosen to make it easier to generate SourceMap line by line.
115118
> It also looks similar to the `mappings` field, so should allow good compression.

0 commit comments

Comments
 (0)