
Closure compiler could not handle the spread operator in this one place. Working around it by removing the use of spread operator. PR Close #22884
114 lines
3.1 KiB
TypeScript
114 lines
3.1 KiB
TypeScript
/**
|
|
* @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 {NgModuleFactory, ɵisObservable as isObservable, ɵisPromise as isPromise} from '@angular/core';
|
|
import {Observable, from, of } from 'rxjs';
|
|
import {concatAll, every, last as lastValue, map, mergeAll} from 'rxjs/operators';
|
|
|
|
import {PRIMARY_OUTLET} from '../shared';
|
|
|
|
export function shallowEqualArrays(a: any[], b: any[]): boolean {
|
|
if (a.length !== b.length) return false;
|
|
for (let i = 0; i < a.length; ++i) {
|
|
if (!shallowEqual(a[i], b[i])) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
export function shallowEqual(a: {[x: string]: any}, b: {[x: string]: any}): boolean {
|
|
const k1 = Object.keys(a);
|
|
const k2 = Object.keys(b);
|
|
if (k1.length != k2.length) {
|
|
return false;
|
|
}
|
|
let key: string;
|
|
for (let i = 0; i < k1.length; i++) {
|
|
key = k1[i];
|
|
if (a[key] !== b[key]) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Flattens single-level nested arrays.
|
|
*/
|
|
export function flatten<T>(arr: T[][]): T[] {
|
|
return Array.prototype.concat.apply([], arr);
|
|
}
|
|
|
|
/**
|
|
* Return the last element of an array.
|
|
*/
|
|
export function last<T>(a: T[]): T|null {
|
|
return a.length > 0 ? a[a.length - 1] : null;
|
|
}
|
|
|
|
/**
|
|
* Verifys all booleans in an array are `true`.
|
|
*/
|
|
export function and(bools: boolean[]): boolean {
|
|
return !bools.some(v => !v);
|
|
}
|
|
|
|
export function forEach<K, V>(map: {[key: string]: V}, callback: (v: V, k: string) => void): void {
|
|
for (const prop in map) {
|
|
if (map.hasOwnProperty(prop)) {
|
|
callback(map[prop], prop);
|
|
}
|
|
}
|
|
}
|
|
|
|
export function waitForMap<A, B>(
|
|
obj: {[k: string]: A}, fn: (k: string, a: A) => Observable<B>): Observable<{[k: string]: B}> {
|
|
if (Object.keys(obj).length === 0) {
|
|
return of ({});
|
|
}
|
|
|
|
const waitHead: Observable<B>[] = [];
|
|
const waitTail: Observable<B>[] = [];
|
|
const res: {[k: string]: B} = {};
|
|
|
|
forEach(obj, (a: A, k: string) => {
|
|
const mapped = fn(k, a).pipe(map((r: B) => res[k] = r));
|
|
if (k === PRIMARY_OUTLET) {
|
|
waitHead.push(mapped);
|
|
} else {
|
|
waitTail.push(mapped);
|
|
}
|
|
});
|
|
|
|
// Closure compiler has problem with using spread operator here. So just using Array.concat.
|
|
return of .apply(null, waitHead.concat(waitTail)).pipe(concatAll(), lastValue(), map(() => res));
|
|
}
|
|
|
|
/**
|
|
* ANDs Observables by merging all input observables, reducing to an Observable verifying all
|
|
* input Observables return `true`.
|
|
*/
|
|
export function andObservables(observables: Observable<Observable<any>>): Observable<boolean> {
|
|
return observables.pipe(mergeAll(), every((result: any) => result === true));
|
|
}
|
|
|
|
export function wrapIntoObservable<T>(value: T | NgModuleFactory<T>| Promise<T>| Observable<T>):
|
|
Observable<T> {
|
|
if (isObservable(value)) {
|
|
return value;
|
|
}
|
|
|
|
if (isPromise(value)) {
|
|
// Use `Promise.resolve()` to wrap promise-like instances.
|
|
// Required ie when a Resolver returns a AngularJS `$q` promise to correctly trigger the
|
|
// change detection.
|
|
return from(Promise.resolve(value));
|
|
}
|
|
|
|
return of (value as T);
|
|
}
|