more fixes:
- added walker for AST_ObjectProperty - handle redefinitions properly (only mangle one symbol, make them all point to a single definition) DynarchLIB seems to run fine after mangling + compressed output.
This commit is contained in:
10
lib/ast.js
10
lib/ast.js
@@ -136,7 +136,7 @@ var AST_ForIn = DEFNODE("ForIn", "init name object", {
|
|||||||
_walk: function(visitor) {
|
_walk: function(visitor) {
|
||||||
return visitor._visit(this, function(){
|
return visitor._visit(this, function(){
|
||||||
if (this.init) this.init._walk(visitor);
|
if (this.init) this.init._walk(visitor);
|
||||||
if (this.name) this.name._walk(visitor);
|
else if (this.name) this.name._walk(visitor);
|
||||||
if (this.object) this.object._walk(visitor);
|
if (this.object) this.object._walk(visitor);
|
||||||
this.body._walk(visitor);
|
this.body._walk(visitor);
|
||||||
});
|
});
|
||||||
@@ -461,7 +461,13 @@ var AST_Object = DEFNODE("Object", "properties", {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value");
|
var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
|
||||||
|
_walk: function(visitor) {
|
||||||
|
return visitor._visit(this, function(){
|
||||||
|
this.value._walk(visitor);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
var AST_ObjectKeyVal = DEFNODE("ObjectKeyval", null, {
|
var AST_ObjectKeyVal = DEFNODE("ObjectKeyval", null, {
|
||||||
}, AST_ObjectProperty);
|
}, AST_ObjectProperty);
|
||||||
|
|||||||
@@ -707,8 +707,9 @@ function OutputStream(options) {
|
|||||||
var expr = self.expression;
|
var expr = self.expression;
|
||||||
expr.print(output);
|
expr.print(output);
|
||||||
if (expr instanceof AST_Number) {
|
if (expr instanceof AST_Number) {
|
||||||
if (!/[xa-f.]/i.test(output.last()))
|
if (!/[xa-f.]/i.test(output.last())) {
|
||||||
output.print(".");
|
output.print(".");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
output.print(".");
|
output.print(".");
|
||||||
output.print_name(self.property);
|
output.print_name(self.property);
|
||||||
@@ -805,7 +806,11 @@ function OutputStream(options) {
|
|||||||
output.print_name(self.name);
|
output.print_name(self.name);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_SymbolDeclaration, function(self, output){
|
DEFPRINT(AST_SymbolDeclaration, function(self, output){
|
||||||
output.print_name(self.mangled_name || self.name);
|
if (self.uniq) {
|
||||||
|
self.uniq.print(output);
|
||||||
|
} else {
|
||||||
|
output.print_name(self.mangled_name || self.name);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_SymbolRef, function(self, output){
|
DEFPRINT(AST_SymbolRef, function(self, output){
|
||||||
var def = self.symbol;
|
var def = self.symbol;
|
||||||
|
|||||||
72
lib/scope.js
72
lib/scope.js
@@ -1,4 +1,4 @@
|
|||||||
AST_Scope.DEFMETHOD("figure_out_scope", function(){
|
AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
|
||||||
// This does what ast_add_scope did in UglifyJS v1.
|
// This does what ast_add_scope did in UglifyJS v1.
|
||||||
//
|
//
|
||||||
// Part of it could be done at parse time, but it would complicate
|
// Part of it could be done at parse time, but it would complicate
|
||||||
@@ -42,28 +42,30 @@ AST_Scope.DEFMETHOD("figure_out_scope", function(){
|
|||||||
// XXX: this is wrong according to ECMA-262 (12.4). the
|
// XXX: this is wrong according to ECMA-262 (12.4). the
|
||||||
// `catch` argument name should be visible only inside the
|
// `catch` argument name should be visible only inside the
|
||||||
// catch block. For a quick fix AST_Catch should inherit
|
// catch block. For a quick fix AST_Catch should inherit
|
||||||
// from AST_Scope.
|
// from AST_Scope. Keeping it this way because of IE,
|
||||||
|
// which doesn't obey the standard. (it introduces the
|
||||||
|
// identifier in the enclosing scope)
|
||||||
scope.def_variable(node);
|
scope.def_variable(node);
|
||||||
}
|
}
|
||||||
else if (node instanceof AST_SymbolRef) {
|
else if (node instanceof AST_SymbolRef) {
|
||||||
node.scope = scope;
|
node.scope = scope;
|
||||||
}
|
}
|
||||||
|
if (node instanceof AST_LabelRef) {
|
||||||
|
var sym = scope.find_label(node);
|
||||||
|
if (!sym) throw new Error("Undefined label " + node.name);
|
||||||
|
node.reference(sym);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
this.walk(tw);
|
this.walk(tw);
|
||||||
|
|
||||||
// pass 2: find back references and eval/with
|
// pass 2: find back references and eval/with
|
||||||
var tw = new TreeWalker(function(node){
|
var tw = new TreeWalker(function(node){
|
||||||
if (node instanceof AST_LabelRef) {
|
if (node instanceof AST_SymbolRef) {
|
||||||
var sym = node.scope.find_label(node);
|
|
||||||
if (!sym) throw new Error("Undefined label " + node.name);
|
|
||||||
node.reference(sym);
|
|
||||||
}
|
|
||||||
else if (node instanceof AST_SymbolRef) {
|
|
||||||
var sym = node.scope.find_variable(node);
|
var sym = node.scope.find_variable(node);
|
||||||
node.reference(sym);
|
node.reference(sym);
|
||||||
if (!sym) {
|
if (!sym) {
|
||||||
if (node.name == "eval") {
|
if (node.name == "eval") {
|
||||||
for (var s = scope; s; s = s.parent_scope)
|
for (var s = node.scope; s; s = s.parent_scope)
|
||||||
s.uses_eval = true;
|
s.uses_eval = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,10 +74,11 @@ AST_Scope.DEFMETHOD("figure_out_scope", function(){
|
|||||||
this.walk(tw);
|
this.walk(tw);
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Scope.DEFMETHOD("scope_warnings", function(options){
|
AST_Toplevel.DEFMETHOD("scope_warnings", function(options){
|
||||||
options = defaults(options, {
|
options = defaults(options, {
|
||||||
undeclared : false,
|
undeclared : false,
|
||||||
assign_to_global : true
|
assign_to_global : true,
|
||||||
|
eval : true
|
||||||
});
|
});
|
||||||
var tw = new TreeWalker(function(node){
|
var tw = new TreeWalker(function(node){
|
||||||
if (options.undeclared
|
if (options.undeclared
|
||||||
@@ -105,6 +108,12 @@ AST_Scope.DEFMETHOD("scope_warnings", function(options){
|
|||||||
col: node.start.col
|
col: node.start.col
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (options.eval
|
||||||
|
&& node instanceof AST_SymbolRef
|
||||||
|
&& node.undeclared
|
||||||
|
&& node.name == "eval") {
|
||||||
|
AST_Node.warn("Eval is used [{line},{col}]", node.start);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
this.walk(tw);
|
this.walk(tw);
|
||||||
});
|
});
|
||||||
@@ -139,15 +148,18 @@ AST_Scope.DEFMETHOD("find_label", function(name){
|
|||||||
});
|
});
|
||||||
|
|
||||||
AST_Scope.DEFMETHOD("def_function", function(symbol){
|
AST_Scope.DEFMETHOD("def_function", function(symbol){
|
||||||
this.def_variable(symbol);
|
|
||||||
this.functions[symbol.name] = symbol;
|
this.functions[symbol.name] = symbol;
|
||||||
symbol.scope = this;
|
this.def_variable(symbol);
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Scope.DEFMETHOD("def_variable", function(symbol){
|
AST_Scope.DEFMETHOD("def_variable", function(symbol){
|
||||||
symbol.global = !this.parent_scope;
|
symbol.global = !this.parent_scope;
|
||||||
this.variables[symbol.name] = symbol;
|
var existing = this.variables[symbol.name];
|
||||||
delete this.functions[symbol.name];
|
if (!existing) {
|
||||||
|
this.variables[symbol.name] = symbol;
|
||||||
|
} else {
|
||||||
|
symbol.uniq = existing;
|
||||||
|
}
|
||||||
symbol.scope = this;
|
symbol.scope = this;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -158,7 +170,7 @@ AST_Scope.DEFMETHOD("def_label", function(symbol){
|
|||||||
|
|
||||||
AST_Scope.DEFMETHOD("next_mangled", function(for_label){
|
AST_Scope.DEFMETHOD("next_mangled", function(for_label){
|
||||||
var ext = this.enclosed, n = ext.length;
|
var ext = this.enclosed, n = ext.length;
|
||||||
out: for (;;) {
|
out: while (true) {
|
||||||
var m = base54(for_label
|
var m = base54(for_label
|
||||||
? (++this.lname)
|
? (++this.lname)
|
||||||
: (++this.cname));
|
: (++this.cname));
|
||||||
@@ -184,22 +196,32 @@ AST_Scope.DEFMETHOD("next_mangled", function(for_label){
|
|||||||
});
|
});
|
||||||
|
|
||||||
AST_SymbolDeclaration.DEFMETHOD("mangle", function(){
|
AST_SymbolDeclaration.DEFMETHOD("mangle", function(){
|
||||||
if (!this.global)
|
if (this.uniq) {
|
||||||
this.mangled_name = this.scope.next_mangled(false);
|
this.uniq.mangle();
|
||||||
|
}
|
||||||
|
else if (!(this.global
|
||||||
|
|| this.scope.uses_eval
|
||||||
|
|| this.scope.uses_with
|
||||||
|
|| this.mangled_name)) {
|
||||||
|
this.mangled_name = this.scope.next_mangled(this instanceof AST_Label);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Label.DEFMETHOD("mangle", function(){
|
AST_Toplevel.DEFMETHOD("mangle_names", function(){
|
||||||
this.mangled_name = this.scope.next_mangled(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
AST_Scope.DEFMETHOD("mangle_names", function(){
|
|
||||||
var tw = new TreeWalker(function(node){
|
var tw = new TreeWalker(function(node){
|
||||||
// We only need to mangle declarations. Special logic wired
|
// We only need to mangle declarations. Special logic wired
|
||||||
// into the code generator will display the mangled name if
|
// into the code generator will display the mangled name if
|
||||||
// it's present (and for AST_SymbolRef-s it'll use the mangled
|
// it's present (and for AST_SymbolRef-s it'll use the mangled
|
||||||
// name of the AST_SymbolDeclaration that it points to).
|
// name of the AST_SymbolDeclaration that it points to).
|
||||||
if (node instanceof AST_SymbolDeclaration) {
|
if (node instanceof AST_Scope) {
|
||||||
node.mangle();
|
var a = node.variables;
|
||||||
|
for (var i in a) if (HOP(a, i)) {
|
||||||
|
a[i].mangle();
|
||||||
|
}
|
||||||
|
var a = node.labels;
|
||||||
|
for (var i in a) if (HOP(a, i)) {
|
||||||
|
a[i].mangle();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.walk(tw);
|
this.walk(tw);
|
||||||
|
|||||||
@@ -5,8 +5,10 @@
|
|||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
var vm = require("vm");
|
var vm = require("vm");
|
||||||
var sys = require("util");
|
var sys = require("util");
|
||||||
|
var path = require("path");
|
||||||
|
|
||||||
function load_global(file) {
|
function load_global(file) {
|
||||||
|
file = path.resolve(path.dirname(module.filename), file);
|
||||||
try {
|
try {
|
||||||
var code = fs.readFileSync(file, "utf8");
|
var code = fs.readFileSync(file, "utf8");
|
||||||
return vm.runInThisContext(code, file);
|
return vm.runInThisContext(code, file);
|
||||||
|
|||||||
Reference in New Issue
Block a user