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(ivy): @NgModule -> ngInjectorDef compilation #22458
Conversation
You can preview ce81cfd at https://pr22458-ce81cfd.ngbuilds.io/. |
You can preview 3d53b4f at https://pr22458-3d53b4f.ngbuilds.io/. |
You can preview 23a7543 at https://pr22458-23a7543.ngbuilds.io/. |
packages/bazel/src/ng_module.bzl
Outdated
outputs = COMMON_OUTPUTS, | ||
) | ||
|
||
ivy_ng_module = rule( |
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.
Leave comments behind to remove this once https://github.com/angular/angular/pull/22480/files#diff-80f32f4427df4c91c1fe4d9d821d9338R739 is done.
@@ -32,6 +33,13 @@ import {DTS, GENERATED_FILES, StructureIsReused, TS, createMessageDiagnostic, is | |||
*/ | |||
const MAX_FILE_COUNT_FOR_SINGLE_FILE_EMIT = 20; | |||
|
|||
const IVY_DECORATORS = [ |
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.
=> CLASS_LEVEL_DECORATORS
or something which does not have ivy
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.
consider stripping all decorators.
packages/core/src/di/injector.ts
Outdated
|
||
export const SOURCE = '__source'; | ||
const _THROW_IF_NOT_FOUND = new Object(); | ||
export const THROW_IF_NOT_FOUND = _THROW_IF_NOT_FOUND; | ||
interface HasInjectableDef<T> { |
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.
InjectableType<T> extends Type<T> {
}
packages/core/src/di/injector.ts
Outdated
|
||
export const SOURCE = '__source'; | ||
const _THROW_IF_NOT_FOUND = new Object(); | ||
export const THROW_IF_NOT_FOUND = _THROW_IF_NOT_FOUND; | ||
interface HasInjectableDef<T> { | ||
ngInjectableDef: { |
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.
pull this out to interface InjectableDef
packages/core/src/di/injector.ts
Outdated
type InjectableDefType<T> = Type<T>& HasInjectableDef<T>; | ||
type InjectableDefToken<T> = InjectionToken<T>& HasInjectableDef<T>; | ||
|
||
type IvyProvider = InjectableDefType<any>| IvyDeepProvider; |
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.
Try not to have code names in types.
packages/core/src/di/r3_injector.ts
Outdated
* found in the LICENSE file at https://angular.io/license | ||
*/ | ||
|
||
import {Type} from '../type'; |
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.
delete
1d0a481
to
0507b2b
Compare
You can preview 0507b2b at https://pr22458-0507b2b.ngbuilds.io/. |
You can preview d85bcf6 at https://pr22458-d85bcf6.ngbuilds.io/. |
You can preview b10cc11 at https://pr22458-b10cc11.ngbuilds.io/. |
bf92046
to
e3bf36c
Compare
You can preview bf92046 at https://pr22458-bf92046.ngbuilds.io/. |
You can preview e3bf36c at https://pr22458-e3bf36c.ngbuilds.io/. |
You can preview 721bf7c at https://pr22458-721bf7c.ngbuilds.io/. |
You can preview 3864720 at https://pr22458-3864720.ngbuilds.io/. |
You can preview 2b32ed9 at https://pr22458-2b32ed9.ngbuilds.io/. |
shouldLower(node)) { | ||
lowerable = true; | ||
} | ||
if (isLiteralFieldNamed(node, this.lowerableFieldNames) && shouldLower(node) && |
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.
else
. It seems pointless to look at these if we already know lowerable
is true.
return lowerable; | ||
}; | ||
|
||
hasLowerableParent = (node: ts.Node | undefined): boolean => { |
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 logic seems backwards to me. Consider, instead, taking !hasLowerableParent(node)
out of isLowerable
and call it shouldBeLowered
instead. The isLowerable
is simply isShouldBeLowered && !alreadyLowered(node)
where !alreadyLowered
returns true if it is in a tree that is being lowered (that is it has a parent nod that is being lowered). Mutually recursive calls make my head hurt.
@@ -32,6 +33,14 @@ import {DTS, GENERATED_FILES, StructureIsReused, TS, createMessageDiagnostic, is | |||
*/ | |||
const MAX_FILE_COUNT_FOR_SINGLE_FILE_EMIT = 20; | |||
|
|||
// TODO(alxhub): develop a way to track the origin of metadata annotations and make this robust. |
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.
Why can't we do this before this commit?
@@ -32,6 +33,14 @@ import {DTS, GENERATED_FILES, StructureIsReused, TS, createMessageDiagnostic, is | |||
*/ | |||
const MAX_FILE_COUNT_FOR_SINGLE_FILE_EMIT = 20; | |||
|
|||
// TODO(alxhub): develop a way to track the origin of metadata annotations and make this robust. | |||
const R3_REIFIED_DECORATORS = [ | |||
'Component', |
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.
These should be StaticSymbol
s and they are already known by the StaticReflector
you just need to ask for them.
@@ -99,7 +108,12 @@ class AngularCompilerProgram implements Program { | |||
this.host = bundleHost; | |||
} | |||
} | |||
this.loweringMetadataTransform = new LowerMetadataTransform(); | |||
|
|||
const lowerFields = ['useValue', 'useFactory', 'data']; |
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.
I would prefer two constants LOWER_FIELDS
and IVY_LOWER_FIELDS
and the if
selects which to use (or use a ternary operator).
@@ -235,7 +249,8 @@ class AngularCompilerProgram implements Program { | |||
0) { | |||
return {emitSkipped: true, diagnostics: [], emittedFiles: []}; | |||
} | |||
const modules = this.compiler.emitAllPartialModules(this.analyzedModules); | |||
const modules = | |||
this.compiler.emitAllPartialModules(this.analyzedModules, this._analyzedInjectables !); |
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 include a comment explaining why the !
is safe.
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.
Done
}; | ||
type MapLiteral = MapEntry[]; | ||
|
||
function mapEntry(key: string, value: o.Expression): MapEntry { |
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.
We should put this in a more generate location and then refactor the other code to use it.
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.
Done.
} | ||
|
||
function toMapLiteral(obj: {[key: string]: o.Expression}): o.Expression { | ||
return o.literalMap(Object.keys(obj).map(key => ({ |
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.
Same 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.
Done.
} else if (meta == null) { | ||
return o.literal(meta); | ||
} else { | ||
throw new Error(`Unsupported or unknown metadata: ${meta}`); |
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.
Prefix with "Internal error: "
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.
Done.
} | ||
|
||
function convertMetaToOutput(meta: any, ctx: OutputContext): o.Expression { | ||
if (Array.isArray(meta)) { |
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.
Same 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.
Will do in a future PR.
You can preview ecfb9fb at https://pr22458-ecfb9fb.ngbuilds.io/. |
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.
- We discussed that
inject
should work in cases where there is no injector present ifprovidedIn: 'root'
. Were you planning on implementing it here, or on next PR? - Could you add a
js_expected_symbol_test
test (see example inpackages/core/test/bundling/hello_world/BUILD.bazel
. The test should create an injector usingcreateInjector()
and than try to inject something. It should that verify that all other values get tree shaken away. - Also could you clean up
packages/core/test/render3/compiler_canonical/pending_api_spec.ts
NOTE: These could be done in follow on PRs.
const R3_LOWER_FIELDS = [...LOWER_FIELDS, 'providers', 'imports', 'exports']; | ||
|
||
const R3_REIFIED_DECORATORS = [ | ||
'Component', |
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.
Should Pipe
be included in this list?
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.
Yes, and I can do that.
@@ -0,0 +1,408 @@ | |||
/** |
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.
I don't see r3_injector_spec.ts
. Where are the tests for this?
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.
Renamed definition_injector_spec.ts
to r3_injector_spec.ts
|
||
describe('InjectorDef-based createInjector()', () => { | ||
class CircularA { | ||
static ngInjectableDef = { |
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.
why not use defineInjectable
API here? (and throughout the file)
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.
Done.
packages/core/src/di/r3_injector.ts
Outdated
* Flag indicating this injector provides the APP_ROOT_SCOPE token, and thus counts as the | ||
* root scope. | ||
*/ | ||
private readonly isRootScope: boolean; |
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.
Should probably change the name to isRootInjector
????
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.
Done.
@@ -0,0 +1,208 @@ | |||
/** |
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 like r3_injector_spec.ts
?
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.
Renamed.
const instance = injector.get(Service); | ||
expect(instance instanceof Service).toBeTruthy(); | ||
expect(injector.get(Service)).toBe(instance); | ||
}); |
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.
nit: cat we have blank like between it
and rest of file.
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.
Done.
|
||
/** @experimental */ | ||
export interface InjectableType<T> extends Type<T> { | ||
export interface InjectableDefType<T> extends Type<T> { |
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.
I think this should be InjectableType
(no Def
)
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.
Done.
You can preview fc03f68 at https://pr22458-fc03f68.ngbuilds.io/. |
You can preview 2b653cc at https://pr22458-2b653cc.ngbuilds.io/. |
You can preview cbb84c7 at https://pr22458-cbb84c7.ngbuilds.io/. |
You can preview 285665f at https://pr22458-285665f.ngbuilds.io/. |
cc3a4dd
to
b44118b
Compare
You can preview b44118b at https://pr22458-b44118b.ngbuilds.io/. |
5da234e
to
a96efda
Compare
You can preview 5da234e at https://pr22458-5da234e.ngbuilds.io/. |
You can preview a96efda at https://pr22458-a96efda.ngbuilds.io/. |
This adds compilation of @NgModule providers and imports into ngInjectorDef statements in generated code. All @NgModule annotations will be compiled and the @NgModule decorators removed from the resultant js output. All @Injectables will also be compiled in Ivy mode, and the decorator removed.
You can preview 92fa681 at https://pr22458-92fa681.ngbuilds.io/. |
This adds compilation of @NgModule providers and imports into ngInjectorDef statements in generated code. All @NgModule annotations will be compiled and the @NgModule decorators removed from the resultant js output. All @Injectables will also be compiled in Ivy mode, and the decorator removed. PR Close angular#22458
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 adds compilation of @NgModule providers and imports into
ngInjectorDef statements in generated code. All @NgModule annotations
will be compiled and the @NgModule decorators removed from the
resultant js output.
All @Injectables will also be compiled in Ivy mode, and the decorator
removed.
PR Checklist
Please check if your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
What is the current behavior?
Issue Number: N/A
What is the new behavior?
Does this PR introduce a breaking change?
Other information