Skip to content

Commit 3d68cea

Browse files
milahuConduitry
andauthored
support using decoded sourcemaps from SourceMapGenerator (#5732)
Co-authored-by: Conduitry <[email protected]>
1 parent 910348f commit 3d68cea

File tree

4 files changed

+118
-3
lines changed

4 files changed

+118
-3
lines changed

src/compiler/preprocess/index.ts

Lines changed: 80 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,81 @@ async function replace_async(
8383
return out.concat(final_content);
8484
}
8585

86-
/**
87-
* Convert a preprocessor output and its leading prefix and trailing suffix into StringWithSourceMap
86+
/**
87+
* Import decoded sourcemap from mozilla/source-map/SourceMapGenerator
88+
* Forked from source-map/lib/source-map-generator.js
89+
* from methods _serializeMappings and toJSON.
90+
* We cannot use source-map.d.ts types, because we access hidden properties.
91+
*/
92+
function decoded_sourcemap_from_generator(generator: any) {
93+
let previous_generated_line = 1;
94+
const converted_mappings = [[]];
95+
let result_line;
96+
let result_segment;
97+
let mapping;
98+
99+
const source_idx = generator._sources.toArray()
100+
.reduce((acc, val, idx) => (acc[val] = idx, acc), {});
101+
102+
const name_idx = generator._names.toArray()
103+
.reduce((acc, val, idx) => (acc[val] = idx, acc), {});
104+
105+
const mappings = generator._mappings.toArray();
106+
result_line = converted_mappings[0];
107+
108+
for (let i = 0, len = mappings.length; i < len; i++) {
109+
mapping = mappings[i];
110+
111+
if (mapping.generatedLine > previous_generated_line) {
112+
while (mapping.generatedLine > previous_generated_line) {
113+
converted_mappings.push([]);
114+
previous_generated_line++;
115+
}
116+
result_line = converted_mappings[mapping.generatedLine - 1]; // line is one-based
117+
} else if (i > 0) {
118+
const previous_mapping = mappings[i - 1];
119+
if (
120+
// sorted by selectivity
121+
mapping.generatedColumn === previous_mapping.generatedColumn &&
122+
mapping.originalColumn === previous_mapping.originalColumn &&
123+
mapping.name === previous_mapping.name &&
124+
mapping.generatedLine === previous_mapping.generatedLine &&
125+
mapping.originalLine === previous_mapping.originalLine &&
126+
mapping.source === previous_mapping.source
127+
) {
128+
continue;
129+
}
130+
}
131+
result_line.push([mapping.generatedColumn]);
132+
result_segment = result_line[result_line.length - 1];
133+
134+
if (mapping.source != null) {
135+
result_segment.push(...[
136+
source_idx[mapping.source],
137+
mapping.originalLine - 1, // line is one-based
138+
mapping.originalColumn
139+
]);
140+
if (mapping.name != null) {
141+
result_segment.push(name_idx[mapping.name]);
142+
}
143+
}
144+
}
145+
146+
const map = {
147+
version: generator._version,
148+
sources: generator._sources.toArray(),
149+
names: generator._names.toArray(),
150+
mappings: converted_mappings
151+
};
152+
if (generator._file != null) {
153+
(map as any).file = generator._file;
154+
}
155+
// not needed: map.sourcesContent and map.sourceRoot
156+
return map;
157+
}
158+
159+
/**
160+
* Convert a preprocessor output and its leading prefix and trailing suffix into StringWithSourceMap
88161
*/
89162
function get_replacement(
90163
filename: string,
@@ -109,6 +182,10 @@ function get_replacement(
109182
if (typeof(decoded_map.mappings) === 'string') {
110183
decoded_map.mappings = decode_mappings(decoded_map.mappings);
111184
}
185+
if ((decoded_map as any)._mappings && decoded_map.constructor.name === 'SourceMapGenerator') {
186+
// import decoded sourcemap from mozilla/source-map/SourceMapGenerator
187+
decoded_map = decoded_sourcemap_from_generator(decoded_map);
188+
}
112189
sourcemap_add_offset(decoded_map, get_location(offset + prefix.length));
113190
}
114191
const processed_with_map = StringWithSourcemap.from_processed(processed.code, decoded_map);
@@ -164,7 +241,7 @@ export default async function preprocess(
164241

165242
async function preprocess_tag_content(tag_name: 'style' | 'script', preprocessor: Preprocessor) {
166243
const get_location = getLocator(source);
167-
const tag_regex = tag_name == 'style'
244+
const tag_regex = tag_name === 'style'
168245
? /<!--[^]*?-->|<style(\s[^]*?)?(?:>([^]*?)<\/style>|\/>)/gi
169246
: /<!--[^]*?-->|<script(\s[^]*?)?(?:>([^]*?)<\/script>|\/>)/gi;
170247

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import MagicString from 'magic-string';
2+
import { SourceMapConsumer, SourceMapGenerator } from 'source-map';
3+
4+
export default {
5+
preprocess: {
6+
style: async ({ content, filename }) => {
7+
const src = new MagicString(content);
8+
const idx = content.indexOf('baritone');
9+
src.overwrite(idx, idx+'baritone'.length, 'bar');
10+
11+
const map = SourceMapGenerator.fromSourceMap(
12+
await new SourceMapConsumer(
13+
// sourcemap must be encoded for SourceMapConsumer
14+
src.generateMap({
15+
source: filename,
16+
hires: true,
17+
includeContent: false
18+
})
19+
)
20+
);
21+
22+
return { code: src.toString(), map };
23+
}
24+
}
25+
};
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<h1>Testing Styles</h1>
2+
<h2>Testing Styles 2</h2>
3+
<script>export const b = 2;</script>
4+
<style>
5+
h1 {
6+
--baritone: red;
7+
}
8+
9+
h2 {
10+
--baz: blue;
11+
}
12+
</style>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { test } from '../preprocessed-styles/test';

0 commit comments

Comments
 (0)