diff --git a/modules/angular2/src/core/dom/browser_adapter.dart b/modules/angular2/src/core/dom/browser_adapter.dart index 6837a8cf6b..8a72785ac8 100644 --- a/modules/angular2/src/core/dom/browser_adapter.dart +++ b/modules/angular2/src/core/dom/browser_adapter.dart @@ -474,6 +474,10 @@ class BrowserDomAdapter extends GenericBrowserDomAdapter { cancelAnimationFrame(id) { window.cancelAnimationFrame(id); } + + num performanceNow() { + return window.performance.now(); + } } var baseElement = null; diff --git a/modules/angular2/src/core/dom/browser_adapter.ts b/modules/angular2/src/core/dom/browser_adapter.ts index c362ded848..e94b5fa6fc 100644 --- a/modules/angular2/src/core/dom/browser_adapter.ts +++ b/modules/angular2/src/core/dom/browser_adapter.ts @@ -1,5 +1,11 @@ import {MapWrapper, ListWrapper} from 'angular2/src/core/facade/collection'; -import {isBlank, isPresent, global, setValueOnPath} from 'angular2/src/core/facade/lang'; +import { + isBlank, + isPresent, + global, + setValueOnPath, + DateWrapper +} from 'angular2/src/core/facade/lang'; import {setRootDomAdapter} from './dom_adapter'; import {GenericBrowserDomAdapter} from './generic_browser_adapter'; @@ -322,6 +328,15 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter { setGlobalVar(path: string, value: any) { setValueOnPath(global, path, value); } requestAnimationFrame(callback): number { return window.requestAnimationFrame(callback); } cancelAnimationFrame(id: number) { window.cancelAnimationFrame(id); } + performanceNow(): number { + // performance.now() is not available in all browsers, see + // http://caniuse.com/#search=performance.now + if (isPresent(window.performance) && isPresent(window.performance.now)) { + return window.performance.now(); + } else { + return DateWrapper.toMillis(DateWrapper.now()); + } + } } diff --git a/modules/angular2/src/core/dom/dom_adapter.ts b/modules/angular2/src/core/dom/dom_adapter.ts index 26fa9040e2..4f9952d6e7 100644 --- a/modules/angular2/src/core/dom/dom_adapter.ts +++ b/modules/angular2/src/core/dom/dom_adapter.ts @@ -138,4 +138,5 @@ export class DomAdapter { setGlobalVar(name: string, value: any) { throw _abstract(); } requestAnimationFrame(callback): number { throw _abstract(); } cancelAnimationFrame(id) { throw _abstract(); } + performanceNow(): number { throw _abstract(); } } diff --git a/modules/angular2/src/core/dom/html_adapter.dart b/modules/angular2/src/core/dom/html_adapter.dart index e48c8df3c0..44176f6e06 100644 --- a/modules/angular2/src/core/dom/html_adapter.dart +++ b/modules/angular2/src/core/dom/html_adapter.dart @@ -431,4 +431,8 @@ class Html5LibDomAdapter implements DomAdapter { cancelAnimationFrame(id) { throw 'not implemented'; } + + performanceNow() { + throw 'not implemented'; + } } diff --git a/modules/angular2/src/core/dom/parse5_adapter.ts b/modules/angular2/src/core/dom/parse5_adapter.ts index 26faa53f18..31f2617d36 100644 --- a/modules/angular2/src/core/dom/parse5_adapter.ts +++ b/modules/angular2/src/core/dom/parse5_adapter.ts @@ -9,7 +9,13 @@ var url = require('url'); import {MapWrapper, ListWrapper, StringMapWrapper} from 'angular2/src/core/facade/collection'; import {DomAdapter, setRootDomAdapter} from './dom_adapter'; -import {isPresent, isBlank, global, setValueOnPath} from 'angular2/src/core/facade/lang'; +import { + isPresent, + isBlank, + global, + setValueOnPath, + DateWrapper +} from 'angular2/src/core/facade/lang'; import {BaseException, WrappedException} from 'angular2/src/core/facade/exceptions'; import {SelectorMatcher, CssSelector} from 'angular2/src/core/render/dom/compiler/selector'; @@ -545,6 +551,7 @@ export class Parse5DomAdapter extends DomAdapter { setGlobalVar(path: string, value: any) { setValueOnPath(global, path, value); } requestAnimationFrame(callback): number { return setTimeout(callback, 0); } cancelAnimationFrame(id: number) { clearTimeout(id); } + performanceNow(): number { return DateWrapper.toMillis(DateWrapper.now()); } } // TODO: build a proper list, this one is all the keys of a HTMLInputElement diff --git a/modules/angular2/src/tools/common_tools.ts b/modules/angular2/src/tools/common_tools.ts index 74a998fbbd..6fe9da98fe 100644 --- a/modules/angular2/src/tools/common_tools.ts +++ b/modules/angular2/src/tools/common_tools.ts @@ -1,6 +1,7 @@ import {ApplicationRef, LifeCycle} from 'angular2/angular2'; import {isPresent, NumberWrapper} from 'angular2/src/core/facade/lang'; import {performance, window} from 'angular2/src/core/facade/browser'; +import {DOM} from 'angular2/src/core/dom/dom_adapter'; /** * Entry point for all Angular debug tools. This object corresponds to the `ng` @@ -40,17 +41,19 @@ export class AngularProfiler { timeChangeDetection(config: any) { var record = isPresent(config) && config['record']; var profileName = 'Change Detection'; - if (record) { + // Profiler is not available in Android browsers, nor in IE 9 without dev tools opened + var isProfilerAvailable = isPresent(window.console.profile); + if (record && isProfilerAvailable) { window.console.profile(profileName); } - var start = window.performance.now(); + var start = DOM.performanceNow(); var numTicks = 0; - while (numTicks < 5 || (window.performance.now() - start) < 500) { + while (numTicks < 5 || (DOM.performanceNow() - start) < 500) { this.lifeCycle.tick(); numTicks++; } - var end = window.performance.now(); - if (record) { + var end = DOM.performanceNow(); + if (record && isProfilerAvailable) { // need to cast to because type checker thinks there's no argument // while in fact there is: //