Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make sourcemap generation a bit faster, roll #2 #2903

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 36 additions & 28 deletions lib/less/source-map-output.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,38 @@
module.exports = function (environment) {

/**
* @param source The code
* @param ignoredCharsCount Number of characters at the start of the file to ignore.
* @constructor
*/
var FileInfo = function (source, ignoredCharsCount) {
this.ignoredCharsCount = ignoredCharsCount;
this.source = source.slice(ignoredCharsCount);
this.sourceLines = this.source.split('\n');
};

/** Translate absolute source offset to line/column offset. */
FileInfo.prototype.getLocation = function (index) {
index = Math.max(0, index - this.ignoredCharsCount);
var line = 0;
for (; line < this.sourceLines.length && index >= this.sourceLines[line].length + 1; line++) {
index -= this.sourceLines[line].length + 1; // +1 for the '\n' character
}
return {line: line + 1, column: index};
};

var SourceMapOutput = function (options) {
this._css = [];
this._rootNode = options.rootNode;
this._contentsMap = options.contentsMap;
this._contentsIgnoredCharsMap = options.contentsIgnoredCharsMap;

this._contentsInfoMap = {};
for (var key in options.contentsMap) {
if (options.contentsMap.hasOwnProperty(key)) {
this._contentsInfoMap[key] = new FileInfo(
options.contentsMap[key], options.contentsIgnoredCharsMap[key] || 0);
}
}

if (options.sourceMapFilename) {
this._sourceMapFilename = options.sourceMapFilename.replace(/\\/g, '/');
}
Expand Down Expand Up @@ -48,39 +76,22 @@ module.exports = function (environment) {
}

var lines,
sourceLines,
columns,
sourceColumns,
i;

if (fileInfo) {
var inputSource = this._contentsMap[fileInfo.filename];

// remove vars/banner added to the top of the file
if (this._contentsIgnoredCharsMap[fileInfo.filename]) {
// adjust the index
index -= this._contentsIgnoredCharsMap[fileInfo.filename];
if (index < 0) { index = 0; }
// adjust the source
inputSource = inputSource.slice(this._contentsIgnoredCharsMap[fileInfo.filename]);
}
inputSource = inputSource.substring(0, index);
sourceLines = inputSource.split("\n");
sourceColumns = sourceLines[sourceLines.length - 1];
}

lines = chunk.split("\n");
columns = lines[lines.length - 1];

if (fileInfo) {
var location = this._contentsInfoMap[fileInfo.filename].getLocation(index);
if (!mapLines) {
this._sourceMapGenerator.addMapping({ generated: { line: this._lineNumber + 1, column: this._column},
original: { line: sourceLines.length, column: sourceColumns.length},
original: location,
source: this.normalizeFilename(fileInfo.filename)});
} else {
for (i = 0; i < lines.length; i++) {
this._sourceMapGenerator.addMapping({ generated: { line: this._lineNumber + i + 1, column: i === 0 ? this._column : 0},
original: { line: sourceLines.length + i, column: i === 0 ? sourceColumns.length : 0},
original: { line: location.line + i, column: i === 0 ? location.column : 0},
source: this.normalizeFilename(fileInfo.filename)});
}
}
Expand All @@ -104,12 +115,9 @@ module.exports = function (environment) {
this._sourceMapGenerator = new this._sourceMapGeneratorConstructor({ file: this._outputFilename, sourceRoot: null });

if (this._outputSourceFiles) {
for (var filename in this._contentsMap) {
if (this._contentsMap.hasOwnProperty(filename)) {
var source = this._contentsMap[filename];
if (this._contentsIgnoredCharsMap[filename]) {
source = source.slice(this._contentsIgnoredCharsMap[filename]);
}
for (var filename in this._contentsInfoMap) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the bug in the last PR was that this line was still referencing this._contentsMap

if (this._contentsInfoMap.hasOwnProperty(filename)) {
var source = this._contentsInfoMap[filename].source;
this._sourceMapGenerator.setSourceContent(this.normalizeFilename(filename), source);
}
}
Expand Down
4 changes: 4 additions & 0 deletions test/css/sourcemaps-map-inline/imported.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions test/css/sourcemaps-map-inline/main.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ lessTester.runTestSet({strictMath: true, strictUnits: true, sourceMap: true, glo
}
return path.join('test/sourcemaps', filename) + '.json';
});
lessTester.runTestSet({sourceMap: true, outputSourceFiles: true}, "sourcemaps-less-inline/",
lessTester.testSourcemap, null, lessTester.normalizeSourceMap,
function(filename, type, baseFolder) {
return path.join('test/sourcemaps-less-inline', filename) + '.json';
});
lessTester.runTestSetNormalOnly({sourceMap: {sourceMapFileInline: true}}, "sourcemaps-map-inline/",
null, null, lessTester.normalizeSourceMap);
lessTester.runTestSet({strictMath: true, strictUnits: true, sourceMap: {sourceMapFileInline: true}}, "sourcemaps-empty/", lessTester.testEmptySourcemap);
lessTester.runTestSet({globalVars: true, banner: "/**\n * Test\n */\n"}, "globalVars/",
null, null, null, function(name, type, baseFolder) { return path.join(baseFolder, name) + '.json'; });
Expand Down
18 changes: 15 additions & 3 deletions test/less-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,9 +255,10 @@ module.exports = function() {
process.stdout.write("- " + path.join(baseFolder, css_name) + ": ");

css = css && doReplacements(css, path.join(baseFolder, foldername));
if (result.css === css) { ok('OK'); }
var actualCss = result.css && doReplacements(result.css, path.join(baseFolder, foldername));
if (actualCss === css) { ok('OK'); }
else {
difference("FAIL", css, result.css);
difference("FAIL", css, actualCss);
}
release();
});
Expand Down Expand Up @@ -372,6 +373,16 @@ module.exports = function() {
ok(stylize("OK\n", "green"));
}

/**
* Source maps are different on different platforms (OS vs Unix). But we don't
* care about testing the source map library anyway, so replace inline
* source maps with "FakeMap".
*/
function normalizeSourceMap(css) {
return css.replace(/sourceMappingURL=data:application\/json;base64,[a-zA-Z0-9=]* /,
'sourceMappingURL=data:application/json;base64,FakeMap ')
}

return {
runTestSet: runTestSet,
runTestSetNormalOnly: runTestSetNormalOnly,
Expand All @@ -381,6 +392,7 @@ module.exports = function() {
testEmptySourcemap: testEmptySourcemap,
testNoOptions: testNoOptions,
prepBomTest: prepBomTest,
finished: finished
finished: finished,
normalizeSourceMap: normalizeSourceMap
};
};
10 changes: 10 additions & 0 deletions test/less/sourcemaps-less-inline/main.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@var: black;

.a() {
color: red;
}

.b {
.a();
background: @var;
}
6 changes: 6 additions & 0 deletions test/less/sourcemaps-map-inline/imported.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

@my-black: black;

.b {
color: green;
}
10 changes: 10 additions & 0 deletions test/less/sourcemaps-map-inline/main.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

@import "imported";

.a {
.b();
}

.c {
color: @my-black;
}
1 change: 1 addition & 0 deletions test/sourcemaps-less-inline/main.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"version":3,"sources":["testweb/sourcemaps-less-inline/main.less"],"names":[],"mappings":"AAMA;EAHE,UAAA;EAKA,iBAAA","file":"sourcemaps-less-inline/main.css","sourcesContent":["@var: black;\n\n.a() {\n color: red;\n}\n\n.b {\n .a();\n background: @var;\n}\n"]}