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() + }) + }) } }, }