[Pkg-javascript-commits] [uglifyjs] 155/228: handle overlapped variable definitions (#1691)
Jonas Smedegaard
dr at jones.dk
Sat Apr 15 14:25:26 UTC 2017
This is an automated email from the git hooks/post-receive script.
js pushed a commit to branch master
in repository uglifyjs.
commit 57ce5bd9e085546a5c1cb8dd4a3ea71ab6c56f26
Author: Alex Lam S.L <alexlamsl at gmail.com>
Date: Mon Mar 27 01:30:21 2017 +0800
handle overlapped variable definitions (#1691)
Process variable definitions with or without assigned values against:
- `arguments`
- named function arguments
- multiple definitions within same scope
Essentially demote variable declarations with no value assignments.
Also fixed invalid use of `AST_VarDef` over `arguments` - should use a member of `AST_SymbolDeclaration` instead.
---
lib/compress.js | 17 ++-
lib/scope.js | 32 ++---
test/compress/reduce_vars.js | 289 ++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 314 insertions(+), 24 deletions(-)
diff --git a/lib/compress.js b/lib/compress.js
index 83486b6..590015f 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -260,7 +260,7 @@ merge(Compressor.prototype, {
if (node instanceof AST_SymbolRef) {
var d = node.definition();
d.references.push(node);
- if (!d.fixed || !is_safe(d)
+ if (d.fixed === undefined || !is_safe(d)
|| is_modified(node, 0, d.fixed instanceof AST_Lambda)) {
d.fixed = false;
}
@@ -270,10 +270,10 @@ merge(Compressor.prototype, {
}
if (node instanceof AST_VarDef) {
var d = node.name.definition();
- if (d.fixed === undefined) {
- d.fixed = node.value || make_node(AST_Undefined, node);
+ if (d.fixed == null) {
+ d.fixed = node.value;
mark_as_safe(d);
- } else {
+ } else if (node.value) {
d.fixed = false;
}
}
@@ -357,7 +357,14 @@ merge(Compressor.prototype, {
function is_safe(def) {
for (var i = safe_ids.length, id = def.id; --i >= 0;) {
- if (safe_ids[i][id]) return true;
+ if (safe_ids[i][id]) {
+ if (def.fixed == null) {
+ var orig = def.orig[0];
+ if (orig instanceof AST_SymbolFunarg || orig.name == "arguments") return false;
+ def.fixed = make_node(AST_Undefined, orig);
+ }
+ return true;
+ }
}
}
diff --git a/lib/scope.js b/lib/scope.js
index 483503e..b255032 100644
--- a/lib/scope.js
+++ b/lib/scope.js
@@ -100,15 +100,14 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
if (node instanceof AST_Catch) {
var save_scope = scope;
scope = new AST_Scope(node);
- scope.init_scope_vars();
- scope.parent_scope = save_scope;
+ scope.init_scope_vars(save_scope);
descend();
scope = save_scope;
return true;
}
if (node instanceof AST_Scope) {
- node.init_scope_vars();
- var save_scope = node.parent_scope = scope;
+ node.init_scope_vars(scope);
+ var save_scope = scope;
var save_defun = defun;
var save_labels = labels;
defun = scope = node;
@@ -243,23 +242,24 @@ AST_Toplevel.DEFMETHOD("def_global", function(node){
}
});
-AST_Scope.DEFMETHOD("init_scope_vars", function(){
- this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
- this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope)
- this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
- this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
- this.parent_scope = null; // the parent scope
- this.enclosed = []; // a list of variables from this or outer scope(s) that are referenced from this or inner scopes
- this.cname = -1; // the current index for mangling functions/variables
+AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope){
+ this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
+ this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope)
+ this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
+ this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
+ this.parent_scope = parent_scope; // the parent scope
+ this.enclosed = []; // a list of variables from this or outer scope(s) that are referenced from this or inner scopes
+ this.cname = -1; // the current index for mangling functions/variables
});
AST_Lambda.DEFMETHOD("init_scope_vars", function(){
AST_Scope.prototype.init_scope_vars.apply(this, arguments);
this.uses_arguments = false;
-
- var symbol = new AST_VarDef({ name: "arguments", start: this.start, end: this.end });
- var def = new SymbolDef(this, this.variables.size(), symbol);
- this.variables.set(symbol.name, def);
+ this.def_variable(new AST_SymbolVar({
+ name: "arguments",
+ start: this.start,
+ end: this.end
+ }));
});
AST_SymbolRef.DEFMETHOD("reference", function(options) {
diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js
index f4dd68d..87942ab 100644
--- a/test/compress/reduce_vars.js
+++ b/test/compress/reduce_vars.js
@@ -425,7 +425,7 @@ iife_new: {
expect_stdout: true
}
-multi_def: {
+multi_def_1: {
options = {
evaluate: true,
reduce_vars: true,
@@ -435,7 +435,7 @@ multi_def: {
if (a)
var b = 1;
else
- var b = 2
+ var b = 2;
console.log(b + 1);
}
}
@@ -444,7 +444,7 @@ multi_def: {
if (a)
var b = 1;
else
- var b = 2
+ var b = 2;
console.log(b + 1);
}
}
@@ -479,6 +479,33 @@ multi_def_2: {
}
}
+multi_def_3: {
+ options = {
+ evaluate: true,
+ reduce_vars: true,
+ }
+ input: {
+ function f(a) {
+ var b = 2;
+ if (a)
+ var b;
+ else
+ var b;
+ console.log(b + 1);
+ }
+ }
+ expect: {
+ function f(a) {
+ var b = 2;
+ if (a)
+ var b;
+ else
+ var b;
+ console.log(3);
+ }
+ }
+}
+
use_before_var: {
options = {
evaluate: true,
@@ -1571,3 +1598,259 @@ unary_delete: {
}
expect_stdout: true
}
+
+redefine_arguments_1: {
+ options = {
+ evaluate: true,
+ keep_fargs: false,
+ reduce_vars: true,
+ unused: true,
+ }
+ input: {
+ function f() {
+ var arguments;
+ return typeof arguments;
+ }
+ function g() {
+ var arguments = 42;
+ return typeof arguments;
+ }
+ function h(x) {
+ var arguments = x;
+ return typeof arguments;
+ }
+ console.log(f(), g(), h());
+ }
+ expect: {
+ function f() {
+ var arguments;
+ return typeof arguments;
+ }
+ function g() {
+ return"number";
+ }
+ function h(x) {
+ var arguments = x;
+ return typeof arguments;
+ }
+ console.log(f(), g(), h());
+ }
+ expect_stdout: "object number undefined"
+}
+
+redefine_arguments_2: {
+ options = {
+ evaluate: true,
+ keep_fargs: false,
+ reduce_vars: true,
+ side_effects: true,
+ toplevel: true,
+ unused: true,
+ }
+ input: {
+ function f() {
+ var arguments;
+ return typeof arguments;
+ }
+ function g() {
+ var arguments = 42;
+ return typeof arguments;
+ }
+ function h(x) {
+ var arguments = x;
+ return typeof arguments;
+ }
+ console.log(f(), g(), h());
+ }
+ expect: {
+ console.log(function() {
+ var arguments;
+ return typeof arguments;
+ }(), function() {
+ return"number";
+ }(), function(x) {
+ var arguments = x;
+ return typeof arguments;
+ }());
+ }
+ expect_stdout: "object number undefined"
+}
+
+redefine_arguments_3: {
+ options = {
+ evaluate: true,
+ keep_fargs: false,
+ passes: 3,
+ reduce_vars: true,
+ side_effects: true,
+ toplevel: true,
+ unused: true,
+ }
+ input: {
+ function f() {
+ var arguments;
+ return typeof arguments;
+ }
+ function g() {
+ var arguments = 42;
+ return typeof arguments;
+ }
+ function h(x) {
+ var arguments = x;
+ return typeof arguments;
+ }
+ console.log(f(), g(), h());
+ }
+ expect: {
+ console.log(function() {
+ var arguments;
+ return typeof arguments;
+ }(), "number", "undefined");
+ }
+ expect_stdout: "object number undefined"
+}
+
+redefine_farg_1: {
+ options = {
+ evaluate: true,
+ keep_fargs: false,
+ reduce_vars: true,
+ unused: true,
+ }
+ input: {
+ function f(a) {
+ var a;
+ return typeof a;
+ }
+ function g(a) {
+ var a = 42;
+ return typeof a;
+ }
+ function h(a, b) {
+ var a = b;
+ return typeof a;
+ }
+ console.log(f([]), g([]), h([]));
+ }
+ expect: {
+ function f(a) {
+ var a;
+ return typeof a;
+ }
+ function g() {
+ return"number";
+ }
+ function h(a, b) {
+ var a = b;
+ return typeof a;
+ }
+ console.log(f([]), g([]), h([]));
+ }
+ expect_stdout: "object number undefined"
+}
+
+redefine_farg_2: {
+ options = {
+ evaluate: true,
+ keep_fargs: false,
+ reduce_vars: true,
+ side_effects: true,
+ toplevel: true,
+ unused: true,
+ }
+ input: {
+ function f(a) {
+ var a;
+ return typeof a;
+ }
+ function g(a) {
+ var a = 42;
+ return typeof a;
+ }
+ function h(a, b) {
+ var a = b;
+ return typeof a;
+ }
+ console.log(f([]), g([]), h([]));
+ }
+ expect: {
+ console.log(function(a) {
+ var a;
+ return typeof a;
+ }([]), function() {
+ return "number";
+ }(),function(a, b) {
+ var a = b;
+ return typeof a;
+ }([]));
+ }
+ expect_stdout: "object number undefined"
+}
+
+redefine_farg_3: {
+ options = {
+ evaluate: true,
+ keep_fargs: false,
+ passes: 3,
+ reduce_vars: true,
+ side_effects: true,
+ toplevel: true,
+ unused: true,
+ }
+ input: {
+ function f(a) {
+ var a;
+ return typeof a;
+ }
+ function g(a) {
+ var a = 42;
+ return typeof a;
+ }
+ function h(a, b) {
+ var a = b;
+ return typeof a;
+ }
+ console.log(f([]), g([]), h([]));
+ }
+ expect: {
+ console.log(function(a) {
+ var a;
+ return typeof a;
+ }([]), "number", function(a) {
+ var a = void 0;
+ return typeof a;
+ }([]));
+ }
+ expect_stdout: "object number undefined"
+}
+
+delay_def: {
+ options = {
+ evaluate: true,
+ reduce_vars: true,
+ unused: true,
+ }
+ input: {
+ function f() {
+ return a;
+ var a;
+ }
+ function g() {
+ return a;
+ var a = 1;
+ }
+ console.log(f(), g());
+ }
+ expect: {
+ function f() {
+ return a;
+ var a;
+ }
+ function g() {
+ return a;
+ var a = 1;
+ }
+ console.log(f(), g());
+ }
+ expect_stdout: true
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/uglifyjs.git
More information about the Pkg-javascript-commits
mailing list