@@ -39,6 +39,7 @@ export {
3939
4040// Capture local references to native APIs, in case a polyfill overrides them.
4141const perf = window . performance ;
42+ const setTimeout = window . setTimeout ;
4243
4344// Use experimental Chrome Scheduler postTask API.
4445const scheduler = global . scheduler ;
@@ -112,7 +113,7 @@ export function unstable_scheduleCallback<T>(
112113 runTask . bind ( null , priorityLevel , postTaskPriority , node , callback ) ,
113114 postTaskOptions ,
114115 )
115- . catch ( handlePostTaskError ) ;
116+ . catch ( handleAbortError ) ;
116117
117118 return node ;
118119}
@@ -124,56 +125,49 @@ function runTask<T>(
124125 callback: SchedulerCallback< T > ,
125126) {
126127 deadline = getCurrentTime ( ) + yieldInterval ;
128+ let result ;
127129 try {
128130 currentPriorityLevel_DEPRECATED = priorityLevel ;
129131 const didTimeout_DEPRECATED = false ;
130- const result = callback ( didTimeout_DEPRECATED ) ;
131- if ( typeof result === 'function' ) {
132- // Assume this is a continuation
133- const continuation : SchedulerCallback < T > = (result: any);
134- const continuationController = new TaskController();
135- const continuationOptions = {
136- priority : postTaskPriority ,
137- signal : continuationController . signal ,
138- } ;
139- // Update the original callback node's controller, since even though we're
140- // posting a new task, conceptually it's the same one.
141- node._controller = continuationController;
142- scheduler
143- .postTask(
144- runTask.bind(
145- null,
146- priorityLevel,
147- postTaskPriority,
148- node,
149- continuation,
150- ),
151- continuationOptions,
152- )
153- .catch(handlePostTaskError);
154- }
132+ result = callback ( didTimeout_DEPRECATED ) ;
133+ } catch ( error ) {
134+ // We're inside a promise. If we don't handle this error, then it will
135+ // trigger an "Unhandled promise rejection" error. We don't want that, but
136+ // we do want the default error reporting behavior that normal (non-Promise)
137+ // tasks get for unhandled errors.
138+ //
139+ // So we'll re-throw the error inside a regular browser task.
140+ setTimeout ( ( ) => {
141+ throw error ;
142+ } ) ;
155143 } finally {
156144 currentPriorityLevel_DEPRECATED = NormalPriority ;
157145 }
146+ if ( typeof result === 'function' ) {
147+ // Assume this is a continuation
148+ const continuation : SchedulerCallback < T > = (result: any);
149+ const continuationController = new TaskController();
150+ const continuationOptions = {
151+ priority : postTaskPriority ,
152+ signal : continuationController . signal ,
153+ } ;
154+ // Update the original callback node's controller, since even though we're
155+ // posting a new task, conceptually it's the same one.
156+ node._controller = continuationController;
157+ scheduler
158+ .postTask(
159+ runTask.bind(null, priorityLevel, postTaskPriority, node, continuation),
160+ continuationOptions,
161+ )
162+ .catch(handleAbortError);
163+ }
158164}
159165
160- function handlePostTaskError ( error ) {
161- // This error is either a user error thrown by a callback, or an AbortError
162- // as a result of a cancellation.
163- //
164- // User errors trigger a global `error` event even if we don't rethrow them.
165- // In fact, if we do rethrow them, they'll get reported to the console twice.
166- // I'm not entirely sure the current `postTask` spec makes sense here. If I
167- // catch a `postTask` call, it shouldn't trigger a global error.
168- //
166+ function handleAbortError ( error ) {
169167 // Abort errors are an implementation detail. We don't expose the
170168 // TaskController to the user, nor do we expose the promise that is returned
171- // from `postTask`. So we shouldn't rethrow those, either, since there's no
172- // way to handle them. (If we did return the promise to the user, then it
173- // should be up to them to handle the AbortError.)
174- //
175- // In either case, we can suppress the error, barring changes to the spec
176- // or the Scheduler API.
169+ // from `postTask`. So we should suppress them, since there's no way for the
170+ // user to handle them.
177171}
178172
179173export function unstable_cancelCallback(node: CallbackNode) {
0 commit comments