From 4d186aa1b0d6279bf8c146d294d9f28c1468745c Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Thu, 1 Dec 2016 09:40:39 -0500 Subject: [PATCH 1/4] dont use options.filename for original code when generating magicstring bundle (#43) --- compiler/generate/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/generate/index.js b/compiler/generate/index.js index f73b4a90b30c..ba984c626395 100644 --- a/compiler/generate/index.js +++ b/compiler/generate/index.js @@ -508,7 +508,6 @@ export default function generate ( parsed, source, options ) { function addString ( str ) { compiled.addSource({ - filename: options.filename, content: new MagicString( str ) }); } From 5e8a25fe65fd473c092ed98a49166c0c6d8dec23 Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Thu, 1 Dec 2016 11:50:10 -0500 Subject: [PATCH 2/4] add infrastructure for sourcemap tests --- package.json | 1 + test/sourcemaps/basic/input.html | 9 +++++++++ test/sourcemaps/basic/solo | 0 test/sourcemaps/basic/test.js | 7 +++++++ test/test.js | 22 ++++++++++++++++++++++ 5 files changed, 39 insertions(+) create mode 100644 test/sourcemaps/basic/input.html create mode 100644 test/sourcemaps/basic/solo create mode 100644 test/sourcemaps/basic/test.js diff --git a/package.json b/package.json index 96bcdcf10bdf..9f227ccf5aed 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "rollup-plugin-buble": "^0.14.0", "rollup-plugin-commonjs": "^5.0.5", "rollup-plugin-node-resolve": "^2.0.0", + "source-map": "^0.5.6", "source-map-support": "^0.4.6" }, "nyc": { diff --git a/test/sourcemaps/basic/input.html b/test/sourcemaps/basic/input.html new file mode 100644 index 000000000000..785dbb2d68d8 --- /dev/null +++ b/test/sourcemaps/basic/input.html @@ -0,0 +1,9 @@ +{{foo.bar.baz}} + + diff --git a/test/sourcemaps/basic/solo b/test/sourcemaps/basic/solo new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/sourcemaps/basic/test.js b/test/sourcemaps/basic/test.js new file mode 100644 index 000000000000..6c8d94128c5e --- /dev/null +++ b/test/sourcemaps/basic/test.js @@ -0,0 +1,7 @@ +export function test ( assert, code, map, smc, locator ) { + console.log( `code`, code ) + console.log( `map`, map ) + + let loc = locator( 'foo.bar.baz' ); + console.log( `loc`, loc ) +} diff --git a/test/test.js b/test/test.js index 9d132849e3c8..a956ac985228 100644 --- a/test/test.js +++ b/test/test.js @@ -5,6 +5,8 @@ import * as path from 'path'; import * as fs from 'fs'; import jsdom from 'jsdom'; import * as acorn from 'acorn'; +import { SourceMapConsumer } from 'source-map'; +import { getLocator } from 'locate-character'; import * as consoleGroup from 'console-group'; consoleGroup.install(); @@ -468,4 +470,24 @@ describe( 'svelte', () => { }); }); }); + + describe( 'sourcemaps', () => { + fs.readdirSync( 'test/sourcemaps' ).forEach( dir => { + if ( dir[0] === '.' ) return; + + const solo = exists( `test/sourcemaps/${dir}/solo` ); + + ( solo ? it.only : it )( dir, () => { + const input = fs.readFileSync( `test/sourcemaps/${dir}/input.html`, 'utf-8' ).replace( /\s+$/, '' ); + const { code, map } = svelte.compile( input ); + + const { test } = require( `./sourcemaps/${dir}/test.js` ); + + const smc = new SourceMapConsumer( map ); + const locator = getLocator( code ); + + test( assert, code, map, smc, locator ); + }); + }); + }); }); From 695cfd01c9f7e6ffd0527fc9ba59fa1d7699b8eb Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 1 Dec 2016 17:37:23 -0500 Subject: [PATCH 3/4] more sourcemap stuff --- .gitignore | 2 ++ compiler/generate/index.js | 7 +++++-- test/sourcemaps/basic/test.js | 19 ++++++++++++++----- test/test.js | 9 +++++++-- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index b0081af1daac..e3eea17ef7d3 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ dist .nyc_output coverage coverage.lcov +test/sourcemaps/*/output.js +test/sourcemaps/*/output.js.map diff --git a/compiler/generate/index.js b/compiler/generate/index.js index ba984c626395..7bcdd46fcc58 100644 --- a/compiler/generate/index.js +++ b/compiler/generate/index.js @@ -514,13 +514,16 @@ export default function generate ( parsed, source, options ) { addString( getIntro( format, options, imports ) ); + // a filename is necessary for sourcemap generation + const filename = options.filename || 'SvelteComponent.html'; + parts.forEach( str => { const match = pattern.exec( str ); addString( str.replace( pattern, '' ) ); compiled.addSource({ - filename: options.filename, + filename, content: generator.code.snip( +match[1], +match[2] ) }); }); @@ -531,6 +534,6 @@ export default function generate ( parsed, source, options ) { return { code: compiled.toString(), - map: compiled.generateMap() + map: compiled.generateMap({ includeContent: true }) }; } diff --git a/test/sourcemaps/basic/test.js b/test/sourcemaps/basic/test.js index 6c8d94128c5e..295e7b223038 100644 --- a/test/sourcemaps/basic/test.js +++ b/test/sourcemaps/basic/test.js @@ -1,7 +1,16 @@ -export function test ( assert, code, map, smc, locator ) { - console.log( `code`, code ) - console.log( `map`, map ) +export function test ({ assert, smc, locateInSource, locateInGenerated }) { + const expected = locateInSource( 'foo.bar.baz' ); + const loc = locateInGenerated( 'foo.bar.baz' ); - let loc = locator( 'foo.bar.baz' ); - console.log( `loc`, loc ) + const actual = smc.originalPositionFor({ + line: loc.line + 1, + column: loc.column + }); + + assert.deepEqual( actual, { + source: 'SvelteComponent.html', + name: null, + line: expected.line, + column: expected.column + }); } diff --git a/test/test.js b/test/test.js index a956ac985228..1738c5e5ad5b 100644 --- a/test/test.js +++ b/test/test.js @@ -481,12 +481,17 @@ describe( 'svelte', () => { const input = fs.readFileSync( `test/sourcemaps/${dir}/input.html`, 'utf-8' ).replace( /\s+$/, '' ); const { code, map } = svelte.compile( input ); + fs.writeFileSync( `test/sourcemaps/${dir}/output.js`, `${code}\n//# sourceMappingURL=output.js.map` ); + fs.writeFileSync( `test/sourcemaps/${dir}/output.js.map`, JSON.stringify( map, null, ' ' ) ); + const { test } = require( `./sourcemaps/${dir}/test.js` ); const smc = new SourceMapConsumer( map ); - const locator = getLocator( code ); - test( assert, code, map, smc, locator ); + const locateInSource = getLocator( input ); + const locateInGenerated = getLocator( code ); + + test({ assert, code, map, smc, locateInSource, locateInGenerated }); }); }); }); From 57f94d4d0bffcf12bf285f3cdf28a7a8e43f071f Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Fri, 2 Dec 2016 11:26:16 -0500 Subject: [PATCH 4/4] upgrade magic-string, fix sourcemaps --- compiler/generate/index.js | 25 +++++++++++-------- .../attributes/addComponentAttributes.js | 2 +- .../attributes/addElementAttributes.js | 2 +- package.json | 2 +- test/sourcemaps/basic/input.html | 8 ------ test/sourcemaps/basic/solo | 0 test/sourcemaps/basic/test.js | 24 +++++++++++++++--- test/sourcemaps/script/input.html | 9 +++++++ test/sourcemaps/script/test.js | 16 ++++++++++++ 9 files changed, 63 insertions(+), 25 deletions(-) delete mode 100644 test/sourcemaps/basic/solo create mode 100644 test/sourcemaps/script/input.html create mode 100644 test/sourcemaps/script/test.js diff --git a/compiler/generate/index.js b/compiler/generate/index.js index 7bcdd46fcc58..347d7062cfd2 100644 --- a/compiler/generate/index.js +++ b/compiler/generate/index.js @@ -86,7 +86,7 @@ export default function generate ( parsed, source, options ) { const { name } = flattenReference( node ); if ( parent && parent.type === 'CallExpression' && node === parent.callee ) { - if ( generator.helpers[ name ] ) generator.code.insertRight( node.start, `template.helpers.` ); + if ( generator.helpers[ name ] ) generator.code.prependRight( node.start, `template.helpers.` ); return; } @@ -102,7 +102,7 @@ export default function generate ( parsed, source, options ) { if ( !~usedContexts.indexOf( context ) ) usedContexts.push( context ); } else { dependencies.push( node.name ); - generator.code.insertRight( node.start, `root.` ); + generator.code.prependRight( node.start, `root.` ); if ( !~usedContexts.indexOf( 'root' ) ) usedContexts.push( 'root' ); } @@ -204,19 +204,19 @@ export default function generate ( parsed, source, options ) { while ( /\s/.test( source[ i - 1 ] ) ) i--; const indentation = source.slice( i, defaultExport.start ); - generator.code.insertLeft( finalNode.end, `\n\n${indentation}return template;` ); + generator.code.appendLeft( finalNode.end, `\n\n${indentation}return template;` ); } defaultExport.declaration.properties.forEach( prop => { templateProperties[ prop.key.name ] = prop.value; }); - generator.code.insertRight( parsed.js.content.start, 'var template = (function () {' ); + generator.code.prependRight( parsed.js.content.start, 'var template = (function () {' ); } else { - generator.code.insertRight( parsed.js.content.start, '(function () {' ); + generator.code.prependRight( parsed.js.content.start, '(function () {' ); } - generator.code.insertLeft( parsed.js.content.end, '}());' ); + generator.code.appendLeft( parsed.js.content.end, '}());' ); [ 'helpers', 'events', 'components' ].forEach( key => { if ( templateProperties[ key ] ) { @@ -512,24 +512,27 @@ export default function generate ( parsed, source, options ) { }); } - addString( getIntro( format, options, imports ) ); + const intro = getIntro( format, options, imports ); + if ( intro ) addString( intro ); // a filename is necessary for sourcemap generation const filename = options.filename || 'SvelteComponent.html'; parts.forEach( str => { + const chunk = str.replace( pattern, '' ); + if ( chunk ) addString( chunk ); + const match = pattern.exec( str ); - addString( str.replace( pattern, '' ) ); + const snippet = generator.code.snip( +match[1], +match[2] ); compiled.addSource({ filename, - content: generator.code.snip( +match[1], +match[2] ) + content: snippet }); }); - compiled.append( finalChunk ); - + addString( finalChunk ); addString( '\n\n' + getOutro( format, constructorName, options, imports ) ); return { diff --git a/compiler/generate/visitors/attributes/addComponentAttributes.js b/compiler/generate/visitors/attributes/addComponentAttributes.js index 9995352dc8ef..47609e9c8194 100644 --- a/compiler/generate/visitors/attributes/addComponentAttributes.js +++ b/compiler/generate/visitors/attributes/addComponentAttributes.js @@ -80,7 +80,7 @@ export default function addComponentAttributes ( generator, node, local ) { else if ( attribute.type === 'EventHandler' ) { // TODO verify that it's a valid callee (i.e. built-in or declared method) generator.addSourcemapLocations( attribute.expression ); - generator.code.insertRight( attribute.expression.start, 'component.' ); + generator.code.prependRight( attribute.expression.start, 'component.' ); const usedContexts = new Set(); attribute.expression.arguments.forEach( arg => { diff --git a/compiler/generate/visitors/attributes/addElementAttributes.js b/compiler/generate/visitors/attributes/addElementAttributes.js index 8637266ffdd5..6f372b24ee4d 100644 --- a/compiler/generate/visitors/attributes/addElementAttributes.js +++ b/compiler/generate/visitors/attributes/addElementAttributes.js @@ -116,7 +116,7 @@ export default function addElementAttributes ( generator, node, local ) { else if ( attribute.type === 'EventHandler' ) { // TODO verify that it's a valid callee (i.e. built-in or declared method) generator.addSourcemapLocations( attribute.expression ); - generator.code.insertRight( attribute.expression.start, 'component.' ); + generator.code.prependRight( attribute.expression.start, 'component.' ); const usedContexts = new Set(); attribute.expression.arguments.forEach( arg => { diff --git a/package.json b/package.json index 9f227ccf5aed..fdd79c6f0494 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "fuzzyset.js": "0.0.1", "jsdom": "^9.8.3", "locate-character": "^2.0.0", - "magic-string": "^0.16.0", + "magic-string": "^0.19.0", "mocha": "^3.1.2", "node-resolve": "^1.3.3", "nyc": "^9.0.1", diff --git a/test/sourcemaps/basic/input.html b/test/sourcemaps/basic/input.html index 785dbb2d68d8..ed83093fa9af 100644 --- a/test/sourcemaps/basic/input.html +++ b/test/sourcemaps/basic/input.html @@ -1,9 +1 @@ {{foo.bar.baz}} - - diff --git a/test/sourcemaps/basic/solo b/test/sourcemaps/basic/solo deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/test/sourcemaps/basic/test.js b/test/sourcemaps/basic/test.js index 295e7b223038..b169b04f7a08 100644 --- a/test/sourcemaps/basic/test.js +++ b/test/sourcemaps/basic/test.js @@ -1,8 +1,26 @@ export function test ({ assert, smc, locateInSource, locateInGenerated }) { const expected = locateInSource( 'foo.bar.baz' ); - const loc = locateInGenerated( 'foo.bar.baz' ); - const actual = smc.originalPositionFor({ + let loc; + let actual; + + loc = locateInGenerated( 'foo.bar.baz' ); + + actual = smc.originalPositionFor({ + line: loc.line + 1, + column: loc.column + }); + + assert.deepEqual( actual, { + source: 'SvelteComponent.html', + name: null, + line: expected.line + 1, + column: expected.column + }); + + loc = locateInGenerated( 'foo.bar.baz', loc.character + 1 ); + + actual = smc.originalPositionFor({ line: loc.line + 1, column: loc.column }); @@ -10,7 +28,7 @@ export function test ({ assert, smc, locateInSource, locateInGenerated }) { assert.deepEqual( actual, { source: 'SvelteComponent.html', name: null, - line: expected.line, + line: expected.line + 1, column: expected.column }); } diff --git a/test/sourcemaps/script/input.html b/test/sourcemaps/script/input.html new file mode 100644 index 000000000000..c4dc11d3a0f3 --- /dev/null +++ b/test/sourcemaps/script/input.html @@ -0,0 +1,9 @@ +
+ + diff --git a/test/sourcemaps/script/test.js b/test/sourcemaps/script/test.js new file mode 100644 index 000000000000..6b14b91a9d5d --- /dev/null +++ b/test/sourcemaps/script/test.js @@ -0,0 +1,16 @@ +export function test ({ assert, smc, locateInSource, locateInGenerated }) { + const expected = locateInSource( '42' ); + const loc = locateInGenerated( '42' ); + + const actual = smc.originalPositionFor({ + line: loc.line + 1, + column: loc.column + }); + + assert.deepEqual( actual, { + source: 'SvelteComponent.html', + name: null, + line: expected.line + 1, + column: expected.column + }); +}