Skip to content

Commit

Permalink
fixes benjamn#128 parse inline sourcemap when parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
caridy committed Jan 29, 2015
1 parent ffc8d19 commit 3f3fc60
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 2 deletions.
12 changes: 11 additions & 1 deletion lib/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ var Patcher = require("./patcher").Patcher;
var normalizeOptions = require("./options").normalize;
var fromString = require("./lines").fromString;
var attachComments = require("./comments").attach;
var extractInlineSourceMaps = require('./util').extractInlineSourceMaps;

exports.parse = function parse(source, options) {
options = normalizeOptions(options);

var lines = fromString(source, options);
var map = extractInlineSourceMaps(source);
var lines = fromString(map.source, options);

var sourceWithoutTabs = lines.toString({
tabWidth: options.tabWidth,
Expand Down Expand Up @@ -49,6 +51,14 @@ exports.parse = function parse(source, options) {
// Attach comments to the copy rather than the original.
attachComments(comments, copy.program, lines);

// Attach inline sourcemap metadata when possible
Object.defineProperty(copy, 'inputSourceMap', {
enumerable: false,
configurable: false,
writable: false,
value: map.inputSourceMap
});

return copy;
};

Expand Down
2 changes: 1 addition & 1 deletion lib/printer.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ function Printer(originalOptions) {
return new PrintResult(
lines.toString(options),
util.composeSourceMaps(
options.inputSourceMap,
options.inputSourceMap || ast.inputSourceMap,
lines.getSourceMap(
options.sourceMapName,
options.sourceRoot
Expand Down
10 changes: 10 additions & 0 deletions lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,13 @@ exports.composeSourceMaps = function(formerMap, latterMap) {

return smg.toJSON();
};

exports.extractInlineSourceMaps = function (source) {
var re = /\s*\/\/(?:@|#) sourceMappingURL=data:application\/json;base64,(\S*)$/m,
map = (source).match(re);

return {
source: map ? source.replace(re, '') : source,
inputSourceMap: map ? (new Buffer(map[1], 'base64')).toString() : undefined
};
};
89 changes: 89 additions & 0 deletions test/mapping.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,95 @@ describe("source maps", function() {
});
});

it("should extract inline sourcemap from source", function() {
function addUseStrict(ast) {
return recast.visit(ast, {
visitFunction: function(path) {
path.get("body", "body").unshift(
b.expressionStatement(b.literal("use strict"))
);
this.traverse(path);
}
});
}

function stripConsole(ast) {
return recast.visit(ast, {
visitCallExpression: function(path) {
var node = path.value;
if (n.MemberExpression.check(node.callee) &&
n.Identifier.check(node.callee.object) &&
node.callee.object.name === "console") {
n.ExpressionStatement.assert(path.parent.node);
path.parent.replace();
return false;
}
}
});
}

var code = [
"function add(a, b) {",
" var sum = a + b;",
" console.log(a, b);",
" return sum;",
"}"
].join("\n");

var ast = parse(code, {
sourceFileName: "original.js"
});

var useStrictResult = new Printer({
sourceMapName: "useStrict.map.json"
}).print(addUseStrict(ast));

var useStrictResultCodeAndMap = [
useStrictResult.code,
"//# sourceMappingURL=data:application/json;base64,",
new Buffer(JSON.stringify(useStrictResult.map)).toString('base64')
].join('');

var useStrictAst = parse(useStrictResultCodeAndMap, {
sourceFileName: "useStrict.js"
});

var oneStepResult = new Printer({
sourceMapName: "oneStep.map.json"
}).print(stripConsole(ast));

var twoStepResult = new Printer({
sourceMapName: "twoStep.map.json"
}).print(stripConsole(useStrictAst));

assert.strictEqual(
oneStepResult.code,
twoStepResult.code
);

var smc1 = new sourceMap.SourceMapConsumer(oneStepResult.map);
var smc2 = new sourceMap.SourceMapConsumer(twoStepResult.map);

smc1.eachMapping(function(mapping) {
var pos = {
line: mapping.generatedLine,
column: mapping.generatedColumn
};

var orig1 = smc1.originalPositionFor(pos);
var orig2 = smc2.originalPositionFor(pos);

// The composition of the source maps generated separately from
// the two transforms should be equivalent to the source map
// generated from the composition of the two transforms.
assert.deepEqual(orig1, orig2);

// Make sure the two-step source map refers back to the original
// source instead of the intermediate source.
assert.strictEqual(orig2.source, "original.js");
});
});

it("should work when a child node becomes null", function() {
// https://github.com/facebook/regenerator/issues/103
var code = [
Expand Down

0 comments on commit 3f3fc60

Please sign in to comment.