Skip to content

Commit 24bab55

Browse files
JeanMechethePunderWoman
authored andcommitted
fix(compiler): lexer support for template literals in object literals (#61601)
This commit fixes a shortcoming of the lexer with template literals fixes #61572 PR Close #61601
1 parent 12e2302 commit 24bab55

3 files changed

Lines changed: 26 additions & 7 deletions

File tree

‎packages/compiler/src/expression_parser/lexer.ts‎

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,7 @@ class _Scanner {
202202
private readonly length: number;
203203
private peek = 0;
204204
private index = -1;
205-
private literalInterpolationDepth = 0;
206-
private braceDepth = 0;
205+
private braceStack: ('interpolation' | 'expression')[] = [];
207206

208207
constructor(private readonly input: string) {
209208
this.length = input.length;
@@ -330,21 +329,20 @@ class _Scanner {
330329
}
331330

332331
private scanOpenBrace(start: number, code: number): Token {
333-
this.braceDepth++;
332+
this.braceStack.push('expression');
334333
this.advance();
335334
return newCharacterToken(start, this.index, code);
336335
}
337336

338337
private scanCloseBrace(start: number, code: number): Token {
339338
this.advance();
340339

341-
if (this.braceDepth === 0 && this.literalInterpolationDepth > 0) {
342-
this.literalInterpolationDepth--;
340+
const currentBrace = this.braceStack.pop();
341+
if (currentBrace === 'interpolation') {
343342
this.tokens.push(newOperatorToken(start, this.index, '}'));
344343
return this.scanTemplateLiteralPart(this.index);
345344
}
346345

347-
this.braceDepth--;
348346
return newCharacterToken(start, this.index, code);
349347
}
350348

@@ -501,7 +499,7 @@ class _Scanner {
501499

502500
// @ts-expect-error
503501
if (this.peek === chars.$LBRACE) {
504-
this.literalInterpolationDepth++;
502+
this.braceStack.push('interpolation');
505503
this.tokens.push(
506504
new StringToken(
507505
start,

‎packages/compiler/test/expression_parser/lexer_spec.ts‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,20 @@ describe('lexer', () => {
567567
expectStringToken(tokens[8], 29, 33, '!!!', StringTokenKind.TemplateLiteralEnd);
568568
});
569569

570+
it('should tokenize a template literal in an literal object value', () => {
571+
const tokens: Token[] = lex('{foo: `${name}`}');
572+
expect(tokens.length).toBe(9);
573+
expectCharacterToken(tokens[0], 0, 1, '{');
574+
expectIdentifierToken(tokens[1], 1, 4, 'foo');
575+
expectCharacterToken(tokens[2], 4, 5, ':');
576+
expectStringToken(tokens[3], 6, 7, '', StringTokenKind.TemplateLiteralPart);
577+
expectOperatorToken(tokens[4], 7, 9, '${');
578+
expectIdentifierToken(tokens[5], 9, 13, 'name');
579+
expectOperatorToken(tokens[6], 13, 14, '}');
580+
expectStringToken(tokens[7], 14, 15, '', StringTokenKind.TemplateLiteralEnd);
581+
expectCharacterToken(tokens[8], 15, 16, '}');
582+
});
583+
570584
it('should produce an error if a template literal is not terminated', () => {
571585
expectErrorToken(
572586
lex('`hello')[0],

‎packages/compiler/test/expression_parser/parser_spec.ts‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,13 @@ describe('parser', () => {
439439
checkBinding('`hello ${(name | capitalize)}!!!`');
440440
});
441441

442+
it('should parse template literals in objects literals', () => {
443+
checkBinding('{"a": `${name}`}');
444+
checkBinding('{"a": `hello ${name}!`}');
445+
checkBinding('{"a": `hello ${`hello ${`hello`}`}!`}');
446+
checkBinding('{"a": `hello ${{"b": `hello`}}`}');
447+
});
448+
442449
it('should report error if interpolation is empty', () => {
443450
expectBindingError(
444451
'`hello ${}`',

0 commit comments

Comments
 (0)