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({
start: my_start_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
});
},
@ -86,6 +91,29 @@
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) {
return new AST_Defun({
start: my_start_token(M),
@ -113,7 +141,8 @@
start: my_start_token(M),
end: my_end_token(M),
argnames: M.params.map(from_moz),
body: from_moz(M.body)
body: from_moz(M.body),
async: M.async,
});
},
ExpressionStatement: function(M) {
@ -147,14 +176,19 @@
if (M.method) {
args.is_generator = M.value.generator;
args.async = M.value.async;
if (key.type == "Identifier") {
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") 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({
name: args.key
});
@ -172,7 +206,7 @@
var args = {
start : my_start_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),
static : M.static,
};
@ -287,12 +321,12 @@
start: my_start_token(M),
end: my_end_token(M),
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({
foreign_name: from_moz(specifier.exported),
name: from_moz(specifier.local)
})
}),
}) : null,
module_name: from_moz(M.source)
});
},
@ -350,7 +384,7 @@
: p.type == "ArrowFunctionExpression" ? (p.params.indexOf(M) !== -1) ? AST_SymbolFunarg : AST_SymbolRef
: p.type == "ClassExpression" ? (p.id === M ? AST_SymbolClass : 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 == "BreakStatement" || p.type == "ContinueStatement" ? AST_LabelRef
: AST_SymbolRef)({
@ -400,7 +434,6 @@
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("RestElement", AST_Expansion, "argument>expression");
map("DebuggerStatement", AST_Debugger);
map("VariableDeclarator", AST_VarDef, "id>name, init>value");
map("CatchClause", AST_Catch, "param>argname, body%body");
@ -417,6 +450,13 @@
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) {
return {
type: "FunctionDeclaration",
@ -449,6 +489,7 @@
return {
type: "ArrowFunctionExpression",
params: M.argnames.map(to_moz),
async: M.async,
body: body
}
});
@ -598,6 +639,13 @@
});
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 {
type: M.operator == "&&" || M.operator == "||" ? "LogicalExpression" : "BinaryExpression",
left: to_moz(M.left),
@ -621,10 +669,16 @@
});
def_to_moz(AST_ObjectProperty, function To_Moz_Property(M, parent) {
var key = {
type: "Literal",
value: M.key instanceof AST_SymbolMethod ? M.key.name : M.key
var key = M.key instanceof AST_Node ? to_moz(M.key) : {
type: "Identifier",
value: M.key
};
if (typeof M.key === "string") {
key = {
type: "Identifier",
name: M.key
};
}
var kind;
if (M instanceof AST_ObjectKeyVal) {
kind = "init";
@ -638,7 +692,7 @@
if (parent instanceof AST_Class) {
return {
type: "MethodDefinition",
computed: !(M.key instanceof AST_Symbol),
computed: !(M.key instanceof AST_Symbol) || M.key instanceof AST_SymbolRef,
kind: kind,
static: M.static,
key: to_moz(M.key),
@ -657,7 +711,7 @@
if (parent instanceof AST_Object) {
return {
type: "Property",
computed: !(M.key instanceof AST_Symbol),
computed: !(M.key instanceof AST_Symbol) || M.key instanceof AST_SymbolRef,
kind: "init",
method: true,
shorthand: false,
@ -667,7 +721,7 @@
}
return {
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",
static: M.static,
key: to_moz(M.key),
@ -903,6 +957,16 @@
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) {
return {
type: "BlockStatement",

View File

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