diff --git a/.all-contributorsrc b/.all-contributorsrc
index cf2f3bdd..0a5aea46 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -1121,6 +1121,25 @@
"contributions": [
"doc"
]
+ },
+ {
+ "login": "kamranayub",
+ "name": "Kamran Ayub",
+ "avatar_url": "https://avatars1.githubusercontent.com/u/563819?v=4",
+ "profile": "http://kamranicus.com/",
+ "contributions": [
+ "code",
+ "test"
+ ]
+ },
+ {
+ "login": "MatanBobi",
+ "name": "Matan Borenkraout",
+ "avatar_url": "https://avatars2.githubusercontent.com/u/12711091?v=4",
+ "profile": "https://twitter.com/matanbobi",
+ "contributions": [
+ "code"
+ ]
}
],
"contributorsPerLine": 7,
diff --git a/.travis.yml b/.travis.yml
index ac04499f..c2f47b7a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,11 +8,14 @@ node_js:
- 12
- 14
- node
+env:
+ - REACT_NEXT=false
+ - REACT_NEXT=true
install:
- npm install
# as requested by the React team :)
# https://reactjs.org/blog/2019/10/22/react-release-channels.html#using-the-next-channel-for-integration-testing
- - if [ "$TRAVIS_EVENT_TYPE" = "cron" ]; then npm install react@next
+ - if [ "$REACT_NEXT" = true ]; then npm install react@next
react-dom@next; fi
script:
- npm run validate
@@ -23,6 +26,8 @@ branches:
- beta
jobs:
+ allow_failures:
+ - env: REACT_NEXT=true
include:
- stage: release
node_js: 14
diff --git a/README.md b/README.md
index d42f9c6d..f33fde6c 100644
--- a/README.md
+++ b/README.md
@@ -588,6 +588,8 @@ Thanks goes to these people ([emoji key][emojis]):
 Artem Zakharchenko 📖 |
 Michael 📖 |
 Braden Lee 📖 |
+  Kamran Ayub 💻 ⚠️ |
+  Matan Borenkraout 💻 |
diff --git a/package.json b/package.json
index 802a2e34..ea03d463 100644
--- a/package.json
+++ b/package.json
@@ -44,7 +44,8 @@
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.10.3",
- "@testing-library/dom": "^7.17.1"
+ "@testing-library/dom": "^7.17.1",
+ "semver": "^7.3.2"
},
"devDependencies": {
"@reach/router": "^1.3.3",
diff --git a/src/flush-microtasks.js b/src/flush-microtasks.js
index 2638da04..99b56ea5 100644
--- a/src/flush-microtasks.js
+++ b/src/flush-microtasks.js
@@ -1,3 +1,6 @@
+import React from 'react'
+import satisfies from 'semver/functions/satisfies'
+
/* istanbul ignore file */
// the part of this file that we need tested is definitely being run
// and the part that is not cannot easily have useful tests written
@@ -15,8 +18,15 @@ function getIsUsingFakeTimers() {
)
}
+const globalObj = typeof window === 'undefined' ? global : window
+let Scheduler = globalObj.Scheduler
+const isModernScheduleCallbackSupported = satisfies(React.version, '>16.8.6', {
+ includePrerelease: true,
+})
+
let didWarnAboutMessageChannel = false
let enqueueTask
+
try {
// read require off the module object to get around the bundlers.
// we don't want them to detect a require and bundle a Node polyfill.
@@ -25,6 +35,8 @@ try {
// assuming we're in node, let's try to get node's
// version of setImmediate, bypassing fake timers if any.
enqueueTask = nodeRequire.call(module, 'timers').setImmediate
+ // import React's scheduler so we'll be able to schedule our tasks later on.
+ Scheduler = nodeRequire.call(module, 'scheduler')
} catch (_err) {
// we're in a browser
// we can't use regular timers because they may still be faked
@@ -49,6 +61,20 @@ try {
}
}
+function scheduleCallback(cb) {
+ const NormalPriority = Scheduler
+ ? Scheduler.NormalPriority || Scheduler.unstable_NormalPriority
+ : null
+
+ const scheduleFn = Scheduler
+ ? Scheduler.scheduleCallback || Scheduler.unstable_scheduleCallback
+ : callback => callback()
+
+ return isModernScheduleCallbackSupported
+ ? scheduleFn(NormalPriority, cb)
+ : scheduleFn(cb)
+}
+
export default function flushMicroTasks() {
return {
then(resolve) {
@@ -59,7 +85,11 @@ export default function flushMicroTasks() {
jest.advanceTimersByTime(0)
resolve()
} else {
- enqueueTask(resolve)
+ scheduleCallback(() => {
+ enqueueTask(() => {
+ resolve()
+ })
+ })
}
},
}