-
Notifications
You must be signed in to change notification settings - Fork 24.7k
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
Batch of Template Type-checking fixes #34649
Conversation
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.
Some minor things that need some cleaning up.
|
||
@Directive({ | ||
selector: '[dir]', | ||
inputs: ['propertyName'], |
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.
Please see #34482 for a suggestion on how to make this setup more clear.
node.typeParameters.map(param => ts.createTypeReferenceNode(param.name, undefined)); | ||
} else { | ||
typeArguments = []; | ||
for (let i = 0; i < node.typeParameters.length; i++) { |
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.
No .map
here? :-)
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 felt a little weird to use, since we're ignoring the value. Done though.
39c94c6
to
6056a8f
Compare
6056a8f
to
258d41b
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.
LGTM, but I'd like to see https://github.com/angular/angular/pull/34649/files#r363443363 addressed.
It's possible to declare multiple inputs for a directive/component which all map to the same property name. This is usually done in error, as only one of any bindings to the property will "win". In the template type-checker, an error was previously being raised as a result of this ambiguity. Specifically, a type constructor was produced which required a binding for each field, but only one of the fields had a value via the binding. TypeScript would (rightfully) error on missing values for the remaining fields. This ultimately was happening when the code which generated the default values for "unset" inputs belonging to directives or pipes used the final mapping from properties to fields as a source for field names. Instead, this commit uses the original list of fields to generate unset input values, which correctly provides values for fields which shared a property name but didn't receive the final binding.
Currently, the template type-checker gives an error if there are multiple bindings to the same input. This commit aligns the behavior of the template type-checker with the View Engine runtime: only the first binding to a field has any effect. The rest are ignored.
Previously, when generating template type-checking code, casts to 'any' were produced as `expr as any`, regardless of the expression. However, for certain expression types, this led to precedence issues with the cast. For example, `a !== b` is a `ts.BinaryExpression`, and wrapping it directly in the cast yields `a !== b as any`, which is semantically equivalent to `a !== (b as any)`. This is obviously not what is intended. Instead, this commit adds a list of expression types for which a "bare" wrapping is permitted. For other expressions, parentheses are added to ensure correct precedence: `(a !== b) as any`
Previously, `ReferenceEmitter.emit()` took an `ImportMode` enum value, where one value of the enum allowed forcing new imports to be generated when emitting a reference to some value or type. This commit refactors `ImportMode` to be an `ImportFlags` value instead. Using a bit field of flags will allow future customization of reference emitting.
258d41b
to
4d59c99
Compare
Done :) |
FileToModuleHost aliasing supports compilation within environments that have two properties: 1. A `FileToModuleHost` exists which defines canonical module names for any given TS file. 2. Dependency restrictions exist which prevent the import of arbitrary files even if such files are within the .d.ts transitive closure of a compilation ("strictdeps"). In such an environment, generated imports can only go through import paths which are already present in the user program. The aliasing system supports the generation and consumption of such imports at runtime. `FileToModuleHost` aliasing does not emit re-exports in .d.ts files. This means that it's safe to rely on alias re-exports in generated .js code (they are guaranteed to exist at runtime) but not in template type-checking code (since TS will not be able to follow such imports). Therefore, non-aliased imports should be used in template type-checking code. This commit adds a `NoAliasing` flag to `ImportFlags` and sets it when generating imports in template type-checking code. The testing environment is also patched to support resolution of FileToModuleHost canonical paths within the template type-checking program, enabling testing of this change.
Previously, the template type-checker would always construct a generic template context type with correct bounds, even when strictTemplates was disabled. This meant that type-checking of expressions involving that type was stricter than View Engine. This commit introduces a 'strictContextGenerics' flag which behaves similarly to other 'strictTemplates' flags, and switches the inference of generic type parameters on the component context based on the value of this flag.
4d59c99
to
fba022e
Compare
…34649) It's possible to declare multiple inputs for a directive/component which all map to the same property name. This is usually done in error, as only one of any bindings to the property will "win". In the template type-checker, an error was previously being raised as a result of this ambiguity. Specifically, a type constructor was produced which required a binding for each field, but only one of the fields had a value via the binding. TypeScript would (rightfully) error on missing values for the remaining fields. This ultimately was happening when the code which generated the default values for "unset" inputs belonging to directives or pipes used the final mapping from properties to fields as a source for field names. Instead, this commit uses the original list of fields to generate unset input values, which correctly provides values for fields which shared a property name but didn't receive the final binding. PR Close #34649
Currently, the template type-checker gives an error if there are multiple bindings to the same input. This commit aligns the behavior of the template type-checker with the View Engine runtime: only the first binding to a field has any effect. The rest are ignored. PR Close #34649
Previously, when generating template type-checking code, casts to 'any' were produced as `expr as any`, regardless of the expression. However, for certain expression types, this led to precedence issues with the cast. For example, `a !== b` is a `ts.BinaryExpression`, and wrapping it directly in the cast yields `a !== b as any`, which is semantically equivalent to `a !== (b as any)`. This is obviously not what is intended. Instead, this commit adds a list of expression types for which a "bare" wrapping is permitted. For other expressions, parentheses are added to ensure correct precedence: `(a !== b) as any` PR Close #34649
Previously, `ReferenceEmitter.emit()` took an `ImportMode` enum value, where one value of the enum allowed forcing new imports to be generated when emitting a reference to some value or type. This commit refactors `ImportMode` to be an `ImportFlags` value instead. Using a bit field of flags will allow future customization of reference emitting. PR Close #34649
FileToModuleHost aliasing supports compilation within environments that have two properties: 1. A `FileToModuleHost` exists which defines canonical module names for any given TS file. 2. Dependency restrictions exist which prevent the import of arbitrary files even if such files are within the .d.ts transitive closure of a compilation ("strictdeps"). In such an environment, generated imports can only go through import paths which are already present in the user program. The aliasing system supports the generation and consumption of such imports at runtime. `FileToModuleHost` aliasing does not emit re-exports in .d.ts files. This means that it's safe to rely on alias re-exports in generated .js code (they are guaranteed to exist at runtime) but not in template type-checking code (since TS will not be able to follow such imports). Therefore, non-aliased imports should be used in template type-checking code. This commit adds a `NoAliasing` flag to `ImportFlags` and sets it when generating imports in template type-checking code. The testing environment is also patched to support resolution of FileToModuleHost canonical paths within the template type-checking program, enabling testing of this change. PR Close #34649
…34649) Previously, the template type-checker would always construct a generic template context type with correct bounds, even when strictTemplates was disabled. This meant that type-checking of expressions involving that type was stricter than View Engine. This commit introduces a 'strictContextGenerics' flag which behaves similarly to other 'strictTemplates' flags, and switches the inference of generic type parameters on the component context based on the value of this flag. PR Close #34649
Currently, the template type-checker gives an error if there are multiple bindings to the same input. This commit aligns the behavior of the template type-checker with the View Engine runtime: only the first binding to a field has any effect. The rest are ignored. PR Close #34649
Previously, when generating template type-checking code, casts to 'any' were produced as `expr as any`, regardless of the expression. However, for certain expression types, this led to precedence issues with the cast. For example, `a !== b` is a `ts.BinaryExpression`, and wrapping it directly in the cast yields `a !== b as any`, which is semantically equivalent to `a !== (b as any)`. This is obviously not what is intended. Instead, this commit adds a list of expression types for which a "bare" wrapping is permitted. For other expressions, parentheses are added to ensure correct precedence: `(a !== b) as any` PR Close #34649
Previously, `ReferenceEmitter.emit()` took an `ImportMode` enum value, where one value of the enum allowed forcing new imports to be generated when emitting a reference to some value or type. This commit refactors `ImportMode` to be an `ImportFlags` value instead. Using a bit field of flags will allow future customization of reference emitting. PR Close #34649
FileToModuleHost aliasing supports compilation within environments that have two properties: 1. A `FileToModuleHost` exists which defines canonical module names for any given TS file. 2. Dependency restrictions exist which prevent the import of arbitrary files even if such files are within the .d.ts transitive closure of a compilation ("strictdeps"). In such an environment, generated imports can only go through import paths which are already present in the user program. The aliasing system supports the generation and consumption of such imports at runtime. `FileToModuleHost` aliasing does not emit re-exports in .d.ts files. This means that it's safe to rely on alias re-exports in generated .js code (they are guaranteed to exist at runtime) but not in template type-checking code (since TS will not be able to follow such imports). Therefore, non-aliased imports should be used in template type-checking code. This commit adds a `NoAliasing` flag to `ImportFlags` and sets it when generating imports in template type-checking code. The testing environment is also patched to support resolution of FileToModuleHost canonical paths within the template type-checking program, enabling testing of this change. PR Close #34649
…34649) Previously, the template type-checker would always construct a generic template context type with correct bounds, even when strictTemplates was disabled. This meant that type-checking of expressions involving that type was stricter than View Engine. This commit introduces a 'strictContextGenerics' flag which behaves similarly to other 'strictTemplates' flags, and switches the inference of generic type parameters on the component context based on the value of this flag. PR Close #34649
…ngular#34649) It's possible to declare multiple inputs for a directive/component which all map to the same property name. This is usually done in error, as only one of any bindings to the property will "win". In the template type-checker, an error was previously being raised as a result of this ambiguity. Specifically, a type constructor was produced which required a binding for each field, but only one of the fields had a value via the binding. TypeScript would (rightfully) error on missing values for the remaining fields. This ultimately was happening when the code which generated the default values for "unset" inputs belonging to directives or pipes used the final mapping from properties to fields as a source for field names. Instead, this commit uses the original list of fields to generate unset input values, which correctly provides values for fields which shared a property name but didn't receive the final binding. PR Close angular#34649
Currently, the template type-checker gives an error if there are multiple bindings to the same input. This commit aligns the behavior of the template type-checker with the View Engine runtime: only the first binding to a field has any effect. The rest are ignored. PR Close angular#34649
Previously, when generating template type-checking code, casts to 'any' were produced as `expr as any`, regardless of the expression. However, for certain expression types, this led to precedence issues with the cast. For example, `a !== b` is a `ts.BinaryExpression`, and wrapping it directly in the cast yields `a !== b as any`, which is semantically equivalent to `a !== (b as any)`. This is obviously not what is intended. Instead, this commit adds a list of expression types for which a "bare" wrapping is permitted. For other expressions, parentheses are added to ensure correct precedence: `(a !== b) as any` PR Close angular#34649
Previously, `ReferenceEmitter.emit()` took an `ImportMode` enum value, where one value of the enum allowed forcing new imports to be generated when emitting a reference to some value or type. This commit refactors `ImportMode` to be an `ImportFlags` value instead. Using a bit field of flags will allow future customization of reference emitting. PR Close angular#34649
…34649) FileToModuleHost aliasing supports compilation within environments that have two properties: 1. A `FileToModuleHost` exists which defines canonical module names for any given TS file. 2. Dependency restrictions exist which prevent the import of arbitrary files even if such files are within the .d.ts transitive closure of a compilation ("strictdeps"). In such an environment, generated imports can only go through import paths which are already present in the user program. The aliasing system supports the generation and consumption of such imports at runtime. `FileToModuleHost` aliasing does not emit re-exports in .d.ts files. This means that it's safe to rely on alias re-exports in generated .js code (they are guaranteed to exist at runtime) but not in template type-checking code (since TS will not be able to follow such imports). Therefore, non-aliased imports should be used in template type-checking code. This commit adds a `NoAliasing` flag to `ImportFlags` and sets it when generating imports in template type-checking code. The testing environment is also patched to support resolution of FileToModuleHost canonical paths within the template type-checking program, enabling testing of this change. PR Close angular#34649
…ngular#34649) Previously, the template type-checker would always construct a generic template context type with correct bounds, even when strictTemplates was disabled. This meant that type-checking of expressions involving that type was stricter than View Engine. This commit introduces a 'strictContextGenerics' flag which behaves similarly to other 'strictTemplates' flags, and switches the inference of generic type parameters on the component context based on the value of this flag. PR Close angular#34649
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. |
This is a batch PR fixing several template type-checking issues that were discovered in the g3 codebase:
@Input('x') x; @Input('x') y;
for example (amazingly, this is not an error).[x]="..." [x]="..."
).as any
casts generated by the template type-checker in certain cases (a ? b : c as any
was previously generated where the intent was(a ? b : c) as any
).Component<T>
hasT
inferred asany
unlessstrictTemplates
is enabled.