From 1a33f6b5bae822195fcf4d90ad02dc30fe46cad5 Mon Sep 17 00:00:00 2001 From: Panos Vekris Date: Tue, 17 Dec 2024 11:26:23 -0800 Subject: [PATCH] [flow] perform call check on Array [react-rule-unsafe-mutation] errors Summary: In ``` component Foo(arr: Array) { arr.sort((a: number, b: number) => { return 1; }); return null; } ``` the call to `.sort` is an error, but we should still try to populate some type in the entry for `sort`. This diff makes it so that right after we raise the EPropNotReadable ReactDeepReadOnly error we perform the call as usual. Changelog: [errors] Flow will now perform a complete function call check even when [react-rule-unsafe-mutation] errors are raised. Reviewed By: SamChou19815 Differential Revision: D67320626 fbshipit-source-id: fc2c3df9661f43739c405103f59bd57870c0e2c8 --- src/typing/flow_js.ml | 9 +++++++-- tests/react_rules/react_rules.exp | 19 ++++++++++++++++++- tests/type_at_pos_react/.flowconfig | 1 + tests/type_at_pos_react/dro.js | 6 ++++++ tests/type_at_pos_react/test.sh | 5 +++++ tests/type_at_pos_react/type_at_pos_react.exp | 2 ++ 6 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 tests/type_at_pos_react/dro.js diff --git a/src/typing/flow_js.ml b/src/typing/flow_js.ml index 02da052f54c..6e58435964b 100644 --- a/src/typing/flow_js.ml +++ b/src/typing/flow_js.ml @@ -5097,7 +5097,8 @@ struct (**********************) (* Array library call *) (**********************) - | ( DefT (reason, ArrT (ArrayAT { elem_t; react_dro = Some (dro_loc, dro_type); _ })), + | ( DefT + (reason, ArrT (ArrayAT { elem_t; react_dro = Some (dro_loc, dro_type); tuple_view })), (GetPropT _ | SetPropT _ | MethodT _ | LookupT _) ) -> begin match u with @@ -5122,7 +5123,11 @@ struct prop_name = Some (OrdinaryName name); use_op = Frame (ReactDeepReadOnly (dro_loc, dro_type), use_op); } - ) + ); + rec_flow + cx + trace + (DefT (reason, ArrT (ArrayAT { elem_t; react_dro = None; tuple_view })), u) | _ -> let l = get_builtin_typeapp diff --git a/tests/react_rules/react_rules.exp b/tests/react_rules/react_rules.exp index ada718fd01b..16ec9906935 100644 --- a/tests/react_rules/react_rules.exp +++ b/tests/react_rules/react_rules.exp @@ -412,6 +412,23 @@ References: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [1] +Error ----------------------------------------------------------------------------------------------------- dro.js:84:13 + +Cannot call `droarr.push` because number [1] is incompatible with unknown element of empty array [2] in array element of +array element. Arrays are invariantly typed. See +https://flow.org/en/docs/faq/#why-cant-i-pass-an-arraystring-to-a-function-that-takes-an-arraystring-number. +[incompatible-call] + + dro.js:84:13 + 84| droarr.push([]); // error + ^^ [2] + +References: + dro.js:83:51 + 83| declare const droarr: React$Immutable>>; + ^^^^^^ [1] + + Error ------------------------------------------------------------------------------------------------------ dro.js:85:1 Cannot call `droarr[0].push` because property `push` is not readable. Values annotated using `React.Immutable` [1] are @@ -829,4 +846,4 @@ Cannot read `current` from `otherRef` [1] because `ref` values may not be read d -Found 63 errors +Found 64 errors diff --git a/tests/type_at_pos_react/.flowconfig b/tests/type_at_pos_react/.flowconfig index 1468a0ac3cb..5a8c3d82dc0 100644 --- a/tests/type_at_pos_react/.flowconfig +++ b/tests/type_at_pos_react/.flowconfig @@ -9,5 +9,6 @@ [options] all=true no_flowlib=false +component_syntax=true [strict] diff --git a/tests/type_at_pos_react/dro.js b/tests/type_at_pos_react/dro.js new file mode 100644 index 00000000000..be3ad545210 --- /dev/null +++ b/tests/type_at_pos_react/dro.js @@ -0,0 +1,6 @@ +component Foo(arr: Array) { + arr.sort((a: number, b: number) => { + return 1; + }); + return null; +} diff --git a/tests/type_at_pos_react/test.sh b/tests/type_at_pos_react/test.sh index 536a6dd7b61..ea2084d51bb 100644 --- a/tests/type_at_pos_react/test.sh +++ b/tests/type_at_pos_react/test.sh @@ -4,6 +4,11 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. + +# dro.js +printf "dro.js:2:9 = " +assert_ok "$FLOW" type-at-pos dro.js 2 9 --strip-root + # lazy_ref.js printf "lazy_ref.js:14:9 = " assert_ok "$FLOW" type-at-pos lazy_ref.js 14 9 --strip-root diff --git a/tests/type_at_pos_react/type_at_pos_react.exp b/tests/type_at_pos_react/type_at_pos_react.exp index 1db4c67d117..a794c8d5fdb 100644 --- a/tests/type_at_pos_react/type_at_pos_react.exp +++ b/tests/type_at_pos_react/type_at_pos_react.exp @@ -1,3 +1,5 @@ +dro.js:2:9 = (compareFn?: (a: number, b: number) => number) => Array +dro.js:2:9,2:12 lazy_ref.js:14:9 = { default: component(ref: RefSetter<{moo(x: string): void}>, ...empty) renders null }