Skip to content
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

Closed
wants to merge 1 commit into from

Conversation

alxhub
Copy link
Member

@alxhub alxhub commented Feb 26, 2018

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?

[ ] Bugfix
[ ] Feature
[ ] Code style update (formatting, local variables)
[ ] Refactoring (no functional changes, no api changes)
[ ] Build related changes
[ ] CI related changes
[ ] Documentation content changes
[ ] angular.io application / infrastructure changes
[ ] Other... Please describe:

What is the current behavior?

Issue Number: N/A

What is the new behavior?

Does this PR introduce a breaking change?

[ ] Yes
[ ] No

Other information

@mary-poppins
Copy link

You can preview ce81cfd at https://pr22458-ce81cfd.ngbuilds.io/.

@mary-poppins
Copy link

You can preview 3d53b4f at https://pr22458-3d53b4f.ngbuilds.io/.

@mary-poppins
Copy link

You can preview 23a7543 at https://pr22458-23a7543.ngbuilds.io/.

outputs = COMMON_OUTPUTS,
)

ivy_ng_module = rule(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -32,6 +33,13 @@ import {DTS, GENERATED_FILES, StructureIsReused, TS, createMessageDiagnostic, is
*/
const MAX_FILE_COUNT_FOR_SINGLE_FILE_EMIT = 20;

const IVY_DECORATORS = [
Copy link
Contributor

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

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider stripping all decorators.


export const SOURCE = '__source';
const _THROW_IF_NOT_FOUND = new Object();
export const THROW_IF_NOT_FOUND = _THROW_IF_NOT_FOUND;
interface HasInjectableDef<T> {
Copy link
Contributor

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> {
}


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: {
Copy link
Contributor

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

type InjectableDefType<T> = Type<T>& HasInjectableDef<T>;
type InjectableDefToken<T> = InjectionToken<T>& HasInjectableDef<T>;

type IvyProvider = InjectableDefType<any>| IvyDeepProvider;
Copy link
Contributor

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.

* found in the LICENSE file at https://angular.io/license
*/

import {Type} from '../type';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delete

@alxhub alxhub force-pushed the injector-def branch 2 times, most recently from 1d0a481 to 0507b2b Compare February 28, 2018 23:51
@mary-poppins
Copy link

You can preview 0507b2b at https://pr22458-0507b2b.ngbuilds.io/.

@mary-poppins
Copy link

You can preview d85bcf6 at https://pr22458-d85bcf6.ngbuilds.io/.

@mary-poppins
Copy link

You can preview b10cc11 at https://pr22458-b10cc11.ngbuilds.io/.

@alxhub alxhub force-pushed the injector-def branch 2 times, most recently from bf92046 to e3bf36c Compare March 1, 2018 21:57
@mary-poppins
Copy link

You can preview bf92046 at https://pr22458-bf92046.ngbuilds.io/.

@mary-poppins
Copy link

You can preview e3bf36c at https://pr22458-e3bf36c.ngbuilds.io/.

@mary-poppins
Copy link

You can preview 721bf7c at https://pr22458-721bf7c.ngbuilds.io/.

@mary-poppins
Copy link

You can preview 3864720 at https://pr22458-3864720.ngbuilds.io/.

@mary-poppins
Copy link

You can preview 2b32ed9 at https://pr22458-2b32ed9.ngbuilds.io/.

@alxhub alxhub added action: merge The PR is ready for merge by the caretaker target: major This PR is targeted for the next major release labels Mar 2, 2018
shouldLower(node)) {
lowerable = true;
}
if (isLiteralFieldNamed(node, this.lowerableFieldNames) && shouldLower(node) &&
Copy link
Contributor

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 => {
Copy link
Contributor

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.
Copy link
Contributor

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',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be StaticSymbols 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'];
Copy link
Contributor

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 !);
Copy link
Contributor

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.

Copy link
Member Author

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 {
Copy link
Contributor

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.

Copy link
Member Author

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 => ({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

Copy link
Member Author

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}`);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefix with "Internal error: "

Copy link
Member Author

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)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

Copy link
Member Author

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.

@mary-poppins
Copy link

You can preview ecfb9fb at https://pr22458-ecfb9fb.ngbuilds.io/.

@angular angular deleted a comment from alxhub Mar 14, 2018
Copy link
Contributor

@mhevery mhevery left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. We discussed that inject should work in cases where there is no injector present if providedIn: 'root'. Were you planning on implementing it here, or on next PR?
  2. Could you add a js_expected_symbol_test test (see example in packages/core/test/bundling/hello_world/BUILD.bazel. The test should create an injector using createInjector() and than try to inject something. It should that verify that all other values get tree shaken away.
  3. 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',
Copy link
Contributor

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?

Copy link
Member Author

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 @@
/**
Copy link
Contributor

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?

Copy link
Member Author

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 = {
Copy link
Contributor

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)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

* Flag indicating this injector provides the APP_ROOT_SCOPE token, and thus counts as the
* root scope.
*/
private readonly isRootScope: boolean;
Copy link
Contributor

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????

Copy link
Member Author

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 @@
/**
Copy link
Contributor

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?

Copy link
Member Author

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);
});
Copy link
Contributor

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.

Copy link
Member Author

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> {
Copy link
Contributor

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)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@mary-poppins
Copy link

You can preview fc03f68 at https://pr22458-fc03f68.ngbuilds.io/.

@mary-poppins
Copy link

You can preview 2b653cc at https://pr22458-2b653cc.ngbuilds.io/.

@mary-poppins
Copy link

You can preview cbb84c7 at https://pr22458-cbb84c7.ngbuilds.io/.

@mary-poppins
Copy link

You can preview 285665f at https://pr22458-285665f.ngbuilds.io/.

@alxhub alxhub force-pushed the injector-def branch 2 times, most recently from cc3a4dd to b44118b Compare March 16, 2018 17:16
@mary-poppins
Copy link

You can preview b44118b at https://pr22458-b44118b.ngbuilds.io/.

@alxhub alxhub force-pushed the injector-def branch 2 times, most recently from 5da234e to a96efda Compare March 16, 2018 17:30
@mary-poppins
Copy link

You can preview 5da234e at https://pr22458-5da234e.ngbuilds.io/.

@mary-poppins
Copy link

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.
@mary-poppins
Copy link

You can preview 92fa681 at https://pr22458-92fa681.ngbuilds.io/.

@alxhub alxhub added the action: merge The PR is ready for merge by the caretaker label Mar 16, 2018
@mhevery mhevery closed this in 6ef9f22 Mar 16, 2018
leo6104 pushed a commit to leo6104/angular that referenced this pull request Mar 25, 2018
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
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 13, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker cla: yes target: major This PR is targeted for the next major release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants