From 100eba35d9af209f607a932e0efe1ace00bb7ef1 Mon Sep 17 00:00:00 2001 From: dmitrage Date: Tue, 8 Dec 2020 13:30:36 +0300 Subject: [PATCH 01/11] Fix some issues with preprocess source maps --- src/compiler/preprocess/index.ts | 54 +++++++++++++++---- src/compiler/utils/string_with_sourcemap.ts | 43 +++++++++------ .../samples/script-and-style/_config.js | 22 ++++++++ .../samples/script-and-style/input.svelte | 19 +++++++ .../samples/script-and-style/test.js | 17 ++++++ test/sourcemaps/samples/typescript/_config.js | 26 +++++++++ .../samples/typescript/input.svelte | 13 +++++ test/sourcemaps/samples/typescript/test.js | 17 ++++++ 8 files changed, 185 insertions(+), 26 deletions(-) create mode 100644 test/sourcemaps/samples/script-and-style/_config.js create mode 100644 test/sourcemaps/samples/script-and-style/input.svelte create mode 100644 test/sourcemaps/samples/script-and-style/test.js create mode 100644 test/sourcemaps/samples/typescript/_config.js create mode 100644 test/sourcemaps/samples/typescript/input.svelte create mode 100644 test/sourcemaps/samples/typescript/test.js diff --git a/src/compiler/preprocess/index.ts b/src/compiler/preprocess/index.ts index b51b67bb2345..f8e2f95c89f6 100644 --- a/src/compiler/preprocess/index.ts +++ b/src/compiler/preprocess/index.ts @@ -39,6 +39,10 @@ function parse_attributes(str: string) { return attrs; } +function get_file_basename(filename: string) { + return filename.split(/[/\\]/).pop(); +} + interface Replacement { offset: number; length: number; @@ -46,7 +50,7 @@ interface Replacement { } async function replace_async( - filename: string, + file_basename: string, source: string, get_location: ReturnType, re: RegExp, @@ -73,13 +77,13 @@ async function replace_async( )) { // content = unchanged source characters before the replaced segment const content = StringWithSourcemap.from_source( - filename, source.slice(last_end, offset), get_location(last_end)); + file_basename, source.slice(last_end, offset), get_location(last_end)); out.concat(content).concat(replacement); last_end = offset + length; } // final_content = unchanged source characters after last replaced segment const final_content = StringWithSourcemap.from_source( - filename, source.slice(last_end), get_location(last_end)); + file_basename, source.slice(last_end), get_location(last_end)); return out.concat(final_content); } @@ -156,11 +160,34 @@ function decoded_sourcemap_from_generator(generator: any) { return map; } +/** + * Heuristic used to find index of component source inside source map sources. + */ +function guess_source_index( + file_basename: string, + decoded_map: DecodedSourceMap +): number { + if (!file_basename) { + return decoded_map.sources.findIndex(source => !source); + } + // different tools produce different sources + // (file name, relative path, absolute path) + const index = decoded_map.sources.findIndex(source => { + const source_basename = source && get_file_basename(source); + return source_basename === file_basename; + }); + if (index !== -1) { + // also normalize it in on source map + decoded_map.sources[index] = file_basename; + } + return index; +} + /** * Convert a preprocessor output and its leading prefix and trailing suffix into StringWithSourceMap */ function get_replacement( - filename: string, + file_basename: string, offset: number, get_location: ReturnType, original: string, @@ -171,9 +198,9 @@ function get_replacement( // Convert the unchanged prefix and suffix to StringWithSourcemap const prefix_with_map = StringWithSourcemap.from_source( - filename, prefix, get_location(offset)); + file_basename, prefix, get_location(offset)); const suffix_with_map = StringWithSourcemap.from_source( - filename, suffix, get_location(offset + prefix.length + original.length)); + file_basename, suffix, get_location(offset + prefix.length + original.length)); // Convert the preprocessed code and its sourcemap to a StringWithSourcemap let decoded_map: DecodedSourceMap; @@ -186,7 +213,9 @@ function get_replacement( // 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)); + // offset only segments pointing at original component source + const source_index = guess_source_index(file_basename, decoded_map); + sourcemap_add_offset(decoded_map, get_location(offset + prefix.length), source_index); } const processed_with_map = StringWithSourcemap.from_processed(processed.code, decoded_map); @@ -203,6 +232,9 @@ export default async function preprocess( const filename = (options && options.filename) || preprocessor.filename; // legacy const dependencies = []; + // preprocess source must be relative to itself + const file_basename = filename && get_file_basename(filename); + const preprocessors = preprocessor ? Array.isArray(preprocessor) ? preprocessor : [preprocessor] : []; @@ -246,13 +278,13 @@ export default async function preprocess( : /|([^]*?)<\/script>|\/>)/gi; const res = await replace_async( - filename, + file_basename, source, get_location, tag_regex, async (match, attributes = '', content = '', offset) => { const no_change = () => StringWithSourcemap.from_source( - filename, match, get_location(offset)); + file_basename, match, get_location(offset)); if (!attributes && !content) { return no_change(); } @@ -268,7 +300,7 @@ export default async function preprocess( if (!processed) return no_change(); if (processed.dependencies) dependencies.push(...processed.dependencies); - return get_replacement(filename, offset, get_location, content, processed, `<${tag_name}${attributes}>`, ``); + return get_replacement(file_basename, offset, get_location, content, processed, `<${tag_name}${attributes}>`, ``); } ); source = res.string; @@ -285,7 +317,7 @@ export default async function preprocess( // Combine all the source maps for each preprocessor function into one const map: RawSourceMap = combine_sourcemaps( - filename, + file_basename, sourcemap_list ); diff --git a/src/compiler/utils/string_with_sourcemap.ts b/src/compiler/utils/string_with_sourcemap.ts index 421a0c1fbd97..3dbd0a674a7a 100644 --- a/src/compiler/utils/string_with_sourcemap.ts +++ b/src/compiler/utils/string_with_sourcemap.ts @@ -13,21 +13,22 @@ function last_line_length(s: string) { // mutate map in-place export function sourcemap_add_offset( - map: DecodedSourceMap, offset: SourceLocation + map: DecodedSourceMap, offset: SourceLocation, source_index: number ) { - if (map.mappings.length == 0) return map; - // shift columns in first line - const segment_list = map.mappings[0]; - for (let segment = 0; segment < segment_list.length; segment++) { - const seg = segment_list[segment]; - if (seg[3]) seg[3] += offset.column; - } + if (map.mappings.length == 0 || source_index < 0) return; // shift lines for (let line = 0; line < map.mappings.length; line++) { const segment_list = map.mappings[line]; for (let segment = 0; segment < segment_list.length; segment++) { const seg = segment_list[segment]; - if (seg[2]) seg[2] += offset.line; + // shift only segments that belong to component source file + if (seg.length >= 4 && seg[1] === source_index) { + // shift columns pointing at the first line + if (seg[2] === 0) { + seg[3] += offset.column; + } + seg[2] += offset.line; + } } } } @@ -97,6 +98,9 @@ export class StringWithSourcemap { return this; } + // compute last line length before mutating + const column_offset = last_line_length(this.string); + this.string += other.string; const m1 = this.map; @@ -117,8 +121,8 @@ export class StringWithSourcemap { const segment_list = m2.mappings[line]; for (let segment = 0; segment < segment_list.length; segment++) { const seg = segment_list[segment]; - if (seg[1]) seg[1] = new_source_idx[seg[1]]; - if (seg[4]) seg[4] = new_name_idx[seg[4]]; + if (seg.length > 1) seg[1] = new_source_idx[seg[1]]; + if (seg.length > 4) seg[4] = new_name_idx[seg[4]]; } } } else if (sources_idx_changed) { @@ -126,7 +130,7 @@ export class StringWithSourcemap { const segment_list = m2.mappings[line]; for (let segment = 0; segment < segment_list.length; segment++) { const seg = segment_list[segment]; - if (seg[1]) seg[1] = new_source_idx[seg[1]]; + if (seg.length > 1) seg[1] = new_source_idx[seg[1]]; } } } else if (names_idx_changed) { @@ -134,7 +138,7 @@ export class StringWithSourcemap { const segment_list = m2.mappings[line]; for (let segment = 0; segment < segment_list.length; segment++) { const seg = segment_list[segment]; - if (seg[4]) seg[4] = new_name_idx[seg[4]]; + if (seg.length > 4) seg[4] = new_name_idx[seg[4]]; } } } @@ -146,7 +150,6 @@ export class StringWithSourcemap { // 2. first line of second map // columns of 2 must be shifted - const column_offset = last_line_length(this.string); if (m2.mappings.length > 0 && column_offset > 0) { const first_line = m2.mappings[0]; for (let i = 0; i < first_line.length; i++) { @@ -164,7 +167,17 @@ export class StringWithSourcemap { } static from_processed(string: string, map?: DecodedSourceMap): StringWithSourcemap { - if (map) return new StringWithSourcemap(string, map); + if (map) { + // ensure that count of source map mappings lines + // is equal to count of generated code lines + // (some tools may produce less) + const missing_lines = string.split('\n').length - map.mappings.length; + for (let i = 0; i < missing_lines; i++) { + map.mappings.push([]); + } + return new StringWithSourcemap(string, map); + } + if (string == '') return new StringWithSourcemap(); map = { version: 3, names: [], sources: [], mappings: [] }; diff --git a/test/sourcemaps/samples/script-and-style/_config.js b/test/sourcemaps/samples/script-and-style/_config.js new file mode 100644 index 000000000000..50795b2d90ab --- /dev/null +++ b/test/sourcemaps/samples/script-and-style/_config.js @@ -0,0 +1,22 @@ +import MagicString from 'magic-string'; +import { magic_string_preprocessor_result } from '../../helpers'; + +export default { + js_map_sources: [ + 'input.svelte' + ], + preprocess: [ + { + script: ({ content, filename }) => { + const s = new MagicString(content); + s.prepend('// This script code is approved\n'); + return magic_string_preprocessor_result(filename, s); + }, + style: ({ content, filename }) => { + const s = new MagicString(content); + s.prepend('/* This style code is approved */\n'); + return magic_string_preprocessor_result(filename, s); + } + } + ] +}; diff --git a/test/sourcemaps/samples/script-and-style/input.svelte b/test/sourcemaps/samples/script-and-style/input.svelte new file mode 100644 index 000000000000..489f128ef1a6 --- /dev/null +++ b/test/sourcemaps/samples/script-and-style/input.svelte @@ -0,0 +1,19 @@ + + + + +

Hello world!

+
Counter value: {count}
diff --git a/test/sourcemaps/samples/script-and-style/test.js b/test/sourcemaps/samples/script-and-style/test.js new file mode 100644 index 000000000000..473d7aaa1b87 --- /dev/null +++ b/test/sourcemaps/samples/script-and-style/test.js @@ -0,0 +1,17 @@ +export function test({ assert, input, preprocessed }) { + const content = '

Hello world!

'; + + const original = input.locate(content); + const transformed = preprocessed.locate_1('

Hello world!

'); + + assert.deepEqual( + preprocessed.mapConsumer.originalPositionFor(transformed), + { + source: 'input.svelte', + name: null, + line: original.line + 1, + column: original.column + }, + `failed to locate "${content}"` + ); +} diff --git a/test/sourcemaps/samples/typescript/_config.js b/test/sourcemaps/samples/typescript/_config.js new file mode 100644 index 000000000000..c8a955dfbdf4 --- /dev/null +++ b/test/sourcemaps/samples/typescript/_config.js @@ -0,0 +1,26 @@ +import * as ts from 'typescript'; + +export default { + js_map_sources: [ + 'input.svelte' + ], + preprocess: [ + { + script: ({ content, filename }) => { + const { outputText, sourceMapText } = ts.transpileModule(content, { + fileName: filename, + compilerOptions: { + target: ts.ScriptTarget.ES2015, + module: ts.ModuleKind.ES2015, + sourceMap: true + } + }); + + return { + code: outputText, + map: sourceMapText + }; + } + } + ] +}; diff --git a/test/sourcemaps/samples/typescript/input.svelte b/test/sourcemaps/samples/typescript/input.svelte new file mode 100644 index 000000000000..718336f346a1 --- /dev/null +++ b/test/sourcemaps/samples/typescript/input.svelte @@ -0,0 +1,13 @@ + + +

Hello world!

+
Counter value: {count}
diff --git a/test/sourcemaps/samples/typescript/test.js b/test/sourcemaps/samples/typescript/test.js new file mode 100644 index 000000000000..473d7aaa1b87 --- /dev/null +++ b/test/sourcemaps/samples/typescript/test.js @@ -0,0 +1,17 @@ +export function test({ assert, input, preprocessed }) { + const content = '

Hello world!

'; + + const original = input.locate(content); + const transformed = preprocessed.locate_1('

Hello world!

'); + + assert.deepEqual( + preprocessed.mapConsumer.originalPositionFor(transformed), + { + source: 'input.svelte', + name: null, + line: original.line + 1, + column: original.column + }, + `failed to locate "${content}"` + ); +} From 5441835d41a8c10103173a330beb0a462356d237 Mon Sep 17 00:00:00 2001 From: dmitrage Date: Tue, 8 Dec 2020 21:57:31 +0300 Subject: [PATCH 02/11] Add more tests --- test/sourcemaps/helpers.ts | 24 +++++++++++- test/sourcemaps/samples/external/_config.js | 23 +++++++++++ test/sourcemaps/samples/external/input.svelte | 3 ++ test/sourcemaps/samples/external/test.js | 27 +++++++++++++ .../samples/guess-source/_config.js | 19 +++++++++ .../samples/guess-source/input.svelte | 6 +++ test/sourcemaps/samples/guess-source/test.js | 30 ++++++++++++++ .../samples/typescript/input.svelte | 17 +++++--- test/sourcemaps/samples/typescript/test.js | 39 ++++++++++++------- 9 files changed, 168 insertions(+), 20 deletions(-) create mode 100644 test/sourcemaps/samples/external/_config.js create mode 100644 test/sourcemaps/samples/external/input.svelte create mode 100644 test/sourcemaps/samples/external/test.js create mode 100644 test/sourcemaps/samples/guess-source/_config.js create mode 100644 test/sourcemaps/samples/guess-source/input.svelte create mode 100644 test/sourcemaps/samples/guess-source/test.js diff --git a/test/sourcemaps/helpers.ts b/test/sourcemaps/helpers.ts index d0bea310e623..af3b02f85eb2 100644 --- a/test/sourcemaps/helpers.ts +++ b/test/sourcemaps/helpers.ts @@ -1,4 +1,26 @@ -import MagicString from 'magic-string'; +import MagicString, { Bundle } from 'magic-string'; + +export function magic_string_bundle( + inputs: Array<{ code: string | MagicString, filename: string }>, + filename = 'bundle.js', + separator = '\n' +) { + const bundle = new Bundle({ separator }); + inputs.forEach(({ code, filename }) => { + bundle.addSource({ + filename, + content: typeof code === 'string' ? new MagicString(code) : code + }); + }); + return { + code: bundle.toString(), + map: bundle.generateMap({ + source: filename, + hires: true, + includeContent: false + }) + }; +} export function magic_string_preprocessor_result(filename: string, src: MagicString) { return { diff --git a/test/sourcemaps/samples/external/_config.js b/test/sourcemaps/samples/external/_config.js new file mode 100644 index 000000000000..349df3aeae6f --- /dev/null +++ b/test/sourcemaps/samples/external/_config.js @@ -0,0 +1,23 @@ +import { magic_string_bundle } from '../../helpers'; + +export const COMMON = ':global(html) { height: 100%; }\n'; + +// TODO: removing '\n' breaks test +// - _actual.svelte.map looks correct +// - _actual.css.map adds reference to on input.svelte +export const STYLES = '.awesome { color: orange; }\n'; + +export default { + css_map_sources: ['common.scss', 'styles.scss'], + js_map_sources: [], + preprocess: [ + { + style: () => { + return magic_string_bundle([ + { filename: 'common.scss', code: COMMON }, + { filename: 'styles.scss', code: STYLES } + ]); + } + } + ] +}; diff --git a/test/sourcemaps/samples/external/input.svelte b/test/sourcemaps/samples/external/input.svelte new file mode 100644 index 000000000000..94d895e4a724 --- /dev/null +++ b/test/sourcemaps/samples/external/input.svelte @@ -0,0 +1,3 @@ + + +
Divs ftw!
\ No newline at end of file diff --git a/test/sourcemaps/samples/external/test.js b/test/sourcemaps/samples/external/test.js new file mode 100644 index 000000000000..c11f40d7587a --- /dev/null +++ b/test/sourcemaps/samples/external/test.js @@ -0,0 +1,27 @@ +import { getLocator } from 'locate-character'; +import { COMMON, STYLES } from './_config'; + +export function test({ assert, input, preprocessed }) { + + const assertMapped = (locateInput, code, filename) => { + const sourceLoc = locateInput(code); + const transformedLoc = preprocessed.locate_1(code); + assert.deepEqual( + preprocessed.mapConsumer.originalPositionFor(transformedLoc), + { + source: filename, + name: null, + line: sourceLoc.line + 1, + column: sourceLoc.column + }, + `failed to locate "${code}"` + ); + }; + + // Transformed script, main file + assertMapped(input.locate, 'Divs ftw!', 'input.svelte'); + + // External files + assertMapped(getLocator(COMMON), 'height: 100%;', 'common.scss'); + assertMapped(getLocator(STYLES), 'color: orange;', 'styles.scss'); +} diff --git a/test/sourcemaps/samples/guess-source/_config.js b/test/sourcemaps/samples/guess-source/_config.js new file mode 100644 index 000000000000..4cc5d9d7b770 --- /dev/null +++ b/test/sourcemaps/samples/guess-source/_config.js @@ -0,0 +1,19 @@ +import { magic_string_bundle } from '../../helpers'; + +export const PREPEND = 'console.log("COUNTER_START")'; +export const APPEND = 'console.log("COUNTER_END")'; + +export default { + js_map_sources: ['input.svelte', 'src/prepend.js', 'src/append.js'], + preprocess: [ + { + script: ({ content }) => { + return magic_string_bundle([ + { filename: 'src/prepend.js', code: PREPEND }, + { filename: 'src/input.svelte', code: content }, + { filename: 'src/append.js', code: APPEND } + ]); + } + } + ] +}; diff --git a/test/sourcemaps/samples/guess-source/input.svelte b/test/sourcemaps/samples/guess-source/input.svelte new file mode 100644 index 000000000000..da111701efae --- /dev/null +++ b/test/sourcemaps/samples/guess-source/input.svelte @@ -0,0 +1,6 @@ + + +

Hello world!

+
Counter value: {count}
diff --git a/test/sourcemaps/samples/guess-source/test.js b/test/sourcemaps/samples/guess-source/test.js new file mode 100644 index 000000000000..6ef7fb18298d --- /dev/null +++ b/test/sourcemaps/samples/guess-source/test.js @@ -0,0 +1,30 @@ +import { getLocator } from 'locate-character'; +import { APPEND, PREPEND } from './_config'; + +export function test({ assert, input, preprocessed }) { + + const assertMapped = (locateInput, code, filename) => { + const sourceLoc = locateInput(code); + const transformedLoc = preprocessed.locate_1(code); + assert.deepEqual( + preprocessed.mapConsumer.originalPositionFor(transformedLoc), + { + source: filename, + name: null, + line: sourceLoc.line + 1, + column: sourceLoc.column + }, + `failed to locate "${code}"` + ); + }; + + // Transformed script, main file + assertMapped(input.locate, 'let count = 3;', 'input.svelte'); + + // Untouched markup, main file + assertMapped(input.locate, '

Hello world!

', 'input.svelte'); + + // External files + assertMapped(getLocator(PREPEND), '"COUNTER_START"', 'src/prepend.js'); + assertMapped(getLocator(APPEND), '"COUNTER_END"', 'src/append.js'); +} diff --git a/test/sourcemaps/samples/typescript/input.svelte b/test/sourcemaps/samples/typescript/input.svelte index 718336f346a1..93639544b66e 100644 --- a/test/sourcemaps/samples/typescript/input.svelte +++ b/test/sourcemaps/samples/typescript/input.svelte @@ -1,12 +1,17 @@

Hello world!

diff --git a/test/sourcemaps/samples/typescript/test.js b/test/sourcemaps/samples/typescript/test.js index 473d7aaa1b87..73e2c8a66bb6 100644 --- a/test/sourcemaps/samples/typescript/test.js +++ b/test/sourcemaps/samples/typescript/test.js @@ -1,17 +1,30 @@ export function test({ assert, input, preprocessed }) { - const content = '

Hello world!

'; + const assertMapped = (source, transformed) => { + const sourceLoc = input.locate(source); + const transformedLoc = preprocessed.locate_1(transformed); + assert.deepEqual( + preprocessed.mapConsumer.originalPositionFor(transformedLoc), + { + source: 'input.svelte', + name: null, + line: sourceLoc.line + 1, + column: sourceLoc.column + }, + `failed to locate "${transformed}"` + ); + }; - const original = input.locate(content); - const transformed = preprocessed.locate_1('

Hello world!

'); + const assertNotMapped = (code) => { + const transformedLoc = preprocessed.locate_1(code); + assert.strictEqual(transformedLoc, undefined, `failed to remove "${code}"`); + }; - assert.deepEqual( - preprocessed.mapConsumer.originalPositionFor(transformed), - { - source: 'input.svelte', - name: null, - line: original.line + 1, - column: original.column - }, - `failed to locate "${content}"` - ); + // TS => JS code + assertMapped('let count: number = 0;', 'let count = 0;'); + + // Markup, not touched + assertMapped('

Hello world!

', '

Hello world!

'); + + // TS types, removed + assertNotMapped('ITimeoutDestroyer'); } From 7ac102a8058ef7bccdd3495fec8c361dd5c0c210 Mon Sep 17 00:00:00 2001 From: dmitrage Date: Wed, 9 Dec 2020 14:41:34 +0300 Subject: [PATCH 03/11] Remove source guessing workaround --- src/compiler/preprocess/index.ts | 25 +--------------- test/sourcemaps/samples/external/test.js | 2 +- .../samples/guess-source/_config.js | 19 ------------ .../samples/guess-source/input.svelte | 6 ---- test/sourcemaps/samples/guess-source/test.js | 30 ------------------- 5 files changed, 2 insertions(+), 80 deletions(-) delete mode 100644 test/sourcemaps/samples/guess-source/_config.js delete mode 100644 test/sourcemaps/samples/guess-source/input.svelte delete mode 100644 test/sourcemaps/samples/guess-source/test.js diff --git a/src/compiler/preprocess/index.ts b/src/compiler/preprocess/index.ts index f8e2f95c89f6..29a5e45931a7 100644 --- a/src/compiler/preprocess/index.ts +++ b/src/compiler/preprocess/index.ts @@ -160,29 +160,6 @@ function decoded_sourcemap_from_generator(generator: any) { return map; } -/** - * Heuristic used to find index of component source inside source map sources. - */ -function guess_source_index( - file_basename: string, - decoded_map: DecodedSourceMap -): number { - if (!file_basename) { - return decoded_map.sources.findIndex(source => !source); - } - // different tools produce different sources - // (file name, relative path, absolute path) - const index = decoded_map.sources.findIndex(source => { - const source_basename = source && get_file_basename(source); - return source_basename === file_basename; - }); - if (index !== -1) { - // also normalize it in on source map - decoded_map.sources[index] = file_basename; - } - return index; -} - /** * Convert a preprocessor output and its leading prefix and trailing suffix into StringWithSourceMap */ @@ -214,7 +191,7 @@ function get_replacement( decoded_map = decoded_sourcemap_from_generator(decoded_map); } // offset only segments pointing at original component source - const source_index = guess_source_index(file_basename, decoded_map); + const source_index = decoded_map.sources.findIndex(source => source === file_basename); sourcemap_add_offset(decoded_map, get_location(offset + prefix.length), source_index); } const processed_with_map = StringWithSourcemap.from_processed(processed.code, decoded_map); diff --git a/test/sourcemaps/samples/external/test.js b/test/sourcemaps/samples/external/test.js index c11f40d7587a..e83bbe34c74b 100644 --- a/test/sourcemaps/samples/external/test.js +++ b/test/sourcemaps/samples/external/test.js @@ -14,7 +14,7 @@ export function test({ assert, input, preprocessed }) { line: sourceLoc.line + 1, column: sourceLoc.column }, - `failed to locate "${code}"` + `failed to locate "${code}" in "${filename}"` ); }; diff --git a/test/sourcemaps/samples/guess-source/_config.js b/test/sourcemaps/samples/guess-source/_config.js deleted file mode 100644 index 4cc5d9d7b770..000000000000 --- a/test/sourcemaps/samples/guess-source/_config.js +++ /dev/null @@ -1,19 +0,0 @@ -import { magic_string_bundle } from '../../helpers'; - -export const PREPEND = 'console.log("COUNTER_START")'; -export const APPEND = 'console.log("COUNTER_END")'; - -export default { - js_map_sources: ['input.svelte', 'src/prepend.js', 'src/append.js'], - preprocess: [ - { - script: ({ content }) => { - return magic_string_bundle([ - { filename: 'src/prepend.js', code: PREPEND }, - { filename: 'src/input.svelte', code: content }, - { filename: 'src/append.js', code: APPEND } - ]); - } - } - ] -}; diff --git a/test/sourcemaps/samples/guess-source/input.svelte b/test/sourcemaps/samples/guess-source/input.svelte deleted file mode 100644 index da111701efae..000000000000 --- a/test/sourcemaps/samples/guess-source/input.svelte +++ /dev/null @@ -1,6 +0,0 @@ - - -

Hello world!

-
Counter value: {count}
diff --git a/test/sourcemaps/samples/guess-source/test.js b/test/sourcemaps/samples/guess-source/test.js deleted file mode 100644 index 6ef7fb18298d..000000000000 --- a/test/sourcemaps/samples/guess-source/test.js +++ /dev/null @@ -1,30 +0,0 @@ -import { getLocator } from 'locate-character'; -import { APPEND, PREPEND } from './_config'; - -export function test({ assert, input, preprocessed }) { - - const assertMapped = (locateInput, code, filename) => { - const sourceLoc = locateInput(code); - const transformedLoc = preprocessed.locate_1(code); - assert.deepEqual( - preprocessed.mapConsumer.originalPositionFor(transformedLoc), - { - source: filename, - name: null, - line: sourceLoc.line + 1, - column: sourceLoc.column - }, - `failed to locate "${code}"` - ); - }; - - // Transformed script, main file - assertMapped(input.locate, 'let count = 3;', 'input.svelte'); - - // Untouched markup, main file - assertMapped(input.locate, '

Hello world!

', 'input.svelte'); - - // External files - assertMapped(getLocator(PREPEND), '"COUNTER_START"', 'src/prepend.js'); - assertMapped(getLocator(APPEND), '"COUNTER_END"', 'src/append.js'); -} From d5408003efc33df9fb235704cb97a9def847d89e Mon Sep 17 00:00:00 2001 From: dmitrage Date: Wed, 9 Dec 2020 15:22:38 +0300 Subject: [PATCH 04/11] Update test todo note --- test/sourcemaps/samples/external/_config.js | 1 + .../samples/script-and-style/_config.js | 16 ++++++++-------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/test/sourcemaps/samples/external/_config.js b/test/sourcemaps/samples/external/_config.js index 349df3aeae6f..54a59d66f18f 100644 --- a/test/sourcemaps/samples/external/_config.js +++ b/test/sourcemaps/samples/external/_config.js @@ -5,6 +5,7 @@ export const COMMON = ':global(html) { height: 100%; }\n'; // TODO: removing '\n' breaks test // - _actual.svelte.map looks correct // - _actual.css.map adds reference to on input.svelte +// - Most probably it is caused by bug in current magic-string version (fixed in 0.25.7) export const STYLES = '.awesome { color: orange; }\n'; export default { diff --git a/test/sourcemaps/samples/script-and-style/_config.js b/test/sourcemaps/samples/script-and-style/_config.js index 50795b2d90ab..9c5f3a06f509 100644 --- a/test/sourcemaps/samples/script-and-style/_config.js +++ b/test/sourcemaps/samples/script-and-style/_config.js @@ -8,14 +8,14 @@ export default { preprocess: [ { script: ({ content, filename }) => { - const s = new MagicString(content); - s.prepend('// This script code is approved\n'); - return magic_string_preprocessor_result(filename, s); - }, - style: ({ content, filename }) => { - const s = new MagicString(content); - s.prepend('/* This style code is approved */\n'); - return magic_string_preprocessor_result(filename, s); + const s = new MagicString(content); + s.prepend('// This script code is approved\n'); + return magic_string_preprocessor_result(filename, s); + }, + style: ({ content, filename }) => { + const s = new MagicString(content); + s.prepend('/* This style code is approved */\n'); + return magic_string_preprocessor_result(filename, s); } } ] From c842d1617f2edc98dbe1f6dbdc663323f7fede1d Mon Sep 17 00:00:00 2001 From: dmitrage Date: Wed, 9 Dec 2020 15:58:01 +0300 Subject: [PATCH 05/11] Cleanup tests --- test/sourcemaps/helpers.ts | 55 +++++++++++++++++++ test/sourcemaps/samples/external/_config.js | 2 +- test/sourcemaps/samples/external/test.js | 41 +++++++------- .../samples/script-and-style/test.js | 22 +++----- test/sourcemaps/samples/typescript/test.js | 39 +++++-------- 5 files changed, 98 insertions(+), 61 deletions(-) diff --git a/test/sourcemaps/helpers.ts b/test/sourcemaps/helpers.ts index af3b02f85eb2..c1a6e6798caa 100644 --- a/test/sourcemaps/helpers.ts +++ b/test/sourcemaps/helpers.ts @@ -1,5 +1,60 @@ +import * as assert from 'assert'; +import { getLocator } from 'locate-character'; import MagicString, { Bundle } from 'magic-string'; +type AssertMappedParameters = { + code: string; + filename?: string; + input: string | ReturnType; + input_code?: string; + preprocessed: any; +}; + +export function assert_mapped( + { code, filename, input, input_code, preprocessed }: AssertMappedParameters +) { + const locate_input = typeof input === 'function' ? input : getLocator(input); + if (filename === undefined) filename = 'input.svelte'; + if (input_code === undefined) input_code = code; + + const source_loc = locate_input(input_code); + assert.notEqual( + source_loc, + undefined, + `failed to locate "${input_code}" in "${filename}"` + ); + + const transformed_loc = preprocessed.locate_1(code); + assert.notEqual( + transformed_loc, + undefined, + `failed to locate "${code}" in transformed "${filename}"` + ); + + assert.deepEqual( + preprocessed.mapConsumer.originalPositionFor(transformed_loc), + { + source: filename, + name: null, + line: source_loc.line + 1, + column: source_loc.column + }, + `incorrect mappings for "${input_code}" in "${filename}"` + ); +} + +export function assert_not_located( + code: string, + locate: ReturnType, + filename = 'input.svelte' +) { + assert.equal( + locate(code), + undefined, + `located "${code}" that should be removed from ${filename}` + ); +} + export function magic_string_bundle( inputs: Array<{ code: string | MagicString, filename: string }>, filename = 'bundle.js', diff --git a/test/sourcemaps/samples/external/_config.js b/test/sourcemaps/samples/external/_config.js index 54a59d66f18f..400def20ac63 100644 --- a/test/sourcemaps/samples/external/_config.js +++ b/test/sourcemaps/samples/external/_config.js @@ -5,7 +5,7 @@ export const COMMON = ':global(html) { height: 100%; }\n'; // TODO: removing '\n' breaks test // - _actual.svelte.map looks correct // - _actual.css.map adds reference to on input.svelte -// - Most probably it is caused by bug in current magic-string version (fixed in 0.25.7) +// - Most probably caused by bug in current magic-string version (fixed in 0.25.7) export const STYLES = '.awesome { color: orange; }\n'; export default { diff --git a/test/sourcemaps/samples/external/test.js b/test/sourcemaps/samples/external/test.js index e83bbe34c74b..5193b62ba1d4 100644 --- a/test/sourcemaps/samples/external/test.js +++ b/test/sourcemaps/samples/external/test.js @@ -1,27 +1,26 @@ -import { getLocator } from 'locate-character'; +import { assert_mapped } from '../../helpers'; import { COMMON, STYLES } from './_config'; -export function test({ assert, input, preprocessed }) { - - const assertMapped = (locateInput, code, filename) => { - const sourceLoc = locateInput(code); - const transformedLoc = preprocessed.locate_1(code); - assert.deepEqual( - preprocessed.mapConsumer.originalPositionFor(transformedLoc), - { - source: filename, - name: null, - line: sourceLoc.line + 1, - column: sourceLoc.column - }, - `failed to locate "${code}" in "${filename}"` - ); - }; - +export function test({ input, preprocessed }) { // Transformed script, main file - assertMapped(input.locate, 'Divs ftw!', 'input.svelte'); + assert_mapped({ + filename: 'input.svelte', + code: 'Divs ftw!', + input: input.locate, + preprocessed + }); // External files - assertMapped(getLocator(COMMON), 'height: 100%;', 'common.scss'); - assertMapped(getLocator(STYLES), 'color: orange;', 'styles.scss'); + assert_mapped({ + filename: 'common.scss', + code: 'height: 100%;', + input: COMMON, + preprocessed + }); + assert_mapped({ + filename: 'styles.scss', + code: 'color: orange;', + input: STYLES, + preprocessed + }); } diff --git a/test/sourcemaps/samples/script-and-style/test.js b/test/sourcemaps/samples/script-and-style/test.js index 473d7aaa1b87..8d695e6dbe2c 100644 --- a/test/sourcemaps/samples/script-and-style/test.js +++ b/test/sourcemaps/samples/script-and-style/test.js @@ -1,17 +1,9 @@ -export function test({ assert, input, preprocessed }) { - const content = '

Hello world!

'; +import { assert_mapped } from '../../helpers'; - const original = input.locate(content); - const transformed = preprocessed.locate_1('

Hello world!

'); - - assert.deepEqual( - preprocessed.mapConsumer.originalPositionFor(transformed), - { - source: 'input.svelte', - name: null, - line: original.line + 1, - column: original.column - }, - `failed to locate "${content}"` - ); +export function test({ input, preprocessed }) { + assert_mapped({ + code: '

Hello world!

', + input: input.locate, + preprocessed + }); } diff --git a/test/sourcemaps/samples/typescript/test.js b/test/sourcemaps/samples/typescript/test.js index 73e2c8a66bb6..bec397e33c49 100644 --- a/test/sourcemaps/samples/typescript/test.js +++ b/test/sourcemaps/samples/typescript/test.js @@ -1,30 +1,21 @@ -export function test({ assert, input, preprocessed }) { - const assertMapped = (source, transformed) => { - const sourceLoc = input.locate(source); - const transformedLoc = preprocessed.locate_1(transformed); - assert.deepEqual( - preprocessed.mapConsumer.originalPositionFor(transformedLoc), - { - source: 'input.svelte', - name: null, - line: sourceLoc.line + 1, - column: sourceLoc.column - }, - `failed to locate "${transformed}"` - ); - }; - - const assertNotMapped = (code) => { - const transformedLoc = preprocessed.locate_1(code); - assert.strictEqual(transformedLoc, undefined, `failed to remove "${code}"`); - }; +import { assert_mapped, assert_not_located } from '../../helpers'; +export function test({ input, preprocessed }) { // TS => JS code - assertMapped('let count: number = 0;', 'let count = 0;'); + assert_mapped({ + code: 'let count = 0;', + input_code: 'let count: number = 0;', + input: input.locate, + preprocessed + }); // Markup, not touched - assertMapped('

Hello world!

', '

Hello world!

'); - + assert_mapped({ + code: '

Hello world!

', + input: input.locate, + preprocessed + }); + // TS types, removed - assertNotMapped('ITimeoutDestroyer'); + assert_not_located('ITimeoutDestroyer', preprocessed.locate_1); } From 1c241dd1a83458a4dbf3add79a8ac9a37c1a10f6 Mon Sep 17 00:00:00 2001 From: dmitrage Date: Thu, 10 Dec 2020 01:34:32 +0300 Subject: [PATCH 06/11] Add test for sourcemap offset --- src/compiler/preprocess/index.ts | 6 ++++-- src/compiler/utils/string_with_sourcemap.ts | 2 +- test/sourcemaps/samples/concat/_config.js | 15 +++++++++++++++ test/sourcemaps/samples/concat/input.svelte | 3 +++ test/sourcemaps/samples/concat/test.js | 9 +++++++++ 5 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 test/sourcemaps/samples/concat/_config.js create mode 100644 test/sourcemaps/samples/concat/input.svelte create mode 100644 test/sourcemaps/samples/concat/test.js diff --git a/src/compiler/preprocess/index.ts b/src/compiler/preprocess/index.ts index 29a5e45931a7..e878cdc019ef 100644 --- a/src/compiler/preprocess/index.ts +++ b/src/compiler/preprocess/index.ts @@ -191,8 +191,10 @@ function get_replacement( decoded_map = decoded_sourcemap_from_generator(decoded_map); } // offset only segments pointing at original component source - const source_index = decoded_map.sources.findIndex(source => source === file_basename); - sourcemap_add_offset(decoded_map, get_location(offset + prefix.length), source_index); + const source_index = decoded_map.sources.indexOf(file_basename); + if (source_index !== -1) { + sourcemap_add_offset(decoded_map, get_location(offset + prefix.length), source_index); + } } const processed_with_map = StringWithSourcemap.from_processed(processed.code, decoded_map); diff --git a/src/compiler/utils/string_with_sourcemap.ts b/src/compiler/utils/string_with_sourcemap.ts index 3dbd0a674a7a..4b4be2884610 100644 --- a/src/compiler/utils/string_with_sourcemap.ts +++ b/src/compiler/utils/string_with_sourcemap.ts @@ -15,7 +15,7 @@ function last_line_length(s: string) { export function sourcemap_add_offset( map: DecodedSourceMap, offset: SourceLocation, source_index: number ) { - if (map.mappings.length == 0 || source_index < 0) return; + if (map.mappings.length == 0) return; // shift lines for (let line = 0; line < map.mappings.length; line++) { const segment_list = map.mappings[line]; diff --git a/test/sourcemaps/samples/concat/_config.js b/test/sourcemaps/samples/concat/_config.js new file mode 100644 index 000000000000..835b3c9e48cf --- /dev/null +++ b/test/sourcemaps/samples/concat/_config.js @@ -0,0 +1,15 @@ +import MagicString from 'magic-string'; +import { magic_string_preprocessor_result } from '../../helpers'; + +export default { + js_map_sources: ['input.svelte'], + preprocess: [ + { + script: ({ content }) => { + const src = new MagicString(content); + src.prepend('console.log("Injected first line");\n'); + return magic_string_preprocessor_result('input.svelte', src); + } + } + ] +}; diff --git a/test/sourcemaps/samples/concat/input.svelte b/test/sourcemaps/samples/concat/input.svelte new file mode 100644 index 000000000000..18a1ac775f4d --- /dev/null +++ b/test/sourcemaps/samples/concat/input.svelte @@ -0,0 +1,3 @@ + + +

Hello

\ No newline at end of file diff --git a/test/sourcemaps/samples/concat/test.js b/test/sourcemaps/samples/concat/test.js new file mode 100644 index 000000000000..0d7af05407cb --- /dev/null +++ b/test/sourcemaps/samples/concat/test.js @@ -0,0 +1,9 @@ +import { assert_mapped } from '../../helpers'; + +export function test({ input, preprocessed }) { + assert_mapped({ + code: 'Target', + input: input.locate, + preprocessed + }); +} From 3830216b16036f6579cc22dd3f65d2554a7265a2 Mon Sep 17 00:00:00 2001 From: dmitrage Date: Fri, 11 Dec 2020 14:19:54 +0300 Subject: [PATCH 07/11] Tests and chores --- src/compiler/preprocess/index.ts | 4 ++-- src/compiler/utils/string_with_sourcemap.ts | 14 ++++++------ .../samples/script-and-style/_config.js | 22 ------------------- .../samples/script-and-style/input.svelte | 19 ---------------- .../samples/script-and-style/test.js | 9 -------- .../{concat => sourcemap-concat}/_config.js | 0 .../{concat => sourcemap-concat}/input.svelte | 0 .../{concat => sourcemap-concat}/test.js | 2 +- .../samples/sourcemap-offsets/_config.js | 18 +++++++++++++++ .../samples/sourcemap-offsets/input.svelte | 9 ++++++++ .../samples/sourcemap-offsets/test.js | 19 ++++++++++++++++ 11 files changed, 56 insertions(+), 60 deletions(-) delete mode 100644 test/sourcemaps/samples/script-and-style/_config.js delete mode 100644 test/sourcemaps/samples/script-and-style/input.svelte delete mode 100644 test/sourcemaps/samples/script-and-style/test.js rename test/sourcemaps/samples/{concat => sourcemap-concat}/_config.js (100%) rename test/sourcemaps/samples/{concat => sourcemap-concat}/input.svelte (100%) rename test/sourcemaps/samples/{concat => sourcemap-concat}/test.js (88%) create mode 100644 test/sourcemaps/samples/sourcemap-offsets/_config.js create mode 100644 test/sourcemaps/samples/sourcemap-offsets/input.svelte create mode 100644 test/sourcemaps/samples/sourcemap-offsets/test.js diff --git a/src/compiler/preprocess/index.ts b/src/compiler/preprocess/index.ts index e878cdc019ef..82c5f4be7412 100644 --- a/src/compiler/preprocess/index.ts +++ b/src/compiler/preprocess/index.ts @@ -211,8 +211,8 @@ export default async function preprocess( const filename = (options && options.filename) || preprocessor.filename; // legacy const dependencies = []; - // preprocess source must be relative to itself - const file_basename = filename && get_file_basename(filename); + // preprocess source must be relative to itself or equal null + const file_basename = filename == null ? null : get_file_basename(filename); const preprocessors = preprocessor ? Array.isArray(preprocessor) ? preprocessor : [preprocessor] diff --git a/src/compiler/utils/string_with_sourcemap.ts b/src/compiler/utils/string_with_sourcemap.ts index 4b4be2884610..1707c86aac53 100644 --- a/src/compiler/utils/string_with_sourcemap.ts +++ b/src/compiler/utils/string_with_sourcemap.ts @@ -16,17 +16,17 @@ export function sourcemap_add_offset( map: DecodedSourceMap, offset: SourceLocation, source_index: number ) { if (map.mappings.length == 0) return; - // shift lines for (let line = 0; line < map.mappings.length; line++) { const segment_list = map.mappings[line]; for (let segment = 0; segment < segment_list.length; segment++) { const seg = segment_list[segment]; // shift only segments that belong to component source file - if (seg.length >= 4 && seg[1] === source_index) { - // shift columns pointing at the first line + if (seg[1] === source_index) { // also ensures that seg.length >= 4 + // shift column if it points at the first line if (seg[2] === 0) { seg[3] += offset.column; } + // shift line seg[2] += offset.line; } } @@ -121,8 +121,8 @@ export class StringWithSourcemap { const segment_list = m2.mappings[line]; for (let segment = 0; segment < segment_list.length; segment++) { const seg = segment_list[segment]; - if (seg.length > 1) seg[1] = new_source_idx[seg[1]]; - if (seg.length > 4) seg[4] = new_name_idx[seg[4]]; + if (seg[1] >= 0) seg[1] = new_source_idx[seg[1]]; + if (seg[4] >= 0) seg[4] = new_name_idx[seg[4]]; } } } else if (sources_idx_changed) { @@ -130,7 +130,7 @@ export class StringWithSourcemap { const segment_list = m2.mappings[line]; for (let segment = 0; segment < segment_list.length; segment++) { const seg = segment_list[segment]; - if (seg.length > 1) seg[1] = new_source_idx[seg[1]]; + if (seg[1] >= 0) seg[1] = new_source_idx[seg[1]]; } } } else if (names_idx_changed) { @@ -138,7 +138,7 @@ export class StringWithSourcemap { const segment_list = m2.mappings[line]; for (let segment = 0; segment < segment_list.length; segment++) { const seg = segment_list[segment]; - if (seg.length > 4) seg[4] = new_name_idx[seg[4]]; + if (seg[4] >= 0) seg[4] = new_name_idx[seg[4]]; } } } diff --git a/test/sourcemaps/samples/script-and-style/_config.js b/test/sourcemaps/samples/script-and-style/_config.js deleted file mode 100644 index 9c5f3a06f509..000000000000 --- a/test/sourcemaps/samples/script-and-style/_config.js +++ /dev/null @@ -1,22 +0,0 @@ -import MagicString from 'magic-string'; -import { magic_string_preprocessor_result } from '../../helpers'; - -export default { - js_map_sources: [ - 'input.svelte' - ], - preprocess: [ - { - script: ({ content, filename }) => { - const s = new MagicString(content); - s.prepend('// This script code is approved\n'); - return magic_string_preprocessor_result(filename, s); - }, - style: ({ content, filename }) => { - const s = new MagicString(content); - s.prepend('/* This style code is approved */\n'); - return magic_string_preprocessor_result(filename, s); - } - } - ] -}; diff --git a/test/sourcemaps/samples/script-and-style/input.svelte b/test/sourcemaps/samples/script-and-style/input.svelte deleted file mode 100644 index 489f128ef1a6..000000000000 --- a/test/sourcemaps/samples/script-and-style/input.svelte +++ /dev/null @@ -1,19 +0,0 @@ - - - - -

Hello world!

-
Counter value: {count}
diff --git a/test/sourcemaps/samples/script-and-style/test.js b/test/sourcemaps/samples/script-and-style/test.js deleted file mode 100644 index 8d695e6dbe2c..000000000000 --- a/test/sourcemaps/samples/script-and-style/test.js +++ /dev/null @@ -1,9 +0,0 @@ -import { assert_mapped } from '../../helpers'; - -export function test({ input, preprocessed }) { - assert_mapped({ - code: '

Hello world!

', - input: input.locate, - preprocessed - }); -} diff --git a/test/sourcemaps/samples/concat/_config.js b/test/sourcemaps/samples/sourcemap-concat/_config.js similarity index 100% rename from test/sourcemaps/samples/concat/_config.js rename to test/sourcemaps/samples/sourcemap-concat/_config.js diff --git a/test/sourcemaps/samples/concat/input.svelte b/test/sourcemaps/samples/sourcemap-concat/input.svelte similarity index 100% rename from test/sourcemaps/samples/concat/input.svelte rename to test/sourcemaps/samples/sourcemap-concat/input.svelte diff --git a/test/sourcemaps/samples/concat/test.js b/test/sourcemaps/samples/sourcemap-concat/test.js similarity index 88% rename from test/sourcemaps/samples/concat/test.js rename to test/sourcemaps/samples/sourcemap-concat/test.js index 0d7af05407cb..c68d7175dc23 100644 --- a/test/sourcemaps/samples/concat/test.js +++ b/test/sourcemaps/samples/sourcemap-concat/test.js @@ -2,7 +2,7 @@ import { assert_mapped } from '../../helpers'; export function test({ input, preprocessed }) { assert_mapped({ - code: 'Target', + code: 'Target', input: input.locate, preprocessed }); diff --git a/test/sourcemaps/samples/sourcemap-offsets/_config.js b/test/sourcemaps/samples/sourcemap-offsets/_config.js new file mode 100644 index 000000000000..392fb68a434f --- /dev/null +++ b/test/sourcemaps/samples/sourcemap-offsets/_config.js @@ -0,0 +1,18 @@ +import { magic_string_bundle } from '../../helpers'; + +export const EXTERNAL = 'span { --external-var: 1px; }'; + +export default { + js_map_sources: [], + css_map_sources: ['input.svelte', 'external.css'], + preprocess: [ + { + style: ({ content, filename }) => { + return magic_string_bundle([ + { code: EXTERNAL, filename: 'external.css' }, + { code: content, filename } + ]); + } + } + ] +}; diff --git a/test/sourcemaps/samples/sourcemap-offsets/input.svelte b/test/sourcemaps/samples/sourcemap-offsets/input.svelte new file mode 100644 index 000000000000..51f7762e2ab7 --- /dev/null +++ b/test/sourcemaps/samples/sourcemap-offsets/input.svelte @@ -0,0 +1,9 @@ + + + + +
Text
\ No newline at end of file diff --git a/test/sourcemaps/samples/sourcemap-offsets/test.js b/test/sourcemaps/samples/sourcemap-offsets/test.js new file mode 100644 index 000000000000..a6c328770c0e --- /dev/null +++ b/test/sourcemaps/samples/sourcemap-offsets/test.js @@ -0,0 +1,19 @@ +import { assert_mapped } from '../../helpers'; +import { EXTERNAL } from './_config'; + +export function test({ input, preprocessed }) { + // Part from component, should be with offset + assert_mapped({ + code: '--component-var', + input: input.locate, + preprocessed + }); + + // Part from external file, should be without offset + assert_mapped({ + filename: 'external.css', + code: '--external-var', + input: EXTERNAL, + preprocessed + }); +} From 20499ee77ef0224aef62cd4f0f3fb2a6bac683d7 Mon Sep 17 00:00:00 2001 From: dmitrage Date: Sat, 12 Dec 2020 19:19:53 +0300 Subject: [PATCH 08/11] Add test for basename --- .../samples/sourcemap-basename/_config.js | 33 +++++++++++++++++++ .../samples/sourcemap-basename/input.svelte | 3 ++ .../samples/sourcemap-basename/test.js | 15 +++++++++ 3 files changed, 51 insertions(+) create mode 100644 test/sourcemaps/samples/sourcemap-basename/_config.js create mode 100644 test/sourcemaps/samples/sourcemap-basename/input.svelte create mode 100644 test/sourcemaps/samples/sourcemap-basename/test.js diff --git a/test/sourcemaps/samples/sourcemap-basename/_config.js b/test/sourcemaps/samples/sourcemap-basename/_config.js new file mode 100644 index 000000000000..d50dd882a685 --- /dev/null +++ b/test/sourcemaps/samples/sourcemap-basename/_config.js @@ -0,0 +1,33 @@ +import { magic_string_bundle } from '../../helpers'; + +export const component_filepath = 'src/input.svelte'; + +export const component_file_basename = 'input.svelte'; + +// as output by external tool for src/external_code.css (relative to src/input.svelte) +export const external_relative_filename = 'external_code.css'; + +const external_code = ` +span { + --external_code-var: 1px; +} +`; + +export default { + css_map_sources: [external_relative_filename], + js_map_sources: [], + preprocess: [ + { + style: ({ content, filename }) => { + const external =`/* Filename from preprocess: ${filename} */` + external_code; + return magic_string_bundle([ + { code: external, filename: external_relative_filename }, + { code: content, filename } + ]); + } + } + ], + options: { + filename: component_filepath + } +}; diff --git a/test/sourcemaps/samples/sourcemap-basename/input.svelte b/test/sourcemaps/samples/sourcemap-basename/input.svelte new file mode 100644 index 000000000000..72e524a30834 --- /dev/null +++ b/test/sourcemaps/samples/sourcemap-basename/input.svelte @@ -0,0 +1,3 @@ + + +Hello world diff --git a/test/sourcemaps/samples/sourcemap-basename/test.js b/test/sourcemaps/samples/sourcemap-basename/test.js new file mode 100644 index 000000000000..34f650472254 --- /dev/null +++ b/test/sourcemaps/samples/sourcemap-basename/test.js @@ -0,0 +1,15 @@ +import { component_filepath, component_file_basename, external_relative_filename } from './_config'; + +export function test({ assert, preprocessed }) { + assert.notEqual( + preprocessed.locate(`/* Filename from preprocess: ${component_filepath} */`), + undefined, + 'Preprocessor should receive same value for filename as passed to preprocess function' + ); + + assert.deepEqual( + preprocessed.map.sources.slice().sort(), + [external_relative_filename, component_file_basename].sort(), + 'Preprocessed map should contain sources relative to filepath' + ); +} From 35d7628e13b6593e2128666320bc421a2b549da5 Mon Sep 17 00:00:00 2001 From: dmitrage Date: Sun, 13 Dec 2020 02:12:15 +0300 Subject: [PATCH 09/11] Fix and cover case when preprocessor returns no source map --- src/compiler/utils/string_with_sourcemap.ts | 5 +-- test/sourcemaps/helpers.ts | 30 ++++++++++++++++ .../samples/preprocess-no-map/_config.js | 13 +++++++ .../samples/preprocess-no-map/input.svelte | 13 +++++++ .../samples/preprocess-no-map/test.js | 36 +++++++++++++++++++ 5 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 test/sourcemaps/samples/preprocess-no-map/_config.js create mode 100644 test/sourcemaps/samples/preprocess-no-map/input.svelte create mode 100644 test/sourcemaps/samples/preprocess-no-map/test.js diff --git a/src/compiler/utils/string_with_sourcemap.ts b/src/compiler/utils/string_with_sourcemap.ts index 1707c86aac53..1766a0db069a 100644 --- a/src/compiler/utils/string_with_sourcemap.ts +++ b/src/compiler/utils/string_with_sourcemap.ts @@ -167,11 +167,13 @@ export class StringWithSourcemap { } static from_processed(string: string, map?: DecodedSourceMap): StringWithSourcemap { + const line_count = string.split('\n').length; + if (map) { // ensure that count of source map mappings lines // is equal to count of generated code lines // (some tools may produce less) - const missing_lines = string.split('\n').length - map.mappings.length; + const missing_lines = line_count - map.mappings.length; for (let i = 0; i < missing_lines; i++) { map.mappings.push([]); } @@ -182,7 +184,6 @@ export class StringWithSourcemap { map = { version: 3, names: [], sources: [], mappings: [] }; // add empty SourceMapSegment[] for every line - const line_count = (string.match(/\n/g) || '').length; for (let i = 0; i < line_count; i++) map.mappings.push([]); return new StringWithSourcemap(string, map); } diff --git a/test/sourcemaps/helpers.ts b/test/sourcemaps/helpers.ts index c1a6e6798caa..f546566a95ce 100644 --- a/test/sourcemaps/helpers.ts +++ b/test/sourcemaps/helpers.ts @@ -43,6 +43,36 @@ export function assert_mapped( ); } +type AssertNotMappedParameters = { + code: string; + filename?: string; + preprocessed: any; +}; + +export function assert_not_mapped( + { code, filename, preprocessed }: AssertNotMappedParameters +) { + if (filename === undefined) filename = 'input.svelte'; + + const transformed_loc = preprocessed.locate_1(code); + assert.notEqual( + transformed_loc, + undefined, + `failed to locate "${code}" in transformed "${filename}"` + ); + + assert.deepEqual( + preprocessed.mapConsumer.originalPositionFor(transformed_loc), + { + source: null, + name: null, + line: null, + column: null + }, + `incorrect mappings for "${code}" in "${filename}"` + ); +} + export function assert_not_located( code: string, locate: ReturnType, diff --git a/test/sourcemaps/samples/preprocess-no-map/_config.js b/test/sourcemaps/samples/preprocess-no-map/_config.js new file mode 100644 index 000000000000..d9ac6f3c0b68 --- /dev/null +++ b/test/sourcemaps/samples/preprocess-no-map/_config.js @@ -0,0 +1,13 @@ +export default { + css_map_sources: [], + preprocess: [ + { + style: ({ content }) => { + return { code: content }; + }, + script: ({ content }) => { + return { code: content }; + } + } + ] +}; diff --git a/test/sourcemaps/samples/preprocess-no-map/input.svelte b/test/sourcemaps/samples/preprocess-no-map/input.svelte new file mode 100644 index 000000000000..febfa5191b4b --- /dev/null +++ b/test/sourcemaps/samples/preprocess-no-map/input.svelte @@ -0,0 +1,13 @@ + + +
+
{name}
+
+ + diff --git a/test/sourcemaps/samples/preprocess-no-map/test.js b/test/sourcemaps/samples/preprocess-no-map/test.js new file mode 100644 index 000000000000..89afd9961b88 --- /dev/null +++ b/test/sourcemaps/samples/preprocess-no-map/test.js @@ -0,0 +1,36 @@ +import { assert_mapped, assert_not_mapped } from '../../helpers'; + +export function test({ input, preprocessed }) { + // markup (start) + assert_mapped({ + code: '