docs(ivy): update STATUS.md with compiler work breakdown (#22874)
PR Close #22874
This commit is contained in:
parent
f88fba020b
commit
b524e4b142
|
@ -0,0 +1,92 @@
|
|||
# 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;
|
||||
````
|
|
@ -8,7 +8,79 @@ We currently expect Ivy to remain behind the flag until it's feature complete an
|
|||
|
||||
# Implementation Status
|
||||
|
||||
## Annotations
|
||||
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
|
||||
| Annotation | `defineXXX()` | Run time | Spec | Compiler | Back Patch |
|
||||
| -------------------- | ------------------------------ | ------- | -------- | -------- | -------- |
|
||||
| `@Component` | ✅ `defineComponent()` | ✅ | ✅ | ✅ | ❌ |
|
||||
|
@ -31,86 +103,6 @@ We currently expect Ivy to remain behind the flag until it's feature complete an
|
|||
|
||||
|
||||
|
||||
## 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 |
|
||||
| ----------------------------------- | ------- |
|
||||
|
@ -131,11 +123,90 @@ We currently expect Ivy to remain behind the flag until it's feature complete an
|
|||
| ----------------------------------- | ------- |
|
||||
| `renderComponent()` | ✅ |
|
||||
| `getHostElement()` | ✅ |
|
||||
| `createInjector()` | ❌ |
|
||||
| `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 | ✅ | ✅ | ✅ |
|
||||
|
||||
|
||||
|
||||
## I18N
|
||||
### `@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
|
||||
| Feature | Runtime | Spec | Compiler |
|
||||
| ----------------------------------- | ------- | -------- | -------- |
|
||||
| translate text literals | ❌ | ❌ | ❌ |
|
||||
|
@ -143,10 +214,17 @@ We currently expect Ivy to remain behind the flag until it's feature complete an
|
|||
| 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 |
|
||||
|
@ -165,8 +243,3 @@ We currently expect Ivy to remain behind the flag until it's feature complete an
|
|||
| `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 ❌
|
Loading…
Reference in New Issue