[Pkg-javascript-commits] [node-magic-string] 01/06: New upstream version 0.19.0
Julien Puydt
julien.puydt at laposte.net
Wed Dec 7 07:23:28 UTC 2016
This is an automated email from the git hooks/post-receive script.
jpuydt-guest pushed a commit to branch master
in repository node-magic-string.
commit 948813531e8a2d7ca87a0b5ed0f75e75b31d7fba
Author: Julien Puydt <julien.puydt at laposte.net>
Date: Mon Dec 5 10:20:15 2016 +0100
New upstream version 0.19.0
---
CHANGELOG.md | 4 ++
package.json | 2 +-
src/Bundle.js | 71 +++++++++++++++--------
src/MagicString.js | 30 ++++++++--
src/utils/Mappings.js | 117 +++++++++++++++++++++++++++++++++++++
src/utils/encodeMappings.js | 137 --------------------------------------------
src/utils/getSemis.js | 3 -
test/MagicString.Bundle.js | 102 ++++++++++++++++++++++++++++++++-
8 files changed, 292 insertions(+), 174 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fa2153f..c1f13db 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
# magic-string changelog
+## 0.19.0
+
+* More accurate bundle sourcemaps ([#114](https://github.com/Rich-Harris/magic-string/pull/114))
+
## 0.18.0
* Optimisation – remove empty chunks following `overwrite` or `remove` ([#113](https://github.com/Rich-Harris/magic-string/pull/113))
diff --git a/package.json b/package.json
index 486e862..245ac73 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "magic-string",
"description": "Modify strings, generate sourcemaps",
"author": "Rich Harris",
- "version": "0.18.0",
+ "version": "0.19.0",
"repository": "https://github.com/rich-harris/magic-string",
"main": "dist/magic-string.cjs.js",
"module": "dist/magic-string.es.js",
diff --git a/src/Bundle.js b/src/Bundle.js
index 0f3786a..8a11683 100644
--- a/src/Bundle.js
+++ b/src/Bundle.js
@@ -1,9 +1,10 @@
import MagicString from './MagicString.js';
import SourceMap from './utils/SourceMap.js';
-import getSemis from './utils/getSemis.js';
import getRelativePath from './utils/getRelativePath.js';
import hasOwnProp from './utils/hasOwnProp.js';
import isObject from './utils/isObject.js';
+import getLocator from './utils/getLocator.js';
+import Mappings from './utils/Mappings.js';
export default function Bundle ( options = {} ) {
this.intro = options.intro || '';
@@ -87,6 +88,50 @@ Bundle.prototype = {
});
});
+ const mappings = new Mappings( options.hires );
+
+ if ( this.intro ) {
+ mappings.advance( this.intro );
+ }
+
+ this.sources.forEach( ( source, i ) => {
+ if ( i > 0 ) {
+ mappings.advance( this.separator );
+ }
+
+ const sourceIndex = source.filename ? this.uniqueSourceIndexByFilename[ source.filename ] : -1;
+ const magicString = source.content;
+ const locate = getLocator( magicString.original );
+
+ if ( magicString.intro ) {
+ mappings.advance( magicString.intro );
+ }
+
+ magicString.firstChunk.eachNext( chunk => {
+ const loc = locate( chunk.start );
+
+ if ( chunk.intro.length ) mappings.advance( chunk.intro );
+
+ if ( source.filename ) {
+ if ( chunk.edited ) {
+ mappings.addEdit( sourceIndex, chunk.content, chunk.original, loc, chunk.storeName ? names.indexOf( chunk.original ) : -1 );
+ } else {
+ mappings.addUneditedChunk( sourceIndex, chunk, magicString.original, loc, magicString.sourcemapLocations );
+ }
+ }
+
+ else {
+ mappings.advance( chunk.content );
+ }
+
+ if ( chunk.outro.length ) mappings.advance( chunk.outro );
+ });
+
+ if ( magicString.outro ) {
+ mappings.advance( magicString.outro );
+ }
+ });
+
return new SourceMap({
file: ( options.file ? options.file.split( /[\/\\]/ ).pop() : null ),
sources: this.uniqueSources.map( source => {
@@ -96,32 +141,10 @@ Bundle.prototype = {
return options.includeContent ? source.content : null;
}),
names,
- mappings: this.getMappings( options, names )
+ mappings: mappings.encode()
});
},
- getMappings ( options, names ) {
- const offsets = {};
-
- return (
- getSemis( this.intro ) +
- this.sources.map( ( source, i ) => {
- const prefix = ( i > 0 ) ? ( getSemis( source.separator ) || ',' ) : '';
- let mappings;
-
- // we don't bother encoding sources without a filename
- if ( !source.filename ) {
- mappings = getSemis( source.content.toString() );
- } else {
- const sourceIndex = this.uniqueSourceIndexByFilename[ source.filename ];
- mappings = source.content.getMappings( options, sourceIndex, offsets, names );
- }
-
- return prefix + mappings;
- }).join( '' )
- );
- },
-
getIndentString () {
const indentStringCounts = {};
diff --git a/src/MagicString.js b/src/MagicString.js
index 7fc93d1..af851f2 100644
--- a/src/MagicString.js
+++ b/src/MagicString.js
@@ -1,10 +1,10 @@
import Chunk from './Chunk.js';
import SourceMap from './utils/SourceMap.js';
import guessIndent from './utils/guessIndent.js';
-import encodeMappings from './utils/encodeMappings.js';
import getRelativePath from './utils/getRelativePath.js';
import isObject from './utils/isObject.js';
import getLocator from './utils/getLocator.js';
+import Mappings from './utils/Mappings.js';
import Stats from './utils/Stats.js';
const warned = {
@@ -130,7 +130,29 @@ MagicString.prototype = {
generateMap ( options ) {
options = options || {};
+ const sourceIndex = 0;
const names = Object.keys( this.storedNames );
+ const mappings = new Mappings( options.hires );
+
+ const locate = getLocator( this.original );
+
+ if ( this.intro ) {
+ mappings.advance( this.intro );
+ }
+
+ this.firstChunk.eachNext( chunk => {
+ const loc = locate( chunk.start );
+
+ if ( chunk.intro.length ) mappings.advance( chunk.intro );
+
+ if ( chunk.edited ) {
+ mappings.addEdit( sourceIndex, chunk.content, chunk.original, loc, chunk.storeName ? names.indexOf( chunk.original ) : -1 );
+ } else {
+ mappings.addUneditedChunk( sourceIndex, chunk, this.original, loc, this.sourcemapLocations );
+ }
+
+ if ( chunk.outro.length ) mappings.advance( chunk.outro );
+ });
if ( DEBUG ) this.stats.time( 'generateMap' );
const map = new SourceMap({
@@ -138,7 +160,7 @@ MagicString.prototype = {
sources: [ options.source ? getRelativePath( options.file || '', options.source ) : null ],
sourcesContent: options.includeContent ? [ this.original ] : [ null ],
names,
- mappings: this.getMappings( options, 0, {}, names )
+ mappings: mappings.encode()
});
if ( DEBUG ) this.stats.timeEnd( 'generateMap' );
@@ -149,10 +171,6 @@ MagicString.prototype = {
return this.indentStr === null ? '\t' : this.indentStr;
},
- getMappings ( options, sourceIndex, offsets, names ) {
- return encodeMappings( this.original, this.intro, this.outro, this.firstChunk, options.hires, this.sourcemapLocations, sourceIndex, offsets, names );
- },
-
indent ( indentStr, options ) {
const pattern = /^[^\r\n]/gm;
diff --git a/src/utils/Mappings.js b/src/utils/Mappings.js
new file mode 100644
index 0000000..b32cf0e
--- /dev/null
+++ b/src/utils/Mappings.js
@@ -0,0 +1,117 @@
+import { encode } from 'vlq';
+
+export default function Mappings ( hires ) {
+ const offsets = {
+ generatedCodeColumn: 0,
+ sourceIndex: 0,
+ sourceCodeLine: 0,
+ sourceCodeColumn: 0,
+ sourceCodeName: 0
+ };
+
+ let generatedCodeLine = 0;
+ let generatedCodeColumn = 0;
+
+ this.raw = [];
+ let rawSegments = this.raw[ generatedCodeLine ] = [];
+
+ let pending = null;
+
+ this.addEdit = ( sourceIndex, content, original, loc, nameIndex ) => {
+ if ( content.length ) {
+ rawSegments.push([
+ generatedCodeColumn,
+ sourceIndex,
+ loc.line,
+ loc.column,
+ nameIndex,
+ ]);
+ } else if ( pending ) {
+ rawSegments.push( pending );
+ }
+
+ this.advance( content );
+ pending = null;
+ };
+
+ this.addUneditedChunk = ( sourceIndex, chunk, original, loc, sourcemapLocations ) => {
+ let originalCharIndex = chunk.start;
+ let first = true;
+
+ while ( originalCharIndex < chunk.end ) {
+ if ( hires || first || sourcemapLocations[ originalCharIndex ] ) {
+ rawSegments.push([
+ generatedCodeColumn,
+ sourceIndex,
+ loc.line,
+ loc.column,
+ -1
+ ]);
+ }
+
+ if ( original[ originalCharIndex ] === '\n' ) {
+ loc.line += 1;
+ loc.column = 0;
+ generatedCodeLine += 1;
+ this.raw[ generatedCodeLine ] = rawSegments = [];
+ generatedCodeColumn = 0;
+ } else {
+ loc.column += 1;
+ generatedCodeColumn += 1;
+ }
+
+ originalCharIndex += 1;
+ first = false;
+ }
+
+ pending = [
+ generatedCodeColumn,
+ sourceIndex,
+ loc.line,
+ loc.column,
+ -1,
+ ];
+ };
+
+ this.advance = str => {
+ if ( !str ) return;
+
+ const lines = str.split( '\n' );
+ const lastLine = lines.pop();
+
+ if ( lines.length ) {
+ generatedCodeLine += lines.length;
+ this.raw[ generatedCodeLine ] = rawSegments = [];
+ generatedCodeColumn = lastLine.length;
+ } else {
+ generatedCodeColumn += lastLine.length;
+ }
+ };
+
+ this.encode = () => {
+ return this.raw.map( segments => {
+ let generatedCodeColumn = 0;
+
+ return segments.map( segment => {
+ const arr = [
+ segment[0] - generatedCodeColumn,
+ segment[1] - offsets.sourceIndex,
+ segment[2] - offsets.sourceCodeLine,
+ segment[3] - offsets.sourceCodeColumn
+ ];
+
+ generatedCodeColumn = segment[0];
+ offsets.sourceIndex = segment[1];
+ offsets.sourceCodeLine = segment[2];
+ offsets.sourceCodeColumn = segment[3];
+
+ if ( ~segment[4] ) {
+ arr.push( segment[4] - offsets.sourceCodeName );
+ offsets.sourceCodeName = segment[4];
+ }
+
+ return encode( arr );
+ }).join( ',' );
+ }).join( ';' );
+ };
+}
diff --git a/src/utils/encodeMappings.js b/src/utils/encodeMappings.js
deleted file mode 100644
index de210e0..0000000
--- a/src/utils/encodeMappings.js
+++ /dev/null
@@ -1,137 +0,0 @@
-import { encode } from 'vlq';
-import getSemis from './getSemis.js';
-import getLocator from './getLocator.js';
-
-const nonWhitespace = /\S/;
-
-export default function encodeMappings ( original, intro, outro, chunk, hires, sourcemapLocations, sourceIndex, offsets, names ) {
- const rawLines = [];
-
- let generatedCodeLine = intro.split( '\n' ).length - 1;
- let rawSegments = rawLines[ generatedCodeLine ] = [];
-
- let generatedCodeColumn = 0;
-
- const locate = getLocator( original );
-
- function addEdit ( content, original, loc, nameIndex, i ) {
- if ( i || ( content.length && nonWhitespace.test( content ) ) ) {
- rawSegments.push({
- generatedCodeLine,
- generatedCodeColumn,
- sourceCodeLine: loc.line,
- sourceCodeColumn: loc.column,
- sourceCodeName: nameIndex,
- sourceIndex
- });
- }
-
- let lines = content.split( '\n' );
- let lastLine = lines.pop();
-
- if ( lines.length ) {
- generatedCodeLine += lines.length;
- rawLines[ generatedCodeLine ] = rawSegments = [];
- generatedCodeColumn = lastLine.length;
- } else {
- generatedCodeColumn += lastLine.length;
- }
-
- lines = original.split( '\n' );
- lastLine = lines.pop();
-
- if ( lines.length ) {
- loc.line += lines.length;
- loc.column = lastLine.length;
- } else {
- loc.column += lastLine.length;
- }
- }
-
- function addUneditedChunk ( chunk, loc ) {
- let originalCharIndex = chunk.start;
- let first = true;
-
- while ( originalCharIndex < chunk.end ) {
- if ( hires || first || sourcemapLocations[ originalCharIndex ] ) {
- rawSegments.push({
- generatedCodeLine,
- generatedCodeColumn,
- sourceCodeLine: loc.line,
- sourceCodeColumn: loc.column,
- sourceCodeName: -1,
- sourceIndex
- });
- }
-
- if ( original[ originalCharIndex ] === '\n' ) {
- loc.line += 1;
- loc.column = 0;
- generatedCodeLine += 1;
- rawLines[ generatedCodeLine ] = rawSegments = [];
- generatedCodeColumn = 0;
- } else {
- loc.column += 1;
- generatedCodeColumn += 1;
- }
-
- originalCharIndex += 1;
- first = false;
- }
- }
-
- let hasContent = false;
-
- while ( chunk ) {
- const loc = locate( chunk.start );
-
- if ( chunk.intro.length ) {
- addEdit( chunk.intro, '', loc, -1, hasContent );
- }
-
- if ( chunk.edited ) {
- addEdit( chunk.content, chunk.original, loc, chunk.storeName ? names.indexOf( chunk.original ) : -1, hasContent );
- } else {
- addUneditedChunk( chunk, loc );
- }
-
- if ( chunk.outro.length ) {
- addEdit( chunk.outro, '', loc, -1, hasContent );
- }
-
- if ( chunk.content || chunk.intro || chunk.outro ) hasContent = true;
-
- const nextChunk = chunk.next;
- chunk = nextChunk;
- }
-
- offsets.sourceIndex = offsets.sourceIndex || 0;
- offsets.sourceCodeLine = offsets.sourceCodeLine || 0;
- offsets.sourceCodeColumn = offsets.sourceCodeColumn || 0;
- offsets.sourceCodeName = offsets.sourceCodeName || 0;
-
- return rawLines.map( segments => {
- let generatedCodeColumn = 0;
-
- return segments.map( segment => {
- const arr = [
- segment.generatedCodeColumn - generatedCodeColumn,
- segment.sourceIndex - offsets.sourceIndex,
- segment.sourceCodeLine - offsets.sourceCodeLine,
- segment.sourceCodeColumn - offsets.sourceCodeColumn
- ];
-
- generatedCodeColumn = segment.generatedCodeColumn;
- offsets.sourceIndex = segment.sourceIndex;
- offsets.sourceCodeLine = segment.sourceCodeLine;
- offsets.sourceCodeColumn = segment.sourceCodeColumn;
-
- if ( ~segment.sourceCodeName ) {
- arr.push( segment.sourceCodeName - offsets.sourceCodeName );
- offsets.sourceCodeName = segment.sourceCodeName;
- }
-
- return encode( arr );
- }).join( ',' );
- }).join( ';' ) + getSemis(outro);
-}
diff --git a/src/utils/getSemis.js b/src/utils/getSemis.js
deleted file mode 100644
index 4ead76e..0000000
--- a/src/utils/getSemis.js
+++ /dev/null
@@ -1,3 +0,0 @@
-export default function getSemis ( str ) {
- return new Array( str.split( '\n' ).length ).join( ';' );
-}
diff --git a/test/MagicString.Bundle.js b/test/MagicString.Bundle.js
index 9033450..f0ce009 100644
--- a/test/MagicString.Bundle.js
+++ b/test/MagicString.Bundle.js
@@ -111,9 +111,6 @@ describe( 'MagicString.Bundle', () => {
assert.deepEqual( map.sources, [ 'foo.js', 'bar.js' ]);
assert.deepEqual( map.sourcesContent, [ 'var answer = 42;', 'console.log( answer );' ]);
- assert.equal( map.toString(), '{"version":3,"file":"bundle.js","sources":["foo.js","bar.js"],"sourcesContent":["var answer = 42;","console.log( answer );"],"names":[],"mappings":"AAAA,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;ACAf,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC"}' );
- assert.equal( map.toUrl(), 'data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVuZGxlLmpzIiwic291cmNlcyI6WyJmb28uanMiLCJiYXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsidmFyIGFuc3dlciA9IDQyOyIsImNvbnNvbGUubG9nKCBhbnN3ZXIgKTsiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUNBZixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE [...]
-
const smc = new SourceMapConsumer( map );
let loc;
@@ -400,6 +397,105 @@ describe( 'MagicString.Bundle', () => {
loc = smc.originalPositionFor({ line: 3, column: 9 });
assert.equal( loc.source, 'two.js' );
});
+
+ it( 'should handle empty separator', () => {
+ const b = new MagicString.Bundle({
+ separator: ''
+ });
+
+ b.addSource({
+ content: new MagicString( 'if ( foo ) { ' )
+ });
+
+ const s = new MagicString( 'console.log( 42 );' );
+ s.addSourcemapLocation( 8 );
+ s.addSourcemapLocation( 15 );
+
+ b.addSource({
+ filename: 'input.js',
+ content: s
+ });
+
+ b.addSource({
+ content: new MagicString( ' }' )
+ });
+
+ assert.equal( b.toString(), 'if ( foo ) { console.log( 42 ); }' );
+
+ const map = b.generateMap({
+ file: 'output.js',
+ source: 'input.js',
+ includeContent: true
+ });
+
+ const smc = new SourceMapConsumer( map );
+ const loc = smc.originalPositionFor({ line: 1, column: 21 });
+
+ assert.deepEqual( loc, {
+ source: 'input.js',
+ name: null,
+ line: 1,
+ column: 8
+ });
+ });
+
+ // TODO tidy this up. is a recreation of a bug in Svelte
+ it( 'generates a correct sourcemap for a Svelte component', () => {
+ const b = new MagicString.Bundle({
+ separator: ''
+ });
+
+ const s = new MagicString( `
+<div></div>
+
+<script>
+ export default {
+ onrender () {
+ console.log( 42 );
+ }
+ }
+</script>`.trim() );
+
+ [ 21, 23, 38, 42, 50, 51, 54, 59, 66, 67, 70, 72, 74, 76, 77, 81, 84, 85 ].forEach( pos => {
+ s.addSourcemapLocation( pos );
+ });
+
+ s.remove( 0, 21 );
+ s.overwrite( 23, 38, 'return ' );
+ s.prependRight( 21, 'var template = (function () {' );
+ s.appendLeft( 85, '}());' );
+ s.overwrite( 85, 94, '' );
+
+ b.addSource({
+ content: s,
+ filename: 'input.js'
+ });
+
+ assert.equal( b.toString(), `
+var template = (function () {
+ return {
+ onrender () {
+ console.log( 42 );
+ }
+ }
+}());`.trim() );
+
+ const map = b.generateMap({
+ file: 'output.js',
+ source: 'input.js',
+ includeContent: true
+ });
+
+ const smc = new SourceMapConsumer( map );
+ const loc = smc.originalPositionFor({ line: 4, column: 16 });
+
+ assert.deepEqual( loc, {
+ source: 'input.js',
+ name: null,
+ line: 6,
+ column: 16
+ });
+ });
});
describe( 'indent', () => {
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-magic-string.git
More information about the Pkg-javascript-commits
mailing list