forked from angular/angular
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(ngUpgrade): add support for AoT compiled upgrade applications
This commit introduces a new API to the ngUpgrade module, which is compatible with AoT compilation. Primarily, it removes the dependency on reflection over the Angular 2 metadata by introducing an API where this information is explicitly defined, in the source code, in a way that is not lost through AoT compilation. This commit is a collaboration between @mhevery (who provided the original design of the API); @gkalpak & @petebacondarwin (who implemented the API and migrated the specs from the original ngUpgrade tests) and alexeagle (who provided input and review). This commit is an starting point, there is still work to be done: * add more documentation * validate the API via internal projects * align the ngUpgrade compilation of A1 directives closer to the real A1 compiler * add more unit tests * consider support for async `templateUrl` A1 upgraded components Closes angular#12239
- Loading branch information
1 parent
a2d3564
commit e7d76b5
Showing
31 changed files
with
3,270 additions
and
46 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
/** | ||
* @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 | ||
*/ | ||
|
||
export {downgradeComponent} from './aot/downgrade_component'; | ||
export {downgradeInjectable} from './aot/downgrade_injectable'; | ||
export {UpgradeComponent} from './aot/upgrade_component'; | ||
export {UpgradeModule} from './aot/upgrade_module'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/** | ||
* @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 * as angular from '../angular_js'; | ||
|
||
// We have to do a little dance to get the ng1 injector into the module injector. | ||
// We store the ng1 injector so that the provider in the module injector can access it | ||
// Then we "get" the ng1 injector from the module injector, which triggers the provider to read | ||
// the stored injector and release the reference to it. | ||
let tempInjectorRef: angular.IInjectorService; | ||
export function setTempInjectorRef(injector: angular.IInjectorService) { | ||
tempInjectorRef = injector; | ||
} | ||
export function injectorFactory() { | ||
const injector: angular.IInjectorService = tempInjectorRef; | ||
tempInjectorRef = null; // clear the value to prevent memory leaks | ||
return injector; | ||
} | ||
|
||
export function rootScopeFactory(i: angular.IInjectorService) { | ||
return i.get('$rootScope'); | ||
} | ||
|
||
export function compileFactory(i: angular.IInjectorService) { | ||
return i.get('$compile'); | ||
} | ||
|
||
export function parseFactory(i: angular.IInjectorService) { | ||
return i.get('$parse'); | ||
} | ||
|
||
export const angular1Providers = [ | ||
// We must use exported named functions for the ng2 factories to keep the compiler happy: | ||
// > Metadata collected contains an error that will be reported at runtime: | ||
// > Function calls are not supported. | ||
// > Consider replacing the function or lambda with a reference to an exported function | ||
{provide: '$injector', useFactory: injectorFactory}, | ||
{provide: '$rootScope', useFactory: rootScopeFactory, deps: ['$injector']}, | ||
{provide: '$compile', useFactory: compileFactory, deps: ['$injector']}, | ||
{provide: '$parse', useFactory: parseFactory, deps: ['$injector']} | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/** | ||
* @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 {Type} from '@angular/core'; | ||
|
||
export interface ComponentInfo { | ||
component: Type<any>; | ||
inputs?: string[]; | ||
outputs?: string[]; | ||
} | ||
|
||
export class PropertyBinding { | ||
prop: string; | ||
attr: string; | ||
bracketAttr: string; | ||
bracketParenAttr: string; | ||
parenAttr: string; | ||
onAttr: string; | ||
bindAttr: string; | ||
bindonAttr: string; | ||
|
||
constructor(public binding: string) { this.parseBinding(); } | ||
|
||
private parseBinding() { | ||
const parts = this.binding.split(':'); | ||
this.prop = parts[0].trim(); | ||
this.attr = (parts[1] || this.prop).trim(); | ||
this.bracketAttr = `[${this.attr}]`; | ||
this.parenAttr = `(${this.attr})`; | ||
this.bracketParenAttr = `[(${this.attr})]`; | ||
const capitalAttr = this.attr.charAt(0).toUpperCase() + this.attr.substr(1); | ||
this.onAttr = `on${capitalAttr}`; | ||
this.bindAttr = `bind${capitalAttr}`; | ||
this.bindonAttr = `bindon${capitalAttr}`; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/** | ||
* @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 | ||
*/ | ||
|
||
export const UPGRADE_MODULE_NAME = '$$UpgradeModule'; | ||
export const INJECTOR_KEY = '$$angularInjector'; | ||
|
||
export const $INJECTOR = '$injector'; | ||
export const $PARSE = '$parse'; | ||
export const $SCOPE = '$scope'; | ||
|
||
export const $COMPILE = '$compile'; | ||
export const $TEMPLATE_CACHE = '$templateCache'; | ||
export const $HTTP_BACKEND = '$httpBackend'; | ||
export const $CONTROLLER = '$controller'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/** | ||
* @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 {ComponentFactory, ComponentFactoryResolver, Injector} from '@angular/core'; | ||
|
||
import * as angular from '../angular_js'; | ||
|
||
import {ComponentInfo} from './component_info'; | ||
import {$INJECTOR, $PARSE, INJECTOR_KEY} from './constants'; | ||
import {DowngradeComponentAdapter} from './downgrade_component_adapter'; | ||
|
||
let downgradeCount = 0; | ||
|
||
/** | ||
* @experimental | ||
*/ | ||
export function downgradeComponent(info: ComponentInfo): angular.IInjectable { | ||
const idPrefix = `NG2_UPGRADE_${downgradeCount++}_`; | ||
let idCount = 0; | ||
|
||
const directiveFactory: | ||
angular.IAnnotatedFunction = function( | ||
$injector: angular.IInjectorService, | ||
$parse: angular.IParseService): angular.IDirective { | ||
|
||
return { | ||
restrict: 'E', | ||
require: '?^' + INJECTOR_KEY, | ||
link: (scope: angular.IScope, element: angular.IAugmentedJQuery, attrs: angular.IAttributes, | ||
parentInjector: Injector, transclude: angular.ITranscludeFunction) => { | ||
|
||
if (parentInjector === null) { | ||
parentInjector = $injector.get(INJECTOR_KEY); | ||
} | ||
|
||
const componentFactoryResolver: ComponentFactoryResolver = | ||
parentInjector.get(ComponentFactoryResolver); | ||
const componentFactory: ComponentFactory<any> = | ||
componentFactoryResolver.resolveComponentFactory(info.component); | ||
|
||
if (!componentFactory) { | ||
throw new Error('Expecting ComponentFactory for: ' + info.component); | ||
} | ||
|
||
const facade = new DowngradeComponentAdapter( | ||
idPrefix + (idCount++), info, element, attrs, scope, parentInjector, $parse, | ||
componentFactory); | ||
facade.setupInputs(); | ||
facade.createComponent(); | ||
facade.projectContent(); | ||
facade.setupOutputs(); | ||
facade.registerCleanup(); | ||
} | ||
}; | ||
}; | ||
|
||
directiveFactory.$inject = [$INJECTOR, $PARSE]; | ||
return directiveFactory; | ||
} |
Oops, something went wrong.