mirror of
https://github.com/zebrajr/react.git
synced 2025-12-06 12:20:20 +01:00
This took a while, but I'm happy I went through it. Some key moments - recursively flushing effects, flushing microtasks on each async turn, and my team's uncompromising philosophy on code reuse. Really happy with this. I still want to expand test coverage, and I have some more small related todos, but this is good to land. On to the next one. Soundtrack to landing this - https://open.spotify.com/track/0MF8I8OUo8kytiOo8aSHYq?si=gSWqUheKQbiQDXzptCXHTg * hacked up act(async () => {...}) * move stuff around * merge changes * abstract .act warnings and stuff. all renderers. pass all tests. * move testutils.act back into testutils * move into scheduler, rename some bits * smaller bundle * a comment for why we don't do typeof === 'function' * fix test * pass tests - fire, prod * lose actContainerElement * tighter * write a test for TestRenderer it's an odd one, because not only does sync act not flush effects correctly, but the async one does (wut). verified it's fine with the dom version. * lint * rewrote to move flushing logic closer to the renderer the scheduler's `flushPassiveEffects` didn't work as expected for the test renderer, so I decided to go back to the hack (rendering a dumb container) This also makes reactdom not as heavy (by a few bytes, but still). * move it around so the delta isn't too bad * cleanups fix promise chaining propagate errors correctly test for thenable the 'right' way more tests! tidier! ponies! * Stray comment * recursively flush effects * fixed tests * lint, move noop.act into react-reconciler * microtasks when checking if called, s/called/calledLog, cleanup * pass fb lint we could have globally changed our eslint config to assume Promise is available, but that means we expect a promise polyfill on the page, and we don't yet. this code is triggered only in jest anyway, and we're fairly certain Promise will be available there. hence, the once-off disable for the check * shorter timers, fix a test, test for Promise * use global.Promise for existence check * flush microtasks * a version that works in browsers (that support postMessage) I also added a sanity fixture inside fixtures/dom/ mostly for me. * hoist flushEffectsAndMicroTasks * pull out tick logic from ReactFiberScheduler * fix await act (...sync) hanging - fix a hang when awaiting sync logic - a better async/await test for test renderer * feedback changes - use node's setImmediate if available - a warning if MessageChannel isn't available - rename some functions * pass lint/flow checks (without requiring a Promise polyfill/exclusion) * prettier the prettiest, even. * use globalPromise for the missed await warning * __DEV__ check for didWarnAboutMessageChannel * thenables and callbacks instead of promises, pass flow/lint * tinier. better. - pulled most bits out of FiberScheduler - actedUpdates uses callbacks now * pass build validation * augh prettier * golfing 7 more chars * Test that effects are not flushed without also flushing microtasks * export doesHavePendingPassiveEffects, nits * createAct() * dead code * missed in merge? * lose the preflushing bits * ugh prettier * removed `actedUpdates()`, created shared/actingUpdatesScopeDepth * rearrange imports so builds work, remove the hack versions of flushPassiveEffects * represent actingUpdatesScopeDepth as a tuple [number] * use a shared flag on React.__SECRET... * remove createAct, setup act for all relevant renderers * review feedback shared/enqueueTask import ReactSharedInternals from 'shared/ReactSharedInternals'; simpler act() internals ReactSharedInternals.ReactShouldWarnActingUpdates * move act() implementation into createReactNoop * warnIfNotCurrentlyActingUpdatesInDev condition check order
43 lines
1.4 KiB
JavaScript
43 lines
1.4 KiB
JavaScript
/**
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @flow
|
|
*/
|
|
|
|
import warningWithoutStack from './warningWithoutStack';
|
|
|
|
let didWarnAboutMessageChannel = false;
|
|
let enqueueTask;
|
|
try {
|
|
// assuming we're in node, let's try to get node's
|
|
// version of setImmediate, bypassing fake timers if any
|
|
let r = require; // trick packagers not to bundle this stuff.
|
|
enqueueTask = r('timers').setImmediate;
|
|
} catch (_err) {
|
|
// we're in a browser
|
|
// we can't use regular timers because they may still be faked
|
|
// so we try MessageChannel+postMessage instead
|
|
enqueueTask = function(callback: () => void) {
|
|
if (__DEV__) {
|
|
if (didWarnAboutMessageChannel === false) {
|
|
didWarnAboutMessageChannel = true;
|
|
warningWithoutStack(
|
|
typeof MessageChannel !== 'undefined',
|
|
'This browser does not have a MessageChannel implementation, ' +
|
|
'so enqueuing tasks via await act(async () => ...) will fail. ' +
|
|
'Please file an issue at https://github.com/facebook/react/issues ' +
|
|
'if you encounter this warning.',
|
|
);
|
|
}
|
|
}
|
|
const channel = new MessageChannel();
|
|
channel.port1.onmessage = callback;
|
|
channel.port2.postMessage(undefined);
|
|
};
|
|
}
|
|
|
|
export default enqueueTask;
|