Skip to content

Commit

Permalink
Merge branch 'main' into remove-feature-flag-enableStrictEffects
Browse files Browse the repository at this point in the history
  • Loading branch information
sammy-SC authored Oct 5, 2022
2 parents ce6a837 + 2872a26 commit 31e85c2
Show file tree
Hide file tree
Showing 215 changed files with 1,215 additions and 553 deletions.
4 changes: 2 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version: 2.1

aliases:
- &docker
- image: cimg/openjdk:17.0.0-node
- image: cimg/openjdk:18.0-node

- &environment
TZ: /usr/share/zoneinfo/America/Los_Angeles
Expand Down Expand Up @@ -121,7 +121,7 @@ jobs:
steps:
- checkout
- run:
name: Nodejs Version
name: NodeJS Version
command: node --version
- *restore_yarn_cache
- *restore_node_modules
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
"eslint-plugin-react-internal": "link:./scripts/eslint-rules",
"fbjs-scripts": "1.2.0",
"filesize": "^6.0.1",
"flow-bin": "^0.142.0",
"flow-bin": "^0.188.0",
"glob": "^7.1.6",
"glob-stream": "^6.1.0",
"google-closure-compiler": "^20200517.0.0",
Expand Down Expand Up @@ -100,7 +100,7 @@
"yargs": "^15.3.1"
},
"devEngines": {
"node": "^12.17.0 || 13.x || 14.x || 15.x || 16.x || 17.x"
"node": "^12.17.0 || 13.x || 14.x || 15.x || 16.x || 17.x || 18.x"
},
"jest": {
"testRegex": "/scripts/jest/dont-run-jest-directly\\.js$"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,6 @@ const tests = {
code: normalizeIndent`
// Valid because they're not matching use[A-Z].
fooState();
use();
_use();
_useState();
use_hook();
Expand Down Expand Up @@ -496,8 +495,6 @@ const tests = {
},
{
code: normalizeIndent`
Hook.use();
Hook._use();
Hook.useState();
Hook._useState();
Hook.use42();
Expand Down Expand Up @@ -1146,6 +1143,45 @@ if (__EXPERIMENTAL__) {
}
`,
},
{
code: normalizeIndent`
function App() {
const text = use(Promise.resolve('A'));
return <Text text={text} />
}
`,
},
{
code: normalizeIndent`
function App() {
if (shouldShowText) {
const text = use(query);
return <Text text={text} />
}
return <Text text={shouldFetchBackupText ? use(backupQuery) : "Nothing to see here"} />
}
`,
},
{
code: normalizeIndent`
function App() {
let data = [];
for (const query of queries) {
const text = use(item);
data.push(text);
}
return <Child data={data} />
}
`,
},
{
code: normalizeIndent`
function App() {
const data = someCallback((x) => use(x));
return <Child data={data} />
}
`,
},
];
tests.invalid = [
...tests.invalid,
Expand Down Expand Up @@ -1220,6 +1256,50 @@ if (__EXPERIMENTAL__) {
`,
errors: [useEventError('onClick')],
},
{
code: normalizeIndent`
Hook.use();
Hook._use();
Hook.useState();
Hook._useState();
Hook.use42();
Hook.useHook();
Hook.use_hook();
`,
errors: [
topLevelError('Hook.use'),
topLevelError('Hook.useState'),
topLevelError('Hook.use42'),
topLevelError('Hook.useHook'),
],
},
{
code: normalizeIndent`
function notAComponent() {
use(promise);
}
`,
errors: [functionError('use', 'notAComponent')],
},
{
code: normalizeIndent`
const text = use(promise);
function App() {
return <Text text={text} />
}
`,
errors: [topLevelError('use')],
},
{
code: normalizeIndent`
class C {
m() {
use(promise);
}
}
`,
errors: [classError('use')],
},
];
}

Expand Down
22 changes: 19 additions & 3 deletions packages/eslint-plugin-react-hooks/src/RulesOfHooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
*/

function isHookName(s) {
if (__EXPERIMENTAL__) {
return s === 'use' || /^use[A-Z0-9]/.test(s);
}
return /^use[A-Z0-9]/.test(s);
}

Expand Down Expand Up @@ -107,6 +110,13 @@ function isUseEventIdentifier(node) {
return false;
}

function isUseIdentifier(node) {
if (__EXPERIMENTAL__) {
return node.type === 'Identifier' && node.name === 'use';
}
return false;
}

export default {
meta: {
type: 'problem',
Expand Down Expand Up @@ -458,7 +468,8 @@ export default {

for (const hook of reactHooks) {
// Report an error if a hook may be called more then once.
if (cycled) {
// `use(...)` can be called in loops.
if (cycled && !isUseIdentifier(hook)) {
context.report({
node: hook,
message:
Expand All @@ -479,7 +490,11 @@ export default {
// path segments.
//
// Special case when we think there might be an early return.
if (!cycled && pathsFromStartToEnd !== allPathsFromStartToEnd) {
if (
!cycled &&
pathsFromStartToEnd !== allPathsFromStartToEnd &&
!isUseIdentifier(hook) // `use(...)` can be called conditionally.
) {
const message =
`React Hook "${context.getSource(hook)}" is called ` +
'conditionally. React Hooks must be called in the exact ' +
Expand Down Expand Up @@ -525,7 +540,8 @@ export default {
// anonymous function expressions. Hopefully this is clarifying
// enough in the common case that the incorrect message in
// uncommon cases doesn't matter.
if (isSomewhereInsideComponentOrHook) {
// `use(...)` can be called in callbacks.
if (isSomewhereInsideComponentOrHook && !isUseIdentifier(hook)) {
const message =
`React Hook "${context.getSource(hook)}" cannot be called ` +
'inside a callback. React Hooks must be called in a ' +
Expand Down
1 change: 1 addition & 0 deletions packages/jest-react/src/internalAct.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export function act<T>(scope: () => Thenable<T> | T): Thenable<T> {
if (
typeof result === 'object' &&
result !== null &&
// $FlowFixMe[method-unbinding]
typeof result.then === 'function'
) {
const thenableResult: Thenable<T> = (result: any);
Expand Down
2 changes: 1 addition & 1 deletion packages/react-cache/src/LRU.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export function createLRU<T>(limit: number): LRU<T> {
// Delete entries from the cache, starting from the end of the list.
if (first !== null) {
const resolvedFirst: Entry<T> = (first: any);
let last = resolvedFirst.previous;
let last: null | Entry<T> = resolvedFirst.previous;
while (size > targetSize && last !== null) {
const onDelete = last.onDelete;
const previous = last.previous;
Expand Down
4 changes: 3 additions & 1 deletion packages/react-cache/src/ReactCacheOld.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ import * as React from 'react';

import {createLRU} from './LRU';

type Suspender = {then(resolve: () => mixed, reject: () => mixed): mixed, ...};
interface Suspender {
then(resolve: () => mixed, reject: () => mixed): mixed;
}

type PendingResult = {
status: 0,
Expand Down
5 changes: 3 additions & 2 deletions packages/react-debug-tools/src/ReactDebugHooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ function useImperativeHandle<T>(
// and if there is a ref callback it might not store it but if it does we
// have no way of knowing where. So let's only enable introspection of the
// ref itself if it is using the object form.
let instance = undefined;
let instance: ?T = undefined;
if (ref !== null && typeof ref === 'object') {
instance = ref.current;
}
Expand Down Expand Up @@ -716,14 +716,15 @@ export function inspectHooks<Props>(
} finally {
readHookLog = hookLog;
hookLog = [];
// $FlowFixMe[incompatible-use] found when upgrading Flow
currentDispatcher.current = previousDispatcher;
}
const rootStack = ErrorStackParser.parse(ancestorStackError);
return buildTree(rootStack, readHookLog, includeHooksSource);
}

function setupContexts(contextMap: Map<ReactContext<any>, any>, fiber: Fiber) {
let current = fiber;
let current: null | Fiber = fiber;
while (current) {
if (current.tag === ContextProvider) {
const providerType: ReactProviderType<any> = current.type;
Expand Down
4 changes: 4 additions & 0 deletions packages/react-devtools-core/src/backend.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ export function connectToDevTools(options: ?ConnectOptions) {
}
},
);
// $FlowFixMe[incompatible-use] found when upgrading Flow
bridge.addListener(
'updateComponentFilters',
(componentFilters: Array<ComponentFilter>) => {
Expand All @@ -165,10 +166,12 @@ export function connectToDevTools(options: ?ConnectOptions) {
// Ideally the backend would save the filters itself, but RN doesn't provide a sync storage solution.
// So for now we just fall back to using the default filters...
if (window.__REACT_DEVTOOLS_COMPONENT_FILTERS__ == null) {
// $FlowFixMe[incompatible-use] found when upgrading Flow
bridge.send('overrideComponentFilters', savedComponentFilters);
}

// TODO (npm-packages) Warn if "isBackendStorageAPISupported"
// $FlowFixMe[incompatible-call] found when upgrading Flow
const agent = new Agent(bridge);
agent.addListener('shutdown', () => {
// If we received 'shutdown' from `agent`, we assume the `bridge` is already shutting down,
Expand All @@ -181,6 +184,7 @@ export function connectToDevTools(options: ?ConnectOptions) {
// Setup React Native style editor if the environment supports it.
if (resolveRNStyle != null || hook.resolveRNStyle != null) {
setupNativeStyleEditor(
// $FlowFixMe[incompatible-call] found when upgrading Flow
bridge,
agent,
((resolveRNStyle || hook.resolveRNStyle: any): ResolveNativeStyle),
Expand Down
2 changes: 2 additions & 0 deletions packages/react-devtools-core/src/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ export function launchEditor(
// There's an existing editor process already and it's attached
// to the terminal, so go kill it. Otherwise two separate editor
// instances attach to the stdin/stdout which gets confusing.
// $FlowFixMe[incompatible-use] found when upgrading Flow
childProcess.kill('SIGKILL');
}

Expand All @@ -186,6 +187,7 @@ export function launchEditor(
childProcess = spawn(editor, args, {stdio: 'inherit'});
}
childProcess.on('error', function() {});
// $FlowFixMe[incompatible-use] found when upgrading Flow
childProcess.on('exit', function(errorCode) {
childProcess = null;
});
Expand Down
9 changes: 6 additions & 3 deletions packages/react-devtools-core/src/standalone.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ function hookNamesModuleLoaderFunction() {
);
}

function setContentDOMNode(value: HTMLElement) {
function setContentDOMNode(value: HTMLElement): typeof DevtoolsUI {
node = value;

// Save so we can restore the exact waiting message between sessions.
Expand All @@ -70,12 +70,14 @@ function setProjectRoots(value: Array<string>) {
projectRoots = value;
}

function setStatusListener(value: StatusListener) {
function setStatusListener(value: StatusListener): typeof DevtoolsUI {
statusListener = value;
return DevtoolsUI;
}

function setDisconnectedCallback(value: OnDisconnectedCallback) {
function setDisconnectedCallback(
value: OnDisconnectedCallback,
): typeof DevtoolsUI {
disconnectedCallback = value;
return DevtoolsUI;
}
Expand Down Expand Up @@ -254,6 +256,7 @@ function initialize(socket: WebSocket) {
socket.close();
});

// $FlowFixMe[incompatible-call] found when upgrading Flow
store = new Store(bridge, {
checkBridgeProtocolCompatibility: true,
supportsNativeInspection: true,
Expand Down
1 change: 1 addition & 0 deletions packages/react-devtools-inline/src/backend.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export function activate(
bridge,
}: {
bridge?: BackendBridge,
// $FlowFixMe[incompatible-exact]
} = {},
): void {
if (bridge == null) {
Expand Down
1 change: 1 addition & 0 deletions packages/react-devtools-inline/src/frontend.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export function initialize(
}: {
bridge?: FrontendBridge,
store?: Store,
// $FlowFixMe[incompatible-exact]
} = {},
): React.AbstractComponent<Props, mixed> {
if (bridge == null) {
Expand Down
3 changes: 3 additions & 0 deletions packages/react-devtools-shared/src/PerformanceLoggingUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ import {__PERFORMANCE_PROFILE__} from './constants';

const supportsUserTiming =
typeof performance !== 'undefined' &&
// $FlowFixMe[method-unbinding]
typeof performance.mark === 'function' &&
// $FlowFixMe[method-unbinding]
typeof performance.clearMarks === 'function';

const supportsPerformanceNow =
// $FlowFixMe[method-unbinding]
typeof performance !== 'undefined' && typeof performance.now === 'function';

function mark(markName: string): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ export function describeNativeComponentFrame(
} catch (x) {
control = x;
}
// $FlowFixMe[prop-missing] found when upgrading Flow
fn.call(Fake.prototype);
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,10 @@ export function getStackByFiberInDevAndProd(
): string {
try {
let info = '';
let node = workInProgress;
let node: Fiber = workInProgress;
do {
info += describeFiber(workTagMap, node, currentDispatcherRef);
// $FlowFixMe[incompatible-type] we bail out when we get a null
node = node.return;
} while (node);
return info;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,6 @@ function measureStyle(
return;
}

// $FlowFixMe the parameter types of an unknown function are unknown
instance.measure((x, y, width, height, left, top) => {
// RN Android sometimes returns undefined here. Don't send measurements in this case.
// https://github.com/jhen0409/react-native-debugger/issues/84#issuecomment-304611817
Expand Down
Loading

0 comments on commit 31e85c2

Please sign in to comment.