feat(compiler): add support for shorthand property declarations in templates (#42421)

Adds support for shorthand property declarations inside Angular templates. E.g. doing `{foo, bar}` instead of `{foo: foo, bar: bar}`.

Fixes #10277.

PR Close #42421
This commit is contained in:
Kristiyan Kostadinov
2021-06-19 08:07:20 +02:00
committed by Dylan Hunn
parent 699a8b43cb
commit cc672f05bf
17 changed files with 390 additions and 10 deletions
@@ -929,11 +929,23 @@ export class _ParseAST {
if (!this.consumeOptionalCharacter(chars.$RBRACE)) {
this.rbracesExpected++;
do {
const keyStart = this.inputIndex;
const quoted = this.next.isString();
const key = this.expectIdentifierOrKeywordOrString();
keys.push({key, quoted});
this.expectCharacter(chars.$COLON);
values.push(this.parsePipe());
// Properties with quoted keys can't use the shorthand syntax.
if (quoted) {
this.expectCharacter(chars.$COLON);
values.push(this.parsePipe());
} else if (this.consumeOptionalCharacter(chars.$COLON)) {
values.push(this.parsePipe());
} else {
const span = this.span(keyStart);
const sourceSpan = this.sourceSpan(keyStart);
values.push(new PropertyRead(
span, sourceSpan, sourceSpan, new ImplicitReceiver(span, sourceSpan), key));
}
} while (this.consumeOptionalCharacter(chars.$COMMA));
this.rbracesExpected--;
this.expectCharacter(chars.$RBRACE);
@@ -122,6 +122,23 @@ describe('parser', () => {
expectActionError('{1234:0}', 'expected identifier, keyword, or string');
expectActionError('{#myField:0}', 'expected identifier, keyword or string');
});
it('should parse property shorthand declarations', () => {
checkAction('{a, b, c}', '{a: a, b: b, c: c}');
checkAction('{a: 1, b}', '{a: 1, b: b}');
checkAction('{a, b: 1}', '{a: a, b: 1}');
checkAction('{a: 1, b, c: 2}', '{a: 1, b: b, c: 2}');
});
it('should not allow property shorthand declaration on quoted properties', () => {
expectActionError('{"a-b"}', 'expected : at column 7');
});
it('should not infer invalid identifiers as shorthand property declarations', () => {
expectActionError('{a.b}', 'expected } at column 3');
expectActionError('{a["b"]}', 'expected } at column 3');
expectActionError('{1234}', ' expected identifier, keyword, or string at column 2');
});
});
describe('member access', () => {
@@ -360,4 +360,15 @@ describe('expression AST absolute source spans', () => {
expect(spans).toContain(['nestedPlaceholder', new AbsoluteSourceSpan(89, 106)]);
});
});
describe('object literal', () => {
it('is correct for object literals with shorthand property declarations', () => {
const spans =
humanizeExpressionSource(parse('<div (click)="test({a: 1, b, c: 3, foo})"></div>').nodes);
expect(spans).toContain(['{a: 1, b: b, c: 3, foo: foo}', new AbsoluteSourceSpan(19, 39)]);
expect(spans).toContain(['b', new AbsoluteSourceSpan(26, 27)]);
expect(spans).toContain(['foo', new AbsoluteSourceSpan(35, 38)]);
});
});
});