This commit is contained in:
Fábio Santos 2018-03-25 19:54:15 +00:00 committed by GitHub
commit fa8f9f4ed2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 762 additions and 73 deletions

View File

@ -445,7 +445,7 @@ var AST_PrefixedTemplateString = DEFNODE("PrefixedTemplateString", "template_str
this.prefix._walk(visitor); this.prefix._walk(visitor);
this.template_string._walk(visitor); this.template_string._walk(visitor);
} }
}) });
var AST_TemplateString = DEFNODE("TemplateString", "segments", { var AST_TemplateString = DEFNODE("TemplateString", "segments", {
$documentation: "A template string literal", $documentation: "A template string literal",
@ -643,7 +643,7 @@ var AST_NameMapping = DEFNODE("NameMapping", "foreign_name name", {
this.name._walk(visitor); this.name._walk(visitor);
}); });
} }
}) });
var AST_Import = DEFNODE("Import", "imported_name imported_names module_name", { var AST_Import = DEFNODE("Import", "imported_name imported_names module_name", {
$documentation: "An `import` statement", $documentation: "An `import` statement",

View File

@ -71,12 +71,88 @@
body: normalize_directives(M.body.map(from_moz)) body: normalize_directives(M.body.map(from_moz))
}); });
}, },
ArrayPattern: function(M) {
return new AST_Destructuring({
start: my_start_token(M),
end: my_end_token(M),
names: M.elements.map(function(elm) {
if (elm === null) {
return new AST_Hole();
}
return from_moz(elm);
}),
is_array: true
});
},
ObjectPattern: function(M) {
return new AST_Destructuring({
start: my_start_token(M),
end: my_end_token(M),
names: M.properties.map(from_moz),
is_array: false
});
},
AssignmentPattern: function(M) {
return new AST_Binary({
start: my_start_token(M),
end: my_end_token(M),
left: from_moz(M.left),
operator: "=",
right: from_moz(M.right)
});
},
SpreadElement: function(M) {
return new AST_Expansion({
start: my_start_token(M),
end: my_end_token(M),
expression: from_moz(M.argument)
});
},
RestElement: function(M) {
return new AST_Expansion({
start: my_start_token(M),
end: my_end_token(M),
expression: from_moz(M.argument)
});
},
TemplateElement: function(M) {
return new AST_TemplateSegment({
start: my_start_token(M),
end: my_end_token(M),
value: M.value.cooked,
raw: M.value.raw
});
},
TemplateLiteral: function(M) {
var segments = [];
for (var i = 0; i < M.quasis.length; i++) {
segments.push(from_moz(M.quasis[i]));
if (M.expressions[i]) {
segments.push(from_moz(M.expressions[i]));
}
}
return new AST_TemplateString({
start: my_start_token(M),
end: my_end_token(M),
segments: segments
});
},
TaggedTemplateExpression: function(M) {
return new AST_PrefixedTemplateString({
start: my_start_token(M),
end: my_end_token(M),
template_string: from_moz(M.quasi),
prefix: from_moz(M.tag)
});
},
FunctionDeclaration: function(M) { FunctionDeclaration: function(M) {
return new AST_Defun({ return new AST_Defun({
start: my_start_token(M), start: my_start_token(M),
end: my_end_token(M), end: my_end_token(M),
name: from_moz(M.id), name: from_moz(M.id),
argnames: M.params.map(from_moz), argnames: M.params.map(from_moz),
is_generator: M.generator,
async: M.async,
body: normalize_directives(from_moz(M.body).body) body: normalize_directives(from_moz(M.body).body)
}); });
}, },
@ -86,9 +162,20 @@
end: my_end_token(M), end: my_end_token(M),
name: from_moz(M.id), name: from_moz(M.id),
argnames: M.params.map(from_moz), argnames: M.params.map(from_moz),
is_generator: M.generator,
async: M.async,
body: normalize_directives(from_moz(M.body).body) body: normalize_directives(from_moz(M.body).body)
}); });
}, },
ArrowFunctionExpression: function(M) {
return new AST_Arrow({
start: my_start_token(M),
end: my_end_token(M),
argnames: M.params.map(from_moz),
body: from_moz(M.body),
async: M.async,
});
},
ExpressionStatement: function(M) { ExpressionStatement: function(M) {
return new AST_SimpleStatement({ return new AST_SimpleStatement({
start: my_start_token(M), start: my_start_token(M),
@ -112,18 +199,62 @@
Property: function(M) { Property: function(M) {
var key = M.key; var key = M.key;
var args = { var args = {
start : my_start_token(key), start : my_start_token(key || M.value),
end : my_end_token(M.value), end : my_end_token(M.value),
key : key.type == "Identifier" ? key.name : key.value, key : key.type == "Identifier" ? key.name : key.value,
value : from_moz(M.value) value : from_moz(M.value)
}; };
if (M.kind == "init") return new AST_ObjectKeyVal(args); if (M.computed) {
args.key = from_moz(M.key);
}
if (M.method) {
args.is_generator = M.value.generator;
args.async = M.value.async;
if (!M.computed) {
args.key = new AST_SymbolMethod({ name: args.key });
} else {
args.key = from_moz(M.key);
}
return new AST_ConciseMethod(args);
}
if (M.kind == "init") {
if (key.type != "Identifier" && key.type != "Literal") {
args.key = from_moz(key);
}
return new AST_ObjectKeyVal(args);
}
if (typeof args.key === "string" || typeof args.key === "number") {
args.key = new AST_SymbolMethod({ args.key = new AST_SymbolMethod({
name: args.key name: args.key
}); });
}
args.value = new AST_Accessor(args.value); args.value = new AST_Accessor(args.value);
if (M.kind == "get") return new AST_ObjectGetter(args); if (M.kind == "get") return new AST_ObjectGetter(args);
if (M.kind == "set") return new AST_ObjectSetter(args); if (M.kind == "set") return new AST_ObjectSetter(args);
if (M.kind == "method") {
args.async = M.value.async;
args.is_generator = M.value.generator;
args.quote = M.computed ? "\"" : null;
return new AST_ConciseMethod(args);
}
},
MethodDefinition: function(M) {
var args = {
start : my_start_token(M),
end : my_end_token(M),
key : M.computed ? from_moz(M.key) : new AST_SymbolMethod({ name: M.key.name || M.key.value }),
value : from_moz(M.value),
static : M.static,
};
if (M.kind == "get") {
return new AST_ObjectGetter(args);
}
if (M.kind == "set") {
return new AST_ObjectSetter(args);
}
args.is_generator = M.value.generator;
args.async = M.value.async;
return new AST_ConciseMethod(args);
}, },
ArrayExpression: function(M) { ArrayExpression: function(M) {
return new AST_Array({ return new AST_Array({
@ -139,6 +270,9 @@
start : my_start_token(M), start : my_start_token(M),
end : my_end_token(M), end : my_end_token(M),
properties : M.properties.map(function(prop){ properties : M.properties.map(function(prop){
if (prop.type === "SpreadElement") {
return from_moz(prop);
}
prop.type = "Property"; prop.type = "Property";
return from_moz(prop) return from_moz(prop)
}) })
@ -168,18 +302,98 @@
}); });
}, },
VariableDeclaration: function(M) { VariableDeclaration: function(M) {
return new (M.kind === "const" ? AST_Const : AST_Var)({ return new (M.kind === "const" ? AST_Const :
M.kind === "let" ? AST_Let : AST_Var)({
start : my_start_token(M), start : my_start_token(M),
end : my_end_token(M), end : my_end_token(M),
definitions : M.declarations.map(from_moz) definitions : M.declarations.map(from_moz)
}); });
}, },
ImportDeclaration: function(M) {
var imported_name = null;
var imported_names = null;
M.specifiers.forEach(function (specifier) {
if (specifier.type === "ImportSpecifier") {
if (!imported_names) { imported_names = []; }
imported_names.push(new AST_NameMapping({
start: my_start_token(specifier),
end: my_end_token(specifier),
foreign_name: from_moz(specifier.imported),
name: from_moz(specifier.local)
}));
} else if (specifier.type === "ImportDefaultSpecifier") {
imported_name = from_moz(specifier.local);
} else if (specifier.type === "ImportNamespaceSpecifier") {
if (!imported_names) { imported_names = []; }
imported_names.push(new AST_NameMapping({
start: my_start_token(specifier),
end: my_end_token(specifier),
foreign_name: new AST_SymbolImportForeign({ name: "*" }),
name: from_moz(specifier.local)
}));
}
});
return new AST_Import({
start : my_start_token(M),
end : my_end_token(M),
imported_name: imported_name,
imported_names : imported_names,
module_name : from_moz(M.source)
})
},
ExportAllDeclaration: function(M) {
return new AST_Export({
start: my_start_token(M),
end: my_end_token(M),
exported_names: [
new AST_NameMapping({
name: new AST_SymbolExportForeign({ name: "*" }),
foreign_name: new AST_SymbolExportForeign({ name: "*" })
})
],
module_name: from_moz(M.source)
});
},
ExportNamedDeclaration: function(M) {
return new AST_Export({
start: my_start_token(M),
end: my_end_token(M),
exported_definition: from_moz(M.declaration),
exported_names: M.specifiers && M.specifiers.length ? M.specifiers.map(function (specifier) {
return new AST_NameMapping({
foreign_name: from_moz(specifier.exported),
name: from_moz(specifier.local)
})
}) : null,
module_name: from_moz(M.source)
});
},
ExportDefaultDeclaration: function(M) {
return new AST_Export({
start: my_start_token(M),
end: my_end_token(M),
exported_value: from_moz(M.declaration),
is_default: true
});
},
Literal: function(M) { Literal: function(M) {
var val = M.value, args = { var val = M.value, args = {
start : my_start_token(M), start : my_start_token(M),
end : my_end_token(M) end : my_end_token(M)
}; };
if (val === null) return new AST_Null(args); if (val === null) return new AST_Null(args);
var rx = M.regex;
if (rx && rx.pattern) {
// RegExpLiteral as per ESTree AST spec
args.value = new RegExp(rx.pattern, rx.flags);
args.value.raw_source = rx.pattern;
return new AST_RegExp(args);
} else if (rx) {
// support legacy RegExp
args.value = M.regex && M.raw ? M.raw : val;
return new AST_RegExp(args);
}
switch (typeof val) { switch (typeof val) {
case "string": case "string":
args.value = val; args.value = val;
@ -189,24 +403,29 @@
return new AST_Number(args); return new AST_Number(args);
case "boolean": case "boolean":
return new (val ? AST_True : AST_False)(args); return new (val ? AST_True : AST_False)(args);
default:
var rx = M.regex;
if (rx && rx.pattern) {
// RegExpLiteral as per ESTree AST spec
args.value = new RegExp(rx.pattern, rx.flags).toString();
} else {
// support legacy RegExp
args.value = M.regex && M.raw ? M.raw : val;
} }
return new AST_RegExp(args); },
MetaProperty: function(M) {
if (M.meta.name === "new" && M.property.name === "target") {
return new AST_NewTarget({
start: my_start_token(M),
end: my_end_token(M)
});
} }
}, },
Identifier: function(M) { Identifier: function(M) {
var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2]; var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2];
return new ( p.type == "LabeledStatement" ? AST_Label return new ( p.type == "LabeledStatement" ? AST_Label
: p.type == "VariableDeclarator" && p.id === M ? (p.kind == "const" ? AST_SymbolConst : AST_SymbolVar) : p.type == "VariableDeclarator" && p.id === M ? (p.kind == "const" ? AST_SymbolConst : p.kind == "let" ? AST_SymbolLet : AST_SymbolVar)
: /Import.*Specifier/.test(p.type) ? (p.local === M ? AST_SymbolImport : AST_SymbolImportForeign)
: p.type == "ExportSpecifier" ? (p.local === M ? AST_SymbolExport : AST_SymbolExportForeign)
: p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg) : p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg)
: p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg) : p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg)
: p.type == "ArrowFunctionExpression" ? (p.params.indexOf(M) !== -1) ? AST_SymbolFunarg : AST_SymbolRef
: p.type == "ClassExpression" ? (p.id === M ? AST_SymbolClass : AST_SymbolRef)
: p.type == "Property" ? (p.key === M && p.computed || p.value === M ? AST_SymbolRef : AST_SymbolMethod)
: p.type == "ClassDeclaration" ? (p.id === M ? AST_SymbolDefClass : AST_SymbolRef)
: p.type == "MethodDefinition" ? (p.computed ? AST_SymbolRef : AST_SymbolMethod)
: p.type == "CatchClause" ? AST_SymbolCatch : p.type == "CatchClause" ? AST_SymbolCatch
: p.type == "BreakStatement" || p.type == "ContinueStatement" ? AST_LabelRef : p.type == "BreakStatement" || p.type == "ContinueStatement" ? AST_LabelRef
: AST_SymbolRef)({ : AST_SymbolRef)({
@ -229,6 +448,17 @@
}); });
}; };
MOZ_TO_ME.ClassDeclaration =
MOZ_TO_ME.ClassExpression = function From_Moz_Class(M) {
return new (M.type === "ClassDeclaration" ? AST_DefClass : AST_ClassExpression)({
start : my_start_token(M),
end : my_end_token(M),
name : from_moz(M.id),
extends : from_moz(M.superClass),
properties: M.body.body.map(from_moz)
});
};
map("EmptyStatement", AST_EmptyStatement); map("EmptyStatement", AST_EmptyStatement);
map("BlockStatement", AST_BlockStatement, "body@body"); map("BlockStatement", AST_BlockStatement, "body@body");
map("IfStatement", AST_If, "test>condition, consequent>body, alternate>alternative"); map("IfStatement", AST_If, "test>condition, consequent>body, alternate>alternative");
@ -243,11 +473,15 @@
map("DoWhileStatement", AST_Do, "test>condition, body>body"); map("DoWhileStatement", AST_Do, "test>condition, body>body");
map("ForStatement", AST_For, "init>init, test>condition, update>step, body>body"); map("ForStatement", AST_For, "init>init, test>condition, update>step, body>body");
map("ForInStatement", AST_ForIn, "left>init, right>object, body>body"); map("ForInStatement", AST_ForIn, "left>init, right>object, body>body");
map("ForOfStatement", AST_ForOf, "left>init, right>object, body>body");
map("AwaitExpression", AST_Await, "argument>expression");
map("YieldExpression", AST_Yield, "argument>expression, delegate=is_star");
map("DebuggerStatement", AST_Debugger); map("DebuggerStatement", AST_Debugger);
map("VariableDeclarator", AST_VarDef, "id>name, init>value"); map("VariableDeclarator", AST_VarDef, "id>name, init>value");
map("CatchClause", AST_Catch, "param>argname, body%body"); map("CatchClause", AST_Catch, "param>argname, body%body");
map("ThisExpression", AST_This); map("ThisExpression", AST_This);
map("SuperExpression", AST_Super);
map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right"); map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right");
map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right"); map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right");
map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right"); map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right");
@ -259,24 +493,95 @@
return to_moz_scope("Program", M); return to_moz_scope("Program", M);
}); });
def_to_moz(AST_Expansion, function To_Moz_Spread(M, parent) {
return {
type: to_moz_in_destructuring() ? "RestElement" : "SpreadElement",
argument: to_moz(M.expression)
};
});
def_to_moz(AST_PrefixedTemplateString, function To_Moz_TaggedTemplateExpression(M) {
return {
type: "TaggedTemplateExpression",
tag: to_moz(M.prefix),
quasi: to_moz(M.template_string)
};
});
def_to_moz(AST_TemplateString, function To_Moz_TemplateLiteral(M) {
var quasis = [];
var expressions = [];
for (var i = 0; i < M.segments.length; i++) {
if (i % 2 !== 0) {
expressions.push(to_moz(M.segments[i]));
} else {
quasis.push({
type: "TemplateElement",
value: {
raw: M.segments[i].raw,
cooked: M.segments[i].value
},
tail: i === M.segments.length - 1
});
}
}
return {
type: "TemplateLiteral",
quasis: quasis,
expressions: expressions
};
});
def_to_moz(AST_Defun, function To_Moz_FunctionDeclaration(M) { def_to_moz(AST_Defun, function To_Moz_FunctionDeclaration(M) {
return { return {
type: "FunctionDeclaration", type: "FunctionDeclaration",
id: to_moz(M.name), id: to_moz(M.name),
params: M.argnames.map(to_moz), params: M.argnames.map(to_moz),
generator: M.is_generator,
async: M.async,
body: to_moz_scope("BlockStatement", M) body: to_moz_scope("BlockStatement", M)
} }
}); });
def_to_moz(AST_Function, function To_Moz_FunctionExpression(M) { def_to_moz(AST_Function, function To_Moz_FunctionExpression(M, parent) {
var is_generator = parent.is_generator !== undefined ?
parent.is_generator : M.is_generator
return { return {
type: "FunctionExpression", type: "FunctionExpression",
id: to_moz(M.name), id: to_moz(M.name),
params: M.argnames.map(to_moz), params: M.argnames.map(to_moz),
generator: is_generator,
async: M.async,
body: to_moz_scope("BlockStatement", M) body: to_moz_scope("BlockStatement", M)
} }
}); });
def_to_moz(AST_Arrow, function To_Moz_ArrowFunctionExpression(M) {
var body = M.body instanceof Array ? {
type: "BlockStatement",
body: M.body.map(to_moz)
} : to_moz(M.body);
return {
type: "ArrowFunctionExpression",
params: M.argnames.map(to_moz),
async: M.async,
body: body
}
});
def_to_moz(AST_Destructuring, function To_Moz_ObjectPattern(M) {
if (M.is_array) {
return {
type: "ArrayPattern",
elements: M.names.map(to_moz)
}
}
return {
type: "ObjectPattern",
properties: M.names.map(to_moz)
};
});
def_to_moz(AST_Directive, function To_Moz_Directive(M) { def_to_moz(AST_Directive, function To_Moz_Directive(M) {
return { return {
type: "ExpressionStatement", type: "ExpressionStatement",
@ -324,11 +629,69 @@
def_to_moz(AST_Definitions, function To_Moz_VariableDeclaration(M) { def_to_moz(AST_Definitions, function To_Moz_VariableDeclaration(M) {
return { return {
type: "VariableDeclaration", type: "VariableDeclaration",
kind: M instanceof AST_Const ? "const" : "var", kind:
M instanceof AST_Const ? "const" :
M instanceof AST_Let ? "let" : "var",
declarations: M.definitions.map(to_moz) declarations: M.definitions.map(to_moz)
}; };
}); });
def_to_moz(AST_Export, function To_Moz_ExportDeclaration(M) {
if (M.exported_names) {
if (M.exported_names[0].name.name === "*") {
return {
type: "ExportAllDeclaration",
source: to_moz(M.module_name)
};
}
return {
type: "ExportNamedDeclaration",
specifiers: M.exported_names.map(function (name_mapping) {
return {
type: "ExportSpecifier",
exported: to_moz(name_mapping.foreign_name),
local: to_moz(name_mapping.name)
};
}),
declaration: to_moz(M.exported_definition),
source: to_moz(M.module_name)
};
}
return {
type: M.is_default ? "ExportDefaultDeclaration" : "ExportNamedDeclaration",
declaration: to_moz(M.exported_value || M.exported_definition)
};
});
def_to_moz(AST_Import, function To_Moz_ImportDeclaration(M) {
var specifiers = [];
if (M.imported_name) {
specifiers.push({
type: "ImportDefaultSpecifier",
local: to_moz(M.imported_name)
});
}
if (M.imported_names && M.imported_names[0].foreign_name.name === '*') {
specifiers.push({
type: "ImportNamespaceSpecifier",
local: to_moz(M.imported_names[0].name)
});
} else if (M.imported_names) {
M.imported_names.forEach(function(name_mapping) {
specifiers.push({
type: "ImportSpecifier",
local: to_moz(name_mapping.name),
imported: to_moz(name_mapping.foreign_name)
});
});
}
return {
type: "ImportDeclaration",
specifiers: specifiers,
source: to_moz(M.module_name)
}
});
def_to_moz(AST_Sequence, function To_Moz_SequenceExpression(M) { def_to_moz(AST_Sequence, function To_Moz_SequenceExpression(M) {
return { return {
type: "SequenceExpression", type: "SequenceExpression",
@ -356,6 +719,13 @@
}); });
def_to_moz(AST_Binary, function To_Moz_BinaryExpression(M) { def_to_moz(AST_Binary, function To_Moz_BinaryExpression(M) {
if (M.operator == "=" && to_moz_in_destructuring()) {
return {
type: "AssignmentPattern",
left: to_moz(M.left),
right: to_moz(M.right)
};
}
return { return {
type: M.operator == "&&" || M.operator == "||" ? "LogicalExpression" : "BinaryExpression", type: M.operator == "&&" || M.operator == "||" ? "LogicalExpression" : "BinaryExpression",
left: to_moz(M.left), left: to_moz(M.left),
@ -378,14 +748,29 @@
}; };
}); });
def_to_moz(AST_ObjectProperty, function To_Moz_Property(M) { def_to_moz(AST_ObjectProperty, function To_Moz_Property(M, parent) {
var key = { var key = M.key instanceof AST_Node ? to_moz(M.key) : {
type: "Literal", type: "Identifier",
value: M.key instanceof AST_SymbolMethod ? M.key.name : M.key value: M.key
}; };
if (typeof M.key === "number") {
key = {
type: "Literal",
value: Number(M.key)
};
}
if (typeof M.key === "string") {
key = {
type: "Identifier",
name: M.key
};
}
var kind; var kind;
var string_or_num = typeof M.key === "string" || typeof M.key === "number";
var computed = string_or_num ? false : !(M.key instanceof AST_Symbol) || M.key instanceof AST_SymbolRef;
if (M instanceof AST_ObjectKeyVal) { if (M instanceof AST_ObjectKeyVal) {
kind = "init"; kind = "init";
computed = !string_or_num;
} else } else
if (M instanceof AST_ObjectGetter) { if (M instanceof AST_ObjectGetter) {
kind = "get"; kind = "get";
@ -393,15 +778,81 @@
if (M instanceof AST_ObjectSetter) { if (M instanceof AST_ObjectSetter) {
kind = "set"; kind = "set";
} }
if (parent instanceof AST_Class) {
return {
type: "MethodDefinition",
computed: computed,
kind: kind,
static: M.static,
key: to_moz(M.key),
value: to_moz(M.value)
};
}
return { return {
type: "Property", type: "Property",
computed: computed,
kind: kind, kind: kind,
key: key, key: key,
value: to_moz(M.value) value: to_moz(M.value)
}; };
}); });
def_to_moz(AST_Symbol, function To_Moz_Identifier(M) { def_to_moz(AST_ConciseMethod, function To_Moz_MethodDefinition(M, parent) {
if (parent instanceof AST_Object) {
return {
type: "Property",
computed: !(M.key instanceof AST_Symbol) || M.key instanceof AST_SymbolRef,
kind: "init",
method: true,
shorthand: false,
key: to_moz(M.key),
value: to_moz(M.value)
};
}
return {
type: "MethodDefinition",
computed: !(M.key instanceof AST_Symbol) || M.key instanceof AST_SymbolRef,
kind: M.key === "constructor" ? "constructor" : "method",
static: M.static,
key: to_moz(M.key),
value: to_moz(M.value)
};
});
def_to_moz(AST_Class, function To_Moz_Class(M) {
var type = M instanceof AST_ClassExpression ? "ClassExpression" : "ClassDeclaration";
return {
type: type,
superClass: to_moz(M.extends),
id: M.name ? to_moz(M.name) : null,
body: {
type: "ClassBody",
body: M.properties.map(to_moz)
}
}
});
def_to_moz(AST_NewTarget, function To_Moz_MetaProperty(M) {
return {
type: "MetaProperty",
meta: {
type: "Identifier",
name: "new"
},
property: {
type: "Identifier",
name: "target"
}
};
});
def_to_moz(AST_Symbol, function To_Moz_Identifier(M, parent) {
if (M instanceof AST_SymbolMethod && parent.quote) {
return {
type: "Literal",
value: M.name
};
}
var def = M.definition(); var def = M.definition();
return { return {
type: "Identifier", type: "Identifier",
@ -410,14 +861,15 @@
}); });
def_to_moz(AST_RegExp, function To_Moz_RegExpLiteral(M) { def_to_moz(AST_RegExp, function To_Moz_RegExpLiteral(M) {
var value = M.value; var flags = M.value.toString().match(/[gimuy]*$/)[0];
var value = "/" + M.value.raw_source + "/" + flags;
return { return {
type: "Literal", type: "Literal",
value: value, value: value,
raw: value.toString(), raw: value,
regex: { regex: {
pattern: value.source, pattern: M.value.raw_source,
flags: value.toString().match(/[gimuy]*$/)[0] flags: flags
} }
}; };
}); });
@ -586,13 +1038,30 @@
}; };
function def_to_moz(mytype, handler) { function def_to_moz(mytype, handler) {
mytype.DEFMETHOD("to_mozilla_ast", function() { mytype.DEFMETHOD("to_mozilla_ast", function(parent) {
return set_moz_loc(this, handler(this)); return set_moz_loc(this, handler(this, parent));
}); });
}; };
var TO_MOZ_STACK = null;
function to_moz(node) { function to_moz(node) {
return node != null ? node.to_mozilla_ast() : null; if (TO_MOZ_STACK === null) { TO_MOZ_STACK = []; }
TO_MOZ_STACK.push(node);
var ast = node != null ? node.to_mozilla_ast(TO_MOZ_STACK[TO_MOZ_STACK.length - 2]) : null;
TO_MOZ_STACK.pop();
if (TO_MOZ_STACK.length === 0) { TO_MOZ_STACK = null; }
return ast
};
function to_moz_in_destructuring() {
var i = TO_MOZ_STACK.length;
while (i--) {
if (TO_MOZ_STACK[i] instanceof AST_Destructuring) {
return true;
}
}
return false;
}; };
function to_moz_block(node) { function to_moz_block(node) {

View File

@ -1455,7 +1455,15 @@ function OutputStream(options) {
output.space(); output.space();
self.module_name.print(output); self.module_name.print(output);
} }
if (self.exported_value
&& !(self.exported_value instanceof AST_Defun ||
self.exported_value instanceof AST_Function ||
self.exported_value instanceof AST_Class)
|| self.module_name
|| self.exported_names
) {
output.semicolon(); output.semicolon();
}
}); });
function parenthesize_for_noin(node, output, noin) { function parenthesize_for_noin(node, output, noin) {

View File

@ -1159,7 +1159,9 @@ function parse($TEXT, options) {
case "export": case "export":
if (!is_token(peek(), "punc", "(")) { if (!is_token(peek(), "punc", "(")) {
next(); next();
return export_(); var node = export_();
if (is("punc", ";")) semicolon();
return node;
} }
} }
} }
@ -1294,9 +1296,14 @@ function parse($TEXT, options) {
var body = _function_body(is("punc", "{"), false, is_async); var body = _function_body(is("punc", "{"), false, is_async);
var end =
body instanceof Array && body.length ? body[body.length - 1].end :
body instanceof Array ? start :
body.end;
return new AST_Arrow({ return new AST_Arrow({
start : start, start : start,
end : body.end, end : end,
async : is_async, async : is_async,
argnames : argnames, argnames : argnames,
body : body body : body
@ -1709,6 +1716,8 @@ function parse($TEXT, options) {
} }
// the await expression is parsed as a unary expression in Babel // the await expression is parsed as a unary expression in Babel
return new AST_Await({ return new AST_Await({
start: prev(),
end: S.token,
expression : maybe_unary(true), expression : maybe_unary(true),
}); });
} }
@ -1719,6 +1728,7 @@ function parse($TEXT, options) {
croak("Unexpected yield expression outside generator function", croak("Unexpected yield expression outside generator function",
S.prev.line, S.prev.col, S.prev.pos); S.prev.line, S.prev.col, S.prev.pos);
} }
var start = S.token;
var star = false; var star = false;
var has_expression = true; var has_expression = true;
@ -1742,8 +1752,10 @@ function parse($TEXT, options) {
} }
return new AST_Yield({ return new AST_Yield({
start : start,
is_star : star, is_star : star,
expression : has_expression ? expression() : null expression : has_expression ? expression() : null,
end : prev()
}); });
} }
@ -2478,7 +2490,7 @@ function parse($TEXT, options) {
next(); next();
if (is_import && is("name", "as")) { if (is_import && is("name", "as")) {
next(); // The "as" word next(); // The "as" word
name = as_symbol(AST_SymbolImportForeign); name = as_symbol(is_import ? AST_SymbolImportForeign : AST_SymbolExportForeign);
} }
names = [map_nameAsterisk(is_import, name)]; names = [map_nameAsterisk(is_import, name)];
} }
@ -2686,7 +2698,8 @@ function parse($TEXT, options) {
return subscripts(new AST_PrefixedTemplateString({ return subscripts(new AST_PrefixedTemplateString({
start: start, start: start,
prefix: expr, prefix: expr,
template_string: template_string() template_string: template_string(),
end: prev()
}), allow_calls); }), allow_calls);
} }
return expr; return expr;
@ -2699,7 +2712,8 @@ function parse($TEXT, options) {
next(); next();
args.push(new AST_Expansion({ args.push(new AST_Expansion({
start: prev(), start: prev(),
expression: expression(false) expression: expression(false),
end: prev()
})); }));
} else { } else {
args.push(expression(false)); args.push(expression(false));

View File

@ -29,6 +29,7 @@
}, },
"devDependencies": { "devDependencies": {
"acorn": "~5.4.1", "acorn": "~5.4.1",
"escodegen": "^1.9.1",
"mocha": "~3.5.1", "mocha": "~3.5.1",
"semver": "~5.5.0" "semver": "~5.5.0"
}, },

View File

@ -277,7 +277,7 @@ export_default_anonymous_function: {
foo(); foo();
} }
} }
expect_exact: "export default function(){foo()};" expect_exact: "export default function(){foo()}"
} }
export_default_arrow: { export_default_arrow: {
@ -309,7 +309,7 @@ export_default_anonymous_generator: {
yield foo(); yield foo();
} }
} }
expect_exact: "export default function*(){yield foo()};" expect_exact: "export default function*(){yield foo()}"
} }
export_default_anonymous_async_function: { export_default_anonymous_async_function: {
@ -326,7 +326,7 @@ export_default_anonymous_async_function: {
return await foo(); return await foo();
} }
} }
expect_exact: "export default async function(){return await foo()};" expect_exact: "export default async function(){return await foo()}"
} }
export_default_async_arrow_function: { export_default_async_arrow_function: {
@ -358,7 +358,7 @@ export_default_named_generator: {
yield foo(); yield foo();
} }
} }
expect_exact: "export default function*gen(){yield foo()};" expect_exact: "export default function*gen(){yield foo()}"
} }
export_default_named_async_function: { export_default_named_async_function: {
@ -375,7 +375,7 @@ export_default_named_async_function: {
return await foo(); return await foo();
} }
} }
expect_exact: "export default async function bar(){return await foo()};" expect_exact: "export default async function bar(){return await foo()}"
} }
export_default_anonymous_class: { export_default_anonymous_class: {
@ -394,7 +394,7 @@ export_default_anonymous_class: {
} }
}; };
} }
expect_exact: "export default class{constructor(){foo()}};" expect_exact: "export default class{constructor(){foo()}}"
} }
export_default_anonymous_function_not_call: { export_default_anonymous_function_not_call: {
@ -426,7 +426,7 @@ export_default_anonymous_generator_not_call: {
export default function*(){}(foo); export default function*(){}(foo);
} }
// agrees with `acorn` and `babylon 7` // agrees with `acorn` and `babylon 7`
expect_exact: "export default function*(){};foo;" expect_exact: "export default function*(){}foo;"
} }
export_default_anonymous_async_function_not_call: { export_default_anonymous_async_function_not_call: {
@ -442,5 +442,5 @@ export_default_anonymous_async_function_not_call: {
export default async function(){}(foo); export default async function(){}(foo);
} }
// agrees with `acorn` and `babylon 7` // agrees with `acorn` and `babylon 7`
expect_exact: "export default async function(){};foo;" expect_exact: "export default async function(){}foo;"
} }

View File

@ -218,7 +218,7 @@ export_statement: {
export function d() {}; export function d() {};
export class e {}; export class e {};
} }
expect_exact: "export default 3;export var a=4;export let b=6;export const c=6;export function d(){};export class e{};" expect_exact: "export default 3;export var a=4;export let b=6;export const c=6;export function d(){}export class e{}"
} }
export_default_object_expression: { export_default_object_expression: {
@ -254,7 +254,7 @@ export_default_anon_function: {
console.log(1 + 2); console.log(1 + 2);
} }
} }
expect_exact: "export default function(){console.log(3)};" expect_exact: "export default function(){console.log(3)}"
} }
export_default_anon_class: { export_default_anon_class: {
@ -266,7 +266,7 @@ export_default_anon_class: {
foo() { console.log(1 + 2); } foo() { console.log(1 + 2); }
} }
} }
expect_exact: "export default class{foo(){console.log(3)}};" expect_exact: "export default class{foo(){console.log(3)}}"
} }
export_module_statement: { export_module_statement: {
@ -680,7 +680,7 @@ export_default_function_decl: {
export default function Foo() {}; export default function Foo() {};
export function Far() {}; export function Far() {};
} }
expect_exact: "export default function Foo(){};export function Far(){};" expect_exact: "export default function Foo(){}export function Far(){}"
} }
export_default_class_decl: { export_default_class_decl: {
@ -694,7 +694,7 @@ export_default_class_decl: {
export default class Car {}; export default class Car {};
export class Cab {}; export class Cab {};
} }
expect_exact: "export default class Car{};export class Cab{};" expect_exact: "export default class Car{}export class Cab{}"
} }
object_rest_spread: { object_rest_spread: {

View File

@ -5,9 +5,9 @@ export_func_1: {
unused: true, unused: true,
} }
input: { input: {
export function f(){}; export function f(){}
} }
expect_exact: "export function f(){};" expect_exact: "export function f(){}"
} }
export_func_2: { export_func_2: {
@ -20,7 +20,7 @@ export_func_2: {
input: { input: {
export function f(){}(1); export function f(){}(1);
} }
expect_exact: "export function f(){};1;" expect_exact: "export function f(){}1;"
} }
export_func_3: { export_func_3: {
@ -33,7 +33,7 @@ export_func_3: {
input: { input: {
export function f(){}(1); export function f(){}(1);
} }
expect_exact: "export function f(){};" expect_exact: "export function f(){}"
} }
export_default_func_1: { export_default_func_1: {
@ -43,9 +43,9 @@ export_default_func_1: {
unused: true, unused: true,
} }
input: { input: {
export default function f(){}; export default function f(){}
} }
expect_exact: "export default function f(){};" expect_exact: "export default function f(){}"
} }
export_default_func_2: { export_default_func_2: {
@ -58,7 +58,7 @@ export_default_func_2: {
input: { input: {
export default function f(){}(1); export default function f(){}(1);
} }
expect_exact: "export default function f(){};1;" expect_exact: "export default function f(){}1;"
} }
export_default_func_3: { export_default_func_3: {
@ -71,7 +71,7 @@ export_default_func_3: {
input: { input: {
export default function f(){}(1); export default function f(){}(1);
} }
expect_exact: "export default function f(){};" expect_exact: "export default function f(){}"
} }
export_class_1: { export_class_1: {
@ -83,7 +83,7 @@ export_class_1: {
input: { input: {
export class C {}; export class C {};
} }
expect_exact: "export class C{};" expect_exact: "export class C{}"
} }
export_class_2: { export_class_2: {
@ -96,7 +96,7 @@ export_class_2: {
input: { input: {
export class C {}(1); export class C {}(1);
} }
expect_exact: "export class C{};1;" expect_exact: "export class C{}1;"
} }
export_class_3: { export_class_3: {
@ -109,7 +109,7 @@ export_class_3: {
input: { input: {
export class C {}(1); export class C {}(1);
} }
expect_exact: "export class C{};" expect_exact: "export class C{}"
} }
export_default_class_1: { export_default_class_1: {
@ -121,7 +121,7 @@ export_default_class_1: {
input: { input: {
export default class C {}; export default class C {};
} }
expect_exact: "export default class C{};" expect_exact: "export default class C{}"
} }
export_default_class_2: { export_default_class_2: {
@ -134,7 +134,7 @@ export_default_class_2: {
input: { input: {
export default class C {}(1); export default class C {}(1);
} }
expect_exact: "export default class C{};1;" expect_exact: "export default class C{}1;"
} }
export_default_class_3: { export_default_class_3: {
@ -147,7 +147,7 @@ export_default_class_3: {
input: { input: {
export default class C {}(1); export default class C {}(1);
} }
expect_exact: "export default class C{};" expect_exact: "export default class C{}"
} }
export_mangle_1: { export_mangle_1: {
@ -159,7 +159,7 @@ export_mangle_1: {
return one - two; return one - two;
}; };
} }
expect_exact: "export function foo(o,n){return o-n};" expect_exact: "export function foo(o,n){return o-n}"
} }
export_mangle_2: { export_mangle_2: {
@ -171,7 +171,7 @@ export_mangle_2: {
return one - two; return one - two;
}; };
} }
expect_exact: "export default function foo(o,t){return o-t};" expect_exact: "export default function foo(o,t){return o-t}"
} }
export_mangle_3: { export_mangle_3: {
@ -190,7 +190,7 @@ export_mangle_3: {
} }
}; };
} }
expect_exact: "export class C{go(r,e){return r-e+r}};" expect_exact: "export class C{go(r,e){return r-e+r}}"
} }
export_mangle_4: { export_mangle_4: {
@ -209,7 +209,7 @@ export_mangle_4: {
} }
}; };
} }
expect_exact: "export default class C{go(e,r){return e-r+e}};" expect_exact: "export default class C{go(e,r){return e-r+e}}"
} }
export_mangle_5: { export_mangle_5: {
@ -276,8 +276,8 @@ export_default_func_ref: {
unused: true, unused: true,
} }
input: { input: {
export default function f(){}; export default function f(){}
f(); f();
} }
expect_exact: "export default function f(){};f();" expect_exact: "export default function f(){}f();"
} }

View File

@ -0,0 +1,146 @@
import "mod-name";
import Foo from "bar";
import * as Food from "food"
import { Bar, Baz } from "lel";
import Bar1, { Foo2 } from "lel";
import { Bar2 as kex, Baz as food } from "lel";
const x = 0b01;
let y = 6;
export default x;
export const z = 4;
export function fun() {}
export * from "a.js";
export {A} from "a.js";
export {A1, B1} from "a.js";
export {C};
(a, [b], {c:foo = 3}, ...d) => null;
() => {};
async function f() { }
function*gen() {
yield 1;
yield* 2;
}
class Class extends Object {
constructor(...args) {
}
foo() {}
}
x = class {
static staticMethod() {}
static get foo() {}
static set bar(value) {}
get x() {}
set x(value) {}
static() {
// "static" can be a method name!
}
get() {
// "get" can be a method name!
}
async set() {
// "set" can be a method name!
}
*bar() {}
static *baz() {}
*['constructor']() {}
static ['constructor']() {}
[a]() {}
"%"(){}
}
y = {
get x() {},
set x(value) {},
bar() {},
*bar() {},
*['constructor']() {}
}
function f () {
console.log(new.target);
}
console.log([10, ...[], 20, ...[30, 40], 50]["length"]);
var { w: w1, ...V } = { w: 7, x: 1, y: 2 };
for (const x of y) {}
async function f1() { await x; }
``;
`x`;
`x${1}`;
String.raw`\n`;
// arrow.js
var foo = ([]) => "foo";
var bar = ({}) => "bar";
var with_default = (foo = "default") => foo;
var object_with_default = ({foo = "default", bar: baz = "default"}) => foo;
var array_after_spread = (...[foo]) => foo;
var array_after_spread = (...{foo}) => foo;
var computed = ({ [compute()]: x }) => {};
var array_hole = ([, , ...x] = [1, 2]) => {};
var object_trailing_elision = ({foo,}) => {};
var spread_empty_array = (...[]) => "foo";
var spread_empty_object = (...{}) => "foo";
// async.js
async (x) => await x
// destructuring.js
var [aa, bb] = cc;
var [aa, [bb, cc]] = dd;
var [,[,,,,,],,,zz,] = xx; // Trailing comma
var [,,zzz,,] = xxx; // Trailing comma after hole
var {aa, bb} = {aa:1, bb:2};
var {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};
for (const [x,y] in pairs);
for (const [a] = 0;;);
for (const {c} of cees);
// object.js
var a = {
get,
set: "foo",
get bar() {
return this.get;
},
get 5() {
return "five";
},
get 0xf55() {
return "f five five";
},
get "five"() {
return 5;
},
set one(value) {
this._one = value;
},
set 9(value) {
this._nine = value;
},
set 0b1010(value) {
this._ten = value;
},
set "eleven"(value) {
this._eleven = value;
},
*"%"() {
return 2;
},
*["%"]() {
return 2;
},
[a]() {}
};

View File

@ -1,5 +1,8 @@
var assert = require("assert"); var assert = require("assert");
var fs = require("fs");
var exec = require("child_process").exec; var exec = require("child_process").exec;
var acorn = require("acorn");
var escodegen = require("escodegen");
var uglify = require("../node"); var uglify = require("../node");
describe("spidermonkey export/import sanity test", function() { describe("spidermonkey export/import sanity test", function() {
@ -112,4 +115,42 @@ describe("spidermonkey export/import sanity test", function() {
assert.strictEqual(counter_strings, tests[i].strings, "String count mismatch for test " + tests[i].input); assert.strictEqual(counter_strings, tests[i].strings, "String count mismatch for test " + tests[i].input);
} }
}); });
it("should output and parse ES6 code correctly", function() {
var code = fs.readFileSync("test/input/spidermonkey/input.js", "utf-8");
var uglify_ast = uglify.parse(code);
var moz_ast = uglify_ast.to_mozilla_ast();
var from_moz_ast = uglify.AST_Node.from_mozilla_ast(moz_ast);
assert.strictEqual(
from_moz_ast.print_to_string(),
uglify_ast.print_to_string()
);
});
it("should be capable of importing from acorn", function() {
var code = fs.readFileSync("test/input/spidermonkey/input.js", "utf-8");
var uglify_ast = uglify.parse(code);
var moz_ast = acorn.parse(code, {sourceType: 'module', ecmaVersion: 9});
var from_moz_ast = uglify.AST_Node.from_mozilla_ast(moz_ast);
assert.strictEqual(
from_moz_ast.print_to_string(),
uglify_ast.print_to_string()
);
});
it("should produce an AST compatible with escodegen", function() {
var code = fs.readFileSync("test/input/spidermonkey/input.js", "utf-8");
var uglify_ast = uglify.parse(code);
var moz_ast = uglify_ast.to_mozilla_ast();
var generated = escodegen.generate(moz_ast)
.replace(/\[object Object\].\[object Object\]/g, "new.target"); // escodegen issue
var parsed = acorn.parse(generated, {
sourceType: "module",
ecmaVersion: 9
});
assert.strictEqual(
uglify.AST_Node.from_mozilla_ast(parsed).print_to_string(),
uglify_ast.print_to_string()
);
});
}); });

View File

@ -110,6 +110,16 @@ function run_compress_tests() {
}); });
return false; return false;
} }
var ast = input.to_mozilla_ast();
var ast_as_string = U.AST_Node.from_mozilla_ast(ast).print_to_string();
var input_string = input.print_to_string();
if (input_string !== ast_as_string) {
log("!!! Mozilla AST I/O corrupted input\n---INPUT---\n{input}\n---OUTPUT---\n{output}\n\n", {
input: input_string,
output: ast_as_string,
});
return false;
}
var options = U.defaults(test.options, { var options = U.defaults(test.options, {
warnings: false warnings: false
}); });