diff --git a/lib/compress.js b/lib/compress.js index d58b68bcef..815797caf4 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -7671,12 +7671,21 @@ merge(Compressor.prototype, { return expressions === this.expressions ? this : make_sequence(this, expressions); }); def(AST_Sub, function(compressor, first_in_statement) { - if (this.expression.may_throw_on_access(compressor)) return this; - var expression = this.expression.drop_side_effect_free(compressor, first_in_statement); - if (!expression) return this.property.drop_side_effect_free(compressor, first_in_statement); - var property = this.property.drop_side_effect_free(compressor); - if (!property) return expression; - return make_sequence(this, [ expression, property ]); + var expr = this.expression; + var prop = this.property; + if (expr.may_throw_on_access(compressor)) { + if (!this.optional) return this; + prop = prop.drop_side_effect_free(compressor); + if (!prop) return expr.drop_side_effect_free(compressor, first_in_statement); + var node = this.clone(); + node.property = prop; + return node; + } + expr = expr.drop_side_effect_free(compressor, first_in_statement); + if (!expr) return prop.drop_side_effect_free(compressor, first_in_statement); + prop = prop.drop_side_effect_free(compressor); + if (!prop) return expr; + return make_sequence(this, [ expr, prop ]); }); def(AST_SymbolRef, function(compressor) { return this.is_declared(compressor) && can_drop_symbol(this, compressor) ? null : this; diff --git a/test/compress/optional-chains.js b/test/compress/optional-chains.js index f55136ec14..fbee6743ec 100644 --- a/test/compress/optional-chains.js +++ b/test/compress/optional-chains.js @@ -194,3 +194,20 @@ trim_2: { expect_stdout: "PASS" node_version: ">=14" } + +issue_4906: { + options = { + toplevel: true, + unused: true, + } + input: { + do { + var a = a?.[42]; + } while (console.log("PASS")); + } + expect: { + do {} while (console.log("PASS")); + } + expect_stdout: "PASS" + node_version: ">=14" +}