From 8da3754e51140c0eee80f02fcf3f5d99a74ca86e Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Sat, 2 Dec 2017 02:18:33 +0800 Subject: [PATCH] improve `evaluate` on `typeof` (#2550) - gated through `typeofs` --- lib/compress.js | 10 ++++-- test/compress/typeof.js | 80 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 86 insertions(+), 4 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index 5301d48f..7d87c4a6 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -1828,12 +1828,17 @@ merge(Compressor.prototype, { return this; }); def(AST_UnaryPrefix, function(compressor){ + var e = this.expression; // Function would be evaluated to an array and so typeof would // incorrectly return 'object'. Hence making is a special case. - if (this.operator == "typeof" && this.expression instanceof AST_Function) { + if (compressor.option("typeofs") + && this.operator == "typeof" + && (e instanceof AST_Lambda + || e instanceof AST_SymbolRef + && e.fixed_value() instanceof AST_Lambda)) { return typeof function(){}; } - var e = ev(this.expression, compressor); + e = ev(e, compressor); if (e === this.expression) return this; switch (this.operator) { case "!": return !e; @@ -1894,7 +1899,6 @@ merge(Compressor.prototype, { return value === node ? this : value; }); def(AST_SymbolRef, function(compressor){ - if (!compressor.option("reduce_vars")) return this; var fixed = this.fixed_value(); if (!fixed) return this; this._eval = return_this; diff --git a/test/compress/typeof.js b/test/compress/typeof.js index 34949fbe..180e5451 100644 --- a/test/compress/typeof.js +++ b/test/compress/typeof.js @@ -1,6 +1,7 @@ typeof_evaluation: { options = { - evaluate: true + evaluate: true, + typeofs: true, }; input: { a = typeof 1; @@ -60,3 +61,80 @@ issue_1668: { if (1); } } + +typeof_defun_1: { + options = { + evaluate: true, + inline: true, + passes: 2, + reduce_vars: true, + side_effects: true, + toplevel: true, + typeofs: true, + unused: true, + } + input: { + function f() { + console.log("YES"); + } + function g() { + h = 42; + console.log("NOPE"); + } + function h() { + console.log("YUP"); + } + g = 42; + "function" == typeof f && f(); + "function" == typeof g && g(); + "function" == typeof h && h(); + } + expect: { + function g() { + h = 42; + console.log("NOPE"); + } + function h() { + console.log("YUP"); + } + g = 42; + console.log("YES"); + "function" == typeof g && g(); + h(); + } + expect_stdout: [ + "YES", + "YUP", + ] +} + +typeof_defun_2: { + options = { + evaluate: true, + reduce_vars: true, + toplevel: true, + typeofs: true, + } + input: { + var f = function() { + console.log(x); + }; + var x = 0; + x++ < 2 && typeof f == "function" && f(); + x++ < 2 && typeof f == "function" && f(); + x++ < 2 && typeof f == "function" && f(); + } + expect: { + var f = function() { + console.log(x); + }; + var x = 0; + x++ < 2 && f(); + x++ < 2 && f(); + x++ < 2 && f(); + } + expect_stdout: [ + "1", + "2", + ] +} -- 2.34.1