diff --git a/lib/compress.js b/lib/compress.js index b06186ee..b5c67c2d 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -12560,7 +12560,8 @@ Compressor.prototype.compress = function(node) { var found = false; var generated = false; var keep_duplicate = compressor.has_directive("use strict"); - var keys = new Dictionary(); + var keys = []; + var map = new Dictionary(); var values = []; self.properties.forEach(function(prop) { if (!(prop instanceof AST_Spread)) return process(prop); @@ -12603,19 +12604,27 @@ Compressor.prototype.compress = function(node) { return make_node(AST_Object, self, { properties: values }); function flush() { - keys.each(function(props) { - if (props.length == 1) return values.push(props[0]); + keys.forEach(function(key) { + var props = map.get(key); + switch (props.length) { + case 0: + return; + case 1: + return values.push(props[0]); + } changed = true; var tail = keep_duplicate && !generated && props.pop(); values.push(props.length == 1 ? props[0] : make_node(AST_ObjectKeyVal, self, { key: props[0].key, value: make_sequence(self, props.map(function(prop) { return prop.value; - })) + })), })); if (tail) values.push(tail); + props.length = 0; }); - keys = new Dictionary(); + keys = []; + map = new Dictionary(); } function process(prop) { @@ -12631,14 +12640,15 @@ Compressor.prototype.compress = function(node) { } if (can_hoist_property(prop)) { if (prop.value.has_side_effects(compressor)) flush(); - keys.add(key, prop); + keys.push(key); + map.add(key, prop); } else { flush(); values.push(prop); } if (found && !generated && typeof key == "string" && RE_POSITIVE_INTEGER.test(key)) { generated = true; - if (keys.has(key)) prop = keys.get(key)[0]; + if (map.has(key)) prop = map.get(key)[0]; prop.key = make_node(AST_Number, prop, { value: +key }); } } diff --git a/test/compress/objects.js b/test/compress/objects.js index beec4bfd..3e110fe0 100644 --- a/test/compress/objects.js +++ b/test/compress/objects.js @@ -198,9 +198,9 @@ numeric_literal: { expect_exact: [ 'var obj = {', ' 0: 0,', - ' 37: 4,', - ' 42: 3,', ' "-0": 1,', + ' 42: 3,', + ' 37: 4,', ' o: 5,', ' 1e42: 8,', ' b: 7', @@ -521,3 +521,25 @@ issue_4415: { expect_stdout: "PASS" node_version: ">=4" } + +issue_5213: { + options = { + objects: true, + } + input: { + var a = "FAIL"; + console.log({ + p: a = "PASS", + 0: a, + p: null, + }[0]); + } + expect: { + var a = "FAIL"; + console.log({ + p: (a = "PASS", null), + 0: a, + }[0]); + } + expect_stdout: "PASS" +} diff --git a/test/sandbox.js b/test/sandbox.js index 8ebbaab7..bc02114f 100644 --- a/test/sandbox.js +++ b/test/sandbox.js @@ -252,7 +252,7 @@ function run_code_vm(code, toplevel, timeout) { var ctx = vm.createContext({ console: console }); // for Node.js v6 vm.runInContext(setup_code, ctx); - vm.runInContext(toplevel ? "(function(){" + code + "})();" : code, ctx, { timeout: timeout }); + vm.runInContext(toplevel ? "(function(){\n" + code + "\n})();" : code, ctx, { timeout: timeout }); // for Node.js v4 return strip_color_codes(stdout.replace(/\b(Array \[|Object {)/g, function(match) { return match.slice(-1); @@ -266,7 +266,7 @@ function run_code_vm(code, toplevel, timeout) { function run_code_exec(code, toplevel, timeout) { if (toplevel) { - code = setup_code + "(function(){" + code + "})();"; + code = setup_code + "(function(){\n" + code + "\n})();"; } else { code = code.replace(/^((["'])[^"']*\2(;|$))?/, function(directive) { return directive + setup_code;