From d77bb460b0d513d93fa5afbc36e0e51a410ad177 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Niemel=C3=A4?= Date: Thu, 22 Mar 2018 18:09:45 -0400 Subject: [PATCH] revert: docs(ivy): update STATUS.md with compiler work breakdown (#22874) This reverts commit b524e4b142eb1e7dd52ce6b239ef1ee825e2b42c. --- packages/core/src/render3/METADATA.md | 92 ---------- packages/core/src/render3/STATUS.md | 251 +++++++++----------------- 2 files changed, 89 insertions(+), 254 deletions(-) delete mode 100644 packages/core/src/render3/METADATA.md diff --git a/packages/core/src/render3/METADATA.md b/packages/core/src/render3/METADATA.md deleted file mode 100644 index a9fa9ed351..0000000000 --- a/packages/core/src/render3/METADATA.md +++ /dev/null @@ -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; - 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(module: {ngModule: {exports: T[]}}): T; -declare function getNgModuleImports(module: {ngModule: {imports: T[]}}): T; -declare function getSelector(componentType: { - ngComponentDef?: ComponentDef<{selector: T}>, - ngDirectiveDef?: DirectiveDef<{selector: T}>, - ngPipeDef?: PipeDef<{selector: T}>, -}): T; -```` \ No newline at end of file diff --git a/packages/core/src/render3/STATUS.md b/packages/core/src/render3/STATUS.md index df0919a32b..7a691c89a9 100644 --- a/packages/core/src/render3/STATUS.md +++ b/packages/core/src/render3/STATUS.md @@ -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 | +| -------------------------------- | ------- | -------- | -------- | +| `
` | ✅ | ✅ | ✅ | +| `
{{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 | +| ------------------------------- | ------- | -------- | -------- | +| `` | ✅ | ✅ | ✅ | +| `` | ✅ | ✅ | ✅ | +| 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 | -| --------------------------------------- | ------- | -------- | -------- | -| `
` | ✅ | ✅ | ✅ | -| `
{{exp}}
` | ✅ | ✅ | ✅ | -| `
` | ✅ | ✅ | ✅ | -| `
` | ✅ | ✅ | ✅ | -| `
` | ✅ | ✅ | ✅ | -| `
` | ✅ | ✅ | ✅ | -| `
` | ✅ | ✅ | ✅ | -| `
` | ✅ | ✅ | ✅ | -| `
` | ✅ | ✅ | ❌ | -| `
` | ✅ | ✅ | ✅ | -| `
` | ❌ | ❌ | ❌ | -| `
` | ✅ | ✅ | ❌ | -| `
` | ✅ | ✅ | ✅ | -| `
` | ❌ | ❌ | ❌ | -| `
` | ✅ | ✅ | ❌ | -| `{{ ['literal', exp ] }}` | ✅ | ✅ | ✅ | -| `{{ { a: 'literal', b: exp } }}` | ✅ | ✅ | ✅ | -| `{{ exp \| pipe: arg }}` | ✅ | ✅ | ✅ | -| `` | ❌ | ❌ | ❌ | -| `` 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 | -| ------------------------------- | ------- | -------- | -------- | -| `` | ✅ | ✅ | ✅ | -| `` | ✅ | ✅ | ✅ | -| 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 ❌ \ No newline at end of file