support #__PURE__ in ESTree

This commit is contained in:
alexlamsl 2021-04-28 22:37:57 +08:00
parent a06e20304b
commit c7cbd7a278
3 changed files with 55 additions and 6 deletions

View File

@ -314,16 +314,43 @@ function run() {
try { try {
if (options.parse) { if (options.parse) {
if (options.parse.acorn) { if (options.parse.acorn) {
var annotations = Object.create(null);
files = convert_ast(function(toplevel, name) { files = convert_ast(function(toplevel, name) {
return require("acorn").parse(files[name], { var content = files[name];
var list = annotations[name] = [];
var prev = -1;
return require("acorn").parse(content, {
allowHashBang: true, allowHashBang: true,
ecmaVersion: "latest", ecmaVersion: "latest",
locations: true, locations: true,
onComment: function(block, text, start, end) {
var match = /[@#]__PURE__/.exec(text);
if (!match) {
if (start != prev) return;
match = [ list[prev] ];
}
while (/\s/.test(content[end])) end++;
list[end] = match[0];
prev = end;
},
preserveParens: true,
program: toplevel, program: toplevel,
sourceFile: name, sourceFile: name,
sourceType: "module", sourceType: "module",
}); });
}); });
files.walk(new UglifyJS.TreeWalker(function(node) {
if (!(node instanceof UglifyJS.AST_Call)) return;
var list = annotations[node.start.file];
var pure = list[node.start.pos];
if (!pure) {
var pos = node.start.parens;
if (pos) for (var i = 0; !pure && i < pos.length; i++) {
pure = list[pos[i]];
}
}
if (pure) node.pure = pure;
}));
} else if (options.parse.spidermonkey) { } else if (options.parse.spidermonkey) {
files = convert_ast(function(toplevel, name) { files = convert_ast(function(toplevel, name) {
var obj = JSON.parse(files[name]); var obj = JSON.parse(files[name]);

View File

@ -446,8 +446,22 @@
args.value = val; args.value = val;
return new AST_String(args); return new AST_String(args);
case "number": case "number":
args.value = val; if (isNaN(val)) return new AST_NaN(args);
return new AST_Number(args); var negate, node;
if (isFinite(val)) {
negate = 1 / val < 0;
args.value = negate ? -val : val;
node = new AST_Number(args);
} else {
negate = val < 0;
node = new AST_Infinity(args);
}
return negate ? new AST_UnaryPrefix({
start: args.start,
end: args.end,
operator: "-",
expression: node,
}) : node;
case "boolean": case "boolean":
return new (val ? AST_True : AST_False)(args); return new (val ? AST_True : AST_False)(args);
} }
@ -532,6 +546,14 @@
name: "this", name: "this",
}); });
}, },
ParenthesizedExpression: function(M) {
var node = from_moz(M.expression);
if (!node.start.parens) node.start.parens = [];
node.start.parens.push(my_start_token(M));
if (!node.end.parens) node.end.parens = [];
node.end.parens.push(my_end_token(M));
return node;
},
}; };
MOZ_TO_ME.UpdateExpression = MOZ_TO_ME.UpdateExpression =
@ -570,8 +592,8 @@
map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right"); map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right");
map("AssignmentPattern", AST_DefaultValue, "left>name, right>value"); map("AssignmentPattern", AST_DefaultValue, "left>name, right>value");
map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative"); map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative");
map("NewExpression", AST_New, "callee>expression, arguments@args"); map("NewExpression", AST_New, "callee>expression, arguments@args, pure=pure");
map("CallExpression", AST_Call, "callee>expression, arguments@args"); map("CallExpression", AST_Call, "callee>expression, arguments@args, pure=pure");
map("SequenceExpression", AST_Sequence, "expressions@expressions"); map("SequenceExpression", AST_Sequence, "expressions@expressions");
map("SpreadElement", AST_Spread, "argument>expression"); map("SpreadElement", AST_Spread, "argument>expression");
map("ObjectExpression", AST_Object, "properties@properties"); map("ObjectExpression", AST_Object, "properties@properties");

View File

@ -1456,7 +1456,7 @@ function OutputStream(options) {
parent = output.parent(level++); parent = output.parent(level++);
if (parent instanceof AST_Call && parent.expression === node) return; if (parent instanceof AST_Call && parent.expression === node) return;
} while (parent instanceof AST_PropAccess && parent.expression === node); } while (parent instanceof AST_PropAccess && parent.expression === node);
output.print("/*" + self.pure + "*/"); output.print(typeof self.pure == "string" ? "/*" + self.pure + "*/" : "/*@__PURE__*/");
} }
function print_call_args(self, output) { function print_call_args(self, output) {
if (self.expression instanceof AST_Call || self.expression instanceof AST_Lambda) { if (self.expression instanceof AST_Call || self.expression instanceof AST_Lambda) {