diff --git a/lib/coffeescript/nodes.js b/lib/coffeescript/nodes.js index 64af6312..504a5333 100644 --- a/lib/coffeescript/nodes.js +++ b/lib/coffeescript/nodes.js @@ -1267,6 +1267,15 @@ if (!props && base instanceof Value) { return base; } + if (base instanceof Parens && base.contains(function(n) { + return n instanceof StatementLiteral; + })) { + // When `Parens` block includes a `StatementLiteral` (e.g. `(b; break) for a in arr`), + // it won't compile since `Parens` (`(b; break)`) is compiled as `Value` and + // pure statement (`break`) can't be used in an expression. + // For this reasons, we return `Block` instead of `Parens`. + return base.unwrap(); + } this.base = base; this.properties = props || []; if (tag) { diff --git a/src/nodes.coffee b/src/nodes.coffee index 90359a14..8ca12ee9 100644 --- a/src/nodes.coffee +++ b/src/nodes.coffee @@ -863,6 +863,11 @@ exports.Value = class Value extends Base constructor: (base, props, tag, isDefaultValue = no) -> super() return base if not props and base instanceof Value + # When `Parens` block includes a `StatementLiteral` (e.g. `(b; break) for a in arr`), + # it won't compile since `Parens` (`(b; break)`) is compiled as `Value` and + # pure statement (`break`) can't be used in an expression. + # For this reasons, we return `Block` instead of `Parens`. + return base.unwrap() if base instanceof Parens and base.contains (n) -> n instanceof StatementLiteral @base = base @properties = props or [] @[tag] = yes if tag diff --git a/test/control_flow.coffee b/test/control_flow.coffee index 9b5e3b03..22837e8c 100644 --- a/test/control_flow.coffee +++ b/test/control_flow.coffee @@ -484,3 +484,34 @@ test "#4267: lots of for-loops in the same scope", -> true """ ok CoffeeScript.eval(code) + +# Issue #3441: Parentheses wrapping expression throw invalid error in `then` clause +test "#3441: `StatementLiteral` in parentheses", -> + i = 0 + r1 = ((i++; break) while i < 10) + arrayEq r1, [] + + i = 0 + r2 = ((i++; continue) while i < 10) + arrayEq r2, [] + + i = 0 + r4 = while i < 10 then (i++; break) + arrayEq r4, [] + + i = 0 + r5 = while i < 10 then (i++; continue) + arrayEq r5, [] + + arr = [0..9] + r6 = ((a; break) for a in arr) + arrayEq r6, [] + + r7 = ((a; continue) for a in arr) + arrayEq r7, [] + + r8 = for a in arr then (a; break) + arrayEq r8, [] + + r9 = for a in arr then (a; continue) + arrayEq r9, []