Skip to content

Commit

Permalink
Migrate large amount of modules to flow strict and strict-local
Browse files Browse the repository at this point in the history
Summary:
| Group | Before | After | Change |
| Untyped | 50 | 49 | -1 |
| flow | 197 | 155 | -42 |
| flow strict-local | 226 | 185 | -41 |
| flow strict | 33 | 117 | +84

Changelog: [Changed] Improved Flow typing of multiple modules (with migrations to `flow strict` and `flow strict-local`

Reviewed By: motiz88

Differential Revision: D22549140

fbshipit-source-id: ed29415332cfce15b244ee4dea9e13d035543175
  • Loading branch information
rubennorte authored and facebook-github-bot committed Jul 22, 2020
1 parent 050a7dd commit 4409642
Show file tree
Hide file tree
Showing 105 changed files with 461 additions and 271 deletions.
2 changes: 1 addition & 1 deletion Libraries/BatchedBridge/BatchedBridge.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow strict-local
* @flow strict
*/

'use strict';
Expand Down
120 changes: 64 additions & 56 deletions Libraries/BatchedBridge/MessageQueue.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
* @flow strict
* @format
*/

Expand All @@ -22,7 +22,7 @@ export type SpyData = {
type: number,
module: ?string,
method: string | number,
args: any[],
args: mixed[],
...
};

Expand All @@ -40,10 +40,10 @@ const TRACE_TAG_REACT_APPS = 1 << 17;
const DEBUG_INFO_LIMIT = 32;

class MessageQueue {
_lazyCallableModules: {[key: string]: (void) => Object, ...};
_queue: [number[], number[], any[], number];
_successCallbacks: Map<number, ?Function>;
_failureCallbacks: Map<number, ?Function>;
_lazyCallableModules: {[key: string]: (void) => {...}, ...};
_queue: [number[], number[], mixed[], number];
_successCallbacks: Map<number, ?(...mixed[]) => void>;
_failureCallbacks: Map<number, ?(...mixed[]) => void>;
_callID: number;
_lastFlush: number;
_eventLoopStartTime: number;
Expand Down Expand Up @@ -71,11 +71,15 @@ class MessageQueue {
this._remoteMethodTable = {};
}

(this: any).callFunctionReturnFlushedQueue = this.callFunctionReturnFlushedQueue.bind(
// $FlowFixMe[cannot-write]
this.callFunctionReturnFlushedQueue = this.callFunctionReturnFlushedQueue.bind(
this,
);
(this: any).flushedQueue = this.flushedQueue.bind(this);
(this: any).invokeCallbackAndReturnFlushedQueue = this.invokeCallbackAndReturnFlushedQueue.bind(
// $FlowFixMe[cannot-write]
this.flushedQueue = this.flushedQueue.bind(this);

// $FlowFixMe[cannot-write]
this.invokeCallbackAndReturnFlushedQueue = this.invokeCallbackAndReturnFlushedQueue.bind(
this,
);
}
Expand All @@ -89,7 +93,7 @@ class MessageQueue {
MessageQueue.prototype.__spy = info => {
console.log(
`${info.type === TO_JS ? 'N->JS' : 'JS->N'} : ` +
`${info.module ? info.module + '.' : ''}${info.method}` +
`${info.module != null ? info.module + '.' : ''}${info.method}` +
`(${JSON.stringify(info.args)})`,
);
};
Expand All @@ -103,8 +107,8 @@ class MessageQueue {
callFunctionReturnFlushedQueue(
module: string,
method: string,
args: any[],
): null | [Array<number>, Array<number>, Array<any>, number] {
args: mixed[],
): null | [Array<number>, Array<number>, Array<mixed>, number] {
this.__guard(() => {
this.__callFunction(module, method, args);
});
Expand All @@ -114,16 +118,16 @@ class MessageQueue {

invokeCallbackAndReturnFlushedQueue(
cbID: number,
args: any[],
): null | [Array<number>, Array<number>, Array<any>, number] {
args: mixed[],
): null | [Array<number>, Array<number>, Array<mixed>, number] {
this.__guard(() => {
this.__invokeCallback(cbID, args);
});

return this.flushedQueue();
}

flushedQueue(): null | [Array<number>, Array<number>, Array<any>, number] {
flushedQueue(): null | [Array<number>, Array<number>, Array<mixed>, number] {
this.__guard(() => {
this.__callImmediates();
});
Expand All @@ -137,13 +141,13 @@ class MessageQueue {
return Date.now() - this._eventLoopStartTime;
}

registerCallableModule(name: string, module: Object) {
registerCallableModule(name: string, module: {...}) {
this._lazyCallableModules[name] = () => module;
}

registerLazyCallableModule(name: string, factory: void => Object) {
let module: Object;
let getValue: ?(void) => Object = factory;
registerLazyCallableModule(name: string, factory: void => {...}) {
let module: {...};
let getValue: ?(void) => {...} = factory;
this._lazyCallableModules[name] = () => {
if (getValue) {
module = getValue();
Expand All @@ -153,18 +157,18 @@ class MessageQueue {
};
}

getCallableModule(name: string): any | null {
getCallableModule(name: string): {...} | null {
const getValue = this._lazyCallableModules[name];
return getValue ? getValue() : null;
}

callNativeSyncHook(
moduleID: number,
methodID: number,
params: any[],
onFail: ?Function,
onSucc: ?Function,
): any {
params: mixed[],
onFail: ?(...mixed[]) => void,
onSucc: ?(...mixed[]) => void,
): mixed {
if (__DEV__) {
invariant(
global.nativeCallSyncHook,
Expand All @@ -181,10 +185,10 @@ class MessageQueue {
processCallbacks(
moduleID: number,
methodID: number,
params: any[],
onFail: ?Function,
onSucc: ?Function,
) {
params: mixed[],
onFail: ?(...mixed[]) => void,
onSucc: ?(...mixed[]) => void,
): void {
if (onFail || onSucc) {
if (__DEV__) {
this._debugInfo[this._callID] = [moduleID, methodID];
Expand Down Expand Up @@ -232,9 +236,9 @@ class MessageQueue {
enqueueNativeCall(
moduleID: number,
methodID: number,
params: any[],
onFail: ?Function,
onSucc: ?Function,
params: mixed[],
onFail: ?(...mixed[]) => void,
onSucc: ?(...mixed[]) => void,
) {
this.processCallbacks(moduleID, methodID, params, onFail, onSucc);

Expand All @@ -247,30 +251,34 @@ class MessageQueue {
// function it is permitted here, and special-cased in the
// conversion.
const isValidArgument = val => {
const t = typeof val;
if (
t === 'undefined' ||
t === 'null' ||
t === 'boolean' ||
t === 'string'
) {
return true;
}
if (t === 'number') {
return isFinite(val);
}
if (t === 'function' || t !== 'object') {
return false;
}
if (Array.isArray(val)) {
return val.every(isValidArgument);
}
for (const k in val) {
if (typeof val[k] !== 'function' && !isValidArgument(val[k])) {
switch (typeof val) {
case 'undefined':
case 'boolean':
case 'string':
return true;
case 'number':
return isFinite(val);
case 'object':
if (val == null) {
return true;
}

if (Array.isArray(val)) {
return val.every(isValidArgument);
}

for (const k in val) {
if (typeof val[k] !== 'function' && !isValidArgument(val[k])) {
return false;
}
}

return true;
case 'function':
return false;
default:
return false;
}
}
return true;
};

// Replacement allows normally non-JSON-convertible values to be
Expand All @@ -295,7 +303,7 @@ class MessageQueue {
);

// The params object should not be mutated after being queued
deepFreezeAndThrowOnMutationInDev((params: any));
deepFreezeAndThrowOnMutationInDev(params);
}
this._queue[PARAMS].push(params);

Expand Down Expand Up @@ -382,7 +390,7 @@ class MessageQueue {
Systrace.endEvent();
}

__callFunction(module: string, method: string, args: any[]): void {
__callFunction(module: string, method: string, args: mixed[]): void {
this._lastFlush = Date.now();
this._eventLoopStartTime = this._lastFlush;
if (__DEV__ || this.__spy) {
Expand Down Expand Up @@ -410,7 +418,7 @@ class MessageQueue {
Systrace.endEvent();
}

__invokeCallback(cbID: number, args: any[]) {
__invokeCallback(cbID: number, args: mixed[]) {
this._lastFlush = Date.now();
this._eventLoopStartTime = this._lastFlush;

Expand Down
38 changes: 23 additions & 15 deletions Libraries/BatchedBridge/NativeModules.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow
* @flow strict
*/

'use strict';
Expand All @@ -18,7 +18,7 @@ import type {ExtendedError} from '../Core/Devtools/parseErrorStack';

export type ModuleConfig = [
string /* name */,
?Object /* constants */,
?{...} /* constants */,
?$ReadOnlyArray<string> /* functions */,
?$ReadOnlyArray<number> /* promise method IDs */,
?$ReadOnlyArray<number> /* sync method IDs */,
Expand All @@ -31,7 +31,7 @@ function genModule(
moduleID: number,
): ?{
name: string,
module?: Object,
module?: {...},
...
} {
if (!config) {
Expand All @@ -55,8 +55,9 @@ function genModule(
methods &&
methods.forEach((methodName, methodID) => {
const isPromise =
promiseMethods && arrayContains(promiseMethods, methodID);
const isSync = syncMethods && arrayContains(syncMethods, methodID);
(promiseMethods && arrayContains(promiseMethods, methodID)) || false;
const isSync =
(syncMethods && arrayContains(syncMethods, methodID)) || false;
invariant(
!isPromise || !isSync,
'Cannot have a method that is both async and a sync hook',
Expand Down Expand Up @@ -85,7 +86,7 @@ function genModule(
// export this method as a global so we can call it from native
global.__fbGenNativeModule = genModule;

function loadModule(name: string, moduleID: number): ?Object {
function loadModule(name: string, moduleID: number): ?{...} {
invariant(
global.nativeRequireModuleConfig,
"Can't lazily create module without nativeRequireModuleConfig",
Expand All @@ -98,7 +99,7 @@ function loadModule(name: string, moduleID: number): ?Object {
function genMethod(moduleID: number, methodID: number, type: MethodType) {
let fn = null;
if (type === 'promise') {
fn = function promiseMethodWrapper(...args: Array<any>) {
fn = function promiseMethodWrapper(...args: Array<mixed>) {
// In case we reject, capture a useful stack trace here.
const enqueueingFrameError: ExtendedError = new Error();
return new Promise((resolve, reject) => {
Expand All @@ -108,12 +109,17 @@ function genMethod(moduleID: number, methodID: number, type: MethodType) {
args,
data => resolve(data),
errorData =>
reject(updateErrorWithErrorData(errorData, enqueueingFrameError)),
reject(
updateErrorWithErrorData(
(errorData: $FlowFixMe),
enqueueingFrameError,
),
),
);
});
};
} else {
fn = function nonPromiseMethodWrapper(...args: Array<any>) {
fn = function nonPromiseMethodWrapper(...args: Array<mixed>) {
const lastArg = args.length > 0 ? args[args.length - 1] : null;
const secondLastArg = args.length > 1 ? args[args.length - 2] : null;
const hasSuccessCallback = typeof lastArg === 'function';
Expand All @@ -123,23 +129,25 @@ function genMethod(moduleID: number, methodID: number, type: MethodType) {
hasSuccessCallback,
'Cannot have a non-function arg after a function arg.',
);
const onSuccess = hasSuccessCallback ? lastArg : null;
const onFail = hasErrorCallback ? secondLastArg : null;
// $FlowFixMe[incompatible-type]
const onSuccess: ?(mixed) => void = hasSuccessCallback ? lastArg : null;
// $FlowFixMe[incompatible-type]
const onFail: ?(mixed) => void = hasErrorCallback ? secondLastArg : null;
const callbackCount = hasSuccessCallback + hasErrorCallback;
args = args.slice(0, args.length - callbackCount);
const newArgs = args.slice(0, args.length - callbackCount);
if (type === 'sync') {
return BatchedBridge.callNativeSyncHook(
moduleID,
methodID,
args,
newArgs,
onFail,
onSuccess,
);
} else {
BatchedBridge.enqueueNativeCall(
moduleID,
methodID,
args,
newArgs,
onFail,
onSuccess,
);
Expand All @@ -161,7 +169,7 @@ function updateErrorWithErrorData(
return Object.assign(error, errorData || {});
}

let NativeModules: {[moduleName: string]: Object, ...} = {};
let NativeModules: {[moduleName: string]: $FlowFixMe, ...} = {};
if (global.nativeModuleProxy) {
NativeModules = global.nativeModuleProxy;
} else if (!global.nativeExtensions) {
Expand Down
Loading

0 comments on commit 4409642

Please sign in to comment.