Skip to content

Commit

Permalink
Deprecate nonstandard Promise.prototype.done
Browse files Browse the repository at this point in the history
Summary:
Deprecates the nonstandard `Promise.prototype.done` method. This also removes one call site within React Native itself that relied on this method.

As part of this we are also removing React Native's custom Flow definition for `Promise` in favour of the standard one built into Flow. This will flag uses of `done` as type errors for anyone using the default app template's `.flowconfig`.

In a future release of React Native, we will remove the `done` method from the built-in `Promise` polyfill.

Changelog:
[General][Deprecated] - Deprecate the Promise.prototype.done method and log a warning when it's called in development.

Reviewed By: yungsters

Differential Revision: D34222667

fbshipit-source-id: 4b9708ac20c45b3966fdb93e883ab7f8d80017c1
  • Loading branch information
motiz88 authored and facebook-github-bot committed Feb 17, 2022
1 parent 062c1f7 commit 3580096
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 62 deletions.
32 changes: 32 additions & 0 deletions Libraries/Core/polyfillPromise.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
'use strict';

const {polyfillGlobal} = require('../Utilities/PolyfillFunctions');
const warnOnce = require('../Utilities/warnOnce');

/**
* Set up Promise. The native Promise implementation throws the following error:
Expand All @@ -36,3 +37,34 @@ if (global?.HermesInternal?.hasPromise?.()) {
} else {
polyfillGlobal('Promise', () => require('../Promise'));
}

if (__DEV__) {
// $FlowFixMe
const done = Promise.prototype.done;
if (done != null) {
let depth = 0;
/* eslint-disable no-extend-native */
// $FlowFixMe
Promise.prototype.done = function () {
++depth;
try {
// Avoid infinite recursion if done() happens to be triggered by warnOnce.
if (depth === 1) {
// Warn once per unique call stack. Not super efficient, but we're in
// __DEV__ and .done() calls are rare to begin with.
const key = new Error().stack;
warnOnce(
key,
'Promise.prototype.done(): This nonstandard polyfill ' +
'has been deprecated and will be removed in a future release. ' +
'Please instead use `.then()`.',
);
}
} finally {
--depth;
}
return done.apply(this, arguments);
};
/* eslint-enable no-extend-native */
}
}
11 changes: 0 additions & 11 deletions Libraries/Interaction/InteractionManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ const InteractionManager = {
onFulfill?: ?(void) => ?(Promise<U> | U),
onReject?: ?(error: mixed) => ?(Promise<U> | U),
) => Promise<U>,
done: () => void,
cancel: () => void,
...
} {
Expand All @@ -110,16 +109,6 @@ const InteractionManager = {
return {
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
then: promise.then.bind(promise),
done: (...args) => {
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
if (promise.done) {
return promise.done(...args);
} else {
console.warn(
'Tried to call done when not supported by current Promise implementation.',
);
}
},
cancel: function () {
_taskQueue.cancelTasks(tasks);
},
Expand Down
9 changes: 5 additions & 4 deletions Libraries/Interaction/TaskQueue.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,11 @@ class TaskQueue {
this.hasTasksToProcess() && this._onMoreTasks();
})
.catch(ex => {
ex.message = `TaskQueue: Error resolving Promise in task ${task.name}: ${ex.message}`;
throw ex;
})
.done();
setTimeout(() => {
ex.message = `TaskQueue: Error resolving Promise in task ${task.name}: ${ex.message}`;
throw ex;
}, 0);
});
}
}

Expand Down
47 changes: 0 additions & 47 deletions flow/Promise.js

This file was deleted.

0 comments on commit 3580096

Please sign in to comment.