revert: docs(ivy): update STATUS.md with compiler work breakdown (#22874)

This reverts commit b524e4b142.
This commit is contained in:
Matias Niemelä 2018-03-22 18:09:45 -04:00
parent bb58664b13
commit d77bb460b0
2 changed files with 89 additions and 254 deletions

View File

@ -1,92 +0,0 @@
# Metadata storage in `.d.ts` files
Currently angular stores metadata in `.metadata.json` files. This is problematic for several reasons:
- Error prone (tools have to know how to work with them.)
- Metadata does not follow import/exports.
- Complicated to explain, maintain.
- Hard for 3rd party contributors to add value.
For Ivy we will be storing the metadata directly in `.d.ts` in the form of type information. This has several advantages:
- TypeScript does most of the work of resolution
- 3rd party developers already understand `.d.ts` as well as TypeScript type system.
The key information which Ivy needs is the selector information. That is what pipe, component or directive has to be inserted at which location. These selector maps are declared in `@NgModule` annotations. Therefore the goal is to store: selectors and `@NgModule` import/exports rules.
Let's assume that we have a file such as:
```javascript
@Pipe({ name: 'myPipe' })
export class MyPipe { }
@Component({ selector: `my-component` })
export class MyComponent { }
@Component({ selector: `[myDirective]` })
export class MyDirective { }
@NgModule({
declarations: [MyDirective, MyPipe],
exports: [MyDirective, MyPipe]
})
export class MyModule { }
@NgModule({
declarations: [MyComponent],
imports: [MyModule],
exports: [MyComponent],
})
export class MyAppModule { }
```
Then we can encode the selector information into the types as shown in this `.d.ts` file:
```javascript
export class MyPipe {
static ngPipeDef: PipeDef<{type: MyPipe, selector: 'myPipe'}>;
}
export class MyComponent {
static ngComponentDef: ComponentDef<{type: MyComponent, selector: 'my-component'}>;
}
export class MyDirective {
static ngDirectiveDef: DirectiveDef<{type: MyDirective, selector: '[myDirective]'}>;
}
export class MyModule {
static ngInjectorDef: InjectorDef<MyAppModule>;
static ngModule = {
type: MyModule,
imports: [],
exports: [MyDirective, MyPipe]
};
}
export class MyAppModule {
static ngModule = {
type: MyAppModule,
imports: [MyModule],
exports: [MyComponent]
};
}
```
This means that `ngtsc` can extract selector information from `Program` by having TypeScript resolving the types and then doing walking the resolved AST. This would be equivalent to something like this in code:
```javascript
const MyComponent_selector /* inferred type: 'my-component' */ = getSelector(MyComponent);
const MyDirective_selector /* inferred type: '[myDirective]' */ = getSelector(MyDirective);
const MyPipe_selector /* inferred type: 'myPipe' */ = getSelector(MyPipe);
const MyModule_exports /* inferred type: typeof MyDirective | typeof MyPipe */ =
getNgModuleExports(MyModule);
const MyAppModule_imports /* inferred type: typeof MyModule */ = getNgModuleImports(MyAppModule);
const MyAppModule_transitive_imports /* inferred type: typeof MyDirective | typeof MyPipe */ =
getNgModuleExports(MyAppModule_imports);
declare function getNgModuleExports<T>(module: {ngModule: {exports: T[]}}): T;
declare function getNgModuleImports<T>(module: {ngModule: {imports: T[]}}): T;
declare function getSelector<T>(componentType: {
ngComponentDef?: ComponentDef<{selector: T}>,
ngDirectiveDef?: DirectiveDef<{selector: T}>,
ngPipeDef?: PipeDef<{selector: T}>,
}): T;
````

View File

@ -8,79 +8,7 @@ We currently expect Ivy to remain behind the flag until it's feature complete an
# Implementation Status
The work can be divided into three categories:
- `@angular/compiler-cli`: TypeScript transformer pipeline which includes two command line tools:
- `ngtsc`: (Angular TypeScript Compiler) Angular compiler which strips out `@Component` (and friends) and replaces it with `defineComponent` (and friends).
- `ngcc`: (Angular Compatibility Compiler) NPM upgrade compiler which reads the `.metadata.json` files and `.js` files and adds `defineComponent` (and friends) into the `node_module`. This in effect converts a pre-ivy module into ivy module.
- `@angular/compiler`: Ivy Compiler which converts decorator into ivy
- `@angular/core`: Decorators which can be patched with `@angular/compiler`.
## `@angular/compiler-cli` changes
### `ngtsc` TSC compiler transformer
TSC transformer which removes and converts `@Pipe`, `@Component`, `@Directive` and `@NgModule`
to the corresponding `definePipe`, `defineComponent`, `defineDirective` and `defineInjector`.
- ❌ Basic setup of the transformer into `tsc`
- ❌ Can read metadata from `.d.ts` (see: [METADATA.md](./METADATA.md))
- ❌ Detect decorators and convert them to the `defineXXX` method using the `__Compiler` in `@angular/compiler`.
- ❌ `@Pipe` => `definePipe`
- ❌ `@Component` => `defineComponent`
- ❌ `@Directive` => `defineDirective`
- ❌ `@NgModule` => `defineInjector`
- ❌ Encode selectors into `.d.ts` file.
- ❌ `@Pipe` => see [METADATA.md](./METADATA.md)
- ❌ `@Component` => see [METADATA.md](./METADATA.md)
- ❌ `@Directive` => see [METADATA.md](./METADATA.md)
- ❌ `@NgModule` => see [METADATA.md](./METADATA.md)
- ❌ support `extends` for `@Pipe`, `@Component`, `@Directive` and `@NgModule`.
- ❌ Documentation
### `ngcc` Angular `node_module` compatibility compiler
A tool which "upgrades" `node_module` compiled with non-ivy `ngc` into ivy compliant format.
- ❌ Basic setup of stand alone executable
- ❌ Integration with WebPack (cli)
- ❌ Rewrite existing code by interpreting the associated metadata
- ❌ `PipeCompiler`: `@Pipe` => `definePipe`
- ❌ `DirectiveCompiler`: `@Directive` => `defineDirective`
- ❌ `NgModuleCompiler`: `@NgModule` => `defineInjector`
- ❌ `ComponentCompiler`: `@Component` => `defineComponent`
- ❌ `TemplateCompiler`
- ❌ `StyleCompiler`
- ❌ Documentation
## `@angular/compiler` changes
- ❌ Component compilation: Translates `@Component` => `defineComponent`
- ❌ `TemplateCompiler` (current known as `ViewCompiler`)
- ❌ `StyleCompiler`
- ❌ `PipeCompiler`: Translates `@Pipe` => `definePipe`
- ❌ `DirectiveCompiler`: Translates `@Directive` => `defineDirective`
- ❌ `InjectableCompiler`: Translates `@Injectable` => `defineInjectable`
- ❌ `NgModuleCompiler`: Translates `@NgModule` => `defineInjector` (and `defineNgModule` only in jit)
- ❌ Documentation
## `@angular/core` changes
The goal is for the `@Component` (and friends) to be the compiler of template. Since decorators are functions which execute during parsing of the `.js` file, the decorator can compile the template into Ivy. The AoT compiler's job is to remove the `@Component` and replace it with call to `defineComponent`.
- ❌ Remove `createDecorator` (and friends) since we no longer support other modes.
- ❌ `@angular/compiler` can patch itself onto:
- ❌ `@Injectable`
- ❌ `@NgModule`
- ❌ `@Pipe`
- ❌ `@Directive`
- ❌ `@Component`
- ❌ `ResourceLoader.resolved: Promise<>` Returns true if all `templateUrl`s and `styleUrl` have been resolved and application is ready to be bootstrapped.
# Crosscutting
## Decorators
## Annotations
| Annotation | `defineXXX()` | Run time | Spec | Compiler | Back Patch |
| -------------------- | ------------------------------ | ------- | -------- | -------- | -------- |
| `@Component` | ✅ `defineComponent()` | ✅ | ✅ | ✅ | ❌ |
@ -103,6 +31,86 @@ The goal is for the `@Component` (and friends) to be the compiler of template. S
## Life Cycle Hooks
| Feature | Runtime | Spec | Compiler |
| ------------------------- | ------- | -------- | -------- |
| `onChanges()` | ✅ | ✅ | ✅ |
| `onDestroy()` | ✅ | ✅ | ✅ |
| `onInit()` | ✅ | ✅ | ✅ |
| `onChanges()` | ✅ | ✅ | ✅ |
| `doCheck()` | ✅ | ✅ | ✅ |
| `afterViewChecked()` | ✅ | ✅ | ✅ |
| `afterViewInit()` | ✅ | ✅ | ✅ |
| `afterContentChecked()` | ✅ | ✅ | ✅ |
| `afterContentInit()` | ✅ | ✅ | ✅ |
| listener teardown | ✅ | ✅ | ✅ |
## Template Syntax
| Feature | Runtime | Spec | Compiler |
| -------------------------------- | ------- | -------- | -------- |
| `<div>` | ✅ | ✅ | ✅ |
| `<div>{{exp}}</div>` | ✅ | ✅ | ✅ |
| `<div attr=value>` | ✅ | ✅ | ✅ |
| `<div (click)="stmt">` | ✅ | ✅ | ✅ |
| `<div #foo>` | ✅ | ✅ | ✅ |
| `<div #foo="bar">` | ✅ | ✅ | ✅ |
| `<div [value]="exp">` | ✅ | ✅ | ✅ |
| `<div title="Hello {{name}}!">` | ✅ | ✅ | ✅ |
| `<div [attr.value]="exp">` | ✅ | ✅ | ❌ |
| `<div class="literal">` | ✅ | ✅ | ✅ |
| `<div [class]="exp">` | ❌ | ❌ | ❌ |
| `<div [class.foo]="exp">` | ✅ | ✅ | ❌ |
| `<div style="literal">` | ✅ | ✅ | ✅ |
| `<div [style]="exp">` | ❌ | ❌ | ❌ |
| `<div [style.foo]="exp">` | ✅ | ✅ | ❌ |
| `{{ ['literal', exp ] }}` | ✅ | ✅ | ✅ |
| `{{ { a: 'literal', b: exp } }}` | ✅ | ✅ | ✅ |
| `{{ exp \| pipe: arg }}` | ✅ | ✅ | ✅ |
## `@Query`
| Feature | Runtime | Spec | Compiler |
| ------------------------------- | ------- | -------- | -------- |
| `@Query(descendants)` | ✅ | ✅ | n/a |
| `@Query(one)` | ✅ | ✅ | n/a |
| `@Query(read)` | ✅ | ✅ | n/a |
| `@Query(selector)` | ✅ | ✅ | n/a |
| `@Query(Type)` | ✅ | ✅ | n/a |
| `@ContentChildred` | ✅ | ✅ | ❌ |
| `@ContentChild` | ✅ | ✅ | ✅ |
| `@ViewChildren` | ✅ | ✅ | ❌ |
| `@ViewChild` | ✅ | ✅ | ✅ |
## Content Projection
| Feature | Runtime | Spec | Compiler |
| ------------------------------- | ------- | -------- | -------- |
| `<ng-content>` | ✅ | ✅ | ✅ |
| `<ng-content selector="...">` | ✅ | ✅ | ✅ |
| container `projectAs` | ✅ | ✅ | ❌ |
## Injection Features
| Feature | Runtime | Spec | Compiler |
| ----------------------------------- | ------- | -------- | -------- |
| `inject(Type)` | ✅ | ✅ | ✅ |
| `directiveInject(Type)` | ✅ | ✅ | ❌ |
| `inject(Type, SkipSelf)` | ❌ | ❌ | ❌ |
| `attribute('name')` | ✅ | ✅ | ❌ |
| `injectChangeDetectionRef()` | ✅ | ✅ | ❌ |
| `injectElementRef()` | ✅ | ✅ | ✅ |
| `injectViewContainerRef()` | ✅ | ✅ | ✅ |
| `injectTemplateRef()` | ✅ | ✅ | ✅ |
| default `inject()` with no injector | ❌ | ❌ | ❌ |
| sanitization with no injector | ✅ | ✅ | ❌ |
## Change Detection
| Feature | Runtime |
| ----------------------------------- | ------- |
@ -123,90 +131,11 @@ The goal is for the `@Component` (and friends) to be the compiler of template. S
| ----------------------------------- | ------- |
| `renderComponent()` | ✅ |
| `getHostElement()` | ✅ |
| `createInjector()` | ✅ |
## Template Compiler
### Template Syntax
| Feature | Runtime | Spec | Compiler |
| --------------------------------------- | ------- | -------- | -------- |
| `<div>` | ✅ | ✅ | ✅ |
| `<div>{{exp}}</div>` | ✅ | ✅ | ✅ |
| `<div attr=value>` | ✅ | ✅ | ✅ |
| `<div (click)="stmt">` | ✅ | ✅ | ✅ |
| `<div #foo>` | ✅ | ✅ | ✅ |
| `<div #foo="bar">` | ✅ | ✅ | ✅ |
| `<div [value]="exp">` | ✅ | ✅ | ✅ |
| `<div title="Hello {{name}}!">` | ✅ | ✅ | ✅ |
| `<div [attr.value]="exp">` | ✅ | ✅ | ❌ |
| `<div class="literal">` | ✅ | ✅ | ✅ |
| `<div [class]="exp">` | ❌ | ❌ | ❌ |
| `<div [class.foo]="exp">` | ✅ | ✅ | ❌ |
| `<div style="literal">` | ✅ | ✅ | ✅ |
| `<div [style]="exp">` | ❌ | ❌ | ❌ |
| `<div [style.foo]="exp">` | ✅ | ✅ | ❌ |
| `{{ ['literal', exp ] }}` | ✅ | ✅ | ✅ |
| `{{ { a: 'literal', b: exp } }}` | ✅ | ✅ | ✅ |
| `{{ exp \| pipe: arg }}` | ✅ | ✅ | ✅ |
| `<svg:g svg:p>` | ❌ | ❌ | ❌ |
| `<img src=[userData]>` sanitization | ❌ | ❌ | ❌ |
### Life Cycle Hooks
| Feature | Runtime | Spec | Compiler |
| ------------------------- | ------- | -------- | -------- |
| `onChanges()` | ✅ | ✅ | ✅ |
| `onDestroy()` | ✅ | ✅ | ✅ |
| `onInit()` | ✅ | ✅ | ✅ |
| `onChanges()` | ✅ | ✅ | ✅ |
| `doCheck()` | ✅ | ✅ | ✅ |
| `afterViewChecked()` | ✅ | ✅ | ✅ |
| `afterViewInit()` | ✅ | ✅ | ✅ |
| `afterContentChecked()` | ✅ | ✅ | ✅ |
| `afterContentInit()` | ✅ | ✅ | ✅ |
| listener teardown | ✅ | ✅ | ✅ |
| `createInjector()` | ❌ |
### `@Query`
| Feature | Runtime | Spec | Compiler |
| ------------------------------- | ------- | -------- | -------- |
| `@Query(descendants)` | ✅ | ✅ | n/a |
| `@Query(one)` | ✅ | ✅ | n/a |
| `@Query(read)` | ✅ | ✅ | n/a |
| `@Query(selector)` | ✅ | ✅ | n/a |
| `@Query(Type)` | ✅ | ✅ | n/a |
| `@ContentChildred` | ✅ | ✅ | ❌ |
| `@ContentChild` | ✅ | ✅ | ✅ |
| `@ViewChildren` | ✅ | ✅ | ❌ |
| `@ViewChild` | ✅ | ✅ | ✅ |
### Content Projection
| Feature | Runtime | Spec | Compiler |
| ------------------------------- | ------- | -------- | -------- |
| `<ng-content>` | ✅ | ✅ | ✅ |
| `<ng-content selector="...">` | ✅ | ✅ | ✅ |
| container `projectAs` | ✅ | ✅ | ❌ |
### Injection Features
| Feature | Runtime | Spec | Compiler |
| ----------------------------------- | ------- | -------- | -------- |
| `inject(Type)` | ✅ | ✅ | ✅ |
| `directiveInject(Type)` | ✅ | ✅ | ❌ |
| `inject(Type, SkipSelf)` | ❌ | ❌ | ❌ |
| `attribute('name')` | ✅ | ✅ | ❌ |
| `injectChangeDetectionRef()` | ✅ | ✅ | ❌ |
| `injectElementRef()` | ✅ | ✅ | ✅ |
| `injectViewContainerRef()` | ✅ | ✅ | ✅ |
| `injectTemplateRef()` | ✅ | ✅ | ✅ |
| default `inject()` with no injector | ❌ | ❌ | ❌ |
| sanitization with no injector | ✅ | ✅ | ❌ |
### I18N
## I18N
| Feature | Runtime | Spec | Compiler |
| ----------------------------------- | ------- | -------- | -------- |
| translate text literals | ❌ | ❌ | ❌ |
@ -214,17 +143,10 @@ The goal is for the `@Component` (and friends) to be the compiler of template. S
| ICU | ❌ | ❌ | ❌ |
### View Encapsulation
| Feature | Runtime | Spec | Compiler |
| ----------------------------------- | ------- | -------- | -------- |
| Render3.None | ✅ | ✅ | ✅ |
| Render2.None | ✅ | ✅ | ✅ |
| Render2.Emulated | ❌ | ❌ | ❌ |
| Render2.Native | ❌ | ❌ | ❌ |
### `______Ref`s
## `______Ref`s
| Method | View Container Ref | Template Ref | Embeded View Ref | View Ref | Element Ref | Change Detection Ref |
| ---------------------- | ------------------ | ------------ | ---------------- | -------- | ----------- | -------------------- |
| `clear()` | ❌ | n/a | n/a | n/a | n/a | n/a |
@ -243,3 +165,8 @@ The goal is for the `@Component` (and friends) to be the compiler of template. S
| `checkNoChanges()` | n/a | n/a | ❌ | n/a | n/a | ✅ |
| `reattach()` | n/a | n/a | ❌ | n/a | n/a | ✅ |
| `nativeElement()` | n/a | n/a | n/a | n/a | ✅ | n/a |
## Missing Pieces
- Sanitization ✅
- Back patching in tree shakable way. ❌
- attribute namespace ❌