diff --git a/src/compiler/preprocess/index.ts b/src/compiler/preprocess/index.ts index 660a327e2d..e0847898d5 100644 --- a/src/compiler/preprocess/index.ts +++ b/src/compiler/preprocess/index.ts @@ -175,7 +175,8 @@ function get_replacement( original: string, processed: Processed, prefix: string, - suffix: string + suffix: string, + tag_name: 'script' | 'style' ): StringWithSourcemap { // Convert the unchanged prefix and suffix to StringWithSourcemap @@ -184,7 +185,7 @@ function get_replacement( const suffix_with_map = StringWithSourcemap.from_source( file_basename, suffix, get_location(offset + prefix.length + original.length)); - parse_attached_sourcemap(processed); + parse_attached_sourcemap(processed, tag_name); // Convert the preprocessed code and its sourcemap to a StringWithSourcemap let decoded_map: DecodedSourceMap; @@ -289,7 +290,7 @@ export default async function preprocess( if (!processed || !processed.map && processed.code === content) { return no_change(); } - return get_replacement(file_basename, offset, get_location, content, processed, `<${tag_name}${attributes}>`, ``); + return get_replacement(file_basename, offset, get_location, content, processed, `<${tag_name}${attributes}>`, ``, tag_name); } ); source = res.string; diff --git a/src/compiler/utils/string_with_sourcemap.ts b/src/compiler/utils/string_with_sourcemap.ts index dc182a6321..b0507aa2f8 100644 --- a/src/compiler/utils/string_with_sourcemap.ts +++ b/src/compiler/utils/string_with_sourcemap.ts @@ -292,13 +292,14 @@ export function apply_preprocessor_sourcemap(filename: string, svelte_map: Sourc } // parse attached sourcemap in processed.code -export function parse_attached_sourcemap(processed: Processed): void { - const magic_prefix = '\n/*# sourceMappingURL=data:application/json;'; +export function parse_attached_sourcemap(processed: Processed, tag_name: 'script' | 'style'): void { + const magic_prefix = '# sourceMappingURL=data:application/json;'; const cut_index = processed.code.lastIndexOf('\n'); const last_line = processed.code.slice(cut_index); - if (magic_prefix != last_line.slice(0, magic_prefix.length)) { - return; // attachment not found - } + const line_start = last_line.slice(1, 3); // last_line[0] == '\n' + if ((line_start != '/*' && (tag_name == 'script' && line_start != '//')) || + magic_prefix != last_line.slice(3, 3 + magic_prefix.length) + ) return; // attachment not found if (processed.map) { throw 'not implemented. '+ 'found sourcemap in both processed.code and processed.map. '+ @@ -306,9 +307,8 @@ export function parse_attached_sourcemap(processed: Processed): void { 'processed.code:\n'+ processed.code.slice(0, 100)+' [....]'; // help to find preprocessor } - // remove last line - processed.code = processed.code.slice(0, cut_index); - // slice to -2 --> remove trailing '*/' - const b64map = last_line.slice(last_line.indexOf('base64,')+7, -2).trim(); + processed.code = processed.code.slice(0, cut_index); // remove last line + const slice_to = (line_start == '/*') ? -2 : undefined; + const b64map = last_line.slice(last_line.indexOf('base64,')+7, slice_to).trim(); processed.map = b64dec(b64map); } diff --git a/test/sourcemaps/index.ts b/test/sourcemaps/index.ts index f00c2ced33..903629c06b 100644 --- a/test/sourcemaps/index.ts +++ b/test/sourcemaps/index.ts @@ -42,7 +42,7 @@ describe('sourcemaps', () => { filename: 'input.svelte' } ); - + const { js, css } = svelte.compile( preprocessed.code, { filename: 'input.svelte', diff --git a/test/sourcemaps/samples/attached-sourcemap/_config.js b/test/sourcemaps/samples/attached-sourcemap/_config.js index 588ab7515c..6d9786f6b0 100644 --- a/test/sourcemaps/samples/attached-sourcemap/_config.js +++ b/test/sourcemaps/samples/attached-sourcemap/_config.js @@ -1,37 +1,44 @@ import MagicString from 'magic-string'; let indent_size = 4; -function get_processor(search, replace) { - return ({ content, filename }) => { - let code = content.slice(); - const ms = new MagicString(code); - - const idx = ms.original.indexOf(search); - if (idx == -1) throw new Error('search not found in src'); - ms.overwrite(idx, idx + search.length, replace, { storeName: true }); - - // change line + column - const indent = Array.from({ length: indent_size }).join(' '); - ms.prependLeft(idx, '\n'+indent); - - const map_opts = { source: filename, hires: true, includeContent: false }; - const map = ms.generateMap(map_opts); - const attach_line = `\n/*# sourceMappingURL=${map.toUrl()} */`; - code = ms.toString() + attach_line; - - indent_size += 2; - return { code }; +let comment_multi = true; +function get_processor(tag_name, search, replace) { + return { + [tag_name]: ({ content, filename }) => { + let code = content.slice(); + const ms = new MagicString(code); + + const idx = ms.original.indexOf(search); + if (idx == -1) throw new Error('search not found in src'); + ms.overwrite(idx, idx + search.length, replace, { storeName: true }); + + // change line + column + const indent = Array.from({ length: indent_size }).join(' '); + ms.prependLeft(idx, '\n'+indent); + + const map_opts = { source: filename, hires: true, includeContent: false }; + const map = ms.generateMap(map_opts); + const attach_line = (tag_name == 'style' || comment_multi) + ? `\n/*# sourceMappingURL=${map.toUrl()} */` + : `\n//# sourceMappingURL=${map.toUrl()}` // only in script + ; + code = ms.toString() + attach_line; + + indent_size += 2; + if (tag_name == 'script') comment_multi = !comment_multi; + return { code }; + } }; } export default { preprocess: [ - { script: get_processor('replace_me_script', 'done_replace_script_1') }, - { script: get_processor('done_replace_script_1', 'done_replace_script_2') }, + get_processor('script', 'replace_me_script', 'done_replace_script_1'), + get_processor('script', 'done_replace_script_1', 'done_replace_script_2'), - { style: get_processor('.replace_me_style', '.done_replace_style_1') }, - { style: get_processor('.done_replace_style_1', '.done_replace_style_2') } + get_processor('style', '.replace_me_style', '.done_replace_style_1'), + get_processor('style', '.done_replace_style_1', '.done_replace_style_2') ] };