mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-17 04:41:36 +08:00
Merge branch 'master' into feat/webpack5
This commit is contained in:
@ -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) {
|
export function test_setInterval_callbackShouldBeCleared(done) {
|
||||||
const start = TKUnit.time();
|
const start = TKUnit.time();
|
||||||
// >> timer-set-interval
|
// >> timer-set-interval
|
||||||
|
@ -20,7 +20,7 @@ export interface ApplicationEventData extends EventData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface LaunchEventData extends ApplicationEventData {
|
export interface LaunchEventData extends ApplicationEventData {
|
||||||
root?: View;
|
root?: View | null;
|
||||||
savedInstanceState?: any /* android.os.Bundle */;
|
savedInstanceState?: any /* android.os.Bundle */;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,7 +191,7 @@ export function addCss(cssText: string, attributeScoped?: boolean): void {
|
|||||||
const CALLBACKS = '_callbacks';
|
const CALLBACKS = '_callbacks';
|
||||||
|
|
||||||
export function _resetRootView(entry?: NavigationEntry | string): void {
|
export function _resetRootView(entry?: NavigationEntry | string): void {
|
||||||
const activity = androidApp.foregroundActivity;
|
const activity = androidApp.foregroundActivity || androidApp.startActivity;
|
||||||
if (!activity) {
|
if (!activity) {
|
||||||
throw new Error('Cannot find android activity.');
|
throw new Error('Cannot find android activity.');
|
||||||
}
|
}
|
||||||
|
3
packages/core/application/index.d.ts
vendored
3
packages/core/application/index.d.ts
vendored
@ -103,8 +103,9 @@ export interface LaunchEventData extends ApplicationEventData {
|
|||||||
/**
|
/**
|
||||||
* The root view for this Window on iOS or Activity for Android.
|
* 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 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 */;
|
savedInstanceState?: any /* android.os.Bundle */;
|
||||||
}
|
}
|
||||||
|
@ -207,7 +207,9 @@ export class iOSApplication implements iOSApplicationDefinition {
|
|||||||
|
|
||||||
// this._window will be undefined when NS app is embedded in a native one
|
// this._window will be undefined when NS app is embedded in a native one
|
||||||
if (this._window) {
|
if (this._window) {
|
||||||
this.setWindowContent(args.root);
|
if (args.root !== null) {
|
||||||
|
this.setWindowContent(args.root);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this._window = UIApplication.sharedApplication.delegate.window;
|
this._window = UIApplication.sharedApplication.delegate.window;
|
||||||
}
|
}
|
||||||
|
9
packages/core/data/observable/index.d.ts
vendored
9
packages/core/data/observable/index.d.ts
vendored
@ -12,6 +12,13 @@ export interface EventData {
|
|||||||
object: Observable;
|
object: Observable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface NotifyData extends Partial<EventData> {
|
||||||
|
eventName: string;
|
||||||
|
object?: Observable;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data for the "propertyChange" event.
|
* Data for the "propertyChange" event.
|
||||||
*/
|
*/
|
||||||
@ -136,7 +143,7 @@ export class Observable {
|
|||||||
* Notifies all the registered listeners for the event provided in the data.eventName.
|
* Notifies all the registered listeners for the event provided in the data.eventName.
|
||||||
* @param data The data associated with the event.
|
* @param data The data associated with the event.
|
||||||
*/
|
*/
|
||||||
notify<T extends EventData>(data: T): void;
|
notify<T extends NotifyData>(data: T): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies all the registered listeners for the property change event.
|
* Notifies all the registered listeners for the property change event.
|
||||||
|
@ -5,6 +5,11 @@ export interface EventData {
|
|||||||
object: Observable;
|
object: Observable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface NotifyData extends Partial<EventData> {
|
||||||
|
eventName: string;
|
||||||
|
object?: Observable;
|
||||||
|
}
|
||||||
|
|
||||||
export interface PropertyChangeData extends EventData {
|
export interface PropertyChangeData extends EventData {
|
||||||
propertyName: string;
|
propertyName: string;
|
||||||
value: any;
|
value: any;
|
||||||
@ -262,16 +267,18 @@ export class Observable implements ObservableDefinition {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public notify<T extends EventData>(data: T): void {
|
public notify<T extends NotifyData>(data: T): void {
|
||||||
|
const eventData = data as EventData;
|
||||||
|
eventData.object = eventData.object || this;
|
||||||
const eventClass = this.constructor.name;
|
const eventClass = this.constructor.name;
|
||||||
this._globalNotify(eventClass, 'First', data);
|
this._globalNotify(eventClass, 'First', eventData);
|
||||||
|
|
||||||
const observers = <Array<ListenerEntry>>this._observers[data.eventName];
|
const observers = <Array<ListenerEntry>>this._observers[data.eventName];
|
||||||
if (observers) {
|
if (observers) {
|
||||||
Observable._handleEvent(observers, data);
|
Observable._handleEvent(observers, eventData);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._globalNotify(eventClass, '', data);
|
this._globalNotify(eventClass, '', eventData);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static _handleEvent<T extends EventData>(observers: Array<ListenerEntry>, data: T): void {
|
private static _handleEvent<T extends EventData>(observers: Array<ListenerEntry>, data: T): void {
|
||||||
|
@ -58,12 +58,16 @@ export function setInterval(callback: Function, milliseconds = 0, ...args): numb
|
|||||||
const handler = timeoutHandler;
|
const handler = timeoutHandler;
|
||||||
const invoke = () => callback(...args);
|
const invoke = () => callback(...args);
|
||||||
const zoneBound = zonedCallback(invoke);
|
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({
|
const runnable = new java.lang.Runnable({
|
||||||
run: () => {
|
run: () => {
|
||||||
zoneBound();
|
zoneBound();
|
||||||
if (timeoutCallbacks[id]) {
|
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;
|
timeoutCallbacks[id] = runnable;
|
||||||
}
|
}
|
||||||
|
|
||||||
timeoutHandler.postDelayed(runnable, long(milliseconds));
|
timeoutHandler.postDelayed(runnable, long(nextCallMs()));
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -1301,13 +1301,19 @@ class ActivityCallbacksImplementation implements AndroidActivityCallbacks {
|
|||||||
if (!rootView) {
|
if (!rootView) {
|
||||||
const mainEntry = application.getMainEntry();
|
const mainEntry = application.getMainEntry();
|
||||||
const intent = activity.getIntent();
|
const intent = activity.getIntent();
|
||||||
|
// useful for integrations that would like to set rootView asynchronously after app launch
|
||||||
|
let shouldRootViewBeEmpty = false;
|
||||||
|
|
||||||
if (fireLaunchEvent) {
|
if (fireLaunchEvent) {
|
||||||
// entry point for Angular and Vue frameworks
|
// entry point for Angular and Vue frameworks
|
||||||
rootView = notifyLaunch(intent, <any>savedInstanceState, null);
|
rootView = notifyLaunch(intent, <any>savedInstanceState, null);
|
||||||
|
shouldRootViewBeEmpty = rootView === null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rootView) {
|
if (!rootView) {
|
||||||
|
if (shouldRootViewBeEmpty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// entry point for NS Core
|
// entry point for NS Core
|
||||||
if (!mainEntry) {
|
if (!mainEntry) {
|
||||||
// Also handles scenarios with Angular and Vue where the notifyLaunch didn't return a root view.
|
// Also handles scenarios with Angular and Vue where the notifyLaunch didn't return a root view.
|
||||||
|
Reference in New Issue
Block a user