From 8e4a19ffec0506c25aebb05e2c84ec32ff307642 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Fri, 30 Apr 2021 15:21:15 +0100 Subject: [PATCH] fix corner case in `spreads` (#4883) fixes #4882 --- lib/compress.js | 24 +++++++---- test/compress/spreads.js | 88 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 8 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index 384e0e89c8..ce126c8094 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -11649,13 +11649,23 @@ merge(Compressor.prototype, { found = true; var exp = prop.expression; if (compressor.option("spreads") && exp instanceof AST_Object && all(exp.properties, function(prop) { - return !(prop instanceof AST_ObjectGetter || prop instanceof AST_Spread); + if (prop instanceof AST_ObjectGetter) return false; + if (prop instanceof AST_Spread) return false; + if (prop.key !== "__proto__") return true; + if (prop instanceof AST_ObjectSetter) return true; + return !prop.value.has_side_effects(compressor); })) { changed = true; exp.properties.forEach(function(prop) { - process(prop instanceof AST_ObjectSetter ? make_node(AST_ObjectKeyVal, prop, { - key: prop.key, - value: make_node(AST_Undefined, prop).optimize(compressor) + var key = prop.key; + var setter = prop instanceof AST_ObjectSetter; + if (key === "__proto__") { + if (!setter) return; + key = make_node_from_constant(key, prop); + } + process(setter ? make_node(AST_ObjectKeyVal, prop, { + key: key, + value: make_node(AST_Undefined, prop).optimize(compressor), }) : prop); }); } else { @@ -11695,7 +11705,7 @@ merge(Compressor.prototype, { if (key instanceof AST_Node) { found = true; key = key.evaluate(compressor); - if (key === prop.key) { + if (key === prop.key || key === "__proto__") { generated = true; } else { key = prop.key = "" + key; @@ -11711,9 +11721,7 @@ merge(Compressor.prototype, { if (found && !generated && typeof key == "string" && RE_POSITIVE_INTEGER.test(key)) { generated = true; if (keys.has(key)) prop = keys.get(key)[0]; - prop.key = make_node(AST_Number, prop, { - value: +key - }); + prop.key = make_node(AST_Number, prop, { value: +key }); } } }); diff --git a/test/compress/spreads.js b/test/compress/spreads.js index 4e5d0d987a..6e37bf18b0 100644 --- a/test/compress/spreads.js +++ b/test/compress/spreads.js @@ -1068,3 +1068,91 @@ issue_4849: { expect_stdout: "object" node_version: ">=8" } + +issue_4882_1: { + options = { + objects: true, + spreads: true, + } + input: { + var o = { + p: "PASS", + ... { + __proto__: { + p: "FAIL 1", + q: "FAIL 2", + }, + }, + }; + console.log(o.p); + console.log(o.q); + } + expect: { + var o = { + p: "PASS", + }; + console.log(o.p); + console.log(o.q); + } + expect_stdout: [ + "PASS", + "undefined", + ] + node_version: ">=8" +} + +issue_4882_2: { + options = { + objects: true, + spreads: true, + } + input: { + console.log(null == Object.getPrototypeOf({ + ... { + __proto__: (console.log(42), null), + }, + }) ? "FAIL" : "PASS"); + } + expect: { + console.log(null == Object.getPrototypeOf({ + ... { + __proto__: (console.log(42), null), + }, + }) ? "FAIL" : "PASS"); + } + expect_stdout: [ + "42", + "PASS", + ] + node_version: ">=8" +} + +issue_4882_3: { + options = { + objects: true, + spreads: true, + } + input: { + var o = { + __proto__: { p: 42 }, + ... { + set __proto__(v) {}, + }, + }; + console.log(o.__proto__ === Object.getPrototypeOf(o) ? "FAIL" : "PASS"); + console.log(o.p); + } + expect: { + var o = { + __proto__: { p: 42 }, + ["__proto__"]: void 0, + }; + console.log(o.__proto__ === Object.getPrototypeOf(o) ? "FAIL" : "PASS"); + console.log(o.p); + } + expect_stdout: [ + "PASS", + "42", + ] + node_version: ">=8" +}