further AST input/output

This commit is contained in:
Fábio Santos 2018-03-20 20:27:06 +00:00
parent 9f7246305c
commit 0c924fca64
3 changed files with 180 additions and 23 deletions

View File

@ -75,7 +75,12 @@
return new AST_Destructuring({ return new AST_Destructuring({
start: my_start_token(M), start: my_start_token(M),
end: my_end_token(M), end: my_end_token(M),
names: M.elements.map(from_moz), names: M.elements.map(function(elm) {
if (elm === null) {
return new AST_Hole();
}
return from_moz(elm);
}),
is_array: true is_array: true
}); });
}, },
@ -86,6 +91,29 @@
names: M.properties.map(from_moz), names: M.properties.map(from_moz),
}); });
}, },
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)
});
},
FunctionDeclaration: function(M) { FunctionDeclaration: function(M) {
return new AST_Defun({ return new AST_Defun({
start: my_start_token(M), start: my_start_token(M),
@ -113,7 +141,8 @@
start: my_start_token(M), start: my_start_token(M),
end: my_end_token(M), end: my_end_token(M),
argnames: M.params.map(from_moz), argnames: M.params.map(from_moz),
body: from_moz(M.body) body: from_moz(M.body),
async: M.async,
}); });
}, },
ExpressionStatement: function(M) { ExpressionStatement: function(M) {
@ -147,14 +176,19 @@
if (M.method) { if (M.method) {
args.is_generator = M.value.generator; args.is_generator = M.value.generator;
args.async = M.value.async; args.async = M.value.async;
if (key.type == "Identifier") { if (!M.computed) {
args.key = new AST_SymbolMethod({ name: args.key }); args.key = new AST_SymbolMethod({ name: args.key });
} else { } else {
args.key = from_moz(M.key); args.key = from_moz(M.key);
} }
return new AST_ConciseMethod(args); return new AST_ConciseMethod(args);
} }
if (M.kind == "init") return new AST_ObjectKeyVal(args); if (M.kind == "init") {
if (key.type != "Identifier") {
args.key = from_moz(key);
}
return new AST_ObjectKeyVal(args);
}
args.key = new AST_SymbolMethod({ args.key = new AST_SymbolMethod({
name: args.key name: args.key
}); });
@ -172,7 +206,7 @@
var args = { var args = {
start : my_start_token(M), start : my_start_token(M),
end : my_end_token(M), end : my_end_token(M),
key : from_moz(M.key), key : M.computed ? from_moz(M.key) : new AST_SymbolMethod({ name: M.key.name || M.key.value }),
value : from_moz(M.value), value : from_moz(M.value),
static : M.static, static : M.static,
}; };
@ -287,12 +321,12 @@
start: my_start_token(M), start: my_start_token(M),
end: my_end_token(M), end: my_end_token(M),
exported_definition: from_moz(M.declaration), exported_definition: from_moz(M.declaration),
exported_names: M.specifiers && M.specifiers.map(function (specifier) { exported_names: M.specifiers && M.specifiers.length ? M.specifiers.map(function (specifier) {
return new AST_NameMapping({ return new AST_NameMapping({
foreign_name: from_moz(specifier.exported), foreign_name: from_moz(specifier.exported),
name: from_moz(specifier.local) name: from_moz(specifier.local)
}) })
}), }) : null,
module_name: from_moz(M.source) module_name: from_moz(M.source)
}); });
}, },
@ -350,7 +384,7 @@
: p.type == "ArrowFunctionExpression" ? (p.params.indexOf(M) !== -1) ? AST_SymbolFunarg : AST_SymbolRef : p.type == "ArrowFunctionExpression" ? (p.params.indexOf(M) !== -1) ? AST_SymbolFunarg : AST_SymbolRef
: p.type == "ClassExpression" ? (p.id === M ? AST_SymbolClass : AST_SymbolRef) : p.type == "ClassExpression" ? (p.id === M ? AST_SymbolClass : AST_SymbolRef)
: p.type == "ClassDeclaration" ? (p.id === M ? AST_SymbolDefClass : AST_SymbolRef) : p.type == "ClassDeclaration" ? (p.id === M ? AST_SymbolDefClass : AST_SymbolRef)
: p.type == "MethodDefinition" ? AST_SymbolMethod : 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)({
@ -400,7 +434,6 @@
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("ForOfStatement", AST_ForOf, "left>init, right>object, body>body");
map("AwaitExpression", AST_Await, "argument>expression"); map("AwaitExpression", AST_Await, "argument>expression");
map("RestElement", AST_Expansion, "argument>expression");
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");
@ -417,6 +450,13 @@
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_Defun, function To_Moz_FunctionDeclaration(M) { def_to_moz(AST_Defun, function To_Moz_FunctionDeclaration(M) {
return { return {
type: "FunctionDeclaration", type: "FunctionDeclaration",
@ -449,6 +489,7 @@
return { return {
type: "ArrowFunctionExpression", type: "ArrowFunctionExpression",
params: M.argnames.map(to_moz), params: M.argnames.map(to_moz),
async: M.async,
body: body body: body
} }
}); });
@ -598,6 +639,13 @@
}); });
def_to_moz(AST_Binary, function To_Moz_BinaryExpression(M) { def_to_moz(AST_Binary, function To_Moz_BinaryExpression(M) {
if (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),
@ -621,10 +669,16 @@
}); });
def_to_moz(AST_ObjectProperty, function To_Moz_Property(M, parent) { 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 === "string") {
key = {
type: "Identifier",
name: M.key
};
}
var kind; var kind;
if (M instanceof AST_ObjectKeyVal) { if (M instanceof AST_ObjectKeyVal) {
kind = "init"; kind = "init";
@ -638,7 +692,7 @@
if (parent instanceof AST_Class) { if (parent instanceof AST_Class) {
return { return {
type: "MethodDefinition", type: "MethodDefinition",
computed: !(M.key instanceof AST_Symbol), computed: !(M.key instanceof AST_Symbol) || M.key instanceof AST_SymbolRef,
kind: kind, kind: kind,
static: M.static, static: M.static,
key: to_moz(M.key), key: to_moz(M.key),
@ -657,7 +711,7 @@
if (parent instanceof AST_Object) { if (parent instanceof AST_Object) {
return { return {
type: "Property", type: "Property",
computed: !(M.key instanceof AST_Symbol), computed: !(M.key instanceof AST_Symbol) || M.key instanceof AST_SymbolRef,
kind: "init", kind: "init",
method: true, method: true,
shorthand: false, shorthand: false,
@ -667,7 +721,7 @@
} }
return { return {
type: "MethodDefinition", type: "MethodDefinition",
computed: !(M.key instanceof AST_Symbol), computed: !(M.key instanceof AST_Symbol) || M.key instanceof AST_SymbolRef,
kind: M.key === "constructor" ? "constructor" : "method", kind: M.key === "constructor" ? "constructor" : "method",
static: M.static, static: M.static,
key: to_moz(M.key), key: to_moz(M.key),
@ -903,6 +957,16 @@
return ast 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) {
return { return {
type: "BlockStatement", type: "BlockStatement",

View File

@ -2,8 +2,8 @@ import "mod-name";
import Foo from "bar"; import Foo from "bar";
import * as Food from "food" import * as Food from "food"
import { Bar, Baz } from "lel"; import { Bar, Baz } from "lel";
import Bar, { Foo } from "lel"; import Bar1, { Foo2 } from "lel";
import { Bar as kex, Baz as food } from "lel"; import { Bar2 as kex, Baz as food } from "lel";
const x = 0b01; const x = 0b01;
let y = 6; let y = 6;
@ -13,7 +13,7 @@ export const z = 4;
export function fun() {} export function fun() {}
export * from "a.js"; export * from "a.js";
export {A} from "a.js"; export {A} from "a.js";
export {A, B} from "a.js"; export {A1, B1} from "a.js";
export {C}; export {C};
(a, [b], {c:foo = 3}, ...d) => null; (a, [b], {c:foo = 3}, ...d) => null;
@ -31,16 +31,24 @@ class Class extends Object {
x = class { x = class {
static staticMethod() {} static staticMethod() {}
static get foo() {} static get foo() {}
static set bar() {} static set bar(value) {}
get x() {} get x() {}
set x(value) {} set x(value) {}
static() { /* "static" can be a method name! */ } static() {
get() { /* "get" can be a method name! */ } // "static" can be a method name!
set() { /* "set" can be a method name! */ } }
get() {
// "get" can be a method name!
}
async set() {
// "set" can be a method name!
}
*bar() {} *bar() {}
static *baz() {} static *baz() {}
*['constructor']() {} *['constructor']() {}
static ['constructor']() {} static ['constructor']() {}
[a]() {}
"%"(){}
} }
y = { y = {
@ -50,8 +58,81 @@ y = {
*bar() {}, *bar() {},
*['constructor']() {} *['constructor']() {}
} }
console.log(new.target); function f () {
console.log(new.target);
}
console.log([10, ...[], 20, ...[30, 40], 50]["length"]); console.log([10, ...[], 20, ...[30, 40], 50]["length"]);
var { w: w1, ...V } = { w: 7, x: 1, y: 2 }; var { w: w1, ...V } = { w: 7, x: 1, y: 2 };
for (const x of y) {} for (const x of y) {}
async function f1() { await x + y; } async function f1() { await x + y; }
// 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,6 +1,7 @@
var assert = require("assert"); var assert = require("assert");
var fs = require("fs"); var fs = require("fs");
var exec = require("child_process").exec; var exec = require("child_process").exec;
var acorn = require("acorn");
var uglify = require("../node"); var uglify = require("../node");
describe("spidermonkey export/import sanity test", function() { describe("spidermonkey export/import sanity test", function() {
@ -124,4 +125,15 @@ describe("spidermonkey export/import sanity test", function() {
uglify_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()
);
});
}); });