From 3f55aa609f60f130f1d69188ed057214b1267cb3 Mon Sep 17 00:00:00 2001 From: Tobias Bosch Date: Thu, 30 Jun 2016 13:07:17 -0700 Subject: [PATCH] feat(browser): use AppModules for bootstrap in the browser MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This introduces the `BrowserModule` to be used for long form bootstrap and offline compile bootstrap: ``` @AppModule({ modules: [BrowserModule], precompile: [MainComponent], providers: […], // additional providers directives: […], // additional platform directives pipes: […] // additional platform pipes }) class MyModule { constructor(appRef: ApplicationRef) { appRef.bootstrap(MainComponent); } } // offline compile import {bootstrapModuleFactory} from ‘@angular/platform-browser’; bootstrapModuleFactory(MyModuleNgFactory); // runtime compile long form import {bootstrapModule} from ‘@angular/platform-browser-dynamic’; bootstrapModule(MyModule); ``` The short form, `bootstrap(...)`, can now creates a module on the fly, given `directives`, `pipes, `providers`, `precompile` and `modules` properties. Related changes: - make `SanitizationService`, `SecurityContext` public in `@angular/core` so that the offline compiler can resolve the token - move `AnimationDriver` to `platform-browser` and make it public so that the offline compiler can resolve the token BREAKING CHANGES: - short form bootstrap does no longer allow to inject compiler internals (i.e. everything from `@angular/compiler). Inject `Compiler` instead. To provide custom providers for the compiler, create a custom compiler via `browserCompiler({providers: [...]})` and pass that into the `bootstrap` method. --- modules/@angular/compiler-cli/README.md | 27 ++- .../src/a/multiple_components.ts | 2 +- .../compiler-cli/integrationtest/src/basic.ts | 6 +- .../integrationtest/src/bootstrap.ts | 12 +- .../integrationtest/src/module.ts | 24 +++ .../src/{app_module.ts => module_fixtures.ts} | 4 +- .../integrationtest/src/precompile.ts | 7 +- .../integrationtest/src/projection.ts | 6 +- .../integrationtest/test/animate_spec.ts | 45 ++--- .../integrationtest/test/app_module_spec.ts | 48 ++---- .../integrationtest/test/basic_spec.ts | 47 ++--- .../integrationtest/test/i18n_spec.ts | 6 +- .../compiler-cli/integrationtest/test/init.ts | 18 ++ .../integrationtest/test/precompile_spec.ts | 21 +-- .../integrationtest/test/projection_spec.ts | 21 +-- .../integrationtest/test/query_spec.ts | 33 ++-- .../compiler-cli/integrationtest/test/util.ts | 29 ++++ .../compiler-cli/src/static_reflector.ts | 36 ++-- .../test/static_reflector_spec.ts | 7 + modules/@angular/compiler/core_private.ts | 9 +- modules/@angular/compiler/src/compiler.ts | 4 + modules/@angular/compiler/src/identifiers.ts | 4 +- .../compiler/src/metadata_resolver.ts | 42 +++-- .../@angular/compiler/src/runtime_compiler.ts | 76 ++++++-- .../src/schema/dom_element_schema_registry.ts | 3 +- .../src/schema/dom_security_schema.ts | 2 +- modules/@angular/compiler/src/template_ast.ts | 2 +- .../@angular/compiler/src/template_parser.ts | 4 +- .../src/view_compiler/property_binder.ts | 4 +- .../dom_element_schema_registry_spec.ts | 3 +- .../compiler/test/template_parser_spec.ts | 2 +- .../compiler/testing/schema_registry_mock.ts | 2 +- modules/@angular/core/core.dart | 2 +- modules/@angular/core/index.ts | 6 +- modules/@angular/core/private_export.ts | 13 -- .../core/src/application_common_providers.ts | 26 ++- modules/@angular/core/src/application_ref.ts | 56 ++++-- .../@angular/core/src/application_tokens.ts | 4 +- modules/@angular/core/src/linker/compiler.ts | 14 +- modules/@angular/core/src/linker/view.ts | 1 - modules/@angular/core/src/security.ts | 3 +- .../animation/animation_integration_spec.ts | 4 +- .../core/test/application_ref_spec.ts | 4 +- .../linker/app_module_integration_spec.ts | 37 +++- .../change_detection_integration_spec.ts | 12 +- .../core/testing/component_fixture.ts | 2 +- .../@angular/core/testing/testing_internal.ts | 1 - .../forms/ts/ng_validators/ng_validators.ts | 2 +- .../platform-browser-dynamic/index.ts | 162 ++++++++++++++++-- .../platform_browser_private.ts | 1 + .../@angular/platform-browser/core_private.ts | 12 -- modules/@angular/platform-browser/index.ts | 10 +- .../platform-browser/private_export.ts | 5 +- .../@angular/platform-browser/src/browser.ts | 66 ++++++- .../src/dom}/animation_driver.ts | 22 ++- .../src/dom/debug/ng_probe.ts | 2 +- .../platform-browser/src/dom/dom_renderer.ts | 3 +- .../src/dom/web_animations_driver.ts | 3 +- .../src/security/dom_sanitization_service.ts | 4 +- .../platform-browser/src/worker_render.ts | 5 +- .../test/browser/bootstrap_spec.ts | 63 ++++++- .../platform-browser/testing/browser.ts | 5 +- .../testing}/mock_animation_driver.ts | 12 +- .../@angular/platform-server/core_private.ts | 4 - .../platform-server/testing/server.ts | 5 +- modules/playground/README.md | 6 + modules/playground/src/bootstrap.ts | 6 +- tools/public_api_guard/core/index.d.ts | 30 ++-- tools/public_api_guard/core/testing.d.ts | 2 +- .../platform-browser-dynamic/index.d.ts | 12 +- .../platform-browser/index.d.ts | 16 +- 71 files changed, 793 insertions(+), 406 deletions(-) create mode 100644 modules/@angular/compiler-cli/integrationtest/src/module.ts rename modules/@angular/compiler-cli/integrationtest/src/{app_module.ts => module_fixtures.ts} (89%) create mode 100644 modules/@angular/compiler-cli/integrationtest/test/init.ts create mode 100644 modules/@angular/compiler-cli/integrationtest/test/util.ts rename modules/@angular/{core/src/animation => platform-browser/src/dom}/animation_driver.ts (69%) rename modules/@angular/{core/testing/animation => platform-browser/testing}/mock_animation_driver.ts (75%) create mode 100644 modules/playground/README.md diff --git a/modules/@angular/compiler-cli/README.md b/modules/@angular/compiler-cli/README.md index b4f8fc673c..7969e2a679 100644 --- a/modules/@angular/compiler-cli/README.md +++ b/modules/@angular/compiler-cli/README.md @@ -27,13 +27,30 @@ Then you can add an import statement in the `bootstrap` allowing you to bootstra generated code: ```typescript -import {ComponentResolver, ReflectiveInjector, coreBootstrap} from '@angular/core'; -import {BROWSER_APP_PROVIDERS, browserPlatform} from '@angular/platform-browser'; +main_module.ts +------------- +import {BrowserModule} from '@angular/platform-browser'; +import {Component, AppModule, ApplicationRef} from '@angular/core'; -import {MyComponentNgFactory} from './mycomponent.ngfactory'; +@Component(...) +export class MyComponent {} -const appInjector = ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS, browserPlatform().injector); -coreBootstrap(MyComponentNgFactory, appInjector); +@AppModule({ + modules: [BrowserModule], + precompile: [MyComponent] +}) +export class MainModule { + constructor(appRef: ApplicationRef) { + appRef.bootstrap(MyComponent); + } +} + +bootstrap.ts +------------- + +import {MainModuleNgFactory} from './main_module.ngfactory'; + +MainModuleNgFactory.create(browserPlatform().injector); ``` ## Configuration diff --git a/modules/@angular/compiler-cli/integrationtest/src/a/multiple_components.ts b/modules/@angular/compiler-cli/integrationtest/src/a/multiple_components.ts index e80da85482..854634661b 100644 --- a/modules/@angular/compiler-cli/integrationtest/src/a/multiple_components.ts +++ b/modules/@angular/compiler-cli/integrationtest/src/a/multiple_components.ts @@ -12,7 +12,7 @@ import {Component} from '@angular/core'; selector: 'my-comp', template: '
', }) -export class MyComp { +export class MultipleComponentsMyComp { } @Component({ diff --git a/modules/@angular/compiler-cli/integrationtest/src/basic.ts b/modules/@angular/compiler-cli/integrationtest/src/basic.ts index 54964def67..62cd26427a 100644 --- a/modules/@angular/compiler-cli/integrationtest/src/basic.ts +++ b/modules/@angular/compiler-cli/integrationtest/src/basic.ts @@ -9,16 +9,16 @@ import {FORM_DIRECTIVES, NgFor, NgIf} from '@angular/common'; import {Component, Inject} from '@angular/core'; -import {MyComp} from './a/multiple_components'; +import {MultipleComponentsMyComp} from './a/multiple_components'; @Component({ selector: 'basic', templateUrl: './basic.html', styles: ['.red { color: red }'], styleUrls: ['./basic.css'], - directives: [MyComp, FORM_DIRECTIVES, NgIf, NgFor] + directives: [MultipleComponentsMyComp, FORM_DIRECTIVES, NgIf, NgFor] }) -export class Basic { +export class BasicComp { ctxProp: string; ctxBool: boolean; ctxArr: any[] = []; diff --git a/modules/@angular/compiler-cli/integrationtest/src/bootstrap.ts b/modules/@angular/compiler-cli/integrationtest/src/bootstrap.ts index 4a5b51542e..49e82322c2 100644 --- a/modules/@angular/compiler-cli/integrationtest/src/bootstrap.ts +++ b/modules/@angular/compiler-cli/integrationtest/src/bootstrap.ts @@ -6,12 +6,8 @@ * found in the LICENSE file at https://angular.io/license */ -import {ReflectiveInjector, coreBootstrap} from '@angular/core'; -import {BROWSER_APP_PROVIDERS, browserPlatform} from '@angular/platform-browser'; +import {browserPlatform} from '@angular/platform-browser'; +import {BasicComp} from './basic'; +import {MainModuleNgFactory} from './module.ngfactory'; -import {Basic} from './basic'; -import {BasicNgFactory} from './basic.ngfactory'; - -const appInjector = - ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS, browserPlatform().injector); -coreBootstrap(BasicNgFactory, appInjector); +MainModuleNgFactory.create().instance.appRef.bootstrap(BasicComp); diff --git a/modules/@angular/compiler-cli/integrationtest/src/module.ts b/modules/@angular/compiler-cli/integrationtest/src/module.ts new file mode 100644 index 0000000000..b8c5429cae --- /dev/null +++ b/modules/@angular/compiler-cli/integrationtest/src/module.ts @@ -0,0 +1,24 @@ +/** + * @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 {AppModule, ApplicationRef} from '@angular/core'; +import {BrowserModule} from '@angular/platform-browser'; + +import {AnimateCmp} from './animate'; +import {BasicComp} from './basic'; +import {CompWithPrecompile} from './precompile'; +import {ProjectingComp} from './projection'; +import {CompWithChildQuery} from './queries'; + +@AppModule({ + modules: [BrowserModule], + precompile: [AnimateCmp, BasicComp, CompWithPrecompile, ProjectingComp, CompWithChildQuery] +}) +export class MainModule { + constructor(public appRef: ApplicationRef) {} +} diff --git a/modules/@angular/compiler-cli/integrationtest/src/app_module.ts b/modules/@angular/compiler-cli/integrationtest/src/module_fixtures.ts similarity index 89% rename from modules/@angular/compiler-cli/integrationtest/src/app_module.ts rename to modules/@angular/compiler-cli/integrationtest/src/module_fixtures.ts index 4c2c794e5a..1bb5791ca6 100644 --- a/modules/@angular/compiler-cli/integrationtest/src/app_module.ts +++ b/modules/@angular/compiler-cli/integrationtest/src/module_fixtures.ts @@ -8,6 +8,7 @@ import {LowerCasePipe, NgIf} from '@angular/common'; import {AppModule, Component, ComponentFactoryResolver, Injectable} from '@angular/core'; +import {BrowserModule} from '@angular/platform-browser'; @Injectable() export class SomeService { @@ -39,7 +40,7 @@ export class NestedModule { pipes: [LowerCasePipe], providers: [SomeService], precompile: [SomeComp], - modules: [NestedModule] + modules: [NestedModule, BrowserModule] }) export class SomeModule { } @@ -48,6 +49,7 @@ export class SomeModule { directives: [NgIf], pipes: [LowerCasePipe], precompile: [ParentComp], + modules: [BrowserModule] }) export class SomeModuleUsingParentComp { } diff --git a/modules/@angular/compiler-cli/integrationtest/src/precompile.ts b/modules/@angular/compiler-cli/integrationtest/src/precompile.ts index 32172c0eea..e6cc5d31bc 100644 --- a/modules/@angular/compiler-cli/integrationtest/src/precompile.ts +++ b/modules/@angular/compiler-cli/integrationtest/src/precompile.ts @@ -7,12 +7,9 @@ */ import {Component, ComponentFactoryResolver, Inject, OpaqueToken} from '@angular/core'; +import {BasicComp} from './basic'; -@Component({selector: 'cmp', template: ''}) -export class SomeComp { -} - -@Component({selector: 'cmp-precompile', template: '', precompile: [SomeComp]}) +@Component({selector: 'cmp-precompile', template: '', precompile: [BasicComp]}) export class CompWithPrecompile { constructor(public cfr: ComponentFactoryResolver) {} } diff --git a/modules/@angular/compiler-cli/integrationtest/src/projection.ts b/modules/@angular/compiler-cli/integrationtest/src/projection.ts index 4191c4abf0..9a979f6a65 100644 --- a/modules/@angular/compiler-cli/integrationtest/src/projection.ts +++ b/modules/@angular/compiler-cli/integrationtest/src/projection.ts @@ -9,13 +9,13 @@ import {Component} from '@angular/core'; @Component({selector: 'comp-with-proj', template: ''}) -export class CompWithProjection { +export class CompWithNgContent { } @Component({ selector: 'main', template: '', - directives: [CompWithProjection] + directives: [CompWithNgContent] }) -export class MainComp { +export class ProjectingComp { } diff --git a/modules/@angular/compiler-cli/integrationtest/test/animate_spec.ts b/modules/@angular/compiler-cli/integrationtest/test/animate_spec.ts index 1d0c865f7f..5c06381f71 100644 --- a/modules/@angular/compiler-cli/integrationtest/test/animate_spec.ts +++ b/modules/@angular/compiler-cli/integrationtest/test/animate_spec.ts @@ -5,19 +5,10 @@ * 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 */ - -require('reflect-metadata'); -require('zone.js/dist/zone-node.js'); -require('zone.js/dist/long-stack-trace-zone.js'); - -import {AnimateCmpNgFactory} from '../src/animate.ngfactory'; -import {ReflectiveInjector, DebugElement, getDebugNode, lockRunMode} from '@angular/core'; -import {serverPlatform} from '@angular/platform-server'; -import {BROWSER_APP_PROVIDERS} from '@angular/platform-browser'; - - -// Need to lock the mode explicitely as this test is not using Angular's testing framework. -lockRunMode(); +import './init'; +import {DebugElement} from '@angular/core'; +import {AnimateCmp} from '../src/animate'; +import {createComponent} from './util'; describe('template codegen output', () => { function findTargetElement(elm: DebugElement): DebugElement { @@ -27,23 +18,21 @@ describe('template codegen output', () => { } it('should apply the animate states to the element', (done) => { - const appInjector = - ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS, serverPlatform().injector); - var comp = AnimateCmpNgFactory.create(appInjector); - var debugElement = getDebugNode(comp.location.nativeElement); + const compFixture = createComponent(AnimateCmp); + var debugElement = compFixture.debugElement; var targetDebugElement = findTargetElement(debugElement); - comp.instance.setAsOpen(); - comp.changeDetectorRef.detectChanges(); + compFixture.componentInstance.setAsOpen(); + compFixture.detectChanges(); setTimeout(() => { expect(targetDebugElement.styles['height']).toEqual(null); expect(targetDebugElement.styles['borderColor']).toEqual('green'); expect(targetDebugElement.styles['color']).toEqual('green'); - comp.instance.setAsClosed(); - comp.changeDetectorRef.detectChanges(); + compFixture.componentInstance.setAsClosed(); + compFixture.detectChanges(); setTimeout(() => { expect(targetDebugElement.styles['height']).toEqual('0px'); @@ -55,23 +44,21 @@ describe('template codegen output', () => { }); it('should apply the default animate state to the element', (done) => { - const appInjector = - ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS, serverPlatform().injector); - var comp = AnimateCmpNgFactory.create(appInjector); - var debugElement = getDebugNode(comp.location.nativeElement); + const compFixture = createComponent(AnimateCmp); + var debugElement = compFixture.debugElement; var targetDebugElement = findTargetElement(debugElement); - comp.instance.setAsSomethingElse(); - comp.changeDetectorRef.detectChanges(); + compFixture.componentInstance.setAsSomethingElse(); + compFixture.detectChanges(); setTimeout(() => { expect(targetDebugElement.styles['height']).toEqual(null); expect(targetDebugElement.styles['borderColor']).toEqual('black'); expect(targetDebugElement.styles['color']).toEqual('black'); - comp.instance.setAsClosed(); - comp.changeDetectorRef.detectChanges(); + compFixture.componentInstance.setAsClosed(); + compFixture.detectChanges(); setTimeout(() => { expect(targetDebugElement.styles['height']).not.toEqual(null); diff --git a/modules/@angular/compiler-cli/integrationtest/test/app_module_spec.ts b/modules/@angular/compiler-cli/integrationtest/test/app_module_spec.ts index 49c4637713..8c58578deb 100644 --- a/modules/@angular/compiler-cli/integrationtest/test/app_module_spec.ts +++ b/modules/@angular/compiler-cli/integrationtest/test/app_module_spec.ts @@ -5,68 +5,52 @@ * 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 {ComponentFactoryResolver, DebugElement, ReflectiveInjector, getDebugNode, lockRunMode} from '@angular/core'; -import {BROWSER_APP_PROVIDERS, By} from '@angular/platform-browser'; -import {serverPlatform} from '@angular/platform-server'; - -import {NestedModule, NestedService, ParentComp, SomeComp, SomeModule, SomeService} from '../src/app_module'; -import {SomeModuleNgFactory, SomeModuleUsingParentCompNgFactory} from '../src/app_module.ngfactory'; - - -// Need to lock the mode explicitely as this test is not using Angular's testing framework. -lockRunMode(); +import './init'; +import {NestedModule, NestedService, ParentComp, SomeComp, SomeModule, SomeService} from '../src/module_fixtures'; +import {SomeModuleNgFactory, SomeModuleUsingParentCompNgFactory} from '../src/module_fixtures.ngfactory'; +import {createComponent, createModule} from './util'; describe('AppModule', () => { it('should support providers', () => { - var moduleRef = SomeModuleNgFactory.create(); + var moduleRef = createModule(SomeModuleNgFactory); expect(moduleRef.instance instanceof SomeModule).toBe(true); expect(moduleRef.injector.get(SomeModule) instanceof SomeModule).toBe(true); expect(moduleRef.injector.get(SomeService) instanceof SomeService).toBe(true); }); it('should support precompile components', () => { - const appInjector = - ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS, serverPlatform().injector); - var moduleRef = SomeModuleNgFactory.create(appInjector); - var cf = moduleRef.injector.get(ComponentFactoryResolver).resolveComponentFactory(SomeComp); + var moduleRef = createModule(SomeModuleNgFactory); + var cf = moduleRef.componentFactoryResolver.resolveComponentFactory(SomeComp); expect(cf.componentType).toBe(SomeComp); - var comp = cf.create(moduleRef.injector); + var compRef = cf.create(moduleRef.injector); + expect(compRef.instance instanceof SomeComp).toBe(true); }); it('should support module directives and pipes', () => { - const appInjector = - ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS, serverPlatform().injector); - var moduleRef = SomeModuleNgFactory.create(appInjector); - var cf = moduleRef.injector.get(ComponentFactoryResolver).resolveComponentFactory(SomeComp); - var comp = cf.create(moduleRef.injector); - var debugElement = getDebugNode(comp.location.nativeElement); + var compFixture = createComponent(SomeComp, SomeModuleNgFactory); + var debugElement = compFixture.debugElement; // NgIf should work, is being used as module directive expect(debugElement.children.length).toBe(1); - comp.changeDetectorRef.detectChanges(); + compFixture.detectChanges(); expect(debugElement.children.length).toBe(2); expect(debugElement.children[0].properties['title']).toBe('hello'); }); it('should support module directives and pipes on nested components', () => { - const appInjector = - ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS, serverPlatform().injector); - var moduleRef = SomeModuleUsingParentCompNgFactory.create(appInjector); - var cf = moduleRef.injector.get(ComponentFactoryResolver).resolveComponentFactory(ParentComp); - var comp = cf.create(moduleRef.injector); - var debugElement = getDebugNode(comp.location.nativeElement); + var compFixture = createComponent(ParentComp, SomeModuleUsingParentCompNgFactory); + var debugElement = compFixture.debugElement; debugElement = debugElement.children[0]; // NgIf should work, is being used as module directive expect(debugElement.children.length).toBe(1); - comp.changeDetectorRef.detectChanges(); + compFixture.detectChanges(); expect(debugElement.children.length).toBe(2); expect(debugElement.children[0].properties['title']).toBe('hello'); }); it('should support child moduless', () => { - var moduleRef = SomeModuleNgFactory.create(); + var moduleRef = createModule(SomeModuleNgFactory); expect(moduleRef.instance instanceof SomeModule).toBe(true); expect(moduleRef.injector.get(NestedModule) instanceof NestedModule).toBe(true); expect(moduleRef.injector.get(NestedService) instanceof NestedService).toBe(true); diff --git a/modules/@angular/compiler-cli/integrationtest/test/basic_spec.ts b/modules/@angular/compiler-cli/integrationtest/test/basic_spec.ts index 8ace343d9b..c2c6820b92 100644 --- a/modules/@angular/compiler-cli/integrationtest/test/basic_spec.ts +++ b/modules/@angular/compiler-cli/integrationtest/test/basic_spec.ts @@ -5,24 +5,13 @@ * 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 */ - -// Only needed to satisfy the check in core/src/util/decorators.ts -// TODO(alexeagle): maybe remove that check? -require('reflect-metadata'); - -require('zone.js/dist/zone-node.js'); -require('zone.js/dist/long-stack-trace-zone.js'); - +import './init'; import * as fs from 'fs'; import * as path from 'path'; -import {BasicNgFactory} from '../src/basic.ngfactory'; -import {MyComp} from '../src/a/multiple_components'; -import {ReflectiveInjector, DebugElement, getDebugNode, lockRunMode} from '@angular/core'; -import {BROWSER_APP_PROVIDERS} from '@angular/platform-browser'; -import {serverPlatform} from '@angular/platform-server'; -// Need to lock the mode explicitely as this test is not using Angular's testing framework. -lockRunMode(); +import {MultipleComponentsMyComp} from '../src/a/multiple_components'; +import {BasicComp} from '../src/basic'; +import {createComponent} from './util'; describe('template codegen output', () => { const outDir = 'src'; @@ -48,35 +37,29 @@ describe('template codegen output', () => { }); it('should be able to create the basic component', () => { - const appInjector = - ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS, serverPlatform().injector); - var comp = BasicNgFactory.create(appInjector); - expect(comp.instance).toBeTruthy(); + var compFixture = createComponent(BasicComp); + expect(compFixture.componentInstance).toBeTruthy(); }); it('should support ngIf', () => { - const appInjector = - ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS, serverPlatform().injector); - var comp = BasicNgFactory.create(appInjector); - var debugElement = getDebugNode(comp.location.nativeElement); + var compFixture = createComponent(BasicComp); + var debugElement = compFixture.debugElement; expect(debugElement.children.length).toBe(2); - comp.instance.ctxBool = true; - comp.changeDetectorRef.detectChanges(); + compFixture.componentInstance.ctxBool = true; + compFixture.detectChanges(); expect(debugElement.children.length).toBe(3); - expect(debugElement.children[2].injector.get(MyComp)).toBeTruthy(); + expect(debugElement.children[2].injector.get(MultipleComponentsMyComp)).toBeTruthy(); }); it('should support ngFor', () => { - const appInjector = - ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS, serverPlatform().injector); - var comp = BasicNgFactory.create(appInjector); - var debugElement = getDebugNode(comp.location.nativeElement); + var compFixture = createComponent(BasicComp); + var debugElement = compFixture.debugElement; expect(debugElement.children.length).toBe(2); // test NgFor - comp.instance.ctxArr = [1, 2]; - comp.changeDetectorRef.detectChanges(); + compFixture.componentInstance.ctxArr = [1, 2]; + compFixture.detectChanges(); expect(debugElement.children.length).toBe(4); expect(debugElement.children[2].attributes['value']).toBe('1'); expect(debugElement.children[3].attributes['value']).toBe('2'); diff --git a/modules/@angular/compiler-cli/integrationtest/test/i18n_spec.ts b/modules/@angular/compiler-cli/integrationtest/test/i18n_spec.ts index e1aefd2d28..064eb21110 100644 --- a/modules/@angular/compiler-cli/integrationtest/test/i18n_spec.ts +++ b/modules/@angular/compiler-cli/integrationtest/test/i18n_spec.ts @@ -6,11 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -// Only needed to satisfy the check in core/src/util/decorators.ts -// TODO(alexeagle): maybe remove that check? -require('reflect-metadata'); -require('zone.js/dist/zone-node.js'); -require('zone.js/dist/long-stack-trace-zone.js'); +import './init'; let serializer = require('@angular/compiler/src/i18n/xmb_serializer.js'); import * as fs from 'fs'; diff --git a/modules/@angular/compiler-cli/integrationtest/test/init.ts b/modules/@angular/compiler-cli/integrationtest/test/init.ts new file mode 100644 index 0000000000..a1f5703231 --- /dev/null +++ b/modules/@angular/compiler-cli/integrationtest/test/init.ts @@ -0,0 +1,18 @@ +/** + * @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 + */ + +// Only needed to satisfy the check in core/src/util/decorators.ts +// TODO(alexeagle): maybe remove that check? +require('reflect-metadata'); + +require('zone.js/dist/zone-node.js'); +require('zone.js/dist/long-stack-trace-zone.js'); + +import {lockRunMode} from '@angular/core'; +// Need to lock the mode explicitely as this test is not using Angular's testing framework. +lockRunMode(); diff --git a/modules/@angular/compiler-cli/integrationtest/test/precompile_spec.ts b/modules/@angular/compiler-cli/integrationtest/test/precompile_spec.ts index 722ec5c8db..c9dc1679ac 100644 --- a/modules/@angular/compiler-cli/integrationtest/test/precompile_spec.ts +++ b/modules/@angular/compiler-cli/integrationtest/test/precompile_spec.ts @@ -6,22 +6,15 @@ * found in the LICENSE file at https://angular.io/license */ -import {DebugElement, ReflectiveInjector, getDebugNode, lockRunMode} from '@angular/core'; -import {BROWSER_APP_PROVIDERS, By} from '@angular/platform-browser'; -import {serverPlatform} from '@angular/platform-server'; - -import {SomeComp} from '../src/precompile'; -import {CompWithPrecompileNgFactory} from '../src/precompile.ngfactory'; - -// Need to lock the mode explicitely as this test is not using Angular's testing framework. -lockRunMode(); +import './init'; +import {BasicComp} from '../src/basic'; +import {CompWithPrecompile} from '../src/precompile'; +import {createComponent} from './util'; describe('content projection', () => { it('should support basic content projection', () => { - const appInjector = - ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS, serverPlatform().injector); - var compWithPrecompile = CompWithPrecompileNgFactory.create(appInjector).instance; - var cf = compWithPrecompile.cfr.resolveComponentFactory(SomeComp); - expect(cf.componentType).toBe(SomeComp); + var compFixture = createComponent(CompWithPrecompile); + var cf = compFixture.componentInstance.cfr.resolveComponentFactory(BasicComp); + expect(cf.componentType).toBe(BasicComp); }); }); diff --git a/modules/@angular/compiler-cli/integrationtest/test/projection_spec.ts b/modules/@angular/compiler-cli/integrationtest/test/projection_spec.ts index cd95399906..4d150a56fa 100644 --- a/modules/@angular/compiler-cli/integrationtest/test/projection_spec.ts +++ b/modules/@angular/compiler-cli/integrationtest/test/projection_spec.ts @@ -6,24 +6,17 @@ * found in the LICENSE file at https://angular.io/license */ -import {DebugElement, ReflectiveInjector, getDebugNode, lockRunMode} from '@angular/core'; -import {BROWSER_APP_PROVIDERS, By} from '@angular/platform-browser'; -import {serverPlatform} from '@angular/platform-server'; - -import {CompWithProjection} from '../src/projection'; -import {MainCompNgFactory} from '../src/projection.ngfactory'; - -// Need to lock the mode explicitely as this test is not using Angular's testing framework. -lockRunMode(); +import './init'; +import {By} from '@angular/platform-browser'; +import {CompWithNgContent, ProjectingComp} from '../src/projection'; +import {createComponent} from './util'; describe('content projection', () => { it('should support basic content projection', () => { - const appInjector = - ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS, serverPlatform().injector); - var mainComp = MainCompNgFactory.create(appInjector); + var mainCompFixture = createComponent(ProjectingComp); - var debugElement = getDebugNode(mainComp.location.nativeElement); - var compWithProjection = debugElement.query(By.directive(CompWithProjection)); + var debugElement = mainCompFixture.debugElement; + var compWithProjection = debugElement.query(By.directive(CompWithNgContent)); expect(compWithProjection.children.length).toBe(1); expect(compWithProjection.children[0].attributes['greeting']).toEqual('Hello world!'); }); diff --git a/modules/@angular/compiler-cli/integrationtest/test/query_spec.ts b/modules/@angular/compiler-cli/integrationtest/test/query_spec.ts index c4fab5c590..30adb61f93 100644 --- a/modules/@angular/compiler-cli/integrationtest/test/query_spec.ts +++ b/modules/@angular/compiler-cli/integrationtest/test/query_spec.ts @@ -6,37 +6,30 @@ * found in the LICENSE file at https://angular.io/license */ -import {DebugElement, QueryList, ReflectiveInjector, getDebugNode, lockRunMode} from '@angular/core'; -import {BROWSER_APP_PROVIDERS, By} from '@angular/platform-browser'; -import {serverPlatform} from '@angular/platform-server'; - +import './init'; +import {DebugElement, QueryList} from '@angular/core'; +import {By} from '@angular/platform-browser'; import {CompForChildQuery, CompWithChildQuery} from '../src/queries'; -import {CompWithChildQueryNgFactory} from '../src/queries.ngfactory'; +import {createComponent} from './util'; describe('child queries', () => { it('should support compiling child queries', () => { - const appInjector = - ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS, serverPlatform().injector); - var childQueryComp = CompWithChildQueryNgFactory.create(appInjector); - - var debugElement = getDebugNode(childQueryComp.location.nativeElement); + var childQueryCompFixture = createComponent(CompWithChildQuery); + var debugElement = childQueryCompFixture.debugElement; var compWithChildren = debugElement.query(By.directive(CompWithChildQuery)); - expect(childQueryComp.instance.child).toBeDefined(); - expect(childQueryComp.instance.child instanceof CompForChildQuery).toBe(true); + expect(childQueryCompFixture.componentInstance.child).toBeDefined(); + expect(childQueryCompFixture.componentInstance.child instanceof CompForChildQuery).toBe(true); }); it('should support compiling children queries', () => { - const appInjector = - ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS, serverPlatform().injector); - var childQueryComp = CompWithChildQueryNgFactory.create(appInjector); - - var debugElement = getDebugNode(childQueryComp.location.nativeElement); + var childQueryCompFixture = createComponent(CompWithChildQuery); + var debugElement = childQueryCompFixture.debugElement; var compWithChildren = debugElement.query(By.directive(CompWithChildQuery)); - childQueryComp.changeDetectorRef.detectChanges(); + childQueryCompFixture.detectChanges(); - expect(childQueryComp.instance.children).toBeDefined(); - expect(childQueryComp.instance.children instanceof QueryList).toBe(true); + expect(childQueryCompFixture.componentInstance.children).toBeDefined(); + expect(childQueryCompFixture.componentInstance.children instanceof QueryList).toBe(true); }); }); diff --git a/modules/@angular/compiler-cli/integrationtest/test/util.ts b/modules/@angular/compiler-cli/integrationtest/test/util.ts new file mode 100644 index 0000000000..9f2892888b --- /dev/null +++ b/modules/@angular/compiler-cli/integrationtest/test/util.ts @@ -0,0 +1,29 @@ +/** + * @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 {AppModuleFactory, AppModuleRef} from '@angular/core'; +import {ComponentFixture} from '@angular/core/testing'; +import {serverPlatform} from '@angular/platform-server'; + +import {MainModuleNgFactory} from '../src/module.ngfactory'; + +export function createModule(factory: AppModuleFactory): AppModuleRef { + return factory.create(serverPlatform().injector); +} + +export function createComponent( + comp: {new (...args: any[]): C}, + moduleFactory: AppModuleFactory = null): ComponentFixture { + if (!moduleFactory) { + moduleFactory = MainModuleNgFactory; + } + const moduleRef = createModule(moduleFactory); + const compRef = + moduleRef.componentFactoryResolver.resolveComponentFactory(comp).create(moduleRef.injector); + return new ComponentFixture(compRef, null, null); +} diff --git a/modules/@angular/compiler-cli/src/static_reflector.ts b/modules/@angular/compiler-cli/src/static_reflector.ts index 6109b64c5b..d93f4f0000 100644 --- a/modules/@angular/compiler-cli/src/static_reflector.ts +++ b/modules/@angular/compiler-cli/src/static_reflector.ts @@ -246,7 +246,7 @@ export class StaticReflector implements ReflectorReader { let calling = new Map(); function simplifyInContext(context: StaticSymbol, value: any, depth: number): any { - function resolveReference(expression: any): StaticSymbol { + function resolveReference(context: StaticSymbol, expression: any): StaticSymbol { let staticSymbol: StaticSymbol; if (expression['module']) { staticSymbol = _this.host.findDeclaration( @@ -257,25 +257,34 @@ export class StaticReflector implements ReflectorReader { return staticSymbol; } - function isOpaqueToken(value: any): boolean { + function resolveReferenceValue(staticSymbol: StaticSymbol): any { + let result: any = staticSymbol; + let moduleMetadata = _this.getModuleMetadata(staticSymbol.filePath); + let declarationValue = + moduleMetadata ? moduleMetadata['metadata'][staticSymbol.name] : null; + return declarationValue; + } + + function isOpaqueToken(context: StaticSymbol, value: any): boolean { if (value && value.__symbolic === 'new' && value.expression) { let target = value.expression; if (target.__symbolic == 'reference') { - return sameSymbol(resolveReference(target), _this.opaqueToken); + return sameSymbol(resolveReference(context, target), _this.opaqueToken); } } return false; } function simplifyCall(expression: any) { - let context: {[name: string]: string}|undefined = undefined; + let callContext: {[name: string]: string}|undefined = undefined; if (expression['__symbolic'] == 'call') { let target = expression['expression']; + let targetFunction: any; if (target && target.__symbolic === 'reference') { - context = {name: target.name}; + callContext = {name: target.name}; + targetFunction = resolveReferenceValue(resolveReference(context, target)); } - let targetFunction = simplify(target); - if (targetFunction['__symbolic'] == 'function') { + if (targetFunction && targetFunction['__symbolic'] == 'function') { if (calling.get(targetFunction)) { throw new Error('Recursion not supported'); } @@ -309,7 +318,8 @@ export class StaticReflector implements ReflectorReader { // non-angular decorator, and we should just ignore it. return {__symbolic: 'ignore'}; } - return simplify({__symbolic: 'error', message: 'Function call not supported', context}); + return simplify( + {__symbolic: 'error', message: 'Function call not supported', context: callContext}); } function simplify(expression: any): any { @@ -421,13 +431,11 @@ export class StaticReflector implements ReflectorReader { return localValue; } } - staticSymbol = resolveReference(expression); + staticSymbol = resolveReference(context, expression); let result: any = staticSymbol; - let moduleMetadata = _this.getModuleMetadata(staticSymbol.filePath); - let declarationValue = - moduleMetadata ? moduleMetadata['metadata'][staticSymbol.name] : null; + let declarationValue = resolveReferenceValue(result); if (declarationValue) { - if (isOpaqueToken(declarationValue)) { + if (isOpaqueToken(staticSymbol, declarationValue)) { // If the referenced symbol is initalized by a new OpaqueToken we can keep the // reference to the symbol. return staticSymbol; @@ -438,7 +446,7 @@ export class StaticReflector implements ReflectorReader { case 'class': return context; case 'function': - return expression; + return context; case 'new': case 'call': // Determine if the function is a built-in conversion diff --git a/modules/@angular/compiler-cli/test/static_reflector_spec.ts b/modules/@angular/compiler-cli/test/static_reflector_spec.ts index 7b40419175..8d187d15a2 100644 --- a/modules/@angular/compiler-cli/test/static_reflector_spec.ts +++ b/modules/@angular/compiler-cli/test/static_reflector_spec.ts @@ -308,6 +308,13 @@ describe('StaticReflector', () => { .toEqual(host.getStaticSymbol('/src/extern.d.ts', 'nonExisting')); }); + it('should simplify a function reference as a static symbol', () => { + expect(simplify( + new StaticSymbol('/src/cases', 'myFunction'), + ({__symbolic: 'function', parameters: ['a'], value: []}))) + .toEqual(host.getStaticSymbol('/src/cases', 'myFunction')); + }); + it('should simplify values initialized with a function call', () => { expect(simplify(new StaticSymbol('/tmp/src/function-reference.ts', ''), { __symbolic: 'reference', diff --git a/modules/@angular/compiler/core_private.ts b/modules/@angular/compiler/core_private.ts index a47beb008c..2c0e252b30 100644 --- a/modules/@angular/compiler/core_private.ts +++ b/modules/@angular/compiler/core_private.ts @@ -48,10 +48,6 @@ export var ValueUnwrapper: typeof t.ValueUnwrapper = r.ValueUnwrapper; export var TemplateRef_: typeof t.TemplateRef_ = r.TemplateRef_; export type RenderDebugInfo = t.RenderDebugInfo; export var RenderDebugInfo: typeof t.RenderDebugInfo = r.RenderDebugInfo; -export var SecurityContext: typeof t.SecurityContext = r.SecurityContext; -export type SecurityContext = t.SecurityContext; -export var SanitizationService: typeof t.SanitizationService = r.SanitizationService; -export type SanitizationService = t.SanitizationService; export var createProvider: typeof t.createProvider = r.createProvider; export var isProviderLiteral: typeof t.isProviderLiteral = r.isProviderLiteral; export var EMPTY_ARRAY: typeof t.EMPTY_ARRAY = r.EMPTY_ARRAY; @@ -70,15 +66,12 @@ export var castByValue: typeof t.castByValue = r.castByValue; export type Console = t.Console; export var Console: typeof t.Console = r.Console; export var reflector: t.Reflector = r.reflector; +export var Reflector: typeof t.Reflector = r.Reflector; export type Reflector = t.Reflector; export type NoOpAnimationPlayer = t.NoOpAnimationPlayer; export var NoOpAnimationPlayer: typeof t.NoOpAnimationPlayer = r.NoOpAnimationPlayer; export type AnimationPlayer = t.AnimationPlayer; export var AnimationPlayer: typeof t.AnimationPlayer = r.AnimationPlayer; -export type NoOpAnimationDriver = t.NoOpAnimationDriver; -export var NoOpAnimationDriver: typeof t.NoOpAnimationDriver = r.NoOpAnimationDriver; -export type AnimationDriver = t.AnimationDriver; -export var AnimationDriver: typeof t.AnimationDriver = r.AnimationDriver; export type AnimationSequencePlayer = t.AnimationSequencePlayer; export var AnimationSequencePlayer: typeof t.AnimationSequencePlayer = r.AnimationSequencePlayer; export type AnimationGroupPlayer = t.AnimationGroupPlayer; diff --git a/modules/@angular/compiler/src/compiler.ts b/modules/@angular/compiler/src/compiler.ts index c6e2b61dba..f3229ad57a 100644 --- a/modules/@angular/compiler/src/compiler.ts +++ b/modules/@angular/compiler/src/compiler.ts @@ -38,6 +38,7 @@ import {Lexer} from './expression_parser/lexer'; import {ViewResolver} from './view_resolver'; import {DirectiveResolver} from './directive_resolver'; import {PipeResolver} from './pipe_resolver'; +import {Console, Reflector, reflector, ReflectorReader} from '../core_private'; /** * A set of providers that provide `RuntimeCompiler` and its dependencies to use for @@ -45,6 +46,9 @@ import {PipeResolver} from './pipe_resolver'; */ export const COMPILER_PROVIDERS: Array = /*@ts2dart_const*/[ + {provide: Reflector, useValue: reflector}, + {provide: ReflectorReader, useExisting: Reflector}, + Console, Lexer, Parser, HtmlParser, diff --git a/modules/@angular/compiler/src/identifiers.ts b/modules/@angular/compiler/src/identifiers.ts index f83a893813..0f72d3b24c 100644 --- a/modules/@angular/compiler/src/identifiers.ts +++ b/modules/@angular/compiler/src/identifiers.ts @@ -6,9 +6,9 @@ * found in the LICENSE file at https://angular.io/license */ -import {AppModuleFactory, ChangeDetectionStrategy, ChangeDetectorRef, ComponentFactory, ComponentFactoryResolver, ElementRef, Injector, QueryList, RenderComponentType, Renderer, SimpleChange, TemplateRef, ViewContainerRef, ViewEncapsulation} from '@angular/core'; +import {AppModuleFactory, ChangeDetectionStrategy, ChangeDetectorRef, ComponentFactory, ComponentFactoryResolver, ElementRef, Injector, QueryList, RenderComponentType, Renderer, SecurityContext, SimpleChange, TemplateRef, ViewContainerRef, ViewEncapsulation} from '@angular/core'; -import {AnimationGroupPlayer as AnimationGroupPlayer_, AnimationKeyframe as AnimationKeyframe_, AnimationSequencePlayer as AnimationSequencePlayer_, AnimationStyles as AnimationStyles_, AppElement, AppModuleInjector, AppView, ChangeDetectorStatus, CodegenComponentFactoryResolver, DebugAppView, DebugContext, EMPTY_ARRAY, EMPTY_MAP, NoOpAnimationPlayer as NoOpAnimationPlayer_, SecurityContext, StaticNodeDebugInfo, TemplateRef_, ValueUnwrapper, ViewType, ViewUtils, balanceAnimationKeyframes as impBalanceAnimationKeyframes, castByValue, checkBinding, clearStyles as impClearStyles, collectAndResolveStyles as impCollectAndResolveStyles, devModeEqual, flattenNestedViewRenderNodes, interpolate, prepareFinalAnimationStyles as impBalanceAnimationStyles, pureProxy1, pureProxy10, pureProxy2, pureProxy3, pureProxy4, pureProxy5, pureProxy6, pureProxy7, pureProxy8, pureProxy9, renderStyles as impRenderStyles, uninitialized} from '../core_private'; +import {AnimationGroupPlayer as AnimationGroupPlayer_, AnimationKeyframe as AnimationKeyframe_, AnimationSequencePlayer as AnimationSequencePlayer_, AnimationStyles as AnimationStyles_, AppElement, AppModuleInjector, AppView, ChangeDetectorStatus, CodegenComponentFactoryResolver, DebugAppView, DebugContext, EMPTY_ARRAY, EMPTY_MAP, NoOpAnimationPlayer as NoOpAnimationPlayer_, StaticNodeDebugInfo, TemplateRef_, ValueUnwrapper, ViewType, ViewUtils, balanceAnimationKeyframes as impBalanceAnimationKeyframes, castByValue, checkBinding, clearStyles as impClearStyles, collectAndResolveStyles as impCollectAndResolveStyles, devModeEqual, flattenNestedViewRenderNodes, interpolate, prepareFinalAnimationStyles as impBalanceAnimationStyles, pureProxy1, pureProxy10, pureProxy2, pureProxy3, pureProxy4, pureProxy5, pureProxy6, pureProxy7, pureProxy8, pureProxy9, renderStyles as impRenderStyles, uninitialized} from '../core_private'; import {CompileIdentifierMetadata, CompileTokenMetadata} from './compile_metadata'; import {assetUrl} from './util'; diff --git a/modules/@angular/compiler/src/metadata_resolver.ts b/modules/@angular/compiler/src/metadata_resolver.ts index 4d13f9abed..5f50985bfe 100644 --- a/modules/@angular/compiler/src/metadata_resolver.ts +++ b/modules/@angular/compiler/src/metadata_resolver.ts @@ -196,29 +196,11 @@ export class CompileMetadataResolver { throw new BaseException( `Could not compile '${stringify(moduleType)}' because it is not an AppModule.`); } - let providers: any[] = []; - if (meta.providers) { - providers.push(...this.getProvidersMetadata(meta.providers)); - } - - let directives: cpl.CompileTypeMetadata[] = []; - if (meta.directives) { - directives.push(...flattenArray(meta.directives) - .map(type => this.getTypeMetadata(type, staticTypeModuleUrl(type)))); - } - - let pipes: cpl.CompileTypeMetadata[] = []; - if (meta.pipes) { - pipes.push(...flattenArray(meta.pipes) - .map(type => this.getTypeMetadata(type, staticTypeModuleUrl(type)))); - } - - let precompile: cpl.CompileTypeMetadata[] = []; - if (meta.precompile) { - precompile.push(...flattenArray(meta.precompile) - .map(type => this.getTypeMetadata(type, staticTypeModuleUrl(type)))); - } let modules: cpl.CompileTypeMetadata[] = []; + let providers: any[] = []; + let directives: cpl.CompileTypeMetadata[] = []; + let pipes: cpl.CompileTypeMetadata[] = []; + let precompile: cpl.CompileTypeMetadata[] = []; if (meta.modules) { flattenArray(meta.modules).forEach((moduleType) => { var meta = this.getAppModuleMetadata(moduleType); @@ -231,6 +213,22 @@ export class CompileMetadataResolver { }); } + if (meta.providers) { + providers.push(...this.getProvidersMetadata(meta.providers)); + } + if (meta.directives) { + directives.push(...flattenArray(meta.directives) + .map(type => this.getTypeMetadata(type, staticTypeModuleUrl(type)))); + } + if (meta.pipes) { + pipes.push(...flattenArray(meta.pipes) + .map(type => this.getTypeMetadata(type, staticTypeModuleUrl(type)))); + } + if (meta.precompile) { + precompile.push(...flattenArray(meta.precompile) + .map(type => this.getTypeMetadata(type, staticTypeModuleUrl(type)))); + } + compileMeta = new cpl.CompileAppModuleMetadata({ type: this.getTypeMetadata(moduleType, staticTypeModuleUrl(moduleType)), providers: providers, diff --git a/modules/@angular/compiler/src/runtime_compiler.ts b/modules/@angular/compiler/src/runtime_compiler.ts index bf25ac5fe2..2eedc118e0 100644 --- a/modules/@angular/compiler/src/runtime_compiler.ts +++ b/modules/@angular/compiler/src/runtime_compiler.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {AppModuleFactory, AppModuleMetadata, Compiler, ComponentFactory, ComponentResolver, Injectable} from '@angular/core'; +import {AppModuleFactory, AppModuleMetadata, Compiler, ComponentFactory, ComponentResolver, Injectable, Provider} from '@angular/core'; import {BaseException} from '../src/facade/exceptions'; import {ConcreteType, IS_DART, Type, isBlank, isString, stringify} from '../src/facade/lang'; @@ -76,6 +76,14 @@ export class RuntimeCompiler implements ComponentResolver, Compiler { let componentCompilePromises: Promise[] = []; if (!appModuleFactory || !useCache) { var compileModuleMeta = this._metadataResolver.getAppModuleMetadata(moduleType, metadata); + let boundCompiler = new BoundCompiler( + this, compileModuleMeta.directives.map(dir => dir.type.runtime), + compileModuleMeta.pipes.map((pipe) => pipe.type.runtime)); + // Always provide a bound Compiler / ComponentResolver + compileModuleMeta.providers.push(this._metadataResolver.getProviderMetadata( + new Provider(Compiler, {useValue: boundCompiler}))); + compileModuleMeta.providers.push(this._metadataResolver.getProviderMetadata( + new Provider(ComponentResolver, {useExisting: Compiler}))); var compileResult = this._appModuleCompiler.compile(compileModuleMeta); compileResult.dependencies.forEach((dep) => { let compileResult = this._compileComponent( @@ -102,21 +110,18 @@ export class RuntimeCompiler implements ComponentResolver, Compiler { appModuleFactory, Promise.all(componentCompilePromises).then(() => appModuleFactory)); } - compileComponentAsync(compType: ConcreteType, {moduleDirectives = [], modulePipes = []}: { - moduleDirectives?: ConcreteType[], - modulePipes?: ConcreteType[] - } = {}): Promise> { - return this._compileComponent(compType, false, moduleDirectives, modulePipes).asyncResult; + compileComponentAsync(compType: ConcreteType): Promise> { + return this._compileComponent(compType, false, [], []).asyncResult; } - compileComponentSync(compType: ConcreteType, {moduleDirectives = [], modulePipes = []}: { - moduleDirectives?: ConcreteType[], - modulePipes?: ConcreteType[] - } = {}): ComponentFactory { - return this._compileComponent(compType, true, moduleDirectives, modulePipes).syncResult; + compileComponentSync(compType: ConcreteType): ComponentFactory { + return this._compileComponent(compType, true, [], []).syncResult; } - private _compileComponent( + /** + * @internal + */ + _compileComponent( compType: ConcreteType, isSync: boolean, moduleDirectives: ConcreteType[], modulePipes: ConcreteType[]): SyncAsyncResult> { var templates = @@ -343,3 +348,50 @@ function assertComponent(meta: CompileDirectiveMetadata) { throw new BaseException(`Could not compile '${meta.type.name}' because it is not a component.`); } } + +/** + * A wrapper around `Compiler` and `ComponentResolver` that + * provides default patform directives / pipes. + */ +class BoundCompiler implements Compiler, ComponentResolver { + constructor( + private _delegate: RuntimeCompiler, private _directives: any[], private _pipes: any[]) {} + + resolveComponent(component: Type|string): Promise> { + if (isString(component)) { + return PromiseWrapper.reject( + new BaseException(`Cannot resolve component using '${component}'.`), null); + } + return this.compileComponentAsync(>component); + } + + compileComponentAsync(compType: ConcreteType): Promise> { + return this._delegate._compileComponent(compType, false, this._directives, this._pipes) + .asyncResult; + } + + compileComponentSync(compType: ConcreteType): ComponentFactory { + return this._delegate._compileComponent(compType, true, this._directives, this._pipes) + .syncResult; + } + + compileAppModuleSync(moduleType: ConcreteType, metadata: AppModuleMetadata = null): + AppModuleFactory { + return this._delegate.compileAppModuleSync(moduleType, metadata); + } + + compileAppModuleAsync(moduleType: ConcreteType, metadata: AppModuleMetadata = null): + Promise> { + return this._delegate.compileAppModuleAsync(moduleType, metadata); + } + + /** + * Clears all caches + */ + clearCache(): void { this._delegate.clearCache(); } + + /** + * Clears the cache for the given component/appModule. + */ + clearCacheFor(type: Type) { this._delegate.clearCacheFor(type); } +} \ No newline at end of file diff --git a/modules/@angular/compiler/src/schema/dom_element_schema_registry.ts b/modules/@angular/compiler/src/schema/dom_element_schema_registry.ts index 9f9e6b0348..81a81a4263 100644 --- a/modules/@angular/compiler/src/schema/dom_element_schema_registry.ts +++ b/modules/@angular/compiler/src/schema/dom_element_schema_registry.ts @@ -6,9 +6,8 @@ * found in the LICENSE file at https://angular.io/license */ -import {Injectable} from '@angular/core'; +import {Injectable, SecurityContext} from '@angular/core'; -import {SecurityContext} from '../../core_private'; import {StringMapWrapper} from '../facade/collection'; import {isPresent} from '../facade/lang'; diff --git a/modules/@angular/compiler/src/schema/dom_security_schema.ts b/modules/@angular/compiler/src/schema/dom_security_schema.ts index 6fc40d1bcc..2fcdef119a 100644 --- a/modules/@angular/compiler/src/schema/dom_security_schema.ts +++ b/modules/@angular/compiler/src/schema/dom_security_schema.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {SecurityContext} from '../../core_private'; +import {SecurityContext} from '@angular/core'; // ================================================================================================= // ================================================================================================= diff --git a/modules/@angular/compiler/src/template_ast.ts b/modules/@angular/compiler/src/template_ast.ts index ce78210609..ab02652fbf 100644 --- a/modules/@angular/compiler/src/template_ast.ts +++ b/modules/@angular/compiler/src/template_ast.ts @@ -12,7 +12,7 @@ import {AST} from './expression_parser/ast'; import {CompileDirectiveMetadata, CompileTokenMetadata, CompileProviderMetadata,} from './compile_metadata'; import {ParseSourceSpan} from './parse_util'; -import {SecurityContext} from '../core_private'; +import {SecurityContext} from '@angular/core'; /** * An Abstract Syntax Tree node representing part of a parsed Angular template. diff --git a/modules/@angular/compiler/src/template_parser.ts b/modules/@angular/compiler/src/template_parser.ts index 29807b875b..b6b80cfc9e 100644 --- a/modules/@angular/compiler/src/template_parser.ts +++ b/modules/@angular/compiler/src/template_parser.ts @@ -6,9 +6,9 @@ * found in the LICENSE file at https://angular.io/license */ -import {Inject, Injectable, OpaqueToken, Optional} from '@angular/core'; +import {Inject, Injectable, OpaqueToken, Optional, SecurityContext} from '@angular/core'; -import {Console, MAX_INTERPOLATION_VALUES, SecurityContext} from '../core_private'; +import {Console, MAX_INTERPOLATION_VALUES} from '../core_private'; import {ListWrapper, StringMapWrapper, SetWrapper,} from '../src/facade/collection'; import {RegExpWrapper, isPresent, StringWrapper, isBlank, isArray} from '../src/facade/lang'; diff --git a/modules/@angular/compiler/src/view_compiler/property_binder.ts b/modules/@angular/compiler/src/view_compiler/property_binder.ts index 62ea63fae2..75f1d8542c 100644 --- a/modules/@angular/compiler/src/view_compiler/property_binder.ts +++ b/modules/@angular/compiler/src/view_compiler/property_binder.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {EMPTY_STATE as EMPTY_ANIMATION_STATE, LifecycleHooks, SecurityContext, isDefaultChangeDetectionStrategy} from '../../core_private'; +import {EMPTY_STATE as EMPTY_ANIMATION_STATE, LifecycleHooks, isDefaultChangeDetectionStrategy} from '../../core_private'; import * as cdAst from '../expression_parser/ast'; import {isBlank, isPresent} from '../facade/lang'; import {Identifiers} from '../identifiers'; @@ -25,7 +25,7 @@ import {camelCaseToDashCase} from '../util'; import {convertCdExpressionToIr} from './expression_converter'; import {CompileBinding} from './compile_binding'; -import {BaseException} from '@angular/core'; +import {BaseException, SecurityContext} from '@angular/core'; function createBindFieldExpr(exprIndex: number): o.ReadPropExpr { diff --git a/modules/@angular/compiler/test/schema/dom_element_schema_registry_spec.ts b/modules/@angular/compiler/test/schema/dom_element_schema_registry_spec.ts index 549b63ccb3..ff8a7cfdde 100644 --- a/modules/@angular/compiler/test/schema/dom_element_schema_registry_spec.ts +++ b/modules/@angular/compiler/test/schema/dom_element_schema_registry_spec.ts @@ -9,11 +9,10 @@ import {HtmlElementAst} from '@angular/compiler/src/html_ast'; import {HtmlParser} from '@angular/compiler/src/html_parser'; import {DomElementSchemaRegistry} from '@angular/compiler/src/schema/dom_element_schema_registry'; +import {SecurityContext} from '@angular/core'; import {beforeEach, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal'; import {browserDetection} from '@angular/platform-browser/testing/browser_util'; -import {SecurityContext} from '../../core_private'; - import {extractSchema} from './schema_extractor'; export function main() { diff --git a/modules/@angular/compiler/test/template_parser_spec.ts b/modules/@angular/compiler/test/template_parser_spec.ts index 7b1122fc7a..8bb2f12a5b 100644 --- a/modules/@angular/compiler/test/template_parser_spec.ts +++ b/modules/@angular/compiler/test/template_parser_spec.ts @@ -12,10 +12,10 @@ import {ElementSchemaRegistry} from '@angular/compiler/src/schema/element_schema import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, ElementAst, EmbeddedTemplateAst, NgContentAst, PropertyBindingType, ProviderAstType, ReferenceAst, TemplateAst, TemplateAstVisitor, TextAst, VariableAst, templateVisitAll} from '@angular/compiler/src/template_ast'; import {TEMPLATE_TRANSFORMS, TemplateParser, splitClasses} from '@angular/compiler/src/template_parser'; import {MockSchemaRegistry} from '@angular/compiler/testing'; +import {SecurityContext} from '@angular/core'; import {Console} from '@angular/core/src/console'; import {afterEach, beforeEach, beforeEachProviders, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal'; -import {SecurityContext} from '../core_private'; import {Identifiers, identifierToken} from '../src/identifiers'; import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from '../src/interpolation_config'; diff --git a/modules/@angular/compiler/testing/schema_registry_mock.ts b/modules/@angular/compiler/testing/schema_registry_mock.ts index 4445c48290..57c30fc6c5 100644 --- a/modules/@angular/compiler/testing/schema_registry_mock.ts +++ b/modules/@angular/compiler/testing/schema_registry_mock.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {SecurityContext} from '../core_private'; +import {SecurityContext} from '@angular/core'; import {ElementSchemaRegistry} from '../index'; import {isPresent} from '../src/facade/lang'; diff --git a/modules/@angular/core/core.dart b/modules/@angular/core/core.dart index 961b85624f..53f11e47a1 100644 --- a/modules/@angular/core/core.dart +++ b/modules/@angular/core/core.dart @@ -7,7 +7,7 @@ export './src/core/di.dart' hide ForwardRefFn, resolveForwardRef, forwardRef; export './src/facade/facade.dart'; export './src/core/application_ref.dart' show createPlatform, assertPlatform, disposePlatform, getPlatform, - coreLoadAndBootstrap, coreBootstrap, createNgZone, PlatformRef, ApplicationRef; + coreLoadAndBootstrap, coreBootstrap, PlatformRef, ApplicationRef; export './src/core/application_tokens.dart' show APP_ID, APP_INITIALIZER, PACKAGE_ROOT_URL, diff --git a/modules/@angular/core/index.ts b/modules/@angular/core/index.ts index 7faff82290..6f3d8cb9d2 100644 --- a/modules/@angular/core/index.ts +++ b/modules/@angular/core/index.ts @@ -14,7 +14,7 @@ export * from './src/metadata'; export * from './src/util'; export * from './src/di'; -export {createPlatform, assertPlatform, disposePlatform, getPlatform, coreBootstrap, coreLoadAndBootstrap, createNgZone, PlatformRef, ApplicationRef, enableProdMode, lockRunMode, isDevMode} from './src/application_ref'; +export {createPlatform, assertPlatform, disposePlatform, getPlatform, coreBootstrap, coreLoadAndBootstrap, PlatformRef, ApplicationRef, enableProdMode, lockRunMode, isDevMode} from './src/application_ref'; export {APP_ID, APP_INITIALIZER, PACKAGE_ROOT_URL, PLATFORM_INITIALIZER} from './src/application_tokens'; export * from './src/zone'; export * from './src/render'; @@ -24,7 +24,7 @@ export * from './src/testability/testability'; export * from './src/change_detection'; export * from './src/platform_directives_and_pipes'; export * from './src/platform_common_providers'; -export * from './src/application_common_providers'; +export {APPLICATION_COMMON_PROVIDERS} from './src/application_common_providers'; export {wtfCreateScope, wtfLeave, wtfStartTimeRange, wtfEndTimeRange, WtfScopeFn} from './src/profile/profile'; export {Type} from './src/facade/lang'; @@ -34,3 +34,5 @@ export * from './private_export'; export * from './src/animation/metadata'; export {AnimationPlayer} from './src/animation/animation_player'; + +export {SanitizationService, SecurityContext} from './src/security'; diff --git a/modules/@angular/core/private_export.ts b/modules/@angular/core/private_export.ts index 417e4e5180..907e20f9eb 100644 --- a/modules/@angular/core/private_export.ts +++ b/modules/@angular/core/private_export.ts @@ -8,7 +8,6 @@ import {Provider} from './index'; import {ANY_STATE as ANY_STATE_, DEFAULT_STATE as DEFAULT_STATE_, EMPTY_STATE as EMPTY_STATE_, FILL_STYLE_FLAG as FILL_STYLE_FLAG_} from './src/animation/animation_constants'; -import {AnimationDriver as AnimationDriver_, NoOpAnimationDriver as NoOpAnimationDriver_} from './src/animation/animation_driver'; import {AnimationGroupPlayer as AnimationGroupPlayer_} from './src/animation/animation_group_player'; import {AnimationKeyframe as AnimationKeyframe_} from './src/animation/animation_keyframe'; import {AnimationPlayer as AnimationPlayer_, NoOpAnimationPlayer as NoOpAnimationPlayer_} from './src/animation/animation_player'; @@ -77,10 +76,6 @@ export declare namespace __core_private_types__ { export var ValueUnwrapper: typeof change_detection_util.ValueUnwrapper; export type RenderDebugInfo = api.RenderDebugInfo; export var RenderDebugInfo: typeof api.RenderDebugInfo; - export type SecurityContext = security.SecurityContext; - export var SecurityContext: typeof security.SecurityContext; - export type SanitizationService = security.SanitizationService; - export var SanitizationService: typeof security.SanitizationService; export type TemplateRef_ = template_ref.TemplateRef_; export var TemplateRef_: typeof template_ref.TemplateRef_; export var wtfInit: typeof wtf_init.wtfInit; @@ -113,10 +108,6 @@ export declare namespace __core_private_types__ { export var NoOpAnimationPlayer: typeof NoOpAnimationPlayer_; export type AnimationPlayer = AnimationPlayer_; export var AnimationPlayer: typeof AnimationPlayer_; - export type NoOpAnimationDriver = NoOpAnimationDriver_; - export var NoOpAnimationDriver: typeof NoOpAnimationDriver_; - export type AnimationDriver = AnimationDriver_; - export var AnimationDriver: typeof AnimationDriver_; export type AnimationSequencePlayer = AnimationSequencePlayer_; export var AnimationSequencePlayer: typeof AnimationSequencePlayer_; export type AnimationGroupPlayer = AnimationGroupPlayer_; @@ -164,8 +155,6 @@ export var __core_private__ = { uninitialized: change_detection_util.uninitialized, ValueUnwrapper: change_detection_util.ValueUnwrapper, RenderDebugInfo: api.RenderDebugInfo, - SecurityContext: security.SecurityContext, - SanitizationService: security.SanitizationService, TemplateRef_: template_ref.TemplateRef_, wtfInit: wtf_init.wtfInit, ReflectionCapabilities: reflection_capabilities.ReflectionCapabilities, @@ -191,8 +180,6 @@ export var __core_private__ = { Reflector: reflection.Reflector, NoOpAnimationPlayer: NoOpAnimationPlayer_, AnimationPlayer: AnimationPlayer_, - NoOpAnimationDriver: NoOpAnimationDriver_, - AnimationDriver: AnimationDriver_, AnimationSequencePlayer: AnimationSequencePlayer_, AnimationGroupPlayer: AnimationGroupPlayer_, AnimationKeyframe: AnimationKeyframe_, diff --git a/modules/@angular/core/src/application_common_providers.ts b/modules/@angular/core/src/application_common_providers.ts index 4081b2eb32..ccf8619759 100644 --- a/modules/@angular/core/src/application_common_providers.ts +++ b/modules/@angular/core/src/application_common_providers.ts @@ -18,6 +18,18 @@ import {ViewUtils} from './linker/view_utils'; let __unused: Type; // avoid unused import when Type union types are erased +export function _componentFactoryResolverFactory() { + return ComponentFactoryResolver.NULL; +} + +export function _iterableDiffersFactory() { + return defaultIterableDiffers; +} + +export function _keyValueDiffersFactory() { + return defaultKeyValueDiffers; +} + /** * A default set of providers which should be included in any Angular * application, regardless of the platform it runs onto. @@ -27,10 +39,18 @@ export const APPLICATION_COMMON_PROVIDERS: Array /*@ts2dart_const*/[ APPLICATION_CORE_PROVIDERS, /* @ts2dart_Provider */ {provide: ComponentResolver, useClass: ReflectorComponentResolver}, - {provide: ComponentFactoryResolver, useValue: ComponentFactoryResolver.NULL}, + {provide: ComponentFactoryResolver, useFactory: _componentFactoryResolverFactory, deps: []}, APP_ID_RANDOM_PROVIDER, ViewUtils, - /* @ts2dart_Provider */ {provide: IterableDiffers, useValue: defaultIterableDiffers}, - /* @ts2dart_Provider */ {provide: KeyValueDiffers, useValue: defaultKeyValueDiffers}, + /* @ts2dart_Provider */ { + provide: IterableDiffers, + useFactory: _iterableDiffersFactory, + deps: [] + }, + /* @ts2dart_Provider */ { + provide: KeyValueDiffers, + useFactory: _keyValueDiffersFactory, + deps: [] + }, /* @ts2dart_Provider */ {provide: DynamicComponentLoader, useClass: DynamicComponentLoader_}, ]; diff --git a/modules/@angular/core/src/application_ref.ts b/modules/@angular/core/src/application_ref.ts index 10b5973dfb..5e4a7ce4ae 100644 --- a/modules/@angular/core/src/application_ref.ts +++ b/modules/@angular/core/src/application_ref.ts @@ -9,23 +9,35 @@ import {ObservableWrapper, PromiseWrapper} from '../src/facade/async'; import {ListWrapper} from '../src/facade/collection'; import {BaseException, ExceptionHandler, unimplemented} from '../src/facade/exceptions'; -import {IS_DART, Type, isBlank, isPresent, isPromise} from '../src/facade/lang'; +import {ConcreteType, IS_DART, Type, isBlank, isPresent, isPromise} from '../src/facade/lang'; import {APP_INITIALIZER, PLATFORM_INITIALIZER} from './application_tokens'; import {ChangeDetectorRef} from './change_detection/change_detector_ref'; import {Console} from './console'; -import {Injectable, Injector} from './di'; +import {Inject, Injectable, Injector, Optional, OptionalMetadata, SkipSelf, SkipSelfMetadata, forwardRef} from './di'; import {ComponentFactory, ComponentRef} from './linker/component_factory'; +import {ComponentFactoryResolver} from './linker/component_factory_resolver'; import {ComponentResolver} from './linker/component_resolver'; import {WtfScopeFn, wtfCreateScope, wtfLeave} from './profile/profile'; import {Testability, TestabilityRegistry} from './testability/testability'; import {NgZone, NgZoneError} from './zone/ng_zone'; + + /** * Create an Angular zone. * @experimental */ -export function createNgZone(): NgZone { +export function createNgZone(parent: NgZone): NgZone { + // If an NgZone is already present in the parent injector, + // use that one. Creating the NgZone in the same injector as the + // application is dangerous as some services might get created before + // the NgZone has been created. + // We keep the NgZone factory in the application providers for + // backwards compatibility for now though. + if (parent) { + return parent; + } return new NgZone({enableLongStackTrace: isDevMode()}); } @@ -279,7 +291,7 @@ export abstract class ApplicationRef { * ### Example * {@example core/ts/platform/platform.ts region='longform'} */ - abstract bootstrap(componentFactory: ComponentFactory): ComponentRef; + abstract bootstrap(componentFactory: ComponentFactory|ConcreteType): ComponentRef; /** * Retrieve the application {@link Injector}. @@ -334,18 +346,19 @@ export class ApplicationRef_ extends ApplicationRef { /** @internal */ private _enforceNoNewChanges: boolean = false; - private _exceptionHandler: ExceptionHandler; - private _asyncInitDonePromise: Promise; private _asyncInitDone: boolean; - constructor(private _platform: PlatformRef_, private _zone: NgZone, private _injector: Injector) { + constructor( + private _platform: PlatformRef_, private _zone: NgZone, private _console: Console, + private _injector: Injector, private _exceptionHandler: ExceptionHandler, + private _componentFactoryResolver: ComponentFactoryResolver, + @Optional() private _testabilityRegistry: TestabilityRegistry, + @Optional() private _testability: Testability, + @Optional() @Inject(APP_INITIALIZER) inits: Function[]) { super(); - var zone: NgZone = _injector.get(NgZone); this._enforceNoNewChanges = isDevMode(); - zone.run(() => { this._exceptionHandler = _injector.get(ExceptionHandler); }); this._asyncInitDonePromise = this.run(() => { - let inits: Function[] = _injector.get(APP_INITIALIZER, null); var asyncInitResults: Promise[] = []; var asyncInitDonePromise: Promise; if (isPresent(inits)) { @@ -366,7 +379,7 @@ export class ApplicationRef_ extends ApplicationRef { } return asyncInitDonePromise; }); - ObservableWrapper.subscribe(zone.onError, (error: NgZoneError) => { + ObservableWrapper.subscribe(this._zone.onError, (error: NgZoneError) => { this._exceptionHandler.call(error.error, error.stackTrace); }); ObservableWrapper.subscribe( @@ -390,7 +403,6 @@ export class ApplicationRef_ extends ApplicationRef { waitForAsyncInitializers(): Promise { return this._asyncInitDonePromise; } run(callback: Function): any { - var zone = this.injector.get(NgZone); var result: any; // Note: Don't use zone.runGuarded as we want to know about // the thrown exception! @@ -398,7 +410,7 @@ export class ApplicationRef_ extends ApplicationRef { // of `zone.run` as Dart swallows rejected promises // via the onError callback of the promise. var completer = PromiseWrapper.completer(); - zone.run(() => { + this._zone.run(() => { try { result = callback(); if (isPromise(result)) { @@ -417,12 +429,19 @@ export class ApplicationRef_ extends ApplicationRef { return isPromise(result) ? completer.promise : result; } - bootstrap(componentFactory: ComponentFactory): ComponentRef { + bootstrap(componentOrFactory: ComponentFactory|ConcreteType): ComponentRef { if (!this._asyncInitDone) { throw new BaseException( 'Cannot bootstrap as there are still asynchronous initializers running. Wait for them using waitForAsyncInitializers().'); } return this.run(() => { + let componentFactory: ComponentFactory; + if (componentOrFactory instanceof ComponentFactory) { + componentFactory = componentOrFactory; + } else { + componentFactory = + this._componentFactoryResolver.resolveComponentFactory(componentOrFactory); + } this._rootComponentTypes.push(componentFactory.componentType); var compRef = componentFactory.create(this._injector, [], componentFactory.selector); compRef.onDestroy(() => { this._unloadComponent(compRef); }); @@ -433,11 +452,10 @@ export class ApplicationRef_ extends ApplicationRef { } this._loadComponent(compRef); - let c: Console = this._injector.get(Console); if (isDevMode()) { let prodDescription = IS_DART ? 'Production mode is disabled in Dart.' : 'Call enableProdMode() to enable the production mode.'; - c.log(`Angular 2 is running in the development mode. ${prodDescription}`); + this._console.log(`Angular 2 is running in the development mode. ${prodDescription}`); } return compRef; }); @@ -500,7 +518,11 @@ export const PLATFORM_CORE_PROVIDERS = ]; export const APPLICATION_CORE_PROVIDERS = /*@ts2dart_const*/[ - /* @ts2dart_Provider */ {provide: NgZone, useFactory: createNgZone, deps: [] as any}, + /* @ts2dart_Provider */ { + provide: NgZone, + useFactory: createNgZone, + deps: [[new SkipSelfMetadata(), new OptionalMetadata(), NgZone]] + }, ApplicationRef_, /* @ts2dart_Provider */ {provide: ApplicationRef, useExisting: ApplicationRef_}, ]; diff --git a/modules/@angular/core/src/application_tokens.ts b/modules/@angular/core/src/application_tokens.ts index b45327ab87..51f2d82e32 100644 --- a/modules/@angular/core/src/application_tokens.ts +++ b/modules/@angular/core/src/application_tokens.ts @@ -23,7 +23,7 @@ import {OpaqueToken} from './di'; */ export const APP_ID: any = /*@ts2dart_const*/ new OpaqueToken('AppId'); -function _appIdRandomProviderFactory() { +export function _appIdRandomProviderFactory() { return `${_randomChar()}${_randomChar()}${_randomChar()}`; } @@ -35,7 +35,7 @@ export const APP_ID_RANDOM_PROVIDER = /*@ts2dart_const*/ /* @ts2dart_Provider */ { provide: APP_ID, useFactory: _appIdRandomProviderFactory, - deps: [] as any + deps: [] }; function _randomChar(): string { diff --git a/modules/@angular/core/src/linker/compiler.ts b/modules/@angular/core/src/linker/compiler.ts index ed9c71c36e..ee014d8e1f 100644 --- a/modules/@angular/core/src/linker/compiler.ts +++ b/modules/@angular/core/src/linker/compiler.ts @@ -18,16 +18,17 @@ import {ComponentFactory} from './component_factory'; * Low-level service for running the angular compiler duirng runtime * to create {@link ComponentFactory}s, which * can later be used to create and render a Component instance. + * + * Each `@AppModule` provides an own `Compiler` to its injector, + * that will use the directives/pipes of the app module for compilation + * of components. * @stable */ export class Compiler { /** * Loads the template and styles of a component and returns the associated `ComponentFactory`. */ - compileComponentAsync(component: ConcreteType, {moduleDirectives = [], modulePipes = []}: { - moduleDirectives?: ConcreteType[], - modulePipes?: ConcreteType[] - } = {}): Promise> { + compileComponentAsync(component: ConcreteType): Promise> { throw new BaseException( `Runtime compiler is not loaded. Tried to compile ${stringify(component)}`); } @@ -35,10 +36,7 @@ export class Compiler { * Compiles the given component. All templates have to be either inline or compiled via * `compileComponentAsync` before. */ - compileComponentSync(component: ConcreteType, {moduleDirectives = [], modulePipes = []}: { - moduleDirectives?: ConcreteType[], - modulePipes?: ConcreteType[] - } = {}): ComponentFactory { + compileComponentSync(component: ConcreteType): ComponentFactory { throw new BaseException( `Runtime compiler is not loaded. Tried to compile ${stringify(component)}`); } diff --git a/modules/@angular/core/src/linker/view.ts b/modules/@angular/core/src/linker/view.ts index 64298309a8..f68fc6f071 100644 --- a/modules/@angular/core/src/linker/view.ts +++ b/modules/@angular/core/src/linker/view.ts @@ -28,7 +28,6 @@ import {AnimationPlayer} from '../animation/animation_player'; import {AnimationGroupPlayer} from '../animation/animation_group_player'; import {AnimationKeyframe} from '../animation/animation_keyframe'; import {AnimationStyles} from '../animation/animation_styles'; -import {AnimationDriver} from '../animation/animation_driver'; import {ActiveAnimationPlayersMap} from '../animation/active_animation_players_map'; var _scope_check: WtfScopeFn = wtfCreateScope(`AppView#check(ascii id)`); diff --git a/modules/@angular/core/src/security.ts b/modules/@angular/core/src/security.ts index 8b1b94988b..cf5af1798a 100644 --- a/modules/@angular/core/src/security.ts +++ b/modules/@angular/core/src/security.ts @@ -25,8 +25,7 @@ export enum SecurityContext { } /** - * SanitizationService is used by the views to sanitize potentially dangerous values. This is a - * private API, use code should only refer to DomSanitizationService. + * SanitizationService is used by the views to sanitize potentially dangerous values. * * @stable */ diff --git a/modules/@angular/core/test/animation/animation_integration_spec.ts b/modules/@angular/core/test/animation/animation_integration_spec.ts index b449263ee5..b973afb43d 100644 --- a/modules/@angular/core/test/animation/animation_integration_spec.ts +++ b/modules/@angular/core/test/animation/animation_integration_spec.ts @@ -9,16 +9,16 @@ import {NgIf} from '@angular/common'; import {CompilerConfig} from '@angular/compiler'; import {TestComponentBuilder} from '@angular/compiler/testing'; +import {AnimationDriver} from '@angular/platform-browser/src/dom/animation_driver'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; +import {MockAnimationDriver} from '@angular/platform-browser/testing/mock_animation_driver'; import {Component} from '../../index'; import {DEFAULT_STATE} from '../../src/animation/animation_constants'; -import {AnimationDriver} from '../../src/animation/animation_driver'; import {AnimationEntryMetadata, animate, group, keyframes, sequence, state, style, transition, trigger} from '../../src/animation/metadata'; import {AUTO_STYLE} from '../../src/animation/metadata'; import {IS_DART, isArray, isPresent} from '../../src/facade/lang'; import {fakeAsync, flushMicrotasks, tick} from '../../testing'; -import {MockAnimationDriver} from '../../testing/animation/mock_animation_driver'; import {AsyncTestCompleter, beforeEach, beforeEachProviders, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '../../testing/testing_internal'; export function main() { diff --git a/modules/@angular/core/test/application_ref_spec.ts b/modules/@angular/core/test/application_ref_spec.ts index dd479e286c..091767c0a9 100644 --- a/modules/@angular/core/test/application_ref_spec.ts +++ b/modules/@angular/core/test/application_ref_spec.ts @@ -11,7 +11,7 @@ import {AsyncTestCompleter} from '@angular/core/testing/testing_internal'; import {Type} from '@angular/core'; import {SpyChangeDetectorRef} from './spies'; import {ApplicationRef_, ApplicationRef, PLATFORM_CORE_PROVIDERS, APPLICATION_CORE_PROVIDERS} from '@angular/core/src/application_ref'; -import {Injector, APP_INITIALIZER, Component, ReflectiveInjector, coreLoadAndBootstrap, PlatformRef, createPlatform, disposePlatform, ComponentResolver, ChangeDetectorRef} from '@angular/core'; +import {Injector, APP_INITIALIZER, Component, ReflectiveInjector, coreLoadAndBootstrap, PlatformRef, createPlatform, disposePlatform, ComponentResolver, ComponentFactoryResolver, ChangeDetectorRef} from '@angular/core'; import {Console} from '@angular/core/src/console'; import {BaseException} from '../src/facade/exceptions'; import {PromiseWrapper, PromiseCompleter, TimerWrapper} from '../src/facade/async'; @@ -40,7 +40,7 @@ export function main() { APPLICATION_CORE_PROVIDERS, {provide: Console, useValue: new _MockConsole()}, {provide: ExceptionHandler, useValue: new ExceptionHandler(errorLogger, false)}, {provide: ComponentResolver, useValue: new _MockComponentResolver(someCompFactory)}, - providers + {provide: ComponentFactoryResolver, useValue: ComponentFactoryResolver.NULL}, providers ], platform.injector); return appInjector.get(ApplicationRef); diff --git a/modules/@angular/core/test/linker/app_module_integration_spec.ts b/modules/@angular/core/test/linker/app_module_integration_spec.ts index d594e039a4..e0db19f0e6 100644 --- a/modules/@angular/core/test/linker/app_module_integration_spec.ts +++ b/modules/@angular/core/test/linker/app_module_integration_spec.ts @@ -1,8 +1,8 @@ import {LowerCasePipe, NgIf} from '@angular/common'; import {CompilerConfig} from '@angular/compiler'; -import {AppModule, AppModuleMetadata, Compiler, Component, ComponentFactoryResolver, ComponentRef, DebugElement, Host, Inject, Injectable, Injector, OpaqueToken, Optional, Provider, SelfMetadata, SkipSelf, SkipSelfMetadata, forwardRef, getDebugNode, provide} from '@angular/core'; +import {AppModule, AppModuleMetadata, Compiler, Component, ComponentFactoryResolver, ComponentRef, ComponentResolver, DebugElement, Host, Inject, Injectable, Injector, OpaqueToken, Optional, Provider, SelfMetadata, SkipSelf, SkipSelfMetadata, forwardRef, getDebugNode, provide} from '@angular/core'; import {ComponentFixture} from '@angular/core/testing'; -import {beforeEach, beforeEachProviders, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal'; +import {AsyncTestCompleter, beforeEach, beforeEachProviders, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal'; import {BaseException} from '../../src/facade/exceptions'; import {ConcreteType, IS_DART, Type, stringify} from '../../src/facade/lang'; @@ -195,6 +195,26 @@ function declareTests({useJit}: {useJit: boolean}) { })); checkNgIfAndLowerCasePipe(compFixture, compFixture.debugElement.children[0]); }); + + it('should provide a Compiler instance that uses the directives/pipes of the module', () => { + let appModule = compiler.compileAppModuleSync(ModuleWithDirectivesAndPipes).create(); + let boundCompiler: Compiler = appModule.injector.get(Compiler); + var cf = boundCompiler.compileComponentSync(CompUsingModuleDirectiveAndPipe); + let compFixture = new ComponentFixture(cf.create(injector), null, false); + checkNgIfAndLowerCasePipe(compFixture, compFixture.debugElement); + }); + + it('should provide a ComponentResolver instance that uses the directives/pipes of the module', + inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { + let appModule = compiler.compileAppModuleSync(ModuleWithDirectivesAndPipes).create(); + let boundCompiler: ComponentResolver = appModule.injector.get(ComponentResolver); + boundCompiler.resolveComponent(CompUsingModuleDirectiveAndPipe).then((cf) => { + let compFixture = new ComponentFixture(cf.create(injector), null, false); + checkNgIfAndLowerCasePipe(compFixture, compFixture.debugElement); + async.done(); + }); + })); + }); describe('providers', function() { @@ -471,6 +491,19 @@ function declareTests({useJit}: {useJit: boolean}) { expect(injector.get('a')).toBe('aValue'); expect(injector.get('someToken')).toBe('someValue'); }); + + it('should override the providers of nested modules', () => { + var injector = compiler + .compileAppModuleSync( + SomeModule, new AppModuleMetadata({ + providers: [{provide: 'someToken', useValue: 'someNewValue'}], + modules: [ModuleWithProvider] + })) + .create() + .injector; + expect(injector.get('someToken')).toBe('someNewValue'); + + }); }); }); diff --git a/modules/@angular/core/test/linker/change_detection_integration_spec.ts b/modules/@angular/core/test/linker/change_detection_integration_spec.ts index 7e566e18ed..1d26fa7a09 100644 --- a/modules/@angular/core/test/linker/change_detection_integration_spec.ts +++ b/modules/@angular/core/test/linker/change_detection_integration_spec.ts @@ -40,6 +40,10 @@ export function main() { var renderLog: RenderLog; var directiveLog: DirectiveLog; + function createCompFixture(template: string): ComponentFixture; + function createCompFixture(template: string, compType: ConcreteType): ComponentFixture; + function createCompFixture( + template: string, compType: ConcreteType, _tcb: TestComponentBuilder): ComponentFixture; function createCompFixture( template: string, compType: ConcreteType = TestComponent, _tcb: TestComponentBuilder = null): ComponentFixture { @@ -58,19 +62,23 @@ export function main() { return nodes.map(node => node.injector.get(dirType)); } + function _bindSimpleProp(bindAttr: string): ComponentFixture; + function _bindSimpleProp(bindAttr: string, compType: ConcreteType): ComponentFixture; function _bindSimpleProp( bindAttr: string, compType: ConcreteType = TestComponent): ComponentFixture { var template = `
`; return createCompFixture(template, compType); } + function _bindSimpleValue(expression: any): ComponentFixture; + function _bindSimpleValue(expression: any, compType: ConcreteType): ComponentFixture; function _bindSimpleValue( expression: any, compType: ConcreteType = TestComponent): ComponentFixture { return _bindSimpleProp(`[someProp]='${expression}'`, compType); } - function _bindAndCheckSimpleValue( - expression: any, compType: ConcreteType = TestComponent): string[] { + function _bindAndCheckSimpleValue( + expression: any, compType: ConcreteType = TestComponent): string[] { var ctx = _bindSimpleValue(expression, compType); ctx.detectChanges(false); return renderLog.log; diff --git a/modules/@angular/core/testing/component_fixture.ts b/modules/@angular/core/testing/component_fixture.ts index 23b9ad5af7..cb7910e38e 100644 --- a/modules/@angular/core/testing/component_fixture.ts +++ b/modules/@angular/core/testing/component_fixture.ts @@ -28,7 +28,7 @@ export class ComponentFixture { /** * The instance of the root component class. */ - componentInstance: any; + componentInstance: T; /** * The native element at the root of the component. diff --git a/modules/@angular/core/testing/testing_internal.ts b/modules/@angular/core/testing/testing_internal.ts index 2a600bdd50..cc6180831c 100644 --- a/modules/@angular/core/testing/testing_internal.ts +++ b/modules/@angular/core/testing/testing_internal.ts @@ -13,7 +13,6 @@ import {Math, global, isFunction, isPromise} from '../src/facade/lang'; import {AsyncTestCompleter} from './async_test_completer'; import {getTestInjector, inject} from './test_injector'; -export {MockAnimationDriver} from './animation/mock_animation_driver'; export {MockAnimationPlayer} from './animation/mock_animation_player'; export {AsyncTestCompleter} from './async_test_completer'; export {inject} from './test_injector'; diff --git a/modules/@angular/examples/core/forms/ts/ng_validators/ng_validators.ts b/modules/@angular/examples/core/forms/ts/ng_validators/ng_validators.ts index df046c9218..135c25b4ed 100644 --- a/modules/@angular/examples/core/forms/ts/ng_validators/ng_validators.ts +++ b/modules/@angular/examples/core/forms/ts/ng_validators/ng_validators.ts @@ -9,7 +9,7 @@ import {NG_VALIDATORS} from '@angular/common'; import {bootstrap} from '@angular/platform-browser-dynamic'; -let MyApp: Function = null; +class MyApp {} let myValidator: any = null; // #docregion ng_validators diff --git a/modules/@angular/platform-browser-dynamic/index.ts b/modules/@angular/platform-browser-dynamic/index.ts index bad55239b1..30301c6dfb 100644 --- a/modules/@angular/platform-browser-dynamic/index.ts +++ b/modules/@angular/platform-browser-dynamic/index.ts @@ -8,16 +8,18 @@ import {COMMON_DIRECTIVES, COMMON_PIPES} from '@angular/common'; import {COMPILER_PROVIDERS, CompilerConfig, XHR} from '@angular/compiler'; -import {ApplicationRef, ComponentRef, PLATFORM_DIRECTIVES, PLATFORM_PIPES, ReflectiveInjector, Type, coreLoadAndBootstrap} from '@angular/core'; -import {BROWSER_APP_PROVIDERS, WORKER_APP_APPLICATION_PROVIDERS, WORKER_SCRIPT, WORKER_UI_APPLICATION_PROVIDERS, browserPlatform, workerAppPlatform, workerUiPlatform} from '@angular/platform-browser'; +import {AppModule, AppModuleRef, ApplicationRef, Compiler, ComponentRef, ComponentResolver, ExceptionHandler, PLATFORM_DIRECTIVES, PLATFORM_PIPES, ReflectiveInjector, Type, coreLoadAndBootstrap, isDevMode, lockRunMode} from '@angular/core'; +import {BROWSER_APP_PROVIDERS, BrowserModule, WORKER_APP_APPLICATION_PROVIDERS, WORKER_SCRIPT, WORKER_UI_APPLICATION_PROVIDERS, bootstrapModuleFactory, browserPlatform, workerAppPlatform, workerUiPlatform} from '@angular/platform-browser'; import {ReflectionCapabilities, reflector} from './core_private'; +import {getDOM, initDomAdapter} from './platform_browser_private'; import {PromiseWrapper} from './src/facade/async'; -import {isPresent} from './src/facade/lang'; +import {ConcreteType, isPresent, stringify} from './src/facade/lang'; import {CachedXHR} from './src/xhr/xhr_cache'; import {XHRImpl} from './src/xhr/xhr_impl'; + /** * @experimental */ @@ -41,7 +43,55 @@ export const BROWSER_APP_COMPILER_PROVIDERS: Array = [{provide: XHR, useClass: CachedXHR}]; +function _initGlobals() { + lockRunMode(); + initDomAdapter(); + reflector.reflectionCapabilities = new ReflectionCapabilities(); +} +/** + * Creates the runtime compiler for the browser. + * + * @stable + */ +export function browserCompiler({useDebug, useJit = true, providers = []}: { + useDebug?: boolean, + useJit?: boolean, + providers?: Array +} = {}): Compiler { + _initGlobals(); + if (useDebug === undefined) { + useDebug = isDevMode(); + } + const injector = ReflectiveInjector.resolveAndCreate([ + COMPILER_PROVIDERS, { + provide: CompilerConfig, + useValue: new CompilerConfig({genDebugInfo: useDebug, useJit: useJit}) + }, + {provide: XHR, useClass: XHRImpl}, providers ? providers : [] + ]); + return injector.get(Compiler); +} + +/** + * Creates an instance of an `@AppModule` for the browser platform. + * + * ## Simple Example + * + * ```typescript + * @AppModule({ + * modules: [BrowserModule] + * }) + * class MyModule {} + * + * let moduleRef = bootstrapModule(MyModule); + * ``` + * @stable + */ +export function bootstrapModule( + moduleType: ConcreteType, compiler: Compiler = browserCompiler()): Promise> { + return compiler.compileAppModuleAsync(moduleType).then(bootstrapModuleFactory); +} /** * Bootstrapping for Angular applications. @@ -102,30 +152,108 @@ export const CACHED_TEMPLATE_PROVIDER: Array = * applications on a page, Angular treats each application injector's services as private * to that application. * - * ## API + * ## API (version 1) * * - `appComponentType`: The root component which should act as the application. This is * a reference to a `Type` which is annotated with `@Component(...)`. * - `customProviders`: An additional set of providers that can be added to the * app injector to override default injection behavior. * + * ## API (version 2) + * - `appComponentType`: The root component which should act as the application. This is + * a reference to a `Type` which is annotated with `@Component(...)`. + * - `providers`, `directives`, `pipes`, `modules`, `precompile`: Defines the properties + * of the dynamically created module that is used to bootstrap the module. + * * Returns a `Promise` of {@link ComponentRef}. * * @experimental This api cannot be used with the offline compiler and thus is still subject to * change. */ -export function bootstrap( - appComponentType: Type, - customProviders?: Array): Promise> { - reflector.reflectionCapabilities = new ReflectionCapabilities(); - let providers = [ - BROWSER_APP_PROVIDERS, BROWSER_APP_COMPILER_PROVIDERS, - isPresent(customProviders) ? customProviders : [] - ]; - var appInjector = ReflectiveInjector.resolveAndCreate(providers, browserPlatform().injector); - return coreLoadAndBootstrap(appComponentType, appInjector); -} +// Note: We are using typescript overloads here to have 2 function signatures! +export function bootstrap( + appComponentType: ConcreteType, + customProviders?: Array): Promise>; +export function bootstrap( + appComponentType: ConcreteType, + {providers, directives, pipes, modules, precompile, compiler}?: { + providers?: Array, + directives?: any[], + pipes?: any[], + modules?: any[], + precompile?: any[], + compiler?: Compiler + }): Promise>; +export function bootstrap( + appComponentType: ConcreteType, + customProvidersOrDynamicModule?: Array| { + providers: Array, + directives: any[], + pipes: any[], + modules: any[], + precompile: any[], + compiler: Compiler + }): Promise> { + _initGlobals(); + let compiler: Compiler; + let compilerProviders: any = []; + let providers: any[] = []; + let directives: any[] = []; + let pipes: any[] = []; + let modules: any[] = []; + let precompile: any[] = []; + if (customProvidersOrDynamicModule instanceof Array) { + providers = customProvidersOrDynamicModule; + } else if (customProvidersOrDynamicModule) { + providers = normalizeArray(customProvidersOrDynamicModule.providers); + directives = normalizeArray(customProvidersOrDynamicModule.directives); + pipes = normalizeArray(customProvidersOrDynamicModule.pipes); + modules = normalizeArray(customProvidersOrDynamicModule.modules); + precompile = normalizeArray(customProvidersOrDynamicModule.precompile); + compiler = customProvidersOrDynamicModule.compiler; + } + if (providers && providers.length > 0) { + // Note: This is a hack to still support the old way + // of configuring platform directives / pipes and the compiler xhr. + // This will soon be deprecated! + let inj = ReflectiveInjector.resolveAndCreate(providers); + let compilerConfig: CompilerConfig = inj.get(CompilerConfig, null); + if (compilerConfig) { + // Note: forms read the platform directives / pipes, modify them + // and provide a CompilerConfig out of it + directives = directives.concat(compilerConfig.platformDirectives); + pipes = pipes.concat(compilerConfig.platformPipes); + } else { + // If nobody provided a CompilerConfig, use the + // PLATFORM_DIRECTIVES / PLATFORM_PIPES values directly. + directives = directives.concat(inj.get(PLATFORM_DIRECTIVES, [])); + pipes = pipes.concat(inj.get(PLATFORM_PIPES, [])); + } + let xhr = inj.get(XHR, null); + if (xhr) { + compilerProviders.push([{provide: XHR, useValue: xhr}]); + } + } + if (!compiler) { + compiler = browserCompiler({providers: compilerProviders}); + } + @AppModule({ + providers: providers, + modules: modules.concat([BrowserModule]), + directives: directives, + pipes: pipes, + precompile: precompile.concat([appComponentType]) + }) + class DynamicModule { + constructor(public appRef: ApplicationRef) {} + } + + return bootstrapModule(DynamicModule, compiler) + .then( + (moduleRef) => moduleRef.instance.appRef.waitForAsyncInitializers().then( + () => moduleRef.instance.appRef.bootstrap(appComponentType))); +} /** * @experimental @@ -178,3 +306,7 @@ export function bootstrapWorkerApp( workerAppPlatform().injector); return coreLoadAndBootstrap(appComponentType, appInjector); } + +function normalizeArray(arr: any[]): any[] { + return arr ? arr : []; +} \ No newline at end of file diff --git a/modules/@angular/platform-browser-dynamic/platform_browser_private.ts b/modules/@angular/platform-browser-dynamic/platform_browser_private.ts index 39a14200e1..5ae937569b 100644 --- a/modules/@angular/platform-browser-dynamic/platform_browser_private.ts +++ b/modules/@angular/platform-browser-dynamic/platform_browser_private.ts @@ -9,3 +9,4 @@ import {__platform_browser_private__ as r, __platform_browser_private__ as t} from '@angular/platform-browser'; export var getDOM: typeof t.getDOM = r.getDOM; +export var initDomAdapter: typeof t.initDomAdapter = r.initDomAdapter; diff --git a/modules/@angular/platform-browser/core_private.ts b/modules/@angular/platform-browser/core_private.ts index 76f728ae4e..a65f6b94a8 100644 --- a/modules/@angular/platform-browser/core_private.ts +++ b/modules/@angular/platform-browser/core_private.ts @@ -16,24 +16,12 @@ export var VIEW_ENCAPSULATION_VALUES: typeof t.VIEW_ENCAPSULATION_VALUES = r.VIEW_ENCAPSULATION_VALUES; export type DebugDomRootRenderer = t.DebugDomRootRenderer; export var DebugDomRootRenderer: typeof t.DebugDomRootRenderer = r.DebugDomRootRenderer; -/** - * @experimental bogus marker to pass the ts-api-guardian's check - this api should be public so - * this line will go away when that happens - */ -export var SecurityContext: typeof t.SecurityContext = r.SecurityContext; -export type SecurityContext = t.SecurityContext; -export var SanitizationService: typeof t.SanitizationService = r.SanitizationService; -export type SanitizationService = t.SanitizationService; export var reflector: typeof t.reflector = r.reflector; export type NoOpAnimationPlayer = t.NoOpAnimationPlayer; export var NoOpAnimationPlayer: typeof t.NoOpAnimationPlayer = r.NoOpAnimationPlayer; export type AnimationPlayer = t.AnimationPlayer; export var AnimationPlayer: typeof t.AnimationPlayer = r.AnimationPlayer; -export type NoOpAnimationDriver = t.NoOpAnimationDriver; -export var NoOpAnimationDriver: typeof t.NoOpAnimationDriver = r.NoOpAnimationDriver; -export type AnimationDriver = t.AnimationDriver; -export var AnimationDriver: typeof t.AnimationDriver = r.AnimationDriver; export type AnimationSequencePlayer = t.AnimationSequencePlayer; export var AnimationSequencePlayer: typeof t.AnimationSequencePlayer = r.AnimationSequencePlayer; export type AnimationGroupPlayer = t.AnimationGroupPlayer; diff --git a/modules/@angular/platform-browser/index.ts b/modules/@angular/platform-browser/index.ts index a9b80b927d..8c1309f93f 100644 --- a/modules/@angular/platform-browser/index.ts +++ b/modules/@angular/platform-browser/index.ts @@ -6,21 +6,21 @@ * found in the LICENSE file at https://angular.io/license */ +export {BROWSER_APP_PROVIDERS, BROWSER_PLATFORM_PROVIDERS, BROWSER_SANITIZATION_PROVIDERS, BrowserModule, bootstrapModuleFactory, browserPlatform} from './src/browser'; export {BrowserPlatformLocation} from './src/browser/location/browser_platform_location'; export {Title} from './src/browser/title'; export {disableDebugTools, enableDebugTools} from './src/browser/tools/tools'; +export {AnimationDriver} from './src/dom/animation_driver'; export {By} from './src/dom/debug/by'; export {DOCUMENT} from './src/dom/dom_tokens'; export {EVENT_MANAGER_PLUGINS, EventManager} from './src/dom/events/event_manager'; export {HAMMER_GESTURE_CONFIG, HammerGestureConfig} from './src/dom/events/hammer_gestures'; -export {DomSanitizationService, SafeHtml, SafeResourceUrl, SafeScript, SafeStyle, SafeUrl, SecurityContext} from './src/security/dom_sanitization_service'; - -export * from './src/browser'; - +export {DomSanitizationService, SafeHtml, SafeResourceUrl, SafeScript, SafeStyle, SafeUrl} from './src/security/dom_sanitization_service'; // Web Workers export {ClientMessageBroker, ClientMessageBrokerFactory, FnArg, UiArguments} from './src/web_workers/shared/client_message_broker'; -export {ReceivedMessage, ServiceMessageBroker, ServiceMessageBrokerFactory} from './src/web_workers/shared/service_message_broker'; export {PRIMITIVE} from './src/web_workers/shared/serializer'; +export {ReceivedMessage, ServiceMessageBroker, ServiceMessageBrokerFactory} from './src/web_workers/shared/service_message_broker'; + export * from './src/web_workers/shared/message_bus'; export {WORKER_APP_LOCATION_PROVIDERS} from './src/web_workers/worker/location_providers'; export {WORKER_UI_LOCATION_PROVIDERS} from './src/web_workers/ui/location_providers'; diff --git a/modules/@angular/platform-browser/private_export.ts b/modules/@angular/platform-browser/private_export.ts index 9e85d63bf7..87d65a52bc 100644 --- a/modules/@angular/platform-browser/private_export.ts +++ b/modules/@angular/platform-browser/private_export.ts @@ -6,6 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ +import * as browser from './src/browser'; import * as ng_proble from './src/dom/debug/ng_probe'; import * as dom_adapter from './src/dom/dom_adapter'; import * as dom_renderer from './src/dom/dom_renderer'; @@ -28,6 +29,7 @@ export declare namespace __platform_browser_private_types__ { export var ELEMENT_PROBE_PROVIDERS: typeof ng_proble.ELEMENT_PROBE_PROVIDERS; export type DomEventsPlugin = dom_events.DomEventsPlugin; export var DomEventsPlugin: typeof dom_events.DomEventsPlugin; + export var initDomAdapter: typeof browser.initDomAdapter; } export var __platform_browser_private__ = { @@ -39,5 +41,6 @@ export var __platform_browser_private__ = { DomSharedStylesHost: shared_styles_host.DomSharedStylesHost, SharedStylesHost: shared_styles_host.SharedStylesHost, ELEMENT_PROBE_PROVIDERS: ng_proble.ELEMENT_PROBE_PROVIDERS, - DomEventsPlugin: dom_events.DomEventsPlugin + DomEventsPlugin: dom_events.DomEventsPlugin, + initDomAdapter: browser.initDomAdapter }; diff --git a/modules/@angular/platform-browser/src/browser.ts b/modules/@angular/platform-browser/src/browser.ts index 98cd6c47e8..ad2da207b5 100644 --- a/modules/@angular/platform-browser/src/browser.ts +++ b/modules/@angular/platform-browser/src/browser.ts @@ -6,10 +6,11 @@ * found in the LICENSE file at https://angular.io/license */ -import {FORM_PROVIDERS, PlatformLocation} from '@angular/common'; -import {APPLICATION_COMMON_PROVIDERS, ExceptionHandler, OpaqueToken, PLATFORM_COMMON_PROVIDERS, PLATFORM_INITIALIZER, PlatformRef, ReflectiveInjector, RootRenderer, Testability, assertPlatform, createPlatform, getPlatform} from '@angular/core'; +import {COMMON_DIRECTIVES, COMMON_PIPES, FORM_PROVIDERS, PlatformLocation} from '@angular/common'; +import {APPLICATION_COMMON_PROVIDERS, AppModule, AppModuleFactory, AppModuleRef, ExceptionHandler, NgZone, OpaqueToken, PLATFORM_COMMON_PROVIDERS, PLATFORM_INITIALIZER, PlatformRef, ReflectiveInjector, RootRenderer, SanitizationService, Testability, assertPlatform, createPlatform, getPlatform, isDevMode} from '@angular/core'; -import {AnimationDriver, NoOpAnimationDriver, SanitizationService, wtfInit} from '../core_private'; +import {wtfInit} from '../core_private'; +import {AnimationDriver} from '../src/dom/animation_driver'; import {WebAnimationsDriver} from '../src/dom/web_animations_driver'; import {BrowserDomAdapter} from './browser/browser_adapter'; @@ -27,7 +28,6 @@ import {DomSharedStylesHost, SharedStylesHost} from './dom/shared_styles_host'; import {isBlank} from './facade/lang'; import {DomSanitizationService, DomSanitizationServiceImpl} from './security/dom_sanitization_service'; - const BROWSER_PLATFORM_MARKER = new OpaqueToken('BrowserPlatformMarker'); /** @@ -86,23 +86,71 @@ export function browserPlatform(): PlatformRef { return assertPlatform(BROWSER_PLATFORM_MARKER); } -function initDomAdapter() { +export function initDomAdapter() { BrowserDomAdapter.makeCurrent(); wtfInit(); BrowserGetTestability.init(); } -function _exceptionHandler(): ExceptionHandler { +export function _exceptionHandler(): ExceptionHandler { return new ExceptionHandler(getDOM()); } -function _document(): any { +export function _document(): any { return getDOM().defaultDoc(); } -function _resolveDefaultAnimationDriver(): AnimationDriver { +export function _resolveDefaultAnimationDriver(): AnimationDriver { if (getDOM().supportsWebAnimation()) { return new WebAnimationsDriver(); } - return new NoOpAnimationDriver(); + return AnimationDriver.NOOP; +} + +/** + * The app module for the browser. + * @stable + */ +@AppModule({ + providers: [ + BROWSER_APP_PROVIDERS, + ], + directives: COMMON_DIRECTIVES, + pipes: COMMON_PIPES +}) +export class BrowserModule { +} + +/** + * Creates an instance of an `@AppModule` for the browser platform + * for offline compilation. + * + * ## Simple Example + * + * ```typescript + * my_module.ts: + * + * @AppModule({ + * modules: [BrowserModule] + * }) + * class MyModule {} + * + * main.ts: + * import {MyModuleNgFactory} from './my_module.ngfactory'; + * import {bootstrapModuleFactory} from '@angular/platform-browser'; + * + * let moduleRef = bootstrapModuleFactory(MyModuleNgFactory); + * ``` + * @stable + */ +export function bootstrapModuleFactory(moduleFactory: AppModuleFactory): AppModuleRef { + let platformInjector = browserPlatform().injector; + // Note: We need to create the NgZone _before_ we instantiate the module, + // as instantiating the module creates some providers eagerly. + // So we create a mini parent injector that just contains the new NgZone and + // pass that as parent to the AppModuleFactory. + let ngZone = new NgZone({enableLongStackTrace: isDevMode()}); + let ngZoneInjector = + ReflectiveInjector.resolveAndCreate([{provide: NgZone, useValue: ngZone}], platformInjector); + return ngZone.run(() => { return moduleFactory.create(ngZoneInjector); }); } diff --git a/modules/@angular/core/src/animation/animation_driver.ts b/modules/@angular/platform-browser/src/dom/animation_driver.ts similarity index 69% rename from modules/@angular/core/src/animation/animation_driver.ts rename to modules/@angular/platform-browser/src/dom/animation_driver.ts index fcea0ff345..feb5040cda 100644 --- a/modules/@angular/core/src/animation/animation_driver.ts +++ b/modules/@angular/platform-browser/src/dom/animation_driver.ts @@ -6,20 +6,24 @@ * found in the LICENSE file at https://angular.io/license */ -import {AnimationKeyframe} from './animation_keyframe'; -import {AnimationPlayer, NoOpAnimationPlayer} from './animation_player'; -import {AnimationStyles} from './animation_styles'; +import {AnimationPlayer} from '@angular/core'; -export abstract class AnimationDriver { - abstract animate( - element: any, startingStyles: AnimationStyles, keyframes: AnimationKeyframe[], - duration: number, delay: number, easing: string): AnimationPlayer; -} +import {AnimationKeyframe, AnimationStyles, NoOpAnimationPlayer} from '../../core_private'; -export class NoOpAnimationDriver extends AnimationDriver { +class _NoOpAnimationDriver implements AnimationDriver { animate( element: any, startingStyles: AnimationStyles, keyframes: AnimationKeyframe[], duration: number, delay: number, easing: string): AnimationPlayer { return new NoOpAnimationPlayer(); } } + +/** + * @experimental + */ +export abstract class AnimationDriver { + static NOOP: AnimationDriver = new _NoOpAnimationDriver(); + abstract animate( + element: any, startingStyles: AnimationStyles, keyframes: AnimationKeyframe[], + duration: number, delay: number, easing: string): AnimationPlayer; +} diff --git a/modules/@angular/platform-browser/src/dom/debug/ng_probe.ts b/modules/@angular/platform-browser/src/dom/debug/ng_probe.ts index ef4264c549..ffb4ebbf52 100644 --- a/modules/@angular/platform-browser/src/dom/debug/ng_probe.ts +++ b/modules/@angular/platform-browser/src/dom/debug/ng_probe.ts @@ -30,7 +30,7 @@ export function inspectNativeElement(element: any /** TODO #9100 */): DebugNode return getDebugNode(element); } -function _createConditionalRootRenderer(rootRenderer: any /** TODO #9100 */) { +export function _createConditionalRootRenderer(rootRenderer: any /** TODO #9100 */) { if (isDevMode()) { return _createRootRenderer(rootRenderer); } diff --git a/modules/@angular/platform-browser/src/dom/dom_renderer.ts b/modules/@angular/platform-browser/src/dom/dom_renderer.ts index 68d890ab46..8692535247 100644 --- a/modules/@angular/platform-browser/src/dom/dom_renderer.ts +++ b/modules/@angular/platform-browser/src/dom/dom_renderer.ts @@ -14,11 +14,12 @@ import {Json, RegExpWrapper, StringWrapper, isArray, isBlank, isPresent, isStrin import {DomSharedStylesHost} from './shared_styles_host'; -import {AnimationKeyframe, AnimationStyles, AnimationPlayer, AnimationDriver, RenderDebugInfo,} from '../../core_private'; +import {AnimationKeyframe, AnimationStyles, AnimationPlayer, RenderDebugInfo,} from '../../core_private'; import {EventManager} from './events/event_manager'; import {DOCUMENT} from './dom_tokens'; import {getDOM} from './dom_adapter'; +import {AnimationDriver} from './animation_driver'; import {camelCaseToDashCase} from './util'; const NAMESPACE_URIS = { diff --git a/modules/@angular/platform-browser/src/dom/web_animations_driver.ts b/modules/@angular/platform-browser/src/dom/web_animations_driver.ts index 1c0daf68a2..ce12179393 100644 --- a/modules/@angular/platform-browser/src/dom/web_animations_driver.ts +++ b/modules/@angular/platform-browser/src/dom/web_animations_driver.ts @@ -8,10 +8,11 @@ import {AUTO_STYLE, BaseException} from '@angular/core'; -import {AnimationDriver, AnimationKeyframe, AnimationPlayer, AnimationStyles, NoOpAnimationPlayer} from '../../core_private'; +import {AnimationKeyframe, AnimationPlayer, AnimationStyles, NoOpAnimationPlayer} from '../../core_private'; import {StringMapWrapper} from '../facade/collection'; import {StringWrapper, isNumber, isPresent} from '../facade/lang'; +import {AnimationDriver} from './animation_driver'; import {getDOM} from './dom_adapter'; import {DomAnimatePlayer} from './dom_animate_player'; import {dashCaseToCamelCase} from './util'; diff --git a/modules/@angular/platform-browser/src/security/dom_sanitization_service.ts b/modules/@angular/platform-browser/src/security/dom_sanitization_service.ts index 83c0fe52da..8b636f5366 100644 --- a/modules/@angular/platform-browser/src/security/dom_sanitization_service.ts +++ b/modules/@angular/platform-browser/src/security/dom_sanitization_service.ts @@ -6,9 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {Injectable} from '@angular/core'; - -import {SanitizationService, SecurityContext} from '../../core_private'; +import {Injectable, SanitizationService, SecurityContext} from '@angular/core'; import {sanitizeHtml} from './html_sanitizer'; import {sanitizeStyle} from './style_sanitizer'; diff --git a/modules/@angular/platform-browser/src/worker_render.ts b/modules/@angular/platform-browser/src/worker_render.ts index f66413a621..896bf940d6 100644 --- a/modules/@angular/platform-browser/src/worker_render.ts +++ b/modules/@angular/platform-browser/src/worker_render.ts @@ -8,11 +8,12 @@ import {APPLICATION_COMMON_PROVIDERS, APP_INITIALIZER, ExceptionHandler, Injectable, Injector, NgZone, OpaqueToken, PLATFORM_COMMON_PROVIDERS, PLATFORM_INITIALIZER, PlatformRef, ReflectiveInjector, RootRenderer, Testability, assertPlatform, createPlatform, getPlatform} from '@angular/core'; -import {AnimationDriver, NoOpAnimationDriver, wtfInit} from '../core_private'; +import {wtfInit} from '../core_private'; import {BROWSER_SANITIZATION_PROVIDERS} from './browser'; import {BrowserDomAdapter} from './browser/browser_adapter'; import {BrowserGetTestability} from './browser/testability'; +import {AnimationDriver} from './dom/animation_driver'; import {getDOM} from './dom/dom_adapter'; import {DomRootRenderer, DomRootRenderer_} from './dom/dom_renderer'; import {DOCUMENT} from './dom/dom_tokens'; @@ -178,5 +179,5 @@ function spawnWebWorker(uri: string, instance: WebWorkerInstance): void { function _resolveDefaultAnimationDriver(): AnimationDriver { // web workers have not been tested or configured to // work with animations just yet... - return new NoOpAnimationDriver(); + return AnimationDriver.NOOP; } diff --git a/modules/@angular/platform-browser/test/browser/bootstrap_spec.ts b/modules/@angular/platform-browser/test/browser/bootstrap_spec.ts index 59cce51848..6f73322f5e 100644 --- a/modules/@angular/platform-browser/test/browser/bootstrap_spec.ts +++ b/modules/@angular/platform-browser/test/browser/bootstrap_spec.ts @@ -6,12 +6,15 @@ * found in the LICENSE file at https://angular.io/license */ -import {APP_INITIALIZER, Component, Directive, ExceptionHandler, Inject, OnDestroy, PLATFORM_INITIALIZER, ReflectiveInjector, coreLoadAndBootstrap, createPlatform, provide} from '@angular/core'; +import {LowerCasePipe, NgIf} from '@angular/common'; +import {XHR} from '@angular/compiler'; +import {APP_INITIALIZER, Component, Directive, ExceptionHandler, Inject, OnDestroy, PLATFORM_DIRECTIVES, PLATFORM_INITIALIZER, PLATFORM_PIPES, ReflectiveInjector, coreLoadAndBootstrap, createPlatform, provide} from '@angular/core'; import {ApplicationRef, disposePlatform} from '@angular/core/src/application_ref'; import {Console} from '@angular/core/src/console'; import {ComponentRef} from '@angular/core/src/linker/component_factory'; import {Testability, TestabilityRegistry} from '@angular/core/src/testability/testability'; -import {AsyncTestCompleter, Log, afterEach, beforeEach, beforeEachProviders, describe, expect, inject, it} from '@angular/core/testing/testing_internal'; +import {ComponentFixture} from '@angular/core/testing'; +import {AsyncTestCompleter, Log, afterEach, beforeEach, beforeEachProviders, ddescribe, describe, expect, iit, inject, it} from '@angular/core/testing/testing_internal'; import {BROWSER_APP_PROVIDERS, BROWSER_PLATFORM_PROVIDERS} from '@angular/platform-browser'; import {BROWSER_APP_COMPILER_PROVIDERS, bootstrap} from '@angular/platform-browser-dynamic'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; @@ -69,6 +72,19 @@ class HelloOnDestroyTickCmp implements OnDestroy { ngOnDestroy(): void { this.appRef.tick(); } } +@Component({selector: 'hello-app', templateUrl: './sometemplate.html'}) +class HelloUrlCmp { + greeting = 'hello'; +} + +@Component({ + selector: 'hello-app', + template: `
` +}) +class HelloCmpUsingPlatformDirectiveAndPipe { + show: boolean = false; +} + class _ArrayLogger { res: any[] = []; log(s: any): void { this.res.push(s); } @@ -108,15 +124,9 @@ export function main() { afterEach(disposePlatform); it('should throw if bootstrapped Directive is not a Component', () => { - var logger = new _ArrayLogger(); - var exceptionHandler = new ExceptionHandler(logger, false); - expect( - () => bootstrap( - HelloRootDirectiveIsNotCmp, - [testProviders, {provide: ExceptionHandler, useValue: exceptionHandler}])) + expect(() => bootstrap(HelloRootDirectiveIsNotCmp)) .toThrowError( `Could not compile '${stringify(HelloRootDirectiveIsNotCmp)}' because it is not a component.`); - expect(logger.res.join('')).toContain('Could not compile'); }); it('should throw if no element is found', @@ -270,5 +280,40 @@ export function main() { }); }); })); + + // Note: This will soon be deprecated as bootstrap creates a separate injector for the compiler, + // i.e. such providers needs to go into that injecotr (when calling `browserCompiler`); + it('should still allow to provide a custom xhr via the regular providers', + inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { + let spyXhr: XHR = {get: (url: string) => Promise.resolve('{{greeting}} world!')}; + bootstrap(HelloUrlCmp, testProviders.concat([{provide: XHR, useValue: spyXhr}])) + .then((compRef) => { + expect(el).toHaveText('hello world!'); + async.done(); + }); + })); + + // Note: This will soon be deprecated as bootstrap creates a separate injector for the compiler, + // i.e. such providers needs to go into that injecotr (when calling `browserCompiler`); + it('should still allow to provide platform directives/pipes via the regular providers', + inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { + bootstrap(HelloCmpUsingPlatformDirectiveAndPipe, testProviders.concat([ + {provide: PLATFORM_DIRECTIVES, useValue: [NgIf]}, + {provide: PLATFORM_PIPES, useValue: [LowerCasePipe]} + ])).then((compRef) => { + let compFixture = new ComponentFixture(compRef, null, null); + let el = compFixture.debugElement; + // Test that ngIf works + expect(el.children.length).toBe(1); + compFixture.componentInstance.show = true; + compFixture.detectChanges(); + expect(el.children.length).toBe(2); + + // Test that lowercase pipe works + expect(el.children[0].properties['title']).toBe('hello'); + async.done(); + }); + })); + }); } diff --git a/modules/@angular/platform-browser/testing/browser.ts b/modules/@angular/platform-browser/testing/browser.ts index 4b62187ba3..8fe8de5855 100644 --- a/modules/@angular/platform-browser/testing/browser.ts +++ b/modules/@angular/platform-browser/testing/browser.ts @@ -9,14 +9,15 @@ import {LocationStrategy} from '@angular/common'; import {APP_ID, NgZone, PLATFORM_COMMON_PROVIDERS, PLATFORM_INITIALIZER} from '@angular/core'; -import {AnimationDriver, NoOpAnimationDriver} from '../core_private'; import {BROWSER_APP_PROVIDERS} from '../src/browser'; import {BrowserDomAdapter} from '../src/browser/browser_adapter'; +import {AnimationDriver} from '../src/dom/animation_driver'; import {ELEMENT_PROBE_PROVIDERS} from '../src/dom/debug/ng_probe'; import {BrowserDetection} from './browser_util'; + /** * Default platform providers for testing without a compiler. */ @@ -28,7 +29,7 @@ const TEST_BROWSER_STATIC_PLATFORM_PROVIDERS: Array = [ {provide: APP_ID, useValue: 'a'}, ELEMENT_PROBE_PROVIDERS, {provide: NgZone, useFactory: createNgZone}, - {provide: AnimationDriver, useClass: NoOpAnimationDriver} + {provide: AnimationDriver, useValue: AnimationDriver.NOOP} ]; diff --git a/modules/@angular/core/testing/animation/mock_animation_driver.ts b/modules/@angular/platform-browser/testing/mock_animation_driver.ts similarity index 75% rename from modules/@angular/core/testing/animation/mock_animation_driver.ts rename to modules/@angular/platform-browser/testing/mock_animation_driver.ts index 6519ff0939..c3dd5c6cb3 100644 --- a/modules/@angular/core/testing/animation/mock_animation_driver.ts +++ b/modules/@angular/platform-browser/testing/mock_animation_driver.ts @@ -6,12 +6,12 @@ * found in the LICENSE file at https://angular.io/license */ -import {AnimationDriver} from '../../src/animation/animation_driver'; -import {AnimationKeyframe} from '../../src/animation/animation_keyframe'; -import {AnimationPlayer} from '../../src/animation/animation_player'; -import {AnimationStyles} from '../../src/animation/animation_styles'; -import {StringMapWrapper} from '../../src/facade/collection'; -import {MockAnimationPlayer} from '../../testing/animation/mock_animation_player'; +import {AnimationPlayer} from '@angular/core'; +import {MockAnimationPlayer} from '@angular/core/testing/testing_internal'; + +import {AnimationKeyframe, AnimationStyles} from '../core_private'; +import {AnimationDriver} from '../src/dom/animation_driver'; +import {StringMapWrapper} from '../src/facade/collection'; export class MockAnimationDriver extends AnimationDriver { log: any[] /** TODO #9100 */ = []; diff --git a/modules/@angular/platform-server/core_private.ts b/modules/@angular/platform-server/core_private.ts index 1bee64047b..9cc4f2dd68 100644 --- a/modules/@angular/platform-server/core_private.ts +++ b/modules/@angular/platform-server/core_private.ts @@ -11,7 +11,3 @@ import {__core_private__ as r, __core_private_types__ as t} from '@angular/core' export var reflector: typeof t.reflector = r.reflector; export var ReflectionCapabilities: typeof t.ReflectionCapabilities = r.ReflectionCapabilities; export var wtfInit: typeof t.wtfInit = r.wtfInit; -export type NoOpAnimationDriver = t.NoOpAnimationDriver; -export var NoOpAnimationDriver: typeof t.NoOpAnimationDriver = r.NoOpAnimationDriver; -export type AnimationDriver = t.AnimationDriver; -export var AnimationDriver: typeof t.AnimationDriver = r.AnimationDriver; diff --git a/modules/@angular/platform-server/testing/server.ts b/modules/@angular/platform-server/testing/server.ts index 17a8b437df..6a2dc8d3d4 100644 --- a/modules/@angular/platform-server/testing/server.ts +++ b/modules/@angular/platform-server/testing/server.ts @@ -10,9 +10,8 @@ import {COMPILER_PROVIDERS, DirectiveResolver, ViewResolver, XHR} from '@angular import {MockDirectiveResolver, MockViewResolver, OverridingTestComponentBuilder} from '@angular/compiler/testing'; import {APPLICATION_COMMON_PROVIDERS, APP_ID, NgZone, PLATFORM_COMMON_PROVIDERS, PLATFORM_INITIALIZER, RootRenderer} from '@angular/core'; import {TestComponentBuilder, TestComponentRenderer} from '@angular/core/testing'; -import {BROWSER_SANITIZATION_PROVIDERS, DOCUMENT, EVENT_MANAGER_PLUGINS, EventManager} from '@angular/platform-browser'; +import {AnimationDriver, BROWSER_SANITIZATION_PROVIDERS, DOCUMENT, EVENT_MANAGER_PLUGINS, EventManager} from '@angular/platform-browser'; -import {AnimationDriver, NoOpAnimationDriver} from '../core_private'; import {DOMTestComponentRenderer} from '../platform_browser_dynamic_testing_private'; import {DomEventsPlugin, DomRootRenderer, DomRootRenderer_, DomSharedStylesHost, ELEMENT_PROBE_PROVIDERS, SharedStylesHost, getDOM} from '../platform_browser_private'; import {Parse5DomAdapter} from '../src/parse5_adapter'; @@ -63,7 +62,7 @@ export const TEST_SERVER_APPLICATION_PROVIDERS: Array(componentFactory: ComponentFactory): ComponentRef; + abstract bootstrap(componentFactory: ComponentFactory | ConcreteType): ComponentRef; abstract dispose(): void; abstract registerBootstrapListener(listener: (ref: ComponentRef) => void): void; abstract registerDisposeListener(dispose: () => void): void; @@ -289,14 +289,8 @@ export declare class Compiler { clearCacheFor(type: Type): void; compileAppModuleAsync(moduleType: ConcreteType, metadata?: AppModuleMetadata): Promise>; compileAppModuleSync(moduleType: ConcreteType, metadata?: AppModuleMetadata): AppModuleFactory; - compileComponentAsync(component: ConcreteType, {moduleDirectives, modulePipes}?: { - moduleDirectives?: ConcreteType[]; - modulePipes?: ConcreteType[]; - }): Promise>; - compileComponentSync(component: ConcreteType, {moduleDirectives, modulePipes}?: { - moduleDirectives?: ConcreteType[]; - modulePipes?: ConcreteType[]; - }): ComponentFactory; + compileComponentAsync(component: ConcreteType): Promise>; + compileComponentSync(component: ConcreteType): ComponentFactory; } /** @stable */ @@ -501,9 +495,6 @@ export declare function coreBootstrap(componentFactory: ComponentFactory, /** @experimental */ export declare function coreLoadAndBootstrap(componentType: Type, injector: Injector): Promise>; -/** @experimental */ -export declare function createNgZone(): NgZone; - /** @experimental */ export declare function createPlatform(injector: Injector): PlatformRef; @@ -1224,6 +1215,21 @@ export declare abstract class RootRenderer { abstract renderComponent(componentType: RenderComponentType): Renderer; } +/** @stable */ +export declare abstract class SanitizationService { + abstract sanitize(context: SecurityContext, value: string): string; +} + +/** @stable */ +export declare enum SecurityContext { + NONE = 0, + HTML = 1, + STYLE = 2, + SCRIPT = 3, + URL = 4, + RESOURCE_URL = 5, +} + /** @stable */ export declare var Self: SelfMetadataFactory; diff --git a/tools/public_api_guard/core/testing.d.ts b/tools/public_api_guard/core/testing.d.ts index 3d9fd18415..908a6bf594 100644 --- a/tools/public_api_guard/core/testing.d.ts +++ b/tools/public_api_guard/core/testing.d.ts @@ -16,7 +16,7 @@ export declare function beforeEachProviders(fn: () => Array): void; /** @stable */ export declare class ComponentFixture { changeDetectorRef: ChangeDetectorRef; - componentInstance: any; + componentInstance: T; componentRef: ComponentRef; debugElement: DebugElement; elementRef: ElementRef; diff --git a/tools/public_api_guard/platform-browser-dynamic/index.d.ts b/tools/public_api_guard/platform-browser-dynamic/index.d.ts index c91e85811d..ddb333534e 100644 --- a/tools/public_api_guard/platform-browser-dynamic/index.d.ts +++ b/tools/public_api_guard/platform-browser-dynamic/index.d.ts @@ -1,5 +1,8 @@ /** @experimental */ -export declare function bootstrap(appComponentType: Type, customProviders?: Array): Promise>; +export declare function bootstrap(appComponentType: ConcreteType, customProviders?: Array): Promise>; + +/** @stable */ +export declare function bootstrapModule(moduleType: ConcreteType, compiler?: Compiler): Promise>; /** @experimental */ export declare function bootstrapWorkerApp(appComponentType: Type, customProviders?: Array): Promise>; @@ -10,5 +13,12 @@ export declare function bootstrapWorkerUi(workerScriptUri: string, customProvide /** @experimental */ export declare const BROWSER_APP_COMPILER_PROVIDERS: Array; +/** @stable */ +export declare function browserCompiler({useDebug, useJit, providers}?: { + useDebug?: boolean; + useJit?: boolean; + providers?: Array; +}): Compiler; + /** @experimental */ export declare const CACHED_TEMPLATE_PROVIDER: Array; diff --git a/tools/public_api_guard/platform-browser/index.d.ts b/tools/public_api_guard/platform-browser/index.d.ts index 8fd3640686..c1a7d2e281 100644 --- a/tools/public_api_guard/platform-browser/index.d.ts +++ b/tools/public_api_guard/platform-browser/index.d.ts @@ -1,3 +1,12 @@ +/** @experimental */ +export declare abstract class AnimationDriver { + abstract animate(element: any, startingStyles: AnimationStyles, keyframes: AnimationKeyframe[], duration: number, delay: number, easing: string): AnimationPlayer; + static NOOP: AnimationDriver; +} + +/** @stable */ +export declare function bootstrapModuleFactory(moduleFactory: AppModuleFactory): AppModuleRef; + /** @experimental */ export declare const BROWSER_APP_PROVIDERS: Array; @@ -7,6 +16,10 @@ export declare const BROWSER_PLATFORM_PROVIDERS: Array; /** @experimental */ export declare const BROWSER_SANITIZATION_PROVIDERS: Array; +/** @stable */ +export declare class BrowserModule { +} + /** @experimental */ export declare function browserPlatform(): PlatformRef; @@ -147,9 +160,6 @@ export interface SafeStyle extends SafeValue { export interface SafeUrl extends SafeValue { } -/** @experimental */ -export declare var SecurityContext: typeof t.SecurityContext; - /** @experimental */ export declare abstract class ServiceMessageBroker { abstract registerMethod(methodName: string, signature: Type[], method: Function, returnType?: Type): void;