test(ivy): Back patch example (#22235)

PR Close #22235
This commit is contained in:
Miško Hevery 2018-02-13 14:25:13 -08:00 committed by Alex Eagle
parent b3d1761825
commit 363dfa5437
2 changed files with 216 additions and 0 deletions

View File

@ -0,0 +1,138 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Component, ContentChild, Directive, Injectable, Injector, Input, NgModule, NgModuleFactory, NgModuleRef, OnDestroy, Optional, Pipe, PipeTransform, QueryList, SimpleChanges, TemplateRef, Type, ViewChild, ViewContainerRef} from '../../../src/core';
import * as r3 from '../../../src/render3/index';
import {pending_pull_22005} from './small_app_spec';
const details_elided = {
type: Object,
} as any;
export type $ComponentDef$ = any;
///////////
// Lib A - Compiled pre-Ivy
// "enableIvy": false
//////////
// BEGIN FILE: node_modules/libA/module.ts (Compiled without Ivy)
@Component({})
export class LibAComponent {
}
@NgModule({declarations: [LibAComponent], imports: []})
export class LibAModule {
}
// END FILE: node_modules/libA/module.ts
// BEGIN FILE: node_modules/libA/module.metadata.json
// Abridged version of metadata
const node_modules_libA_module_metadata = {
'LibAModule': {
refs: ['LibAComponent'],
constructorDes: [],
},
'LibAComponent': {
constructorDes: [],
}
};
// END FILE: node_modules/libA/module.metadata.json
///////////
// Lib B - Compiled with Ivy
// "enableIvy": true
//////////
// BEGIN FILE: node_modules/libB/module.ts (Compiled with Ivy)
@Component({})
export class LibBComponent {
// COMPILER GENERATED
static ngComponentDef: $ComponentDef$ = r3.defineComponent(details_elided);
}
@NgModule({declarations: [LibAComponent], imports: []})
export class LibBModule {
// COMPILER GENERATED
static ngInjectorDef = pending_pull_22005.defineInjector(details_elided);
}
// END FILE: node_modules/libB/module.ts
// BEGIN FILE: node_modules/libB/module.metadata.json
// Abridged version of metadata
// Must still generate metadata in case it should be consumed with non-ivy application
// Must mark the metadata with `hasNgDef: true` so that Ivy knows to ignore it.
const node_modules_libB_module_metadata = {
'LibBModule': {refs: ['LibBComponent'], constructorDes: [], hasNgDef: true},
'LibBComponent': {constructorDes: [], hasNgDef: true}
};
// END FILE: node_modules/libA/module.metadata.json
///////////
// Lib B - Compiled with Ivy
// "enableIvy": true
// "enableIvyBackPatch": true
//////////
// BEGIN FILE: src/app.ts (Compiled with Ivy)
@Component({})
export class AppComponent {
// COMPILER GENERATED
static ngComponentDef: $ComponentDef$ = r3.defineComponent(details_elided);
}
@NgModule({declarations: [LibAComponent], imports: []})
export class AppModule {
// COMPILER GENERATED
static ngInjectorDef = pending_pull_22005.defineInjector(details_elided);
}
// END FILE: src/app.ts
// BEGIN FILE: src/main.ts
// platformBrowserDynamic().bootstrapModule(AppModule);
// CLI rewrites it later to:
// platformBrowser().bootstrapModuleFactory(AppModuleFactory);
// END FILE: src/main.ts
// BEGIN FILE: src/app.ngfactory.ts
function ngBackPatch_node_modules_libB_module() {
ngBackPatch_node_modules_libB_module_LibAComponent();
ngBackPatch_node_modules_libB_module_LibAModule();
}
function ngBackPatch_node_modules_libB_module_LibAComponent() {
(LibAComponent as any).ngComponentDef = r3.defineComponent(details_elided);
}
function ngBackPatch_node_modules_libB_module_LibAModule() {
(LibAModule as any).ngInjectorDef = pending_pull_22005.defineInjector(details_elided);
}
export const AppModuleFactory: NgModuleFactory<AppModule>&{patchedDeps: boolean} = {
moduleType: AppModule,
patchedDeps: false,
create(parentInjector: Injector | null): NgModuleRef<AppModule>{
this.patchedDeps && ngBackPatch_node_modules_libB_module() && (this.patchedDeps = true);
return details_elided;}
};
// BEGIN FILE: src/app.ngfactory.ts
// ISSUE: I don't think this works. The issue is that multiple modules get flattened into single
// module and hence we can't patch transitively.
// ISSUE: can non-ivy @NgModule import Ivy @NgModule? I assume no, since the flattening of modules
// happens during compilation.
// BEGIN FILE: src/main.ts
// platformBrowserDynamic().bootstrapModule(AppModule);
// CLI rewrites it to:
// platformBrowser().bootstrapModuleFactory(AppModuleFactory);
// END FILE: src/main.ts

View File

@ -0,0 +1,78 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Component, ContentChild, Directive, Injectable, Input, NgModule, OnDestroy, Optional, Pipe, PipeTransform, QueryList, SimpleChanges, TemplateRef, Type, ViewChild, ViewContainerRef} from '../../../src/core';
import * as r3 from '../../../src/render3/index';
import {pending_pull_22005} from './small_app_spec';
/**
* GOALS:
* - Patch types in tree shakable way
* - Generate these types for files which have `metadata.json` (since those are the files which
* have not been compiled with Ivy)
* - Have build optimizer hoist the patch functions into corresponding types to allow tree-shaking.
*/
// File: node_modules/some_library/path/public.ts
// Implies metadata: node_modules/some_library/path/public.metadata.json
// Assume: node_modules/some_library/index.js re-exports ./path/public.ts#ThirdPartyClass
@Injectable()
class ThirdPartyClass {
}
@Injectable()
class CompiledWithIvy {
// NORMATIVE
static ngInjectableDef = pending_pull_22005.defineInjectable(
{factory: function CompileWithIvy_Factory() { return new CompiledWithIvy(); }});
// /NORMATIVE
}
// import { CompiledWithIvy } from 'some_library';
@NgModule({providers: [ThirdPartyClass, CompiledWithIvy]})
class CompiledWithIvyModule {
// NORMATIVE
static ngInjectorDef = pending_pull_22005.defineInjector({
providers: [ThirdPartyClass, CompiledWithIvy],
factory: function CompiledWithIvyModule_Factory() { return new CompiledWithIvyModule(); }
});
// /NORMATIVE
}
/**
* Below is a function which should be generated right next to the `@NgModule` which
* imports types which have `.metadata.json` files.
*
* # JIT Mode
* - Because the `ngPatch_CompiledWithIvyModule` is invoked all parts get patched.
*
* # AOT Mode
* - Build Optimizer detects `@__BUILD_OPTIMIZER_COLOCATE__` annotation and moves the
* code from the current location to the destination.
* - The resulting `ngPatch_CompiledWithIvyModule` becomes empty and eligible for tree-shaking.
* - Uglify removes the `ngPatch_CompiledWithIvyModule` since it is empty.
*
* # AOT Closure Mode
* - Option A: not supported. (Preferred option)
* - Externally very few people use closure they will just have to wait until all of their
* libraries are Ivy.
* - Internally (g3) we build from source hence everyone switches to Ivy at the same time.
* - Option B: Write a closure pass similar to Build Optimizer which would move the code.
*/
// NORMATIVE
ngPatch_depsOf_CompiledWithIvyModule();
function ngPatch_depsOf_CompiledWithIvyModule() {
ngPatch_node_modules_some_library_path_public_CompileWithIvy();
}
function ngPatch_node_modules_some_library_path_public_CompileWithIvy() {
/** @__BUILD_OPTIMIZER_COLOCATE__ */
(ThirdPartyClass as any).ngInjectableDef = pending_pull_22005.defineInjectable(
{factory: function CompileWithIvy_Factory() { return new ThirdPartyClass(); }});
}
// /NORMATIVE