-
Notifications
You must be signed in to change notification settings - Fork 24.8k
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
feat(compiler): support tagged template literals in code generator #39122
Conversation
8dbfc88
to
bf70ea9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking nice. Do we care to support tagged template literals in View Engine, given that it is deprecated?
bf70ea9
to
1a3b684
Compare
Thanks for the comments @petebacondarwin!
Since I'm a bit new to the Angular codebase, do you mind pointing out which components in my PR are ViewEngine-specific? And for full ViewEngine support, do you think there's anything missing? For background I'm working on adding support for Trusted Types in Angular. Tagged template literals make it possible to define an API that only accepts a constant string as input (i.e. with a regular function it's impossible to distinguish between |
@bjarkler - the main part of this PR that is ViewEngine specific, I believe, is the |
In this Trusted Types requirement, will the template literal string be something that the application developer puts into a template or will the compiler generate them somehow? Can you point me at some background to this? The reason I ask is that the "raw" strings are dependent upon the source of the literal. |
For the Trusted Types use case, consider the following Angular template:
When the template is compiled, any attributes with constant values are hoisted by Angular into a separate "consts" array in the compiled source:
If an application enforces Trusted Types, this will later cause a Trusted Types violation, as setting the srcdoc of an iframe requires a TrustedHTML object. So the idea is to introduce a function/tag called
Using Supporting raw strings or even sourceSpans are not strict requirements for this I believe, but since I was adding support for this I figured it would be better to try to do it properly, in case there were other use cases in the future. |
(But FWIW, in my current implementation I use the sourceSpan of the corresponding constant in the Angular template.) |
1a3b684
to
21184cd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks much better. Nice work!
@alxhub, can you take a look? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me, but I'd like @alxhub to take a look as well. Thank you!
* array. | ||
*/ | ||
const makeTemplateObjectPolyfill = | ||
'(this&&this.__makeTemplateObject||function(e,t){return Object.defineProperty?Object.defineProperty(e,"raw",{value:t}):e.raw=t,e})'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's strange that we need to provide this polyfill ourselves.
Shouldn't it come from tslib?
Could we check if the current file has import for this method and if not add an import from tslib? Is that feasible @petebacondarwin @alxhub ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this PR were aimed at Ivy only, I think it would definitely be possible. The way to do this would be to treat it as an ExternalExpr
that refers to {moduleName: 'tslib', name: 'makeTemplateObject'}
(or whatever the tslib export is).
Then, we'll have to ensure that in JIT mode (which is where AbstractJsEmitterVisitor
ends up being used in Ivy), that external reference will have be made resolvable by the R3JitReflector
to the real tslib
function.
View Engine might be able to handle emitting such an import, but I've not ever tried that so I don't know for sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this PR was originally sent we've now decided not to support Trusted Types in ViewEngine, and I believe the $localize
tag was already Ivy-only. So I don't think there's anything preventing us from dropping the ViewEngine-specific parts from this PR and following @alxhub's proposal. I'd be happy to see how far I can take this but might need some guidance with the R3JitReflector
part.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good @IgorMinar. I've now removed the VE-specific code.
* array. | ||
*/ | ||
const makeTemplateObjectPolyfill = | ||
'(this&&this.__makeTemplateObject||function(e,t){return Object.defineProperty?Object.defineProperty(e,"raw",{value:t}):e.raw=t,e})'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this PR were aimed at Ivy only, I think it would definitely be possible. The way to do this would be to treat it as an ExternalExpr
that refers to {moduleName: 'tslib', name: 'makeTemplateObject'}
(or whatever the tslib export is).
Then, we'll have to ensure that in JIT mode (which is where AbstractJsEmitterVisitor
ends up being used in Ivy), that external reference will have be made resolvable by the R3JitReflector
to the real tslib
function.
View Engine might be able to handle emitting such an import, but I've not ever tried that so I don't know for sure.
cd11097
to
a5c457f
Compare
Add a TaggedTemplateExpr to represent tagged template literals in Angular's syntax tree (more specifically Expression in output_ast.ts). Also update classes that implement ExpressionVisitor to add support for tagged template literals in different contexts, such as JIT compilation and conversion to JS. Partial support for tagged template literals had already been implemented to support the $localize tag used by Angular's i18n framework. Where applicable, this code was refactored to support arbitrary tags, although completely replacing the i18n-specific support for the $localize tag with the new generic support for tagged template literals may not be completely trivial, and is left as future work.
a5c457f
to
5a49982
Compare
…39122) Add a TaggedTemplateExpr to represent tagged template literals in Angular's syntax tree (more specifically Expression in output_ast.ts). Also update classes that implement ExpressionVisitor to add support for tagged template literals in different contexts, such as JIT compilation and conversion to JS. Partial support for tagged template literals had already been implemented to support the $localize tag used by Angular's i18n framework. Where applicable, this code was refactored to support arbitrary tags, although completely replacing the i18n-specific support for the $localize tag with the new generic support for tagged template literals may not be completely trivial, and is left as future work. PR Close #39122
…rator (angular#39122)" This reverts commit 5631daa.
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. |
Add a TaggedTemplateExpr to represent tagged template literals in
Angular's syntax tree (more specifically Expression in output_ast.ts).
Also update classes that implement ExpressionVisitor to add support for
tagged template literals in different contexts, such as JIT compilation
and conversion to JS.
Partial support for tagged template literals had already been
implemented to support the $localize tag used by Angular's i18n
framework. Where applicable, this code was refactored to support
arbitrary tags, although completely replacing the i18n-specific support
for the $localize tag with the new generic support for tagged template
literals may not be completely trivial, and is left as future work.
PR Checklist
Please check if your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?