mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-05-03 03:00:14 -04:00
* Fix #5046: Adjacent JSX * check CSX only when wrapped in parentheses * Fix indentation * Add test for unlikely, but valid, JSX syntax
This commit is contained in:
@@ -671,23 +671,29 @@
|
||||
// A Block node does not return its entire body, rather it
|
||||
// ensures that the final expression is returned.
|
||||
makeReturn(res) {
|
||||
var csxCheckIndex, expr, j, len, ref1;
|
||||
var expr, expressions, last, lastExp, len, penult, ref1;
|
||||
len = this.expressions.length;
|
||||
ref1 = this.expressions, [lastExp] = slice1.call(ref1, -1);
|
||||
lastExp = (lastExp != null ? lastExp.unwrap() : void 0) || false;
|
||||
// We also need to check that we’re not returning a CSX tag if there’s an
|
||||
// adjacent one at the same level; JSX doesn’t allow that.
|
||||
if (lastExp && lastExp instanceof Parens && lastExp.body.expressions.length > 1) {
|
||||
({
|
||||
body: {expressions}
|
||||
} = lastExp);
|
||||
[penult, last] = slice1.call(expressions, -2);
|
||||
penult = penult.unwrap();
|
||||
last = last.unwrap();
|
||||
if (penult instanceof Call && penult.csx && last instanceof Call && last.csx) {
|
||||
expressions[expressions.length - 1].error('Adjacent JSX elements must be wrapped in an enclosing tag');
|
||||
}
|
||||
}
|
||||
while (len--) {
|
||||
expr = this.expressions[len];
|
||||
this.expressions[len] = expr.makeReturn(res);
|
||||
if (expr instanceof Return && !expr.expression) {
|
||||
this.expressions.splice(len, 1);
|
||||
}
|
||||
// We also need to check that we’re not returning a CSX tag if there’s an
|
||||
// adjacent one at the same level; JSX doesn’t allow that.
|
||||
if (expr.unwrapAll().csx) {
|
||||
for (csxCheckIndex = j = ref1 = len; (ref1 <= 0 ? j <= 0 : j >= 0); csxCheckIndex = ref1 <= 0 ? ++j : --j) {
|
||||
if (this.expressions[csxCheckIndex].unwrapAll().csx) {
|
||||
expr.error('Adjacent JSX elements must be wrapped in an enclosing tag');
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return this;
|
||||
|
||||
@@ -478,16 +478,21 @@ exports.Block = class Block extends Base
|
||||
# ensures that the final expression is returned.
|
||||
makeReturn: (res) ->
|
||||
len = @expressions.length
|
||||
[..., lastExp] = @expressions
|
||||
lastExp = lastExp?.unwrap() or no
|
||||
# We also need to check that we’re not returning a CSX tag if there’s an
|
||||
# adjacent one at the same level; JSX doesn’t allow that.
|
||||
if lastExp and lastExp instanceof Parens and lastExp.body.expressions.length > 1
|
||||
{body:{expressions}} = lastExp
|
||||
[..., penult, last] = expressions
|
||||
penult = penult.unwrap()
|
||||
last = last.unwrap()
|
||||
if penult instanceof Call and penult.csx and last instanceof Call and last.csx
|
||||
expressions[expressions.length - 1].error 'Adjacent JSX elements must be wrapped in an enclosing tag'
|
||||
while len--
|
||||
expr = @expressions[len]
|
||||
@expressions[len] = expr.makeReturn res
|
||||
@expressions.splice(len, 1) if expr instanceof Return and not expr.expression
|
||||
# We also need to check that we’re not returning a CSX tag if there’s an
|
||||
# adjacent one at the same level; JSX doesn’t allow that.
|
||||
if expr.unwrapAll().csx
|
||||
for csxCheckIndex in [len..0]
|
||||
if @expressions[csxCheckIndex].unwrapAll().csx
|
||||
expr.error 'Adjacent JSX elements must be wrapped in an enclosing tag'
|
||||
break
|
||||
this
|
||||
|
||||
|
||||
@@ -771,11 +771,11 @@ test 'JSX fragments: fragment with text nodes', ->
|
||||
|
||||
test 'JSX fragments: fragment with component nodes', ->
|
||||
eqJS '''
|
||||
Component = (props) =>
|
||||
<Fragment>
|
||||
<OtherComponent />
|
||||
<OtherComponent />
|
||||
</Fragment>
|
||||
Component = (props) =>
|
||||
<Fragment>
|
||||
<OtherComponent />
|
||||
<OtherComponent />
|
||||
</Fragment>
|
||||
''', '''
|
||||
var Component;
|
||||
|
||||
@@ -821,3 +821,20 @@ test '#5055: JSX expression indentation bug', ->
|
||||
{typeof a !== "undefined" && a !== null ? a : <span />}
|
||||
</div>;
|
||||
'''
|
||||
|
||||
# JSX is like XML, in that there needs to be a root element; but
|
||||
# technically, adjacent top-level elements where only the last one
|
||||
# is returned (as opposed to a fragment or root element) is permissible
|
||||
# syntax. It’s almost certainly an error, but it’s valid, so need to leave it
|
||||
# to linters to catch. https://github.com/jashkenas/coffeescript/pull/5049
|
||||
test '“Adjacent” tags on separate lines should still compile', ->
|
||||
eqJS '''
|
||||
->
|
||||
<a />
|
||||
<b />
|
||||
''', '''
|
||||
(function() {
|
||||
<a />;
|
||||
return <b />;
|
||||
});
|
||||
'''
|
||||
|
||||
@@ -1663,15 +1663,6 @@ test 'CSX error: invalid attributes', ->
|
||||
'''
|
||||
|
||||
test '#5034: CSX error: Adjacent JSX elements must be wrapped in an enclosing tag', ->
|
||||
assertErrorFormat '''
|
||||
render = ->
|
||||
<Row>a</Row>
|
||||
<Row>b</Row>
|
||||
''', '''
|
||||
[stdin]:3:4: error: Adjacent JSX elements must be wrapped in an enclosing tag
|
||||
<Row>b</Row>
|
||||
^^^^^^^^^^^
|
||||
'''
|
||||
assertErrorFormat '''
|
||||
render = -> (
|
||||
<Row>a</Row>
|
||||
@@ -1682,7 +1673,17 @@ test '#5034: CSX error: Adjacent JSX elements must be wrapped in an enclosing ta
|
||||
<Row>b</Row>
|
||||
^^^^^^^^^^^
|
||||
'''
|
||||
|
||||
assertErrorFormat '''
|
||||
render = -> (
|
||||
a = "foo"
|
||||
<Row>a</Row>
|
||||
<Row>b</Row>
|
||||
)
|
||||
''', '''
|
||||
[stdin]:4:4: error: Adjacent JSX elements must be wrapped in an enclosing tag
|
||||
<Row>b</Row>
|
||||
^^^^^^^^^^^
|
||||
'''
|
||||
test 'Bound method called as callback before binding throws runtime error', ->
|
||||
class Base
|
||||
constructor: ->
|
||||
|
||||
Reference in New Issue
Block a user