mirror of
https://github.com/facebook/react.git
synced 2026-02-27 03:07:57 +00:00
Hermes parser is the preferred parser for Flow code going forward. We need to upgrade to this parser to support new Flow syntax like function `this` context type annotations or `ObjectType['prop']` syntax. Unfortunately, there's quite a few upgrades here to make it work somehow (dependencies between the changes) - ~Upgrade `eslint` to `8.*`~ reverted this as the React eslint plugin tests depend on the older version and there's a [yarn bug](https://github.com/yarnpkg/yarn/issues/6285) that prevents `devDependencies` and `peerDependencies` to different versions. - Remove `eslint-config-fbjs` preset dependency and inline the rules, imho this makes it a lot clearer what the rules are. - Remove the turned off `jsx-a11y/*` rules and it's dependency instead of inlining those from the `fbjs` config. - Update parser and dependency from `babel-eslint` to `hermes-eslint`. - `ft-flow/no-unused-expressions` rule replaces `no-unused-expressions` which now allows standalone type asserts, e.g. `(foo: number);` - Bunch of globals added to the eslint config - Disabled `no-redeclare`, seems like the eslint upgrade started making this more precise and warn against re-defined globals like `__EXPERIMENTAL__` (in rollup scripts) or `fetch` (when importing fetch from node-fetch). - Minor lint fixes like duplicate keys in objects.
148 lines
3.8 KiB
JavaScript
148 lines
3.8 KiB
JavaScript
/**
|
|
* Copyright (c) Meta Platforms, Inc. and 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 type {ReactContext} from 'shared/ReactTypes';
|
|
import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
|
|
|
|
import {enableCache} from 'shared/ReactFeatureFlags';
|
|
import {REACT_CONTEXT_TYPE} from 'shared/ReactSymbols';
|
|
|
|
import {pushProvider, popProvider} from './ReactFiberNewContext';
|
|
import * as Scheduler from 'scheduler';
|
|
|
|
// In environments without AbortController (e.g. tests)
|
|
// replace it with a lightweight shim that only has the features we use.
|
|
const AbortControllerLocal: typeof AbortController = enableCache
|
|
? typeof AbortController !== 'undefined'
|
|
? AbortController
|
|
: (function AbortControllerShim() {
|
|
const listeners = [];
|
|
const signal = (this.signal = {
|
|
aborted: false,
|
|
addEventListener: (type, listener) => {
|
|
listeners.push(listener);
|
|
},
|
|
});
|
|
|
|
this.abort = () => {
|
|
signal.aborted = true;
|
|
listeners.forEach(listener => listener());
|
|
};
|
|
}: AbortController)
|
|
: (null: any);
|
|
|
|
export type Cache = {
|
|
controller: AbortController,
|
|
data: Map<() => mixed, mixed>,
|
|
refCount: number,
|
|
};
|
|
|
|
export type CacheComponentState = {
|
|
+parent: Cache,
|
|
+cache: Cache,
|
|
};
|
|
|
|
export type SpawnedCachePool = {
|
|
+parent: Cache,
|
|
+pool: Cache,
|
|
};
|
|
|
|
// Intentionally not named imports because Rollup would
|
|
// use dynamic dispatch for CommonJS interop named imports.
|
|
const {
|
|
unstable_scheduleCallback: scheduleCallback,
|
|
unstable_NormalPriority: NormalPriority,
|
|
} = Scheduler;
|
|
|
|
export const CacheContext: ReactContext<Cache> = enableCache
|
|
? {
|
|
$$typeof: REACT_CONTEXT_TYPE,
|
|
// We don't use Consumer/Provider for Cache components. So we'll cheat.
|
|
Consumer: (null: any),
|
|
Provider: (null: any),
|
|
// We'll initialize these at the root.
|
|
_currentValue: (null: any),
|
|
_currentValue2: (null: any),
|
|
_threadCount: 0,
|
|
_defaultValue: (null: any),
|
|
_globalName: (null: any),
|
|
}
|
|
: (null: any);
|
|
|
|
if (__DEV__ && enableCache) {
|
|
CacheContext._currentRenderer = null;
|
|
CacheContext._currentRenderer2 = null;
|
|
}
|
|
|
|
// Creates a new empty Cache instance with a ref-count of 0. The caller is responsible
|
|
// for retaining the cache once it is in use (retainCache), and releasing the cache
|
|
// once it is no longer needed (releaseCache).
|
|
export function createCache(): Cache {
|
|
if (!enableCache) {
|
|
return (null: any);
|
|
}
|
|
const cache: Cache = {
|
|
controller: new AbortControllerLocal(),
|
|
data: new Map(),
|
|
refCount: 0,
|
|
};
|
|
|
|
return cache;
|
|
}
|
|
|
|
export function retainCache(cache: Cache) {
|
|
if (!enableCache) {
|
|
return;
|
|
}
|
|
if (__DEV__) {
|
|
if (cache.controller.signal.aborted) {
|
|
console.warn(
|
|
'A cache instance was retained after it was already freed. ' +
|
|
'This likely indicates a bug in React.',
|
|
);
|
|
}
|
|
}
|
|
cache.refCount++;
|
|
}
|
|
|
|
// Cleanup a cache instance, potentially freeing it if there are no more references
|
|
export function releaseCache(cache: Cache) {
|
|
if (!enableCache) {
|
|
return;
|
|
}
|
|
cache.refCount--;
|
|
if (__DEV__) {
|
|
if (cache.refCount < 0) {
|
|
console.warn(
|
|
'A cache instance was released after it was already freed. ' +
|
|
'This likely indicates a bug in React.',
|
|
);
|
|
}
|
|
}
|
|
if (cache.refCount === 0) {
|
|
scheduleCallback(NormalPriority, () => {
|
|
cache.controller.abort();
|
|
});
|
|
}
|
|
}
|
|
|
|
export function pushCacheProvider(workInProgress: Fiber, cache: Cache) {
|
|
if (!enableCache) {
|
|
return;
|
|
}
|
|
pushProvider(workInProgress, CacheContext, cache);
|
|
}
|
|
|
|
export function popCacheProvider(workInProgress: Fiber, cache: Cache) {
|
|
if (!enableCache) {
|
|
return;
|
|
}
|
|
popProvider(CacheContext, workInProgress);
|
|
}
|