X Tutup
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions modules/angular2/src/change_detection/parser/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,18 +65,21 @@ export class Parser {
}

parseAction(input: string, location: any): ASTWithSource {
this._checkNoInterpolation(input, location);
var tokens = this._lexer.tokenize(input);
var ast = new _ParseAST(input, location, tokens, this._reflector, true).parseChain();
return new ASTWithSource(ast, input, location);
}

parseBinding(input: string, location: any): ASTWithSource {
this._checkNoInterpolation(input, location);
var tokens = this._lexer.tokenize(input);
var ast = new _ParseAST(input, location, tokens, this._reflector, false).parseChain();
return new ASTWithSource(ast, input, location);
}

parseSimpleBinding(input: string, location: string): ASTWithSource {
this._checkNoInterpolation(input, location);
var tokens = this._lexer.tokenize(input);
var ast = new _ParseAST(input, location, tokens, this._reflector, false).parseSimpleBinding();
return new ASTWithSource(ast, input, location);
Expand Down Expand Up @@ -105,12 +108,9 @@ export class Parser {
var ast = new _ParseAST(input, location, tokens, this._reflector, false).parseChain();
expressions.push(ast);
} else {
var errLocation = '';
for (var j = 0; j < i; j++) {
errLocation += j % 2 === 0 ? parts[j] : `{{${parts[j]}}}`;
}
throw new ParseException('Blank expressions are not allowed in interpolated strings', input,
`at column ${errLocation.length} in`, location);
`at column ${this._findInterpolationErrorColumn(parts, i)} in`,
location);
}
}
return new ASTWithSource(new Interpolation(strings, expressions), input, location);
Expand All @@ -119,6 +119,24 @@ export class Parser {
wrapLiteralPrimitive(input: string, location: any): ASTWithSource {
return new ASTWithSource(new LiteralPrimitive(input), input, location);
}

private _checkNoInterpolation(input: string, location: any): void {
var parts = StringWrapper.split(input, INTERPOLATION_REGEXP);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about adding the check in parseInterpolation() to avoid duplicating the logic here ?
(you would have to check that you are parsing a template binding there)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, yeh, this line here is not ideal but I didn't want to call the entire parseIntorpolation just to do this check. I'm not sure I can think of a much better solution atm....

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I mean is that if parseInterpolation() finds an interpolation while we are parsing a tpl binding, we should throw.

This would also makes your code consistent with the existing code (check how parsePipe() throws when parsing an action)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM when the minor fixes are in (as discussed)

if (parts.length > 1) {
throw new ParseException('Got interpolation ({{}}) where expression was expected', input,
`at column ${this._findInterpolationErrorColumn(parts, 1)} in`,
location);
}
}

private _findInterpolationErrorColumn(parts: string[], partInErrIdx: number): number {
var errLocation = '';
for (var j = 0; j < partInErrIdx; j++) {
errLocation += j % 2 === 0 ? parts[j] : `{{${parts[j]}}}`;
}

return errLocation.length;
}
}

export class _ParseAST {
Expand Down
27 changes: 21 additions & 6 deletions modules/angular2/test/change_detection/parser/parser_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,11 @@ export function main() {

it('should store the passed-in location',
() => { expect(parseAction('someExpr', 'location').location).toBe('location'); });

it("should throw when encountering interpolation", () => {
expectActionError("{{a()}}")
.toThrowErrorWith('Got interpolation ({{}}) where expression was expected');
});
});

describe("general error handling", () => {
Expand Down Expand Up @@ -256,6 +261,11 @@ export function main() {
it('should throw on assignment', () => {
expect(() => parseBinding("a=2")).toThrowError(new RegExp("contain assignments"));
});

it('should throw when encountering interpolation', () => {
expectBindingError("{{a.b}}")
.toThrowErrorWith('Got interpolation ({{}}) where expression was expected');
});
});

describe('parseTemplateBindings', () => {
Expand Down Expand Up @@ -398,12 +408,12 @@ export function main() {

it("should throw on empty interpolation expressions", () => {
expect(() => parseInterpolation("{{}}"))
.toThrowError(new RegExp(
"Parser Error: Blank expressions are not allowed in interpolated strings"));
.toThrowErrorWith(
"Parser Error: Blank expressions are not allowed in interpolated strings");

expect(() => parseInterpolation("foo {{ }}"))
.toThrowError(new RegExp(
"Parser Error: Blank expressions are not allowed in interpolated strings"));
.toThrowErrorWith(
"Parser Error: Blank expressions are not allowed in interpolated strings");
});
});

Expand All @@ -420,8 +430,13 @@ export function main() {

it("should throw when the given expression is not just a field name", () => {
expect(() => parseSimpleBinding("name + 1"))
.toThrowError(new RegExp(
'Simple binding expression can only contain field access and constants'));
.toThrowErrorWith(
'Simple binding expression can only contain field access and constants');
});

it('should throw when encountering interpolation', () => {
expect(() => parseSimpleBinding('{{exp}}'))
.toThrowErrorWith('Got interpolation ({{}}) where expression was expected');
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ export function main() {
expect(process(el('<div [a]v="b"></div>'))[0]).toBe(null);
});

it('should throw when [] binding contains interpolation', () => {
expect(() => process(el('<div [a]="a + {{b()}}"></div>'))[0])
.toThrowErrorWith(
'Got interpolation ({{}}) where expression was expected at column 4 in [a + {{b()}}] in someComponent');
});

it('should detect bind- syntax', () => {
var results = process(el('<div bind-a="b"></div>'));
expect(results[0].propertyBindings.get('a').source).toEqual('b');
Expand Down Expand Up @@ -157,6 +163,12 @@ export function main() {
expect(eventBinding.fullName).toEqual('click');
});

it('should throw when () action contains interpolation', () => {
expect(() => process(el('<div (a)="{{b()}}"></div>'))[0])
.toThrowErrorWith(
'Got interpolation ({{}}) where expression was expected at column 0 in [{{b()}}] in someComponent');
});

it('should detect on- syntax', () => {
var results = process(el('<div on-click="b()"></div>'));
var eventBinding = results[0].eventBindings[0];
Expand Down
X Tutup