Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

compiler: Parser interpolation assertion failure after the introduction of new control flow @ symbol syntax #55772

Closed
bougwal opened this issue May 13, 2024 · 2 comments
Labels
area: compiler Issues related to `ngc`, Angular's template compiler core: control flow Issues related to the built-in control flow (@if, @for, @switch)
Milestone

Comments

@bougwal
Copy link
Contributor

bougwal commented May 13, 2024

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!'
}

Link to a working example V16

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 "&#64;" HTML entity instead.`,
      ),
    );
  }

Link to a broken example V17

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:

Screenshot 2024-05-12 at 12 28 38

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

@alxhub
Copy link
Member

alxhub commented May 14, 2024

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.

@pkozlowski-opensource pkozlowski-opensource added area: core Issues related to the framework runtime core: control flow Issues related to the built-in control flow (@if, @for, @switch) labels May 15, 2024
@ngbot ngbot bot modified the milestone: needsTriage May 15, 2024
@pkozlowski-opensource pkozlowski-opensource added area: compiler Issues related to `ngc`, Angular's template compiler and removed area: core Issues related to the framework runtime labels May 15, 2024
@bougwal
Copy link
Contributor Author

bougwal commented May 16, 2024

Closing after relevant PR merged under commit 2bb12ac.

@bougwal bougwal closed this as completed May 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: compiler Issues related to `ngc`, Angular's template compiler core: control flow Issues related to the built-in control flow (@if, @for, @switch)
Projects
None yet
3 participants