From f496ac5c85263581aeaad6deb816a38c1fcd3b45 Mon Sep 17 00:00:00 2001 From: kzc Date: Sun, 15 Oct 2017 23:35:04 -0400 Subject: [PATCH] implement compress option `computed_props` (#2361) transforms `{["computed"]: 1}` into `{computed: 1}` --- README.md | 3 ++ lib/compress.js | 13 +++++++++ test/compress/object.js | 61 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+) diff --git a/README.md b/README.md index 7b4d6059..64a33c4e 100644 --- a/README.md +++ b/README.md @@ -759,6 +759,9 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u - `ecma` -- default `5`. Pass `6` or greater to enable `compress` options that will transform ES5 code into smaller ES6+ equivalent forms. +- `computed_props` -- default `true`. Transforms constant computed properties + into regular ones: `{["computed"]: 1}` is converted into `{computed: 1}`. + ## Mangle options - `reserved` (default `[]`). Pass an array of identifiers that should be diff --git a/lib/compress.js b/lib/compress.js index 9304e5d4..27d3c8eb 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -53,6 +53,7 @@ function Compressor(options, false_by_default) { cascade : !false_by_default, collapse_vars : !false_by_default, comparisons : !false_by_default, + computed_props: !false_by_default, conditionals : !false_by_default, dead_code : !false_by_default, drop_console : false, @@ -4869,6 +4870,18 @@ merge(Compressor.prototype, { }); OPT(AST_ObjectKeyVal, function(self, compressor){ + // ["p"]:1 ---> p:1 + // [42]:1 ---> 42:1 + if (compressor.option("computed_props") + && self.key instanceof AST_Constant // save a comparison in the typical case + && ( + // whitelist acceptable props as not all AST_Constants are true constants + self.key instanceof AST_String + || self.key instanceof AST_Number + )) { + self.key = self.key.value; + // fallthrough - `return self` not needed as transformed tree in good form + } // p:function(){} ---> p(){} // p:function*(){} ---> *p(){} // p:async function(){} ---> async p(){} diff --git a/test/compress/object.js b/test/compress/object.js index 5a516511..6e0737df 100644 --- a/test/compress/object.js +++ b/test/compress/object.js @@ -126,6 +126,67 @@ computed_property_names: { expect_exact: 'obj({["x"+"x"]:6});' } +convert_computed_props_to_regular_ones: { + options = { + booleans: true, + computed_props: true, + evaluate: true, + } + input: { + var o = { + ["hi"]: 0, + ["A" + 1]: 1, + [/B/]: 2, + [100 + 23]: 3, + [1 + .5]: 4, + [Math.PI]: 5, + [undefined]: 6, + [true]: 7, + [false]: 8, + [null]: 9, + [Infinity]: 10, + [NaN]: 11, + }; + for (var k in o) { + console.log(k, o[k]); + } + } + expect: { + var o = { + hi: 0, + A1: 1, + [/B/]: 2, + 123: 3, + 1.5: 4, + [Math.PI]: 5, + + // leave these problematic cases as is + [void 0]: 6, + [!0]: 7, + [!1]: 8, + [null]: 9, + [1 / 0]: 10, + [NaN]: 11 + }; + for (var k in o) console.log(k, o[k]); + } + expect_stdout: [ + "123 3", + "hi 0", + "A1 1", + "/B/ 2", + "1.5 4", + "3.141592653589793 5", + "undefined 6", + "true 7", + "false 8", + "null 9", + "Infinity 10", + "NaN 11", + ] + node_version: ">=6" +} + computed_property_names_evaluated_1: { options = { evaluate: true