compiler: Parser interpolation assertion failure after the introduction of new control flow @ symbol syntax
bougwal opened this issue · comments
Which @angular/* package(s) are the source of the bug?
compiler
Is this a regression?
Yes
Description
Prior to the introduction of the new control flow, the compiler was successfully handling the custom interpolation marker set to the @ sign in the component interpolation config such as:
@component({
selector: 'x',
template: 'Heya, @p@'
interpolation: ['@', '@']
})
export class X {
p = 'wassup!'
}
now after the introduction of the new control flow, the example above throws
1. [ERROR] NG5002: Incomplete block "p". If you meant to write the @ character, you should use the @ HTML entity instead. [plugin angular-compiler]
IMHO
1 - This seems to be a regression
2- The error failure should not be about the incomplete block which is being thrown right here:
private _consumeIncompleteBlock(token: IncompleteBlockOpenToken) {
const parameters: html.BlockParameter[] = [];
while (this._peek.type === TokenType.BLOCK_PARAMETER) {
const paramToken = this._advance<BlockParameterToken>();
parameters.push(new html.BlockParameter(paramToken.parts[0], paramToken.sourceSpan));
}
const end = this._peek.sourceSpan.fullStart;
const span = new ParseSourceSpan(token.sourceSpan.start, end, token.sourceSpan.fullStart);
// Create a separate `startSpan` because `span` will be modified when there is an `end` span.
const startSpan = new ParseSourceSpan(token.sourceSpan.start, end, token.sourceSpan.fullStart);
const block = new html.Block(token.parts[0], parameters, [], span, token.sourceSpan, startSpan);
this._pushContainer(block, false);
// Incomplete blocks don't have children so we close them immediately and report an error.
this._popContainer(null, html.Block, null);
this.errors.push(
TreeError.create(
token.parts[0],
span,
`Incomplete block "${token.parts[0]}". If you meant to write the @ character, ` +
`you should use the "@" HTML entity instead.`,
),
);
}
But rather about unusable interpolation symbol..
As the new control flow is reserving @ for its usage, I would suggest adding it to the UNUSABLE_INTERPOLATION_REGEXPS in the compiler assertion file as follows:
const UNUSABLE_INTERPOLATION_REGEXPS = [
/@/, //reserved control flow syntax <------------------------ Addition
/^\s*$/, // empty
/[<>]/, // html tag
/^[{}]$/, // i18n expansion
/&(#|[a-z])/i, // character reference,
/^\/\//, // comment
];
function assertInterpolationSymbols(identifier, value) {
if (value != null && !(Array.isArray(value) && value.length == 2)) {
throw new Error(`Expected '${identifier}' to be an array, [start, end].`);
}
else if (value != null) {
const start = value[0];
const end = value[1];
// Check for unusable interpolation symbols
UNUSABLE_INTERPOLATION_REGEXPS.forEach((regexp) => {
if (regexp.test(start) || regexp.test(end)) {
throw new Error(`['${start}', '${end}'] contains unusable interpolation symbol.`);
}
});
}
}
With that we fail properly as follows:
If there is a plan to allow this interpolation case with the new control flow, that might require a more subtle refactor.
I have a PR ready to add the new control flow marker to the unusable/banned interpolation const in the complier/assertions so we provide proper feedback
As of now, if this regression is valid, any existing app that uses the reserved control flow @ sign as a custom interpolation, it will fail upon upgrade to control flow usage.
Looking forward to the team's feedback on this
Please provide a link to a minimal reproduction of the bug
No response
Please provide the exception or error you saw
No response
Please provide the environment you discovered this bug in (run ng version
)
No response
Anything else?
No response
This isn't really a regression, more of an intentional breaking change. v17 reserved the @
symbol in templates, making it illegal to use as a plain character, or for interpolations. Your PR would be welcome to improve the error message.
I've also opened #55778 to formally deprecate the interpolation
option itself.