feat(core): Add type information to injector.get() (#13785)

- Introduce `InjectionToken<T>` which is a parameterized and type-safe
  version of `OpaqueToken`.

DEPRECATION:
- `OpaqueToken` is now deprecated, use `InjectionToken<T>` instead.
- `Injector.get(token: any, notFoundValue?: any): any` is now deprecated
  use the same method which is now overloaded as
  `Injector.get<T>(token: Type<T>|InjectionToken<T>, notFoundValue?: T): T;`.

Migration
- Replace `OpaqueToken` with `InjectionToken<?>` and parameterize it.
- Migrate your code to only use `Type<?>` or `InjectionToken<?>` as
  injection tokens. Using other tokens will not be supported in the
  future.

BREAKING CHANGE:
- Because `injector.get()` is now parameterize it is possible that code
  which used to work no longer type checks. Example would be if one
  injects `Foo` but configures it as `{provide: Foo, useClass: MockFoo}`.
  The injection instance will be that of `MockFoo` but the type will be
  `Foo` instead of `any` as in the past. This means that it was possible
  to call a method on `MockFoo` in the past which now will fail type
  check. See this example:

```
class Foo {}
class MockFoo extends Foo {
  setupMock();
}

var PROVIDERS = [
  {provide: Foo, useClass: MockFoo}
];

...

function myTest(injector: Injector) {
  var foo = injector.get(Foo);
  // This line used to work since `foo` used to be `any` before this
  // change, it will now be `Foo`, and `Foo` does not have `setUpMock()`.
  // The fix is to downcast: `injector.get(Foo) as MockFoo`.
  foo.setUpMock();
}
```

PR Close #13785
This commit is contained in:
Miško Hevery 2017-01-03 16:54:46 -08:00 committed by Miško Hevery
parent 6d1f1a43bb
commit d169c2434e
59 changed files with 255 additions and 175 deletions

View File

@ -9,7 +9,7 @@
// Must be imported first, because angular2 decorators throws on load.
import 'reflect-metadata';
export {Injector, OpaqueToken, Provider, ReflectiveInjector} from '@angular/core';
export {InjectionToken, Injector, Provider, ReflectiveInjector} from '@angular/core';
export {Options} from './src/common_options';
export {MeasureValues} from './src/measure_values';
export {Metric} from './src/metric';

View File

@ -6,26 +6,26 @@
* found in the LICENSE file at https://angular.io/license
*/
import {OpaqueToken} from '@angular/core';
import {InjectionToken} from '@angular/core';
import * as fs from 'fs';
export class Options {
static SAMPLE_ID = new OpaqueToken('Options.sampleId');
static DEFAULT_DESCRIPTION = new OpaqueToken('Options.defaultDescription');
static SAMPLE_DESCRIPTION = new OpaqueToken('Options.sampleDescription');
static FORCE_GC = new OpaqueToken('Options.forceGc');
static SAMPLE_ID = new InjectionToken('Options.sampleId');
static DEFAULT_DESCRIPTION = new InjectionToken('Options.defaultDescription');
static SAMPLE_DESCRIPTION = new InjectionToken('Options.sampleDescription');
static FORCE_GC = new InjectionToken('Options.forceGc');
static NO_PREPARE = () => true;
static PREPARE = new OpaqueToken('Options.prepare');
static EXECUTE = new OpaqueToken('Options.execute');
static CAPABILITIES = new OpaqueToken('Options.capabilities');
static USER_AGENT = new OpaqueToken('Options.userAgent');
static MICRO_METRICS = new OpaqueToken('Options.microMetrics');
static USER_METRICS = new OpaqueToken('Options.userMetrics');
static NOW = new OpaqueToken('Options.now');
static WRITE_FILE = new OpaqueToken('Options.writeFile');
static RECEIVED_DATA = new OpaqueToken('Options.receivedData');
static REQUEST_COUNT = new OpaqueToken('Options.requestCount');
static CAPTURE_FRAMES = new OpaqueToken('Options.frameCapture');
static PREPARE = new InjectionToken('Options.prepare');
static EXECUTE = new InjectionToken('Options.execute');
static CAPABILITIES = new InjectionToken('Options.capabilities');
static USER_AGENT = new InjectionToken('Options.userAgent');
static MICRO_METRICS = new InjectionToken('Options.microMetrics');
static USER_METRICS = new InjectionToken('Options.userMetrics');
static NOW = new InjectionToken('Options.now');
static WRITE_FILE = new InjectionToken('Options.writeFile');
static RECEIVED_DATA = new InjectionToken('Options.receivedData');
static REQUEST_COUNT = new InjectionToken('Options.requestCount');
static CAPTURE_FRAMES = new InjectionToken('Options.frameCapture');
static DEFAULT_PROVIDERS = [
{provide: Options.DEFAULT_DESCRIPTION, useValue: {}},
{provide: Options.SAMPLE_DESCRIPTION, useValue: {}},

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Injector, OpaqueToken} from '@angular/core';
import {InjectionToken, Injector} from '@angular/core';
import {Metric} from '../metric';
@ -60,4 +60,4 @@ function mergeStringMaps(maps: {[key: string]: string}[]): {[key: string]: strin
return result;
}
const _CHILDREN = new OpaqueToken('MultiMetric.children');
const _CHILDREN = new InjectionToken('MultiMetric.children');

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Inject, Injectable, OpaqueToken} from '@angular/core';
import {Inject, Injectable, InjectionToken} from '@angular/core';
import {Options} from '../common_options';
import {Metric} from '../metric';
@ -18,7 +18,7 @@ import {PerfLogEvent, PerfLogFeatures, WebDriverExtension} from '../web_driver_e
*/
@Injectable()
export class PerflogMetric extends Metric {
static SET_TIMEOUT = new OpaqueToken('PerflogMetric.setTimeout');
static SET_TIMEOUT = new InjectionToken('PerflogMetric.setTimeout');
static PROVIDERS = [
PerflogMetric, {
provide: PerflogMetric.SET_TIMEOUT,

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Inject, Injectable, OpaqueToken} from '@angular/core';
import {Inject, Injectable, InjectionToken} from '@angular/core';
import {print} from '../facade/lang';
import {MeasureValues} from '../measure_values';
import {Reporter} from '../reporter';
@ -20,8 +20,8 @@ import {formatNum, formatStats, sortedProps} from './util';
*/
@Injectable()
export class ConsoleReporter extends Reporter {
static PRINT = new OpaqueToken('ConsoleReporter.print');
static COLUMN_WIDTH = new OpaqueToken('ConsoleReporter.columnWidth');
static PRINT = new InjectionToken('ConsoleReporter.print');
static COLUMN_WIDTH = new InjectionToken('ConsoleReporter.columnWidth');
static PROVIDERS = [
ConsoleReporter, {provide: ConsoleReporter.COLUMN_WIDTH, useValue: 18},
{provide: ConsoleReporter.PRINT, useValue: print}

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Inject, Injectable, OpaqueToken} from '@angular/core';
import {Inject, Injectable, InjectionToken} from '@angular/core';
import {Options} from '../common_options';
import {MeasureValues} from '../measure_values';
@ -21,7 +21,7 @@ import {formatStats, sortedProps} from './util';
*/
@Injectable()
export class JsonFileReporter extends Reporter {
static PATH = new OpaqueToken('JsonFileReporter.path');
static PATH = new InjectionToken('JsonFileReporter.path');
static PROVIDERS = [JsonFileReporter, {provide: JsonFileReporter.PATH, useValue: '.'}];
constructor(

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Injector, OpaqueToken} from '@angular/core';
import {InjectionToken, Injector} from '@angular/core';
import {MeasureValues} from '../measure_values';
import {Reporter} from '../reporter';
@ -39,4 +39,4 @@ export class MultiReporter extends Reporter {
}
}
const _CHILDREN = new OpaqueToken('MultiReporter.children');
const _CHILDREN = new InjectionToken('MultiReporter.children');

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {OpaqueToken} from '@angular/core';
import {InjectionToken} from '@angular/core';
import {Options} from './common_options';
import {Metric} from './metric';

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Inject, Injectable, OpaqueToken} from '@angular/core';
import {Inject, Injectable, InjectionToken} from '@angular/core';
import {MeasureValues} from '../measure_values';
import {Statistic} from '../statistic';
@ -18,8 +18,8 @@ import {Validator} from '../validator';
*/
@Injectable()
export class RegressionSlopeValidator extends Validator {
static SAMPLE_SIZE = new OpaqueToken('RegressionSlopeValidator.sampleSize');
static METRIC = new OpaqueToken('RegressionSlopeValidator.metric');
static SAMPLE_SIZE = new InjectionToken('RegressionSlopeValidator.sampleSize');
static METRIC = new InjectionToken('RegressionSlopeValidator.metric');
static PROVIDERS = [
RegressionSlopeValidator, {provide: RegressionSlopeValidator.SAMPLE_SIZE, useValue: 10},
{provide: RegressionSlopeValidator.METRIC, useValue: 'scriptTime'}

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Inject, Injectable, OpaqueToken} from '@angular/core';
import {Inject, Injectable, InjectionToken} from '@angular/core';
import {MeasureValues} from '../measure_values';
import {Validator} from '../validator';
@ -16,7 +16,7 @@ import {Validator} from '../validator';
*/
@Injectable()
export class SizeValidator extends Validator {
static SAMPLE_SIZE = new OpaqueToken('SizeValidator.sampleSize');
static SAMPLE_SIZE = new InjectionToken('SizeValidator.sampleSize');
static PROVIDERS = [SizeValidator, {provide: SizeValidator.SAMPLE_SIZE, useValue: 10}];
constructor(@Inject(SizeValidator.SAMPLE_SIZE) private _sampleSize: number) { super(); }

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Injector, OpaqueToken} from '@angular/core';
import {InjectionToken, Injector} from '@angular/core';
import {Options} from './common_options';
@ -101,4 +101,4 @@ export class PerfLogFeatures {
}
}
const _CHILDREN = new OpaqueToken('WebDriverExtension.children');
const _CHILDREN = new InjectionToken('WebDriverExtension.children');

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {OpaqueToken} from '@angular/core';
import {InjectionToken} from '@angular/core';
import {LocationChangeListener} from './platform_location';
/**
@ -61,4 +61,4 @@ export abstract class LocationStrategy {
*
* @stable
*/
export const APP_BASE_HREF: OpaqueToken = new OpaqueToken('appBaseHref');
export const APP_BASE_HREF = new InjectionToken<string>('appBaseHref');

View File

@ -8,7 +8,7 @@
import {CommonModule} from '@angular/common';
import {NgComponentOutlet} from '@angular/common/src/directives/ng_component_outlet';
import {Component, ComponentRef, Inject, Injector, NO_ERRORS_SCHEMA, NgModule, OpaqueToken, Optional, Provider, QueryList, ReflectiveInjector, TemplateRef, Type, ViewChild, ViewChildren, ViewContainerRef} from '@angular/core';
import {Component, ComponentRef, Inject, InjectionToken, Injector, NO_ERRORS_SCHEMA, NgModule, Optional, Provider, QueryList, ReflectiveInjector, TemplateRef, Type, ViewChild, ViewChildren, ViewContainerRef} from '@angular/core';
import {TestBed, async} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/matchers';
@ -146,7 +146,7 @@ export function main() {
});
}
const TEST_TOKEN = new OpaqueToken('TestToken');
const TEST_TOKEN = new InjectionToken('TestToken');
@Component({selector: 'injected-component', template: 'foo'})
class InjectedComponent {
constructor(@Optional() @Inject(TEST_TOKEN) public testToken: any) {}

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ANALYZE_FOR_ENTRY_COMPONENTS, Component, ComponentFactoryResolver, Inject, OpaqueToken} from '@angular/core';
import {ANALYZE_FOR_ENTRY_COMPONENTS, Component, ComponentFactoryResolver, Inject, InjectionToken} from '@angular/core';
import {BasicComp} from './basic';
@ -15,7 +15,7 @@ export class CompWithEntryComponents {
constructor(public cfr: ComponentFactoryResolver) {}
}
export const SOME_TOKEN = new OpaqueToken('someToken');
export const SOME_TOKEN = new InjectionToken('someToken');
export function provideValueWithEntryComponents(value: any) {
return [

View File

@ -7,21 +7,21 @@
*/
import * as common from '@angular/common';
import {CUSTOM_ELEMENTS_SCHEMA, Component, Directive, EventEmitter, Inject, NgModule, OpaqueToken, Output} from '@angular/core';
import {CUSTOM_ELEMENTS_SCHEMA, Component, Directive, EventEmitter, Inject, InjectionToken, NgModule, Output} from '@angular/core';
import {Observable} from 'rxjs/Observable';
import {wrapInArray} from './funcs';
export const SOME_OPAQUE_TOKEN = new OpaqueToken('opaqueToken');
export const SOME_INJECTON_TOKEN = new InjectionToken('injectionToken');
@Component({
selector: 'comp-providers',
template: '',
providers: [
{provide: 'strToken', useValue: 'strValue'},
{provide: SOME_OPAQUE_TOKEN, useValue: 10},
{provide: SOME_INJECTON_TOKEN, useValue: 10},
{provide: 'reference', useValue: common.NgIf},
{provide: 'complexToken', useValue: {a: 1, b: ['test', SOME_OPAQUE_TOKEN]}},
{provide: 'complexToken', useValue: {a: 1, b: ['test', SOME_INJECTON_TOKEN]}},
]
})
export class CompWithProviders {

View File

@ -7,7 +7,7 @@
*/
import {LowerCasePipe, NgIf} from '@angular/common';
import {ANALYZE_FOR_ENTRY_COMPONENTS, Component, ComponentFactoryResolver, Directive, Inject, Injectable, Input, ModuleWithProviders, NgModule, OpaqueToken, Pipe} from '@angular/core';
import {ANALYZE_FOR_ENTRY_COMPONENTS, Component, ComponentFactoryResolver, Directive, Inject, Injectable, InjectionToken, Input, ModuleWithProviders, NgModule, Pipe} from '@angular/core';
@Injectable()
export class SomeService {
@ -48,7 +48,7 @@ export class CompUsingRootModuleDirectiveAndPipe {
export class CompUsingLibModuleDirectiveAndPipe {
}
export const SOME_TOKEN = new OpaqueToken('someToken');
export const SOME_TOKEN = new InjectionToken('someToken');
export function provideValueWithEntryComponents(value: any) {
return [

View File

@ -17,7 +17,8 @@ const ANGULAR_IMPORT_LOCATIONS = {
coreDecorators: '@angular/core/src/metadata',
diDecorators: '@angular/core/src/di/metadata',
diMetadata: '@angular/core/src/di/metadata',
diOpaqueToken: '@angular/core/src/di/opaque_token',
diInjectionToken: '@angular/core/src/di/injection_token',
diOpaqueToken: '@angular/core/src/di/injection_token',
animationMetadata: '@angular/core/src/animation/metadata',
provider: '@angular/core/src/di/provider'
};
@ -34,6 +35,7 @@ export class StaticReflector implements ReflectorReader {
private parameterCache = new Map<StaticSymbol, any[]>();
private methodCache = new Map<StaticSymbol, {[key: string]: boolean}>();
private conversionMap = new Map<StaticSymbol, (context: StaticSymbol, args: any[]) => any>();
private injectionToken: StaticSymbol;
private opaqueToken: StaticSymbol;
constructor(
@ -229,9 +231,10 @@ export class StaticReflector implements ReflectorReader {
}
private initializeConversionMap(): void {
const {coreDecorators, diDecorators, diMetadata, diOpaqueToken, animationMetadata, provider} =
ANGULAR_IMPORT_LOCATIONS;
this.opaqueToken = this.findDeclaration(diOpaqueToken, 'OpaqueToken');
const {coreDecorators, diDecorators, diMetadata, diInjectionToken,
diOpaqueToken, animationMetadata, provider} = ANGULAR_IMPORT_LOCATIONS;
this.injectionToken = this.findDeclaration(diInjectionToken, 'InjectionToken');
this.opaqueToken = this.findDeclaration(diInjectionToken, 'OpaqueToken');
this._registerDecoratorOrConstructor(this.findDeclaration(diDecorators, 'Host'), Host);
this._registerDecoratorOrConstructor(
@ -382,7 +385,8 @@ export class StaticReflector implements ReflectorReader {
}
if (expression instanceof StaticSymbol) {
// Stop simplification at builtin symbols
if (expression === self.opaqueToken || self.conversionMap.has(expression)) {
if (expression === self.injectionToken || expression === self.opaqueToken ||
self.conversionMap.has(expression)) {
return expression;
} else {
const staticSymbol = expression;
@ -506,9 +510,9 @@ export class StaticReflector implements ReflectorReader {
// Determine if the function is a built-in conversion
staticSymbol = simplifyInContext(context, expression['expression'], depth + 1);
if (staticSymbol instanceof StaticSymbol) {
if (staticSymbol === self.opaqueToken) {
// if somebody calls new OpaqueToken, don't create an OpaqueToken,
// but rather return the symbol to which the OpaqueToken is assigned to.
if (staticSymbol === self.injectionToken || staticSymbol === self.opaqueToken) {
// if somebody calls new InjectionToken, don't create an InjectionToken,
// but rather return the symbol to which the InjectionToken is assigned to.
return context;
}
const argExpressions: any[] = expression['arguments'] || [];
@ -674,4 +678,4 @@ function positionalError(message: string, fileName: string, line: number, column
(result as any).line = line;
(result as any).column = column;
return result;
}
}

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {COMPILER_OPTIONS, Compiler, CompilerFactory, CompilerOptions, Inject, OpaqueToken, Optional, PLATFORM_INITIALIZER, PlatformRef, Provider, ReflectiveInjector, TRANSLATIONS, TRANSLATIONS_FORMAT, Type, ViewEncapsulation, createPlatformFactory, isDevMode, platformCore} from '@angular/core';
import {COMPILER_OPTIONS, Compiler, CompilerFactory, CompilerOptions, Inject, InjectionToken, Optional, PLATFORM_INITIALIZER, PlatformRef, Provider, ReflectiveInjector, TRANSLATIONS, TRANSLATIONS_FORMAT, Type, ViewEncapsulation, createPlatformFactory, isDevMode, platformCore} from '@angular/core';
import {AnimationParser} from '../animation/animation_parser';
import {CompilerConfig} from '../config';
@ -40,7 +40,7 @@ const _NO_RESOURCE_LOADER: ResourceLoader = {
`No ResourceLoader implementation has been provided. Can't read the url "${url}"`);}
};
const baseHtmlParser = new OpaqueToken('HtmlParser');
const baseHtmlParser = new InjectionToken('HtmlParser');
/**
* A set of providers that provide `JitCompiler` and its dependencies to use for

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {AnimationAnimateMetadata, AnimationEntryMetadata, AnimationGroupMetadata, AnimationKeyframesSequenceMetadata, AnimationMetadata, AnimationStateDeclarationMetadata, AnimationStateMetadata, AnimationStateTransitionMetadata, AnimationStyleMetadata, AnimationWithStepsMetadata, Attribute, ChangeDetectionStrategy, Component, ComponentFactory, Directive, Host, Inject, Injectable, ModuleWithProviders, OpaqueToken, Optional, Provider, Query, SchemaMetadata, Self, SkipSelf, Type, resolveForwardRef} from '@angular/core';
import {AnimationAnimateMetadata, AnimationEntryMetadata, AnimationGroupMetadata, AnimationKeyframesSequenceMetadata, AnimationMetadata, AnimationStateDeclarationMetadata, AnimationStateMetadata, AnimationStateTransitionMetadata, AnimationStyleMetadata, AnimationWithStepsMetadata, Attribute, ChangeDetectionStrategy, Component, ComponentFactory, Directive, Host, Inject, Injectable, InjectionToken, ModuleWithProviders, Optional, Provider, Query, SchemaMetadata, Self, SkipSelf, Type, resolveForwardRef} from '@angular/core';
import {StaticSymbol, StaticSymbolCache} from './aot/static_symbol';
import {ngfactoryFilePath} from './aot/util';
@ -27,7 +27,7 @@ import {getUrlScheme} from './url_resolver';
import {MODULE_SUFFIX, SyntaxError, ValueTransformer, visitValue} from './util';
export type ErrorCollector = (error: any, type?: any) => void;
export const ERROR_COLLECTOR_TOKEN = new OpaqueToken('ErrorCollector');
export const ERROR_COLLECTOR_TOKEN = new InjectionToken('ErrorCollector');
// Design notes:
// - don't lazily create metadata:

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Inject, OpaqueToken, Optional, SchemaMetadata} from '@angular/core';
import {Inject, InjectionToken, Optional, SchemaMetadata} from '@angular/core';
import {CompileDirectiveMetadata, CompileDirectiveSummary, CompilePipeSummary, CompileTemplateSummary, CompileTokenMetadata, CompileTypeMetadata, identifierName} from '../compile_metadata';
import {Parser} from '../expression_parser/parser';
import {isPresent} from '../facade/lang';
@ -67,7 +67,7 @@ const TEXT_CSS_SELECTOR = CssSelector.parse('*')[0];
*
* This is currently an internal-only feature and not meant for general use.
*/
export const TEMPLATE_TRANSFORMS = new OpaqueToken('TemplateTransforms');
export const TEMPLATE_TRANSFORMS = new InjectionToken('TemplateTransforms');
export class TemplateParseError extends ParseError {
constructor(message: string, span: ParseSourceSpan, level: ParseErrorLevel) {

View File

@ -6,12 +6,13 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Inject, PACKAGE_ROOT_URL} from '@angular/core';
import {Inject, InjectionToken, PACKAGE_ROOT_URL} from '@angular/core';
import {isBlank, isPresent} from './facade/lang';
import {CompilerInjectable} from './injectable';
/**
* Create a {@link UrlResolver} with no package prefix.
*/

View File

@ -8,14 +8,14 @@
import {isPromise} from '../src/util/lang';
import {Inject, Injectable, OpaqueToken, Optional} from './di';
import {Inject, Injectable, InjectionToken, Optional} from './di';
/**
* A function that will be executed when an application is initialized.
* @experimental
*/
export const APP_INITIALIZER: any = new OpaqueToken('Application Initializer');
export const APP_INITIALIZER = new InjectionToken<Array<() => void>>('Application Initializer');
/**
* A class that reflects the state of running {@link APP_INITIALIZER}s.

View File

@ -16,7 +16,7 @@ import {ApplicationInitStatus} from './application_init';
import {APP_BOOTSTRAP_LISTENER, PLATFORM_INITIALIZER} from './application_tokens';
import {ChangeDetectorRef} from './change_detection/change_detector_ref';
import {Console} from './console';
import {Injectable, Injector, OpaqueToken, Optional, Provider, ReflectiveInjector} from './di';
import {Injectable, InjectionToken, Injector, Optional, Provider, ReflectiveInjector} from './di';
import {CompilerFactory, CompilerOptions} from './linker/compiler';
import {ComponentFactory, ComponentRef} from './linker/component_factory';
import {ComponentFactoryResolver} from './linker/component_factory_resolver';
@ -83,7 +83,7 @@ export function createPlatform(injector: Injector): PlatformRef {
'There can be only one platform. Destroy the previous one to create a new one.');
}
_platform = injector.get(PlatformRef);
const inits: Function[] = <Function[]>injector.get(PLATFORM_INITIALIZER, null);
const inits = injector.get(PLATFORM_INITIALIZER, null);
if (inits) inits.forEach(init => init());
return _platform;
}
@ -96,7 +96,7 @@ export function createPlatform(injector: Injector): PlatformRef {
export function createPlatformFactory(
parentPlatformFactory: (extraProviders?: Provider[]) => PlatformRef, name: string,
providers: Provider[] = []): (extraProviders?: Provider[]) => PlatformRef {
const marker = new OpaqueToken(`Platform: ${name}`);
const marker = new InjectionToken(`Platform: ${name}`);
return (extraProviders: Provider[] = []) => {
if (!getPlatform()) {
if (parentPlatformFactory) {
@ -413,7 +413,7 @@ export class ApplicationRef_ extends ApplicationRef {
/** @internal */
static _tickScope: WtfScopeFn = wtfCreateScope('ApplicationRef#tick()');
private _bootstrapListeners: Function[] = [];
private _bootstrapListeners: ((compRef: ComponentRef<any>) => void)[] = [];
private _rootComponents: ComponentRef<any>[] = [];
private _rootComponentTypes: Type<any>[] = [];
private _views: AppView<any>[] = [];
@ -480,8 +480,7 @@ export class ApplicationRef_ extends ApplicationRef {
this._rootComponents.push(componentRef);
// Get the listeners lazily to prevent DI cycles.
const listeners =
<((compRef: ComponentRef<any>) => void)[]>this._injector.get(APP_BOOTSTRAP_LISTENER, [])
.concat(this._bootstrapListeners);
this._injector.get(APP_BOOTSTRAP_LISTENER, []).concat(this._bootstrapListeners);
listeners.forEach((listener) => listener(componentRef));
}

View File

@ -6,7 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/
import {OpaqueToken} from './di';
import {InjectionToken} from './di';
import {ComponentRef} from './linker/component_factory';
/**
@ -19,7 +20,7 @@ import {OpaqueToken} from './di';
* using this token.
* @experimental
*/
export const APP_ID: any = new OpaqueToken('AppId');
export const APP_ID = new InjectionToken<string>('AppId');
export function _appIdRandomProviderFactory() {
return `${_randomChar()}${_randomChar()}${_randomChar()}`;
@ -43,7 +44,7 @@ function _randomChar(): string {
* A function that will be executed when a platform is initialized.
* @experimental
*/
export const PLATFORM_INITIALIZER: any = new OpaqueToken('Platform Initializer');
export const PLATFORM_INITIALIZER = new InjectionToken<Array<() => void>>('Platform Initializer');
/**
* All callbacks provided via this token will be called for every component that is bootstrapped.
@ -53,10 +54,11 @@ export const PLATFORM_INITIALIZER: any = new OpaqueToken('Platform Initializer')
*
* @experimental
*/
export const APP_BOOTSTRAP_LISTENER = new OpaqueToken('appBootstrapListener');
export const APP_BOOTSTRAP_LISTENER =
new InjectionToken<Array<(compRef: ComponentRef<any>) => void>>('appBootstrapListener');
/**
* A token which indicates the root directory of the application
* @experimental
*/
export const PACKAGE_ROOT_URL: any = new OpaqueToken('Application Packages Root URL');
export const PACKAGE_ROOT_URL = new InjectionToken<string>('Application Packages Root URL');

View File

@ -21,4 +21,4 @@ export {ReflectiveInjector} from './di/reflective_injector';
export {Provider, TypeProvider, ValueProvider, ClassProvider, ExistingProvider, FactoryProvider} from './di/provider';
export {ResolvedReflectiveFactory, ResolvedReflectiveProvider} from './di/reflective_provider';
export {ReflectiveKey} from './di/reflective_key';
export {OpaqueToken} from './di/opaque_token';
export {InjectionToken, OpaqueToken} from './di/injection_token';

View File

@ -26,10 +26,42 @@
*
* Using an `OpaqueToken` is preferable to using an `Object` as tokens because it provides better
* error messages.
* @stable
* @deprecated since v4.0.0 because it does not support type information, use `InjectionToken<?>`
* instead.
*/
export class OpaqueToken {
constructor(private _desc: string) {}
constructor(protected _desc: string) {}
toString(): string { return `Token ${this._desc}`; }
}
/**
* Creates a token that can be used in a DI Provider.
*
* Use an `InjectionToken` whenever the type you are injecting is not reified (does not have a
* runtime representation) such as when injecting an interface, callable type, array or
* parametrized type.
*
* `InjectionToken` is parametrize on `T` which is the type of object which will be returned by the
* `Injector`. This provides additional level of type safety.
*
* ```
* interface MyInterface {...}
* var myInterface = injector.get(new InjectionToken<MyInterface>('SomeToken'));
* // myInterface is inferred to be MyInterface.
* ```
*
* ### Example
*
* {@example core/di/ts/injector_spec.ts region='Injector'}
*
* @stable
*/
export class InjectionToken<T> extends OpaqueToken {
// This unused property is needed here so that TS can differentiate InjectionToken from
// OpaqueToken since otherwise they would have the same shape and be treated as equivalent.
private _differentiate_from_OpaqueToken_structurally: any;
constructor(desc: string) { super(desc); }
toString(): string { return `InjectionToken ${this._desc}`; }
}

View File

@ -8,6 +8,9 @@
import {unimplemented} from '../facade/errors';
import {stringify} from '../facade/lang';
import {Type} from '../type';
import {InjectionToken} from './injection_token';
const _THROW_IF_NOT_FOUND = new Object();
export const THROW_IF_NOT_FOUND = _THROW_IF_NOT_FOUND;
@ -52,5 +55,10 @@ export abstract class Injector {
* Injector.THROW_IF_NOT_FOUND is given
* - Returns the `notFoundValue` otherwise
*/
get<T>(token: Type<T>|InjectionToken<T>, notFoundValue?: T): T;
/**
* @deprecated from v4.0.0 use Type<T> or InjectToken<T>
*/
get(token: any, notFoundValue?: any): any;
get(token: any, notFoundValue?: any): any { return unimplemented(); }
}

View File

@ -52,7 +52,7 @@ export interface TypeProvider extends Type<any> {}
*/
export interface ValueProvider {
/**
* An injection token. (Typically an instance of `Type` or `OpaqueToken`, but can be `any`).
* An injection token. (Typically an instance of `Type` or `InjectionToken`, but can be `any`).
*/
provide: any;
@ -96,7 +96,7 @@ export interface ValueProvider {
*/
export interface ClassProvider {
/**
* An injection token. (Typically an instance of `Type` or `OpaqueToken`, but can be `any`).
* An injection token. (Typically an instance of `Type` or `InjectionToken`, but can be `any`).
*/
provide: any;
@ -134,7 +134,7 @@ export interface ClassProvider {
*/
export interface ExistingProvider {
/**
* An injection token. (Typically an instance of `Type` or `OpaqueToken`, but can be `any`).
* An injection token. (Typically an instance of `Type` or `InjectionToken`, but can be `any`).
*/
provide: any;
@ -178,7 +178,7 @@ export interface ExistingProvider {
*/
export interface FactoryProvider {
/**
* An injection token. (Typically an instance of `Type` or `OpaqueToken`, but can be `any`).
* An injection token. (Typically an instance of `Type` or `InjectionToken`, but can be `any`).
*/
provide: any;

View File

@ -6,19 +6,19 @@
* found in the LICENSE file at https://angular.io/license
*/
import {OpaqueToken} from '../di/opaque_token';
import {InjectionToken} from '../di/injection_token';
/**
* @experimental i18n support is experimental.
*/
export const LOCALE_ID = new OpaqueToken('LocaleId');
export const LOCALE_ID = new InjectionToken<string>('LocaleId');
/**
* @experimental i18n support is experimental.
*/
export const TRANSLATIONS = new OpaqueToken('Translations');
export const TRANSLATIONS = new InjectionToken<string>('Translations');
/**
* @experimental i18n support is experimental.
*/
export const TRANSLATIONS_FORMAT = new OpaqueToken('TranslationsFormat');
export const TRANSLATIONS_FORMAT = new InjectionToken<string>('TranslationsFormat');

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Injectable, OpaqueToken} from '../di';
import {Injectable, InjectionToken} from '../di';
import {BaseError} from '../facade/errors';
import {stringify} from '../facade/lang';
import {ViewEncapsulation} from '../metadata';
@ -119,7 +119,7 @@ export type CompilerOptions = {
*
* @experimental
*/
export const COMPILER_OPTIONS = new OpaqueToken('compilerOptions');
export const COMPILER_OPTIONS = new InjectionToken<CompilerOptions[]>('compilerOptions');
/**
* A factory for creating a Compiler

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {OpaqueToken} from '../di/opaque_token';
import {InjectionToken} from '../di/injection_token';
import {Type} from '../type';
import {makeParamDecorator, makePropDecorator} from '../util/decorators';
@ -44,7 +44,7 @@ import {makeParamDecorator, makePropDecorator} from '../util/decorators';
*
* @experimental
*/
export const ANALYZE_FOR_ENTRY_COMPONENTS = new OpaqueToken('AnalyzeForEntryComponents');
export const ANALYZE_FOR_ENTRY_COMPONENTS = new InjectionToken<any>('AnalyzeForEntryComponents');
/**
* Type of the Attribute decorator / constructor function.

View File

@ -7,7 +7,7 @@
*/
import {CommonModule} from '@angular/common';
import {ComponentFactory, Host, Inject, Injectable, Injector, NO_ERRORS_SCHEMA, NgModule, OnDestroy, OpaqueToken, ReflectiveInjector, SkipSelf} from '@angular/core';
import {ComponentFactory, Host, Inject, Injectable, InjectionToken, Injector, NO_ERRORS_SCHEMA, NgModule, OnDestroy, ReflectiveInjector, SkipSelf} from '@angular/core';
import {ChangeDetectionStrategy, ChangeDetectorRef, PipeTransform} from '@angular/core/src/change_detection/change_detection';
import {ComponentFactoryResolver} from '@angular/core/src/linker/component_factory_resolver';
import {ElementRef} from '@angular/core/src/linker/element_ref';
@ -25,7 +25,7 @@ import {expect} from '@angular/platform-browser/testing/matchers';
import {EventEmitter} from '../../src/facade/async';
import {isBlank, isPresent, stringify} from '../../src/facade/lang';
const ANCHOR_ELEMENT = new OpaqueToken('AnchorElement');
const ANCHOR_ELEMENT = new InjectionToken('AnchorElement');
export function main() {
describe('jit', () => { declareTests({useJit: true}); });

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ANALYZE_FOR_ENTRY_COMPONENTS, CUSTOM_ELEMENTS_SCHEMA, Compiler, Component, ComponentFactoryResolver, Directive, HostBinding, Inject, Injectable, Injector, Input, NgModule, NgModuleRef, Optional, Pipe, Provider, Self, Type, forwardRef, getModuleFactory} from '@angular/core';
import {ANALYZE_FOR_ENTRY_COMPONENTS, CUSTOM_ELEMENTS_SCHEMA, Compiler, Component, ComponentFactoryResolver, Directive, HostBinding, Inject, Injectable, InjectionToken, Injector, Input, NgModule, NgModuleRef, Optional, Pipe, Provider, Self, Type, forwardRef, getModuleFactory} from '@angular/core';
import {Console} from '@angular/core/src/console';
import {ComponentFixture, TestBed, inject} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/matchers';
@ -30,6 +30,7 @@ class Dashboard {
class TurboEngine extends Engine {}
const CARS = new InjectionToken<Car[]>('Cars');
@Injectable()
class Car {
engine: Engine;
@ -692,11 +693,11 @@ function declareTests({useJit}: {useJit: boolean}) {
it('should support multiProviders', () => {
const injector = createInjector([
Engine, {provide: Car, useClass: SportsCar, multi: true},
{provide: Car, useClass: CarWithOptionalEngine, multi: true}
Engine, {provide: CARS, useClass: SportsCar, multi: true},
{provide: CARS, useClass: CarWithOptionalEngine, multi: true}
]);
const cars = injector.get(Car);
const cars = injector.get(CARS);
expect(cars.length).toEqual(2);
expect(cars[0]).toBeAnInstanceOf(SportsCar);
expect(cars[1]).toBeAnInstanceOf(CarWithOptionalEngine);
@ -704,9 +705,9 @@ function declareTests({useJit}: {useJit: boolean}) {
it('should support multiProviders that are created using useExisting', () => {
const injector = createInjector(
[Engine, SportsCar, {provide: Car, useExisting: SportsCar, multi: true}]);
[Engine, SportsCar, {provide: CARS, useExisting: SportsCar, multi: true}]);
const cars = injector.get(Car);
const cars = injector.get(CARS);
expect(cars.length).toEqual(1);
expect(cars[0]).toBe(injector.get(SportsCar));
});

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ANALYZE_FOR_ENTRY_COMPONENTS, Component, Injector, OpaqueToken, Pipe, PipeTransform, Provider} from '@angular/core';
import {ANALYZE_FOR_ENTRY_COMPONENTS, Component, InjectionToken, Injector, Pipe, PipeTransform, Provider} from '@angular/core';
import {TestBed} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/matchers';
@ -104,8 +104,8 @@ function declareTests({useJit}: {useJit: boolean}) {
return TestBed.createComponent(MyComp1).componentInstance.injector;
}
it('should support providers with an OpaqueToken that contains a `.` in the name', () => {
const token = new OpaqueToken('a.b');
it('should support providers with an InjectionToken that contains a `.` in the name', () => {
const token = new InjectionToken('a.b');
const tokenValue = 1;
const injector = createInjector([{provide: token, useValue: tokenValue}]);
expect(injector.get(token)).toEqual(tokenValue);
@ -127,9 +127,9 @@ function declareTests({useJit}: {useJit: boolean}) {
expect(injector.get(token)).toEqual(tokenValue);
});
it('should support providers with an OpaqueToken that has a StringMap as value', () => {
const token1 = new OpaqueToken('someToken');
const token2 = new OpaqueToken('someToken');
it('should support providers with an InjectionToken that has a StringMap as value', () => {
const token1 = new InjectionToken('someToken');
const token2 = new InjectionToken('someToken');
const tokenValue1 = {'a': 1};
const tokenValue2 = {'a': 1};
const injector = createInjector(

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {CompilerOptions, Component, Directive, Injector, ModuleWithComponentFactories, NgModule, NgModuleRef, NgZone, OpaqueToken, Pipe, PlatformRef, Provider, ReflectiveInjector, SchemaMetadata, Type} from '@angular/core';
import {CompilerOptions, Component, Directive, InjectionToken, Injector, ModuleWithComponentFactories, NgModule, NgModuleRef, NgZone, Pipe, PlatformRef, Provider, ReflectiveInjector, SchemaMetadata, Type} from '@angular/core';
import {AsyncTestCompleter} from './async_test_completer';
import {ComponentFixture} from './component_fixture';
@ -30,12 +30,13 @@ let _nextRootElementId = 0;
/**
* @experimental
*/
export const ComponentFixtureAutoDetect = new OpaqueToken('ComponentFixtureAutoDetect');
export const ComponentFixtureAutoDetect =
new InjectionToken<boolean[]>('ComponentFixtureAutoDetect');
/**
* @experimental
*/
export const ComponentFixtureNoNgZone = new OpaqueToken('ComponentFixtureNoNgZone');
export const ComponentFixtureNoNgZone = new InjectionToken<boolean[]>('ComponentFixtureNoNgZone');
/**
* @experimental

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Injector, ReflectiveInjector} from '@angular/core';
import {InjectionToken, Injector, ReflectiveInjector} from '@angular/core';
export function main() {
describe('injector metadata examples', () => {
@ -25,7 +25,17 @@ export function main() {
const injector = ReflectiveInjector.resolveAndCreate([]);
expect(injector.get(Injector)).toBe(injector);
// #enddocregion
});
it('should infer type', () => {
// #docregion InjectionToken
const BASE_URL = new InjectionToken<string>('BaseUrl');
const injector =
ReflectiveInjector.resolveAndCreate([{provide: BASE_URL, useValue: 'http://localhost'}]);
const url = injector.get(BASE_URL);
// here `url` is inferred to be `string` because `BASE_URL` is `InjectionToken<string>`.
expect(url).toBe('http://localhost');
// #enddocregion
});
});
}

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Inject, Injectable, OpaqueToken, Optional, ReflectiveInjector} from '@angular/core';
import {Inject, Injectable, InjectionToken, Optional, ReflectiveInjector} from '@angular/core';
export function main() {
describe('Provider examples', () => {
@ -113,8 +113,8 @@ export function main() {
describe('FactoryProvider', () => {
it('works', () => {
// #docregion FactoryProvider
const Location = new OpaqueToken('location');
const Hash = new OpaqueToken('hash');
const Location = new InjectionToken('location');
const Hash = new InjectionToken('hash');
const injector = ReflectiveInjector.resolveAndCreate([
{provide: Location, useValue: 'http://angular.io/#someLocation'}, {
@ -130,8 +130,8 @@ export function main() {
it('supports optional dependencies', () => {
// #docregion FactoryProviderOptionalDeps
const Location = new OpaqueToken('location');
const Hash = new OpaqueToken('hash');
const Location = new InjectionToken('location');
const Hash = new InjectionToken('hash');
const injector = ReflectiveInjector.resolveAndCreate([{
provide: Hash,

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {OpaqueToken} from '@angular/core';
import {InjectionToken} from '@angular/core';
/**
* A bridge between a control and a native element.
@ -49,4 +49,4 @@ export interface ControlValueAccessor {
* See {@link DefaultValueAccessor} for how to implement one.
* @stable
*/
export const NG_VALUE_ACCESSOR: OpaqueToken = new OpaqueToken('NgValueAccessor');
export const NG_VALUE_ACCESSOR = new InjectionToken<ControlValueAccessor>('NgValueAccessor');

View File

@ -116,12 +116,11 @@ function _throwError(dir: AbstractControlDirective, message: string): void {
throw new Error(`${message} ${messageEnd}`);
}
export function composeValidators(validators: /* Array<Validator|Function> */ any[]): ValidatorFn {
export function composeValidators(validators: Array<Validator|Function>): ValidatorFn {
return isPresent(validators) ? Validators.compose(validators.map(normalizeValidator)) : null;
}
export function composeAsyncValidators(validators: /* Array<Validator|Function> */ any[]):
AsyncValidatorFn {
export function composeAsyncValidators(validators: Array<Validator|Function>): AsyncValidatorFn {
return isPresent(validators) ? Validators.composeAsync(validators.map(normalizeAsyncValidator)) :
null;
}

View File

@ -6,9 +6,10 @@
* found in the LICENSE file at https://angular.io/license
*/
import {OpaqueToken} from '@angular/core';
import {InjectionToken} from '@angular/core';
import {toPromise} from 'rxjs/operator/toPromise';
import {AsyncValidatorFn, ValidatorFn} from './directives/validators';
import {AsyncValidatorFn, Validator, ValidatorFn} from './directives/validators';
import {StringMapWrapper} from './facade/collection';
import {isPresent} from './facade/lang';
import {AbstractControl} from './model';
@ -29,7 +30,7 @@ function isEmptyInputValue(value: any): boolean {
* {@example core/forms/ts/ng_validators/ng_validators.ts region='ng_validators'}
* @stable
*/
export const NG_VALIDATORS: OpaqueToken = new OpaqueToken('NgValidators');
export const NG_VALIDATORS = new InjectionToken<Array<Validator|Function>>('NgValidators');
/**
* Providers for asynchronous validators to be used for {@link FormControl}s
@ -41,7 +42,8 @@ export const NG_VALIDATORS: OpaqueToken = new OpaqueToken('NgValidators');
*
* @stable
*/
export const NG_ASYNC_VALIDATORS: OpaqueToken = new OpaqueToken('NgAsyncValidators');
export const NG_ASYNC_VALIDATORS =
new InjectionToken<Array<Validator|Function>>('NgAsyncValidators');
/**
* Provides a set of validators used by form controls.

View File

@ -42,8 +42,8 @@ export function main() {
http = injector.get(Http);
jsonp = injector.get(Jsonp);
jsonpBackend = injector.get(JSONPBackend);
xhrBackend = injector.get(XHRBackend);
jsonpBackend = injector.get(JSONPBackend) as MockBackend;
xhrBackend = injector.get(XHRBackend) as any as MockBackend;
let xhrCreatedConnections = 0;
let jsonpCreatedConnections = 0;

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {OpaqueToken} from '@angular/core';
import {InjectionToken} from '@angular/core';
/**
* A DI Token representing the main rendering context. In a browser this is the DOM Document.
@ -16,4 +16,4 @@ import {OpaqueToken} from '@angular/core';
*
* @stable
*/
export const DOCUMENT: OpaqueToken = new OpaqueToken('DocumentToken');
export const DOCUMENT = new InjectionToken<Document>('DocumentToken');

View File

@ -6,13 +6,16 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Inject, Injectable, NgZone, OpaqueToken} from '@angular/core';
import {Inject, Injectable, InjectionToken, NgZone} from '@angular/core';
import {getDOM} from '../dom_adapter';
/**
* @stable
*/
export const EVENT_MANAGER_PLUGINS: OpaqueToken = new OpaqueToken('EventManagerPlugins');
export const EVENT_MANAGER_PLUGINS =
new InjectionToken<EventManagerPlugin[]>('EventManagerPlugins');
/**
* @stable

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Inject, Injectable, OpaqueToken} from '@angular/core';
import {Inject, Injectable, InjectionToken} from '@angular/core';
import {EventManagerPlugin} from './event_manager';
const EVENT_NAMES = {
@ -53,7 +53,7 @@ const EVENT_NAMES = {
*
* @experimental
*/
export const HAMMER_GESTURE_CONFIG: OpaqueToken = new OpaqueToken('HammerGestureConfig');
export const HAMMER_GESTURE_CONFIG = new InjectionToken<HammerGestureConfig>('HammerGestureConfig');
export interface HammerInstance {
on(eventName: string, callback: Function): void;

View File

@ -6,6 +6,6 @@
* found in the LICENSE file at https://angular.io/license
*/
import {OpaqueToken} from '@angular/core';
import {InjectionToken} from '@angular/core';
export const ON_WEB_WORKER = new OpaqueToken('WebWorker.onWebWorker');
export const ON_WEB_WORKER = new InjectionToken('WebWorker.onWebWorker');

View File

@ -7,11 +7,12 @@
*/
import {PlatformLocation} from '@angular/common';
import {APP_INITIALIZER, NgZone} from '@angular/core';
import {APP_INITIALIZER, InjectionToken, NgZone} from '@angular/core';
import {WebWorkerPlatformLocation} from './platform_location';
/**
* Those providers should be added when the router is used in a worker context in addition to the
* {@link ROUTER_PROVIDERS} and after them.

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ErrorHandler, Injectable, Injector, NgZone, OpaqueToken, PLATFORM_INITIALIZER, PlatformRef, Provider, RootRenderer, Testability, createPlatformFactory, isDevMode, platformCore} from '@angular/core';
import {ErrorHandler, Injectable, InjectionToken, Injector, NgZone, PLATFORM_INITIALIZER, PlatformRef, Provider, RootRenderer, Testability, createPlatformFactory, isDevMode, platformCore} from '@angular/core';
import {AnimationDriver, DOCUMENT, EVENT_MANAGER_PLUGINS, EventManager, HAMMER_GESTURE_CONFIG, HammerGestureConfig} from '@angular/platform-browser';
import {APP_ID_RANDOM_PROVIDER} from './private_import_core';
@ -21,6 +21,7 @@ import {ServiceMessageBrokerFactory, ServiceMessageBrokerFactory_} from './web_w
import {MessageBasedRenderer} from './web_workers/ui/renderer';
/**
* Wrapper class that exposes the Worker
* and underlying {@link MessageBus} for lower level message passing.
@ -42,7 +43,7 @@ export class WebWorkerInstance {
/**
* @experimental WebWorker support is currently experimental.
*/
export const WORKER_SCRIPT: OpaqueToken = new OpaqueToken('WebWorkerScript');
export const WORKER_SCRIPT = new InjectionToken<string>('WebWorkerScript');
/**
* A multi-provider used to automatically call the `start()` method after the service is
@ -52,7 +53,7 @@ export const WORKER_SCRIPT: OpaqueToken = new OpaqueToken('WebWorkerScript');
* @experimental WebWorker support is currently experimental.
*/
export const WORKER_UI_STARTABLE_MESSAGING_SERVICE =
new OpaqueToken('WorkerRenderStartableMsgService');
new InjectionToken<MessageBasedRenderer[]>('WorkerRenderStartableMsgService');
export const _WORKER_UI_PLATFORM_PROVIDERS: Provider[] = [
{provide: NgZone, useFactory: createNgZone, deps: []},

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Compiler, ComponentFactoryResolver, Injector, NgModuleFactory, NgModuleFactoryLoader, OpaqueToken} from '@angular/core';
import {Compiler, ComponentFactoryResolver, InjectionToken, Injector, NgModuleFactory, NgModuleFactoryLoader} from '@angular/core';
import {Observable} from 'rxjs/Observable';
import {fromPromise} from 'rxjs/observable/fromPromise';
import {of } from 'rxjs/observable/of';
@ -16,10 +16,11 @@ import {mergeMap} from 'rxjs/operator/mergeMap';
import {LoadChildren, Route} from './config';
import {flatten, wrapIntoObservable} from './utils/collection';
/**
* @experimental
*/
export const ROUTES = new OpaqueToken('ROUTES');
export const ROUTES = new InjectionToken<Route[][]>('ROUTES');
export class LoadedRouterConfig {
constructor(

View File

@ -7,7 +7,7 @@
*/
import {APP_BASE_HREF, HashLocationStrategy, Location, LocationStrategy, PathLocationStrategy, PlatformLocation} from '@angular/common';
import {ANALYZE_FOR_ENTRY_COMPONENTS, APP_BOOTSTRAP_LISTENER, ApplicationRef, Compiler, ComponentRef, Inject, Injector, ModuleWithProviders, NgModule, NgModuleFactoryLoader, NgProbeToken, OpaqueToken, Optional, Provider, SkipSelf, SystemJsNgModuleLoader} from '@angular/core';
import {ANALYZE_FOR_ENTRY_COMPONENTS, APP_BOOTSTRAP_LISTENER, ApplicationRef, Compiler, ComponentRef, Inject, InjectionToken, Injector, ModuleWithProviders, NgModule, NgModuleFactoryLoader, NgProbeToken, Optional, Provider, SkipSelf, SystemJsNgModuleLoader} from '@angular/core';
import {Route, Routes} from './config';
import {RouterLink, RouterLinkWithHref} from './directives/router_link';
@ -36,12 +36,12 @@ const ROUTER_DIRECTIVES = [RouterOutlet, RouterLink, RouterLinkWithHref, RouterL
* @whatItDoes Is used in DI to configure the router.
* @stable
*/
export const ROUTER_CONFIGURATION = new OpaqueToken('ROUTER_CONFIGURATION');
export const ROUTER_CONFIGURATION = new InjectionToken<ExtraOptions>('ROUTER_CONFIGURATION');
/**
* @docsNotRequired
*/
export const ROUTER_FORROOT_GUARD = new OpaqueToken('ROUTER_FORROOT_GUARD');
export const ROUTER_FORROOT_GUARD = new InjectionToken<void>('ROUTER_FORROOT_GUARD');
export const ROUTER_PROVIDERS: Provider[] = [
Location,
@ -301,7 +301,8 @@ export function initialRouterNavigation(
*
* @experimental
*/
export const ROUTER_INITIALIZER = new OpaqueToken('Router Initializer');
export const ROUTER_INITIALIZER =
new InjectionToken<(compRef: ComponentRef<any>) => void>('Router Initializer');
export function provideRouterInitializer() {
return [

View File

@ -6,11 +6,12 @@
* found in the LICENSE file at https://angular.io/license
*/
import {APP_BOOTSTRAP_LISTENER, ApplicationRef, OpaqueToken} from '@angular/core';
import {APP_BOOTSTRAP_LISTENER, ApplicationRef, ComponentRef, InjectionToken} from '@angular/core';
import {ExtraOptions, ROUTER_CONFIGURATION, ROUTER_INITIALIZER, Router, RouterPreloader} from '@angular/router';
import {UpgradeModule} from '@angular/upgrade/static';
/**
* @whatItDoes Creates an initializer that in addition to setting up the Angular 2
* router sets up the ngRoute integration.
@ -57,7 +58,7 @@ export function initialRouterNavigation(
const router = ngUpgrade.injector.get(Router);
const ref = ngUpgrade.injector.get(ApplicationRef);
router.resetRootComponentType(ref.componentTypes[0]);
(router as any).resetRootComponentType(ref.componentTypes[0]);
preloader.setUpPreloading();
if (opts.initialNavigation === false) {
router.setUpLocationChangeListener();
@ -86,4 +87,4 @@ export function setUpLocationSync(ngUpgrade: UpgradeModule): void {
url.href = next;
router.navigateByUrl(url.pathname);
});
}
}

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {NgModule, OpaqueToken, destroyPlatform} from '@angular/core';
import {InjectionToken, NgModule, destroyPlatform} from '@angular/core';
import {async} from '@angular/core/testing';
import {BrowserModule} from '@angular/platform-browser';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
@ -23,7 +23,7 @@ export function main() {
it('should downgrade ng2 service to ng1', async(() => {
// Tokens used in ng2 to identify services
const Ng2Service = new OpaqueToken('ng2-service');
const Ng2Service = new InjectionToken('ng2-service');
// Sample ng1 NgModule for tests
@NgModule({
@ -49,7 +49,7 @@ export function main() {
it('should upgrade ng1 service to ng2', async(() => {
// Tokens used in ng2 to identify services
const Ng1Service = new OpaqueToken('ng1-service');
const Ng1Service = new InjectionToken('ng1-service');
// Sample ng1 NgModule for tests
@NgModule({

View File

@ -45,7 +45,7 @@ function routerFactory($q, $location, $browser, $rootScope, $injector, $routerRo
var exports = {
Injectable: function () {},
OpaqueToken: function () {},
InjectionToken: function () {},
Inject: function () {}
};
var routerRequire = function () {return exports;};

View File

@ -1,5 +1,5 @@
/** @stable */
export declare const APP_BASE_HREF: OpaqueToken;
export declare const APP_BASE_HREF: InjectionToken<string>;
/** @stable */
export declare class AsyncPipe implements OnDestroy {

View File

@ -19,7 +19,7 @@ export declare abstract class AfterViewInit {
}
/** @experimental */
export declare const ANALYZE_FOR_ENTRY_COMPONENTS: OpaqueToken;
export declare const ANALYZE_FOR_ENTRY_COMPONENTS: InjectionToken<any>;
/** @experimental */
export declare function animate(timing: string | number, styles?: AnimationStyleMetadata | AnimationKeyframesSequenceMetadata): AnimationAnimateMetadata;
@ -131,13 +131,13 @@ export declare abstract class AnimationWithStepsMetadata extends AnimationMetada
}
/** @experimental */
export declare const APP_BOOTSTRAP_LISTENER: OpaqueToken;
export declare const APP_BOOTSTRAP_LISTENER: InjectionToken<((compRef: ComponentRef<any>) => void)[]>;
/** @experimental */
export declare const APP_ID: any;
export declare const APP_ID: InjectionToken<string>;
/** @experimental */
export declare const APP_INITIALIZER: any;
export declare const APP_INITIALIZER: InjectionToken<(() => void)[]>;
/** @experimental */
export declare class ApplicationInitStatus {
@ -221,7 +221,12 @@ export declare class Compiler {
}
/** @experimental */
export declare const COMPILER_OPTIONS: OpaqueToken;
export declare const COMPILER_OPTIONS: InjectionToken<{
useDebug?: boolean;
useJit?: boolean;
defaultEncapsulation?: ViewEncapsulation;
providers?: any[];
}[]>;
/** @experimental */
export declare abstract class CompilerFactory {
@ -491,9 +496,16 @@ export interface InjectDecorator {
new (token: any): Inject;
}
/** @stable */
export declare class InjectionToken<T> extends OpaqueToken {
constructor(desc: string);
toString(): string;
}
/** @stable */
export declare abstract class Injector {
get(token: any, notFoundValue?: any): any;
get<T>(token: Type<T> | InjectionToken<T>, notFoundValue?: T): T;
/** @deprecated */ get(token: any, notFoundValue?: any): any;
static NULL: Injector;
static THROW_IF_NOT_FOUND: Object;
}
@ -586,7 +598,7 @@ export declare class KeyValueDiffers {
}
/** @experimental */
export declare const LOCALE_ID: OpaqueToken;
export declare const LOCALE_ID: InjectionToken<string>;
/** @experimental */
export declare class ModuleWithComponentFactories<T> {
@ -672,8 +684,9 @@ export declare abstract class OnInit {
abstract ngOnInit(): void;
}
/** @stable */
/** @deprecated */
export declare class OpaqueToken {
protected _desc: string;
constructor(_desc: string);
toString(): string;
}
@ -691,7 +704,7 @@ export interface OptionalDecorator {
export declare const Output: OutputDecorator;
/** @experimental */
export declare const PACKAGE_ROOT_URL: any;
export declare const PACKAGE_ROOT_URL: InjectionToken<string>;
/** @stable */
export declare const Pipe: PipeDecorator;
@ -702,7 +715,7 @@ export interface PipeTransform {
}
/** @experimental */
export declare const PLATFORM_INITIALIZER: any;
export declare const PLATFORM_INITIALIZER: InjectionToken<(() => void)[]>;
/** @experimental */
export declare const platformCore: (extraProviders?: Provider[]) => PlatformRef;
@ -946,10 +959,10 @@ export interface TrackByFn {
export declare function transition(stateChangeExpr: string | ((fromState: string, toState: string) => boolean), steps: AnimationMetadata | AnimationMetadata[]): AnimationStateTransitionMetadata;
/** @experimental */
export declare const TRANSLATIONS: OpaqueToken;
export declare const TRANSLATIONS: InjectionToken<string>;
/** @experimental */
export declare const TRANSLATIONS_FORMAT: OpaqueToken;
export declare const TRANSLATIONS_FORMAT: InjectionToken<string>;
/** @experimental */
export declare function trigger(name: string, animation: AnimationMetadata[]): AnimationEntryMetadata;

View File

@ -20,10 +20,10 @@ export declare class ComponentFixture<T> {
}
/** @experimental */
export declare const ComponentFixtureAutoDetect: OpaqueToken;
export declare const ComponentFixtureAutoDetect: InjectionToken<boolean[]>;
/** @experimental */
export declare const ComponentFixtureNoNgZone: OpaqueToken;
export declare const ComponentFixtureNoNgZone: InjectionToken<boolean[]>;
/** @experimental */
export declare function discardPeriodicTasks(): void;

View File

@ -355,13 +355,13 @@ export declare class MinLengthValidator implements Validator, OnChanges {
}
/** @stable */
export declare const NG_ASYNC_VALIDATORS: OpaqueToken;
export declare const NG_ASYNC_VALIDATORS: InjectionToken<(Function | Validator)[]>;
/** @stable */
export declare const NG_VALIDATORS: OpaqueToken;
export declare const NG_VALIDATORS: InjectionToken<(Function | Validator)[]>;
/** @stable */
export declare const NG_VALUE_ACCESSOR: OpaqueToken;
export declare const NG_VALUE_ACCESSOR: InjectionToken<ControlValueAccessor>;
/** @stable */
export declare abstract class NgControl extends AbstractControlDirective {

View File

@ -20,7 +20,7 @@ export declare class By {
export declare function disableDebugTools(): void;
/** @stable */
export declare const DOCUMENT: OpaqueToken;
export declare const DOCUMENT: InjectionToken<Document>;
/** @stable */
export declare abstract class DomSanitizer implements Sanitizer {
@ -36,7 +36,7 @@ export declare abstract class DomSanitizer implements Sanitizer {
export declare function enableDebugTools<T>(ref: ComponentRef<T>): ComponentRef<T>;
/** @stable */
export declare const EVENT_MANAGER_PLUGINS: OpaqueToken;
export declare const EVENT_MANAGER_PLUGINS: InjectionToken<EventManagerPlugin[]>;
/** @stable */
export declare class EventManager {
@ -47,7 +47,7 @@ export declare class EventManager {
}
/** @experimental */
export declare const HAMMER_GESTURE_CONFIG: OpaqueToken;
export declare const HAMMER_GESTURE_CONFIG: InjectionToken<HammerGestureConfig>;
/** @experimental */
export declare class HammerGestureConfig {

View File

@ -85,7 +85,7 @@ export declare const WORKER_APP_LOCATION_PROVIDERS: ({
provide: typeof PlatformLocation;
useClass: typeof WebWorkerPlatformLocation;
} | {
provide: any;
provide: InjectionToken<(() => void)[]>;
useFactory: (platformLocation: WebWorkerPlatformLocation, zone: NgZone) => () => Promise<boolean>;
multi: boolean;
deps: (typeof NgZone | typeof PlatformLocation)[];

View File

@ -223,10 +223,10 @@ export declare class Router {
}
/** @stable */
export declare const ROUTER_CONFIGURATION: OpaqueToken;
export declare const ROUTER_CONFIGURATION: InjectionToken<ExtraOptions>;
/** @experimental */
export declare const ROUTER_INITIALIZER: OpaqueToken;
export declare const ROUTER_INITIALIZER: InjectionToken<(compRef: ComponentRef<any>) => void>;
/** @experimental */
export declare abstract class RouteReuseStrategy {