Skip to content

Commit b5ad21f

Browse files
committed
Adding support to cancel a headless task
On UWP, when the app is executing a Background task, the OS can request it to cancel the task (for various reasons). If the app does not cancel its background task quickly, the OS might terminate the app. This change adds support to cancel the headless task which can be used by native code to forward the cancellation request from the OS to ths JS code.
1 parent fd30cf8 commit b5ad21f

File tree

1 file changed

+33
-6
lines changed

1 file changed

+33
-6
lines changed

Libraries/ReactNative/AppRegistry.js

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ const renderApplication = require('renderApplication');
2121

2222
type Task = (taskData: any) => Promise<void>;
2323
type TaskProvider = () => Task;
24+
type TaskCanceller = () => void;
25+
type TaskCancelProvider = () => TaskCanceller;
26+
2427
export type ComponentProvider = () => React$ComponentType<any>;
2528
export type ComponentProviderInstrumentationHook = (
2629
component: ComponentProvider,
@@ -47,7 +50,8 @@ export type WrapperComponentProvider = any => React$ComponentType<*>;
4750
const runnables: Runnables = {};
4851
let runCount = 1;
4952
const sections: Runnables = {};
50-
const tasks: Map<string, TaskProvider> = new Map();
53+
const taskProviders: Map<string, TaskProvider> = new Map();
54+
const taskCancelProviders: Map<string, TaskCancelProvider> = new Map();
5155
let componentProviderInstrumentationHook: ComponentProviderInstrumentationHook = (
5256
component: ComponentProvider,
5357
) => component();
@@ -209,13 +213,23 @@ const AppRegistry = {
209213
*
210214
* See http://facebook.github.io/react-native/docs/appregistry.html#registerheadlesstask
211215
*/
212-
registerHeadlessTask(taskKey: string, task: TaskProvider): void {
213-
if (tasks.has(taskKey)) {
216+
registerHeadlessTask(taskKey: string, taskProvider: TaskProvider): void {
217+
this.registerCancellableHeadlessTask(taskKey, taskProvider, () => () => { /* Cancel is no-op */ });
218+
},
219+
220+
/**
221+
* Register a cancellable headless task. A headless task is a bit of code that runs without a UI.
222+
*
223+
* See http://facebook.github.io/react-native/docs/appregistry.html#registercancellableheadlesstask
224+
*/
225+
registerCancellableHeadlessTask(taskKey: string, taskProvider: TaskProvider, taskCancelProvider: TaskCancelProvider): void {
226+
if (taskProviders.has(taskKey)) {
214227
console.warn(
215-
`registerHeadlessTask called multiple times for same key '${taskKey}'`,
228+
`registerHeadlessTask or registerCancellableHeadlessTask called multiple times for same key '${taskKey}'`,
216229
);
217230
}
218-
tasks.set(taskKey, task);
231+
taskProviders.set(taskKey, taskProvider);
232+
taskCancelProviders.set(taskKey, taskCancelProvider);
219233
},
220234

221235
/**
@@ -224,7 +238,7 @@ const AppRegistry = {
224238
* See http://facebook.github.io/react-native/docs/appregistry.html#startheadlesstask
225239
*/
226240
startHeadlessTask(taskId: number, taskKey: string, data: any): void {
227-
const taskProvider = tasks.get(taskKey);
241+
const taskProvider = taskProviders.get(taskKey);
228242
if (!taskProvider) {
229243
throw new Error(`No task registered for key ${taskKey}`);
230244
}
@@ -237,6 +251,19 @@ const AppRegistry = {
237251
NativeModules.HeadlessJsTaskSupport.notifyTaskFinished(taskId);
238252
});
239253
},
254+
255+
/**
256+
* Only called from native code. Cancels a headless task.
257+
*
258+
* See http://facebook.github.io/react-native/docs/appregistry.html#cancelheadlesstask
259+
*/
260+
cancelHeadlessTask(taskId: number, taskKey: string): void {
261+
const taskCancelProvider = taskCancelProviders.get(taskKey);
262+
if (!taskCancelProvider) {
263+
throw new Error(`No task canceller registered for key '${taskKey}'`);
264+
}
265+
taskCancelProvider()();
266+
},
240267
};
241268

242269
BatchedBridge.registerCallableModule('AppRegistry', AppRegistry);

0 commit comments

Comments
 (0)