diff --git a/integration/side-effects/snapshots/common/esm2015.js b/integration/side-effects/snapshots/common/esm2015.js index 05c0877c59..595d8ae0af 100644 --- a/integration/side-effects/snapshots/common/esm2015.js +++ b/integration/side-effects/snapshots/common/esm2015.js @@ -1,3 +1 @@ import "@angular/core"; - -import "rxjs"; diff --git a/integration/side-effects/snapshots/common/esm5.js b/integration/side-effects/snapshots/common/esm5.js index e7e3a29ff8..05d504f1d4 100644 --- a/integration/side-effects/snapshots/common/esm5.js +++ b/integration/side-effects/snapshots/common/esm5.js @@ -1,5 +1,3 @@ import "tslib"; import "@angular/core"; - -import "rxjs"; diff --git a/packages/common/src/pipes/async_pipe.ts b/packages/common/src/pipes/async_pipe.ts index 45337cbc73..40d565d2f1 100644 --- a/packages/common/src/pipes/async_pipe.ts +++ b/packages/common/src/pipes/async_pipe.ts @@ -6,8 +6,8 @@ * found in the LICENSE file at https://angular.io/license */ -import {ChangeDetectorRef, EventEmitter, OnDestroy, Pipe, PipeTransform, WrappedValue, ɵisPromise, ɵlooseIdentical} from '@angular/core'; -import {Observable, SubscriptionLike, isObservable} from 'rxjs'; +import {ChangeDetectorRef, EventEmitter, OnDestroy, Pipe, PipeTransform, WrappedValue, ɵisObservable, ɵisPromise, ɵlooseIdentical} from '@angular/core'; +import {Observable, SubscriptionLike} from 'rxjs'; import {invalidPipeArgumentError} from './invalid_pipe_argument_error'; interface SubscriptionStrategy { @@ -122,7 +122,7 @@ export class AsyncPipe implements OnDestroy, PipeTransform { return _promiseStrategy; } - if (isObservable(obj)) { + if (ɵisObservable(obj)) { return _observableStrategy; } diff --git a/packages/core/src/core_private_export.ts b/packages/core/src/core_private_export.ts index 99807e1a7c..fab88f1b34 100644 --- a/packages/core/src/core_private_export.ts +++ b/packages/core/src/core_private_export.ts @@ -30,7 +30,7 @@ export {global as ɵglobal} from './util/global'; export {looseIdentical as ɵlooseIdentical,} from './util/comparison'; export {stringify as ɵstringify} from './util/stringify'; export {makeDecorator as ɵmakeDecorator} from './util/decorators'; -export {isPromise as ɵisPromise} from './util/lang'; +export {isObservable as ɵisObservable, isPromise as ɵisPromise} from './util/lang'; export {clearOverrides as ɵclearOverrides, initServicesIfNeeded as ɵinitServicesIfNeeded, overrideComponentView as ɵoverrideComponentView, overrideProvider as ɵoverrideProvider} from './view/index'; export {NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR as ɵNOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR} from './view/provider'; export {LocaleDataIndex as ɵLocaleDataIndex, CurrencyIndex as ɵCurrencyIndex, ExtraLocaleDataIndex as ɵExtraLocaleDataIndex, getLocalePluralCase as ɵgetLocalePluralCase, findLocaleData as ɵfindLocaleData, registerLocaleData as ɵregisterLocaleData, unregisterAllLocaleData as ɵunregisterLocaleData} from './i18n/locale_data_api'; diff --git a/packages/core/src/render3/instructions/listener.ts b/packages/core/src/render3/instructions/listener.ts index 0c8d871647..37bc71bd8d 100644 --- a/packages/core/src/render3/instructions/listener.ts +++ b/packages/core/src/render3/instructions/listener.ts @@ -6,8 +6,9 @@ * found in the LICENSE file at https://angular.io/license */ -import {isObservable} from 'rxjs'; + import {assertDataInRange} from '../../util/assert'; +import {isObservable} from '../../util/lang'; import {EMPTY_OBJ} from '../empty'; import {PropertyAliasValue, TNode, TNodeFlags, TNodeType} from '../interfaces/node'; import {GlobalTargetResolver, RElement, Renderer3, isProceduralRenderer} from '../interfaces/renderer'; diff --git a/packages/core/src/util/BUILD.bazel b/packages/core/src/util/BUILD.bazel index 0862fc5a20..3ea2b343c1 100644 --- a/packages/core/src/util/BUILD.bazel +++ b/packages/core/src/util/BUILD.bazel @@ -15,5 +15,6 @@ ts_library( deps = [ "//packages:types", "//packages/core/src/interface", + "@npm//rxjs", ], ) diff --git a/packages/core/src/util/lang.ts b/packages/core/src/util/lang.ts index 6cf4316a83..b6631e84d0 100644 --- a/packages/core/src/util/lang.ts +++ b/packages/core/src/util/lang.ts @@ -6,6 +6,8 @@ * found in the LICENSE file at https://angular.io/license */ +import {Observable} from 'rxjs'; + /** * Determine if the argument is shaped like a Promise */ @@ -14,3 +16,12 @@ export function isPromise(obj: any): obj is Promise { // It's up to the caller to ensure that obj.then conforms to the spec return !!obj && typeof obj.then === 'function'; } + +/** + * Determine if the argument is an Observable + */ +export function isObservable(obj: any | Observable): obj is Observable { + // TODO: use isObservable once we update pass rxjs 6.1 + // https://github.com/ReactiveX/rxjs/blob/master/CHANGELOG.md#610-2018-05-03 + return !!obj && typeof obj.subscribe === 'function'; +} diff --git a/packages/core/src/view/provider.ts b/packages/core/src/view/provider.ts index 2c10555612..f8421a03bc 100644 --- a/packages/core/src/view/provider.ts +++ b/packages/core/src/view/provider.ts @@ -6,13 +6,13 @@ * found in the LICENSE file at https://angular.io/license */ -import {isObservable} from 'rxjs'; import {ChangeDetectorRef, SimpleChange, SimpleChanges, WrappedValue} from '../change_detection/change_detection'; import {INJECTOR, Injector, resolveForwardRef} from '../di'; import {ElementRef} from '../linker/element_ref'; import {TemplateRef} from '../linker/template_ref'; import {ViewContainerRef} from '../linker/view_container_ref'; import {Renderer2} from '../render/api'; +import {isObservable} from '../util/lang'; import {stringify} from '../util/stringify'; import {createChangeDetectorRef, createInjector} from './refs'; diff --git a/packages/core/test/util/lang_spec.ts b/packages/core/test/util/lang_spec.ts index 19aade5c38..73086b09cf 100644 --- a/packages/core/test/util/lang_spec.ts +++ b/packages/core/test/util/lang_spec.ts @@ -5,7 +5,8 @@ * 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 {isPromise} from '@angular/core/src/util/lang'; +import {isObservable, isPromise} from '@angular/core/src/util/lang'; +import {of } from 'rxjs'; { describe('isPromise', () => { @@ -25,4 +26,22 @@ import {isPromise} from '@angular/core/src/util/lang'; expect(isPromise(null)).toEqual(false); }); }); + + describe('isObservable', () => { + it('should be true for an Observable', () => expect(isObservable(of (true))).toEqual(true)); + + it('should be true if the argument is the object with subscribe function', + () => expect(isObservable({subscribe: () => {}})).toEqual(true)); + + it('should be false if the argument is undefined', + () => expect(isObservable(undefined)).toEqual(false)); + + it('should be false if the argument is null', () => expect(isObservable(null)).toEqual(false)); + + it('should be false if the argument is an object', + () => expect(isObservable({})).toEqual(false)); + + it('should be false if the argument is a function', + () => expect(isObservable(() => {})).toEqual(false)); + }); } diff --git a/packages/core/test/view/BUILD.bazel b/packages/core/test/view/BUILD.bazel index ca16bb9be6..481f1bcdf1 100644 --- a/packages/core/test/view/BUILD.bazel +++ b/packages/core/test/view/BUILD.bazel @@ -17,7 +17,6 @@ ts_library( "//packages/core/testing", "//packages/platform-browser", "//packages/private/testing", - "@npm//rxjs", ], ) diff --git a/packages/core/test/view/provider_spec.ts b/packages/core/test/view/provider_spec.ts index 9a61e4051e..cab5b26bc8 100644 --- a/packages/core/test/view/provider_spec.ts +++ b/packages/core/test/view/provider_spec.ts @@ -6,7 +6,6 @@ * found in the LICENSE file at https://angular.io/license */ -import {Observable} from 'rxjs'; import {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, ChangeDetectorRef, DoCheck, ElementRef, ErrorHandler, EventEmitter, Injector, OnChanges, OnDestroy, OnInit, Renderer2, SimpleChange, TemplateRef, ViewContainerRef,} from '@angular/core'; import {getDebugContext} from '@angular/core/src/errors'; import {ArgumentType, DepFlags, NodeFlags, Services, anchorDef, asElementData, directiveDef, elementDef, providerDef, textDef} from '@angular/core/src/view/index'; @@ -342,11 +341,13 @@ import {ARG_TYPE_VALUES, checkNodeInlineOrDynamic, createRootView, createAndGetR let unsubscribeSpy: any; class SomeService { - emitter = new Observable((callback: any) => { - const subscription = emitter.subscribe(callback); - unsubscribeSpy = spyOn(subscription, 'unsubscribe').and.callThrough(); - return subscription; - }); + emitter = { + subscribe: (callback: any) => { + const subscription = emitter.subscribe(callback); + unsubscribeSpy = spyOn(subscription, 'unsubscribe').and.callThrough(); + return subscription; + } + }; } const handleEvent = jasmine.createSpy('handleEvent'); diff --git a/packages/forms/src/validators.ts b/packages/forms/src/validators.ts index 0806954b61..116d306e86 100644 --- a/packages/forms/src/validators.ts +++ b/packages/forms/src/validators.ts @@ -6,8 +6,8 @@ * found in the LICENSE file at https://angular.io/license */ -import {InjectionToken, ɵisPromise as isPromise} from '@angular/core'; -import {Observable, forkJoin, from, isObservable} from 'rxjs'; +import {InjectionToken, ɵisObservable as isObservable, ɵisPromise as isPromise} from '@angular/core'; +import {Observable, forkJoin, from} from 'rxjs'; import {map} from 'rxjs/operators'; import {AsyncValidatorFn, ValidationErrors, Validator, ValidatorFn} from './directives/validators'; import {AbstractControl, FormControl} from './model'; diff --git a/packages/router/src/utils/collection.ts b/packages/router/src/utils/collection.ts index 95af5c1390..74fbc81420 100644 --- a/packages/router/src/utils/collection.ts +++ b/packages/router/src/utils/collection.ts @@ -6,8 +6,8 @@ * found in the LICENSE file at https://angular.io/license */ -import {NgModuleFactory, ɵisPromise as isPromise} from '@angular/core'; -import {Observable, from, isObservable, of } from 'rxjs'; +import {NgModuleFactory, ɵisObservable as isObservable, ɵisPromise as isPromise} from '@angular/core'; +import {Observable, from, of } from 'rxjs'; import {concatAll, last as lastValue, map} from 'rxjs/operators'; import {PRIMARY_OUTLET, Params} from '../shared';