diff --git a/Libraries/ReactNative/AppRegistry.js b/Libraries/ReactNative/AppRegistry.js index 4cae030d574420..71b17729ee7a01 100644 --- a/Libraries/ReactNative/AppRegistry.js +++ b/Libraries/ReactNative/AppRegistry.js @@ -21,6 +21,9 @@ const renderApplication = require('renderApplication'); type Task = (taskData: any) => Promise; type TaskProvider = () => Task; +type TaskCanceller = () => void; +type TaskCancelProvider = () => TaskCanceller; + /* $FlowFixMe(>=0.90.0 site=react_native_fb) This comment suppresses an * error found when Flow v0.90 was deployed. To see the error, delete this * comment and run Flow. */ @@ -50,7 +53,8 @@ export type WrapperComponentProvider = any => React$ComponentType<*>; const runnables: Runnables = {}; let runCount = 1; const sections: Runnables = {}; -const tasks: Map = new Map(); +const taskProviders: Map = new Map(); +const taskCancelProviders: Map = new Map(); let componentProviderInstrumentationHook: ComponentProviderInstrumentationHook = ( component: ComponentProvider, ) => component(); @@ -212,13 +216,23 @@ const AppRegistry = { * * See http://facebook.github.io/react-native/docs/appregistry.html#registerheadlesstask */ - registerHeadlessTask(taskKey: string, task: TaskProvider): void { - if (tasks.has(taskKey)) { + registerHeadlessTask(taskKey: string, taskProvider: TaskProvider): void { + this.registerCancellableHeadlessTask(taskKey, taskProvider, () => () => { /* Cancel is no-op */ }); + }, + + /** + * Register a cancellable headless task. A headless task is a bit of code that runs without a UI. + * + * See http://facebook.github.io/react-native/docs/appregistry.html#registercancellableheadlesstask + */ + registerCancellableHeadlessTask(taskKey: string, taskProvider: TaskProvider, taskCancelProvider: TaskCancelProvider): void { + if (taskProviders.has(taskKey)) { console.warn( - `registerHeadlessTask called multiple times for same key '${taskKey}'`, + `registerHeadlessTask or registerCancellableHeadlessTask called multiple times for same key '${taskKey}'`, ); } - tasks.set(taskKey, task); + taskProviders.set(taskKey, taskProvider); + taskCancelProviders.set(taskKey, taskCancelProvider); }, /** @@ -227,7 +241,7 @@ const AppRegistry = { * See http://facebook.github.io/react-native/docs/appregistry.html#startheadlesstask */ startHeadlessTask(taskId: number, taskKey: string, data: any): void { - const taskProvider = tasks.get(taskKey); + const taskProvider = taskProviders.get(taskKey); if (!taskProvider) { throw new Error(`No task registered for key ${taskKey}`); } @@ -240,6 +254,19 @@ const AppRegistry = { NativeModules.HeadlessJsTaskSupport.notifyTaskFinished(taskId); }); }, + + /** + * Only called from native code. Cancels a headless task. + * + * See http://facebook.github.io/react-native/docs/appregistry.html#cancelheadlesstask + */ + cancelHeadlessTask(taskId: number, taskKey: string): void { + const taskCancelProvider = taskCancelProviders.get(taskKey); + if (!taskCancelProvider) { + throw new Error(`No task canceller registered for key '${taskKey}'`); + } + taskCancelProvider()(); + } }; BatchedBridge.registerCallableModule('AppRegistry', AppRegistry);