diff options
author | Alex Lam S.L <alexlamsl@gmail.com> | 2018-03-02 04:04:29 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-03-02 04:04:29 +0800 |
commit | 38f2b4579fc2c8f7fa4e31b544dc93be9dcb031e (patch) | |
tree | 89089eb4b03de1ee227d164d51278a2f156cf959 /lib/compress.js | |
parent | 56e2a369d0b522c315a3b146bdf7581d8e71d9cc (diff) | |
download | tracifyjs-38f2b4579fc2c8f7fa4e31b544dc93be9dcb031e.tar.gz tracifyjs-38f2b4579fc2c8f7fa4e31b544dc93be9dcb031e.zip |
fix value reference caching in `evaluate` (#2969)
fixes #2968
Diffstat (limited to 'lib/compress.js')
-rw-r--r-- | lib/compress.js | 53 |
1 files changed, 29 insertions, 24 deletions
diff --git a/lib/compress.js b/lib/compress.js index 504d270b..97e4c11d 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -2365,7 +2365,11 @@ merge(Compressor.prototype, { // descendant of AST_Node. AST_Node.DEFMETHOD("evaluate", function(compressor){ if (!compressor.option("evaluate")) return this; - var val = this._eval(compressor, 1); + var cached = []; + var val = this._eval(compressor, cached, 1); + cached.forEach(function(node) { + delete node._eval; + }); if (!val || val instanceof RegExp) return val; if (typeof val == "function" || typeof val == "object") return this; return val; @@ -2401,12 +2405,12 @@ merge(Compressor.prototype, { } return this; }); - def(AST_Array, function(compressor, depth) { + def(AST_Array, function(compressor, cached, depth) { if (compressor.option("unsafe")) { var elements = []; for (var i = 0, len = this.elements.length; i < len; i++) { var element = this.elements[i]; - var value = element._eval(compressor, depth); + var value = element._eval(compressor, cached, depth); if (element === value) return this; elements.push(value); } @@ -2414,7 +2418,7 @@ merge(Compressor.prototype, { } return this; }); - def(AST_Object, function(compressor, depth) { + def(AST_Object, function(compressor, cached, depth) { if (compressor.option("unsafe")) { var val = {}; for (var i = 0, len = this.properties.length; i < len; i++) { @@ -2423,14 +2427,14 @@ merge(Compressor.prototype, { if (key instanceof AST_Symbol) { key = key.name; } else if (key instanceof AST_Node) { - key = key._eval(compressor, depth); + key = key._eval(compressor, cached, depth); if (key === prop.key) return this; } if (typeof Object.prototype[key] === 'function') { return this; } if (prop.value instanceof AST_Function) continue; - val[key] = prop.value._eval(compressor, depth); + val[key] = prop.value._eval(compressor, cached, depth); if (val[key] === prop.value) return this; } return val; @@ -2438,7 +2442,7 @@ merge(Compressor.prototype, { return this; }); var non_converting_unary = makePredicate("! typeof void"); - def(AST_UnaryPrefix, function(compressor, depth) { + def(AST_UnaryPrefix, function(compressor, cached, depth) { var e = this.expression; // Function would be evaluated to an array and so typeof would // incorrectly return 'object'. Hence making is a special case. @@ -2450,7 +2454,7 @@ merge(Compressor.prototype, { return typeof function(){}; } if (!non_converting_unary(this.operator)) depth++; - e = e._eval(compressor, depth); + e = e._eval(compressor, cached, depth); if (e === this.expression) return this; switch (this.operator) { case "!": return !e; @@ -2467,11 +2471,11 @@ merge(Compressor.prototype, { return this; }); var non_converting_binary = makePredicate("&& || === !=="); - def(AST_Binary, function(compressor, depth) { + def(AST_Binary, function(compressor, cached, depth) { if (!non_converting_binary(this.operator)) depth++; - var left = this.left._eval(compressor, depth); + var left = this.left._eval(compressor, cached, depth); if (left === this.left) return this; - var right = this.right._eval(compressor, depth); + var right = this.right._eval(compressor, cached, depth); if (right === this.right) return this; var result; switch (this.operator) { @@ -2505,27 +2509,28 @@ merge(Compressor.prototype, { } return result; }); - def(AST_Conditional, function(compressor, depth) { - var condition = this.condition._eval(compressor, depth); + def(AST_Conditional, function(compressor, cached, depth) { + var condition = this.condition._eval(compressor, cached, depth); if (condition === this.condition) return this; var node = condition ? this.consequent : this.alternative; - var value = node._eval(compressor, depth); + var value = node._eval(compressor, cached, depth); return value === node ? this : value; }); - def(AST_SymbolRef, function(compressor, depth) { + def(AST_SymbolRef, function(compressor, cached, depth) { var fixed = this.fixed_value(); if (!fixed) return this; var value; - if (HOP(fixed, "_eval")) { + if (cached.indexOf(fixed) >= 0) { value = fixed._eval(); } else { this._eval = return_this; - value = fixed._eval(compressor, depth); + value = fixed._eval(compressor, cached, depth); delete this._eval; if (value === fixed) return this; fixed._eval = function() { return value; }; + cached.push(fixed); } if (value && typeof value == "object") { var escaped = this.definition().escaped; @@ -2560,11 +2565,11 @@ merge(Compressor.prototype, { ], }; convert_to_predicate(static_values); - def(AST_PropAccess, function(compressor, depth) { + def(AST_PropAccess, function(compressor, cached, depth) { if (compressor.option("unsafe")) { var key = this.property; if (key instanceof AST_Node) { - key = key._eval(compressor, depth); + key = key._eval(compressor, cached, depth); if (key === this.property) return this; } var exp = this.expression; @@ -2573,7 +2578,7 @@ merge(Compressor.prototype, { if (!(static_values[exp.name] || return_false)(key)) return this; val = global_objs[exp.name]; } else { - val = exp._eval(compressor, depth + 1); + val = exp._eval(compressor, cached, depth + 1); if (!val || val === exp || !HOP(val, key)) return this; if (typeof val == "function") switch (key) { case "name": @@ -2588,12 +2593,12 @@ merge(Compressor.prototype, { } return this; }); - def(AST_Call, function(compressor, depth) { + def(AST_Call, function(compressor, cached, depth) { var exp = this.expression; if (compressor.option("unsafe") && exp instanceof AST_PropAccess) { var key = exp.property; if (key instanceof AST_Node) { - key = key._eval(compressor, depth); + key = key._eval(compressor, cached, depth); if (key === exp.property) return this; } var val; @@ -2602,13 +2607,13 @@ merge(Compressor.prototype, { if (!(static_fns[e.name] || return_false)(key)) return this; val = global_objs[e.name]; } else { - val = e._eval(compressor, depth + 1); + val = e._eval(compressor, cached, depth + 1); if (val === e || !(val && native_fns[val.constructor.name] || return_false)(key)) return this; } var args = []; for (var i = 0, len = this.args.length; i < len; i++) { var arg = this.args[i]; - var value = arg._eval(compressor, depth); + var value = arg._eval(compressor, cached, depth); if (arg === value) return this; args.push(value); } |