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
Bug: HostBinding get incorrect semantics when property name is same as literal #18698
Comments
I can help to provide a fix if you agree this is unexpected. |
sounds like a bug. |
Confirmed with Ivy as well: https://stackblitz.com/edit/angular-ivy-gz9sfc?file=src%2Fapp%2Fapp.module.ts |
Currently when analyzing the metadata of a directive, we bundle together the bindings from `host` and the `HostBinding` and `HostListener` together. This can become a problem later on in the compilation pipeline, because we try to evaluate the value of the binding, causing something like `@HostBinding('class.foo') public true = 1;` to be treated the same as `host: {'[class.foo]': 'true'}`. While looking into the issue, I noticed another one that is closely related: we weren't treating quoted property names correctly. E.g. `@HostBinding('class.foo') public "foo-bar" = 1;` was being interpreted as `classProp('foo', ctx.foo - ctx.bar)` due to the same issue where property names were being evaluated. These changes resolve both of the issues by treating all `HostBinding` instance as if they're reading the property from `this`. E.g. the `@HostBinding('class.foo') public true = 1;` from above is now being treated as `host: {'[class.foo]': 'this.true'}` which further down the pipeline becomes `classProp('foo', ctx.true)`. This doesn't have any payload size implications for existing code, because we've always been prefixing implicit property reads with `ctx.`. If the property doesn't have an identifier that can be read using dotted access, we convert it to a quoted one (e.g. `classProp('foo', ctx['is-foo']))`. Fixes angular#40220. Fixes angular#40230. Fixes angular#18698.
Currently when analyzing the metadata of a directive, we bundle together the bindings from `host` and the `HostBinding` and `HostListener` together. This can become a problem later on in the compilation pipeline, because we try to evaluate the value of the binding, causing something like `@HostBinding('class.foo') public true = 1;` to be treated the same as `host: {'[class.foo]': 'true'}`. While looking into the issue, I noticed another one that is closely related: we weren't treating quoted property names correctly. E.g. `@HostBinding('class.foo') public "foo-bar" = 1;` was being interpreted as `classProp('foo', ctx.foo - ctx.bar)` due to the same issue where property names were being evaluated. These changes resolve both of the issues by treating all `HostBinding` instance as if they're reading the property from `this`. E.g. the `@HostBinding('class.foo') public true = 1;` from above is now being treated as `host: {'[class.foo]': 'this.true'}` which further down the pipeline becomes `classProp('foo', ctx.true)`. This doesn't have any payload size implications for existing code, because we've always been prefixing implicit property reads with `ctx.`. If the property doesn't have an identifier that can be read using dotted access, we convert it to a quoted one (e.g. `classProp('foo', ctx['is-foo']))`. Fixes angular#40220. Fixes angular#40230. Fixes angular#18698.
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
I'm submitting a...
Current behavior
When using
@HostBinding()
with a property name is one oftrue
,false
ornull
, Angular will incorrectly regard it as a literal value, for example:Would result to
<element class="foo">
, even the binding value isfalse
.Expected behavior
Should got
<element class="bar">
according to the binding value.And reserved words are allowed as property name in JavaScript.
But for:
It should still be regarded as literal since it's general expression here.
Possibly we'll need a new
boolean
value for parser to indicate whether it's in expression context or not.Minimal reproduction of the problem with instructions
http://plnkr.co/edit/wUsocMIjZ82RnSxOc3U5?p=preview
What is the motivation / use case for changing the behavior?
Angular uses a unified parser for all bindings, so it's indistinguishable whether it came from.
But for
HostBinding()
s directly written on class properties, there is no expression context at all since theHostBinding()
decorator is only for specific property (for what property decorator means), so it should be a bug of Angular parser for the binding recognition. Actually it seems to be a bug of metadata collector, since it's already indistinguishable when it came to parser.Environment
The text was updated successfully, but these errors were encountered: