docs(ivy): update status.md (#26382)

PR Close #26382
This commit is contained in:
Miško Hevery 2018-10-10 14:57:04 -07:00
parent 7fbeb04b7c
commit 9ebb4c02a2
2 changed files with 108 additions and 70 deletions

View File

@ -11,7 +11,7 @@ We currently expect Ivy to remain behind the flag until it's feature complete an
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 `.STORING_METADATA_IN_D.TS.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.
- `ngcc`: (Angular Compatibility Compiler) NPM upgrade compiler which reads the `STORING_METADATA_IN_D.TS.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`.
@ -22,45 +22,31 @@ The work can be divided into three categories:
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 STORING_METADATA_IN_D.TS from `.d.ts` (see: [STORING_METADATA_IN_D.TS.md](./STORING_METADATA_IN_D.TS.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 [STORING_METADATA_IN_D.TS.md](./STORING_METADATA_IN_D.TS.md)
- ❌ `@Component` => see [STORING_METADATA_IN_D.TS.md](./STORING_METADATA_IN_D.TS.md)
- ❌ `@Directive` => see [STORING_METADATA_IN_D.TS.md](./STORING_METADATA_IN_D.TS.md)
- ❌ `@NgModule` => see [STORING_METADATA_IN_D.TS.md](./STORING_METADATA_IN_D.TS.md)
- ❌ support `extends` for `@Pipe`, `@Component`, `@Directive` and `@NgModule`.
- ✅ Basic setup of the transformer into `tsc`
- ✅ Can read STORING_METADATA_IN_D.TS from `.d.ts` (see: [STORING_METADATA_IN_D.TS.md](./STORING_METADATA_IN_D.TS.md))
- ✅ Detect decorators and convert them to the `defineXXX` method using the `__Compiler` in `@angular/compiler`.
- ✅ Encode selectors into `.d.ts` file.
- ✅ 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
- ✅ Basic setup of stand alone executable
- ✅ Rewrite existing code by interpreting the associated STORING_METADATA_IN_D.TS
- ❌ Integration with WebPack (cli)
- ❌ Rewrite existing code by interpreting the associated STORING_METADATA_IN_D.TS
- ❌ `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)
- ✅ 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
@ -68,40 +54,39 @@ A tool which "upgrades" `node_module` compiled with non-ivy `ngc` into ivy compl
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.
- ✅ `@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.
# Testing / Debugging
- in debug mode publish components into DOM nodes for easier debugging.
- in debug mode publish components into DOM nodes for easier debugging.
# Crosscutting
## Decorators
| Annotation | `defineXXX()` | Run time | Spec | Compiler | Back Patch |
| -------------------- | ------------------------------ | ------- | -------- | -------- | -------- |
| `@Component` | ✅ `defineComponent()` | ✅ | ✅ | ✅ | ❌ |
| `@Directive` | ✅ `defineDirective()` | ✅ | ✅ | ✅ | ❌ |
| `@Directive` | `defineAbstractDirective()` | ❌ | ❌ | ❌ | ❌ |
| `@Pipe` | ✅ `definePipe()` | ✅ | ✅ | ✅ | ❌ |
| `@Injectable` | ✅ `defineInjectable()` | ✅ | ❌ | ❌ | ❌ |
| `@NgModule` | ✅ `defineInjector()` | ✅ | ❌ | ❌ | ❌ |
| `@ConfigureInjector` | `defineInjector()` | ❌ | ❌ | ❌ | ❌ |
| Annotation | `defineXXX()` | Run time | Spec | Compiler |
| -------------------- | ------------------------------ | ------- | -------- | -------- |
| `@Component` | ✅ `defineComponent()` | ✅ | ✅ | ✅ |
| `@Directive` | ✅ `defineDirective()` | ✅ | ✅ | ✅ |
| `@Directive` | `defineBase()` | ✅ | ✅ | ✅ |
| `@Pipe` | ✅ `definePipe()` | ✅ | ✅ | ✅ |
| `@Injectable` | ✅ `defineInjectable()` | ✅ | ✅ | ✅ |
| `@NgModule` | ✅ `defineInjector()` | ✅ | ✅ | ✅ |
| `@ConfigureInjector` | `defineInjector()` | ❌ | ❌ | ❌ |
## Component Composition
| Feature | Runtime | Spec | Compiler |
| ---------------------------------------- | ------- | -------- | -------- |
| creation reordering based on injection | ❌ | ❌ | ✅ |
| `class CompA extends CompB {}` | ❌ | ❌ | ❌ |
| `class CompA extends CompB { @Input }` | ❌ | ❌ | ❌ |
| `class CompA extends CompB { @Output }` | ❌ | ❌ | ❌ |
| creation reordering based on injection | ✅ | ✅ | ✅ |
| `class CompA extends CompB {}` | ✅ | ✅ | ✅ |
| `class CompA extends CompB { @Input }` | ✅ | ✅ | ✅ |
| `class CompA extends CompB { @Output }` | ✅ | ✅ | ✅ |
@ -147,16 +132,12 @@ The goal is for the `@Component` (and friends) to be the compiler of template. S
| `<div style="literal">` | ✅ | ✅ | ✅ |
| `<div [style]="exp">` | ✅ | ✅ | ✅ |
| `<div [style.foo]="exp">` | ✅ | ✅ | ✅ |
| `<div xmlns:foo="url" foo:bar="baz">` <br/>Compiler still needs to be updated to process templates with namespaced attributes. ([see #24386](https://github.com/angular/angular/pull/24386)) | ✅ | ✅ | ❌ |
| `<div xmlns:foo="url" foo:bar="baz">` | ✅ | ✅ | ✅ |
| `{{ ['literal', exp ] }}` | ✅ | ✅ | ✅ |
| `{{ { a: 'literal', b: exp } }}` | ✅ | ✅ | ✅ |
| `{{ exp \| pipe: arg }}` | ✅ | ✅ | ✅ |
| `<svg:g svg:p>` | ✅ | ✅ | ✅ |
| `<img src=[userData]>` sanitization | ❌ | ❌ | ❌ |
| `<div (nocd.click)>` | ❌ | ❌ | ❌ |
| `<div (bubble.click)>` | ❌ | ❌ | ❌ |
| `<div (keyup.enter)>` | ❌ | ❌ | ❌ |
| `<div (hammer.js)>` | ❌ | ❌ | ❌ |
| `<img src=[userData]>` sanitization | ✅ | ✅ | ✅ |
| [`<div (directiveOut)>`][gh23560] | ✅ | ✅ | ✅ |
| [`<ng-template (directiveOut)>`][gh23561] | ✅ | ✅ | ✅ |
| [`<ng-container>`][gh24381] | ✅ | ✅ | ✅ |
@ -189,10 +170,10 @@ The goal is for the `@Component` (and friends) to be the compiler of template. S
| `@Query(read)` | ✅ | ✅ | n/a |
| `@Query(selector)` | ✅ | ✅ | n/a |
| `@Query(Type)` | ✅ | ✅ | n/a |
| `@ContentChildren` | ✅ | ✅ | |
| `@ContentChildren` | ✅ | ✅ | |
| `@ContentChild` | ✅ | ✅ | ✅ |
| `@ViewChildren` | ✅ | ✅ | |
| `@ViewChild` | ✅ | ✅ | |
| `@ViewChildren` | ✅ | ✅ | |
| `@ViewChild` | ✅ | ✅ | |
@ -201,7 +182,7 @@ The goal is for the `@Component` (and friends) to be the compiler of template. S
| ------------------------------- | ------- | -------- | -------- |
| `<ng-content>` | ✅ | ✅ | ✅ |
| `<ng-content selector="...">` | ✅ | ✅ | ✅ |
| container `projectAs` | ✅ | ✅ | ❌ |
| container `ngProjectAs` | ✅ | ✅ | ✅ |
@ -209,22 +190,22 @@ The goal is for the `@Component` (and friends) to be the compiler of template. S
| Feature | Runtime | Spec | Compiler |
| ----------------------------------- | ------- | -------- | -------- |
| `inject(Type)` | ✅ | ✅ | ✅ |
| `directiveInject(Type)` | ✅ | ✅ | |
| `directiveInject(Type)` | ✅ | ✅ | |
| `inject(Type, SkipSelf)` | ❌ | ❌ | ❌ |
| `attribute('name')` | ✅ | ✅ | ❌ |
| `injectChangeDetectionRef()` | ✅ | ✅ | |
| `injectChangeDetectionRef()` | ✅ | ✅ | |
| `injectElementRef()` | ✅ | ✅ | ✅ |
| `injectViewContainerRef()` | ✅ | ✅ | ✅ |
| `injectTemplateRef()` | ✅ | ✅ | ✅ |
| `injectRenderer2()` | ✅ | ✅ | ✅ |
| default `inject()` with no injector | ❌ | ❌ | ❌ |
| sanitization with no injector | ✅ | ✅ | |
| default `inject()` with no injector | ✅ | ✅ | ✅ |
| sanitization with no injector | ✅ | ✅ | |
### I18N
| Feature | Runtime | Spec | Compiler |
| ----------------------------------- | ------- | -------- | -------- |
| translate text literals | ✅ | ✅ | ✅ |
| translate text literals | ❌ | ❌ | ✅ |
| rearrange text nodes | ❌ | ❌ | ❌ |
| ICU | ❌ | ❌ | ❌ |
@ -232,10 +213,10 @@ The goal is for the `@Component` (and friends) to be the compiler of template. S
### View Encapsulation
| Feature | Runtime | Spec | Compiler |
| ----------------------------------- | ------- | -------- | -------- |
| Renderer3.None | | ✅ | ✅ |
| Renderer2.None | | ✅ | ✅ |
| Renderer2.Emulated | ❌ | ❌ | ❌ |
| Renderer2.Native | ❌ | ❌ | ❌ |
| Renderer3.None | | ✅ | ✅ |
| Renderer2.None | | ✅ | ✅ |
| Renderer2.Emulated | ✅ | ✅ | ✅ |
| Renderer2.Native | ✅ | ✅ | ✅ |

View File

@ -0,0 +1,57 @@
# Storing Metadata in `.d.ts` files
Previous version of Angular used `metadata.json` files to store information about directives/component/pipes/ng-modules.
`ngc` compiler would than do a global analysis to generate the `.ngfactory.ts` files from the `metadata.json`.
Ivy strives for locality, which means that `ngtsc` should not need any global information in order to compile the system.
The above is mostly true.
Unfortunately, in order for `ngtsc` to generate code which is tree shakable `ngtsc` does need to have global knowledge.
Here is an abbreviated example of breakage of tree-shake-ability.
```typescript
@Directive({
selector: '[tooltip]'
})
export class TooltipDirective {
// ngtsc generates this:
static ngDirectiveDef = defineDirective(...);
}
@Component({
selector: 'my-app',
template: 'Hello World!'
})
class MyAppComponent {
// ngtsc generates this:
static ngDirectiveDef = defineComponent({
...
directives: [
// BREAKS TREE-SHAKING!!!
// TooltipDirective included here because it was declared in the NgModule
// ngtsc does not know it can be omitted.
// Only way for ngtsc to know that it can omit TooltipDirective is if it knows
// its selector and see if the selector matches the current component's template.
TooltipDirective
]
});
}
@NgModule({
declarations: [MyAppComponent, TooltipDirective],
bootstrap: [MyAppComponent],
})
class MyAppModule {
// ngtsc generates this:
static ngDirectiveDef = defineNgModule(...);
}
```
Notice that `ngtsc` can't remove `TooltipDirective` because it would need to know its selector and see if the directive matches in the component's template.
Knowing the selector breaks locality and so we make an exception for some locality information such as selector, inputs and outputs.
Since we are breaking the locality rule, we need to store the information someplace since `ngtsc` can't have access to the `TooltipDirective` source.
We store the information in the `.d.ts` file like so.
```typescript
class TooltipDirective {
static ngDirectiveDef: DirectiveDefWithMeta<TooltipDirective, '[tooltip]', '', {}, {}, []>
}
```