Skip to content

Commit

Permalink
support using decoded sourcemaps from SourceMapGenerator (#5732)
Browse files Browse the repository at this point in the history
Co-authored-by: Conduitry <[email protected]>
  • Loading branch information
milahu and Conduitry authored Nov 30, 2020
1 parent 910348f commit 3d68cea
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 3 deletions.
83 changes: 80 additions & 3 deletions src/compiler/preprocess/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,81 @@ async function replace_async(
return out.concat(final_content);
}

/**
* Convert a preprocessor output and its leading prefix and trailing suffix into StringWithSourceMap
/**
* Import decoded sourcemap from mozilla/source-map/SourceMapGenerator
* Forked from source-map/lib/source-map-generator.js
* from methods _serializeMappings and toJSON.
* We cannot use source-map.d.ts types, because we access hidden properties.
*/
function decoded_sourcemap_from_generator(generator: any) {
let previous_generated_line = 1;
const converted_mappings = [[]];
let result_line;
let result_segment;
let mapping;

const source_idx = generator._sources.toArray()
.reduce((acc, val, idx) => (acc[val] = idx, acc), {});

const name_idx = generator._names.toArray()
.reduce((acc, val, idx) => (acc[val] = idx, acc), {});

const mappings = generator._mappings.toArray();
result_line = converted_mappings[0];

for (let i = 0, len = mappings.length; i < len; i++) {
mapping = mappings[i];

if (mapping.generatedLine > previous_generated_line) {
while (mapping.generatedLine > previous_generated_line) {
converted_mappings.push([]);
previous_generated_line++;
}
result_line = converted_mappings[mapping.generatedLine - 1]; // line is one-based
} else if (i > 0) {
const previous_mapping = mappings[i - 1];
if (
// sorted by selectivity
mapping.generatedColumn === previous_mapping.generatedColumn &&
mapping.originalColumn === previous_mapping.originalColumn &&
mapping.name === previous_mapping.name &&
mapping.generatedLine === previous_mapping.generatedLine &&
mapping.originalLine === previous_mapping.originalLine &&
mapping.source === previous_mapping.source
) {
continue;
}
}
result_line.push([mapping.generatedColumn]);
result_segment = result_line[result_line.length - 1];

if (mapping.source != null) {
result_segment.push(...[
source_idx[mapping.source],
mapping.originalLine - 1, // line is one-based
mapping.originalColumn
]);
if (mapping.name != null) {
result_segment.push(name_idx[mapping.name]);
}
}
}

const map = {
version: generator._version,
sources: generator._sources.toArray(),
names: generator._names.toArray(),
mappings: converted_mappings
};
if (generator._file != null) {
(map as any).file = generator._file;
}
// not needed: map.sourcesContent and map.sourceRoot
return map;
}

/**
* Convert a preprocessor output and its leading prefix and trailing suffix into StringWithSourceMap
*/
function get_replacement(
filename: string,
Expand All @@ -109,6 +182,10 @@ function get_replacement(
if (typeof(decoded_map.mappings) === 'string') {
decoded_map.mappings = decode_mappings(decoded_map.mappings);
}
if ((decoded_map as any)._mappings && decoded_map.constructor.name === 'SourceMapGenerator') {
// import decoded sourcemap from mozilla/source-map/SourceMapGenerator
decoded_map = decoded_sourcemap_from_generator(decoded_map);
}
sourcemap_add_offset(decoded_map, get_location(offset + prefix.length));
}
const processed_with_map = StringWithSourcemap.from_processed(processed.code, decoded_map);
Expand Down Expand Up @@ -164,7 +241,7 @@ export default async function preprocess(

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

Expand Down
25 changes: 25 additions & 0 deletions test/sourcemaps/samples/source-map-generator/_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import MagicString from 'magic-string';
import { SourceMapConsumer, SourceMapGenerator } from 'source-map';

export default {
preprocess: {
style: async ({ content, filename }) => {
const src = new MagicString(content);
const idx = content.indexOf('baritone');
src.overwrite(idx, idx+'baritone'.length, 'bar');

const map = SourceMapGenerator.fromSourceMap(
await new SourceMapConsumer(
// sourcemap must be encoded for SourceMapConsumer
src.generateMap({
source: filename,
hires: true,
includeContent: false
})
)
);

return { code: src.toString(), map };
}
}
};
12 changes: 12 additions & 0 deletions test/sourcemaps/samples/source-map-generator/input.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<h1>Testing Styles</h1>
<h2>Testing Styles 2</h2>
<script>export const b = 2;</script>
<style>
h1 {
--baritone: red;
}
h2 {
--baz: blue;
}
</style>
1 change: 1 addition & 0 deletions test/sourcemaps/samples/source-map-generator/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { test } from '../preprocessed-styles/test';

0 comments on commit 3d68cea

Please sign in to comment.