Skip to content

Commit

Permalink
refactor storage of replacements for readability and performance
Browse files Browse the repository at this point in the history
  • Loading branch information
sokra committed Sep 20, 2018
1 parent 62e6396 commit 6035781
Showing 1 changed file with 39 additions and 23 deletions.
62 changes: 39 additions & 23 deletions lib/ReplaceSource.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,35 @@ var SourceListMap = require("source-list-map").SourceListMap;
var fromStringWithSourceMap = require("source-list-map").fromStringWithSourceMap;
var SourceMapConsumer = require("source-map").SourceMapConsumer;

class Replacement {
constructor(start, end, content, insertIndex, name) {
this.start = start;
this.end = end;
this.content = content;
this.insertIndex = insertIndex;
this.name = name;
}
}

class ReplaceSource extends Source {
constructor(source, name) {
super();
this._source = source;
this._name = name;
/** @type {Replacement[]} */
this.replacements = [];
}

replace(start, end, newValue, name) {
if(typeof newValue !== "string")
throw new Error("insertion must be a string, but is a " + typeof newValue);
this.replacements.push([start, end, newValue, this.replacements.length, name]);
this.replacements.push(new Replacement(start, end, newValue, this.replacements.length, name));
}

insert(pos, newValue, name) {
if(typeof newValue !== "string")
throw new Error("insertion must be a string, but is a " + typeof newValue + ": " + newValue);
this.replacements.push([pos, pos - 1, newValue, this.replacements.length, name]);
this.replacements.push(new Replacement(pos, pos - 1, newValue, this.replacements.length, name));
}

source(options) {
Expand All @@ -40,13 +51,13 @@ class ReplaceSource extends Source {

_sortReplacements() {
this.replacements.sort(function(a, b) {
var diff = b[1] - a[1];
var diff = b.end - a.end;
if(diff !== 0)
return diff;
diff = b[0] - a[0];
diff = b.start - a.start;
if(diff !== 0)
return diff;
return b[3] - a[3];
return b.insertIndex - a.insertIndex;
});
}

Expand All @@ -57,9 +68,9 @@ class ReplaceSource extends Source {
var result = [str];
this.replacements.forEach(function(repl) {
var remSource = result.pop();
var splitted1 = this._splitString(remSource, Math.floor(repl[1] + 1));
var splitted2 = this._splitString(splitted1[0], Math.floor(repl[0]));
result.push(splitted1[1], repl[2], splitted2[0]);
var splitted1 = this._splitString(remSource, Math.floor(repl.end + 1));
var splitted2 = this._splitString(splitted1[0], Math.floor(repl.start));
result.push(splitted1[1], repl.content, splitted2[0]);
}, this);

// write out result array in reverse order
Expand Down Expand Up @@ -146,18 +157,18 @@ class ReplaceSource extends Source {
removeChars = 0;
}
var finalStr = "";
while(idxReplacement >= 0 && replacements[idxReplacement][0] < newCurrentIndex) {
while(idxReplacement >= 0 && replacements[idxReplacement].start < newCurrentIndex) {
var repl = replacements[idxReplacement];
var start = Math.floor(repl[0]);
var end = Math.floor(repl[1] + 1);
var start = Math.floor(repl.start);
var end = Math.floor(repl.end + 1);
var before = str.substr(0, Math.max(0, start - currentIndex));
if(end <= newCurrentIndex) {
var after = str.substr(Math.max(0, end - currentIndex));
finalStr += before + repl[2];
finalStr += before + repl.content;
str = after;
currentIndex = Math.max(currentIndex, end);
} else {
finalStr += before + repl[2];
finalStr += before + repl.content;
str = "";
removeChars = end - newCurrentIndex;
}
Expand All @@ -170,7 +181,7 @@ class ReplaceSource extends Source {
});
var extraCode = "";
while(idxReplacement >= 0) {
extraCode += replacements[idxReplacement][2];
extraCode += replacements[idxReplacement].content;
idxReplacement--;
}
if(extraCode) {
Expand Down Expand Up @@ -260,16 +271,19 @@ class ReplaceSource extends Source {
}

function sortReplacementsAscending(a, b) {
var diff = a[1] - b[1]; // end
var diff = a.end - b.end;
if(diff !== 0)
return diff;
diff = a[0] - b[0]; // start
diff = a.start - b.start;
if(diff !== 0)
return diff;
return a[3] - b[3]; // insert order
return a.insertIndex - b.insertIndex;
}

class ReplacementEnumerator {
/**
* @param {Replacement[]} replacements list of replacements
*/
constructor(replacements) {
this.emit = true;
this.done = !replacements || replacements.length === 0;
Expand All @@ -278,7 +292,7 @@ class ReplacementEnumerator {
if(!this.done) {
// Set initial start position in case .header is not called
var repl = replacements[0];
this.position = Math.floor(repl[0]);
this.position = Math.floor(repl.start);
if(this.position < 0)
this.position = 0;
}
Expand All @@ -290,18 +304,18 @@ class ReplacementEnumerator {
if(this.emit) {
// Start point found. stop emitting. set position to find end
var repl = this.replacements[this.index];
var end = Math.floor(repl[1] + 1);
var end = Math.floor(repl.end + 1);
this.position = end;
this.value = repl[2];
this.name = repl[4];
this.value = repl.content;
this.name = repl.name;
} else {
// End point found. start emitting. set position to find next start
this.index++;
if(this.index >= this.replacements.length) {
this.done = true;
} else {
var nextRepl = this.replacements[this.index];
var start = Math.floor(nextRepl[0]);
var start = Math.floor(nextRepl.start);
this.position = start;
}
}
Expand All @@ -315,7 +329,9 @@ class ReplacementEnumerator {
if(!this.done && !this.emit)
this.next(); // If we finished _replaceInNode mid emit we advance to next entry
return this.done ? [] : this.replacements.slice(this.index).map(function(repl) {
return repl[2];
// this doesn't need to handle repl.name, because in SourceMaps generated code
// without pointer to original source can't have a name
return repl.content;
}).join("");
}
}
Expand Down

0 comments on commit 6035781

Please sign in to comment.