From a3e32fb7e14b5b131c90987559e446769d25d6b7 Mon Sep 17 00:00:00 2001 From: Tobias Bosch Date: Tue, 14 Mar 2017 14:55:37 -0700 Subject: [PATCH] feat(upgrade): use `ComponentFactory.inputs/outputs/ngContentSelectors` DEPRECATION: - the arguments `inputs` / `outputs` / `ngContentSelectors` of `downgradeComponent` are no longer used as Angular calculates these automatically now. - Compiler.getNgContentSelectors is deprecated. Use ComponentFactory.ngContentSelectors instead. --- packages/compiler/src/metadata_resolver.ts | 1 - packages/compiler/test/aot/compiler_spec.ts | 1 - packages/examples/upgrade/static/ts/module.ts | 7 +- packages/upgrade/src/common/component_info.ts | 16 +--- .../src/common/content_projection_helper.ts | 20 ----- .../upgrade/src/common/downgrade_component.ts | 33 ++----- .../src/common/downgrade_component_adapter.ts | 88 +++++++++---------- .../src/common/ng_content_selector_helper.ts | 24 ----- .../src/dynamic/content_projection_helper.ts | 70 --------------- .../src/dynamic/ng_content_selector_helper.ts | 24 ----- .../upgrade/src/dynamic/upgrade_adapter.ts | 11 +-- packages/upgrade/src/static/upgrade_module.ts | 3 +- .../test/common/component_info_spec.ts | 19 +--- .../downgrade_component_adapter_spec.ts | 29 ++---- .../dynamic/group_projectable_nodes_spec.ts | 85 ------------------ .../integration/change_detection_spec.ts | 2 +- .../integration/content_projection_spec.ts | 20 ++--- .../integration/downgrade_component_spec.ts | 12 +-- .../test/static/integration/examples_spec.ts | 4 +- .../integration/upgrade_component_spec.ts | 26 ++---- tools/public_api_guard/core/typings/core.d.ts | 11 ++- .../upgrade/typings/static/index.d.ts | 6 +- 22 files changed, 94 insertions(+), 418 deletions(-) delete mode 100644 packages/upgrade/src/common/content_projection_helper.ts delete mode 100644 packages/upgrade/src/common/ng_content_selector_helper.ts delete mode 100644 packages/upgrade/src/dynamic/content_projection_helper.ts delete mode 100644 packages/upgrade/src/dynamic/ng_content_selector_helper.ts delete mode 100644 packages/upgrade/test/dynamic/group_projectable_nodes_spec.ts diff --git a/packages/compiler/src/metadata_resolver.ts b/packages/compiler/src/metadata_resolver.ts index 106f5f07d4..713ffd1e42 100644 --- a/packages/compiler/src/metadata_resolver.ts +++ b/packages/compiler/src/metadata_resolver.ts @@ -156,7 +156,6 @@ export class CompileMetadataResolver { const templateName = inputs[propName]; factory.inputs.push({propName, templateName}); } - const outputsArr: {propName: string, templateName: string}[] = []; for (let propName in outputs) { const templateName = outputs[propName]; factory.outputs.push({propName, templateName}); diff --git a/packages/compiler/test/aot/compiler_spec.ts b/packages/compiler/test/aot/compiler_spec.ts index 2dab0973cd..072af8adf8 100644 --- a/packages/compiler/test/aot/compiler_spec.ts +++ b/packages/compiler/test/aot/compiler_spec.ts @@ -279,7 +279,6 @@ describe('compiler (unbundled Angular)', () => { const host = new MockCompilerHost(['/app/app.ts'], FILES, angularFiles); const aotHost = new MockAotCompilerHost(host); let generatedFiles: GeneratedFile[]; - const warnSpy = spyOn(console, 'warn'); compile(host, aotHost, expectNoDiagnostics).then((f) => generatedFiles = f); tick(); diff --git a/packages/examples/upgrade/static/ts/module.ts b/packages/examples/upgrade/static/ts/module.ts index 6c6d0aeb6f..ef5b3b44bc 100644 --- a/packages/examples/upgrade/static/ts/module.ts +++ b/packages/examples/upgrade/static/ts/module.ts @@ -145,12 +145,7 @@ ng1AppModule.factory('heroesService', downgradeInjectable(HeroesService)); // #docregion ng2-heroes-wrapper // This is directive will act as the interface to the "downgraded" Angular component -ng1AppModule.directive( - 'ng2Heroes', - downgradeComponent( - // The inputs and outputs here must match the relevant names of the properties on the - // "downgraded" component - {component: Ng2HeroesComponent, inputs: ['heroes'], outputs: ['addHero', 'removeHero']})); +ng1AppModule.directive('ng2Heroes', downgradeComponent({component: Ng2HeroesComponent})); // #enddocregion // #docregion example-app diff --git a/packages/upgrade/src/common/component_info.ts b/packages/upgrade/src/common/component_info.ts index 3419fd178e..898bb72456 100644 --- a/packages/upgrade/src/common/component_info.ts +++ b/packages/upgrade/src/common/component_info.ts @@ -6,15 +6,6 @@ * found in the LICENSE file at https://angular.io/license */ -import {Type} from '@angular/core'; - -export interface ComponentInfo { - component: Type; - inputs?: string[]; - outputs?: string[]; - selectors?: string[]; -} - /** * A `PropertyBinding` represents a mapping between a property name * and an attribute name. It is parsed from a string of the form @@ -22,8 +13,6 @@ export interface ComponentInfo { * and attribute have the same identifier. */ export class PropertyBinding { - prop: string; - attr: string; bracketAttr: string; bracketParenAttr: string; parenAttr: string; @@ -31,12 +20,9 @@ export class PropertyBinding { bindAttr: string; bindonAttr: string; - constructor(public binding: string) { this.parseBinding(); } + constructor(public prop: string, public attr: 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})]`; diff --git a/packages/upgrade/src/common/content_projection_helper.ts b/packages/upgrade/src/common/content_projection_helper.ts deleted file mode 100644 index df9eb42960..0000000000 --- a/packages/upgrade/src/common/content_projection_helper.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * @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'; -import * as angular from './angular1'; - - -export class ContentProjectionHelper { - groupProjectableNodes($injector: angular.IInjectorService, component: Type, nodes: Node[]): - Node[][] { - // By default, do not support multi-slot projection, - // as `upgrade/static` does not support it yet. - return [nodes]; - } -} diff --git a/packages/upgrade/src/common/downgrade_component.ts b/packages/upgrade/src/common/downgrade_component.ts index a25609be84..4becae7b03 100644 --- a/packages/upgrade/src/common/downgrade_component.ts +++ b/packages/upgrade/src/common/downgrade_component.ts @@ -11,7 +11,6 @@ import {ComponentFactory, ComponentFactoryResolver, Injector, Type} from '@angul import * as angular from './angular1'; import {$COMPILE, $INJECTOR, $PARSE, INJECTOR_KEY, REQUIRE_INJECTOR, REQUIRE_NG_MODEL} from './constants'; import {DowngradeComponentAdapter} from './downgrade_component_adapter'; -import {NgContentSelectorHelper} from './ng_content_selector_helper'; import {controllerKey, getComponentName} from './util'; let downgradeCount = 0; @@ -38,15 +37,6 @@ let downgradeCount = 0; * * {@example upgrade/static/ts/module.ts region="ng2-heroes-wrapper"} * - * In this example you can see that we must provide information about the component being - * "downgraded". This is because once the AoT compiler has run, all metadata about the - * component has been removed from the code, and so cannot be inferred. - * - * We must do the following: - * * specify the Angular component class that is to be downgraded - * * specify all inputs and outputs that the AngularJS component expects - * * specify the selectors used in any `ng-content` elements in the component's template - * * @description * * A helper function that returns a factory function to be used for registering an @@ -55,28 +45,17 @@ let downgradeCount = 0; * The parameter contains information about the Component that is being downgraded: * * * `component: Type`: The type of the Component that will be downgraded - * * `inputs: string[]`: A collection of strings that specify what inputs the component accepts - * * `outputs: string[]`: A collection of strings that specify what outputs the component emits - * * `selectors: string[]`: A collection of strings that specify what selectors are expected on - * `ng-content` elements in the template to enable content projection (a.k.a. transclusion in - * AngularJS) - * - * The `inputs` and `outputs` are strings that map the names of properties to camelCased - * attribute names. They are of the form `"prop: attr"`; or simply `"propAndAttr" where the - * property and attribute have the same identifier. - * - * The `selectors` are the values of the `select` attribute of each of the `ng-content` elements - * that appear in the downgraded component's template. - * These selectors must be provided in the order that they appear in the template as they are - * mapped by index to the projected nodes. * * @experimental */ -export function downgradeComponent(info: /* ComponentInfo */ { +export function downgradeComponent(info: { component: Type; + /** @deprecated since v4. This parameter is no longer used */ inputs?: string[]; + /** @deprecated since v4. This parameter is no longer used */ outputs?: string[]; - selectors?: string[] + /** @deprecated since v4. This parameter is no longer used */ + selectors?: string[]; }): any /* angular.IInjectable */ { const idPrefix = `NG2_UPGRADE_${downgradeCount++}_`; let idCount = 0; @@ -114,7 +93,7 @@ export function downgradeComponent(info: /* ComponentInfo */ { const id = idPrefix + (idCount++); const injectorPromise = new ParentInjectorPromise(element); const facade = new DowngradeComponentAdapter( - id, info, element, attrs, scope, ngModel, injector, $injector, $compile, $parse, + id, element, attrs, scope, ngModel, injector, $injector, $compile, $parse, componentFactory); const projectableNodes = facade.compileContents(); diff --git a/packages/upgrade/src/common/downgrade_component_adapter.ts b/packages/upgrade/src/common/downgrade_component_adapter.ts index 36f9e0e808..8af71d8a65 100644 --- a/packages/upgrade/src/common/downgrade_component_adapter.ts +++ b/packages/upgrade/src/common/downgrade_component_adapter.ts @@ -9,9 +9,8 @@ import {ChangeDetectorRef, ComponentFactory, ComponentRef, EventEmitter, Injector, OnChanges, ReflectiveInjector, SimpleChange, SimpleChanges, Type} from '@angular/core'; import * as angular from './angular1'; -import {ComponentInfo, PropertyBinding} from './component_info'; +import {PropertyBinding} from './component_info'; import {$SCOPE} from './constants'; -import {NgContentSelectorHelper} from './ng_content_selector_helper'; import {getAttributesAsArray, getComponentName, hookupNgModel} from './util'; const INITIAL_VALUE = { @@ -27,7 +26,7 @@ export class DowngradeComponentAdapter { private changeDetector: ChangeDetectorRef = null; constructor( - private id: string, private info: ComponentInfo, private element: angular.IAugmentedJQuery, + private id: string, private element: angular.IAugmentedJQuery, private attrs: angular.IAttributes, private scope: angular.IScope, private ngModel: angular.INgModelController, private parentInjector: Injector, private $injector: angular.IInjectorService, private $compile: angular.ICompileService, @@ -67,9 +66,9 @@ export class DowngradeComponentAdapter { setupInputs(): void { const attrs = this.attrs; - const inputs = this.info.inputs || []; + const inputs = this.componentFactory.inputs || []; for (let i = 0; i < inputs.length; i++) { - const input = new PropertyBinding(inputs[i]); + const input = new PropertyBinding(inputs[i].propName, inputs[i].templateName); let expr: any /** TODO #9100 */ = null; if (attrs.hasOwnProperty(input.attr)) { @@ -103,7 +102,7 @@ export class DowngradeComponentAdapter { } } - const prototype = this.info.component.prototype; + const prototype = this.componentFactory.componentType.prototype; if (prototype && (prototype).ngOnChanges) { // Detect: OnChanges interface this.inputChanges = {}; @@ -118,9 +117,9 @@ export class DowngradeComponentAdapter { setupOutputs() { const attrs = this.attrs; - const outputs = this.info.outputs || []; + const outputs = this.componentFactory.outputs || []; for (let j = 0; j < outputs.length; j++) { - const output = new PropertyBinding(outputs[j]); + const output = new PropertyBinding(outputs[j].propName, outputs[j].templateName); let expr: any /** TODO #9100 */ = null; let assignExpr = false; @@ -158,7 +157,7 @@ export class DowngradeComponentAdapter { }); } else { throw new Error( - `Missing emitter '${output.prop}' on component '${getComponentName(this.info.component)}'!`); + `Missing emitter '${output.prop}' on component '${getComponentName(this.componentFactory.componentType)}'!`); } } } @@ -183,49 +182,31 @@ export class DowngradeComponentAdapter { } groupProjectableNodes() { - const ngContentSelectorHelper = - this.parentInjector.get(NgContentSelectorHelper) as NgContentSelectorHelper; - const ngContentSelectors = ngContentSelectorHelper.getNgContentSelectors(this.info); - - if (!ngContentSelectors) { - throw new Error('Expecting ngContentSelectors for: ' + getComponentName(this.info.component)); - } - - return this._groupNodesBySelector(ngContentSelectors, this.element.contents()); - } - - /** - * Group a set of DOM nodes into `ngContent` groups, based on the given content selectors. - */ - private _groupNodesBySelector(ngContentSelectors: string[], nodes: Node[]): Node[][] { - const projectableNodes: Node[][] = []; - let wildcardNgContentIndex: number; - - for (let i = 0, ii = ngContentSelectors.length; i < ii; ++i) { - projectableNodes[i] = []; - } - - for (let j = 0, jj = nodes.length; j < jj; ++j) { - const node = nodes[j]; - const ngContentIndex = findMatchingNgContentIndex(node, ngContentSelectors); - if (ngContentIndex != null) { - projectableNodes[ngContentIndex].push(node); - } - } - - return projectableNodes; + let ngContentSelectors = this.componentFactory.ngContentSelectors; + return groupNodesBySelector(ngContentSelectors, this.element.contents()); } } -let _matches: (this: any, selector: string) => boolean; +/** + * Group a set of DOM nodes into `ngContent` groups, based on the given content selectors. + */ +export function groupNodesBySelector(ngContentSelectors: string[], nodes: Node[]): Node[][] { + const projectableNodes: Node[][] = []; + let wildcardNgContentIndex: number; -function matchesSelector(el: any, selector: string): boolean { - if (!_matches) { - const elProto = Element.prototype; - _matches = elProto.matchesSelector || elProto.mozMatchesSelector || elProto.msMatchesSelector || - elProto.oMatchesSelector || elProto.webkitMatchesSelector; + for (let i = 0, ii = ngContentSelectors.length; i < ii; ++i) { + projectableNodes[i] = []; } - return _matches.call(el, selector); + + for (let j = 0, jj = nodes.length; j < jj; ++j) { + const node = nodes[j]; + const ngContentIndex = findMatchingNgContentIndex(node, ngContentSelectors); + if (ngContentIndex != null) { + projectableNodes[ngContentIndex].push(node); + } + } + + return projectableNodes; } function findMatchingNgContentIndex(element: any, ngContentSelectors: string[]): number { @@ -247,4 +228,15 @@ function findMatchingNgContentIndex(element: any, ngContentSelectors: string[]): ngContentIndices.push(wildcardNgContentIndex); } return ngContentIndices.length ? ngContentIndices[0] : null; -} \ No newline at end of file +} + +let _matches: (this: any, selector: string) => boolean; + +function matchesSelector(el: any, selector: string): boolean { + if (!_matches) { + const elProto = Element.prototype; + _matches = elProto.matches || elProto.matchesSelector || elProto.mozMatchesSelector || + elProto.msMatchesSelector || elProto.oMatchesSelector || elProto.webkitMatchesSelector; + } + return el.nodeType === Node.ELEMENT_NODE ? _matches.call(el, selector) : false; +} diff --git a/packages/upgrade/src/common/ng_content_selector_helper.ts b/packages/upgrade/src/common/ng_content_selector_helper.ts deleted file mode 100644 index 62ea7aa564..0000000000 --- a/packages/upgrade/src/common/ng_content_selector_helper.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * @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 {ComponentInfo} from './component_info'; - -/** - * This class gives an extension point between the static and dynamic versions - * of ngUpgrade: - * * In the static version (this one) we must specify them manually as part of - * the call to `downgradeComponent(...)`. - * * In the dynamic version (`DynamicNgContentSelectorHelper`) we are able to - * ask the compiler for the selectors of a component. - */ -export class NgContentSelectorHelper { - getNgContentSelectors(info: ComponentInfo): string[] { - // if no selectors are passed then default to a single "wildcard" selector - return info.selectors || ['*']; - } -} diff --git a/packages/upgrade/src/dynamic/content_projection_helper.ts b/packages/upgrade/src/dynamic/content_projection_helper.ts deleted file mode 100644 index 338cdef363..0000000000 --- a/packages/upgrade/src/dynamic/content_projection_helper.ts +++ /dev/null @@ -1,70 +0,0 @@ -/** - * @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 {CssSelector, SelectorMatcher, createElementCssSelector} from '@angular/compiler'; -import {Compiler, Type} from '@angular/core'; - -import * as angular from '../common/angular1'; -import {COMPILER_KEY} from '../common/constants'; -import {ContentProjectionHelper} from '../common/content_projection_helper'; -import {getAttributesAsArray, getComponentName} from '../common/util'; - - -export class DynamicContentProjectionHelper extends ContentProjectionHelper { - groupProjectableNodes($injector: angular.IInjectorService, component: Type, nodes: Node[]): - Node[][] { - const ng2Compiler = $injector.get(COMPILER_KEY) as Compiler; - const ngContentSelectors = ng2Compiler.getNgContentSelectors(component); - - if (!ngContentSelectors) { - throw new Error('Expecting ngContentSelectors for: ' + getComponentName(component)); - } - - return this.groupNodesBySelector(ngContentSelectors, nodes); - } - - /** - * Group a set of DOM nodes into `ngContent` groups, based on the given content selectors. - */ - groupNodesBySelector(ngContentSelectors: string[], nodes: Node[]): Node[][] { - const projectableNodes: Node[][] = []; - let matcher = new SelectorMatcher(); - let wildcardNgContentIndex: number; - - for (let i = 0, ii = ngContentSelectors.length; i < ii; ++i) { - projectableNodes[i] = []; - - const selector = ngContentSelectors[i]; - if (selector === '*') { - wildcardNgContentIndex = i; - } else { - matcher.addSelectables(CssSelector.parse(selector), i); - } - } - - for (let j = 0, jj = nodes.length; j < jj; ++j) { - const ngContentIndices: number[] = []; - const node = nodes[j]; - const selector = - createElementCssSelector(node.nodeName.toLowerCase(), getAttributesAsArray(node)); - - matcher.match(selector, (_, index) => ngContentIndices.push(index)); - ngContentIndices.sort(); - - if (wildcardNgContentIndex !== undefined) { - ngContentIndices.push(wildcardNgContentIndex); - } - - if (ngContentIndices.length) { - projectableNodes[ngContentIndices[0]].push(node); - } - } - - return projectableNodes; - } -} diff --git a/packages/upgrade/src/dynamic/ng_content_selector_helper.ts b/packages/upgrade/src/dynamic/ng_content_selector_helper.ts deleted file mode 100644 index 085d101afe..0000000000 --- a/packages/upgrade/src/dynamic/ng_content_selector_helper.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * @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 {Compiler, Injectable} from '@angular/core'; - -import {ComponentInfo} from '../common/component_info'; -import {NgContentSelectorHelper} from '../common/ng_content_selector_helper'; - - -/** - * See `NgContentSelectorHelper` for more information about this class. - */ -@Injectable() -export class DynamicNgContentSelectorHelper extends NgContentSelectorHelper { - constructor(private compiler: Compiler) { super(); } - getNgContentSelectors(info: ComponentInfo): string[] { - return this.compiler.getNgContentSelectors(info.component); - } -} diff --git a/packages/upgrade/src/dynamic/upgrade_adapter.ts b/packages/upgrade/src/dynamic/upgrade_adapter.ts index 14efd6870d..e13f0daa96 100644 --- a/packages/upgrade/src/dynamic/upgrade_adapter.ts +++ b/packages/upgrade/src/dynamic/upgrade_adapter.ts @@ -6,19 +6,15 @@ * found in the LICENSE file at https://angular.io/license */ -import {DirectiveResolver} from '@angular/compiler'; import {Compiler, CompilerOptions, Directive, Injector, NgModule, NgModuleRef, NgZone, Provider, Testability, Type} from '@angular/core'; import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; import * as angular from '../common/angular1'; -import {ComponentInfo} from '../common/component_info'; import {$$TESTABILITY, $COMPILE, $INJECTOR, $ROOT_SCOPE, COMPILER_KEY, INJECTOR_KEY, NG_ZONE_KEY} from '../common/constants'; import {downgradeComponent} from '../common/downgrade_component'; import {downgradeInjectable} from '../common/downgrade_injectable'; -import {NgContentSelectorHelper} from '../common/ng_content_selector_helper'; import {Deferred, controllerKey, onError} from '../common/util'; -import {DynamicNgContentSelectorHelper} from './ng_content_selector_helper'; import {UpgradeNg1ComponentAdapterBuilder} from './upgrade_ng1_adapter'; let upgradeCount: number = 0; @@ -104,7 +100,6 @@ let upgradeCount: number = 0; */ export class UpgradeAdapter { private idPrefix: string = `NG2_UPGRADE_${upgradeCount++}_`; - private directiveResolver: DirectiveResolver = new DirectiveResolver(); private downgradedComponents: Type[] = []; /** * An internal map of ng1 components which need to up upgraded to ng2. @@ -190,10 +185,7 @@ export class UpgradeAdapter { downgradeNg2Component(component: Type): Function { this.downgradedComponents.push(component); - const metadata: Directive = this.directiveResolver.resolve(component); - const info: ComponentInfo = {component, inputs: metadata.inputs, outputs: metadata.outputs}; - - return downgradeComponent(info); + return downgradeComponent({component}); } /** @@ -561,7 +553,6 @@ export class UpgradeAdapter { providers: [ {provide: $INJECTOR, useFactory: () => ng1Injector}, {provide: $COMPILE, useFactory: () => ng1Injector.get($COMPILE)}, - {provide: NgContentSelectorHelper, useClass: DynamicNgContentSelectorHelper}, this.upgradedProviders ], imports: [this.ng2AppModule], diff --git a/packages/upgrade/src/static/upgrade_module.ts b/packages/upgrade/src/static/upgrade_module.ts index 5c32a814c9..e663ca9356 100644 --- a/packages/upgrade/src/static/upgrade_module.ts +++ b/packages/upgrade/src/static/upgrade_module.ts @@ -10,7 +10,6 @@ import {Injector, NgModule, NgZone, Testability} from '@angular/core'; import * as angular from '../common/angular1'; import {$$TESTABILITY, $DELEGATE, $INJECTOR, $PROVIDE, $ROOT_SCOPE, INJECTOR_KEY, UPGRADE_MODULE_NAME} from '../common/constants'; -import {NgContentSelectorHelper} from '../common/ng_content_selector_helper'; import {controllerKey} from '../common/util'; import {angular1Providers, setTempInjectorRef} from './angular1_providers'; @@ -130,7 +129,7 @@ import {angular1Providers, setTempInjectorRef} from './angular1_providers'; * * @experimental */ -@NgModule({providers: [angular1Providers, NgContentSelectorHelper]}) +@NgModule({providers: [angular1Providers]}) export class UpgradeModule { /** * The AngularJS `$injector` for the upgrade application. diff --git a/packages/upgrade/test/common/component_info_spec.ts b/packages/upgrade/test/common/component_info_spec.ts index b4b13f2fe4..5bddf8d2ae 100644 --- a/packages/upgrade/test/common/component_info_spec.ts +++ b/packages/upgrade/test/common/component_info_spec.ts @@ -11,8 +11,7 @@ import {PropertyBinding} from '@angular/upgrade/src/common/component_info'; export function main() { describe('PropertyBinding', () => { it('should process a simple binding', () => { - const binding = new PropertyBinding('someBinding'); - expect(binding.binding).toEqual('someBinding'); + const binding = new PropertyBinding('someBinding', 'someBinding'); expect(binding.prop).toEqual('someBinding'); expect(binding.attr).toEqual('someBinding'); expect(binding.bracketAttr).toEqual('[someBinding]'); @@ -24,21 +23,7 @@ export function main() { }); it('should process a two-part binding', () => { - const binding = new PropertyBinding('someProp:someAttr'); - expect(binding.binding).toEqual('someProp:someAttr'); - expect(binding.prop).toEqual('someProp'); - expect(binding.attr).toEqual('someAttr'); - expect(binding.bracketAttr).toEqual('[someAttr]'); - expect(binding.bracketParenAttr).toEqual('[(someAttr)]'); - expect(binding.parenAttr).toEqual('(someAttr)'); - expect(binding.onAttr).toEqual('onSomeAttr'); - expect(binding.bindAttr).toEqual('bindSomeAttr'); - expect(binding.bindonAttr).toEqual('bindonSomeAttr'); - }); - - it('should cope with whitespace', () => { - const binding = new PropertyBinding(' someProp : someAttr '); - expect(binding.binding).toEqual(' someProp : someAttr '); + const binding = new PropertyBinding('someProp', 'someAttr'); expect(binding.prop).toEqual('someProp'); expect(binding.attr).toEqual('someAttr'); expect(binding.bracketAttr).toEqual('[someAttr]'); diff --git a/packages/upgrade/test/common/downgrade_component_adapter_spec.ts b/packages/upgrade/test/common/downgrade_component_adapter_spec.ts index c92b6f601b..730c2495cd 100644 --- a/packages/upgrade/test/common/downgrade_component_adapter_spec.ts +++ b/packages/upgrade/test/common/downgrade_component_adapter_spec.ts @@ -6,25 +6,13 @@ * found in the LICENSE file at https://angular.io/license */ import * as angular from '@angular/upgrade/src/common/angular1'; -import {DowngradeComponentAdapter} from '@angular/upgrade/src/common/downgrade_component_adapter'; -import {NgContentSelectorHelper} from '@angular/upgrade/src/common/ng_content_selector_helper'; +import {groupNodesBySelector} from '@angular/upgrade/src/common/downgrade_component_adapter'; import {nodes} from './test_helpers'; export function main() { describe('DowngradeComponentAdapter', () => { describe('groupNodesBySelector', () => { - function createAdapter(selectors: string[], contentNodes: Node[]): DowngradeComponentAdapter { - const selectorHelper = new NgContentSelectorHelper(); - const fakeInjector = {get: function() { return selectorHelper; }}; - const fakeScope = { $new: function() {} } as any; - const element = angular.element('
'); - element.append(contentNodes); - return new DowngradeComponentAdapter( - 'id', {component: null, selectors}, element, null, fakeScope, null, fakeInjector, null, - null, null, null); - } - it('should return an array of node collections for each selector', () => { const contentNodes = nodes( '
div-1 content
' + @@ -34,8 +22,7 @@ export function main() { '
div-2 content
'); const selectors = ['input[type=date]', 'span', '.x']; - const adapter = createAdapter(selectors, contentNodes); - const projectableNodes = adapter.groupProjectableNodes(); + const projectableNodes = groupNodesBySelector(selectors, contentNodes); expect(projectableNodes[0]).toEqual(nodes('')); expect(projectableNodes[1]).toEqual(nodes('span content')); @@ -54,8 +41,7 @@ export function main() { '
div-2 content
'); const selectors = ['.x', '*', 'input[type=date]']; - const adapter = createAdapter(selectors, contentNodes); - const projectableNodes = adapter.groupProjectableNodes(); + const projectableNodes = groupNodesBySelector(selectors, contentNodes); expect(projectableNodes[0]) .toEqual(nodes( @@ -70,8 +56,7 @@ export function main() { it('should return an array of empty arrays if there are no nodes passed in', () => { const selectors = ['.x', '*', 'input[type=date]']; - const adapter = createAdapter(selectors, []); - const projectableNodes = adapter.groupProjectableNodes(); + const projectableNodes = groupNodesBySelector(selectors, []); expect(projectableNodes).toEqual([[], [], []]); }); @@ -83,12 +68,10 @@ export function main() { 'span content' + '
div-2 content
'); - const adapter1 = createAdapter([], contentNodes); - const projectableNodes = adapter1.groupProjectableNodes(); + const projectableNodes = groupNodesBySelector([], contentNodes); expect(projectableNodes).toEqual([]); - const adapter2 = createAdapter(['.not-there'], contentNodes); - const noMatchSelectorNodes = adapter2.groupProjectableNodes(); + const noMatchSelectorNodes = groupNodesBySelector(['.not-there'], contentNodes); expect(noMatchSelectorNodes).toEqual([[]]); }); }); diff --git a/packages/upgrade/test/dynamic/group_projectable_nodes_spec.ts b/packages/upgrade/test/dynamic/group_projectable_nodes_spec.ts deleted file mode 100644 index 4c7389e1f3..0000000000 --- a/packages/upgrade/test/dynamic/group_projectable_nodes_spec.ts +++ /dev/null @@ -1,85 +0,0 @@ -/** - * @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 {DynamicContentProjectionHelper} from '@angular/upgrade/src/dynamic/content_projection_helper'; -import {nodes} from './test_helpers'; - - -export function main() { - describe('groupNodesBySelector', () => { - let groupNodesBySelector: (ngContentSelectors: string[], nodes: Node[]) => Node[][]; - - beforeEach(() => { - const projectionHelper = new DynamicContentProjectionHelper(); - groupNodesBySelector = projectionHelper.groupNodesBySelector.bind(projectionHelper); - }); - - - it('should return an array of node collections for each selector', () => { - const contentNodes = nodes( - '
div-1 content
' + - '' + - '' + - 'span content' + - '
div-2 content
'); - - const selectors = ['input[type=date]', 'span', '.x']; - const projectableNodes = groupNodesBySelector(selectors, contentNodes); - - expect(projectableNodes[0]).toEqual(nodes('')); - expect(projectableNodes[1]).toEqual(nodes('span content')); - expect(projectableNodes[2]) - .toEqual(nodes( - '
div-1 content
' + - '
div-2 content
')); - }); - - it('should collect up unmatched nodes for the wildcard selector', () => { - const contentNodes = nodes( - '
div-1 content
' + - '' + - '' + - 'span content' + - '
div-2 content
'); - - const selectors = ['.x', '*', 'input[type=date]']; - const projectableNodes = groupNodesBySelector(selectors, contentNodes); - - expect(projectableNodes[0]) - .toEqual(nodes( - '
div-1 content
' + - '
div-2 content
')); - expect(projectableNodes[1]) - .toEqual(nodes( - '' + - 'span content')); - expect(projectableNodes[2]).toEqual(nodes('')); - }); - - it('should return an array of empty arrays if there are no nodes passed in', () => { - const selectors = ['.x', '*', 'input[type=date]']; - const projectableNodes = groupNodesBySelector(selectors, []); - expect(projectableNodes).toEqual([[], [], []]); - }); - - it('should return an empty array for each selector that does not match', () => { - const contentNodes = nodes( - '
div-1 content
' + - '' + - '' + - 'span content' + - '
div-2 content
'); - - const noSelectorNodes = groupNodesBySelector([], contentNodes); - expect(noSelectorNodes).toEqual([]); - - const noMatchSelectorNodes = groupNodesBySelector(['.not-there'], contentNodes); - expect(noMatchSelectorNodes).toEqual([[]]); - }); - }); -} diff --git a/packages/upgrade/test/static/integration/change_detection_spec.ts b/packages/upgrade/test/static/integration/change_detection_spec.ts index 96eae146a4..9f43a3b0bc 100644 --- a/packages/upgrade/test/static/integration/change_detection_spec.ts +++ b/packages/upgrade/test/static/integration/change_detection_spec.ts @@ -73,7 +73,7 @@ export function main() { bootstrap(platformBrowserDynamic(), Ng2Module, element, ng1Module).then((upgrade) => { expect(document.body.textContent).toEqual('1A;2A;ng1a;2B;ng1b;2C;1C;'); // https://github.com/angular/angular.js/issues/12983 - expect(log).toEqual(['1A', '1B', '1C', '2A', '2B', '2C', 'ng1a', 'ng1b']); + expect(log).toEqual(['1A', '1C', '2A', '2B', '2C', 'ng1a', 'ng1b']); }); })); diff --git a/packages/upgrade/test/static/integration/content_projection_spec.ts b/packages/upgrade/test/static/integration/content_projection_spec.ts index d4e636db6f..ef211d229e 100644 --- a/packages/upgrade/test/static/integration/content_projection_spec.ts +++ b/packages/upgrade/test/static/integration/content_projection_spec.ts @@ -72,16 +72,14 @@ export function main() { ngDoBootstrap() {} } - const ng1Module = - angular.module('ng1', []) - .directive( - 'ng2', downgradeComponent({component: Ng2Component, inputs: ['itemId']})) - .run(($rootScope: angular.IRootScopeService) => { - $rootScope['items'] = [ - {id: 'a', subitems: [1, 2, 3]}, {id: 'b', subitems: [4, 5, 6]}, - {id: 'c', subitems: [7, 8, 9]} - ]; - }); + const ng1Module = angular.module('ng1', []) + .directive('ng2', downgradeComponent({component: Ng2Component})) + .run(($rootScope: angular.IRootScopeService) => { + $rootScope['items'] = [ + {id: 'a', subitems: [1, 2, 3]}, {id: 'b', subitems: [4, 5, 6]}, + {id: 'c', subitems: [7, 8, 9]} + ]; + }); const element = html(` @@ -162,7 +160,7 @@ export function main() { } const ng1Module = angular.module('ng1', []).directive( - 'ng2', downgradeComponent({component: Ng2Component, selectors: ['.ng1a', '.ng1b']})); + 'ng2', downgradeComponent({component: Ng2Component})); // The ng-if on one of the projected children is here to make sure // the correct slot is targeted even with structural directives in play. diff --git a/packages/upgrade/test/static/integration/downgrade_component_spec.ts b/packages/upgrade/test/static/integration/downgrade_component_spec.ts index 59339416dc..0e44113338 100644 --- a/packages/upgrade/test/static/integration/downgrade_component_spec.ts +++ b/packages/upgrade/test/static/integration/downgrade_component_spec.ts @@ -108,15 +108,9 @@ export function main() { }; } - ng1Module.directive( - 'ng2', downgradeComponent({ - component: Ng2Component, - inputs: ['literal', 'interpolate', 'oneWayA', 'oneWayB', 'twoWayA', 'twoWayB'], - outputs: [ - 'eventA', 'eventB', 'twoWayAEmitter: twoWayAChange', - 'twoWayBEmitter: twoWayBChange' - ] - })); + ng1Module.directive('ng2', downgradeComponent({ + component: Ng2Component, + })); @NgModule({ declarations: [Ng2Component], diff --git a/packages/upgrade/test/static/integration/examples_spec.ts b/packages/upgrade/test/static/integration/examples_spec.ts index 831db3bf00..9e9f8dbcad 100644 --- a/packages/upgrade/test/static/integration/examples_spec.ts +++ b/packages/upgrade/test/static/integration/examples_spec.ts @@ -71,9 +71,7 @@ export function main() { }; }) // This is wrapping (downgrading) an Angular component to be used in AngularJS - .directive( - 'ng2', - downgradeComponent({component: Ng2Component, inputs: ['nameProp: name']})); + .directive('ng2', downgradeComponent({component: Ng2Component})); // This is the (AngularJS) application bootstrap element // Notice that it is actually a downgraded Angular component diff --git a/packages/upgrade/test/static/integration/upgrade_component_spec.ts b/packages/upgrade/test/static/integration/upgrade_component_spec.ts index b1690b7126..a8a3546c9f 100644 --- a/packages/upgrade/test/static/integration/upgrade_component_spec.ts +++ b/packages/upgrade/test/static/integration/upgrade_component_spec.ts @@ -2627,12 +2627,10 @@ export function main() { } // Define `ng1Module` - const ng1Module = - angular.module('ng1Module', []) - .directive('ng1A', () => ng1DirectiveA) - .directive('ng1B', () => ng1DirectiveB) - .directive( - 'ng2', downgradeComponent({component: Ng2Component, inputs: ['show']})); + const ng1Module = angular.module('ng1Module', []) + .directive('ng1A', () => ng1DirectiveA) + .directive('ng1B', () => ng1DirectiveB) + .directive('ng2', downgradeComponent({component: Ng2Component})); // Define `Ng2Module` @NgModule({ @@ -2729,12 +2727,10 @@ export function main() { } // Define `ng1Module` - const ng1Module = - angular.module('ng1Module', []) - .directive('ng1A', () => ng1DirectiveA) - .directive('ng1B', () => ng1DirectiveB) - .directive( - 'ng2', downgradeComponent({component: Ng2Component, inputs: ['show']})); + const ng1Module = angular.module('ng1Module', []) + .directive('ng1A', () => ng1DirectiveA) + .directive('ng1B', () => ng1DirectiveB) + .directive('ng2', downgradeComponent({component: Ng2Component})); // Define `Ng2Module` @NgModule({ @@ -3086,11 +3082,7 @@ export function main() { const ng1Module = angular.module('ng1', []) .component('ng1X', ng1Component) .directive('ng2A', downgradeComponent({component: Ng2ComponentA})) - .directive('ng2B', downgradeComponent({ - component: Ng2ComponentB, - inputs: ['ng2BInputA: ng2BInput1', 'ng2BInputC'], - outputs: ['ng2BOutputC'] - })); + .directive('ng2B', downgradeComponent({component: Ng2ComponentB})); // Define `Ng2Module` @NgModule({ diff --git a/tools/public_api_guard/core/typings/core.d.ts b/tools/public_api_guard/core/typings/core.d.ts index 1868d6001c..668ec82df6 100644 --- a/tools/public_api_guard/core/typings/core.d.ts +++ b/tools/public_api_guard/core/typings/core.d.ts @@ -193,7 +193,7 @@ export declare class Compiler { compileModuleAndAllComponentsSync(moduleType: Type): ModuleWithComponentFactories; compileModuleAsync(moduleType: Type): Promise>; compileModuleSync(moduleType: Type): NgModuleFactory; - getNgContentSelectors(component: Type): string[]; + /** @deprecated */ getNgContentSelectors(component: Type): string[]; } /** @experimental */ @@ -226,6 +226,15 @@ export interface ComponentDecorator { /** @stable */ export declare abstract class ComponentFactory { readonly abstract componentType: Type; + readonly abstract inputs: { + propName: string; + templateName: string; + }[]; + readonly abstract ngContentSelectors: string[]; + readonly abstract outputs: { + propName: string; + templateName: string; + }[]; readonly abstract selector: string; abstract create(injector: Injector, projectableNodes?: any[][], rootSelectorOrNode?: string | any, ngModule?: NgModuleRef): ComponentRef; } diff --git a/tools/public_api_guard/upgrade/typings/static/index.d.ts b/tools/public_api_guard/upgrade/typings/static/index.d.ts index 6398773b84..40cee4c38d 100644 --- a/tools/public_api_guard/upgrade/typings/static/index.d.ts +++ b/tools/public_api_guard/upgrade/typings/static/index.d.ts @@ -1,9 +1,9 @@ /** @experimental */ export declare function downgradeComponent(info: { component: Type; - inputs?: string[]; - outputs?: string[]; - selectors?: string[]; + /** @deprecated */ inputs?: string[]; + /** @deprecated */ outputs?: string[]; + /** @deprecated */ selectors?: string[]; }): any; /** @experimental */