diff --git a/lib/coffee-script/nodes.js b/lib/coffee-script/nodes.js index 2d2b84bc..6d4a3496 100644 --- a/lib/coffee-script/nodes.js +++ b/lib/coffee-script/nodes.js @@ -2258,10 +2258,14 @@ Op.prototype.compileUnary = function(o) { var op, parts, plusMinus; + parts = [op = this.operator]; + if (op === '!' && this.first instanceof Existence) { + this.first.negated = !this.first.negated; + return this.first.compile(o); + } if (o.level >= LEVEL_ACCESS) { return (new Parens(this)).compile(o); } - parts = [op = this.operator]; plusMinus = op === '+' || op === '-'; if ((op === 'new' || op === 'typeof' || op === 'delete') || plusMinus && this.first instanceof Op && this.first.operator === op) { parts.push(' '); diff --git a/src/nodes.coffee b/src/nodes.coffee index d1dd3294..49f114e5 100644 --- a/src/nodes.coffee +++ b/src/nodes.coffee @@ -1530,9 +1530,12 @@ exports.Op = class Op extends Base # Compile a unary **Op**. compileUnary: (o) -> + parts = [op = @operator] + if op is '!' and @first instanceof Existence + @first.negated = not @first.negated + return @first.compile o if o.level >= LEVEL_ACCESS return (new Parens this).compile o - parts = [op = @operator] plusMinus = op in ['+', '-'] parts.push ' ' if op in ['new', 'typeof', 'delete'] or plusMinus and @first instanceof Op and @first.operator is op diff --git a/test/operators.coffee b/test/operators.coffee index f6cc1036..98c460d8 100644 --- a/test/operators.coffee +++ b/test/operators.coffee @@ -281,4 +281,10 @@ test "#2197: Existential existential double trouble", -> func = -> counter++ func()? ? 100 eq counter, 1 + +test "#2567: Optimization of negated existential produces correct result", -> + a = 1 + ok !(!a?) + ok !b? + \ No newline at end of file