[CS2] CSX spread attributes: <div {props…} /> (#4607)

* CSX spread attributes: <div {props...} />

* whitespace cleanup

* Style

* valid CSX attributes

* added comments; cleanup

* Fixed allowed CSX properties.

* Cleanup

* Typo

* Improved RegEx

* Reworked CSX attributes

* small fix for CSX attribute validation

* cleanup

* tests

* fix nested assignement; remove unused variable

* cleanup; improve tests

* fix esoteric case; improve tracking nested splats in CSX tag
This commit is contained in:
zdenko
2017-08-03 06:00:39 +02:00
committed by Geoffrey Booth
parent a118ec7cc9
commit cbf035fca9
7 changed files with 351 additions and 420 deletions

View File

@@ -52,6 +52,7 @@
this.importSpecifierList = false; // Used to identify when in an `IMPORT {...} FROM? ...`.
this.exportSpecifierList = false; // Used to identify when in an `EXPORT {...} FROM? ...`.
this.csxDepth = 0; // Used to optimize CSX checks, how deep in CSX we are.
this.csxObjAttribute = {}; // Used to detect if CSX attributes is wrapped in {} (<div {props...} />).
this.chunkLine = opts.line || 0; // The start line for the current @chunk.
this.chunkColumn = opts.column || 0; // The start column of the current @chunk.
code = this.clean(code); // The stripped, cleaned original source code.
@@ -730,8 +731,10 @@
// CSX is like JSX but for CoffeeScript.
csxToken() {
var afterTag, colon, csxTag, end, firstChar, id, input, match, origin, prev, ref, token, tokens;
var afterTag, colon, csxTag, end, firstChar, id, input, match, origin, prev, prevChar, ref, token, tokens;
firstChar = this.chunk[0];
// Check the previous token to detect if attribute is spread.
prevChar = this.tokens.length > 0 ? this.tokens[this.tokens.length - 1][0] : '';
if (firstChar === '<') {
match = CSX_IDENTIFIER.exec(this.chunk.slice(1));
// Not the right hand side of an unspaced comparison (i.e. `a<b`).
@@ -741,7 +744,7 @@
[input, id, colon] = match;
origin = this.token('CSX_TAG', id, 1, id.length);
this.token('CALL_START', '(');
this.token('{', '{');
this.token('[', '[');
this.ends.push({
tag: '/>',
origin: origin,
@@ -752,12 +755,18 @@
} else if (csxTag = this.atCSXTag()) {
if (this.chunk.slice(0, 2) === '/>') {
this.pair('/>');
this.token('}', '}', 0, 2);
this.token(']', ']', 0, 2);
this.token('CALL_END', ')', 0, 2);
this.csxDepth--;
return 2;
} else if (firstChar === '{') {
token = this.token('(', '(');
if (prevChar === ':') {
token = this.token('(', '(');
this.csxObjAttribute[this.csxDepth] = false;
} else {
token = this.token('{', '{');
this.csxObjAttribute[this.csxDepth] = true;
}
this.ends.push({
tag: '}',
origin: token
@@ -766,7 +775,7 @@
} else if (firstChar === '>') {
// Ignore terminators inside a tag.
this.pair('/>'); // As if the current tag was self-closing.
origin = this.token('}', '}');
origin = this.token(']', ']');
this.token(',', ',');
({
tokens,
@@ -800,7 +809,12 @@
} else if (this.atCSXTag(1)) {
if (firstChar === '}') {
this.pair(firstChar);
this.token(')', ')');
if (this.csxObjAttribute[this.csxDepth]) {
this.token('}', '}');
this.csxObjAttribute[this.csxDepth] = false;
} else {
this.token(')', ')');
}
this.token(',', ',');
return 1;
} else {

View File

@@ -1670,7 +1670,7 @@
}
compileCSX(o) {
var attributes, content, fragments, tag;
var attr, attrProps, attributes, content, fragments, j, len1, obj, ref1, tag;
[attributes, content] = this.args;
attributes.base.csx = true;
if (content != null) {
@@ -1678,7 +1678,23 @@
}
fragments = [this.makeCode('<')];
fragments.push(...(tag = this.variable.compileToFragments(o, LEVEL_ACCESS)));
fragments.push(...attributes.compileToFragments(o, LEVEL_PAREN));
if (attributes.base instanceof Arr) {
ref1 = attributes.base.objects;
for (j = 0, len1 = ref1.length; j < len1; j++) {
obj = ref1[j];
attr = obj.base;
attrProps = (attr != null ? attr.properties : void 0) || [];
// Catch invalid CSX attributes: <div {a:"b", props} {props} "value" />
if (!(attr instanceof Obj || attr instanceof IdentifierLiteral) || (attr instanceof Obj && !attr.generated && (attrProps.length > 1 || !(attrProps[0] instanceof Splat)))) {
obj.error("Unexpected token. Allowed CSX attributes are: id=\"val\", src={source}, {props...} or attribute.");
}
if (obj.base instanceof Obj) {
obj.base.csx = true;
}
fragments.push(this.makeCode(' '));
fragments.push(...obj.compileToFragments(o, LEVEL_PAREN));
}
}
if (content) {
fragments.push(this.makeCode('>'));
fragments.push(...content.compileNode(o, LEVEL_LIST));
@@ -2109,12 +2125,16 @@
}
}
}
if (this.hasSplat()) {
if (this.hasSplat() && !this.csx) {
// Object spread properties. https://github.com/tc39/proposal-object-rest-spread/blob/master/Spread.md
return this.compileSpread(o);
}
idt = o.indent += TAB;
lastNode = this.lastNode(this.properties);
if (this.csx) {
// CSX attributes <div id="val" attr={aaa} {props...} />
return this.compileCSXAttributes(o);
}
// If this object is the left-hand side of an assignment, all its children
// are too.
if (this.lhs) {
@@ -2136,7 +2156,7 @@
ref1 = this.properties;
for (l = 0, len3 = ref1.length; l < len3; l++) {
prop = ref1[l];
if (prop instanceof Assign && prop.context === 'object' && !this.csx) {
if (prop instanceof Assign && prop.context === 'object') {
isCompact = false;
}
}
@@ -2144,7 +2164,7 @@
answer.push(this.makeCode(isCompact ? '' : '\n'));
for (i = q = 0, len4 = props.length; q < len4; i = ++q) {
prop = props[i];
join = i === props.length - 1 ? '' : isCompact && this.csx ? ' ' : isCompact ? ', ' : prop === lastNode || this.csx ? '\n' : ',\n';
join = i === props.length - 1 ? '' : isCompact ? ', ' : prop === lastNode ? '\n' : ',\n';
indent = isCompact ? '' : idt;
key = prop instanceof Assign && prop.context === 'object' ? prop.variable : prop instanceof Assign ? (!this.lhs ? prop.operatorToken.error(`unexpected ${prop.operatorToken.value}`) : void 0, prop.variable) : prop;
if (key instanceof Value && key.hasProperties()) {
@@ -2168,21 +2188,13 @@
if (indent) {
answer.push(this.makeCode(indent));
}
if (this.csx) {
prop.csx = true;
}
if (this.csx && i === 0) {
answer.push(this.makeCode(' '));
}
answer.push(...prop.compileToFragments(o, LEVEL_TOP));
if (join) {
answer.push(this.makeCode(join));
}
}
answer.push(this.makeCode(isCompact ? '' : `\n${this.tab}`));
if (!this.csx) {
answer = this.wrapInBraces(answer);
}
answer = this.wrapInBraces(answer);
if (this.front) {
return this.wrapInParentheses(answer);
} else {
@@ -2256,6 +2268,27 @@
return (new Call(new Literal('Object.assign'), slices)).compileToFragments(o);
}
compileCSXAttributes(o) {
var answer, i, j, join, len1, prop, props;
props = this.properties;
answer = [];
for (i = j = 0, len1 = props.length; j < len1; i = ++j) {
prop = props[i];
prop.csx = true;
join = i === props.length - 1 ? '' : ' ';
if (prop instanceof Splat) {
prop = new Literal(`{${prop.compile(o)}}`);
}
answer.push(...prop.compileToFragments(o, LEVEL_TOP));
answer.push(this.makeCode(join));
}
if (this.front) {
return this.wrapInParentheses(answer);
} else {
return answer;
}
}
};
Obj.prototype.children = ['properties'];

View File

@@ -105,16 +105,13 @@ case 12:
this.$ = yy.addDataToNode(yy, _$[$0], _$[$0])(new yy.StatementLiteral($$[$0]));
break;
case 27:
this.$ = yy.addDataToNode(yy, _$[$0], _$[$0])(new yy.Op($$[$0],
new yy.Value(new yy.Literal(''))));
this.$ = yy.addDataToNode(yy, _$[$0], _$[$0])(new yy.Op($$[$0], new yy.Value(new yy.Literal(''))));
break;
case 28: case 271: case 272: case 275:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Op($$[$0-1],
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Op($$[$0-1], $$[$0]));
break;
case 29:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Op($$[$0-2].concat($$[$0-1]),
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Op($$[$0-2].concat($$[$0-1]), $$[$0]));
break;
case 30:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Block);
@@ -165,49 +162,34 @@ case 48:
this.$ = yy.addDataToNode(yy, _$[$0], _$[$0])(new yy.NaNLiteral($$[$0]));
break;
case 49:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Assign($$[$0-2],
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Assign($$[$0-2], $$[$0]));
break;
case 50:
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.Assign($$[$0-3],
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.Assign($$[$0-3], $$[$0]));
break;
case 51:
this.$ = yy.addDataToNode(yy, _$[$0-4], _$[$0])(new yy.Assign($$[$0-4],
$$[$0-1]));
this.$ = yy.addDataToNode(yy, _$[$0-4], _$[$0])(new yy.Assign($$[$0-4], $$[$0-1]));
break;
case 52: case 108: case 112: case 113: case 115: case 116: case 117: case 118: case 120: case 244: case 245:
this.$ = yy.addDataToNode(yy, _$[$0], _$[$0])(new yy.Value($$[$0]));
break;
case 54:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Assign(yy.addDataToNode(yy, _$[$0-2])(new yy.Value($$[$0-2])),
$$[$0],
'object',
{
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Assign(yy.addDataToNode(yy, _$[$0-2])(new yy.Value($$[$0-2])), $$[$0], 'object', {
operatorToken: yy.addDataToNode(yy, _$[$0-1])(new yy.Literal($$[$0-1]))
}));
break;
case 55:
this.$ = yy.addDataToNode(yy, _$[$0-4], _$[$0])(new yy.Assign(yy.addDataToNode(yy, _$[$0-4])(new yy.Value($$[$0-4])),
$$[$0-1],
'object',
{
this.$ = yy.addDataToNode(yy, _$[$0-4], _$[$0])(new yy.Assign(yy.addDataToNode(yy, _$[$0-4])(new yy.Value($$[$0-4])), $$[$0-1], 'object', {
operatorToken: yy.addDataToNode(yy, _$[$0-3])(new yy.Literal($$[$0-3]))
}));
break;
case 56:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Assign(yy.addDataToNode(yy, _$[$0-2])(new yy.Value($$[$0-2])),
$$[$0],
null,
{
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Assign(yy.addDataToNode(yy, _$[$0-2])(new yy.Value($$[$0-2])), $$[$0], null, {
operatorToken: yy.addDataToNode(yy, _$[$0-1])(new yy.Literal($$[$0-1]))
}));
break;
case 57:
this.$ = yy.addDataToNode(yy, _$[$0-4], _$[$0])(new yy.Assign(yy.addDataToNode(yy, _$[$0-4])(new yy.Value($$[$0-4])),
$$[$0-1],
null,
{
this.$ = yy.addDataToNode(yy, _$[$0-4], _$[$0])(new yy.Assign(yy.addDataToNode(yy, _$[$0-4])(new yy.Value($$[$0-4])), $$[$0-1], null, {
operatorToken: yy.addDataToNode(yy, _$[$0-3])(new yy.Literal($$[$0-3]))
}));
break;
@@ -224,18 +206,13 @@ case 66: case 107:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Splat($$[$0]));
break;
case 72:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.SuperCall(yy.addDataToNode(yy, _$[$0-1])(new yy.Super),
$$[$0],
false,
$$[$0-1]));
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.SuperCall(yy.addDataToNode(yy, _$[$0-1])(new yy.Super), $$[$0], false, $$[$0-1]));
break;
case 73:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Call(new yy.Value($$[$0-1]),
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Call(new yy.Value($$[$0-1]), $$[$0]));
break;
case 74:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Call($$[$0-1],
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Call($$[$0-1], $$[$0]));
break;
case 75: case 76:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])((new yy.Value($$[$0-1])).add($$[$0]));
@@ -265,14 +242,10 @@ case 85:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.AwaitReturn);
break;
case 86:
this.$ = yy.addDataToNode(yy, _$[$0-4], _$[$0])(new yy.Code($$[$0-3],
$$[$0],
$$[$0-1]));
this.$ = yy.addDataToNode(yy, _$[$0-4], _$[$0])(new yy.Code($$[$0-3], $$[$0], $$[$0-1]));
break;
case 87:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Code([],
$$[$0],
$$[$0-1]));
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Code([], $$[$0], $$[$0-1]));
break;
case 88: case 89:
this.$ = yy.addDataToNode(yy, _$[$0], _$[$0])(new yy.FuncGlyph($$[$0]));
@@ -296,18 +269,13 @@ case 97:
this.$ = yy.addDataToNode(yy, _$[$0], _$[$0])(new yy.Param($$[$0]));
break;
case 98:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Param($$[$0-1],
null,
true));
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Param($$[$0-1], null, true));
break;
case 99:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Param($$[$0],
null,
true));
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Param($$[$0], null, true));
break;
case 100:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Param($$[$0-2],
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Param($$[$0-2], $$[$0]));
break;
case 101: case 210:
this.$ = yy.addDataToNode(yy, _$[$0], _$[$0])(new yy.Expansion);
@@ -316,36 +284,25 @@ case 109:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])($$[$0-1].add($$[$0]));
break;
case 121:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Super(yy.addDataToNode(yy, _$[$0])(new yy.Access($$[$0])),
[],
false,
$$[$0-2]));
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Super(yy.addDataToNode(yy, _$[$0])(new yy.Access($$[$0])), [], false, $$[$0-2]));
break;
case 122:
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.Super(yy.addDataToNode(yy, _$[$0-1])(new yy.Index($$[$0-1])),
[],
false,
$$[$0-3]));
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.Super(yy.addDataToNode(yy, _$[$0-1])(new yy.Index($$[$0-1])), [], false, $$[$0-3]));
break;
case 124:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Access($$[$0],
'soak'));
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Access($$[$0], 'soak'));
break;
case 125:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])([yy.addDataToNode(yy, _$[$0-1])(new yy.Access(new yy.PropertyName('prototype'))),
yy.addDataToNode(yy, _$[$0])(new yy.Access($$[$0]))]);
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])([yy.addDataToNode(yy, _$[$0-1])(new yy.Access(new yy.PropertyName('prototype'))), yy.addDataToNode(yy, _$[$0])(new yy.Access($$[$0]))]);
break;
case 126:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])([yy.addDataToNode(yy, _$[$0-1])(new yy.Access(new yy.PropertyName('prototype'),
'soak')),
yy.addDataToNode(yy, _$[$0])(new yy.Access($$[$0]))]);
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])([yy.addDataToNode(yy, _$[$0-1])(new yy.Access(new yy.PropertyName('prototype'), 'soak')), yy.addDataToNode(yy, _$[$0])(new yy.Access($$[$0]))]);
break;
case 127:
this.$ = yy.addDataToNode(yy, _$[$0], _$[$0])(new yy.Access(new yy.PropertyName('prototype')));
break;
case 130:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(yy.extend($$[$0],
{
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(yy.extend($$[$0], {
soak: true
}));
break;
@@ -356,76 +313,52 @@ case 132:
this.$ = yy.addDataToNode(yy, _$[$0], _$[$0])(new yy.Slice($$[$0]));
break;
case 133:
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.Obj($$[$0-2],
$$[$0-3].generated));
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.Obj($$[$0-2], $$[$0-3].generated));
break;
case 139:
this.$ = yy.addDataToNode(yy, _$[$0], _$[$0])(new yy.Class);
break;
case 140:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Class(null,
null,
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Class(null, null, $$[$0]));
break;
case 141:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Class(null,
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Class(null, $$[$0]));
break;
case 142:
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.Class(null,
$$[$0-1],
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.Class(null, $$[$0-1], $$[$0]));
break;
case 143:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Class($$[$0]));
break;
case 144:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Class($$[$0-1],
null,
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Class($$[$0-1], null, $$[$0]));
break;
case 145:
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.Class($$[$0-2],
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.Class($$[$0-2], $$[$0]));
break;
case 146:
this.$ = yy.addDataToNode(yy, _$[$0-4], _$[$0])(new yy.Class($$[$0-3],
$$[$0-1],
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-4], _$[$0])(new yy.Class($$[$0-3], $$[$0-1], $$[$0]));
break;
case 147:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.ImportDeclaration(null,
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.ImportDeclaration(null, $$[$0]));
break;
case 148:
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.ImportDeclaration(new yy.ImportClause($$[$0-2],
null),
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.ImportDeclaration(new yy.ImportClause($$[$0-2], null), $$[$0]));
break;
case 149:
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.ImportDeclaration(new yy.ImportClause(null,
$$[$0-2]),
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.ImportDeclaration(new yy.ImportClause(null, $$[$0-2]), $$[$0]));
break;
case 150:
this.$ = yy.addDataToNode(yy, _$[$0-4], _$[$0])(new yy.ImportDeclaration(new yy.ImportClause(null,
new yy.ImportSpecifierList([])),
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-4], _$[$0])(new yy.ImportDeclaration(new yy.ImportClause(null, new yy.ImportSpecifierList([])), $$[$0]));
break;
case 151:
this.$ = yy.addDataToNode(yy, _$[$0-6], _$[$0])(new yy.ImportDeclaration(new yy.ImportClause(null,
new yy.ImportSpecifierList($$[$0-4])),
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-6], _$[$0])(new yy.ImportDeclaration(new yy.ImportClause(null, new yy.ImportSpecifierList($$[$0-4])), $$[$0]));
break;
case 152:
this.$ = yy.addDataToNode(yy, _$[$0-5], _$[$0])(new yy.ImportDeclaration(new yy.ImportClause($$[$0-4],
$$[$0-2]),
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-5], _$[$0])(new yy.ImportDeclaration(new yy.ImportClause($$[$0-4], $$[$0-2]), $$[$0]));
break;
case 153:
this.$ = yy.addDataToNode(yy, _$[$0-8], _$[$0])(new yy.ImportDeclaration(new yy.ImportClause($$[$0-7],
new yy.ImportSpecifierList($$[$0-4])),
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-8], _$[$0])(new yy.ImportDeclaration(new yy.ImportClause($$[$0-7], new yy.ImportSpecifierList($$[$0-4])), $$[$0]));
break;
case 157: case 177: case 190: case 206:
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])($$[$0-2]);
@@ -434,22 +367,19 @@ case 159:
this.$ = yy.addDataToNode(yy, _$[$0], _$[$0])(new yy.ImportSpecifier($$[$0]));
break;
case 160:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.ImportSpecifier($$[$0-2],
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.ImportSpecifier($$[$0-2], $$[$0]));
break;
case 161:
this.$ = yy.addDataToNode(yy, _$[$0], _$[$0])(new yy.ImportSpecifier(new yy.Literal($$[$0])));
break;
case 162:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.ImportSpecifier(new yy.Literal($$[$0-2]),
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.ImportSpecifier(new yy.Literal($$[$0-2]), $$[$0]));
break;
case 163:
this.$ = yy.addDataToNode(yy, _$[$0], _$[$0])(new yy.ImportDefaultSpecifier($$[$0]));
break;
case 164:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.ImportNamespaceSpecifier(new yy.Literal($$[$0-2]),
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.ImportNamespaceSpecifier(new yy.Literal($$[$0-2]), $$[$0]));
break;
case 165:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.ExportNamedDeclaration(new yy.ExportSpecifierList([])));
@@ -461,26 +391,17 @@ case 167:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.ExportNamedDeclaration($$[$0]));
break;
case 168:
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.ExportNamedDeclaration(new yy.Assign($$[$0-2],
$$[$0],
null,
{
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.ExportNamedDeclaration(new yy.Assign($$[$0-2], $$[$0], null, {
moduleDeclaration: 'export'
})));
break;
case 169:
this.$ = yy.addDataToNode(yy, _$[$0-4], _$[$0])(new yy.ExportNamedDeclaration(new yy.Assign($$[$0-3],
$$[$0],
null,
{
this.$ = yy.addDataToNode(yy, _$[$0-4], _$[$0])(new yy.ExportNamedDeclaration(new yy.Assign($$[$0-3], $$[$0], null, {
moduleDeclaration: 'export'
})));
break;
case 170:
this.$ = yy.addDataToNode(yy, _$[$0-5], _$[$0])(new yy.ExportNamedDeclaration(new yy.Assign($$[$0-4],
$$[$0-1],
null,
{
this.$ = yy.addDataToNode(yy, _$[$0-5], _$[$0])(new yy.ExportNamedDeclaration(new yy.Assign($$[$0-4], $$[$0-1], null, {
moduleDeclaration: 'export'
})));
break;
@@ -488,46 +409,34 @@ case 171:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.ExportDefaultDeclaration($$[$0]));
break;
case 172:
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.ExportAllDeclaration(new yy.Literal($$[$0-2]),
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.ExportAllDeclaration(new yy.Literal($$[$0-2]), $$[$0]));
break;
case 173:
this.$ = yy.addDataToNode(yy, _$[$0-6], _$[$0])(new yy.ExportNamedDeclaration(new yy.ExportSpecifierList($$[$0-4]),
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-6], _$[$0])(new yy.ExportNamedDeclaration(new yy.ExportSpecifierList($$[$0-4]), $$[$0]));
break;
case 179:
this.$ = yy.addDataToNode(yy, _$[$0], _$[$0])(new yy.ExportSpecifier($$[$0]));
break;
case 180:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.ExportSpecifier($$[$0-2],
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.ExportSpecifier($$[$0-2], $$[$0]));
break;
case 181:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.ExportSpecifier($$[$0-2],
new yy.Literal($$[$0])));
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.ExportSpecifier($$[$0-2], new yy.Literal($$[$0])));
break;
case 182:
this.$ = yy.addDataToNode(yy, _$[$0], _$[$0])(new yy.ExportSpecifier(new yy.Literal($$[$0])));
break;
case 183:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.ExportSpecifier(new yy.Literal($$[$0-2]),
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.ExportSpecifier(new yy.Literal($$[$0-2]), $$[$0]));
break;
case 184:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.TaggedTemplateCall($$[$0-2],
$$[$0],
$$[$0-1]));
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.TaggedTemplateCall($$[$0-2], $$[$0], $$[$0-1]));
break;
case 185:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Call($$[$0-2],
$$[$0],
$$[$0-1]));
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Call($$[$0-2], $$[$0], $$[$0-1]));
break;
case 186:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.SuperCall(yy.addDataToNode(yy, _$[$0-2])(new yy.Super),
$$[$0],
$$[$0-1],
$$[$0-2]));
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.SuperCall(yy.addDataToNode(yy, _$[$0-2])(new yy.Super), $$[$0], $$[$0-1], $$[$0-2]));
break;
case 187:
this.$ = yy.addDataToNode(yy, _$[$0], _$[$0])(false);
@@ -542,9 +451,7 @@ case 191: case 192:
this.$ = yy.addDataToNode(yy, _$[$0], _$[$0])(new yy.Value(new yy.ThisLiteral($$[$0])));
break;
case 193:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Value(yy.addDataToNode(yy, _$[$0-1])(new yy.ThisLiteral($$[$0-1])),
[yy.addDataToNode(yy, _$[$0])(new yy.Access($$[$0]))],
'this'));
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Value(yy.addDataToNode(yy, _$[$0-1])(new yy.ThisLiteral($$[$0-1])), [yy.addDataToNode(yy, _$[$0])(new yy.Access($$[$0]))], 'this'));
break;
case 194:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Arr([]));
@@ -559,65 +466,43 @@ case 197:
this.$ = yy.addDataToNode(yy, _$[$0], _$[$0])('exclusive');
break;
case 198:
this.$ = yy.addDataToNode(yy, _$[$0-4], _$[$0])(new yy.Range($$[$0-3],
$$[$0-1],
$$[$0-2]));
this.$ = yy.addDataToNode(yy, _$[$0-4], _$[$0])(new yy.Range($$[$0-3], $$[$0-1], $$[$0-2]));
break;
case 199:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Range($$[$0-2],
$$[$0],
$$[$0-1]));
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Range($$[$0-2], $$[$0], $$[$0-1]));
break;
case 200:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Range($$[$0-1],
null,
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Range($$[$0-1], null, $$[$0]));
break;
case 201:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Range(null,
$$[$0],
$$[$0-1]));
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Range(null, $$[$0], $$[$0-1]));
break;
case 202:
this.$ = yy.addDataToNode(yy, _$[$0], _$[$0])(new yy.Range(null,
null,
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0], _$[$0])(new yy.Range(null, null, $$[$0]));
break;
case 212:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])([].concat($$[$0-2],
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])([].concat($$[$0-2], $$[$0]));
break;
case 213:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Try($$[$0]));
break;
case 214:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Try($$[$0-1],
$$[$0][0],
$$[$0][1]));
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Try($$[$0-1], $$[$0][0], $$[$0][1]));
break;
case 215:
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.Try($$[$0-2],
null,
null,
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.Try($$[$0-2], null, null, $$[$0]));
break;
case 216:
this.$ = yy.addDataToNode(yy, _$[$0-4], _$[$0])(new yy.Try($$[$0-3],
$$[$0-2][0],
$$[$0-2][1],
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-4], _$[$0])(new yy.Try($$[$0-3], $$[$0-2][0], $$[$0-2][1], $$[$0]));
break;
case 217:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])([$$[$0-1],
$$[$0]]);
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])([$$[$0-1], $$[$0]]);
break;
case 218:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])([yy.addDataToNode(yy, _$[$0-1])(new yy.Value($$[$0-1])),
$$[$0]]);
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])([yy.addDataToNode(yy, _$[$0-1])(new yy.Value($$[$0-1])), $$[$0]]);
break;
case 219:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])([null,
$$[$0]]);
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])([null, $$[$0]]);
break;
case 220:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Throw($$[$0]));
@@ -635,20 +520,17 @@ case 224:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.While($$[$0]));
break;
case 225:
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.While($$[$0-2],
{
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.While($$[$0-2], {
guard: $$[$0]
}));
break;
case 226:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.While($$[$0],
{
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.While($$[$0], {
invert: true
}));
break;
case 227:
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.While($$[$0-2],
{
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.While($$[$0-2], {
invert: true,
guard: $$[$0]
}));
@@ -669,12 +551,10 @@ case 233:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.While(yy.addDataToNode(yy, _$[$0-1])(new yy.BooleanLiteral('true'))).addBody(yy.addDataToNode(yy, _$[$0])(yy.Block.wrap([$$[$0]]))));
break;
case 234: case 235:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.For($$[$0-1],
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.For($$[$0-1], $$[$0]));
break;
case 236:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.For($$[$0],
$$[$0-1]));
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.For($$[$0], $$[$0-1]));
break;
case 237:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])({
@@ -707,8 +587,7 @@ this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])((function () {
}()));
break;
case 247:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])([$$[$0-2],
$$[$0]]);
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])([$$[$0-2], $$[$0]]);
break;
case 248:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])({
@@ -768,45 +647,33 @@ this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])({
});
break;
case 257:
this.$ = yy.addDataToNode(yy, _$[$0-4], _$[$0])(new yy.Switch($$[$0-3],
$$[$0-1]));
this.$ = yy.addDataToNode(yy, _$[$0-4], _$[$0])(new yy.Switch($$[$0-3], $$[$0-1]));
break;
case 258:
this.$ = yy.addDataToNode(yy, _$[$0-6], _$[$0])(new yy.Switch($$[$0-5],
$$[$0-3],
$$[$0-1]));
this.$ = yy.addDataToNode(yy, _$[$0-6], _$[$0])(new yy.Switch($$[$0-5], $$[$0-3], $$[$0-1]));
break;
case 259:
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.Switch(null,
$$[$0-1]));
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.Switch(null, $$[$0-1]));
break;
case 260:
this.$ = yy.addDataToNode(yy, _$[$0-5], _$[$0])(new yy.Switch(null,
$$[$0-3],
$$[$0-1]));
this.$ = yy.addDataToNode(yy, _$[$0-5], _$[$0])(new yy.Switch(null, $$[$0-3], $$[$0-1]));
break;
case 262:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])($$[$0-1].concat($$[$0]));
break;
case 263:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])([[$$[$0-1],
$$[$0]]]);
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])([[$$[$0-1], $$[$0]]]);
break;
case 264:
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])([[$$[$0-2],
$$[$0-1]]]);
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])([[$$[$0-2], $$[$0-1]]]);
break;
case 265:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.If($$[$0-1],
$$[$0],
{
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.If($$[$0-1], $$[$0], {
type: $$[$0-2]
}));
break;
case 266:
this.$ = yy.addDataToNode(yy, _$[$0-4], _$[$0])($$[$0-4].addElse(yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.If($$[$0-1],
$$[$0],
{
this.$ = yy.addDataToNode(yy, _$[$0-4], _$[$0])($$[$0-4].addElse(yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.If($$[$0-1], $$[$0], {
type: $$[$0-2]
}))));
break;
@@ -814,86 +681,58 @@ case 268:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])($$[$0-2].addElse($$[$0]));
break;
case 269: case 270:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.If($$[$0],
yy.addDataToNode(yy, _$[$0-2])(yy.Block.wrap([$$[$0-2]])),
{
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.If($$[$0], yy.addDataToNode(yy, _$[$0-2])(yy.Block.wrap([$$[$0-2]])), {
type: $$[$0-1],
statement: true
}));
break;
case 273:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Op('-',
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Op('-', $$[$0]));
break;
case 274:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Op('+',
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Op('+', $$[$0]));
break;
case 276:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Op('--',
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Op('--', $$[$0]));
break;
case 277:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Op('++',
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Op('++', $$[$0]));
break;
case 278:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Op('--',
$$[$0-1],
null,
true));
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Op('--', $$[$0-1], null, true));
break;
case 279:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Op('++',
$$[$0-1],
null,
true));
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Op('++', $$[$0-1], null, true));
break;
case 280:
this.$ = yy.addDataToNode(yy, _$[$0-1], _$[$0])(new yy.Existence($$[$0-1]));
break;
case 281:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Op('+',
$$[$0-2],
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Op('+', $$[$0-2], $$[$0]));
break;
case 282:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Op('-',
$$[$0-2],
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Op('-', $$[$0-2], $$[$0]));
break;
case 283: case 284: case 285: case 286: case 287: case 288: case 289: case 290: case 291: case 292:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Op($$[$0-1],
$$[$0-2],
$$[$0]));
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Op($$[$0-1], $$[$0-2], $$[$0]));
break;
case 293:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])((function () {
if ($$[$0-1].charAt(0) === '!') {
return new yy.Op($$[$0-1].slice(1),
$$[$0-2],
$$[$0]).invert();
return new yy.Op($$[$0-1].slice(1), $$[$0-2], $$[$0]).invert();
} else {
return new yy.Op($$[$0-1],
$$[$0-2],
$$[$0]);
return new yy.Op($$[$0-1], $$[$0-2], $$[$0]);
}
}()));
break;
case 294:
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Assign($$[$0-2],
$$[$0],
$$[$0-1]));
this.$ = yy.addDataToNode(yy, _$[$0-2], _$[$0])(new yy.Assign($$[$0-2], $$[$0], $$[$0-1]));
break;
case 295:
this.$ = yy.addDataToNode(yy, _$[$0-4], _$[$0])(new yy.Assign($$[$0-4],
$$[$0-1],
$$[$0-3]));
this.$ = yy.addDataToNode(yy, _$[$0-4], _$[$0])(new yy.Assign($$[$0-4], $$[$0-1], $$[$0-3]));
break;
case 296:
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.Assign($$[$0-3],
$$[$0],
$$[$0-2]));
this.$ = yy.addDataToNode(yy, _$[$0-3], _$[$0])(new yy.Assign($$[$0-3], $$[$0], $$[$0-2]));
break;
}
},

View File

@@ -49,6 +49,7 @@ exports.Lexer = class Lexer
@importSpecifierList = no # Used to identify when in an `IMPORT {...} FROM? ...`.
@exportSpecifierList = no # Used to identify when in an `EXPORT {...} FROM? ...`.
@csxDepth = 0 # Used to optimize CSX checks, how deep in CSX we are.
@csxObjAttribute = {} # Used to detect if CSX attributes is wrapped in {} (<div {props...} />).
@chunkLine =
opts.line or 0 # The start line for the current @chunk.
@@ -546,6 +547,8 @@ exports.Lexer = class Lexer
# CSX is like JSX but for CoffeeScript.
csxToken: ->
firstChar = @chunk[0]
# Check the previous token to detect if attribute is spread.
prevChar = if @tokens.length > 0 then @tokens[@tokens.length - 1][0] else ''
if firstChar is '<'
match = CSX_IDENTIFIER.exec @chunk[1...]
return 0 unless match and (
@@ -558,25 +561,30 @@ exports.Lexer = class Lexer
[input, id, colon] = match
origin = @token 'CSX_TAG', id, 1, id.length
@token 'CALL_START', '('
@token '{', '{'
@token '[', '['
@ends.push tag: '/>', origin: origin, name: id
@csxDepth++
return id.length + 1
else if csxTag = @atCSXTag()
if @chunk[...2] is '/>'
@pair '/>'
@token '}', '}', 0, 2
@token ']', ']', 0, 2
@token 'CALL_END', ')', 0, 2
@csxDepth--
return 2
else if firstChar is '{'
token = @token '(', '('
if prevChar is ':'
token = @token '(', '('
@csxObjAttribute[@csxDepth] = no
else
token = @token '{', '{'
@csxObjAttribute[@csxDepth] = yes
@ends.push {tag: '}', origin: token}
return 1
else if firstChar is '>'
# Ignore terminators inside a tag.
@pair '/>' # As if the current tag was self-closing.
origin = @token '}', '}'
origin = @token ']', ']'
@token ',', ','
{tokens, index: end} =
@matchWithInterpolations INSIDE_CSX, '>', '</', CSX_INTERPOLATION
@@ -598,7 +606,11 @@ exports.Lexer = class Lexer
else if @atCSXTag 1
if firstChar is '}'
@pair firstChar
@token ')', ')'
if @csxObjAttribute[@csxDepth]
@token '}', '}'
@csxObjAttribute[@csxDepth] = no
else
@token ')', ')'
@token ',', ','
return 1
else

View File

@@ -1122,7 +1122,18 @@ exports.Call = class Call extends Base
content?.base.csx = yes
fragments = [@makeCode('<')]
fragments.push (tag = @variable.compileToFragments(o, LEVEL_ACCESS))...
fragments.push attributes.compileToFragments(o, LEVEL_PAREN)...
if attributes.base instanceof Arr
for obj in attributes.base.objects
attr = obj.base
attrProps = attr?.properties or []
# Catch invalid CSX attributes: <div {a:"b", props} {props} "value" />
if not (attr instanceof Obj or attr instanceof IdentifierLiteral) or (attr instanceof Obj and not attr.generated and (attrProps.length > 1 or not (attrProps[0] instanceof Splat)))
obj.error """
Unexpected token. Allowed CSX attributes are: id="val", src={source}, {props...} or attribute.
"""
obj.base.csx = yes if obj.base instanceof Obj
fragments.push @makeCode ' '
fragments.push obj.compileToFragments(o, LEVEL_PAREN)...
if content
fragments.push @makeCode('>')
fragments.push content.compileNode(o, LEVEL_LIST)...
@@ -1425,11 +1436,14 @@ exports.Obj = class Obj extends Base
node.error 'cannot have an implicit value in an implicit object'
# Object spread properties. https://github.com/tc39/proposal-object-rest-spread/blob/master/Spread.md
return @compileSpread o if @hasSplat()
return @compileSpread o if @hasSplat() and not @csx
idt = o.indent += TAB
lastNode = @lastNode @properties
# CSX attributes <div id="val" attr={aaa} {props...} />
return @compileCSXAttributes o if @csx
# If this object is the left-hand side of an assignment, all its children
# are too.
if @lhs
@@ -1443,7 +1457,7 @@ exports.Obj = class Obj extends Base
isCompact = yes
for prop in @properties
if prop instanceof Assign and prop.context is 'object' and not @csx
if prop instanceof Assign and prop.context is 'object'
isCompact = no
answer = []
@@ -1451,11 +1465,9 @@ exports.Obj = class Obj extends Base
for prop, i in props
join = if i is props.length - 1
''
else if isCompact and @csx
' '
else if isCompact
', '
else if prop is lastNode or @csx
else if prop is lastNode
'\n'
else
',\n'
@@ -1480,12 +1492,10 @@ exports.Obj = class Obj extends Base
else if not prop.bareLiteral?(IdentifierLiteral)
prop = new Assign prop, prop, 'object'
if indent then answer.push @makeCode indent
prop.csx = yes if @csx
answer.push @makeCode ' ' if @csx and i is 0
answer.push prop.compileToFragments(o, LEVEL_TOP)...
if join then answer.push @makeCode join
answer.push @makeCode if isCompact then '' else "\n#{@tab}"
answer = @wrapInBraces answer if not @csx
answer = @wrapInBraces answer
if @front then @wrapInParentheses answer else answer
assigns: (name) ->
@@ -1521,6 +1531,17 @@ exports.Obj = class Obj extends Base
slices.unshift new Obj unless slices[0] instanceof Obj
(new Call new Literal('Object.assign'), slices).compileToFragments o
compileCSXAttributes: (o) ->
props = @properties
answer = []
for prop, i in props
prop.csx = yes
join = if i is props.length - 1 then '' else ' '
prop = new Literal "{#{prop.compile(o)}}" if prop instanceof Splat
answer.push prop.compileToFragments(o, LEVEL_TOP)...
answer.push @makeCode join
if @front then @wrapInParentheses answer else answer
#### Arr
# An array literal.

View File

@@ -483,147 +483,115 @@ test 'self closing tag with namespace', ->
<Something.Tag />;
'''
# TODO: Uncomment the following test once destructured object spreads are supported.
# test 'self closing tag with spread attribute', ->
# eqJS '''
# <Component a={b} {... x } b="c" />
# ''', '''
# React.createElement(Component, Object.assign({"a": (b)}, x , {"b": "c"}))
# '''
test 'self closing tag with spread attribute', ->
eqJS '''
<Component a={b} {x...} b="c" />
''', '''
<Component a={b} {...x} b="c" />;
'''
# TODO: Uncomment the following test once destructured object spreads are supported.
# test 'complex spread attribute', ->
# eqJS '''
# <Component {...x} a={b} {... x } b="c" {...$my_xtraCoolVar123 } />
# ''', '''
# React.createElement(Component, Object.assign({}, x, {"a": (b)}, x , {"b": "c"}, $my_xtraCoolVar123 ))
# '''
test 'complex spread attribute', ->
eqJS '''
<Component {x...} a={b} {x...} b="c" {$my_xtraCoolVar123...} />
''', '''
<Component {...x} a={b} {...x} b="c" {...$my_xtraCoolVar123} />;
'''
# TODO: Uncomment the following test once destructured object spreads are supported.
# test 'multiline spread attribute', ->
# eqJS '''
# <Component {...
# x } a={b} {... x } b="c" {...z }>
# </Component>
# ''', '''
# React.createElement(Component, Object.assign({},
# x , {"a": (b)}, x , {"b": "c"}, z )
# )
# '''
test 'multiline spread attribute', ->
eqJS '''
<Component {
x...} a={b} {x...} b="c" {z...}>
</Component>
''', '''
<Component {...x} a={b} {...x} b="c" {...z}>
</Component>;
'''
# TODO: Uncomment the following test once destructured object spreads are supported.
# test 'multiline tag with spread attribute', ->
# eqJS '''
# <Component
# z="1"
# {...x}
# a={b}
# b="c"
# >
# </Component>
# ''', '''
# React.createElement(Component, Object.assign({ \
# "z": "1"
# }, x, { \
# "a": (b), \
# "b": "c"
# })
# )
# '''
test 'multiline tag with spread attribute', ->
eqJS '''
<Component
z="1"
{x...}
a={b}
b="c"
>
</Component>
''', '''
<Component z="1" {...x} a={b} b="c">
</Component>;
'''
# TODO: Uncomment the following test once destructured object spreads are supported.
# test 'multiline tag with spread attribute first', ->
# eqJS '''
# <Component
# {...
# x}
# z="1"
# a={b}
# b="c"
# >
# </Component>
# ''', '''
# React.createElement(Component, Object.assign({}, \
test 'multiline tag with spread attribute first', ->
eqJS '''
<Component
{x...}
z="1"
a={b}
b="c"
>
</Component>
''', '''
<Component {...x} z="1" a={b} b="c">
</Component>;
'''
# x, { \
# "z": "1", \
# "a": (b), \
# "b": "c"
# })
# )
# '''
test 'complex multiline spread attribute', ->
eqJS '''
<Component
{y...
} a={b} {x...} b="c" {z...}>
<div code={someFunc({a:{b:{}, C:'}'}})} />
</Component>
''', '''
<Component {...y} a={b} {...x} b="c" {...z}>
<div code={someFunc({
a: {
b: {},
C: '}'
}
})} />
</Component>;
'''
# TODO: Uncomment the following test once destructured object spreads are supported.
# test 'complex multiline spread attribute', ->
# eqJS '''
# <Component
# {...
# y} a={b} {... x } b="c" {...z }>
# <div code={someFunc({a:{b:{}, C:'}'}})} />
# </Component>
# ''', '''
# React.createElement(Component, Object.assign({}, \
test 'self closing spread attribute on single line', ->
eqJS '''
<Component a="b" c="d" {@props...} />
''', '''
<Component a="b" c="d" {...this.props} />;
'''
# y, {"a": (b)}, x , {"b": "c"}, z ),
# React.createElement("div", {"code": (someFunc({a:{b:{}, C:'}'}}))})
# )
# '''
test 'self closing spread attribute on new line', ->
eqJS '''
<Component
a="b"
c="d"
{@props...}
/>
''', '''
<Component a="b" c="d" {...this.props} />;
'''
# TODO: Uncomment the following test once destructured object spreads are supported.
# test 'self closing spread attribute on single line', ->
# eqJS '''
# <Component a="b" c="d" {...@props} />
# ''', '''
# React.createElement(Component, Object.assign({"a": "b", "c": "d"}, @props ))
# '''
test 'self closing spread attribute on same line', ->
eqJS '''
<Component
a="b"
c="d"
{@props...} />
''', '''
<Component a="b" c="d" {...this.props} />;
'''
# TODO: Uncomment the following test once destructured object spreads are supported.
# test 'self closing spread attribute on new line', ->
# eqJS '''
# <Component
# a="b"
# c="d"
# {...@props}
# />
# ''', '''
# React.createElement(Component, Object.assign({ \
# "a": "b", \
# "c": "d"
# }, @props
# ))
# '''
test 'self closing spread attribute on next line', ->
eqJS '''
<Component
a="b"
c="d"
{@props...}
# TODO: Uncomment the following test once destructured object spreads are supported.
# test 'self closing spread attribute on same line', ->
# eqJS '''
# <Component
# a="b"
# c="d"
# {...@props} />
# ''', '''
# React.createElement(Component, Object.assign({ \
# "a": "b", \
# "c": "d"
# }, @props ))
# '''
# TODO: Uncomment the following test once destructured object spreads are supported.
# test 'self closing spread attribute on next line', ->
# eqJS '''
# <Component
# a="b"
# c="d"
# {...@props}
# />
# ''', '''
# React.createElement(Component, Object.assign({ \
# "a": "b", \
# "c": "d"
# }, @props
# ))
# '''
/>
''', '''
<Component a="b" c="d" {...this.props} />;
'''
test 'empty strings are not converted to true', ->
eqJS '''

View File

@@ -1587,6 +1587,50 @@ test "CSX error: ambiguous tag-like expression", ->
^
'''
test 'CSX error: invalid attributes', ->
assertErrorFormat '''
<div a="b" {props} />
''', '''
[stdin]:1:12: error: Unexpected token. Allowed CSX attributes are: id="val", src={source}, {props...} or attribute.
<div a="b" {props} />
^^^^^^^
'''
assertErrorFormat '''
<div a={b} {a:{b}} />
''', '''
[stdin]:1:12: error: Unexpected token. Allowed CSX attributes are: id="val", src={source}, {props...} or attribute.
<div a={b} {a:{b}} />
^^^^^^^
'''
assertErrorFormat '''
<div {"#{a}"} />
''', '''
[stdin]:1:6: error: Unexpected token. Allowed CSX attributes are: id="val", src={source}, {props...} or attribute.
<div {"#{a}"} />
^^^^^^^^
'''
assertErrorFormat '''
<div props... />
''', '''
[stdin]:1:11: error: Unexpected token. Allowed CSX attributes are: id="val", src={source}, {props...} or attribute.
<div props... />
^^^
'''
assertErrorFormat '''
<div {a:"b", props..., c:d()} />
''', '''
[stdin]:1:6: error: Unexpected token. Allowed CSX attributes are: id="val", src={source}, {props...} or attribute.
<div {a:"b", props..., c:d()} />
^^^^^^^^^^^^^^^^^^^^^^^^
'''
assertErrorFormat '''
<div {props..., a, b} />
''', '''
[stdin]:1:6: error: Unexpected token. Allowed CSX attributes are: id="val", src={source}, {props...} or attribute.
<div {props..., a, b} />
^^^^^^^^^^^^^^^^
'''
test 'Bound method called as callback before binding throws runtime error', ->
class Base
constructor: ->