revert: docs(ivy): update STATUS.md with compiler work breakdown (#22874)
This reverts commit b524e4b142eb1e7dd52ce6b239ef1ee825e2b42c.
This commit is contained in:
		
							parent
							
								
									bb58664b13
								
							
						
					
					
						commit
						d77bb460b0
					
				| @ -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; | ||||
| ```` | ||||
| @ -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 ❌ | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user