Repository navigation
fix(compiler-cli): don't unnecessarily throw on StaticSymbols - #12158
Conversation
|
(fyi this is a blocker for AOT support in angular/universal) |
There was a problem hiding this comment.
Could you add a test for this new behavior? In https://github.com/angular/angular/blob/master/modules/@angular/compiler-cli/test/static_reflector_spec.ts...
There was a problem hiding this comment.
This change is wrong. The reason that this code checks using instanceof is because the static reflector assumes that all the static symbols it receives in its API were produced by the static reflector. This is because it uses object identity to cache information and determine type identity. The bug is not that we are checking for instanceof instead of using isStaticSymbol, rather, it is that someone is passing static symbol that wasn't produced by the static reflector. In this case the test is doing what it was intended to do, report this case.
There was a problem hiding this comment.
got it, thanks for the explanation @chuckjaz
I'll dig deeper and find the source of static symbols not created by the static reflector and update this PR accordingly
There was a problem hiding this comment.
So from digging around deeper I see what is going on.
The objects were originally static symbols created by the StaticSymbol constructor, but then were cloned in the mapStringMap function (which is called by simplify in the parameters method of the static reflector) which is where the instanceof check breaks, as well as proper ability to cache by reference.
Looking deeper into why this happens to only some providers in some situations and to why the simplify functions that are being used exist in the first place and if the cloning can be circumvented or if it is a deeper issue that StaticSymbols are passed to the simplify function in the first place
There was a problem hiding this comment.
Thanks for looking into this! StaticSymbol should be a special case in the evaluator. Try adding the lines:
if (expression instanceof StaticSymbol) {
return expression;
}just after the test for Array in simplify(). This will prevent the static reflector from trying to clone a StaticSymbol, treating it like a primitive instead of a hash map.
There was a problem hiding this comment.
If you find how a StaticSymbol got in a value passed to simplify() I would be curious. That shouldn't happen but if it does we shouldn't damage it.
There was a problem hiding this comment.
@chuckjaz agreed, and thanks!
My solution was identical to yours but I added the check below the check for primitives, if it's important that it be below the check for Array just let me know and I'll happily move it
So far I am stumped as well how only in rare cases static symbols are passed to simplify (it's within some deep recursion in some edge case situations it seems) but I'll definitely let you know if I figure it out!
Also, just added a test for this new check as well 👍
There was a problem hiding this comment.
We are cross talking! No need for it being after Array really. It is slightly faster there (in that StaticSymbols are less common than Arrays) but not really noticeably so. Only move it if you feel so inclined.
There was a problem hiding this comment.
@chuckjaz makes perfect sense, I went a head and pushed one small update with that extra optimization 👍
There was a problem hiding this comment.
Could you then also export the StaticSymbol here as well and drop the declaration in static_reflector? You will probably need to add members to the one in @angular/compiler...
6d545f3 to
14ab2f7
Compare
There was a problem hiding this comment.
Found the issue.
When recursively processing/simplifying annotation metadata StaticSymbols need to be kept in tact rather than treated as plain string maps and cloned
This was happening to us in universal for any private import we made from platform-browser using the format we see from the this repo must be used to properly import private exports (i.e. using the explicit typeof x type annotations) which we do in universal here.
I'm guessing this is just a byproduct of the parsing being a bit different when using that special import/export format required for private exports.
I've updated this PR accordingly to check for StaticSymbol before further processing in the simplifyInContext method which I've verified with this fix universal now builds and runs as expected with AOT
Happy to make any further updates or refactors desired as well, just let me know, and thanks for taking a look at this @tbosch and @chuckjaz!
There was a problem hiding this comment.
Can you add a test to static_reflector_spec.ts that verifies that simplify() will not clone a StaticSymbol? Something like:
it('should not clone a static symbol', () => {
const symbol = new StaticSymbol('/tmp/src/some_file.ts', 'SomeSymbol');
expect(simplify(symbol, symbol)).toBe(symbol);
});There was a problem hiding this comment.
@chuckjaz just did in a separate commit 👍
There was a problem hiding this comment.
if you want me to squash it with the first, just let me know
There was a problem hiding this comment.
Up to you. Tobias will probably squash and merge anyway.
There was a problem hiding this comment.
No need for this to be a separate commit. Just squash them.
1a6e7e2 to
672790d
Compare
672790d to
db4b4b5
Compare
|
Awesome, thanks for digging so deep, @steve8708 ! |
|
no problem, thank you for the tips @alexeagle! |
|
Hey everyone, I'm a bit confused here :/ I stumbled upon this thread from this one as I was looking for a solution to fix my Ionic 2 compiler when I run |
|
I am not sure what your question is but the lines https://github.com/angular/angular/blob/master/modules/%40angular/compiler-cli/src/static_reflector.ts#L369-L371 were added to resolve this issue. |
|
@chuckjaz Thanks for quick response. Sorry for the confusion. I don't have that file in my respective node_modules directory. I was able to solve the problem by not using the DomSanitizer as a provider and just imported it directly into my component. Problem solved :) |
|
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. |
Please check if the PR fulfills these requirements
What kind of change does this PR introduce? (check one with "x")
What is the current behavior? (You can also link to an open issue here)
#11276 #12097
ngc throws an error when StaticSymbol interface compatible objects are passed to
StaticReflector.parametersorStaticReflector.hasLifecycleHookWhat is the new behavior?
If the object properly matches the
StaticSymbolinterface, do not throw an error and allow the object to be processedDoes this PR introduce a breaking change? (check one with "x")
If this PR contains a breaking change, please describe the impact and migration path for existing applications: ...
Other information:
Closes #11276 #12097