import {HyperValue} from './core'; export let recordedHvStack: HyperValue[][] = []; export interface WatcherFn { (newValue: T, oldValue: T): void; } export type WatcherId = number; function hvRecordStart() { recordedHvStack.push([]); } function hvRecordStop(): HyperValue[] { const newList = recordedHvStack.pop(); return newList as HyperValue[]; } export function addToRecords(hv: HyperValue) { if (recordedHvStack.length <= 0) { return; } const currentList = recordedHvStack[recordedHvStack.length - 1]; if (currentList.indexOf(hv) === -1) { currentList.push(hv); } } export function record(fn: () => T): [T, HyperValue[]] { hvRecordStart(); const result = fn(); return [result, hvRecordStop()]; } export type PromiseWrapper = (p: Promise) => Promise; export function recordAsync( fn: (w: PromiseWrapper) => Promise, noNewDeps?: (deps: HyperValue[]) => void ): Promise<[T, HyperValue[]]> { return new Promise((resolve, reject) => { let deps = [] as HyperValue[]; function w(p: Promise): Promise { return new Promise((resolve, reject) => { const newDeps = hvRecordStop(); deps = deps.concat(newDeps); if (noNewDeps) { noNewDeps(newDeps); } p.then( value => { hvRecordStart(); resolve(value); }, error => { reject(error); } ); }); } hvRecordStart(); fn(w).then( value => { const newDeps = hvRecordStop(); const finalDeps = [...deps, ...newDeps]; if (noNewDeps) { noNewDeps(newDeps); } resolve([value, finalDeps]); }, error => { reject(error); } ); }); }