make code generator deopt on input >100KB
This commit is contained in:
@@ -5,14 +5,21 @@ module.exports = Buffer;
|
||||
var repeating = require("repeating");
|
||||
var trimRight = require("trim-right");
|
||||
var isBoolean = require("lodash/lang/isBoolean");
|
||||
var messages = require("../messages");
|
||||
var includes = require("lodash/collection/includes");
|
||||
var isNumber = require("lodash/lang/isNumber");
|
||||
|
||||
function Buffer(position, format) {
|
||||
function Buffer(position, format, opts, code) {
|
||||
this.position = position;
|
||||
this._indent = format.indent.base;
|
||||
this.format = format;
|
||||
this.deopt = false;
|
||||
this.buf = "";
|
||||
|
||||
if (code.length > 100000) { // 100KB
|
||||
this.deopt = true;
|
||||
console.error(messages.get("codeGeneratorDeopt", opts.filename, "100KB"));
|
||||
}
|
||||
}
|
||||
|
||||
Buffer.prototype.get = function () {
|
||||
@@ -20,7 +27,7 @@ Buffer.prototype.get = function () {
|
||||
};
|
||||
|
||||
Buffer.prototype.getIndent = function () {
|
||||
if (this.format.compact || this.format.concise) {
|
||||
if (this.deopt || this.format.concise) {
|
||||
return "";
|
||||
} else {
|
||||
return repeating(this.format.indent.style, this._indent);
|
||||
@@ -58,14 +65,14 @@ Buffer.prototype.keyword = function (name) {
|
||||
};
|
||||
|
||||
Buffer.prototype.space = function () {
|
||||
if (this.format.compact) return;
|
||||
|
||||
if (this.buf && !this.isLast([" ", "\n"])) {
|
||||
if (this.deopt) return;
|
||||
if (this.buf && !this.isLast(" ") && !this.isLast("\n")) {
|
||||
this.push(" ");
|
||||
}
|
||||
};
|
||||
|
||||
Buffer.prototype.removeLast = function (cha) {
|
||||
if (this.deopt) return;
|
||||
if (!this.isLast(cha)) return;
|
||||
|
||||
this.buf = this.buf.substr(0, this.buf.length - 1);
|
||||
@@ -73,7 +80,9 @@ Buffer.prototype.removeLast = function (cha) {
|
||||
};
|
||||
|
||||
Buffer.prototype.newline = function (i, removeLast) {
|
||||
if (this.format.compact || this.format.concise) {
|
||||
if (this.deopt) return;
|
||||
|
||||
if (this.format.concise) {
|
||||
this.space();
|
||||
return;
|
||||
}
|
||||
@@ -81,11 +90,11 @@ Buffer.prototype.newline = function (i, removeLast) {
|
||||
removeLast = removeLast || false;
|
||||
|
||||
if (isNumber(i)) {
|
||||
if (this.endsWith("{\n")) i--;
|
||||
if (this.endsWith(repeating("\n", i > 0 ? i : 0))) return;
|
||||
if (this.isLast("\n")) i--;
|
||||
|
||||
while (i--) {
|
||||
while (i > 0) {
|
||||
this._newline(removeLast);
|
||||
i--;
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -101,36 +110,11 @@ Buffer.prototype._newline = function (removeLast) {
|
||||
if (removeLast && this.isLast("\n")) this.removeLast("\n");
|
||||
|
||||
this.removeLast(" ");
|
||||
|
||||
// remove whitespace if last character was a newline
|
||||
this._removeSpacesAfterLastNewline();
|
||||
this._push("\n");
|
||||
};
|
||||
|
||||
/**
|
||||
* If buffer ends with a newline and some spaces after it, trim those spaces.
|
||||
*/
|
||||
Buffer.prototype._removeSpacesAfterLastNewline = function () {
|
||||
var lastNewlineIndex = this.buf.lastIndexOf("\n");
|
||||
if (lastNewlineIndex === -1)
|
||||
return;
|
||||
|
||||
var index = this.buf.length - 1;
|
||||
while (index > lastNewlineIndex) {
|
||||
if (this.buf[index] !== " ") {
|
||||
break;
|
||||
}
|
||||
|
||||
index--;
|
||||
}
|
||||
|
||||
if (index === lastNewlineIndex) {
|
||||
this.buf = this.buf.substring(0, index + 1);
|
||||
}
|
||||
};
|
||||
|
||||
Buffer.prototype.push = function (str, noIndent) {
|
||||
if (this._indent && !noIndent && str !== "\n") {
|
||||
if (!this.deopt && this._indent && !noIndent && str !== "\n") {
|
||||
// we have an indent level and we aren't pushing a newline
|
||||
var indent = this.getIndent();
|
||||
|
||||
@@ -138,7 +122,7 @@ Buffer.prototype.push = function (str, noIndent) {
|
||||
str = str.replace(/\n/g, "\n" + indent);
|
||||
|
||||
// we've got a newline before us so prepend on the indentation
|
||||
if (this.isLast("\n")) str = indent + str;
|
||||
if (this.isLast("\n")) this._push(indent);
|
||||
}
|
||||
|
||||
this._push(str);
|
||||
@@ -149,14 +133,10 @@ Buffer.prototype._push = function (str) {
|
||||
this.buf += str;
|
||||
};
|
||||
|
||||
Buffer.prototype.endsWith = function (str) {
|
||||
var d = this.buf.length - str.length;
|
||||
return d >= 0 && this.buf.lastIndexOf(str) === d;
|
||||
};
|
||||
Buffer.prototype.isLast = function (cha) {
|
||||
if (this.deopt) return false;
|
||||
|
||||
Buffer.prototype.isLast = function (cha, shouldTrimRight) {
|
||||
var buf = this.buf;
|
||||
if (shouldTrimRight) buf = trimRight(buf);
|
||||
var last = buf[buf.length - 1];
|
||||
|
||||
if (Array.isArray(cha)) {
|
||||
|
||||
@@ -22,12 +22,7 @@ exports.IfStatement = function (node, print) {
|
||||
|
||||
if (node.alternate) {
|
||||
if (this.isLast("}")) this.space();
|
||||
this.keyword("else");
|
||||
|
||||
if (this.format.format && !t.isBlockStatement(node.alternate)) {
|
||||
this.push(" ");
|
||||
}
|
||||
|
||||
this.push("else ");
|
||||
print.indentOnComments(node.alternate);
|
||||
}
|
||||
};
|
||||
@@ -189,7 +184,7 @@ exports.VariableDeclaration = function (node, print, parent) {
|
||||
}
|
||||
|
||||
var sep = ",";
|
||||
if (hasInits) {
|
||||
if (!this.buffer.deopt && hasInits) {
|
||||
sep += "\n" + repeating(" ", node.kind.length + 1);
|
||||
} else {
|
||||
sep += " ";
|
||||
|
||||
@@ -72,7 +72,7 @@ exports.ArrayPattern = function (node, print) {
|
||||
// both (all) of the holes.
|
||||
self.push(",");
|
||||
} else {
|
||||
if (i > 0 && !self.format.compact) self.push(" ");
|
||||
if (i > 0) self.push(" ");
|
||||
print(elem);
|
||||
if (i < len - 1) self.push(",");
|
||||
}
|
||||
|
||||
@@ -28,10 +28,10 @@ function CodeGenerator(ast, opts, code) {
|
||||
this.opts = opts;
|
||||
this.ast = ast;
|
||||
|
||||
this.whitespace = new Whitespace(this.tokens, this.comments);
|
||||
this.whitespace = new Whitespace(this.tokens, this.comments, this.format);
|
||||
this.position = new Position;
|
||||
this.map = new SourceMap(this.position, opts, code);
|
||||
this.buffer = new Buffer(this.position, this.format);
|
||||
this.buffer = new Buffer(this.position, this.format, opts, code);
|
||||
}
|
||||
|
||||
each(Buffer.prototype, function (fn, key) {
|
||||
@@ -50,7 +50,6 @@ CodeGenerator.normalizeOptions = function (code, opts) {
|
||||
return merge({
|
||||
parentheses: true,
|
||||
comments: opts.comments == null || opts.comments,
|
||||
compact: false,
|
||||
concise: false,
|
||||
indent: {
|
||||
adjustMultilineComment: true,
|
||||
@@ -115,11 +114,7 @@ CodeGenerator.prototype.buildPrint = function (parent) {
|
||||
|
||||
print.list = function (items, opts) {
|
||||
opts = opts || {};
|
||||
|
||||
var sep = opts.separator || ", ";
|
||||
if (self.format.compact) sep = ",";
|
||||
opts.separator = sep;
|
||||
|
||||
opts.separator = opts.separator || ", ";
|
||||
print.join(items, opts);
|
||||
};
|
||||
|
||||
@@ -301,7 +296,8 @@ CodeGenerator.prototype._getComments = function (key, node) {
|
||||
};
|
||||
|
||||
CodeGenerator.prototype._printComments = function (comments) {
|
||||
if (this.format.compact) return;
|
||||
if (this.buffer.deopt) return;
|
||||
|
||||
if (!this.format.comments) return;
|
||||
if (!comments || !comments.length) return;
|
||||
|
||||
|
||||
@@ -13,11 +13,13 @@ var sortBy = require("lodash/collection/sortBy");
|
||||
* @param {Number} max Array length
|
||||
* @returns {Number} shiftedIndex
|
||||
*/
|
||||
|
||||
function getLookupIndex(i, base, max) {
|
||||
i += base;
|
||||
|
||||
if (i >= max)
|
||||
if (i >= max) {
|
||||
i -= max;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,8 @@ exports.messages = {
|
||||
modulesIllegalExportName: "Illegal export $1",
|
||||
unknownForHead: "Unknown node type $1 in ForStatement",
|
||||
didYouMean: "Did you mean $1?",
|
||||
evalInStrictMode: "eval is not allowed in strict mode"
|
||||
evalInStrictMode: "eval is not allowed in strict mode",
|
||||
codeGeneratorDeopt: "Note: The code generator has deoptimised the styling of $1 as it exceeds the max of $2."
|
||||
};
|
||||
|
||||
exports.get = function (key) {
|
||||
|
||||
Reference in New Issue
Block a user