diff --git a/apps/automated/src/timer/timer-tests.ts b/apps/automated/src/timer/timer-tests.ts index 99c633828..4f8f10bbb 100644 --- a/apps/automated/src/timer/timer-tests.ts +++ b/apps/automated/src/timer/timer-tests.ts @@ -171,6 +171,40 @@ export function test_setInterval_callbackCalledWithExtraArgs(done) { ); } +export function test_setInterval_callbackNotDelayedByBusyWork() { + let calls = 0; + + let firstCall = true; + const id = timer.setInterval(() => { + calls++; + if (firstCall) { + firstCall = false; + TKUnit.wait(0.025); + } + }, 50); + + TKUnit.wait(0.11); + timer.clearInterval(id); + TKUnit.assertEqual(calls, 2, 'Callback should be called multiple times with busy wait'); +} + +export function test_setInterval_callbackSkippedByBusyWork() { + let calls = 0; + + let firstCall = true; + const id = timer.setInterval(() => { + calls++; + if (firstCall) { + firstCall = false; + TKUnit.wait(0.051); + } + }, 50); + + TKUnit.wait(0.16); + timer.clearInterval(id); + TKUnit.assertEqual(calls, 2, 'Callback should be called skipped when it takes too long to process'); +} + export function test_setInterval_callbackShouldBeCleared(done) { const start = TKUnit.time(); // >> timer-set-interval diff --git a/packages/core/application/application-interfaces.ts b/packages/core/application/application-interfaces.ts index 9427f68a4..13ea7fa5c 100644 --- a/packages/core/application/application-interfaces.ts +++ b/packages/core/application/application-interfaces.ts @@ -20,7 +20,7 @@ export interface ApplicationEventData extends EventData { } export interface LaunchEventData extends ApplicationEventData { - root?: View; + root?: View | null; savedInstanceState?: any /* android.os.Bundle */; } diff --git a/packages/core/application/index.android.ts b/packages/core/application/index.android.ts index c3dbacd38..50ce16597 100644 --- a/packages/core/application/index.android.ts +++ b/packages/core/application/index.android.ts @@ -191,7 +191,7 @@ export function addCss(cssText: string, attributeScoped?: boolean): void { const CALLBACKS = '_callbacks'; export function _resetRootView(entry?: NavigationEntry | string): void { - const activity = androidApp.foregroundActivity; + const activity = androidApp.foregroundActivity || androidApp.startActivity; if (!activity) { throw new Error('Cannot find android activity.'); } diff --git a/packages/core/application/index.d.ts b/packages/core/application/index.d.ts index 8688aebc5..d87a3a33d 100644 --- a/packages/core/application/index.d.ts +++ b/packages/core/application/index.d.ts @@ -103,8 +103,9 @@ export interface LaunchEventData extends ApplicationEventData { /** * The root view for this Window on iOS or Activity for Android. * If not set a new Frame will be created as a root view in order to maintain backwards compatibility. + * If explicitly set to null, there will be no root view. */ - root?: View; + root?: View | null; savedInstanceState?: any /* android.os.Bundle */; } diff --git a/packages/core/application/index.ios.ts b/packages/core/application/index.ios.ts index e502b4758..f36cafb70 100644 --- a/packages/core/application/index.ios.ts +++ b/packages/core/application/index.ios.ts @@ -207,7 +207,9 @@ export class iOSApplication implements iOSApplicationDefinition { // this._window will be undefined when NS app is embedded in a native one if (this._window) { - this.setWindowContent(args.root); + if (args.root !== null) { + this.setWindowContent(args.root); + } } else { this._window = UIApplication.sharedApplication.delegate.window; } diff --git a/packages/core/color/color-common.ts b/packages/core/color/color-common.ts index 8408838f3..f97a8a87b 100644 --- a/packages/core/color/color-common.ts +++ b/packages/core/color/color-common.ts @@ -1,4 +1,4 @@ -import * as definition from '.'; +import * as definition from '.'; import * as types from '../utils/types'; import * as knownColors from './known-colors'; import { convertHSLToRGBColor } from '../css/parser'; @@ -174,7 +174,7 @@ export class Color implements definition.Color { } /** - * return true if brightenss < 128 + * return true if brightness < 128 * */ public isDark() { @@ -182,7 +182,7 @@ export class Color implements definition.Color { } /** - * return true if brightenss >= 128 + * return true if brightness >= 128 * */ public isLight() { diff --git a/packages/core/timer/index.android.ts b/packages/core/timer/index.android.ts index 06d42d958..8bf793113 100644 --- a/packages/core/timer/index.android.ts +++ b/packages/core/timer/index.android.ts @@ -58,12 +58,16 @@ export function setInterval(callback: Function, milliseconds = 0, ...args): numb const handler = timeoutHandler; const invoke = () => callback(...args); const zoneBound = zonedCallback(invoke); + const startOffset = milliseconds > 0 ? Date.now() % milliseconds : 0; + function nextCallMs() { + return milliseconds > 0 ? milliseconds - ((Date.now() - startOffset) % milliseconds) : milliseconds; + } const runnable = new java.lang.Runnable({ run: () => { zoneBound(); if (timeoutCallbacks[id]) { - handler.postDelayed(runnable, long(milliseconds)); + handler.postDelayed(runnable, long(nextCallMs())); } }, }); @@ -72,7 +76,7 @@ export function setInterval(callback: Function, milliseconds = 0, ...args): numb timeoutCallbacks[id] = runnable; } - timeoutHandler.postDelayed(runnable, long(milliseconds)); + timeoutHandler.postDelayed(runnable, long(nextCallMs())); return id; } diff --git a/packages/core/ui/frame/index.android.ts b/packages/core/ui/frame/index.android.ts index dce7b556f..418fdd9bf 100644 --- a/packages/core/ui/frame/index.android.ts +++ b/packages/core/ui/frame/index.android.ts @@ -1305,13 +1305,19 @@ class ActivityCallbacksImplementation implements AndroidActivityCallbacks { if (!rootView) { const mainEntry = application.getMainEntry(); const intent = activity.getIntent(); + // useful for integrations that would like to set rootView asynchronously after app launch + let shouldRootViewBeEmpty = false; if (fireLaunchEvent) { // entry point for Angular and Vue frameworks rootView = notifyLaunch(intent, savedInstanceState, null); + shouldRootViewBeEmpty = rootView === null; } if (!rootView) { + if (shouldRootViewBeEmpty) { + return; + } // entry point for NS Core if (!mainEntry) { // Also handles scenarios with Angular and Vue where the notifyLaunch didn't return a root view.