8000 fix(compiler): error if rawText isn't estimated correctly (#60529) (#… · angular/angular@3441f7b · GitHub
[go: up one dir, main page]

Skip to content

Commit 3441f7b

Browse files
crisbetoatscott
authored andcommitted
fix(compiler): error if rawText isn't estimated correctly (#60529) (#60753)
The `TemplateLiteralElementExpr` has some logic where it tries to estimate the `rawText` if one isn't provided by looking at the node's source span. The problem with this approach is that we have some long-standing issues with our expression AST parser (see #60267 (comment)) where it might not produce accurate spans if escape sequences are involved. This in turn can lead to unrecoverable errors, because TypeScript will throw an error if the raw string doesn't match the cooked one when constructing a TypeScript AST node. These changes remove the logic that depends on the source span and relies purely on the secondary fallback that inserts escaped characters manually. It's also worth noting that the `rawText` doesn't seem to matter much at this point, because the main usage of it is when downlevelling template literals to ES5 which we no longer support. Fixes #60528. PR Close #60529 PR Close #60753
1 parent ae2fc18 commit 3441f7b

File tree

5 files changed

+14
-8
lines changed

5 files changed

+14
-8
lines changed

packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/value_composition/GOLDEN_PARTIAL.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,7 @@ MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "0.0.0-
750750
<div>No interpolations: {{ \`hello world \` }}</div>
751751
<span>With interpolations: {{ \`hello \${name}, it is currently \${timeOfDay}!\` }}</span>
752752
<p>With pipe: {{\`hello \${name}\` | uppercase}}</p>
753+
<h4>@let insideLet = \`Hello \${name}\`; Inside let: {{insideLet}}</h4>
753754
`, isInline: true, dependencies: [{ kind: "pipe", type: UppercasePipe, name: "uppercase" }] });
754755
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyApp, decorators: [{
755756
type: Component,
@@ -759,6 +760,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDE
759760
<div>No interpolations: {{ \`hello world \` }}</div>
760761
<span>With interpolations: {{ \`hello \${name}, it is currently \${timeOfDay}!\` }}</span>
761762
<p>With pipe: {{\`hello \${name}\` | uppercase}}</p>
763+
<h4>@let insideLet = \`Hello \${name}\`; Inside let: {{insideLet}}</h4>
762764
`,
763765
imports: [UppercasePipe],
764766
}]

packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/value_composition/template_literals.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,8 @@ if (rf & 2) {
44
$r3$.ɵɵadvance(2);
55
$r3$.ɵɵtextInterpolate1("With interpolations: ", `hello ${ctx.name}, it is currently ${ctx.timeOfDay}!`, "");
66
$r3$.ɵɵadvance(2);
7-
$r3$.ɵɵtextInterpolate1("With pipe: ", $r3$.ɵɵpipeBind1(6, 3, `hello ${ctx.name}`), "");
7+
$r3$.ɵɵtextInterpolate1("With pipe: ", $r3$.ɵɵpipeBind1(6, 4, `hello ${ctx.name}`), "");
8+
const $insideLet_r1$ = `Hello ${ctx.name}`;
9+
$r3$.ɵɵadvance(4);
10+
$r3$.ɵɵtextInterpolate1(" Inside let: ", $insideLet_r1$, "");
811
}

packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/value_composition/template_literals.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export class UppercasePipe {
1313
<div>No interpolations: {{ \`hello world \` }}</div>
1414
<span>With interpolations: {{ \`hello \${name}, it is currently \${timeOfDay}!\` }}</span>
1515
<p>With pipe: {{\`hello \${name}\` | uppercase}}</p>
16+
<h4>@let insideLet = \`Hello \${name}\`; Inside let: {{insideLet}}</h4>
1617
`,
1718
imports: [UppercasePipe],
1819
})

packages/compiler/src/output/output_ast.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -683,23 +683,22 @@ export class TemplateLiteralExpr extends Expression {
683683
}
684684
}
685685
export class TemplateLiteralElementExpr extends Expression {
686-
rawText: string;
686+
readonly rawText: string;
687687

688688
constructor(
689-
public text: string,
689+
readonly text: string,
690690
sourceSpan?: ParseSourceSpan | null,
691691
rawText?: string,
692692
) {
693693
super(STRING_TYPE, sourceSpan);
694694

695-
// If `rawText` is not provided, try to extract the raw string from its
696-
// associated `sourceSpan`. If that is also not available, "fake" the raw
697-
// string instead by escaping the following control sequences:
695+
// If `rawText` is not provided, "fake" the raw string by escaping the following sequences:
698696
// - "\" would otherwise indicate that the next character is a control character.
699697
// - "`" and "${" are template string control sequences that would otherwise prematurely
700698
// indicate the end of the template literal element.
701-
this.rawText =
702-
rawText ?? sourceSpan?.toString() ?? escapeForTemplateLiteral(escapeSlashes(text));
699+
// Note that we can't rely on the `sourceSpan` here, because it may be incorrect (see
700+
// https://github.com/angular/angular/pull/60267#discussion_r1986402524).
701+
this.rawText = rawText ?? escapeForTemplateLiteral(escapeSlashes(text));
703702
}
704703

705704
override visitExpression(visitor: ExpressionVisitor, context: any) {

packages/core/test/application_ref_spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {
2727
Type,
2828
ViewChild,
2929
ViewContainerRef,
30+
Injector,
3031
} from '../src/core';
3132
import {ErrorHandler} from '../src/error_handler';
3233
import {ComponentRef} from '../src/linker/component_factory';

0 commit comments

Comments
 (0)
0