From df3a60293cdfaa1a35aca01bfe61fc8f8c7362b3 Mon Sep 17 00:00:00 2001 From: Qian Wu Date: Tue, 11 Feb 2025 10:35:55 -0800 Subject: [PATCH] Revert D69277991: Initial Open Sourcing of React Native Compatibility Check Differential Revision: D69277991 Original commit changeset: 886a983d4b17 Original Phabricator Diff: D69277991 fbshipit-source-id: f69d528d87c22d03b0c3e654733c8efa89104df0 --- .../.gitignore | 1 - .../CONTRIBUTING.md | 36 - .../README.md | 245 --- .../package.json | 38 - .../src/ComparisonResult.js | 239 --- .../src/DiffResults.js | 207 --- .../src/ErrorFormatting.js | 309 ---- .../src/SortTypeAnnotations.js | 290 --- .../src/TypeDiffing.js | 1427 --------------- .../src/VersionDiffing.js | 1370 -------------- .../src/__tests__/ErrorFormatting-test.js | 65 - .../src/__tests__/ErrorFormattingTests.js | 150 -- .../src/__tests__/TypeDiffing-test.js | 1207 ------------- .../src/__tests__/VersionDiffing-test.js | 1603 ----------------- .../NativeComponent.js.flow | 169 -- .../NativeComponent.js.flow | 60 - .../NativeComponent.js.flow | 48 - .../NativeComponent.js.flow | 33 - .../NativeComponent.js.flow | 38 - .../NativeComponent.js.flow | 35 - .../NativeComponent.js.flow | 34 - .../NativeComponent.js.flow | 30 - .../NativeComponent.js.flow | 30 - .../NativeComponent.js.flow | 39 - .../NativeComponent.js.flow | 24 - .../NativeComponent.js.flow | 24 - .../NativeComponent.js.flow | 29 - .../NativeComponent.js.flow | 29 - .../NativeComponent.js.flow | 35 - .../NativeComponent.js.flow | 35 - .../NativeComponent.js.flow | 34 - .../NativeComponent.js.flow | 24 - .../NativeComponent.js.flow | 24 - .../NativeComponent.js.flow | 29 - .../native-component/NativeComponent.js.flow | 22 - .../NativeModuleBeforeAfterTypes.js.flow | 33 - .../NativeModuleBeforeAfterTypes.js.flow | 73 - .../NativeModuleBeforeAfterTypes.js.flow | 66 - .../NativeModule.js.flow | 24 - .../NativeModule.js.flow | 24 - .../NativeModule.js.flow | 24 - .../NativeModule.js.flow | 24 - .../NativeModule.js.flow | 24 - .../NativeModule.js.flow | 22 - .../NativeModule.js.flow | 22 - .../NativeModule.js.flow | 23 - .../NativeModule.js.flow | 23 - .../NativeModule.js.flow | 32 - .../NativeModule.js.flow | 32 - .../NativeModule.js.flow | 32 - .../native-module-nested/NativeModule.js.flow | 31 - .../NativeTypeDiffingTypes.js.flow | 218 --- .../NativeModule.js.flow | 24 - .../NativeModule.js.flow | 24 - .../NativeModule.js.flow | 31 - .../NativeModule.js.flow | 31 - .../NativeModule.js.flow | 30 - .../NativeModule.js.flow | 30 - .../NativeModule.js.flow | 30 - .../NativeModule.js.flow | 31 - .../NativeModule.js.flow | 30 - .../NativeModule.js.flow | 30 - .../NativeModule.js.flow | 31 - .../NativeModule.js.flow | 31 - .../NativeModule.js.flow | 24 - .../NativeModule.js.flow | 26 - .../NativeModule.js.flow | 26 - .../NativeModule.js.flow | 26 - .../NativeModule.js.flow | 26 - .../NativeModule.js.flow | 26 - .../NativeModule.js.flow | 26 - .../native-module/NativeModule.js.flow | 24 - .../ErrorFormatting-test.js.snap | 792 -------- .../src/__tests__/utilities/getTestSchema.js | 27 - .../src/convertPropToBasicTypes.js | 104 -- .../src/index.flow.js | 12 - .../src/index.js | 54 - scripts/build/config.js | 4 - yarn.lock | 26 - 79 files changed, 10315 deletions(-) delete mode 100644 packages/react-native-compatibility-check/.gitignore delete mode 100644 packages/react-native-compatibility-check/CONTRIBUTING.md delete mode 100644 packages/react-native-compatibility-check/README.md delete mode 100644 packages/react-native-compatibility-check/package.json delete mode 100644 packages/react-native-compatibility-check/src/ComparisonResult.js delete mode 100644 packages/react-native-compatibility-check/src/DiffResults.js delete mode 100644 packages/react-native-compatibility-check/src/ErrorFormatting.js delete mode 100644 packages/react-native-compatibility-check/src/SortTypeAnnotations.js delete mode 100644 packages/react-native-compatibility-check/src/TypeDiffing.js delete mode 100644 packages/react-native-compatibility-check/src/VersionDiffing.js delete mode 100644 packages/react-native-compatibility-check/src/__tests__/ErrorFormatting-test.js delete mode 100644 packages/react-native-compatibility-check/src/__tests__/ErrorFormattingTests.js delete mode 100644 packages/react-native-compatibility-check/src/__tests__/TypeDiffing-test.js delete mode 100644 packages/react-native-compatibility-check/src/__tests__/VersionDiffing-test.js delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-all-types/NativeComponent.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-command-all-basic-types-arrays/NativeComponent.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-command-all-basic-types/NativeComponent.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-command-changed/NativeComponent.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-command-extra-arg/NativeComponent.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-command-extra-command/NativeComponent.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-command/NativeComponent.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-added-optional-prop/NativeComponent.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-added-required-prop/NativeComponent.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-all-types/NativeComponent.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-array-union-added/NativeComponent.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-array-union/NativeComponent.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-changes/NativeComponent.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-default-change/NativeComponent.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-nested-object-added-optional-key/NativeComponent.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-nested-object-added-required-key/NativeComponent.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-nested-object/NativeComponent.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-union-added/NativeComponent.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-union/NativeComponent.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props/NativeComponent.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component/NativeComponent.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-before-after-types-removed/NativeModuleBeforeAfterTypes.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-before-after-types-type-changed/NativeModuleBeforeAfterTypes.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-before-after-types/NativeModuleBeforeAfterTypes.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-changed/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-get-constants-added-optional-constant-readonly/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-get-constants-added-optional-constant/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-get-constants-added-required-constant-readonly/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-get-constants-added-required-constant/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-get-constants-readonly/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-get-constants/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-nested-alias-changed/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-nested-alias/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-nested-changed/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-nested-nullable/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-nested-optional/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-nested/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-type-diffing-types/NativeTypeDiffingTypes.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-dictionary-changed/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-dictionary/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-changes/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-from-native-changes/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-from-native-type-changes/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-from-native-value-changes/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-from-native/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-type-changes/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-value-changes/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-eventemitter-changes/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-eventemitter/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-optional-argument/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-union-changes/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-union-confusing-string-literals/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-union-from-native-changes/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-union-from-native/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-union-type-changes/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-union/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module/NativeModule.js.flow delete mode 100644 packages/react-native-compatibility-check/src/__tests__/__snapshots__/ErrorFormatting-test.js.snap delete mode 100644 packages/react-native-compatibility-check/src/__tests__/utilities/getTestSchema.js delete mode 100644 packages/react-native-compatibility-check/src/convertPropToBasicTypes.js delete mode 100644 packages/react-native-compatibility-check/src/index.flow.js delete mode 100644 packages/react-native-compatibility-check/src/index.js diff --git a/packages/react-native-compatibility-check/.gitignore b/packages/react-native-compatibility-check/.gitignore deleted file mode 100644 index a65b41774ad..00000000000 --- a/packages/react-native-compatibility-check/.gitignore +++ /dev/null @@ -1 +0,0 @@ -lib diff --git a/packages/react-native-compatibility-check/CONTRIBUTING.md b/packages/react-native-compatibility-check/CONTRIBUTING.md deleted file mode 100644 index c48a6b73f01..00000000000 --- a/packages/react-native-compatibility-check/CONTRIBUTING.md +++ /dev/null @@ -1,36 +0,0 @@ -This tool is essentially a type checker, and as such it can be difficult to -understand the data flow. Luckily, there are fairly extensive tests which can -aid in ramping up. - -This tool is made up of 3 primary stages: TypeDiffing, VersionDiffing, and -ErrorFormatting. - -At a high level, the schemas are passed to TypeDiffing which is the pure -typechecker. It returns all differences between the types. VersionDiffing then -interprets these results and decides if some of those changes are actually safe -in the context of React Native’s JS/Native boundary. - -For example, if you have a NativeModule method that returns a string union -`small | medium | large`. Any changes to that union would be flagged by -TypeDiffing as incompatible. However, adding a value to that union is safe -because it ensures your JS code handles more cases than native returns. Removing -a value from that union isn’t safe though because it means your JS no longer -handles something native might return which could cause an exception. - -VersionDiffing encodes the logic of what is safe and what isn’t; -property/union/enum additions and removals, changing something from optional to -required and vice versa, etc. VersionDiffing has knowledge of components and -modules. - -VersionDiffing returns a set of incompatible changes, which then gets passed to -ErrorFormatting. ErrorFormatting does as you’d expect, converting these deep -objects into nicely formatted strings. - -When contributing, some principles: - -- Keep TypeDiffing and ErrorFormatting pure. They should only know about - JavaScript types, not React Native specific concepts -- Add tests for every case you can think of. This codebase can be complex and - hard to reason about when making changes. The only way to stay sane is to be - able to rely on the tests to catch anything bad you’ve done. Do yourself and - future contributors a favor. diff --git a/packages/react-native-compatibility-check/README.md b/packages/react-native-compatibility-check/README.md deleted file mode 100644 index 0e727aaf885..00000000000 --- a/packages/react-native-compatibility-check/README.md +++ /dev/null @@ -1,245 +0,0 @@ -# **React Native compatibility-check** - -Status: Experimental (stage 1) - -Work In Progress. Documentation is lacking, and intended to be used by power -users at this point. - -This tool enables checking the boundary between JavaScript and Native for -backwards incompatible changes to protect against crashes. - -This is useful for: - -- Local Development -- Over the Air updates on platforms that support it -- Theoretically: Server Components with React Native - -## **Motivating Problems** - -Let’s look at some motivating examples for this project. - -> [!NOTE] -> The examples below are written with Flow, but the compatibility-check -> tool is agnostic to the types you write. The compatibility-check runs on JSON -> schema files, most commonly generated by the -> [@react-native/codegen](https://www.npmjs.com/package/@react-native/codegen) -> tool which supports both TypeScript and Flow. - -### **Adding new methods** - -You might have an Analytics Native Module in your app, and you last built the -native client a couple of days ago: - -```javascript -export interface Spec extends TurboModule { - log: (eventName: string, content: string) => void; -} -``` - -And you are working on a change to add a new method to this Native Module: - -```javascript -export interface Spec extends TurboModule { - log: (eventName: string, content: string) => void; - logError: (message: string) => void; -} -``` - -``` -NativeAnalytics.logError('Oh No! We hit a crash') -``` - -Since you are working on this, you’ve built a new native client and tested the -change on your computer and everything works. - -However, when your colleague pulls your latest changes and tries to run it, -they’ll get a crash `logError is not a function`. They need to rebuild their -native client\! - -Using this tool, you can detect this incompatibility at build time, getting an -error that looks like: - -``` -NativeAnalytics: Object added required properties, which native will not provide - -- logError -``` - -Errors like this can occur for much more nuanced reasons than adding a method. -For example: - -### **Sending native new union values** - -```javascript -export interface Spec extends TurboModule { - // You add 'system' to this union - +setColorScheme: (color: 'light' | 'dark') => void; -} -``` - -If you add a new option of `system` and add native support for that option, when -you call this method with `system` on your commit it would work but on an older -build not expecting `system` it will crash. This tool will give you the error -message: - -``` -ColorManager.setColorScheme parameter 0: Union added items, but native will not expect/support them - -- position 3 system -``` - -### **Changing an enum value sent from native** - -As another example, say you are getting the color scheme from the system as an -integer value, used in JavaScript as an enum: - -```javascript -enum TestEnum { - LIGHT = 1, - DARK = 2, - SYSTEM = 3, -} - -export interface Spec extends TurboModule { - getColorScheme: () => TestEnum; -} -``` - -And you realize you actually need native to send `-1` for System instead of 3\. - -```javascript -enum TestEnum { - LIGHT = 1, - DARK = 2, - SYSTEM = -1, -} -``` - -If you make this change and run the JavaScript on an old build, it might still -send JavaScript the value 3, which your JavaScript isn’t handling anymore\! - -This tool gives an error: - -```javascript -ColorManager: Object contained a property with a type mismatch - -- getColorScheme: has conflicting type changes - --new: ()=>Enum - --old: ()=>Enum - Function return types do not match - --new: ()=>Enum - --old: ()=>Enum - Enum types do not match - --new: Enum {LIGHT = 1, DARK = 2, SYSTEM = -1} - --old: Enum {LIGHT = 1, DARK = 2, SYSTEM = 3} - Enum contained a member with a type mismatch - -- Member SYSTEM: has conflicting changes - --new: -1 - --old: 3 - Numeric literals are not equal - --new: -1 - --old: 3 - -``` - -## **Avoiding Breaking Changes** - -You can use this tool to either detect changes locally to warn that you need to -install a new native build, or when doing OTA you might need to guarantee that -the changes in your PR are compatible with the native client they’ll be running -in. - -### **Example 1** - -In example 1, when adding logError, it needs to be optional to be safe: - -```javascript -export interface Spec extends TurboModule { - log: (eventName: string, content: string) => void; - logError?: (message: string) => void; -} -``` - -That will enforce if you are using TypeScript or Flow that you check if the -native client supports logError before calling it: - -```javascript -if (NativeAnalytics.logError) { - NativeAnalytics.logError('Oh No! We hit a crash'); -} -``` - -### **Example 2** - -When you want to add '`system'` as a value to the union, modifying the existing -union is not safe. You would need to add a new optional method that has that -change. You can clean up the old method when you know that all of the builds you -ever want to run this JavaScript on have native support. - -```javascript -export interface Spec extends TurboModule { - +setColorScheme: (color: 'light' | 'dark') => void - +setColorSchemeWithSystem?: (color: 'light' | 'dark' | 'system') => void -} -``` - -### **Example 3** - -Changing a union case is similar to Example 2, you would either need a new -method, or support the existing value and the new `-1`. - -``` -enum TestEnum { - LIGHT = 1, - DARK = 2, - SYSTEM = 3, - SYSTEM_ALSO = -1, -} -``` - -## **Installation** - -``` -yarn add @react-native/compatibility-check -``` - -## **Usage** - -To use this package, you’ll need a script that works something like this: - -This script checks the compatibility of a React Native app's schema between two -versions. It takes into account the changes made to the schema and determines -whether they are compatible or not. - -```javascript -import {compareSchemas} from '@react-native/compatibility-check'; -const util = require('util'); - -async function run(argv: Argv, STDERR: string) { - const debug = (log: mixed) => { - argv.debug && - console.info(util.inspect(log, {showHidden: false, depth: null})); - }; - - const currentSchema = - JSON.parse(/*you'll read the file generated by codegen wherever it is in your app*/); - const previousSchema = - JSON.parse(/*you'll read the schema file that you persisted from when your native app was built*/); - - const safetyResult = compareSchemas(currentSchema, previousSchema); - - const summary = safetyResult.getSummary(); - switch (summary.status) { - case 'ok': - debug('No changes in boundary'); - console.log(JSON.stringify(summary)); - break; - case 'patchable': - debug('Changes in boundary, but are compatible'); - debug(result.getDebugInfo()); - console.log(JSON.stringify(summary)); - break; - default: - debug(result.getDebugInfo()); - console.error(JSON.stringify(result.getErrors())); - throw new Error(`Incompatible changes in boundary`); - } -} -``` diff --git a/packages/react-native-compatibility-check/package.json b/packages/react-native-compatibility-check/package.json deleted file mode 100644 index d145d16ad63..00000000000 --- a/packages/react-native-compatibility-check/package.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "@react-native/compatibility-check", - "version": "0.0.1", - "description": "Check a React Native app's boundary between JS and Native for incompatibilities", - "license": "MIT", - "repository": { - "type": "git", - "url": "git+https://github.com/facebook/react-native.git", - "directory": "packages/react-native-compatibility-check" - }, - "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/react-native-compatibility-check#readme", - "keywords": [ - "boundary", - "crashes", - "native", - "codegen", - "tools", - "react-native" - ], - "bugs": "https://github.com/facebook/react-native/issues", - "engines": { - "node": ">=18" - }, - "exports": { - ".": "./src/index.js", - "./package.json": "./package.json" - }, - "files": [ - "dist" - ], - "dependencies": { - "@react-native/codegen": "0.79.0-main" - }, - "devDependencies": { - "flow-remove-types": "^2.237.2", - "rimraf": "^3.0.2" - } -} diff --git a/packages/react-native-compatibility-check/src/ComparisonResult.js b/packages/react-native-compatibility-check/src/ComparisonResult.js deleted file mode 100644 index 933ad147364..00000000000 --- a/packages/react-native-compatibility-check/src/ComparisonResult.js +++ /dev/null @@ -1,239 +0,0 @@ -/** - * 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 strict - * @format - */ - -import type { - CompleteTypeAnnotation, - NamedShape, - NativeModuleEnumMember, -} from '@react-native/codegen/src/CodegenSchema'; - -type TypeAnnotationComparisonError = { - type: 'TypeAnnotationComparisonError', - message: string, - newerAnnotation: CompleteTypeAnnotation, - olderAnnotation: CompleteTypeAnnotation, - previousError?: TypeComparisonError, -}; -type TypeInformationComparisonError = { - type: 'TypeInformationComparisonError', - message: string, - newerType: CompleteTypeAnnotation, - olderType: CompleteTypeAnnotation, - previousError?: TypeComparisonError, -}; -type PropertyComparisonError = { - type: 'PropertyComparisonError', - message: string, - mismatchedProperties: Array<{ - property: string, - fault?: TypeComparisonError, - ... - }>, - previousError?: TypeComparisonError, -}; -type PositionalComparisonError = { - type: 'PositionalComparisonError', - message: string, - erroneousItems: Array<[number, CompleteTypeAnnotation]>, - previousError?: TypeComparisonError, -}; -type MemberComparisonError = { - type: 'MemberComparisonError', - message: string, - mismatchedMembers: Array<{ - member: string, - fault?: TypeComparisonError, - }>, - previousError?: TypeComparisonError, -}; -export type TypeComparisonError = - | TypeAnnotationComparisonError - | TypeInformationComparisonError - | PropertyComparisonError - | PositionalComparisonError - | MemberComparisonError; - -// Collects changes that may be type safe within parameters, unions, intersections, and tuples -export type PositionalComparisonResult = { - typeKind: 'stringUnion' | 'union' | 'intersection' | 'parameter' | 'tuple', - // Nested changes stores the position of the old type followed by new - // Except for union and intersection, new position === old position - nestedChanges: Array<[number, number, ComparisonResult]>, - // These properties should never occur for a tuple - addedElements?: Array<[number, CompleteTypeAnnotation]>, - removedElements?: Array<[number, CompleteTypeAnnotation]>, - ... -}; -export type FunctionComparisonResult = { - returnType?: ComparisonResult, - // The following should always have typeKind 'parameter' - parameterTypes?: PositionalComparisonResult, - ... -}; - -// Array>> - -export type PropertiesComparisonResult = { - addedProperties?: $ReadOnlyArray>, - missingProperties?: $ReadOnlyArray>, - errorProperties?: Array<{ - property: string, - fault?: TypeComparisonError, - ... - }>, - madeStrict?: Array<{ - property: string, - furtherChanges?: ComparisonResult, - ... - }>, - madeOptional?: Array<{ - property: string, - furtherChanges?: ComparisonResult, - ... - }>, - nestedPropertyChanges?: Array<[string, ComparisonResult]>, - ... -}; -export type MembersComparisonResult = { - addedMembers?: Array, - missingMembers?: Array, - errorMembers?: Array<{ - member: string, - fault?: TypeComparisonError, - }>, -}; -export type NullableComparisonResult = { - /* Four possible cases of change: - void goes to T? :: typeRefined !optionsReduced - T? goes to void :: typeRefined optionsReduced - T goes to T? :: !typeRefined !optionsReduced - T? goes to T :: !typeRefined optionsReduced - */ - typeRefined: boolean, - optionsReduced: boolean, - // interiorLog not available if either type is void - interiorLog: ?ComparisonResult, - newType: ?CompleteTypeAnnotation, - oldType: ?CompleteTypeAnnotation, - ... -}; -export type ComparisonResult = - | {status: 'matching'} - | {status: 'skipped'} - | {status: 'nullableChange', nullableLog: NullableComparisonResult} - | {status: 'properties', propertyLog: PropertiesComparisonResult} - | {status: 'members', memberLog: MembersComparisonResult} - | {status: 'functionChange', functionChangeLog: FunctionComparisonResult} - | {status: 'positionalTypeChange', changeLog: PositionalComparisonResult} - | {status: 'error', errorLog: TypeComparisonError}; - -export function isPropertyLogEmpty( - result: PropertiesComparisonResult, -): boolean { - return !( - result.addedProperties || - result.missingProperties || - result.nestedPropertyChanges || - result.madeStrict || - result.madeOptional || - result.errorProperties - ); -} - -export function isMemberLogEmpty(result: MembersComparisonResult): boolean { - return !(result.addedMembers || result.missingMembers || result.errorMembers); -} - -export function isFunctionLogEmpty(result: FunctionComparisonResult): boolean { - return !(result.returnType || result.parameterTypes); -} - -export function makeError(error: TypeComparisonError): ComparisonResult { - return { - status: 'error', - errorLog: error, - }; -} - -export function typeInformationComparisonError( - message: string, - newerType: CompleteTypeAnnotation, - olderType: CompleteTypeAnnotation, - previousError?: TypeComparisonError, -): TypeComparisonError { - return { - type: 'TypeInformationComparisonError', - message, - newerType, - olderType, - previousError, - }; -} - -export function typeAnnotationComparisonError( - message: string, - newerAnnotation: CompleteTypeAnnotation, - olderAnnotation: CompleteTypeAnnotation, - previousError?: TypeComparisonError, -): TypeComparisonError { - return { - type: 'TypeAnnotationComparisonError', - message, - newerAnnotation, - olderAnnotation, - previousError, - }; -} - -export function propertyComparisonError( - message: string, - mismatchedProperties: Array<{ - property: string, - fault?: TypeComparisonError, - ... - }>, - previousError?: TypeComparisonError, -): TypeComparisonError { - return { - type: 'PropertyComparisonError', - message, - mismatchedProperties, - previousError, - }; -} - -export function memberComparisonError( - message: string, - mismatchedMembers: Array<{ - member: string, - fault?: TypeComparisonError, - }>, - previousError?: TypeComparisonError, -): TypeComparisonError { - return { - type: 'MemberComparisonError', - message, - mismatchedMembers, - previousError, - }; -} - -export function positionalComparisonError( - message: string, - erroneousItems: Array<[number, CompleteTypeAnnotation]>, - previousError?: TypeComparisonError, -): TypeComparisonError { - return { - type: 'PositionalComparisonError', - message, - erroneousItems, - previousError, - }; -} diff --git a/packages/react-native-compatibility-check/src/DiffResults.js b/packages/react-native-compatibility-check/src/DiffResults.js deleted file mode 100644 index 33eac9b980c..00000000000 --- a/packages/react-native-compatibility-check/src/DiffResults.js +++ /dev/null @@ -1,207 +0,0 @@ -/** - * 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 strict-local - * @format - */ - -import type { - PropertiesComparisonResult, - TypeComparisonError, -} from './ComparisonResult'; -import type {CompleteTypeAnnotation} from '@react-native/codegen/src/CodegenSchema'; - -export type ErrorCode = - | 'addedProps' - | 'removedProps' - | 'changedParams' - | 'incompatibleTypes' - | 'requiredProps' - | 'optionalProps' - | 'nonNullableOfNull' - | 'nullableOfNonNull' - | 'removedUnionCases' - | 'addedUnionCases' - | 'addedEnumCases' - | 'removedEnumCases' - | 'removedIntersectCases' - | 'addedIntersectCases' - | 'removedModule' - | 'removedComponent'; - -export type TypeStore = { - typeName: string, - typeInformation: CompleteTypeAnnotation, - ... -}; -// Stores object properties that are added or removed which could be patchable -export type ObjectTypeChangeStore = { - typeName: string, - newType: CompleteTypeAnnotation, - oldType: CompleteTypeAnnotation, - propertyChange: PropertiesComparisonResult, -}; -export type ErrorStore = { - typeName: string, - errorCode: ErrorCode, - errorInformation: TypeComparisonError, -}; -export type FormattedErrorStore = { - message: string, - errorCode: ErrorCode, -}; -export type NativeSpecErrorStore = { - nativeSpecName: string, - omitted: boolean, - errorCode: ErrorCode, - errorInformation?: TypeComparisonError, - changeInformation?: DiffSet, -}; -export type ExportableNativeSpecErrorStore = { - nativeSpecName: string, - omitted: boolean, - errorCode: ErrorCode, - errorInformation?: TypeComparisonError, - changeInformation?: ExportableDiffSet, -}; -export type DiffSet = { - newTypes: Set, - deprecatedTypes: Set, - objectTypeChanges: Set, - incompatibleChanges: Set, -}; -type ExportableDiffSet = { - newTypes: Array, - deprecatedTypes: Array, - objectTypeChanges: Array, - incompatibleChanges: Array, -}; - -export type Framework = 'ReactNative'; -export type SchemaDiffers = { - incompatibleSpecs: ?Set, -}; -type ExportableSchemaDiffers = { - incompatibleSpecs: ?Array, -}; -export type SchemaDiffCategory = 'new' | 'deprecated' | SchemaDiffers; -type ExportableSchemaDiffCategory = - | 'new' - | 'deprecated' - | ExportableSchemaDiffers; -export type SchemaDiff = { - name: string, - framework: Framework, - status: SchemaDiffCategory, -}; -export type ExportableSchemaDiff = { - name: string, - framework: Framework, - status: ExportableSchemaDiffCategory, -}; - -export type Version = { - device: 'android' | 'ios', - number: string, - ... -}; - -export type Incompatible = { - framework: Framework, - incompatibleSpecs?: Array, -}; -export type IncompatiblityReport = { - [hasteModuleName: string]: Incompatible, -}; -export type DiffSummary = { - /** status records how the diff compares against older versions - * ok: there are no changes that impact older versions - * patchable: there are additions (or modifications) that are not suported - * in older versions but is safe with an auto-generated patch - * incompatible: there are modifications that are not safe for use with older - * versions and are not fixable with an auto-generated patchable - */ - status: 'ok' | 'patchable' | 'incompatible', - // If there are incompatible changes, provide a record of them, otherwise {} - incompatibilityReport: IncompatiblityReport, -}; - -export type FormattedIncompatible = { - framework: Framework, - incompatibleSpecs?: Array, -}; - -export type FormattedIncompatiblityReport = { - [hasteModuleName: string]: FormattedIncompatible, -}; - -export type FormattedDiffSummary = { - /** status records how the diff compares against older versions - * ok: there are no changes that impact older versions - * patchable: there are additions (or modifications) that are not suported - * in older versions but is safe with an auto-generated patch - * incompatible: there are modifications that are not safe for use with older - * versions and are not fixable with an auto-generated patchable - */ - status: 'ok' | 'patchable' | 'incompatible', - // If there are incompatible changes, provide a record of them, otherwise {} - incompatibilityReport: FormattedIncompatiblityReport, -}; - -function diffSetExporter(diffSet: DiffSet): ExportableDiffSet { - return { - newTypes: Array.from(diffSet.newTypes), - deprecatedTypes: Array.from(diffSet.deprecatedTypes), - objectTypeChanges: Array.from(diffSet.objectTypeChanges), - incompatibleChanges: Array.from(diffSet.incompatibleChanges), - }; -} - -export function nativeSpecErrorExporter( - nativeSpecError: NativeSpecErrorStore, -): ExportableNativeSpecErrorStore { - if (nativeSpecError.changeInformation) { - return { - nativeSpecName: nativeSpecError.nativeSpecName, - omitted: nativeSpecError.omitted, - errorCode: nativeSpecError.errorCode, - errorInformation: nativeSpecError.errorInformation, - changeInformation: diffSetExporter(nativeSpecError.changeInformation), - }; - } - return { - nativeSpecName: nativeSpecError.nativeSpecName, - omitted: nativeSpecError.omitted, - errorCode: nativeSpecError.errorCode, - errorInformation: nativeSpecError.errorInformation, - }; -} - -function schemaDiffCategoryExporter( - status: SchemaDiffCategory, -): ExportableSchemaDiffCategory { - switch (status) { - case 'new': - case 'deprecated': - return status; - default: - return { - incompatibleSpecs: status.incompatibleSpecs - ? Array.from(status.incompatibleSpecs).map(nativeSpecErrorExporter) - : undefined, - }; - } -} - -export function schemaDiffExporter( - schemaDiff: SchemaDiff, -): ExportableSchemaDiff { - return { - name: schemaDiff.name, - framework: schemaDiff.framework, - status: schemaDiffCategoryExporter(schemaDiff.status), - }; -} diff --git a/packages/react-native-compatibility-check/src/ErrorFormatting.js b/packages/react-native-compatibility-check/src/ErrorFormatting.js deleted file mode 100644 index f19c796661a..00000000000 --- a/packages/react-native-compatibility-check/src/ErrorFormatting.js +++ /dev/null @@ -1,309 +0,0 @@ -/** - * 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 strict-local - * @format - */ - -import type {TypeComparisonError} from './ComparisonResult'; -import type { - DiffSummary, - ErrorStore, - FormattedDiffSummary, - FormattedErrorStore, - FormattedIncompatible, - FormattedIncompatiblityReport, - NativeSpecErrorStore, -} from './DiffResults'; -import type {CompleteTypeAnnotation} from '@react-native/codegen/src/CodegenSchema'; - -function indentedLineStart(indent: number): string { - return '\n' + ' '.repeat(indent); -} - -export function formatErrorMessage( - error: TypeComparisonError, - indent: number = 0, -): string { - switch (error.type) { - case 'PropertyComparisonError': - const formattedProperties = error.mismatchedProperties.map( - individualPropertyError => - indentedLineStart(indent + 1) + - '-- ' + - individualPropertyError.property + - (individualPropertyError.fault - ? ': ' + - formatErrorMessage(individualPropertyError.fault, indent + 2) - : ''), - ); - return error.message + formattedProperties.join(''); - case 'PositionalComparisonError': - const formattedPositionalChanges = error.erroneousItems.map( - ([index, type]) => - indentedLineStart(indent + 1) + - '-- position ' + - index + - ' ' + - formatTypeAnnotation(type), - ); - return error.message + formattedPositionalChanges.join(''); - case 'TypeAnnotationComparisonError': - const previousError = error.previousError; - - return ( - error.message + - indentedLineStart(indent + 1) + - '--new: ' + - formatTypeAnnotation(error.newerAnnotation) + - indentedLineStart(indent + 1) + - '--old: ' + - formatTypeAnnotation(error.olderAnnotation) + - (previousError != null - ? indentedLineStart(indent + 1) + - '' + - formatErrorMessage(previousError, indent + 2) - : '') - ); - case 'TypeInformationComparisonError': - // I'm not sure that this error type is possible with the codegen - - return ( - error.message + - indentedLineStart(indent + 1) + - '-- new: ' + - formatTypeAnnotation(error.newerType) + - indentedLineStart(indent + 1) + - '-- old: ' + - formatTypeAnnotation(error.olderType) - ); - case 'MemberComparisonError': - const formattedMembers = error.mismatchedMembers.map( - individualMemberError => - indentedLineStart(indent + 1) + - '-- Member ' + - individualMemberError.member + - (individualMemberError.fault - ? ': ' + formatErrorMessage(individualMemberError.fault, indent + 2) - : ''), - ); - return error.message + formattedMembers.join(''); - default: - (error.type: empty); - return ''; - } -} - -function formatTypeAnnotation(annotation: CompleteTypeAnnotation): string { - switch (annotation.type) { - case 'AnyTypeAnnotation': - return 'any'; - case 'ArrayTypeAnnotation': - return 'Array<' + formatTypeAnnotation(annotation.elementType) + '>'; - case 'BooleanTypeAnnotation': - return 'boolean'; - case 'EnumDeclaration': { - let shortHandType = ''; - switch (annotation.memberType) { - case 'StringTypeAnnotation': - shortHandType = 'string'; - break; - case 'NumberTypeAnnotation': - shortHandType = 'number'; - break; - default: - (annotation.memberType: empty); - throw new Error('Unexpected enum memberType'); - } - - return `Enum<${shortHandType}>` + ''; - } - case 'EnumDeclarationWithMembers': { - let shortHandType = ''; - switch (annotation.memberType) { - case 'StringTypeAnnotation': - shortHandType = 'string'; - break; - case 'NumberTypeAnnotation': - shortHandType = 'number'; - break; - default: - (annotation.memberType: empty); - throw new Error('Unexptected enum memberType'); - } - - return ( - `Enum<${shortHandType}> {` + - annotation.members - .map( - member => `${member.name} = ${formatTypeAnnotation(member.value)}`, - ) - .join(', ') + - '}' - ); - } - case 'FunctionTypeAnnotation': - return ( - '(' + - annotation.params - .map( - param => - param.name + - (param.optional ? '?' : '') + - ': ' + - formatTypeAnnotation(param.typeAnnotation), - ) - .join(', ') + - ')' + - '=>' + - formatTypeAnnotation(annotation.returnTypeAnnotation) - ); - case 'NullableTypeAnnotation': - return '?' + formatTypeAnnotation(annotation.typeAnnotation); - case 'NumberTypeAnnotation': - return 'number'; - case 'DoubleTypeAnnotation': - return 'double'; - case 'FloatTypeAnnotation': - return 'float'; - case 'Int32TypeAnnotation': - return 'int'; - case 'NumberLiteralTypeAnnotation': - return annotation.value.toString(); - case 'ObjectTypeAnnotation': - return ( - '{' + - annotation.properties - .map( - property => - property.name + - (property.optional ? '?' : '') + - ': ' + - formatTypeAnnotation(property.typeAnnotation), - ) - .join(', ') + - '}' - ); - case 'StringLiteralTypeAnnotation': - // If the string is a number, disambiguate from a number literal by adding quotes - // Other things are obviously strings so quotes unconditionally would just add noise - return parseInt(annotation.value, 10).toString() === annotation.value || - annotation.value.includes(' ') - ? `'${annotation.value}'` - : annotation.value; - case 'StringLiteralUnionTypeAnnotation': - return ( - '(' + - annotation.types - .map(stringLit => formatTypeAnnotation(stringLit)) - .join(' | ') + - ')' - ); - case 'StringTypeAnnotation': - return 'string'; - case 'UnionTypeAnnotation': { - const shortHandType = - annotation.memberType === 'StringTypeAnnotation' - ? 'string' - : annotation.memberType === 'ObjectTypeAnnotation' - ? 'Object' - : 'number'; - return `Union<${shortHandType}>`; - } - case 'PromiseTypeAnnotation': - return 'Promise<' + formatTypeAnnotation(annotation.elementType) + '>'; - case 'EventEmitterTypeAnnotation': - return ( - 'EventEmitter<' + formatTypeAnnotation(annotation.typeAnnotation) + '>' - ); - case 'TypeAliasTypeAnnotation': - case 'ReservedTypeAnnotation': - return annotation.name; - case 'VoidTypeAnnotation': - return 'void'; - case 'MixedTypeAnnotation': - return 'mixed'; - case 'GenericObjectTypeAnnotation': - if (annotation.dictionaryValueType) { - return `{[string]: ${formatTypeAnnotation(annotation.dictionaryValueType)}`; - } - - return 'Object'; - default: - (annotation.type: empty); - return JSON.stringify(annotation); - } -} - -export function formatErrorStore(errorStore: ErrorStore): FormattedErrorStore { - return { - message: - errorStore.typeName + - ': ' + - formatErrorMessage(errorStore.errorInformation), - errorCode: errorStore.errorCode, - }; -} - -export function formatNativeSpecErrorStore( - specError: NativeSpecErrorStore, -): Array { - if (specError.errorInformation) { - return [ - { - message: - specError.nativeSpecName + - ': ' + - formatErrorMessage(specError.errorInformation), - errorCode: specError.errorCode, - }, - ]; - } - - if (specError.changeInformation?.incompatibleChanges != null) { - return Array.from(specError.changeInformation.incompatibleChanges).map( - errorStore => formatErrorStore(errorStore), - ); - } - // changeInformation does not contain incompatible changes - return []; -} - -export function formatDiffSet(summary: DiffSummary): FormattedDiffSummary { - const summaryStatus = summary.status; - if (summaryStatus === 'ok' || summaryStatus === 'patchable') { - // $FlowFixMe I don't think we can ever get in this branch - return summary; - } - const hasteModules = Object.keys(summary.incompatibilityReport); - const incompatibles = summary.incompatibilityReport; - const formattedIncompatibilities: FormattedIncompatiblityReport = {}; - hasteModules.forEach(hasteModule => { - const incompat = incompatibles[hasteModule]; - const formattedIncompat: FormattedIncompatible = { - framework: incompat.framework, - }; - if (incompat.incompatibleSpecs) { - // nested errors - formattedIncompat.incompatibleSpecs = incompat.incompatibleSpecs.reduce( - ( - formattedModuleErrors: $ReadOnlyArray, - specErrorStore, - ) => - formattedModuleErrors.concat( - formatNativeSpecErrorStore(specErrorStore), - ), - [], - ); - } - - formattedIncompatibilities[hasteModule] = formattedIncompat; - }); - return { - status: (summaryStatus: 'incompatible'), - incompatibilityReport: formattedIncompatibilities, - }; -} diff --git a/packages/react-native-compatibility-check/src/SortTypeAnnotations.js b/packages/react-native-compatibility-check/src/SortTypeAnnotations.js deleted file mode 100644 index 142581169de..00000000000 --- a/packages/react-native-compatibility-check/src/SortTypeAnnotations.js +++ /dev/null @@ -1,290 +0,0 @@ -/** - * 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 strict - * @format - */ - -import type {CompleteTypeAnnotation} from '@react-native/codegen/src/CodegenSchema'; - -import invariant from 'invariant'; - -export function sortTypeAnnotations( - annotations: $ReadOnlyArray, -): Array<[number, CompleteTypeAnnotation]> { - const sortableArray = annotations.map( - (a, i): [number, CompleteTypeAnnotation] => [i, a], - ); - return sortableArray.sort(compareTypeAnnotationForSorting); -} - -const EQUALITY_MSG = 'typeA and typeB differ despite check'; -export function compareTypeAnnotationForSorting( - [originalPositionA, typeA]: [number, CompleteTypeAnnotation], - [originalPositionB, typeB]: [number, CompleteTypeAnnotation], -): number { - if (typeA.type !== typeB.type) { - if (typeA.type === 'NullableTypeAnnotation') { - return compareTypeAnnotationForSorting( - [originalPositionA, typeA.typeAnnotation], - [originalPositionB, typeB], - ); - } - if (typeB.type === 'NullableTypeAnnotation') { - return compareTypeAnnotationForSorting( - [originalPositionA, typeA], - [originalPositionB, typeB.typeAnnotation], - ); - } - return ( - typeAnnotationArbitraryOrder(typeA) - typeAnnotationArbitraryOrder(typeB) - ); - } - switch (typeA.type) { - case 'AnyTypeAnnotation': - return 0; - case 'ArrayTypeAnnotation': - invariant(typeB.type === 'ArrayTypeAnnotation', EQUALITY_MSG); - return compareTypeAnnotationForSorting( - [originalPositionA, typeA.elementType], - [originalPositionB, typeB.elementType], - ); - case 'BooleanTypeAnnotation': - return originalPositionA - originalPositionB; - case 'EnumDeclaration': - invariant(typeB.type === 'EnumDeclaration', EQUALITY_MSG); - return typeA.memberType.localeCompare(typeB.memberType); - case 'EnumDeclarationWithMembers': - invariant(typeB.type === 'EnumDeclarationWithMembers', EQUALITY_MSG); - return compareNameAnnotationArraysForSorting( - [originalPositionA, typeA.members.map(m => [m.name, m.value])], - [originalPositionB, typeB.members.map(m => [m.name, m.value])], - ); - case 'FunctionTypeAnnotation': - invariant(typeB.type === 'FunctionTypeAnnotation', EQUALITY_MSG); - const parmComparison = compareAnnotationArraysForSorting( - [originalPositionA, typeA.params.map(p => p.typeAnnotation)], - [originalPositionB, typeB.params.map(p => p.typeAnnotation)], - ); - if (parmComparison === 0) { - return compareTypeAnnotationForSorting( - [originalPositionA, typeA.returnTypeAnnotation], - [originalPositionB, typeB.returnTypeAnnotation], - ); - } - return parmComparison; - case 'EventEmitterTypeAnnotation': - invariant(typeB.type === 'EventEmitterTypeAnnotation', EQUALITY_MSG); - - return compareTypeAnnotationForSorting( - [originalPositionA, typeA.typeAnnotation], - [originalPositionB, typeB.typeAnnotation], - ); - case 'GenericObjectTypeAnnotation': - invariant(typeB.type === 'GenericObjectTypeAnnotation', EQUALITY_MSG); - - if ( - typeA.dictionaryValueType == null && - typeB.dictionaryValueType == null - ) { - return 0; - } else if ( - typeA.dictionaryValueType != null && - typeB.dictionaryValueType != null - ) { - return compareTypeAnnotationForSorting( - [originalPositionA, typeA.dictionaryValueType], - [originalPositionB, typeB.dictionaryValueType], - ); - } else { - return typeA.dictionaryValueType == null ? -1 : 1; - } - case 'NullableTypeAnnotation': - invariant(typeB.type === 'NullableTypeAnnotation', EQUALITY_MSG); - return compareTypeAnnotationForSorting( - [originalPositionA, typeA.typeAnnotation], - [originalPositionB, typeB.typeAnnotation], - ); - case 'NumberTypeAnnotation': - case 'Int32TypeAnnotation': - case 'FloatTypeAnnotation': - case 'DoubleTypeAnnotation': - return 0; - case 'NumberLiteralTypeAnnotation': - invariant(typeB.type === 'NumberLiteralTypeAnnotation', EQUALITY_MSG); - return typeA.value - typeB.value; - case 'ObjectTypeAnnotation': - invariant(typeB.type === 'ObjectTypeAnnotation', EQUALITY_MSG); - return compareNameAnnotationArraysForSorting( - [ - originalPositionA, - typeA.properties.map(p => [p.name, p.typeAnnotation]), - ], - [ - originalPositionB, - typeB.properties.map(p => [p.name, p.typeAnnotation]), - ], - ); - case 'StringTypeAnnotation': - return originalPositionA - originalPositionB; - case 'StringLiteralTypeAnnotation': - invariant(typeB.type === 'StringLiteralTypeAnnotation', EQUALITY_MSG); - return typeA.value.localeCompare(typeB.value); - case 'StringLiteralUnionTypeAnnotation': - invariant( - typeB.type === 'StringLiteralUnionTypeAnnotation', - EQUALITY_MSG, - ); - return compareAnnotationArraysForSorting( - [originalPositionA, typeA.types], - [originalPositionB, typeB.types], - ); - case 'UnionTypeAnnotation': - invariant(typeB.type === 'UnionTypeAnnotation', EQUALITY_MSG); - return 0; - case 'VoidTypeAnnotation': - return 0; - case 'ReservedTypeAnnotation': - return 0; - case 'PromiseTypeAnnotation': - invariant(typeB.type === 'PromiseTypeAnnotation', EQUALITY_MSG); - return compareTypeAnnotationForSorting( - [originalPositionA, typeA.elementType], - [originalPositionB, typeB.elementType], - ); - case 'TypeAliasTypeAnnotation': - return 0; - case 'MixedTypeAnnotation': - return 0; - default: - (typeA.type: empty); - return -1; - } -} - -function nameComparison( - [nameA]: [string, CompleteTypeAnnotation], - [nameB]: [string, CompleteTypeAnnotation], -) { - if (nameA === nameB) { - return 0; - } else if (nameA < nameB) { - return -1; - } - return 1; -} - -function compareNameAnnotationArraysForSorting( - [originalPositionA, arrayA]: [ - number, - Array<[string, CompleteTypeAnnotation]>, - ], - [originalPositionB, arrayB]: [ - number, - Array<[string, CompleteTypeAnnotation]>, - ], -) { - if (arrayA.length - arrayB.length !== 0) { - return arrayA.length - arrayB.length; - } - const nameSortedA = arrayA.sort(nameComparison); - const nameSortedB = arrayB.sort(nameComparison); - for (let i = 0; i < nameSortedA.length; i++) { - if (nameSortedA[i][0] === nameSortedB[i][0]) { - const compared = compareTypeAnnotationForSorting( - [originalPositionA, nameSortedA[i][1]], - [originalPositionB, nameSortedB[i][1]], - ); - if (compared !== 0) { - return compared; - } - continue; - } - if (nameSortedA[i][0] < nameSortedB[i][0]) { - return -1; - } - return 1; - } - return 0; -} - -function compareAnnotationArraysForSorting( - [originalPositionA, arrayA]: [number, $ReadOnlyArray], - [originalPositionB, arrayB]: [number, $ReadOnlyArray], -) { - if (arrayA.length - arrayB.length !== 0) { - return arrayA.length - arrayB.length; - } - for (let i = 0; i < arrayA.length; i++) { - const compared = compareTypeAnnotationForSorting( - [originalPositionA, arrayA[i]], - [originalPositionB, arrayB[i]], - ); - if (compared !== 0) { - return compared; - } - continue; - } - return 0; -} - -function typeAnnotationArbitraryOrder(annotation: CompleteTypeAnnotation) { - switch (annotation.type) { - case 'AnyTypeAnnotation': - return 0; - case 'ArrayTypeAnnotation': - return 1; - case 'BooleanTypeAnnotation': - return 2; - case 'FunctionTypeAnnotation': - return 3; - case 'EventEmitterTypeAnnotation': - return 4; - case 'PromiseTypeAnnotation': - return 5; - case 'GenericObjectTypeAnnotation': - return 6; - case 'NullableTypeAnnotation': - return 9; - case 'NumberTypeAnnotation': - return 10; - case 'Int32TypeAnnotation': - return 11; - case 'DoubleTypeAnnotation': - return 12; - case 'FloatTypeAnnotation': - return 13; - case 'NumberLiteralTypeAnnotation': - return 14; - case 'ObjectTypeAnnotation': - return 15; - case 'StringLiteralUnionTypeAnnotation': - return 17; - case 'StringTypeAnnotation': - return 18; - case 'StringLiteralTypeAnnotation': - return 19; - case 'VoidTypeAnnotation': - return 20; - case 'EnumDeclaration': - return 21; - case 'EnumDeclarationWithMembers': - return 22; - case 'GenericObjectTypeAnnotation': - return 25; - case 'TypeAliasTypeAnnotation': - return 26; - case 'MixedTypeAnnotation': - return 27; - case 'ReservedTypeAnnotation': - return 28; - case 'UnionTypeAnnotation': - return 30; - default: - (annotation.type: empty); - return -1; - } -} diff --git a/packages/react-native-compatibility-check/src/TypeDiffing.js b/packages/react-native-compatibility-check/src/TypeDiffing.js deleted file mode 100644 index abd3310fe1d..00000000000 --- a/packages/react-native-compatibility-check/src/TypeDiffing.js +++ /dev/null @@ -1,1427 +0,0 @@ -/** - * 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 strict-local - * @format - */ - -import type { - ComparisonResult, - FunctionComparisonResult, - MembersComparisonResult, - PropertiesComparisonResult, - TypeComparisonError, -} from './ComparisonResult'; -import type { - CompleteReservedTypeAnnotation, - CompleteTypeAnnotation, - EventEmitterTypeAnnotation, - NamedShape, - NativeModuleAliasMap, - NativeModuleEnumDeclaration, - NativeModuleEnumDeclarationWithMembers, - NativeModuleEnumMap, - NativeModuleEnumMember, - NativeModuleFunctionTypeAnnotation, - NativeModuleGenericObjectTypeAnnotation, - NativeModuleObjectTypeAnnotation, - NativeModulePromiseTypeAnnotation, - NativeModuleTypeAnnotation, - NativeModuleUnionTypeAnnotation, - NullableTypeAnnotation, - NumberLiteralTypeAnnotation, - ObjectTypeAnnotation, - StringLiteralTypeAnnotation, - StringLiteralUnionTypeAnnotation, -} from '@react-native/codegen/src/CodegenSchema'; - -import { - isFunctionLogEmpty, - isMemberLogEmpty, - isPropertyLogEmpty, - makeError, - memberComparisonError, - propertyComparisonError, - typeAnnotationComparisonError, -} from './ComparisonResult'; -import { - compareTypeAnnotationForSorting, - sortTypeAnnotations, -} from './SortTypeAnnotations.js'; -import invariant from 'invariant'; - -const EQUALITY_MSG = 'previousType and afterType differ despite check'; - -// NOTE: These are module scope type lookup registries. Ideally, they should be local arguments, -// however that would require threading them through all the hierarchical calls of type -// annotation processing, which is a lot of boilerplate. Since our logic is serial, having these -// as shared global variables is acceptable. -let _newerTypesReg, _olderTypesReg, _newerEnumMap, _olderEnumMap; - -export function compareTypes( - newerType: CompleteTypeAnnotation, - olderType: ?CompleteTypeAnnotation, - newerTypesReg: ?NativeModuleAliasMap, - olderTypesReg: ?NativeModuleAliasMap, - newerEnumMap: ?NativeModuleEnumMap, - olderEnumMap: ?NativeModuleEnumMap, -): ComparisonResult { - if (!olderType) { - // No matching olderType for newerType, skip the Comparison. - return {status: 'skipped'}; - } - - _newerTypesReg = newerTypesReg; - _olderTypesReg = olderTypesReg; - _newerEnumMap = newerEnumMap; - _olderEnumMap = olderEnumMap; - - const res = compareTypeAnnotation(newerType, olderType); - - _newerTypesReg = undefined; - _olderTypesReg = undefined; - _newerEnumMap = undefined; - _olderEnumMap = undefined; - - return res; -} - -// ??T is the same as ?T so let's remove any superflous annotations -function removeNullableTypeAnnotations( - annotation: - | NativeModuleTypeAnnotation - | NullableTypeAnnotation, -): NativeModuleTypeAnnotation { - // The parser doesn't allow nested nullables - if (annotation.type === 'NullableTypeAnnotation') { - return removeNullableTypeAnnotations(annotation.typeAnnotation); - } - - return annotation; -} - -function lookupType( - name: string, - aliases: ?NativeModuleAliasMap, -): ?NativeModuleObjectTypeAnnotation { - return aliases?.[name]; -} - -function lookupEnum( - name: string, - enums: ?NativeModuleEnumMap, -): ?NativeModuleEnumDeclarationWithMembers { - return enums?.[name]; -} - -export function compareTypeAnnotation( - originalNewerAnnotation: CompleteTypeAnnotation, - originalOlderAnnotation: CompleteTypeAnnotation, -): ComparisonResult { - const newerAnnotation = originalNewerAnnotation; - const olderAnnotation = originalOlderAnnotation; - - // Consider type aliases (generic type annotations with no type parameters) to be compatible - // with the other type, if the underlying type definition is structurally the same - if (newerAnnotation.type === 'TypeAliasTypeAnnotation') { - const newerAnnotationDefinition = lookupType( - newerAnnotation.name, - _newerTypesReg, - ); - if (newerAnnotationDefinition != null) { - return compareTypeAnnotation(newerAnnotationDefinition, olderAnnotation); - } - } - - if (olderAnnotation.type === 'TypeAliasTypeAnnotation') { - const olderAnnotationDefinition = lookupType( - olderAnnotation.name, - _olderTypesReg, - ); - if (olderAnnotationDefinition != null) { - return compareTypeAnnotation(newerAnnotation, olderAnnotationDefinition); - } - } - - invariant( - newerAnnotation.type !== 'TypeAliasTypeAnnotation' && - olderAnnotation.type !== 'TypeAliasTypeAnnotation', - EQUALITY_MSG, - ); - - if (newerAnnotation.type !== olderAnnotation.type) { - if ( - newerAnnotation.type === 'NullableTypeAnnotation' || - olderAnnotation.type === 'NullableTypeAnnotation' - ) { - return compareNullableChange(newerAnnotation, olderAnnotation); - } - - return makeError( - typeAnnotationComparisonError( - 'Type annotations are not the same.', - newerAnnotation, - olderAnnotation, - ), - ); - } - - switch (newerAnnotation.type) { - case 'AnyTypeAnnotation': - case 'MixedTypeAnnotation': - case 'DoubleTypeAnnotation': - case 'FloatTypeAnnotation': - case 'Int32TypeAnnotation': - case 'BooleanTypeAnnotation': - case 'NumberTypeAnnotation': - case 'StringTypeAnnotation': - case 'VoidTypeAnnotation': - return {status: 'matching'}; - case 'ArrayTypeAnnotation': - invariant(olderAnnotation.type === 'ArrayTypeAnnotation', EQUALITY_MSG); - return compareTypeAnnotation( - newerAnnotation.elementType, - olderAnnotation.elementType, - ); - case 'EnumDeclaration': - invariant(olderAnnotation.type === 'EnumDeclaration', EQUALITY_MSG); - return compareEnumDeclarations(newerAnnotation, olderAnnotation); - case 'EnumDeclarationWithMembers': - invariant( - olderAnnotation.type === 'EnumDeclarationWithMembers', - EQUALITY_MSG, - ); - return compareEnumDeclarationWithMembers( - newerAnnotation, - olderAnnotation, - ); - case 'FunctionTypeAnnotation': - invariant( - olderAnnotation.type === 'FunctionTypeAnnotation', - EQUALITY_MSG, - ); - return compareFunctionTypes(newerAnnotation, olderAnnotation); - case 'PromiseTypeAnnotation': - invariant(olderAnnotation.type === 'PromiseTypeAnnotation', EQUALITY_MSG); - - return comparePromiseTypes(newerAnnotation, olderAnnotation); - case 'GenericObjectTypeAnnotation': - invariant( - olderAnnotation.type === 'GenericObjectTypeAnnotation', - EQUALITY_MSG, - ); - - return compareGenericObjectTypes(newerAnnotation, olderAnnotation); - case 'NullableTypeAnnotation': - invariant( - olderAnnotation.type === 'NullableTypeAnnotation', - EQUALITY_MSG, - ); - return compareTypeAnnotation( - newerAnnotation.typeAnnotation, - olderAnnotation.typeAnnotation, - ); - case 'ObjectTypeAnnotation': - invariant(olderAnnotation.type === 'ObjectTypeAnnotation', EQUALITY_MSG); - return compareObjectTypes( - newerAnnotation.properties, - olderAnnotation.properties, - ); - case 'NumberLiteralTypeAnnotation': - invariant( - olderAnnotation.type === 'NumberLiteralTypeAnnotation', - EQUALITY_MSG, - ); - return compareNumberLiteralTypes(newerAnnotation, olderAnnotation); - case 'StringLiteralUnionTypeAnnotation': - invariant( - olderAnnotation.type === 'StringLiteralUnionTypeAnnotation', - EQUALITY_MSG, - ); - return compareStringLiteralUnionTypes(newerAnnotation, olderAnnotation); - case 'StringLiteralTypeAnnotation': - invariant( - olderAnnotation.type === 'StringLiteralTypeAnnotation', - EQUALITY_MSG, - ); - return compareStringLiteralTypes(newerAnnotation, olderAnnotation); - case 'UnionTypeAnnotation': - invariant(olderAnnotation.type === 'UnionTypeAnnotation', EQUALITY_MSG); - return compareUnionTypes(newerAnnotation, olderAnnotation); - case 'EventEmitterTypeAnnotation': - invariant( - olderAnnotation.type === 'EventEmitterTypeAnnotation', - EQUALITY_MSG, - ); - - return compareEventEmitterTypes(newerAnnotation, olderAnnotation); - case 'ReservedTypeAnnotation': - invariant( - olderAnnotation.type === 'ReservedTypeAnnotation', - EQUALITY_MSG, - ); - - return compareReservedTypeAnnotation(newerAnnotation, olderAnnotation); - default: // Flow exhaustiveness check - (newerAnnotation: empty); - throw new Error(`Unsupported type annotation: ${newerAnnotation.type}`); - } -} - -function compareObjectTypeProperty( - first: NamedShape, - second: NamedShape, -): number { - if (first.name < second.name) { - return -1; - } else if (first.name > second.name) { - return 1; - } - return 0; -} - -function compareEnumMember( - first: NativeModuleEnumMember, - second: NativeModuleEnumMember, -) { - if (first.name < second.name) { - return -1; - } else if (first.name > second.name) { - return 1; - } - return 0; -} - -function updatePropertyError( - name: string, - newType: CompleteTypeAnnotation, - oldType: CompleteTypeAnnotation, - result: PropertiesComparisonResult, -) { - return (oldError: TypeComparisonError) => { - const comparisonError = typeAnnotationComparisonError( - 'has conflicting type changes', - newType, - oldType, - oldError, - ); - const newFault = {property: name, fault: comparisonError}; - if (result.errorProperties) { - result.errorProperties.push(newFault); - } else { - result.errorProperties = [newFault]; - } - }; -} - -function updateEnumMemberError( - name: string, - newType: CompleteTypeAnnotation, - oldType: CompleteTypeAnnotation, - result: MembersComparisonResult, -) { - return (oldError: TypeComparisonError) => { - const comparisonError = typeAnnotationComparisonError( - 'has conflicting changes', - newType, - oldType, - oldError, - ); - const newFault = {member: name, fault: comparisonError}; - if (result.errorMembers) { - result.errorMembers.push(newFault); - } else { - result.errorMembers = [newFault]; - } - }; -} - -function updateNestedProperties( - name: string, - propertyChange: ComparisonResult, - result: PropertiesComparisonResult, -) { - if (result.nestedPropertyChanges) { - result.nestedPropertyChanges.push([name, propertyChange]); - } else { - result.nestedPropertyChanges = [[name, propertyChange]]; - } -} - -function updateMadeOptional( - name: string, - result: PropertiesComparisonResult, - furtherChange?: ComparisonResult, -) { - if (result.madeOptional) { - result.madeOptional.push({property: name, furtherChange}); - } else { - result.madeOptional = [{property: name, furtherChange}]; - } -} - -function updateMadeStrict( - name: string, - result: PropertiesComparisonResult, - furtherChange?: ComparisonResult, -) { - if (result.madeStrict) { - result.madeStrict.push({property: name, furtherChange}); - } else { - result.madeStrict = [{property: name, furtherChange}]; - } -} - -function checkOptionalityChanges( - name: string, - newOptionality: boolean, - oldOptionality: boolean, - result: PropertiesComparisonResult, - furtherChange?: ComparisonResult, -): PropertiesComparisonResult { - if (newOptionality === oldOptionality) { - if (furtherChange) { - updateNestedProperties(name, furtherChange, result); - } - return result; - } - if (newOptionality) { - updateMadeOptional(name, result, furtherChange); - } else { - updateMadeStrict(name, result, furtherChange); - } - return result; -} - -function comparePropertyArrays( - newerOriginal: $ReadOnlyArray>, - olderOriginal: $ReadOnlyArray>, -): PropertiesComparisonResult { - const newer = newerOriginal.slice(0); - const older = olderOriginal.slice(0); - if (newer.length === 0 && older.length === 0) { - return {}; - } - if (newer.length === 0) { - return { - missingProperties: older, - }; - } - if (older.length === 0) { - return { - addedProperties: newer, - }; - } - const newerHead = newer.pop(); - const olderHead = older.pop(); - invariant(newerHead != null && olderHead != null, 'Array is empty'); - - const newerName = newerHead.name; - const olderName = olderHead.name; - if (newerName === olderName) { - const comparedTypes = compareTypeAnnotation( - newerHead.typeAnnotation, - - olderHead.typeAnnotation, - ); - const result = comparePropertyArrays(newer, older); - switch (comparedTypes.status) { - case 'matching': - return checkOptionalityChanges( - newerName, - newerHead.optional, - olderHead.optional, - result, - ); - case 'skipped': - throw new Error( - "Internal error: returned 'skipped' for non-optional older type", - ); - case 'nullableChange': - return checkOptionalityChanges( - newerName, - !comparedTypes.nullableLog.optionsReduced, - comparedTypes.nullableLog.optionsReduced, - result, - ); - case 'members': - case 'properties': - case 'functionChange': - case 'positionalTypeChange': - return checkOptionalityChanges( - newerName, - newerHead.optional, - olderHead.optional, - result, - comparedTypes, - ); - case 'error': - updatePropertyError( - newerName, - newerHead.typeAnnotation, - olderHead.typeAnnotation, - result, - )(comparedTypes.errorLog); - return result; - default: - (comparedTypes: empty); - throw new Error('Unsupported status ' + comparedTypes.status); - } - } - // newer property must have been added based on sorting - if (newerName > olderName) { - older.push(olderHead); - const result = comparePropertyArrays(newer, older); - if (result.hasOwnProperty('addedProperties') && result.addedProperties) { - result.addedProperties = result.addedProperties.concat([newerHead]); - } else { - result.addedProperties = [newerHead]; - } - return result; - } - // older property must have been skipped based on sorting - newer.push(newerHead); - const result = comparePropertyArrays(newer, older); - if (result.hasOwnProperty('missingProperties') && result.missingProperties) { - result.missingProperties = result.missingProperties.concat([olderHead]); - } else { - result.missingProperties = [olderHead]; - } - return result; -} - -export function compareObjectTypes( - newerPropertyTypes: $ReadOnlyArray>, - olderPropertyTypes: $ReadOnlyArray>, -): ComparisonResult { - if (newerPropertyTypes.length === 0 && olderPropertyTypes.length === 0) { - return {status: 'matching'}; - } - const sortedNewerTypes = []; - newerPropertyTypes.forEach(prop => sortedNewerTypes.push(prop)); - if (sortedNewerTypes.length !== 0) { - sortedNewerTypes.sort(compareObjectTypeProperty); - } - const sortedOlderTypes = []; - olderPropertyTypes.forEach(prop => sortedOlderTypes.push(prop)); - if (sortedOlderTypes.length !== 0) { - sortedOlderTypes.sort(compareObjectTypeProperty); - } - - if (sortedNewerTypes.length === 0) { - return { - status: 'properties', - propertyLog: {missingProperties: sortedOlderTypes}, - }; - } - if (sortedOlderTypes.length === 0) { - return { - status: 'properties', - propertyLog: {addedProperties: sortedNewerTypes}, - }; - } - const result = comparePropertyArrays(sortedNewerTypes, sortedOlderTypes); - if (isPropertyLogEmpty(result)) { - return {status: 'matching'}; - } - if (result.errorProperties) { - return makeError( - propertyComparisonError( - result.errorProperties.length > 1 - ? 'Object contained properties with type mismatches' - : 'Object contained a property with a type mismatch', - result.errorProperties, - ), - ); - } - if ( - (result.addedProperties && - result.addedProperties.length > 0 && - result.addedProperties.length === newerPropertyTypes.length) || - (result.missingProperties && - result.missingProperties.length > 0 && - result.missingProperties.length === olderPropertyTypes.length) - ) { - return makeError( - typeAnnotationComparisonError( - 'Object types do not match.', - // $FlowFixMe[incompatible-call] - objectTypeAnnotation(newerPropertyTypes), - // $FlowFixMe[incompatible-call] - objectTypeAnnotation(olderPropertyTypes), - ), - ); - } - return {status: 'properties', propertyLog: result}; -} - -function objectTypeAnnotation( - properties: $ReadOnlyArray>, -): ObjectTypeAnnotation { - return { - type: 'ObjectTypeAnnotation', - properties, - baseTypes: [], - }; -} - -export function compareEnumDeclarations( - newerDeclaration: NativeModuleEnumDeclaration, - olderDeclaration: NativeModuleEnumDeclaration, -): ComparisonResult { - if (newerDeclaration.memberType !== olderDeclaration.memberType) { - return makeError( - typeAnnotationComparisonError( - 'EnumDeclaration member types are not the same', - newerDeclaration, - olderDeclaration, - ), - ); - } - - const newerAnnotationDefinition = lookupEnum( - newerDeclaration.name, - _newerEnumMap, - ); - const olderAnnotationDefinition = lookupEnum( - olderDeclaration.name, - _olderEnumMap, - ); - - invariant( - newerAnnotationDefinition != null && olderAnnotationDefinition != null, - 'Could not find enum definition', - ); - - return compareTypeAnnotation( - newerAnnotationDefinition, - olderAnnotationDefinition, - ); -} - -export function compareEnumDeclarationMemberArrays( - newer: Array, - older: Array, -): MembersComparisonResult { - if (newer.length === 0 && older.length === 0) { - return {}; - } else if (newer.length === 0) { - return {missingMembers: older}; - } else if (older.length === 0) { - return {addedMembers: newer}; - } - - const newerHead = newer.pop(); - const olderHead = older.pop(); - invariant(newerHead != null && olderHead != null, 'Array is empty'); - - const newerName = newerHead.name; - const olderName = olderHead.name; - - if (newerName === olderName) { - const comparedTypes = compareTypeAnnotation( - newerHead.value, - olderHead.value, - ); - - const result = compareEnumDeclarationMemberArrays(newer, older); - switch (comparedTypes.status) { - case 'matching': - return result; - case 'error': - updateEnumMemberError( - newerName, - newerHead.value, - olderHead.value, - result, - )(comparedTypes.errorLog); - return result; - case 'skipped': - throw new Error( - "Internal error: returned 'skipped' for non-optional older type", - ); - case 'nullableChange': - case 'properties': - case 'functionChange': - case 'positionalTypeChange': - case 'members': - break; - default: // Flow exhaustiveness check - (comparedTypes: empty); - throw new Error('Unsupported status ' + comparedTypes.status); - } - } else if (newerName > olderName) { - older.push(olderHead); - const result = compareEnumDeclarationMemberArrays(newer, older); - if (result.hasOwnProperty('addedMembers') && result.addedMembers) { - result.addedMembers.push(newerHead); - } else { - result.addedMembers = [newerHead]; - } - return result; - } else if (newerName < olderName) { - newer.push(newerHead); - const result = compareEnumDeclarationMemberArrays(newer, older); - if (result.hasOwnProperty('missingMembers') && result.missingMembers) { - result.missingMembers.push(olderHead); - } else { - result.missingMembers = [olderHead]; - } - return result; - } - - throw new Error('Internal error: should not reach here'); -} - -export function compareEnumDeclarationWithMembers( - newerDeclaration: NativeModuleEnumDeclarationWithMembers, - olderDeclaration: NativeModuleEnumDeclarationWithMembers, -): ComparisonResult { - const sortedNewerTypes = Array.from(newerDeclaration.members).sort( - compareEnumMember, - ); - const sortedOlderTypes = Array.from(olderDeclaration.members).sort( - compareEnumMember, - ); - - const result = compareEnumDeclarationMemberArrays( - sortedNewerTypes, - sortedOlderTypes, - ); - - if (isMemberLogEmpty(result)) { - return {status: 'matching'}; - } else if (result.errorMembers) { - return makeError( - typeAnnotationComparisonError( - 'Enum types do not match', - newerDeclaration, - olderDeclaration, - memberComparisonError( - result.errorMembers.length > 1 - ? 'Enum contained members with type mismatches' - : 'Enum contained a member with a type mismatch', - result.errorMembers, - ), - ), - ); - } else if ( - (result.addedMembers && - result.addedMembers.length > 0 && - result.addedMembers.length === newerDeclaration.members.length) || - (result.missingMembers && - result.missingMembers.length > 0 && - result.missingMembers.length === olderDeclaration.members.length) - ) { - return makeError( - typeAnnotationComparisonError( - 'Enum types do not match.', - newerDeclaration, - olderDeclaration, - ), - ); - } - - return {status: 'members', memberLog: result}; -} - -function compareNullableChange( - newerAnnotation: CompleteTypeAnnotation, - olderAnnotation: CompleteTypeAnnotation, -): ComparisonResult { - const newVoidRemoved = - newerAnnotation.type === 'NullableTypeAnnotation' - ? removeNullableTypeAnnotations(newerAnnotation) - : newerAnnotation; - - const oldVoidRemoved = - olderAnnotation.type === 'NullableTypeAnnotation' - ? removeNullableTypeAnnotations(olderAnnotation) - : olderAnnotation; - - const optionalNew = newVoidRemoved.type !== newerAnnotation.type; - const optionalOld = oldVoidRemoved.type !== olderAnnotation.type; - - invariant( - optionalNew !== optionalOld, - 'compareNullableChange called with both being nullable', - ); - - const optionsReduced = !optionalNew && optionalOld; - if ( - newVoidRemoved.type === 'VoidTypeAnnotation' || - oldVoidRemoved.type === 'VoidTypeAnnotation' - ) { - return { - status: 'nullableChange', - nullableLog: { - typeRefined: true, - optionsReduced, - interiorLog: null, - newType: newerAnnotation, - oldType: olderAnnotation, - }, - }; - } - const interiorLog = compareTypeAnnotation(newVoidRemoved, oldVoidRemoved); - switch (interiorLog.status) { - case 'error': - return makeError( - typeAnnotationComparisonError( - 'Type annotations are not the same.', - newerAnnotation, - olderAnnotation, - ), - ); - case 'matching': - return { - status: 'nullableChange', - nullableLog: { - typeRefined: false, - optionsReduced, - interiorLog, - newType: newerAnnotation, - oldType: olderAnnotation, - }, - }; - default: - return { - status: 'nullableChange', - nullableLog: { - typeRefined: false, - optionsReduced, - interiorLog, - newType: newerAnnotation, - oldType: olderAnnotation, - }, - }; - } -} - -export function compareUnionTypes( - newerType: NativeModuleUnionTypeAnnotation, - olderType: NativeModuleUnionTypeAnnotation, -): ComparisonResult { - if (newerType.memberType !== olderType.memberType) { - return makeError( - typeAnnotationComparisonError( - 'Union member type does not match', - newerType, - olderType, - ), - ); - } - - return {status: 'matching'}; -} - -export function comparePromiseTypes( - newerType: NativeModulePromiseTypeAnnotation, - olderType: NativeModulePromiseTypeAnnotation, -): ComparisonResult { - if (newerType.elementType == null || olderType.elementType == null) { - return makeError( - typeAnnotationComparisonError( - 'Promise has differing arguments', - newerType, - olderType, - ), - ); - } - - invariant( - newerType.elementType != null && olderType.elementType != null, - EQUALITY_MSG, - ); - - return compareTypeAnnotation(newerType.elementType, olderType.elementType); -} - -export function compareGenericObjectTypes( - newerType: NativeModuleGenericObjectTypeAnnotation, - olderType: NativeModuleGenericObjectTypeAnnotation, -): ComparisonResult { - if ( - newerType.dictionaryValueType == null && - olderType.dictionaryValueType == null - ) { - return {status: 'matching'}; - } - - if ( - newerType.dictionaryValueType != null && - olderType.dictionaryValueType != null - ) { - return compareTypeAnnotation( - newerType.dictionaryValueType, - olderType.dictionaryValueType, - ); - } - - return makeError( - typeAnnotationComparisonError( - 'Generic Object types do not have matching dictionary types', - newerType, - olderType, - ), - ); -} - -export function compareNumberLiteralTypes( - newerType: NumberLiteralTypeAnnotation, - olderType: NumberLiteralTypeAnnotation, -): ComparisonResult { - return newerType.value === olderType.value - ? {status: 'matching'} - : makeError( - typeAnnotationComparisonError( - 'Numeric literals are not equal', - newerType, - olderType, - ), - ); -} - -export function compareStringLiteralTypes( - newerType: StringLiteralTypeAnnotation, - olderType: StringLiteralTypeAnnotation, -): ComparisonResult { - return newerType.value === olderType.value - ? {status: 'matching'} - : makeError( - typeAnnotationComparisonError( - 'String literals are not equal', - newerType, - olderType, - ), - ); -} - -export function compareStringLiteralUnionTypes( - newerType: StringLiteralUnionTypeAnnotation, - olderType: StringLiteralUnionTypeAnnotation, -): ComparisonResult { - const results = compareArrayOfTypes( - true, // Fixed order - false, // Can grow/shrink at the end - newerType.types, - olderType.types, - ); - switch (results.status) { - case 'length-mismatch': - throw new Error('length-mismatch returned with length changes allowed'); - case 'type-mismatch': - return makeError( - typeAnnotationComparisonError( - `Subtype of union at position ${results.newIndex} did not match`, - newerType, - olderType, - results.error, - ), - ); - case 'subtypable-changes': - if (results.nestedChanges.length > 0) { - throw new Error( - 'Unexpected inline objects/functions in string literal union', - ); - } - if (results.addedElements.length > 0) { - return { - status: 'positionalTypeChange', - changeLog: { - typeKind: 'stringUnion', - nestedChanges: [], - addedElements: results.addedElements, - }, - }; - } - if (results.removedElements.length > 0) { - return { - status: 'positionalTypeChange', - changeLog: { - typeKind: 'stringUnion', - nestedChanges: [], - removedElements: results.removedElements, - }, - }; - } - console.log(JSON.stringify(results)); - throw new Error('string union returned unexpected set of changes'); - case 'matching': - return {status: 'matching'}; - default: - throw new Error('Unknown status'); - } -} - -export function compareFunctionTypes( - newerType: NativeModuleFunctionTypeAnnotation, - olderType: NativeModuleFunctionTypeAnnotation, -): ComparisonResult { - // Check return types - const returnTypeResult = compareTypeAnnotation( - newerType.returnTypeAnnotation, - olderType.returnTypeAnnotation, - ); - if (returnTypeResult.status === 'error') { - return makeError( - typeAnnotationComparisonError( - 'Function return types do not match', - newerType, - olderType, - returnTypeResult.errorLog, - ), - ); - } - const functionChanges: FunctionComparisonResult = {}; - if ( - returnTypeResult.status === 'properties' || - returnTypeResult.status === 'members' || - returnTypeResult.status === 'functionChange' || - returnTypeResult.status === 'positionalTypeChange' || - returnTypeResult.status === 'nullableChange' - ) { - functionChanges.returnType = returnTypeResult; - } - - // Check argument types - const argumentResults = compareArrayOfTypes( - true, // fixedOrder - true, // fixedLength - newerType.params.map(_ => _.typeAnnotation), - olderType.params.map(_ => _.typeAnnotation), - ); - switch (argumentResults.status) { - case 'length-mismatch': - return makeError( - typeAnnotationComparisonError( - 'Function types have differing length of arguments', - newerType, - olderType, - ), - ); - case 'type-mismatch': - return makeError( - typeAnnotationComparisonError( - `Parameter at index ${argumentResults.newIndex} did not match`, - newerType, - olderType, - argumentResults.error, - ), - ); - case 'subtypable-changes': - functionChanges.parameterTypes = { - typeKind: 'parameter', - nestedChanges: argumentResults.nestedChanges, - }; - break; - case 'matching': - default: - break; - } - - if (isFunctionLogEmpty(functionChanges)) { - return {status: 'matching'}; - } - return {status: 'functionChange', functionChangeLog: functionChanges}; -} - -type ArrayComparisonResult = - | {status: 'matching', ...} - | {status: 'length-mismatch', ...} - | { - status: 'subtypable-changes', - nestedChanges: Array<[number, number, ComparisonResult]>, - addedElements: Array<[number, CompleteTypeAnnotation]>, - removedElements: Array<[number, CompleteTypeAnnotation]>, - ... - } - | { - status: 'type-mismatch', - error: TypeComparisonError, - newIndex: number, - oldIndex: number, - ... - }; - -function compareArrayOfTypes( - fixedOrder: boolean, - fixedLength: boolean, - newerTypes: $ReadOnlyArray, - olderTypes: $ReadOnlyArray, -): ArrayComparisonResult { - const sameLength = newerTypes.length === olderTypes.length; - if (fixedLength && !sameLength) { - return {status: 'length-mismatch'}; - } - const nestedChanges: Array<[number, number, ComparisonResult]> = []; - const minLength = Math.min(newerTypes.length, olderTypes.length); - - if (fixedOrder) { - for (let i = 0; i < minLength; i++) { - const result = compareTypeAnnotation(newerTypes[i], olderTypes[i]); - if (result.status === 'error') { - return { - status: 'type-mismatch', - error: result.errorLog, - newIndex: i, - oldIndex: i, - }; - } - if ( - result.status === 'properties' || - result.status === 'members' || - result.status === 'functionChange' || - result.status === 'positionalTypeChange' || - result.status === 'nullableChange' - ) { - nestedChanges.push([i, i, result]); - } - } - if (nestedChanges.length === 0 && sameLength) { - return {status: 'matching'}; - } - const addedElements: Array<[number, CompleteTypeAnnotation]> = []; - const removedElements: Array<[number, CompleteTypeAnnotation]> = []; - if (newerTypes.length < olderTypes.length) { - const elements = olderTypes.slice(minLength, olderTypes.length); - for (let i = 0; i < elements.length; i++) { - removedElements.push([i + minLength + 1, elements[i]]); - } - } - if (newerTypes.length > olderTypes.length) { - const elements = newerTypes.slice(minLength, newerTypes.length); - for (let i = 0; i < elements.length; i++) { - addedElements.push([i + minLength + 1, elements[i]]); - } - } - return { - status: 'subtypable-changes', - nestedChanges, - addedElements, - removedElements, - }; - } - return compareArrayTypesOutOfOrder( - sortTypeAnnotations(newerTypes), - 0, - sortTypeAnnotations(olderTypes), - 0, - [], - [], - [], - ); -} - -type PotentialErrorOrChange = { - olderPosition: number, - newerPosition: number, - error: TypeComparisonError, - annotation: CompleteTypeAnnotation, - ... -}; - -function compareArrayTypesOutOfOrder( - newerTypes: Array<[number, CompleteTypeAnnotation]>, - newerIndex: number, - olderTypes: Array<[number, CompleteTypeAnnotation]>, - olderIndex: number, - potentiallyAddedElements: Array, - potentiallyRemovedElements: Array, - nestedChanges: Array<[number, number, ComparisonResult]>, -): ArrayComparisonResult { - const newLength = newerTypes.length; - const oldLength = olderTypes.length; - if (newerIndex === newLength || olderIndex === oldLength) { - const [errors, added, removed] = resolvePotentials( - potentiallyAddedElements, - potentiallyRemovedElements, - ); - if (errors.length !== 0) { - // Return the first error, others might be dubious - return { - status: 'type-mismatch', - error: errors[0][0], - oldIndex: errors[0][1], - newIndex: errors[0][2], - }; - } - if ( - added.length === 0 && - removed.length === 0 && - nestedChanges.length === 0 && - newerIndex === newLength && - olderIndex === oldLength - ) { - return {status: 'matching'}; - } - if (newerIndex === newLength && olderIndex === oldLength) { - return { - status: 'subtypable-changes', - nestedChanges, - addedElements: added, - removedElements: removed, - }; - } - if (newerIndex === newLength) { - return { - status: 'subtypable-changes', - nestedChanges, - addedElements: added, - removedElements: removed.concat( - olderTypes.slice(olderIndex, oldLength), - ), - }; - } - // By elimination (olderIndex === oldLength) - return { - status: 'subtypable-changes', - nestedChanges, - addedElements: added.concat(newerTypes.slice(newerIndex, newLength)), - removedElements: removed, - }; - } - const newTypePosn = newerTypes[newerIndex][0]; - const newType = newerTypes[newerIndex][1]; - const oldTypePosn = olderTypes[olderIndex][0]; - const oldType = olderTypes[olderIndex][1]; - const currentResult = compareTypeAnnotation(newType, oldType); - const sortComparison = compareTypeAnnotationForSorting( - newerTypes[newerIndex], - olderTypes[olderIndex], - ); - switch (currentResult.status) { - case 'matching': - return compareArrayTypesOutOfOrder( - newerTypes, - newerIndex + 1, - olderTypes, - olderIndex + 1, - potentiallyAddedElements, - potentiallyRemovedElements, - nestedChanges, - ); - case 'properties': - case 'functionChange': - case 'positionalTypeChange': - case 'nullableChange': - // The match was sufficiently close so move to the next items - return compareArrayTypesOutOfOrder( - newerTypes, - newerIndex + 1, - olderTypes, - olderIndex + 1, - potentiallyAddedElements, - potentiallyRemovedElements, - // I'm not sure how I should fix this FlowFixMe. It returns `undefined` - // and has existed since the day it was written. Fixing it might break things. - // $FlowFixMe[method-unbinding] added when improving typing for this parameters - nestedChanges.concat[[oldTypePosn, newTypePosn, currentResult]], - ); - case 'error': - // This case seems impossible, but if it happens there was ceratinly an error - if (sortComparison === 0) { - return { - status: 'type-mismatch', - error: currentResult.errorLog, - newIndex: newTypePosn, - oldIndex: oldTypePosn, - }; - } - // A matching newerType should have appeared in the sorted list by now - // So either added or an error - if (sortComparison < 0) { - return compareArrayTypesOutOfOrder( - newerTypes, - newerIndex + 1, - olderTypes, - olderIndex, - potentiallyAddedElements.concat([ - { - olderPosition: oldTypePosn, - newerPosition: newTypePosn, - error: currentResult.errorLog, - annotation: newType, - }, - ]), - potentiallyRemovedElements, - nestedChanges, - ); - } - // Else a matching olderType should have appeared in the sorted arrays - // So either error or removed - return compareArrayTypesOutOfOrder( - newerTypes, - newerIndex, - olderTypes, - olderIndex + 1, - potentiallyAddedElements, - potentiallyRemovedElements.concat([ - { - olderPosition: oldTypePosn, - newerPosition: newTypePosn, - error: currentResult.errorLog, - annotation: oldType, - }, - ]), - nestedChanges, - ); - case 'skipped': - throw new Error( - 'Unexpected skipped status for array of type annotations', - ); - default: - throw new Error('Unsupported status ' + currentResult.status); - } -} - -function resolvePotentials( - potentiallyAdded: Array, - potentiallyRemoved: Array, -): [ - Array<[TypeComparisonError, number, number]>, - Array<[number, CompleteTypeAnnotation]>, - Array<[number, CompleteTypeAnnotation]>, -] { - const addedLength = potentiallyAdded.length; - const removedLength = potentiallyRemoved.length; - if (addedLength === 0 && removedLength === 0) { - return [[], [], []]; - } - if (addedLength === 0) { - return [ - [], - [], - potentiallyRemoved.map(removed => [ - removed.olderPosition, - removed.annotation, - ]), - ]; - } - if (removedLength === 0) { - return [ - [], - potentiallyAdded.map(added => [added.newerPosition, added.annotation]), - [], - ]; - } - const addedHead = potentiallyAdded[0]; - const removedHead = potentiallyRemoved[0]; - // Found added when looking for a match to removed, - // Didn't find a match for removed after skipping added - // So an add and a remove is more likely a mismatch - if (addedHead.olderPosition === removedHead.olderPosition) { - return [ - [[addedHead.error, addedHead.olderPosition, addedHead.newerPosition]], - [], - [], - ]; - } - // Found removed when looking for a match to added, didn't find after skipping - if (removedHead.newerPosition === addedHead.newerPosition) { - return [ - [ - [ - removedHead.error, - removedHead.olderPosition, - removedHead.newerPosition, - ], - ], - [], - [], - ]; - } - // Current added and current removed heads aren't the same erroneousItems - const sortedOrder = compareTypeAnnotationForSorting( - [addedHead.newerPosition, addedHead.annotation], - [removedHead.olderPosition, removedHead.annotation], - ); - // Odd but possible, step down both - if (sortedOrder === 0) { - const [errors, added, removed] = resolvePotentials( - potentiallyAdded.slice(1, addedLength), - potentiallyRemoved.slice(1, removedLength), - ); - return [ - errors, - added.concat([[addedHead.newerPosition, addedHead.annotation]]), - removed.concat([[removedHead.olderPosition, removedHead.annotation]]), - ]; - } - if (sortedOrder < 0) { - const [errors, added, removed] = resolvePotentials( - potentiallyAdded.slice(1, addedLength), - potentiallyRemoved, - ); - return [ - errors, - added.concat([[addedHead.newerPosition, addedHead.annotation]]), - removed, - ]; - } - - const [errors, added, removed] = resolvePotentials( - potentiallyAdded, - potentiallyRemoved.slice(1, removedLength), - ); - return [ - errors, - added, - removed.concat([[removedHead.olderPosition, removedHead.annotation]]), - ]; -} - -function compareEventEmitterTypes( - newerAnnotation: EventEmitterTypeAnnotation, - olderAnnotation: EventEmitterTypeAnnotation, -): ComparisonResult { - const comparison = compareTypeAnnotation( - newerAnnotation.typeAnnotation, - olderAnnotation.typeAnnotation, - ); - - if (comparison.status === 'error') { - return makeError( - typeAnnotationComparisonError( - 'EventEmitter eventTypes are not equivalent', - newerAnnotation, - olderAnnotation, - comparison.errorLog, - ), - ); - } - - return comparison; -} - -function compareReservedTypeAnnotation( - newerAnnotation: CompleteReservedTypeAnnotation, - olderAnnotation: CompleteReservedTypeAnnotation, -): ComparisonResult { - if (newerAnnotation.name !== olderAnnotation.name) { - return makeError( - typeAnnotationComparisonError( - 'Types are not equivalent', - newerAnnotation, - olderAnnotation, - ), - ); - } - - switch (newerAnnotation.name) { - case 'RootTag': - case 'ColorPrimitive': - case 'ImageSourcePrimitive': - case 'PointPrimitive': - case 'EdgeInsetsPrimitive': - case 'ImageRequestPrimitive': - case 'DimensionPrimitive': - return {status: 'matching'}; - default: - (newerAnnotation.name: empty); - throw new Error('Unknown reserved type ' + newerAnnotation.name); - } -} diff --git a/packages/react-native-compatibility-check/src/VersionDiffing.js b/packages/react-native-compatibility-check/src/VersionDiffing.js deleted file mode 100644 index 93664a18f20..00000000000 --- a/packages/react-native-compatibility-check/src/VersionDiffing.js +++ /dev/null @@ -1,1370 +0,0 @@ -/** - * 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 - * @format - */ - -import type { - ComparisonResult, - FunctionComparisonResult, - MembersComparisonResult, - NullableComparisonResult, - PositionalComparisonResult, - PropertiesComparisonResult, -} from './ComparisonResult'; -import type { - DiffSet, - DiffSummary, - ErrorCode, - ErrorStore, - IncompatiblityReport, - NativeSpecErrorStore, - ObjectTypeChangeStore, - SchemaDiff, -} from './DiffResults'; -import type { - CompleteTypeAnnotation, - ComponentSchema, - NamedShape, - NativeModuleSchema, - SchemaType, -} from '@react-native/codegen/src/CodegenSchema'; - -import { - memberComparisonError, - positionalComparisonError, - propertyComparisonError, - typeAnnotationComparisonError, - typeInformationComparisonError, -} from './ComparisonResult.js'; -import convertPropToBasicTypes from './convertPropToBasicTypes'; -import * as codegenTypeDiffing from './TypeDiffing'; - -type BoundaryDirection = 'toNative' | 'fromNative' | 'both'; - -type checkerType = ( - propertyChange: ?PropertiesComparisonResult, - positionalChange: ?PositionalComparisonResult, - nullableChange: ?NullableComparisonResult, - memberChange: ?MembersComparisonResult, - typeName: string, -) => Array; - -function nestedPropertiesCheck( - typeName: string, - result: ComparisonResult, - check: checkerType, - inverseCheck: checkerType, -): Array { - const nestedMap = - (mid: string, end: string) => - /* $FlowFixMe[missing-local-annot] The type annotation(s) required by - * Flow's LTI update could not be added via codemod */ - ([propertyName, comparisonResult]) => - nestedPropertiesCheck( - typeName + mid + propertyName + end, - comparisonResult, - check, - inverseCheck, - ); - switch (result.status) { - case 'error': - case 'matching': - case 'skipped': - throw new Error( - 'Internal error: nested property change ' + result.status, - ); - case 'properties': - let finalResult = check(result.propertyLog, null, null, null, typeName); - if (result.propertyLog.nestedPropertyChanges) { - finalResult = combine( - finalResult, - result.propertyLog.nestedPropertyChanges.map(nestedMap('.', '')), - ); - } - if (result.propertyLog.madeOptional) { - const furtherNestedProps = result.propertyLog.madeOptional.filter( - optionalProp => optionalProp.furtherChanges, - ); - if (furtherNestedProps && furtherNestedProps.length > 0) { - const localNestedMap = nestedMap('.', ''); - const mappedProps = furtherNestedProps.map(optionalProp => { - if (optionalProp.furtherChanges) { - return localNestedMap([ - optionalProp.property, - optionalProp.furtherChanges, - ]); - } - throw new Error('Internal error, filter failed'); - }); - finalResult = combine(finalResult, mappedProps); - } - } - return finalResult; - case 'members': - return check(null, null, null, result.memberLog, typeName); - case 'functionChange': - let returnTypeResult: Array = []; - if (result.functionChangeLog.returnType) { - returnTypeResult = nestedPropertiesCheck( - typeName, - result.functionChangeLog.returnType, - check, - inverseCheck, - ); - } - if (result.functionChangeLog.parameterTypes) { - return combine( - returnTypeResult, - result.functionChangeLog.parameterTypes.nestedChanges.map( - ([_oldParameterNumber, newParameterNumber, comparisonResult]) => - nestedPropertiesCheck( - typeName + ' parameter ' + newParameterNumber, - comparisonResult, - inverseCheck, - check, - ), - ), - ); - } - return returnTypeResult; - case 'positionalTypeChange': - const changeLog = result.changeLog; - const currentPositionalCheck = check( - null, - changeLog, - null, - null, - typeName, - ); - return combine( - currentPositionalCheck, - changeLog.nestedChanges.map(([_oldIndex, newIndex, nestedChange]) => - nestedMap( - ' element ', - ' of ' + changeLog.typeKind, - )([newIndex.toString(), nestedChange]), - ), - ); - case 'nullableChange': - const currentCheck = check( - null, - null, - result.nullableLog, - null, - typeName, - ); - if (result.nullableLog.interiorLog) { - const interiorLog = result.nullableLog.interiorLog; - switch (interiorLog.status) { - case 'matching': - return currentCheck; - case 'properties': - case 'functionChange': - case 'positionalTypeChange': - case 'nullableChange': - return combine(currentCheck, [ - nestedPropertiesCheck(typeName, interiorLog, check, inverseCheck), - ]); - default: - throw new Error( - 'Internal error: nested with error or skipped status', - ); - } - } - return currentCheck; - default: - (result.status: empty); - return []; - } -} - -function checkOptionalityAndSetError( - typeName: string, - properties: $ReadOnlyArray>, - msg: string, - errorCode: ErrorCode, -): Array { - const requiredProperties = properties.filter( - objectTypeProperty => !objectTypeProperty.optional, - ); - if (requiredProperties.length > 0) { - return [ - { - typeName, - errorCode, - errorInformation: propertyComparisonError( - msg, - requiredProperties.map(property => ({ - property: property.name, - })), - ), - }, - ]; - } - return []; -} - -// Exported for testing -export const removedPropertiesMessage = - 'Object removed required properties expected by native'; -function checkForUnsafeRemovedProperties( - propertyChange: ?PropertiesComparisonResult, - _postionalChange: ?PositionalComparisonResult, - _nullableChange: ?NullableComparisonResult, - _memberChange: ?MembersComparisonResult, - typeName: string, -): Array { - if (propertyChange && propertyChange.missingProperties) { - return checkOptionalityAndSetError( - typeName, - propertyChange.missingProperties, - removedPropertiesMessage, - 'removedProps', - ); - } - return []; -} - -export const addedPropertiesMessage = - 'Object added required properties, which native will not provide'; -function checkForUnsafeAddedProperties( - propertyChange: ?PropertiesComparisonResult, - _positionalChange: ?PositionalComparisonResult, - _nullableChange: ?NullableComparisonResult, - _memberChange: ?MembersComparisonResult, - typeName: string, -): Array { - if (propertyChange && propertyChange.addedProperties) { - return checkOptionalityAndSetError( - typeName, - propertyChange.addedProperties, - addedPropertiesMessage, - 'addedProps', - ); - } - return []; -} - -export const stricterPropertiesMessage = - 'Property made strict, but native may not provide it'; -function checkForUnSafeMadeStrictProperties( - propertyChange: ?PropertiesComparisonResult, - _positionalChange: ?PositionalComparisonResult, - _nullableChange: ?NullableComparisonResult, - _memberChange: ?MembersComparisonResult, - typeName: string, -): Array { - if ( - propertyChange && - propertyChange.madeStrict && - propertyChange.madeStrict.length > 0 - ) { - const err = propertyComparisonError( - stricterPropertiesMessage, - propertyChange.madeStrict.map(property => ({ - property: property.property, - })), - ); - return [ - { - typeName, - errorCode: 'requiredProps', - errorInformation: err, - }, - ]; - } - return []; -} - -export const tooOptionalPropertiesMessage = - 'Property made optional, but native requires it'; -function checkForUnSafeMadeOptionalProperties( - propertyChange: ?PropertiesComparisonResult, - _positionalChange: ?PositionalComparisonResult, - _nullableChange: ?NullableComparisonResult, - _memberChange: ?MembersComparisonResult, - typeName: string, -): Array { - if ( - propertyChange && - propertyChange.madeOptional && - propertyChange.madeOptional.length > 0 - ) { - const err = propertyComparisonError( - tooOptionalPropertiesMessage, - propertyChange.madeOptional.map(property => ({ - property: property.property, - })), - ); - return [ - { - typeName, - errorCode: 'optionalProps', - errorInformation: err, - }, - ]; - } - return []; -} - -export const removedUnionMessage = - 'Union removed items, but native may still provide them'; -function checkForUnsafeRemovedUnionItems( - _propertyChange: ?PropertiesComparisonResult, - positionalChange: ?PositionalComparisonResult, - _nullableChange: ?NullableComparisonResult, - _memberChange: ?MembersComparisonResult, - typeName: string, -): Array { - if ( - positionalChange && - (positionalChange.typeKind === 'union' || - positionalChange.typeKind === 'stringUnion') && - positionalChange.removedElements && - positionalChange.removedElements.length > 0 - ) { - return [ - { - typeName, - errorCode: 'removedUnionCases', - errorInformation: positionalComparisonError( - removedUnionMessage, - positionalChange.removedElements, - ), - }, - ]; - } - return []; -} - -export const addedUnionMessage = - 'Union added items, but native will not expect/support them'; -function checkForUnsafeAddedUnionItems( - _propertyChange: ?PropertiesComparisonResult, - positionalChange: ?PositionalComparisonResult, - _nullableChange: ?NullableComparisonResult, - _memberChange: ?MembersComparisonResult, - typeName: string, -): Array { - if ( - positionalChange && - (positionalChange.typeKind === 'union' || - positionalChange.typeKind === 'stringUnion') && - positionalChange.addedElements && - positionalChange.addedElements.length > 0 - ) { - return [ - { - typeName, - errorCode: 'addedUnionCases', - errorInformation: positionalComparisonError( - addedUnionMessage, - positionalChange.addedElements, - ), - }, - ]; - } - return []; -} - -export const removedEnumMessage = - 'Enum removed items, but native may still provide them'; -function checkForUnsafeRemovedEnumItems( - _propertyChange: ?PropertiesComparisonResult, - _positionalChange: ?PositionalComparisonResult, - _nullableChange: ?NullableComparisonResult, - memberChange: ?MembersComparisonResult, - typeName: string, -): Array { - if (memberChange?.missingMembers && memberChange?.missingMembers.length > 0) { - return [ - { - typeName, - errorCode: 'removedEnumCases', - errorInformation: memberComparisonError( - removedEnumMessage, - memberChange.missingMembers.map(member => ({ - member: member.name, - })), - ), - }, - ]; - } - - return []; -} - -export const addedEnumMessage = - 'Enum added items, but native will not expect/support them'; -function checkForUnsafeAddedEnumItems( - _propertyChange: ?PropertiesComparisonResult, - _positionalChange: ?PositionalComparisonResult, - _nullableChange: ?NullableComparisonResult, - memberChange: ?MembersComparisonResult, - typeName: string, -): Array { - if (memberChange?.addedMembers && memberChange?.addedMembers.length > 0) { - return [ - { - typeName, - errorCode: 'addedEnumCases', - errorInformation: memberComparisonError( - addedEnumMessage, - memberChange.addedMembers.map(member => ({ - member: member.name, - })), - ), - }, - ]; - } - - return []; -} - -export const removedIntersectionMessage = - 'Intersection removed items, but native may still require properties contained in them'; -function checkForUnsafeRemovedIntersectionItems( - _propertyChange: ?PropertiesComparisonResult, - positionalChange: ?PositionalComparisonResult, - _nullableChange: ?NullableComparisonResult, - _memberChange: ?MembersComparisonResult, - typeName: string, -): Array { - if ( - positionalChange && - positionalChange.typeKind === 'intersection' && - positionalChange.removedElements && - positionalChange.removedElements.length > 0 - ) { - return [ - { - typeName, - errorCode: 'removedIntersectCases', - errorInformation: positionalComparisonError( - removedIntersectionMessage, - positionalChange.removedElements, - ), - }, - ]; - } - return []; -} - -export const addedIntersectionMessage = - 'Intersection added items, but native may not provide all required attributes'; -function checkForUnsafeAddedIntersectionItems( - _propertyChange: ?PropertiesComparisonResult, - positionalChange: ?PositionalComparisonResult, - _nullableChange: ?NullableComparisonResult, - _memberChange: ?MembersComparisonResult, - typeName: string, -): Array { - if ( - positionalChange && - positionalChange.typeKind === 'intersection' && - positionalChange.addedElements && - positionalChange.addedElements.length > 0 - ) { - return [ - { - typeName, - errorCode: 'addedIntersectCases', - errorInformation: positionalComparisonError( - addedIntersectionMessage, - positionalChange.addedElements, - ), - }, - ]; - } - return []; -} - -export const toNativeVoidChangeMessage = - 'Native may not be able to safely handle presence of type'; -export const typeNullableChangeMessage = - 'Type made nullable, but native requires it'; -function checkForUnsafeNullableToNativeChange( - _propertyChange: ?PropertiesComparisonResult, - _positionalChange: ?PositionalComparisonResult, - nullableChange: ?NullableComparisonResult, - _memberChange: ?MembersComparisonResult, - typeName: string, -): Array { - if ( - nullableChange && - !nullableChange.optionsReduced && - nullableChange.newType && - nullableChange.oldType - ) { - return [ - { - typeName, - errorCode: 'nullableOfNonNull', - errorInformation: typeAnnotationComparisonError( - nullableChange.typeRefined - ? toNativeVoidChangeMessage - : typeNullableChangeMessage, - nullableChange.newType, - nullableChange.oldType, - ), - }, - ]; - } - return []; -} - -export const fromNativeVoidChangeMessage = - 'Type set to void but native may still provide a value'; -export const typeNonNullableChangeMessage = - 'Type made non-nullable, but native might provide null still'; -function checkForUnsafeNullableFromNativeChange( - _propertyChange: ?PropertiesComparisonResult, - _positionalChange: ?PositionalComparisonResult, - nullableChange: ?NullableComparisonResult, - _memberChange: ?MembersComparisonResult, - typeName: string, -): Array { - if ( - nullableChange && - nullableChange.optionsReduced && - nullableChange.newType && - nullableChange.oldType - ) { - return [ - { - typeName, - errorCode: 'nonNullableOfNull', - errorInformation: typeAnnotationComparisonError( - nullableChange.typeRefined - ? fromNativeVoidChangeMessage - : typeNonNullableChangeMessage, - nullableChange.newType, - nullableChange.oldType, - ), - }, - ]; - } - return []; -} - -function chainPropertiesChecks(checks: Array): checkerType { - return ( - propertyChange: ?PropertiesComparisonResult, - positionalChange: ?PositionalComparisonResult, - nullableChange: ?NullableComparisonResult, - memberChange: ?MembersComparisonResult, - typeName: string, - ) => - checks.reduce( - (errorStore, checker) => - errorStore.concat( - checker( - propertyChange, - positionalChange, - nullableChange, - memberChange, - typeName, - ), - ), - [], - ); -} - -function combine( - singleton: Array, - arrayOf: Array>, -) { - if (arrayOf.length > 0) { - return arrayOf.reduce( - (finalErrorArray, current) => finalErrorArray.concat(current), - singleton, - ); - } - return singleton; -} - -function compareFunctionTypesInContext( - typeName: string, - functionLog: FunctionComparisonResult, - check: checkerType, - inversecheck: checkerType, - result: Array, -) { - if (functionLog.returnType) { - result = combine(result, [ - nestedPropertiesCheck( - typeName, - functionLog.returnType, - check, - inversecheck, - ), - ]); - } - if ( - functionLog.parameterTypes && - functionLog.parameterTypes.nestedChanges.length > 0 - ) { - result = combine( - result, - functionLog.parameterTypes.nestedChanges.map( - ([_oldPropertyNum, newPropertyNum, comparisonResult]) => - nestedPropertiesCheck( - typeName + ' parameter ' + newPropertyNum, - comparisonResult, - inversecheck, - check, - ), - ), - ); - } - return result; -} - -// Deleting optional properties is safe and -// Making required properties optional is unsafe. -// Adding to unions and enums is unsafe, as is removing from intersections -// Changing nullable is similar to changing a union -const checksForTypesFlowingToNative: checkerType = chainPropertiesChecks([ - checkForUnsafeRemovedProperties, - checkForUnSafeMadeOptionalProperties, - checkForUnsafeAddedUnionItems, - checkForUnsafeAddedEnumItems, - checkForUnsafeRemovedIntersectionItems, - checkForUnsafeNullableToNativeChange, -]); -// Adding optional properties is safe, otherwise incompatible -// Making optional properties required is unsafe. -// Removing from unions and enums is unsafe, as is adding to intersections -// Changing nullable is similar to changing a union -const checksForTypesFlowingFromNative: checkerType = chainPropertiesChecks([ - checkForUnsafeAddedProperties, - checkForUnSafeMadeStrictProperties, - checkForUnsafeRemovedUnionItems, - checkForUnsafeRemovedEnumItems, - checkForUnsafeAddedIntersectionItems, - checkForUnsafeNullableFromNativeChange, -]); -export function assessComparisonResult( - newTypes: Set<{ - typeName: string, - typeInformation: CompleteTypeAnnotation, - ... - }>, - deprecatedTypes: Set<{ - typeName: string, - typeInformation: CompleteTypeAnnotation, - ... - }>, - incompatibleChanges: Set, - objectTypeChanges: Set, -): ( - typeName: string, - newType: CompleteTypeAnnotation, - oldType: ?CompleteTypeAnnotation, - difference: ComparisonResult, - oldDirection: BoundaryDirection, -) => void { - return ( - typeName: string, - newType: CompleteTypeAnnotation, - oldType: ?CompleteTypeAnnotation, - difference: ComparisonResult, - oldDirection: BoundaryDirection, - ) => { - switch (difference.status) { - case 'matching': - break; - case 'skipped': - newTypes.add({ - typeName, - typeInformation: newType, - }); - break; - case 'members': - { - const memberChange = difference.memberLog; - - const toNativeErrorResult = checksForTypesFlowingToNative( - null, - null, - null, - memberChange, - typeName, - ); - - const fromNativeErrorResult = checksForTypesFlowingFromNative( - null, - null, - null, - memberChange, - typeName, - ); - - switch (oldDirection) { - case 'toNative': - toNativeErrorResult.forEach(error => - incompatibleChanges.add(error), - ); - break; - case 'fromNative': - fromNativeErrorResult.forEach(error => - incompatibleChanges.add(error), - ); - break; - case 'both': - toNativeErrorResult.forEach(error => - incompatibleChanges.add(error), - ); - fromNativeErrorResult.forEach(error => - incompatibleChanges.add(error), - ); - break; - } - } - break; - case 'properties': - const propertyChange = difference.propertyLog; - const unsafeForToNative = nestedPropertiesCheck( - typeName, - difference, - checksForTypesFlowingToNative, - checksForTypesFlowingFromNative, - ); - const unsafeForFromNative = nestedPropertiesCheck( - typeName, - difference, - checksForTypesFlowingFromNative, - checksForTypesFlowingToNative, - ); - - switch (oldDirection) { - case 'toNative': - unsafeForToNative.forEach(error => incompatibleChanges.add(error)); - break; - case 'fromNative': - unsafeForFromNative.forEach(error => - incompatibleChanges.add(error), - ); - break; - case 'both': - unsafeForToNative.forEach(error => incompatibleChanges.add(error)); - unsafeForFromNative.forEach(error => - incompatibleChanges.add(error), - ); - break; - } - - if (!oldType) { - throw new Error('Internal error: properties change with no old type'); - } - objectTypeChanges.add({ - typeName, - newType, - oldType, - propertyChange, - }); - break; - case 'error': - incompatibleChanges.add({ - typeName, - errorCode: 'incompatibleTypes', - errorInformation: difference.errorLog, - }); - break; - case 'functionChange': - const functionLog = difference.functionChangeLog; - let propertyErrors: Array = []; - switch (oldDirection) { - case 'toNative': - propertyErrors = compareFunctionTypesInContext( - typeName, - functionLog, - checksForTypesFlowingToNative, - checksForTypesFlowingFromNative, - propertyErrors, - ); - break; - case 'fromNative': - propertyErrors = compareFunctionTypesInContext( - typeName, - functionLog, - checksForTypesFlowingFromNative, - checksForTypesFlowingToNative, - propertyErrors, - ); - break; - case 'both': - propertyErrors = compareFunctionTypesInContext( - typeName, - functionLog, - checksForTypesFlowingToNative, - checksForTypesFlowingFromNative, - propertyErrors, - ); - propertyErrors = compareFunctionTypesInContext( - typeName, - functionLog, - checksForTypesFlowingFromNative, - checksForTypesFlowingToNative, - propertyErrors, - ); - break; - default: - (oldDirection: empty); - throw new Error( - 'Unsupported native boundary direction ' + oldDirection, - ); - } - propertyErrors.forEach(error => incompatibleChanges.add(error)); - break; - case 'positionalTypeChange': - const changeLog = difference.changeLog; - if ( - changeLog.nestedChanges.length > 0 || - changeLog.addedElements || - changeLog.removedElements - ) { - const changes = changeLog.nestedChanges; - const toNativeBase = checksForTypesFlowingToNative( - null, - changeLog, - null, - null, - typeName, - ); - const toNativeResult = combine( - toNativeBase, - changes.map(([_oldIndex, newIndex, comparisonResult]) => - nestedPropertiesCheck( - `${typeName} element ${newIndex} of ${changeLog.typeKind}`, - comparisonResult, - checksForTypesFlowingToNative, - checksForTypesFlowingFromNative, - ), - ), - ); - const fromNativeBase = checksForTypesFlowingFromNative( - null, - changeLog, - null, - null, - typeName, - ); - const fromNativeResult = combine( - fromNativeBase, - changes.map(([_oldIndex, newIndex, comparisonResult]) => - nestedPropertiesCheck( - `${typeName} element ${newIndex} of ${changeLog.typeKind}`, - comparisonResult, - checksForTypesFlowingFromNative, - checksForTypesFlowingToNative, - ), - ), - ); - switch (oldDirection) { - case 'toNative': - toNativeResult.forEach(error => incompatibleChanges.add(error)); - break; - case 'fromNative': - fromNativeResult.forEach(error => incompatibleChanges.add(error)); - break; - case 'both': - toNativeResult.forEach(error => incompatibleChanges.add(error)); - fromNativeResult.forEach(error => incompatibleChanges.add(error)); - break; - } - } - break; - case 'nullableChange': - if (!oldType) { - throw new Error( - 'Internal error: old type null or undefined, after nullableChange', - ); - } - switch (oldDirection) { - case 'toNative': - checkForUnsafeNullableToNativeChange( - null, - null, - difference.nullableLog, - null, - typeName, - ).forEach(error => incompatibleChanges.add(error)); - break; - case 'fromNative': - checkForUnsafeNullableFromNativeChange( - null, - null, - difference.nullableLog, - null, - typeName, - ).forEach(error => incompatibleChanges.add(error)); - break; - case 'both': - const err = typeInformationComparisonError( - 'Type may not change nullability, due to flowing to and from native', - newType, - oldType, - ); - incompatibleChanges.add({ - typeName, - errorCode: 'incompatibleTypes', - errorInformation: err, - }); - break; - default: - (oldDirection: empty); - throw new Error('Unknown direction : ' + oldDirection); - } - /* $FlowFixMe[prop-missing] (>=0.68.0 site=react_native_fb) This - * comment suppresses an error found when Flow v0.68 was deployed. To - * see the error delete this comment and run Flow. */ - if (difference.interiorLog) { - const log = difference.interiorLog; - assessComparisonResult( - newTypes, - deprecatedTypes, - incompatibleChanges, - objectTypeChanges, - )(typeName, newType, oldType, log, oldDirection); - } - break; - default: - (difference.status: empty); - throw new Error('Unsupported status: ' + difference.status); - } - }; -} - -function buildNativeModulesDiff( - newerNativeModule: NativeModuleSchema, - olderNativeModule: NativeModuleSchema, -): Set { - const moduleErrors = new Set(); - - const nativeModuleName = newerNativeModule.moduleName; - if (olderNativeModule.moduleName !== newerNativeModule.moduleName) { - // old was removed - moduleErrors.add({ - nativeSpecName: olderNativeModule.moduleName, - omitted: true, - errorCode: 'removedModule', - }); - } - - const newTypes = new Set<{ - typeInformation: CompleteTypeAnnotation, - typeName: string, - ... - }>(); - const deprecatedTypes = new Set<{ - typeInformation: CompleteTypeAnnotation, - typeName: string, - ... - }>(); - const incompatibleChanges = new Set(); - const objectTypeChanges = new Set(); - const localAssessComparison = assessComparisonResult( - newTypes, - deprecatedTypes, - incompatibleChanges, - objectTypeChanges, - ); - - const newType = { - type: 'ObjectTypeAnnotation', - properties: [ - ...newerNativeModule.spec.methods, - ...newerNativeModule.spec.eventEmitters, - ], - }; - const oldType = { - type: 'ObjectTypeAnnotation', - properties: [ - ...olderNativeModule.spec.methods, - ...olderNativeModule.spec.eventEmitters, - ], - }; - - const difference = codegenTypeDiffing.compareTypes( - newType, - olderNativeModule.moduleName === newerNativeModule.moduleName - ? oldType - : null, - newerNativeModule.aliasMap, - olderNativeModule.aliasMap, - newerNativeModule.enumMap, - olderNativeModule.enumMap, - ); - - localAssessComparison( - nativeModuleName, - newType, - oldType, - difference, - // Since we are explicitly checking the native module, we know it is starting as fromNative - 'fromNative', - ); - - const typeUpdate = { - newTypes, - deprecatedTypes, - incompatibleChanges, - objectTypeChanges, - }; - if (hasCodegenUpdatesTypes(typeUpdate)) { - moduleErrors.add({ - nativeSpecName: nativeModuleName, - omitted: false, - errorCode: 'incompatibleTypes', - changeInformation: typeUpdate, - }); - } - - return moduleErrors; -} - -function buildNativeComponentsDiff( - newerNativeSchema: ComponentSchema, - olderNativeSchema: ComponentSchema, -): Set { - const componentErrors = new Set(); - - Object.entries(newerNativeSchema.components).forEach( - ([newerComponentName, newerComponent]) => { - const olderComponent = olderNativeSchema.components[newerComponentName]; - - const newTypes = new Set<{ - typeInformation: CompleteTypeAnnotation, - typeName: string, - ... - }>(); - const deprecatedTypes = new Set<{ - typeInformation: CompleteTypeAnnotation, - typeName: string, - ... - }>(); - const incompatibleChanges = new Set(); - const objectTypeChanges = new Set(); - const localAssessComparison = assessComparisonResult( - newTypes, - deprecatedTypes, - incompatibleChanges, - objectTypeChanges, - ); - - /* Commands */ - // We are intentionally allowing new commands to be added - // even though they could result in an OTA issue if the command - // is called immediately and the native side throws on unrecognized - // commands. There is no way to do feature detection of commands - // today to protect against that. - // We are choosing to allow this change to be made since we previously - // had no protection for commands at all. - // See https://fb.workplace.com/groups/615693552291894/posts/1905124013348835 - // for more information. - newerComponent.commands.forEach(command => { - const oldCommand = olderComponent.commands?.find( - olderCommand => olderCommand.name === command.name, - ); - - const newCommands = { - type: 'ObjectTypeAnnotation', - properties: [command], - }; - const oldCommands = - oldCommand != null - ? { - type: 'ObjectTypeAnnotation', - properties: [oldCommand], - } - : null; - - const difference = codegenTypeDiffing.compareTypes( - newCommands, - oldCommands, - {}, - {}, - {}, - {}, - ); - - localAssessComparison( - newerComponentName, - newCommands, - oldCommands, - difference, - // Since we are explicitly checking the native module, we know it is starting as fromNative - 'fromNative', - ); - }); - - olderComponent.commands?.forEach(command => { - const newCommand = newerComponent.commands.find( - newerCommand => newerCommand.name === command.name, - ); - - if (newCommand == null) { - deprecatedTypes.add({ - typeName: command.name, - typeInformation: { - type: 'ObjectTypeAnnotation', - properties: [command], - }, - }); - } - }); - /* End Commands */ - - // We have to do this to remove the .defaults from the props and get it into - // standard JavaScript shapes. - const newConvertedProps = { - type: 'ObjectTypeAnnotation', - properties: newerComponent.props.map(prop => ({ - name: prop.name, - optional: prop.optional, - typeAnnotation: convertPropToBasicTypes(prop.typeAnnotation), - })), - }; - const oldConvertedProps = { - type: 'ObjectTypeAnnotation', - properties: olderComponent.props.map(prop => ({ - name: prop.name, - optional: prop.optional, - typeAnnotation: convertPropToBasicTypes(prop.typeAnnotation), - })), - }; - - const propDifference = codegenTypeDiffing.compareTypes( - newConvertedProps, - oldConvertedProps, - {}, - {}, - {}, - {}, - ); - - localAssessComparison( - newerComponentName, - newConvertedProps, - oldConvertedProps, - propDifference, - 'toNative', - ); - - const typeUpdate = { - newTypes, - deprecatedTypes, - incompatibleChanges, - objectTypeChanges, - }; - if (hasCodegenUpdatesTypes(typeUpdate)) { - componentErrors.add({ - nativeSpecName: newerComponentName, - omitted: false, - errorCode: 'incompatibleTypes', - changeInformation: typeUpdate, - }); - } - }, - ); - - Object.keys(olderNativeSchema.components).forEach(olderComponentName => { - const newerComponent = newerNativeSchema.components[olderComponentName]; - - if (newerComponent == null) { - // Component is missing in new schema - componentErrors.add({ - nativeSpecName: olderComponentName, - omitted: true, - errorCode: 'removedComponent', - }); - } - }); - - return componentErrors; -} - -export function hasUpdatesTypes(diff: DiffSet): boolean { - return ( - diff.newTypes.size > 0 || - diff.deprecatedTypes.size > 0 || - diff.objectTypeChanges.size > 0 || - diff.incompatibleChanges.size > 0 - ); -} - -export function hasCodegenUpdatesTypes(diff: DiffSet): boolean { - return ( - diff.newTypes.size > 0 || - diff.deprecatedTypes.size > 0 || - diff.objectTypeChanges.size > 0 || - diff.incompatibleChanges.size > 0 - ); -} - -export function buildSchemaDiff( - newerSchemaSet: SchemaType, - olderSchemaSet: SchemaType, -): Set { - const diff: Set = new Set(); - const newerSchema = newerSchemaSet.modules; - const olderSchema = olderSchemaSet.modules; - - Object.keys(newerSchema).forEach(hasteModuleName => { - const schemaEntry = newerSchema[hasteModuleName]; - const olderSchemaEntry = olderSchema[hasteModuleName]; - const framework = 'ReactNative'; - - if (schemaEntry.type === 'Component') { - if (olderSchemaEntry?.type === 'Component') { - const incompatibleComponents = buildNativeComponentsDiff( - schemaEntry, - olderSchemaEntry, - ); - const hasIncompatibleComponents = incompatibleComponents?.size > 0; - if (hasIncompatibleComponents) { - diff.add({ - name: hasteModuleName, - framework: framework, - status: { - incompatibleSpecs: incompatibleComponents, - }, - }); - } - } - } - - if (schemaEntry.type === 'NativeModule') { - if (olderSchemaEntry?.type === 'NativeModule') { - // Both native modules - const incompatibleModules = buildNativeModulesDiff( - schemaEntry, - olderSchemaEntry, - ); - - const hasIncompatibleModules = - incompatibleModules != null && incompatibleModules.size; - - if (hasIncompatibleModules) { - diff.add({ - name: hasteModuleName, - framework: framework, - status: { - incompatibleSpecs: incompatibleModules, - }, - }); - } - } - } - - if (olderSchemaEntry == null) { - diff.add({ - name: hasteModuleName, - framework: framework, - status: 'new', - }); - } - }); - - Object.keys(olderSchema).forEach(hasteModuleName => { - const newSchemaEntry = newerSchema[hasteModuleName]; - const oldSchemaEntry = olderSchema[hasteModuleName]; - const framework = 'ReactNative'; - - if (oldSchemaEntry != null && newSchemaEntry == null) { - diff.add({ - name: hasteModuleName, - framework: framework, - status: 'deprecated', - }); - } - }); - - return diff; -} - -function summarizeSchemaDiff(diff: SchemaDiff): DiffSummary { - switch (diff.status) { - case 'new': - return {status: 'patchable', incompatibilityReport: {}}; - case 'deprecated': - // TODO add check that a component can be removed - return {status: 'ok', incompatibilityReport: {}}; - default: - // differs case - const differs = diff.status; - if (!differs.incompatibleSpecs) { - return {status: 'patchable', incompatibilityReport: {}}; - } else { - const incompatibleObject: IncompatiblityReport = {}; - if (differs.incompatibleSpecs) { - const withErrors = Array.from(differs.incompatibleSpecs).filter( - specError => - specError.errorInformation || - (specError.changeInformation && - specError.changeInformation.incompatibleChanges.size > 0), - ); - if (withErrors.length > 0) { - if (incompatibleObject[diff.name]) { - incompatibleObject[diff.name].incompatibleSpecs = withErrors; - } else { - incompatibleObject[diff.name] = { - framework: diff.framework, - incompatibleSpecs: withErrors, - }; - } - } - } - const incompatibleUnchanged = - Object.keys(incompatibleObject).length === 0; - return { - status: incompatibleUnchanged ? 'ok' : 'incompatible', - incompatibilityReport: incompatibleObject, - }; - } - } -} - -function combineSummaries( - finalSummary: DiffSummary, - setSummary: DiffSummary, -): DiffSummary { - switch (setSummary.status) { - case 'ok': - return finalSummary; - case 'patchable': - if (finalSummary.status === 'ok') { - return setSummary; - } else { - return finalSummary; - } - default: - switch (finalSummary.status) { - case 'ok': - case 'patchable': - return setSummary; - default: - Object.keys(setSummary.incompatibilityReport).forEach( - differingSchemaName => - (finalSummary.incompatibilityReport[differingSchemaName] = - setSummary.incompatibilityReport[differingSchemaName]), - ); - return finalSummary; - } - } -} - -export function summarizeDiffSet(diffs: Set): DiffSummary { - if (diffs.size === 0) { - return {status: 'ok', incompatibilityReport: {}}; - } - const summary: Array = []; - diffs.forEach(schemaDiff => summary.push(summarizeSchemaDiff(schemaDiff))); - return summary.reduce(combineSummaries, summary[0]); -} diff --git a/packages/react-native-compatibility-check/src/__tests__/ErrorFormatting-test.js b/packages/react-native-compatibility-check/src/__tests__/ErrorFormatting-test.js deleted file mode 100644 index dd9de5f5bb3..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/ErrorFormatting-test.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * 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 - * @format - * @oncall react_native - */ - -import {formatDiffSet} from '../ErrorFormatting.js'; -import {buildSchemaDiff, summarizeDiffSet} from '../VersionDiffing.js'; -import {incompatibleChanges, okayChanges} from './ErrorFormattingTests.js'; -import {getTestSchema} from './utilities/getTestSchema.js'; - -describe('codegen formattedSummarizeDiffSet', () => { - okayChanges.forEach(([after, before]) => { - it(`allows a diff from ${before} to ${after}`, () => { - const beforeObj = getTestSchema( - __dirname, - '__fixtures__', - before + '.js.flow', - ); - - const afterObj = getTestSchema( - __dirname, - '__fixtures__', - after + '.js.flow', - ); - - const result = formatDiffSet( - summarizeDiffSet(buildSchemaDiff(afterObj, beforeObj)), - ); - - expect(result.status).toEqual('ok'); - - expect(result).toMatchSnapshot(); - }); - }); - - incompatibleChanges.forEach(([after, before]) => { - it(`reports a diff from ${before} to ${after}`, () => { - const beforeObj = getTestSchema( - __dirname, - '__fixtures__', - before + '.js.flow', - ); - - const afterObj = getTestSchema( - __dirname, - '__fixtures__', - after + '.js.flow', - ); - - const result = formatDiffSet( - summarizeDiffSet(buildSchemaDiff(afterObj, beforeObj)), - ); - - expect(result.status).toEqual('incompatible'); - - expect(result).toMatchSnapshot(); - }); - }); -}); diff --git a/packages/react-native-compatibility-check/src/__tests__/ErrorFormattingTests.js b/packages/react-native-compatibility-check/src/__tests__/ErrorFormattingTests.js deleted file mode 100644 index a4a97b720d4..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/ErrorFormattingTests.js +++ /dev/null @@ -1,150 +0,0 @@ -/** - * 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 strict-local - * @format - * @oncall react_native - */ - -export const okayChanges = [ - [ - 'native-module-before-after-types-removed/NativeModuleBeforeAfterTypes', - 'native-module-before-after-types/NativeModuleBeforeAfterTypes', - ], - [ - 'native-module-get-constants/NativeModule', - 'native-module-get-constants-added-optional-constant/NativeModule', - ], - [ - 'native-module-with-enum-from-native-changes/NativeModule', - 'native-module-with-enum-from-native/NativeModule', - ], - [ - 'native-module-with-union/NativeModule', - 'native-module-with-union-changes/NativeModule', - ], - [ - 'native-component-with-command/NativeComponent', - 'native-component-with-command/NativeComponent', - ], - [ - 'native-component-with-props/NativeComponent', - 'native-component-with-props-default-change/NativeComponent', - ], -]; - -export const incompatibleChanges = [ - [ - 'native-module-before-after-types/NativeModuleBeforeAfterTypes', - 'native-module-before-after-types-removed/NativeModuleBeforeAfterTypes', - ], - [ - 'native-module-before-after-types/NativeModuleBeforeAfterTypes', - 'native-module-before-after-types-type-changed/NativeModuleBeforeAfterTypes', - ], - ['native-module/NativeModule', 'native-module-changed/NativeModule'], - [ - 'native-module-nested/NativeModule', - 'native-module-nested-changed/NativeModule', - ], - [ - 'native-module-nested-optional/NativeModule', - 'native-module-nested/NativeModule', - ], - [ - 'native-module-nested-nullable/NativeModule', - 'native-module-nested-optional/NativeModule', - ], - [ - 'native-module-nested-optional/NativeModule', - 'native-module-nested-changed/NativeModule', - ], - [ - 'native-module-nested-alias/NativeModule', - 'native-module-nested-alias-changed/NativeModule', - ], - [ - 'native-module-with-dictionary/NativeModule', - 'native-module-with-dictionary-changed/NativeModule', - ], - [ - 'native-module-with-enum-changes/NativeModule', - 'native-module-with-enum/NativeModule', - ], - [ - 'native-module-with-enum/NativeModule', - 'native-module-with-enum-type-changes/NativeModule', - ], - [ - 'native-module-with-enum/NativeModule', - 'native-module-with-enum-value-changes/NativeModule', - ], - - [ - 'native-module-with-enum-from-native/NativeModule', - 'native-module-with-enum-from-native-changes/NativeModule', - ], - [ - 'native-module-with-enum-from-native/NativeModule', - 'native-module-with-enum-from-native-type-changes/NativeModule', - ], - [ - 'native-module-with-enum-from-native/NativeModule', - 'native-module-with-enum-from-native-value-changes/NativeModule', - ], - [ - 'native-module-with-eventemitter/NativeModule', - 'native-module-with-eventemitter-changes/NativeModule', - ], - [ - 'native-module/NativeModule', - 'native-module-with-optional-argument/NativeModule', - ], - [ - 'native-module-with-union/NativeModule', - 'native-module-with-union-type-changes/NativeModule', - ], - [ - 'native-module-with-union-changes/NativeModule', - 'native-module-with-union/NativeModule', - ], - [ - 'native-module-with-union-from-native/NativeModule', - 'native-module-with-union-from-native-changes/NativeModule', - ], - [ - 'native-module-with-union/NativeModule', - 'native-module-with-union-confusing-string-literals/NativeModule', - ], - [ - 'native-component-with-command/NativeComponent', - 'native-component-with-command-changed/NativeComponent', - ], - [ - 'native-component-with-command-all-basic-types-arrays/NativeComponent', - 'native-component-with-command-all-basic-types/NativeComponent', - ], - [ - 'native-component-with-command-extra-arg/NativeComponent', - 'native-component-with-command/NativeComponent', - ], - [ - 'native-component-with-props/NativeComponent', - 'native-component-with-props-changes/NativeComponent', - ], - [ - 'native-component-with-props/NativeComponent', - 'native-component-with-props-added-required-prop/NativeComponent', - ], - [ - 'native-component-with-props-union-added/NativeComponent', - 'native-component-with-props-union/NativeComponent', - ], - [ - 'native-component-with-props-array-union-added/NativeComponent', - 'native-component-with-props-array-union/NativeComponent', - ], -]; diff --git a/packages/react-native-compatibility-check/src/__tests__/TypeDiffing-test.js b/packages/react-native-compatibility-check/src/__tests__/TypeDiffing-test.js deleted file mode 100644 index 55e0a114fcb..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/TypeDiffing-test.js +++ /dev/null @@ -1,1207 +0,0 @@ -/** - * 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. - * - * @format - * @oncall react_native - */ - -import convertPropToBasicTypes from '../convertPropToBasicTypes'; -import {compareTypes} from '../TypeDiffing.js'; -import {getTestSchema} from './utilities/getTestSchema.js'; - -function getModule(...filenameComponents: Array) { - const schema = getTestSchema( - __dirname, - '__fixtures__', - ...filenameComponents, - ); - const hasteModule = filenameComponents[1].split('.')[0]; - const module = schema.modules[hasteModule]; - const aliasMap = module.aliasMap; - const enumMap = module.enumMap; - const methods = module.spec.methods; - const emitters = module.spec.eventEmitters; - - function methodLookup(methodName: string) { - return methods.find(method => method.name === methodName).typeAnnotation; - } - - function methodParamLookup(methodName: string) { - return methodLookup(methodName).params[0].typeAnnotation; - } - - function emitterLookup(emitterName: string) { - return emitters.find(emitter => emitter.name === emitterName) - .typeAnnotation; - } - - return [aliasMap, methodParamLookup, methodLookup, emitterLookup, enumMap]; -} - -function getComponent(...filenameComponents: Array) { - const schema = getTestSchema( - __dirname, - '__fixtures__', - ...filenameComponents, - ); - const hasteModule = filenameComponents[1].split('.')[0]; - const component = schema.modules[hasteModule]; - const firstComponent = - component.components[Object.keys(component.components)[0]]; - - const {commands} = firstComponent; - - function commandLookup(commandName: string) { - return commands.find(command => command.name === commandName) - .typeAnnotation; - } - - function propLookup(propName: string) { - // This conversion is done in VersionDiffing, so we need to emulate it here. - return convertPropToBasicTypes( - firstComponent.props.find(prop => prop.name === propName).typeAnnotation, - ); - } - - return [propLookup, commandLookup]; -} - -const [ - nativeModuleBeforeAfterTypesAliases, - nativeModuleBeforeAfterTypesMethodParamLookup, - nativeModuleBeforeAfterTypesMethodLookup, -] = getModule( - 'native-module-before-after-types', - 'NativeModuleBeforeAfterTypes.js.flow', -); - -const [ - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesMethodParamLookup, - nativeTypeDiffingTypesMethodLookup, - _, - nativeTypeDiffingTypesEnums, -] = getModule( - 'native-module-type-diffing-types', - 'NativeTypeDiffingTypes.js.flow', -); - -/* eslint-disable no-unused-vars */ -const [ - nativeModuleWithEventEmitterAliases, - _nativeModuleWithEventEmitterMethodParamLookup, - _nativeModuleWithEventEmitterMethodLookup, - nativeModuleWithEventEmitterEmitterLookup, -] = getModule('native-module-with-eventemitter', 'NativeModule.js.flow'); - -const [ - nativeModuleWithEventEmitterChangesAliases, - _nativeModuleWithEventEmitterChangesMethodParamLookup, - _nativeModuleWithEventEmitterChangesMethodLookup, - nativeModuleWithEventEmitterChangesEmitterLookup, -] = getModule( - 'native-module-with-eventemitter-changes', - 'NativeModule.js.flow', -); -/* eslint-enable no-unused-vars */ - -const [ - nativeComponentAllTypesPropLookup, - nativeComponentAllTypesCommandLookup, -] = getComponent('native-component-all-types', 'NativeComponent.js.flow'); - -expect.extend({ - toBeAnError(received) { - expect(received.status).toBe('error'); - return { - pass: true, - }; - }, - - toHaveErrorWithMessage(received, argument) { - expect(received.hasOwnProperty('errorLog')).toBe(true); - expect(received.errorLog.message).toContain(argument); - return { - message: () => '', - pass: true, - }; - }, -}); - -describe('components', () => { - describe('props', () => { - it('errors between number types', () => { - expect( - compareTypes( - nativeComponentAllTypesPropLookup('double'), - nativeComponentAllTypesPropLookup('float'), - {}, - {}, - ), - ).toHaveErrorWithMessage('Type annotations are not the same.'); - }); - - it('does not error between same types', () => { - expect( - compareTypes( - nativeComponentAllTypesPropLookup('double'), - nativeComponentAllTypesPropLookup('double'), - {}, - {}, - ).status, - ).toBe('matching'); - }); - - it('mixed can not become another type', () => { - expect( - compareTypes( - nativeComponentAllTypesPropLookup('int'), - nativeComponentAllTypesPropLookup('mixed'), - {}, - {}, - ), - ).toHaveErrorWithMessage('Type annotations are not the same.'); - }); - - it('int matches WithDefault int', () => { - expect( - compareTypes( - nativeComponentAllTypesPropLookup('int'), - nativeComponentAllTypesPropLookup('optionalInt'), - {}, - {}, - ).status, - ).toBe('matching'); - }); - - it('string matches WithDefault string', () => { - expect( - compareTypes( - nativeComponentAllTypesPropLookup('string'), - nativeComponentAllTypesPropLookup('optionalString'), - {}, - {}, - ).status, - ).toBe('matching'); - }); - - it('optional string with different defaults match', () => { - expect( - compareTypes( - nativeComponentAllTypesPropLookup('optionalString'), - nativeComponentAllTypesPropLookup('optionalStringDiffDefault'), - {}, - {}, - ).status, - ).toBe('matching'); - }); - - it('string not compatible with string union', () => { - expect( - compareTypes( - nativeComponentAllTypesPropLookup('string'), - nativeComponentAllTypesPropLookup('stringUnion'), - {}, - {}, - ), - ).toHaveErrorWithMessage('Type annotations are not the same.'); - }); - - it('string union not compatible with int union', () => { - expect( - compareTypes( - nativeComponentAllTypesPropLookup('stringUnion'), - nativeComponentAllTypesPropLookup('intUnion'), - {}, - {}, - ), - ).toHaveErrorWithMessage('Type annotations are not the same.'); - }); - - it('nested object with changed value not compatible', () => { - expect( - compareTypes( - nativeComponentAllTypesPropLookup('nestedObjectChanged'), - nativeComponentAllTypesPropLookup('nestedObject'), - {}, - {}, - ), - ).toHaveErrorWithMessage( - 'Object contained a property with a type mismatch', - ); - }); - - it('array with a string union to an extra option not compatible', () => { - expect( - compareTypes( - nativeComponentAllTypesPropLookup('arrayStringUnionExtra'), - nativeComponentAllTypesPropLookup('arrayStringUnion'), - {}, - {}, - ), - ).toEqual( - expect.objectContaining({ - status: 'positionalTypeChange', - changeLog: expect.objectContaining({ - typeKind: 'stringUnion', - addedElements: expect.arrayContaining([expect.any(Array)]), - }), - }), - ); - }); - - it('array of an object to an extra key not compatible', () => { - expect( - compareTypes( - nativeComponentAllTypesPropLookup('arrayNestedObjectChange'), - nativeComponentAllTypesPropLookup('arrayNestedObject'), - {}, - {}, - ), - ).toHaveErrorWithMessage( - 'Object contained a property with a type mismatch', - ); - }); - }); - describe('commands', () => { - it('errors on type of parameter changing', () => { - expect( - compareTypes( - nativeComponentAllTypesCommandLookup('methodInt'), - nativeComponentAllTypesCommandLookup('methodString'), - {}, - {}, - ), - ).toHaveErrorWithMessage('Parameter at index 0 did not match'); - }); - - it('errors on parameter changing between number types', () => { - expect( - compareTypes( - nativeComponentAllTypesCommandLookup('methodFloat'), - nativeComponentAllTypesCommandLookup('methodInt'), - {}, - {}, - ), - ).toHaveErrorWithMessage('Parameter at index 0 did not match'); - }); - - it('errors on parameter changing from int to RootTag (opaque int)', () => { - expect( - compareTypes( - nativeComponentAllTypesCommandLookup('methodRootTag'), - nativeComponentAllTypesCommandLookup('methodInt'), - {}, - {}, - ), - ).toHaveErrorWithMessage('Parameter at index 0 did not match'); - }); - - it('does not error when unchanged with string', () => { - expect( - compareTypes( - nativeComponentAllTypesCommandLookup('methodString'), - nativeComponentAllTypesCommandLookup('methodString'), - {}, - {}, - ).status, - ).toBe('matching'); - }); - - it('does not error when unchanged with RootTag', () => { - expect( - compareTypes( - nativeComponentAllTypesCommandLookup('methodRootTag'), - nativeComponentAllTypesCommandLookup('methodRootTag'), - {}, - {}, - ).status, - ).toBe('matching'); - }); - - it('errors on additional argument', () => { - expect( - compareTypes( - nativeComponentAllTypesCommandLookup('methodIntString'), - nativeComponentAllTypesCommandLookup('methodInt'), - {}, - {}, - ), - ).toHaveErrorWithMessage( - 'Function types have differing length of arguments', - ); - }); - - it('errors on argument removed', () => { - expect( - compareTypes( - nativeComponentAllTypesCommandLookup('methodInt'), - nativeComponentAllTypesCommandLookup('methodIntString'), - {}, - {}, - ), - ).toHaveErrorWithMessage( - 'Function types have differing length of arguments', - ); - }); - - it('errors on argument compared to array of argument', () => { - expect( - compareTypes( - nativeComponentAllTypesCommandLookup('methodInt'), - nativeComponentAllTypesCommandLookup('methodIntArray'), - {}, - {}, - ), - ).toHaveErrorWithMessage('Parameter at index 0 did not match'); - }); - - it('errors on arrays of different types', () => { - expect( - compareTypes( - nativeComponentAllTypesCommandLookup('methodIntArray'), - nativeComponentAllTypesCommandLookup('methodFloatArray'), - {}, - {}, - ), - ).toHaveErrorWithMessage('Parameter at index 0 did not match'); - }); - - it('does not error when becoming an alias', () => { - expect( - compareTypes( - nativeComponentAllTypesCommandLookup('methodBool'), - nativeComponentAllTypesCommandLookup('methodBoolAlias'), - {}, - {}, - ).status, - ).toBe('matching'); - }); - - it('does not error when becoming inlined', () => { - expect( - compareTypes( - nativeComponentAllTypesCommandLookup('methodString'), - nativeComponentAllTypesCommandLookup('methodStringAlias'), - {}, - {}, - ).status, - ).toBe('matching'); - }); - - it('does not error (but it should) on arrays of two different objects', () => { - // This doesn't fail because we don't store object alias info in the schema - // These are just arrays of mixed. Someday someone should fix this. NativeModules support this. - // More info in https://github.com/facebook/react-native/pull/48476 - expect( - compareTypes( - nativeComponentAllTypesCommandLookup('methodCustomObjArray'), - nativeComponentAllTypesCommandLookup('methodCustomObj2Array'), - {}, - {}, - ).status, - ).toBe('matching'); - }); - - it('errors on arrays of mixed vs array of standard type', () => { - expect( - compareTypes( - nativeComponentAllTypesCommandLookup('methodIntArray'), - nativeComponentAllTypesCommandLookup('methodCustomObjArray'), - {}, - {}, - ), - ).toHaveErrorWithMessage('Parameter at index 0 did not match'); - }); - }); -}); - -describe('compareTypes', () => { - it('matches the exact same type', () => { - expect( - compareTypes( - nativeModuleBeforeAfterTypesAliases.SimpleObject, - nativeModuleBeforeAfterTypesAliases.SimpleObject, - nativeModuleBeforeAfterTypesAliases, - nativeModuleBeforeAfterTypesAliases, - ).status, - ).toBe('matching'); - }); - - it('skips null types', () => { - expect( - compareTypes( - nativeModuleBeforeAfterTypesAliases.SimpleObject, - null, - nativeModuleBeforeAfterTypesAliases, - nativeModuleBeforeAfterTypesAliases, - ).status, - ).toBe('skipped'); - }); - - it('matches on types with the same generic parameters', () => { - expect( - compareTypes( - nativeModuleBeforeAfterTypesAliases.BeforeMatchingGeneric, - nativeModuleBeforeAfterTypesAliases.AfterMatchingGeneric, - nativeModuleBeforeAfterTypesAliases, - nativeModuleBeforeAfterTypesAliases, - ).status, - ).toBe('matching'); - }); - - it('matches the exact same EventEmitter', () => { - expect( - compareTypes( - nativeModuleWithEventEmitterEmitterLookup('onClick'), - nativeModuleWithEventEmitterEmitterLookup('onClick'), - nativeModuleWithEventEmitterAliases, - nativeModuleWithEventEmitterAliases, - ).status, - ).toBe('matching'); - }); - - it('fails on mismatching EventEmitter parameters', () => { - expect( - compareTypes( - nativeModuleWithEventEmitterEmitterLookup('onClick'), - nativeModuleWithEventEmitterChangesEmitterLookup('onClick'), - nativeModuleWithEventEmitterAliases, - nativeModuleWithEventEmitterChangesAliases, - ), - ).toHaveErrorWithMessage('EventEmitter eventTypes are not equivalent'); - }); -}); - -describe('compareTypes objects', () => { - it('matches objects with same properties', () => { - expect( - compareTypes( - nativeTypeDiffingTypesAliases.ObjectTypeWithProps, - nativeTypeDiffingTypesAliases.ObjectTypeWithProps, - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ).status, - ).toBe('matching'); - }); - - it('matches objects with unsafe objects', () => { - expect( - compareTypes( - nativeTypeDiffingTypesMethodLookup('genericObjectType'), - nativeTypeDiffingTypesMethodLookup('unsafeObjectType'), - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ).status, - ).toBe('matching'); - }); - - it('reports objects with added properties', () => { - expect( - compareTypes( - nativeTypeDiffingTypesAliases.ObjectTypeWithProps, - nativeTypeDiffingTypesAliases.ObjectTypeLessProps, - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ), - ).toEqual( - expect.objectContaining({ - status: 'properties', - propertyLog: expect.objectContaining({ - addedProperties: expect.any(Object), - }), - }), - ); - }); - - it('reports objects with removed properties', () => { - expect( - compareTypes( - nativeTypeDiffingTypesAliases.ObjectTypeLessProps, - nativeTypeDiffingTypesAliases.ObjectTypeWithProps, - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ), - ).toEqual( - expect.objectContaining({ - status: 'properties', - propertyLog: expect.objectContaining({ - missingProperties: expect.any(Object), - }), - }), - ); - }); - - it('matches objects with nested objects', () => { - expect( - compareTypes( - nativeTypeDiffingTypesAliases.ObjectTypeWithNesting, - nativeTypeDiffingTypesAliases.ObjectTypeWithNesting, - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ).status, - ).toBe('matching'); - }); - - it('reports objects with changed properties', () => { - expect( - compareTypes( - nativeTypeDiffingTypesAliases.ObjectTypeWithNesting, - nativeTypeDiffingTypesAliases.ObjectTypeWithChanges, - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ), - ).toHaveErrorWithMessage( - 'Object contained properties with type mismatches', - ); - }); - - it('reports objects with changed nested properties', () => { - expect( - compareTypes( - nativeTypeDiffingTypesAliases.ObjectTypeWithNesting, - nativeTypeDiffingTypesAliases.ObjectTypeWithNestedChanges, - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ), - ).toHaveErrorWithMessage( - 'Object contained a property with a type mismatch', - ); - }); - - it('reports objects with completely different properties', () => { - expect( - compareTypes( - nativeTypeDiffingTypesAliases.ObjectTypeWithProps, - nativeTypeDiffingTypesAliases.ObjectTypeWithDifferentProps, - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ), - ).toHaveErrorWithMessage('Object types do not match.'); - }); - - it('matches objects with optional properties, no changes', () => { - expect( - compareTypes( - nativeTypeDiffingTypesAliases.ObjectTypeWithTwoOptionals, - nativeTypeDiffingTypesAliases.ObjectTypeWithTwoOptionals, - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ).status, - ).toBe('matching'); - }); - - it('reports objects with properties made strict', () => { - expect( - compareTypes( - nativeTypeDiffingTypesAliases.ObjectTypeWithProps, - nativeTypeDiffingTypesAliases.ObjectTypeWithTwoOptionals, - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ), - ).toEqual( - expect.objectContaining({ - status: 'properties', - propertyLog: expect.objectContaining({ - madeStrict: expect.any(Object), - }), - }), - ); - }); - - it('reports objects with properties made optional', () => { - expect( - compareTypes( - nativeTypeDiffingTypesAliases.ObjectTypeWithTwoOptionals, - nativeTypeDiffingTypesAliases.ObjectTypeWithProps, - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ), - ).toEqual( - expect.objectContaining({ - status: 'properties', - propertyLog: expect.objectContaining({ - madeOptional: expect.any(Object), - }), - }), - ); - }); - - it('reports objects with properties made strict, and nested changes', () => { - expect( - compareTypes( - nativeTypeDiffingTypesAliases.ObjectTypeWithNesting, - nativeTypeDiffingTypesAliases.ObjectTypeWithOptionalNestedChange, - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ), - ).toEqual( - expect.objectContaining({ - status: 'properties', - propertyLog: expect.objectContaining({ - madeStrict: expect.objectContaining({ - '0': expect.objectContaining({ - furtherChange: expect.objectContaining({status: 'properties'}), - }), - }), - }), - }), - ); - }); - - it('reports objects with properties made optional, and nested changes', () => { - expect( - compareTypes( - nativeTypeDiffingTypesAliases.ObjectTypeWithOptionalNestedChange, - nativeTypeDiffingTypesAliases.ObjectTypeWithNesting, - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ), - ).toEqual( - expect.objectContaining({ - status: 'properties', - propertyLog: expect.objectContaining({ - madeOptional: expect.objectContaining({ - '0': expect.objectContaining({ - furtherChange: expect.objectContaining({status: 'properties'}), - }), - }), - }), - }), - ); - }); - - it('matches structurally same objects', () => { - expect( - compareTypes( - nativeTypeDiffingTypesAliases.ObjectTypeLiteral1, - nativeTypeDiffingTypesAliases.ObjectTypeLiteral2, - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ).status, - ).toBe('matching'); - }); - - it('matches objects with their type aliases', () => { - expect( - compareTypes( - nativeTypeDiffingTypesAliases.ObjectTypeLiteral1, - nativeTypeDiffingTypesMethodParamLookup('objectTypeLiteral1TypeAlias'), - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ).status, - ).toBe('matching'); - }); - - it('matches objects with type aliases of structurally same objects', () => { - expect( - compareTypes( - nativeTypeDiffingTypesAliases.ObjectTypeLiteral1, - nativeTypeDiffingTypesMethodParamLookup('objectTypeLiteral2TypeAlias'), - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ).status, - ).toBe('matching'); - expect( - compareTypes( - nativeTypeDiffingTypesMethodParamLookup('objectTypeLiteral1TypeAlias'), - nativeTypeDiffingTypesAliases.ObjectTypeLiteral2, - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ).status, - ).toBe('matching'); - }); - - it('matches two type aliases of structurally same objects', () => { - expect( - compareTypes( - nativeTypeDiffingTypesMethodParamLookup('objectTypeLiteral1TypeAlias'), - nativeTypeDiffingTypesMethodParamLookup('objectTypeLiteral2TypeAlias'), - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ).status, - ).toBe('matching'); - }); -}); - -describe('compareTypes primitives', () => { - it('matches primitive types that are the same', () => { - expect( - compareTypes( - nativeModuleBeforeAfterTypesMethodParamLookup('booleanType'), - nativeModuleBeforeAfterTypesMethodParamLookup('booleanType'), - nativeModuleBeforeAfterTypesAliases, - nativeModuleBeforeAfterTypesAliases, - ).status, - ).toBe('matching'); - }); - - it('fails on primitive types that are not the same', () => { - expect( - compareTypes( - nativeModuleBeforeAfterTypesMethodParamLookup('booleanType'), - nativeModuleBeforeAfterTypesMethodParamLookup('stringType'), - nativeModuleBeforeAfterTypesAliases, - nativeModuleBeforeAfterTypesAliases, - ), - ).toHaveErrorWithMessage('Type annotations are not the same'); - }); -}); - -describe('compareTypes functions', () => { - it('matches functions on primitive types that are the same', () => { - expect( - compareTypes( - nativeModuleBeforeAfterTypesMethodLookup('simpleFunction'), - nativeModuleBeforeAfterTypesMethodLookup('simpleFunction'), - nativeModuleBeforeAfterTypesAliases, - nativeModuleBeforeAfterTypesAliases, - ).status, - ).toBe('matching'); - }); - - it('fails on functions with differing return types', () => { - expect( - compareTypes( - nativeModuleBeforeAfterTypesMethodLookup('simpleFunction'), - nativeModuleBeforeAfterTypesMethodLookup('simpleFunction2'), - nativeModuleBeforeAfterTypesAliases, - nativeModuleBeforeAfterTypesAliases, - ), - ).toHaveErrorWithMessage('Function return types do not match'); - }); - - it('fails on functions with differing parameter types', () => { - expect( - compareTypes( - nativeModuleBeforeAfterTypesMethodLookup('simpleFunction'), - nativeModuleBeforeAfterTypesMethodLookup('simpleFunction4'), - nativeModuleBeforeAfterTypesAliases, - nativeModuleBeforeAfterTypesAliases, - ), - ).toHaveErrorWithMessage('Parameter at index 0 did not match'); - }); -}); - -describe('compareTypes unions', () => { - it('matches unions that are the same', () => { - expect( - compareTypes( - nativeModuleBeforeAfterTypesMethodParamLookup('simpleUnion'), - nativeModuleBeforeAfterTypesMethodParamLookup('simpleUnion'), - nativeModuleBeforeAfterTypesAliases, - nativeModuleBeforeAfterTypesAliases, - ).status, - ).toBe('matching'); - }); - it('matches unions that are the same alias', () => { - expect( - compareTypes( - nativeModuleBeforeAfterTypesMethodLookup('simpleUnion'), - nativeModuleBeforeAfterTypesMethodLookup('simpleUnion'), - nativeModuleBeforeAfterTypesAliases, - nativeModuleBeforeAfterTypesAliases, - ).status, - ).toBe('matching'); - }); - it('fails on differing unions with same length, string -> number', () => { - expect( - compareTypes( - nativeModuleBeforeAfterTypesMethodParamLookup('simpleUnion'), - nativeModuleBeforeAfterTypesMethodParamLookup('simpleUnion2'), - nativeModuleBeforeAfterTypesAliases, - nativeModuleBeforeAfterTypesAliases, - ), - ).toBeAnError(); - }); - it('fails on differing unions with same length and same alias name', () => { - expect( - compareTypes( - nativeModuleBeforeAfterTypesMethodLookup('simpleUnion'), - nativeModuleBeforeAfterTypesMethodLookup('simpleUnion2'), - nativeModuleBeforeAfterTypesAliases, - nativeModuleBeforeAfterTypesAliases, - ), - ).toBeAnError(); - }); - it('reports on unions with differing types: string -> object', () => { - expect( - compareTypes( - nativeModuleBeforeAfterTypesMethodParamLookup('simpleUnion2'), - nativeModuleBeforeAfterTypesMethodParamLookup('simpleUnion3'), - nativeModuleBeforeAfterTypesAliases, - nativeModuleBeforeAfterTypesAliases, - ), - ).toHaveErrorWithMessage('Union member type does not match'); - }); - it('reports on unions with differing lengths same alias', () => { - expect( - compareTypes( - nativeModuleBeforeAfterTypesMethodLookup('simpleUnion'), - nativeModuleBeforeAfterTypesMethodLookup('simpleUnionLonger'), - nativeModuleBeforeAfterTypesAliases, - nativeModuleBeforeAfterTypesAliases, - ).functionChangeLog.parameterTypes.nestedChanges[0][2], - ).toEqual( - expect.objectContaining({ - status: 'positionalTypeChange', - changeLog: expect.objectContaining({ - typeKind: 'stringUnion', - removedElements: expect.arrayContaining([expect.any(Array)]), - }), - }), - ); - }); -}); - -describe('compareTypes on arrays', () => { - it('arrays that are the same, with primitive types', () => { - expect( - compareTypes( - nativeModuleBeforeAfterTypesMethodParamLookup('simpleArray'), - nativeModuleBeforeAfterTypesMethodParamLookup('simpleArray'), - nativeModuleBeforeAfterTypesAliases, - nativeModuleBeforeAfterTypesAliases, - ).status, - ).toBe('matching'); - }); - - it('arrays that have changed, with primitive types', () => { - expect( - compareTypes( - nativeModuleBeforeAfterTypesMethodParamLookup('simpleArray'), - nativeModuleBeforeAfterTypesMethodParamLookup('simpleArrayChange'), - nativeModuleBeforeAfterTypesAliases, - nativeModuleBeforeAfterTypesAliases, - ), - ).toHaveErrorWithMessage('Type annotations are not the same'); - }); -}); - -describe('compareTypes on string literals', () => { - it('matches literals that are the same', () => { - expect( - compareTypes( - nativeTypeDiffingTypesMethodParamLookup('stringLiteral0'), - nativeTypeDiffingTypesMethodParamLookup('stringLiteral0'), - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ).status, - ).toBe('matching'); - }); - - it('fails on literals that are not the same', () => { - expect( - compareTypes( - nativeTypeDiffingTypesMethodParamLookup('stringLiteral0'), - nativeTypeDiffingTypesMethodParamLookup('stringLiteral1'), - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ), - ).toHaveErrorWithMessage('String literals are not equal'); - }); -}); - -describe('compareTypes on numeric literals', () => { - it('matches literals that are the same', () => { - expect( - compareTypes( - nativeTypeDiffingTypesMethodParamLookup('numericLiteral0'), - nativeTypeDiffingTypesMethodParamLookup('numericLiteral0'), - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ).status, - ).toBe('matching'); - }); - - it('fails on literals that are not the same', () => { - expect( - compareTypes( - nativeTypeDiffingTypesMethodParamLookup('numericLiteral0'), - nativeTypeDiffingTypesMethodParamLookup('numericLiteral1'), - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ), - ).toHaveErrorWithMessage('Numeric literals are not equal'); - }); -}); - -describe('compareTypes on generic types', () => { - it('matches generic types that are the same', () => { - expect( - compareTypes( - nativeTypeDiffingTypesMethodParamLookup('referenceType'), - nativeTypeDiffingTypesMethodParamLookup('referenceType'), - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ).status, - ).toBe('matching'); - }); - - it('fails when different types are referenced', () => { - expect( - compareTypes( - nativeTypeDiffingTypesMethodParamLookup('referenceType'), - nativeTypeDiffingTypesMethodParamLookup('referenceType3'), - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ), - ).toEqual( - expect.objectContaining({ - status: 'properties', - propertyLog: expect.objectContaining({ - missingProperties: expect.any(Object), - }), - }), - ); - }); - - it('matches when structurally same types are referenced', () => { - expect( - compareTypes( - nativeTypeDiffingTypesMethodParamLookup('referenceType'), - nativeTypeDiffingTypesMethodParamLookup('referenceType2'), - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ).status, - ).toBe('matching'); - }); -}); - -describe('compareTypes on string literal unions', () => { - it('matches unions that are the same', () => { - expect( - compareTypes( - nativeTypeDiffingTypesMethodParamLookup('stringLiteralUnion0'), - nativeTypeDiffingTypesMethodParamLookup('stringLiteralUnion0'), - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ).status, - ).toBe('matching'); - }); - - it('reports on unions with different lengths', () => { - expect( - compareTypes( - nativeTypeDiffingTypesMethodParamLookup('stringLiteralUnion0'), - nativeTypeDiffingTypesMethodParamLookup('stringLiteralUnion1'), - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ), - ).toEqual( - expect.objectContaining({ - status: 'positionalTypeChange', - changeLog: expect.objectContaining({ - typeKind: 'stringUnion', - removedElements: expect.arrayContaining([expect.any(Array)]), - }), - }), - ); - }); - - it('fails on unions with differing elements', () => { - expect( - compareTypes( - nativeTypeDiffingTypesMethodParamLookup('stringLiteralUnion0'), - nativeTypeDiffingTypesMethodParamLookup('stringLiteralUnion2'), - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ), - ).toHaveErrorWithMessage('Subtype of union at position 1 did not match'); - }); -}); - -describe('compareTypes on nullables', () => { - it('matches nullables that are the same', () => { - expect( - compareTypes( - nativeTypeDiffingTypesMethodParamLookup('nullableType'), - nativeTypeDiffingTypesMethodParamLookup('nullableType'), - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ).status, - ).toBe('matching'); - }); - - it('reports nullables that have changed to strict', () => { - expect( - compareTypes( - nativeTypeDiffingTypesMethodParamLookup('nonNullableType'), - nativeTypeDiffingTypesMethodParamLookup('nullableType'), - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ), - ).toEqual( - expect.objectContaining({ - status: 'nullableChange', - nullableLog: expect.objectContaining({ - optionsReduced: true, - interiorLog: expect.objectContaining({status: 'matching'}), - }), - }), - ); - }); - - it('reports nonnullables that have changed to nullable', () => { - expect( - compareTypes( - nativeTypeDiffingTypesMethodParamLookup('nullableType'), - nativeTypeDiffingTypesMethodParamLookup('nonNullableType'), - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ), - ).toEqual( - expect.objectContaining({ - status: 'nullableChange', - nullableLog: expect.objectContaining({ - optionsReduced: false, - interiorLog: expect.objectContaining({status: 'matching'}), - }), - }), - ); - }); - - it('reports nullable change, and interior change', () => { - expect( - compareTypes( - nativeTypeDiffingTypesMethodParamLookup('objectTypeWithProps'), - nativeTypeDiffingTypesMethodParamLookup('optionalTypeLessProps'), - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - ), - ).toEqual( - expect.objectContaining({ - status: 'nullableChange', - nullableLog: expect.objectContaining({ - optionsReduced: true, - interiorLog: expect.objectContaining({status: 'properties'}), - }), - }), - ); - }); -}); - -describe('compareTypes on enums', () => { - it('matches enums that are the same', () => { - expect( - compareTypes( - nativeTypeDiffingTypesMethodParamLookup('enum'), - nativeTypeDiffingTypesMethodParamLookup('enum'), - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesEnums, - nativeTypeDiffingTypesEnums, - ).status, - ).toBe('matching'); - }); - - it('reports enums that have changed types', () => { - expect( - compareTypes( - nativeTypeDiffingTypesMethodParamLookup('enum'), - nativeTypeDiffingTypesMethodParamLookup('enumWithTypeChange'), - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesEnums, - nativeTypeDiffingTypesEnums, - ), - ).toHaveErrorWithMessage('EnumDeclaration member types are not the same'); - }); - - it('reports enums that have changed values', () => { - expect( - compareTypes( - nativeTypeDiffingTypesMethodParamLookup('enum'), - nativeTypeDiffingTypesMethodParamLookup('enumWithValueChange'), - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesEnums, - nativeTypeDiffingTypesEnums, - ), - ).toEqual( - expect.objectContaining({ - errorLog: expect.objectContaining({ - message: 'Enum types do not match', - previousError: expect.objectContaining({ - message: 'Enum contained a member with a type mismatch', - mismatchedMembers: expect.arrayContaining([ - expect.objectContaining({ - member: 'D', - }), - ]), - }), - }), - }), - ); - }); - - it('reports enums that have removed items', () => { - expect( - compareTypes( - nativeTypeDiffingTypesMethodParamLookup('enumWithRemoval'), - nativeTypeDiffingTypesMethodParamLookup('enum'), - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesEnums, - nativeTypeDiffingTypesEnums, - ), - ).toEqual( - expect.objectContaining({ - status: 'members', - memberLog: expect.objectContaining({ - missingMembers: expect.arrayContaining([ - expect.objectContaining({ - name: 'D', - value: expect.objectContaining({ - value: 4, - }), - }), - ]), - }), - }), - ); - }); - - it('reports enums that have added items', () => { - expect( - compareTypes( - nativeTypeDiffingTypesMethodParamLookup('enum'), - nativeTypeDiffingTypesMethodParamLookup('enumWithRemoval'), - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesEnums, - nativeTypeDiffingTypesEnums, - ), - ).toEqual( - expect.objectContaining({ - status: 'members', - memberLog: expect.objectContaining({ - addedMembers: expect.arrayContaining([ - expect.objectContaining({ - name: 'D', - value: expect.objectContaining({ - value: 4, - }), - }), - ]), - }), - }), - ); - }); - - it('matches enums that are the same but sorted differently', () => { - expect( - compareTypes( - nativeTypeDiffingTypesMethodParamLookup('enum'), - nativeTypeDiffingTypesMethodParamLookup('enumUnsorted'), - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesAliases, - nativeTypeDiffingTypesEnums, - nativeTypeDiffingTypesEnums, - ).status, - ).toBe('matching'); - }); -}); diff --git a/packages/react-native-compatibility-check/src/__tests__/VersionDiffing-test.js b/packages/react-native-compatibility-check/src/__tests__/VersionDiffing-test.js deleted file mode 100644 index 361a70e6f9c..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/VersionDiffing-test.js +++ /dev/null @@ -1,1603 +0,0 @@ -/** - * 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 - * @format - * @oncall react_native - */ - -import type {SchemaDiff, TypeStore} from '../DiffResults'; - -import {schemaDiffExporter} from '../DiffResults.js'; -import { - addedEnumMessage, - addedPropertiesMessage, - addedUnionMessage, - buildSchemaDiff, - hasUpdatesTypes, - removedEnumMessage, - removedPropertiesMessage, - removedUnionMessage, - summarizeDiffSet, - tooOptionalPropertiesMessage, - typeNullableChangeMessage, -} from '../VersionDiffing.js'; -import {getTestSchema} from './utilities/getTestSchema.js'; - -const schemaBeforeAfterTypes = makeRN( - 'native-module-before-after-types/NativeModuleBeforeAfterTypes', -); - -const schemaBeforeAfterTypesTypesRemoved = makeRN( - 'native-module-before-after-types-removed/NativeModuleBeforeAfterTypes', -); - -const schemaWithRN = makeRN('native-module/NativeModule'); -const schemaWithRNChanged = makeRN('native-module-changed/NativeModule'); - -const schemaGetConstants = makeRN('native-module-get-constants/NativeModule'); - -const schemaGetConstantsAddedRequiredConstant = makeRN( - 'native-module-get-constants-added-required-constant/NativeModule', -); - -const schemaGetConstantsAddedOptionalConstant = makeRN( - 'native-module-get-constants-added-optional-constant/NativeModule', -); - -const schemaGetConstantsReadOnly = makeRN( - 'native-module-get-constants-readonly/NativeModule', -); - -const schemaGetConstantsAddedRequiredConstantReadOnly = makeRN( - 'native-module-get-constants-added-required-constant-readonly/NativeModule', -); - -const schemaGetConstantsAddedOptionalConstantReadOnly = makeRN( - 'native-module-get-constants-added-optional-constant-readonly/NativeModule', -); - -const schemaBeforeAfterTypesTypeChanged = makeRN( - 'native-module-before-after-types-type-changed/NativeModuleBeforeAfterTypes', -); - -function makeRN(name: string) { - return getTestSchema(__dirname, '__fixtures__', name + '.js.flow'); -} - -const schemaWithRnNestedObject = makeRN('native-module-nested/NativeModule'); -const schemaWithRnNestedChanged = makeRN( - 'native-module-nested-changed/NativeModule', -); -const schemaWithRnNestedOptions = makeRN( - 'native-module-nested-optional/NativeModule', -); -const schemaWithRnNestedNullable = makeRN( - 'native-module-nested-nullable/NativeModule', -); -const schemaWithEnum = makeRN('native-module-with-enum/NativeModule'); -const schemaWithEnumChanges = makeRN( - 'native-module-with-enum-changes/NativeModule', -); -const schemaWithEnumTypeChanges = makeRN( - 'native-module-with-enum-type-changes/NativeModule', -); -const schemaWithEnumValueChanges = makeRN( - 'native-module-with-enum-value-changes/NativeModule', -); - -const schemaWithEnumFromNative = makeRN( - 'native-module-with-enum-from-native/NativeModule', -); -const schemaWithEnumFromNativeChanges = makeRN( - 'native-module-with-enum-from-native-changes/NativeModule', -); -const schemaWithEnumFromNativeTypeChanges = makeRN( - 'native-module-with-enum-from-native-type-changes/NativeModule', -); -const schemaWithEnumFromNativeValueChanges = makeRN( - 'native-module-with-enum-from-native-value-changes/NativeModule', -); - -const schemaWithEventEmitter = makeRN( - 'native-module-with-eventemitter/NativeModule', -); -const schemaWithEventEmitterChanges = makeRN( - 'native-module-with-eventemitter-changes/NativeModule', -); -const schemaWithOptionalArgument = makeRN( - 'native-module-with-optional-argument/NativeModule', -); -const schemaWithUnion = makeRN('native-module-with-union/NativeModule'); -const schemaWithUnionChanges = makeRN( - 'native-module-with-union-changes/NativeModule', -); -const schemaWithUnionFromNative = makeRN( - 'native-module-with-union-from-native/NativeModule', -); -const schemaWithUnionFromNativeChanges = makeRN( - 'native-module-with-union-from-native-changes/NativeModule', -); - -const schemaWithRNNativeComponent = makeRN('native-component/NativeComponent'); -const schemaNativeComponentWithCommand = makeRN( - 'native-component-with-command/NativeComponent', -); -const schemaNativeComponentWithCommandExtraArg = makeRN( - 'native-component-with-command-extra-arg/NativeComponent', -); - -const schemaNativeComponentWithCommandExtraCommand = makeRN( - 'native-component-with-command-extra-command/NativeComponent', -); - -const schemaNativeComponentWithProps = makeRN( - 'native-component-with-props/NativeComponent', -); - -const schemaNativeComponentWithPropsAddedOptionalProp = makeRN( - 'native-component-with-props-added-optional-prop/NativeComponent', -); -const schemaNativeComponentWithPropsAddedRequiredProp = makeRN( - 'native-component-with-props-added-required-prop/NativeComponent', -); - -const schemaNativeComponentWithPropsChanges = makeRN( - 'native-component-with-props-changes/NativeComponent', -); - -const schemaNativeComponentWithPropsDefaultChange = makeRN( - 'native-component-with-props-default-change/NativeComponent', -); - -const schemaNativeComponentWithPropsNestedObject = makeRN( - 'native-component-with-props-nested-object/NativeComponent', -); - -const schemaNativeComponentWithPropsNestedObjectAddedOptionalKey = makeRN( - 'native-component-with-props-nested-object-added-optional-key/NativeComponent', -); - -const schemaNativeComponentWithPropsNestedObjectAddedRequiredKey = makeRN( - 'native-component-with-props-nested-object-added-required-key/NativeComponent', -); - -const schemaNativeComponentWithPropsUnion = makeRN( - 'native-component-with-props-union/NativeComponent', -); - -const schemaNativeComponentWithPropsUnionAdded = makeRN( - 'native-component-with-props-union-added/NativeComponent', -); - -const schemaNativeComponentWithPropsArrayUnion = makeRN( - 'native-component-with-props-array-union/NativeComponent', -); - -const schemaNativeComponentWithPropsArrayUnionAdded = makeRN( - 'native-component-with-props-array-union-added/NativeComponent', -); - -describe('hasUpdates', () => { - it('is given empty sets', () => { - expect( - hasUpdatesTypes({ - newTypes: new Set(), - deprecatedTypes: new Set(), - objectTypeChanges: new Set(), - incompatibleChanges: new Set(), - }), - ).toBeFalsy(); - }); - const set = new Set(); - set.add({ - typeName: 'name', - typeInformation: { - type: 'AnyTypeAnnotation', - }, - filename: 'name', - }); - it('is given nonempty newTypes', () => { - expect( - hasUpdatesTypes({ - newTypes: set, - deprecatedTypes: new Set(), - objectTypeChanges: new Set(), - incompatibleChanges: new Set(), - }), - ).toBeTruthy(); - }); - it('is given nonempty deprecatedTypes', () => { - expect( - hasUpdatesTypes({ - newTypes: new Set(), - deprecatedTypes: set, - objectTypeChanges: new Set(), - incompatibleChanges: new Set(), - }), - ).toBeTruthy(); - }); -}); - -describe('buildSchemaDiff', () => { - it('same file, no changes', () => { - expect( - buildSchemaDiff(schemaBeforeAfterTypes, schemaBeforeAfterTypes), - ).toEqual(new Set()); - }); - it('same RN file, no changes', () => { - expect(buildSchemaDiff(schemaWithRN, schemaWithRN)).toEqual(new Set()); - }); - it('two RN files, with incompatible Spec changes', () => { - expect( - schemaDiffExporter( - Array.from(buildSchemaDiff(schemaWithRN, schemaWithRNChanged))[0], - ), - ).toEqual( - expect.objectContaining({ - framework: 'ReactNative', - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - incompatibleChanges: expect.arrayContaining([ - expect.anything(), - ]), - }), - }), - ]), - }), - }), - ); - }); - it('RN file with nested object properties, no changes', () => { - expect( - buildSchemaDiff(schemaWithRnNestedObject, schemaWithRnNestedObject), - ).toEqual(new Set()); - }); - it('RN file with nested object properties, added', () => { - expect( - schemaDiffExporter( - Array.from( - buildSchemaDiff(schemaWithRnNestedChanged, schemaWithRnNestedObject), - )[0], - ), - ).toEqual( - expect.objectContaining({ - framework: 'ReactNative', - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - objectTypeChanges: expect.any(Object), - incompatibleChanges: expect.not.arrayContaining([ - expect.anything(), - ]), - }), - }), - ]), - }), - }), - ); - }); - it('RN file with nested object properties, removed', () => { - expect( - schemaDiffExporter( - Array.from( - buildSchemaDiff(schemaWithRnNestedObject, schemaWithRnNestedChanged), - )[0], - ), - ).toEqual( - expect.objectContaining({ - framework: 'ReactNative', - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - incompatibleChanges: expect.objectContaining({ - '0': expect.objectContaining({ - errorInformation: expect.objectContaining({ - message: removedPropertiesMessage, - }), - }), - }), - }), - }), - ]), - }), - }), - ); - }); - it('RN file with nested object properties, optional removed', () => { - expect( - schemaDiffExporter( - Array.from( - buildSchemaDiff(schemaWithRnNestedOptions, schemaWithRnNestedObject), - )[0], - ), - ).toEqual( - expect.objectContaining({ - framework: 'ReactNative', - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - incompatibleChanges: expect.objectContaining({ - '0': expect.objectContaining({ - errorInformation: expect.objectContaining({ - message: tooOptionalPropertiesMessage, - }), - }), - }), - }), - }), - ]), - }), - }), - ); - }); - it('RN file with nested object properties, nullable added', () => { - expect( - schemaDiffExporter( - Array.from( - buildSchemaDiff( - schemaWithRnNestedNullable, - schemaWithRnNestedOptions, - ), - )[0], - ), - ).toEqual( - expect.objectContaining({ - framework: 'ReactNative', - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - incompatibleChanges: expect.objectContaining({ - '0': expect.objectContaining({ - errorInformation: expect.objectContaining({ - message: typeNullableChangeMessage, - }), - }), - }), - }), - }), - ]), - }), - }), - ); - }); - it('RN file with nested object properties on function, made optional', () => { - expect( - schemaDiffExporter( - Array.from( - buildSchemaDiff(schemaWithRnNestedOptions, schemaWithRnNestedChanged), - )[0], - ), - ).toEqual( - expect.objectContaining({ - framework: 'ReactNative', - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - incompatibleChanges: expect.objectContaining({ - '0': expect.objectContaining({ - errorInformation: expect.objectContaining({ - message: tooOptionalPropertiesMessage, - }), - }), - }), - }), - }), - ]), - }), - }), - ); - }); - - describe('enums', () => { - describe('toNative', () => { - it('RN with enum types, same module', () => { - expect(buildSchemaDiff(schemaWithEnum, schemaWithEnum)).toEqual( - new Set(), - ); - }); - it('RN with enum types, and removal', () => { - expect( - schemaDiffExporter( - Array.from( - buildSchemaDiff(schemaWithEnum, schemaWithEnumChanges), - )[0], - ), - ).toEqual( - expect.objectContaining({ - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - newTypes: expect.not.arrayContaining([expect.anything()]), - deprecatedTypes: expect.not.arrayContaining([ - expect.anything(), - ]), - incompatibleChanges: expect.not.arrayContaining([ - expect.anything(), - ]), - objectTypeChanges: expect.any(Object), - }), - }), - ]), - }), - }), - ); - }); - it('RN with enum types, and addition', () => { - expect( - schemaDiffExporter( - Array.from( - buildSchemaDiff(schemaWithEnumChanges, schemaWithEnum), - )[0], - ), - ).toEqual( - expect.objectContaining({ - framework: 'ReactNative', - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - incompatibleChanges: expect.arrayContaining([ - expect.objectContaining({ - errorCode: 'addedEnumCases', - errorInformation: expect.objectContaining({ - message: addedEnumMessage, - }), - }), - ]), - }), - }), - ]), - }), - }), - ); - }); - it('RN with enum types, and type changes', () => { - expect( - schemaDiffExporter( - Array.from( - buildSchemaDiff(schemaWithEnum, schemaWithEnumTypeChanges), - )[0], - ), - ).toEqual( - expect.objectContaining({ - framework: 'ReactNative', - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - incompatibleChanges: expect.arrayContaining([ - expect.objectContaining({ - errorInformation: expect.objectContaining({ - mismatchedProperties: expect.arrayContaining([ - expect.objectContaining({ - fault: expect.objectContaining({ - previousError: expect.objectContaining({ - previousError: expect.objectContaining({ - message: - 'EnumDeclaration member types are not the same', - }), - }), - }), - }), - ]), - }), - }), - ]), - }), - }), - ]), - }), - }), - ); - }); - it('RN with enum types, and value changes', () => { - expect( - schemaDiffExporter( - Array.from( - buildSchemaDiff(schemaWithEnum, schemaWithEnumValueChanges), - )[0], - ), - ).toEqual( - expect.objectContaining({ - framework: 'ReactNative', - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - incompatibleChanges: expect.arrayContaining([ - expect.objectContaining({ - errorInformation: expect.objectContaining({ - mismatchedProperties: expect.arrayContaining([ - expect.objectContaining({ - fault: expect.objectContaining({ - previousError: expect.objectContaining({ - previousError: expect.objectContaining({ - message: 'Enum types do not match', - previousError: expect.objectContaining({ - message: - 'Enum contained a member with a type mismatch', - mismatchedMembers: expect.arrayContaining( - [ - expect.objectContaining({ - member: 'B', - }), - ], - ), - }), - }), - }), - }), - }), - ]), - }), - }), - ]), - }), - }), - ]), - }), - }), - ); - }); - }); - - describe('fromNative', () => { - it('RN with enum types, same module', () => { - expect( - buildSchemaDiff(schemaWithEnumFromNative, schemaWithEnumFromNative), - ).toEqual(new Set()); - }); - it('RN with enum types, and removal', () => { - expect( - schemaDiffExporter( - Array.from( - buildSchemaDiff( - schemaWithEnumFromNative, - schemaWithEnumFromNativeChanges, - ), - )[0], - ), - ).toEqual( - expect.objectContaining({ - framework: 'ReactNative', - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - incompatibleChanges: expect.arrayContaining([ - expect.objectContaining({ - errorCode: 'removedEnumCases', - errorInformation: expect.objectContaining({ - message: removedEnumMessage, - }), - }), - ]), - }), - }), - ]), - }), - }), - ); - }); - it('RN with enum types, and addition', () => { - expect( - schemaDiffExporter( - Array.from( - buildSchemaDiff( - schemaWithEnumFromNativeChanges, - schemaWithEnumFromNative, - ), - )[0], - ), - ).toEqual( - expect.objectContaining({ - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - newTypes: expect.not.arrayContaining([expect.anything()]), - deprecatedTypes: expect.not.arrayContaining([ - expect.anything(), - ]), - incompatibleChanges: expect.not.arrayContaining([ - expect.anything(), - ]), - objectTypeChanges: expect.any(Object), - }), - }), - ]), - }), - }), - ); - }); - it('RN with enum types, and type changes', () => { - expect( - schemaDiffExporter( - Array.from( - buildSchemaDiff( - schemaWithEnumFromNative, - schemaWithEnumFromNativeTypeChanges, - ), - )[0], - ), - ).toEqual( - expect.objectContaining({ - framework: 'ReactNative', - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - incompatibleChanges: expect.arrayContaining([ - expect.objectContaining({ - errorInformation: expect.objectContaining({ - mismatchedProperties: expect.arrayContaining([ - expect.objectContaining({ - fault: expect.objectContaining({ - previousError: expect.objectContaining({ - previousError: expect.objectContaining({ - mismatchedProperties: - expect.arrayContaining([ - expect.objectContaining({ - fault: expect.objectContaining({ - previousError: - expect.objectContaining({ - message: - 'EnumDeclaration member types are not the same', - }), - }), - }), - ]), - }), - }), - }), - }), - ]), - }), - }), - ]), - }), - }), - ]), - }), - }), - ); - }); - it('RN with enum types, and value changes', () => { - expect( - schemaDiffExporter( - Array.from( - buildSchemaDiff( - schemaWithEnumFromNative, - schemaWithEnumFromNativeValueChanges, - ), - )[0], - ), - ).toEqual( - expect.objectContaining({ - framework: 'ReactNative', - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - incompatibleChanges: expect.arrayContaining([ - expect.objectContaining({ - errorInformation: expect.objectContaining({ - mismatchedProperties: expect.arrayContaining([ - expect.objectContaining({ - fault: expect.objectContaining({ - previousError: expect.objectContaining({ - previousError: expect.objectContaining({ - mismatchedProperties: - expect.arrayContaining([ - expect.objectContaining({ - fault: expect.objectContaining({ - previousError: - expect.objectContaining({ - message: - 'Enum types do not match', - previousError: - expect.objectContaining({ - message: - 'Enum contained a member with a type mismatch', - mismatchedMembers: - expect.arrayContaining([ - expect.objectContaining( - { - member: 'B', - }, - ), - ]), - }), - }), - }), - }), - ]), - }), - }), - }), - }), - ]), - }), - }), - ]), - }), - }), - ]), - }), - }), - ); - }); - }); - }); - - it('RN with eventEmitters, same module', () => { - expect( - buildSchemaDiff(schemaWithEventEmitter, schemaWithEventEmitter), - ).toEqual(new Set()); - }); - - it('RN with eventEmitters, and eventType changes', () => { - expect( - schemaDiffExporter( - Array.from( - buildSchemaDiff( - schemaWithEventEmitter, - schemaWithEventEmitterChanges, - ), - )[0], - ), - ).toEqual( - expect.objectContaining({ - framework: 'ReactNative', - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - incompatibleChanges: expect.arrayContaining([ - expect.objectContaining({ - errorInformation: expect.objectContaining({ - message: - 'Object contained properties with type mismatches', - mismatchedProperties: expect.arrayContaining([ - expect.objectContaining({ - fault: expect.objectContaining({ - message: 'has conflicting type changes', - previousError: expect.objectContaining({ - message: - 'EventEmitter eventTypes are not equivalent', - }), - }), - }), - ]), - }), - }), - ]), - }), - }), - ]), - }), - }), - ); - }); - - it('RN with adding an optional argument to function', () => { - expect( - schemaDiffExporter( - Array.from( - buildSchemaDiff(schemaWithOptionalArgument, schemaWithRN), - )[0], - ), - ).toEqual( - expect.objectContaining({ - framework: 'ReactNative', - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - incompatibleChanges: expect.arrayContaining([ - expect.objectContaining({ - errorInformation: expect.objectContaining({ - message: - 'Object contained a property with a type mismatch', - mismatchedProperties: expect.arrayContaining([ - expect.objectContaining({ - fault: expect.objectContaining({ - message: 'has conflicting type changes', - previousError: expect.objectContaining({ - message: - 'Function types have differing length of arguments', - }), - }), - }), - ]), - }), - }), - ]), - }), - }), - ]), - }), - }), - ); - }); - - it('RN with removing an optional argument to function', () => { - expect( - schemaDiffExporter( - Array.from( - buildSchemaDiff(schemaWithRN, schemaWithOptionalArgument), - )[0], - ), - ).toEqual( - expect.objectContaining({ - framework: 'ReactNative', - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - incompatibleChanges: expect.arrayContaining([ - expect.objectContaining({ - errorInformation: expect.objectContaining({ - message: - 'Object contained a property with a type mismatch', - mismatchedProperties: expect.arrayContaining([ - expect.objectContaining({ - fault: expect.objectContaining({ - message: 'has conflicting type changes', - previousError: expect.objectContaining({ - message: - 'Function types have differing length of arguments', - }), - }), - }), - ]), - }), - }), - ]), - }), - }), - ]), - }), - }), - ); - }); - - it('RN with union types, same module', () => { - expect(buildSchemaDiff(schemaWithUnion, schemaWithUnion)).toEqual( - new Set(), - ); - }); - - it('RN with union types, and addition', () => { - expect( - schemaDiffExporter( - Array.from(buildSchemaDiff(schemaWithUnionChanges, schemaWithUnion))[0], - ), - ).toEqual( - expect.objectContaining({ - framework: 'ReactNative', - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - incompatibleChanges: expect.arrayContaining([ - expect.objectContaining({ - errorInformation: expect.objectContaining({ - message: addedUnionMessage, - }), - }), - ]), - }), - }), - ]), - }), - }), - ); - }); - it('RN with union types, and removal', () => { - expect( - schemaDiffExporter( - Array.from(buildSchemaDiff(schemaWithUnion, schemaWithUnionChanges))[0], - ), - ).toEqual( - expect.objectContaining({ - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - newTypes: expect.not.arrayContaining([expect.anything()]), - deprecatedTypes: expect.not.arrayContaining([ - expect.anything(), - ]), - incompatibleChanges: expect.not.arrayContaining([ - expect.anything(), - ]), - objectTypeChanges: expect.any(Object), - }), - }), - ]), - }), - }), - ); - }); - it('RN with union types from native, and addition', () => { - expect( - schemaDiffExporter( - Array.from( - buildSchemaDiff( - schemaWithUnionFromNativeChanges, - schemaWithUnionFromNative, - ), - )[0], - ), - ).toEqual( - expect.objectContaining({ - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - newTypes: expect.not.arrayContaining([expect.anything()]), - deprecatedTypes: expect.not.arrayContaining([ - expect.anything(), - ]), - incompatibleChanges: expect.not.arrayContaining([ - expect.anything(), - ]), - objectTypeChanges: expect.any(Object), - }), - }), - ]), - }), - }), - ); - }); - it('RN with union types from native, and removal', () => { - expect( - schemaDiffExporter( - Array.from( - buildSchemaDiff( - schemaWithUnionFromNative, - schemaWithUnionFromNativeChanges, - ), - )[0], - ), - ).toEqual( - expect.objectContaining({ - framework: 'ReactNative', - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - incompatibleChanges: expect.arrayContaining([ - expect.objectContaining({ - errorInformation: expect.objectContaining({ - message: removedUnionMessage, - }), - }), - ]), - }), - }), - ]), - }), - }), - ); - }); - - describe('NativeComponent', () => { - it('module to component; deprecated + new', () => { - expect( - Array.from(buildSchemaDiff(schemaWithRNNativeComponent, schemaWithRN)), - ).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - name: 'NativeComponent', - status: 'new', - }), - expect.objectContaining({ - name: 'NativeModule', - status: 'deprecated', - }), - ]), - ); - }); - - it('component changed to module; deprecated + new', () => { - expect( - Array.from(buildSchemaDiff(schemaWithRN, schemaWithRNNativeComponent)), - ).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - name: 'NativeModule', - status: 'new', - }), - expect.objectContaining({ - name: 'NativeComponent', - status: 'deprecated', - }), - ]), - ); - }); - - it('same RN component, no changes', () => { - expect( - buildSchemaDiff( - schemaWithRNNativeComponent, - schemaWithRNNativeComponent, - ), - ).toEqual(new Set()); - }); - - describe('commands', () => { - it('Command with additional arg', () => { - expect( - schemaDiffExporter( - Array.from( - buildSchemaDiff( - schemaNativeComponentWithCommandExtraArg, - schemaNativeComponentWithCommand, - ), - )[0], - ), - ).toEqual( - expect.objectContaining({ - framework: 'ReactNative', - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - incompatibleChanges: expect.arrayContaining([ - expect.objectContaining({ - errorInformation: expect.objectContaining({ - mismatchedProperties: expect.arrayContaining([ - expect.objectContaining({ - fault: expect.objectContaining({ - previousError: expect.objectContaining({ - message: - 'Function types have differing length of arguments', - }), - }), - }), - ]), - }), - }), - ]), - }), - }), - ]), - }), - }), - ); - }); - - it('Command with arg removed', () => { - expect( - schemaDiffExporter( - Array.from( - buildSchemaDiff( - schemaNativeComponentWithCommand, - schemaNativeComponentWithCommandExtraArg, - ), - )[0], - ), - ).toEqual( - expect.objectContaining({ - framework: 'ReactNative', - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - incompatibleChanges: expect.arrayContaining([ - expect.objectContaining({ - errorInformation: expect.objectContaining({ - mismatchedProperties: expect.arrayContaining([ - expect.objectContaining({ - fault: expect.objectContaining({ - previousError: expect.objectContaining({ - message: - 'Function types have differing length of arguments', - }), - }), - }), - ]), - }), - }), - ]), - }), - }), - ]), - }), - }), - ); - }); - - it('1 command to 2 commands is allowed', () => { - // This could technically result in an OTA issue if the command - // is called immediately and the native side throws on unrecognized - // commands. However, there is no way to do feature detection - // of commands today to protect against that. - // We are choosing to allow this change to be made since we previously - // had no protection for commands at all. - // See https://fb.workplace.com/groups/615693552291894/posts/1905124013348835 - // for more information. - expect( - summarizeDiffSet( - buildSchemaDiff( - schemaNativeComponentWithCommandExtraCommand, - schemaNativeComponentWithCommand, - ), - ).status, - ).toEqual('ok'); - }); - - it('2 commands to 1 command is allowed', () => { - expect( - summarizeDiffSet( - buildSchemaDiff( - schemaNativeComponentWithCommand, - schemaNativeComponentWithCommandExtraCommand, - ), - ).status, - ).toEqual('ok'); - }); - - it('0 commands to 1 command is allowed', () => { - expect( - summarizeDiffSet( - buildSchemaDiff( - schemaNativeComponentWithCommand, - schemaWithRNNativeComponent, - ), - ).status, - ).toEqual('ok'); - }); - - it('1 command to 0 commands is allowed', () => { - expect( - summarizeDiffSet( - buildSchemaDiff( - schemaWithRNNativeComponent, - schemaNativeComponentWithCommand, - ), - ).status, - ).toEqual('ok'); - }); - }); - - describe('props', () => { - it('prop with changed value', () => { - expect( - schemaDiffExporter( - Array.from( - buildSchemaDiff( - schemaNativeComponentWithPropsChanges, - schemaNativeComponentWithProps, - ), - )[0], - ), - ).toEqual( - expect.objectContaining({ - framework: 'ReactNative', - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - incompatibleChanges: expect.arrayContaining([ - expect.objectContaining({ - errorInformation: expect.objectContaining({ - message: - 'Object contained a property with a type mismatch', - }), - }), - ]), - }), - }), - ]), - }), - }), - ); - }); - - it('prop with changed default value should be okay', () => { - expect( - summarizeDiffSet( - buildSchemaDiff( - schemaNativeComponentWithPropsDefaultChange, - schemaNativeComponentWithProps, - ), - ).status, - ).toBe('ok'); - }); - - it('props with optional prop added should be okay', () => { - expect( - summarizeDiffSet( - buildSchemaDiff( - schemaNativeComponentWithPropsAddedOptionalProp, - schemaNativeComponentWithProps, - ), - ).status, - ).toBe('ok'); - }); - - it('props with optional prop removed should be okay', () => { - expect( - summarizeDiffSet( - buildSchemaDiff( - schemaNativeComponentWithProps, - schemaNativeComponentWithPropsAddedOptionalProp, - ), - ).status, - ).toBe('ok'); - }); - - it('props with required prop added should be okay', () => { - expect( - summarizeDiffSet( - buildSchemaDiff( - schemaNativeComponentWithPropsAddedRequiredProp, - schemaNativeComponentWithProps, - ), - ).status, - ).toBe('ok'); - }); - - it('props with required prop removed should fail', () => { - expect( - schemaDiffExporter( - Array.from( - buildSchemaDiff( - schemaNativeComponentWithProps, - schemaNativeComponentWithPropsAddedRequiredProp, - ), - )[0], - ), - ).toEqual( - expect.objectContaining({ - framework: 'ReactNative', - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - incompatibleChanges: expect.objectContaining({ - '0': expect.objectContaining({ - errorInformation: expect.objectContaining({ - message: removedPropertiesMessage, - }), - }), - }), - }), - }), - ]), - }), - }), - ); - }); - - it('props with nested object, adding an optional key should be okay', () => { - expect( - summarizeDiffSet( - buildSchemaDiff( - schemaNativeComponentWithPropsNestedObjectAddedOptionalKey, - schemaNativeComponentWithPropsNestedObject, - ), - ).status, - ).toBe('ok'); - }); - - it('props with nested object, removing an optional key should be okay', () => { - expect( - summarizeDiffSet( - buildSchemaDiff( - schemaNativeComponentWithPropsNestedObject, - schemaNativeComponentWithPropsNestedObjectAddedOptionalKey, - ), - ).status, - ).toBe('ok'); - }); - - it('props with nested object, adding a required key should be okay', () => { - expect( - summarizeDiffSet( - buildSchemaDiff( - schemaNativeComponentWithPropsNestedObjectAddedRequiredKey, - schemaNativeComponentWithPropsNestedObject, - ), - ).status, - ).toBe('ok'); - }); - - it('props with union and added option should fail', () => { - expect( - schemaDiffExporter( - Array.from( - buildSchemaDiff( - schemaNativeComponentWithPropsUnionAdded, - schemaNativeComponentWithPropsUnion, - ), - )[0], - ), - ).toEqual( - expect.objectContaining({ - framework: 'ReactNative', - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - incompatibleChanges: expect.objectContaining({ - '0': expect.objectContaining({ - errorInformation: expect.objectContaining({ - message: addedUnionMessage, - }), - }), - }), - }), - }), - ]), - }), - }), - ); - }); - - it('props with union and removed option should be ok', () => { - expect( - summarizeDiffSet( - buildSchemaDiff( - schemaNativeComponentWithPropsUnion, - schemaNativeComponentWithPropsUnionAdded, - ), - ).status, - ).toBe('ok'); - }); - - it('props with array union and added option should fail', () => { - expect( - schemaDiffExporter( - Array.from( - buildSchemaDiff( - schemaNativeComponentWithPropsArrayUnionAdded, - schemaNativeComponentWithPropsArrayUnion, - ), - )[0], - ), - ).toEqual( - expect.objectContaining({ - framework: 'ReactNative', - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - incompatibleChanges: expect.objectContaining({ - '0': expect.objectContaining({ - errorInformation: expect.objectContaining({ - message: addedUnionMessage, - }), - }), - }), - }), - }), - ]), - }), - }), - ); - }); - - it('props with array union and removed option should be ok', () => { - // This is risky due to these being stored from component props codegen - // in C++ ints via bitshift which might change the resulting - // int value for the same inputs. - expect( - summarizeDiffSet( - buildSchemaDiff( - schemaNativeComponentWithPropsArrayUnion, - schemaNativeComponentWithPropsArrayUnionAdded, - ), - ).status, - ).toBe('ok'); - }); - }); - }); - - describe('RN new codegen', () => { - describe('Native Module', () => { - it('removed', () => { - expect( - summarizeDiffSet( - buildSchemaDiff(schemaWithRNNativeComponent, schemaWithRN), - ).status, - ).toEqual('patchable'); - }); - it('added', () => { - expect( - schemaDiffExporter( - Array.from( - buildSchemaDiff(schemaWithRN, schemaWithRNNativeComponent), - )[0], - ), - ).toEqual( - expect.objectContaining({ - name: 'NativeModule', - status: 'new', - }), - ); - }); - }); - }); -}); - -describe('RN NativeModule getConstants type diffing', () => { - it('should not allow required constants to be added to NativeModules', () => { - const schemaDiff = buildSchemaDiff( - schemaGetConstantsAddedRequiredConstant, // new - schemaGetConstants, // old - ); - - expect(summarizeDiffSet(schemaDiff).status).toBe('incompatible'); - expect(schemaDiffExporter(Array.from(schemaDiff)[0])).toEqual( - expect.objectContaining({ - status: expect.objectContaining({ - incompatibleSpecs: expect.arrayContaining([ - expect.objectContaining({ - changeInformation: expect.objectContaining({ - incompatibleChanges: expect.arrayContaining([ - expect.objectContaining({ - errorInformation: expect.objectContaining({ - message: addedPropertiesMessage, - }), - }), - ]), - }), - }), - ]), - }), - }), - ); - }); - - it('should allow optional constants to be added to NativeModules', () => { - const schemaDiff = buildSchemaDiff( - schemaGetConstantsAddedOptionalConstant, // new - schemaGetConstants, // old - ); - - expect(summarizeDiffSet(schemaDiff).status).toBe('ok'); - }); - - it('should allow removal of required constants from NativeModules', () => { - const schemaDiff = buildSchemaDiff( - schemaGetConstants, // new - schemaGetConstantsAddedRequiredConstant, // old - ); - - expect(summarizeDiffSet(schemaDiff).status).toBe('ok'); - }); - - it('should allow removal of optional constants from NativeModules', () => { - const schemaDiff = buildSchemaDiff( - schemaGetConstants, // new - schemaGetConstantsAddedOptionalConstant, // old - ); - - expect(summarizeDiffSet(schemaDiff).status).toBe('ok'); - }); - - it('should not allow promotion of optional constants to required constants', () => { - const schemaDiff = buildSchemaDiff( - schemaGetConstantsAddedRequiredConstant, // new - schemaGetConstantsAddedOptionalConstant, // old - ); - - expect(summarizeDiffSet(schemaDiff).status).toBe('incompatible'); - }); - - it('should allow required constants to become optional constants', () => { - const schemaDiff = buildSchemaDiff( - schemaGetConstantsAddedOptionalConstant, // new - schemaGetConstantsAddedRequiredConstant, // old - ); - - expect(summarizeDiffSet(schemaDiff).status).toBe('ok'); - }); -}); - -describe('RN NativeModule getConstants $ReadOnly type diffing', () => { - it('should not allow required constants to be added to NativeModules', () => { - const schemaDiff = buildSchemaDiff( - schemaGetConstantsAddedRequiredConstantReadOnly, // new - schemaGetConstantsReadOnly, // old - ); - - expect(summarizeDiffSet(schemaDiff).status).toBe('incompatible'); - }); - - it('should allow optional constants to be added to NativeModules', () => { - const schemaDiff = buildSchemaDiff( - schemaGetConstantsAddedOptionalConstantReadOnly, // new - schemaGetConstantsReadOnly, // old - ); - - expect(summarizeDiffSet(schemaDiff).status).toBe('ok'); - }); - - it('should allow removal of required constants from NativeModules', () => { - const schemaDiff = buildSchemaDiff( - schemaGetConstantsReadOnly, // new - schemaGetConstantsAddedRequiredConstantReadOnly, // old - ); - - expect(summarizeDiffSet(schemaDiff).status).toBe('ok'); - }); - - it('should allow removal of optional constants from NativeModules', () => { - const schemaDiff = buildSchemaDiff( - schemaGetConstantsReadOnly, // new - schemaGetConstantsAddedOptionalConstantReadOnly, // old - ); - - expect(summarizeDiffSet(schemaDiff).status).toBe('ok'); - }); - - it('should not allow promotion of optional constants to required constants', () => { - const schemaDiff = buildSchemaDiff( - schemaGetConstantsAddedRequiredConstantReadOnly, // new - schemaGetConstantsAddedOptionalConstantReadOnly, // old - ); - - expect(summarizeDiffSet(schemaDiff).status).toBe('incompatible'); - }); - - it('should allow required constants to become optional constants', () => { - const schemaDiff = buildSchemaDiff( - schemaGetConstantsAddedOptionalConstantReadOnly, // new - schemaGetConstantsAddedRequiredConstantReadOnly, // old - ); - - expect(summarizeDiffSet(schemaDiff).status).toBe('ok'); - }); -}); - -describe('summarizeDiffSet', () => { - const set = new Set(); - it('is given empty set', () => { - expect(summarizeDiffSet(set).status).toBe('ok'); - }); - it('is given set with one new', () => { - set.add({ - name: 'SampleName', - framework: 'ReactNative', - status: 'new', - }); - expect(summarizeDiffSet(set).status).toBe('patchable'); - }); - it('is given complex set', () => { - expect( - summarizeDiffSet( - buildSchemaDiff( - schemaBeforeAfterTypes, - schemaBeforeAfterTypesTypesRemoved, - ), - ).status, - ).toBe('incompatible'); - }); - it('is given a diff that has incompatible changes in the boundary', () => { - expect( - summarizeDiffSet( - buildSchemaDiff( - schemaBeforeAfterTypes, - schemaBeforeAfterTypesTypeChanged, - ), - ).status, - ).toBe('incompatible'); - }); -}); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-all-types/NativeComponent.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-all-types/NativeComponent.js.flow deleted file mode 100644 index ad22b238464..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-all-types/NativeComponent.js.flow +++ /dev/null @@ -1,169 +0,0 @@ -/** - * 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 strict-local - * @format - */ - -import type {HostComponent} from 'react-native'; -import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; -import type {ColorValue} from 'react-native/Libraries/StyleSheet/StyleSheet'; -import type { - EdgeInsetsValue, - PointValue, -} from 'react-native/Libraries/StyleSheet/StyleSheetTypes'; -import type {RootTag} from 'react-native/Libraries/TurboModule/RCTExport'; -import type { - Double, - Float, - Int32, - UnsafeMixed, - WithDefault, -} from 'react-native/Libraries/Types/CodegenTypes'; - -import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands'; -import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; - -type NativeProps = $ReadOnly<{ - ...ViewProps, - bool: boolean, - string: string, - double: Double, - float: Float, - int: Int32, - mixed: UnsafeMixed, - - optionalBool?: WithDefault, - optionalString?: WithDefault, - optionalStringDiffDefault?: WithDefault, - optionalDouble?: WithDefault, - optionalFloat?: WithDefault, - optionalInt?: WithDefault, - - reserverdEdgeInsets: EdgeInsetsValue, - reservedPointValue: PointValue, - - stringUnion?: WithDefault<'foo' | 'bar', 'bar'>, - intUnion?: WithDefault<1 | 2, 1>, - - nestedObject: $ReadOnly<{ - string: string, - color: ColorValue, - }>, - - nestedObjectChanged: $ReadOnly<{ - string: boolean, - color: ColorValue, - }>, - - arrayStringUnion?: WithDefault<$ReadOnlyArray<'foo' | 'bar'>, 'foo'>, - arrayStringUnionExtra?: WithDefault< - $ReadOnlyArray<'foo' | 'bar' | 'baz'>, - 'bar', - >, - - arrayNestedObject: $ReadOnlyArray< - $ReadOnly<{ - string: string, - color: ColorValue, - }>, - >, - - arrayNestedObjectChange: $ReadOnlyArray< - $ReadOnly<{ - string: boolean, - color: ColorValue, - }>, - >, -}>; - -type NativeType = HostComponent; - -type Int = Int32; -type Str = string; -type Bool = boolean; -type Fl = Float; -type Dbl = Double; -type CustomObj = {foo: string, bar: number}; -type CustomObj2 = {a: Int32, b: string}; - -interface NativeCommands { - +methodInt: (viewRef: React.ElementRef, a: Int32) => void; - +methodIntString: ( - viewRef: React.ElementRef, - a: Int32, - b: string, - ) => void; - +methodString: (viewRef: React.ElementRef, a: string) => void; - +methodBool: (viewRef: React.ElementRef, a: boolean) => void; - +methodFloat: (viewRef: React.ElementRef, a: Float) => void; - +methodDouble: (viewRef: React.ElementRef, a: Double) => void; - - +methodIntAlias: (viewRef: React.ElementRef, a: Int) => void; - +methodStringAlias: (viewRef: React.ElementRef, a: Str) => void; - +methodBoolAlias: (viewRef: React.ElementRef, a: Bool) => void; - +methodFloatAlias: (viewRef: React.ElementRef, a: Fl) => void; - +methodDoubleAlias: (viewRef: React.ElementRef, a: Dbl) => void; - - +methodIntArray: ( - viewRef: React.ElementRef, - a: Array, - ) => void; - +methodStringArray: ( - viewRef: React.ElementRef, - a: Array, - ) => void; - +methodBoolArray: ( - viewRef: React.ElementRef, - a: Array, - ) => void; - +methodFloatArray: ( - viewRef: React.ElementRef, - a: Array, - ) => void; - +methodDoubleArray: ( - viewRef: React.ElementRef, - a: Array, - ) => void; - +methodCustomObjArray: ( - viewRef: React.ElementRef, - a: Array, - ) => void; - +methodCustomObj2Array: ( - viewRef: React.ElementRef, - a: Array, - ) => void; - - +methodRootTag: (viewRef: React.ElementRef, a: RootTag) => void; -} - -export const Commands: NativeCommands = codegenNativeCommands({ - supportedCommands: [ - 'methodInt', - 'methodIntString', - 'methodString', - 'methodBool', - 'methodFloat', - 'methodDouble', - 'methodIntAlias', - 'methodStringAlias', - 'methodBoolAlias', - 'methodFloatAlias', - 'methodDoubleAlias', - 'methodIntArray', - 'methodStringArray', - 'methodBoolArray', - 'methodFloatArray', - 'methodDoubleArray', - 'methodCustomObjArray', - 'methodCustomObj2Array', - 'methodRootTag', - ], -}); - -export default codegenNativeComponent( - 'NativeComponent', -) as NativeType; diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-command-all-basic-types-arrays/NativeComponent.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-command-all-basic-types-arrays/NativeComponent.js.flow deleted file mode 100644 index 1c55d96e879..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-command-all-basic-types-arrays/NativeComponent.js.flow +++ /dev/null @@ -1,60 +0,0 @@ -/** - * 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 strict-local - * @format - */ - -import type {HostComponent} from 'react-native'; -import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; -import type { - Double, - Float, - Int32, -} from 'react-native/Libraries/Types/CodegenTypes'; - -import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands'; -import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; - -type NativeProps = $ReadOnly<{ - ...ViewProps, -}>; - -type NativeType = HostComponent; - -interface NativeCommands { - +methodInt: (viewRef: React.ElementRef, a: Array) => void; - +methodString: ( - viewRef: React.ElementRef, - a: Array, - ) => void; - +methodBool: ( - viewRef: React.ElementRef, - a: Array, - ) => void; - +methodFloat: ( - viewRef: React.ElementRef, - a: Array, - ) => void; - +methodDouble: ( - viewRef: React.ElementRef, - a: Array, - ) => void; -} - -export const Commands: NativeCommands = codegenNativeCommands({ - supportedCommands: [ - 'methodInt', - 'methodString', - 'methodBool', - 'methodFloat', - 'methodDouble', - ], -}); - -export default codegenNativeComponent( - 'NativeComponent', -) as NativeType; diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-command-all-basic-types/NativeComponent.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-command-all-basic-types/NativeComponent.js.flow deleted file mode 100644 index eac4e790272..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-command-all-basic-types/NativeComponent.js.flow +++ /dev/null @@ -1,48 +0,0 @@ -/** - * 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 strict-local - * @format - */ - -import type {HostComponent} from 'react-native'; -import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; -import type { - Double, - Float, - Int32, -} from 'react-native/Libraries/Types/CodegenTypes'; - -import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands'; -import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; - -type NativeProps = $ReadOnly<{ - ...ViewProps, -}>; - -type NativeType = HostComponent; - -interface NativeCommands { - +methodInt: (viewRef: React.ElementRef, a: Int32) => void; - +methodString: (viewRef: React.ElementRef, a: string) => void; - +methodBool: (viewRef: React.ElementRef, a: boolean) => void; - +methodFloat: (viewRef: React.ElementRef, a: Float) => void; - +methodDouble: (viewRef: React.ElementRef, a: Double) => void; -} - -export const Commands: NativeCommands = codegenNativeCommands({ - supportedCommands: [ - 'methodInt', - 'methodString', - 'methodBool', - 'methodFloat', - 'methodDouble', - ], -}); - -export default codegenNativeComponent( - 'NativeComponent', -) as NativeType; diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-command-changed/NativeComponent.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-command-changed/NativeComponent.js.flow deleted file mode 100644 index a0c2bf47be8..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-command-changed/NativeComponent.js.flow +++ /dev/null @@ -1,33 +0,0 @@ -/** - * 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 strict-local - * @format - */ - -import type {HostComponent} from 'react-native'; -import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; - -import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands'; -import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; - -type NativeProps = $ReadOnly<{ - ...ViewProps, -}>; - -type NativeType = HostComponent; - -interface NativeCommands { - +methodInt: (viewRef: React.ElementRef, a: string) => void; -} - -export const Commands: NativeCommands = codegenNativeCommands({ - supportedCommands: ['methodInt'], -}); - -export default codegenNativeComponent( - 'NativeComponent', -) as NativeType; diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-command-extra-arg/NativeComponent.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-command-extra-arg/NativeComponent.js.flow deleted file mode 100644 index 4a52639b60d..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-command-extra-arg/NativeComponent.js.flow +++ /dev/null @@ -1,38 +0,0 @@ -/** - * 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 strict-local - * @format - */ - -import type {HostComponent} from 'react-native'; -import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; -import type {Int32} from 'react-native/Libraries/Types/CodegenTypes'; - -import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands'; -import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; - -type NativeProps = $ReadOnly<{ - ...ViewProps, -}>; - -type NativeType = HostComponent; - -interface NativeCommands { - +methodInt: ( - viewRef: React.ElementRef, - a: Int32, - b: string, - ) => void; -} - -export const Commands: NativeCommands = codegenNativeCommands({ - supportedCommands: ['methodInt'], -}); - -export default codegenNativeComponent( - 'NativeComponent', -) as NativeType; diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-command-extra-command/NativeComponent.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-command-extra-command/NativeComponent.js.flow deleted file mode 100644 index 8159b7a528f..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-command-extra-command/NativeComponent.js.flow +++ /dev/null @@ -1,35 +0,0 @@ -/** - * 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 strict-local - * @format - */ - -import type {HostComponent} from 'react-native'; -import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; -import type {Int32} from 'react-native/Libraries/Types/CodegenTypes'; - -import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands'; -import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; - -type NativeProps = $ReadOnly<{ - ...ViewProps, -}>; - -type NativeType = HostComponent; - -interface NativeCommands { - +methodInt: (viewRef: React.ElementRef, a: Int32) => void; - +methodString: (viewRef: React.ElementRef, a: string) => void; -} - -export const Commands: NativeCommands = codegenNativeCommands({ - supportedCommands: ['methodInt', 'methodString'], -}); - -export default codegenNativeComponent( - 'NativeComponent', -) as NativeType; diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-command/NativeComponent.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-command/NativeComponent.js.flow deleted file mode 100644 index 38e623fb18d..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-command/NativeComponent.js.flow +++ /dev/null @@ -1,34 +0,0 @@ -/** - * 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 strict-local - * @format - */ - -import type {HostComponent} from 'react-native'; -import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; -import type {Int32} from 'react-native/Libraries/Types/CodegenTypes'; - -import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands'; -import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; - -type NativeProps = $ReadOnly<{ - ...ViewProps, -}>; - -type NativeType = HostComponent; - -interface NativeCommands { - +methodInt: (viewRef: React.ElementRef, a: Int32) => void; -} - -export const Commands: NativeCommands = codegenNativeCommands({ - supportedCommands: ['methodInt'], -}); - -export default codegenNativeComponent( - 'NativeComponent', -) as NativeType; diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-added-optional-prop/NativeComponent.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-added-optional-prop/NativeComponent.js.flow deleted file mode 100644 index 6e52c2d4a76..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-added-optional-prop/NativeComponent.js.flow +++ /dev/null @@ -1,30 +0,0 @@ -/** - * 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. - * - * @format - * @flow strict-local - */ - -import type {HostComponent} from 'react-native'; -import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; -import type { - Int32, - WithDefault, -} from 'react-native/Libraries/Types/CodegenTypes'; - -import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; - -export type Props = $ReadOnly<{ - ...ViewProps, - text: string, - backgroundColor?: WithDefault, - height?: WithDefault, - width?: WithDefault, -}>; - -export default (codegenNativeComponent( - 'NativeComponent', -): HostComponent); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-added-required-prop/NativeComponent.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-added-required-prop/NativeComponent.js.flow deleted file mode 100644 index 3b4b3f8956b..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-added-required-prop/NativeComponent.js.flow +++ /dev/null @@ -1,30 +0,0 @@ -/** - * 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. - * - * @format - * @flow strict-local - */ - -import type {HostComponent} from 'react-native'; -import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; -import type { - Int32, - WithDefault, -} from 'react-native/Libraries/Types/CodegenTypes'; - -import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; - -export type Props = $ReadOnly<{ - ...ViewProps, - text: string, - backgroundColor?: WithDefault, - height?: WithDefault, - width: Int32, -}>; - -export default (codegenNativeComponent( - 'NativeComponent', -): HostComponent); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-all-types/NativeComponent.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-all-types/NativeComponent.js.flow deleted file mode 100644 index 47f800cdaad..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-all-types/NativeComponent.js.flow +++ /dev/null @@ -1,39 +0,0 @@ -/** - * 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. - * - * @format - * @flow strict-local - */ - -import type {HostComponent} from 'react-native'; -import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; -import type { - Double, - Float, - Int32, - WithDefault, -} from 'react-native/Libraries/Types/CodegenTypes'; - -import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; - -export type Props = $ReadOnly<{ - ...ViewProps, - bool: boolean, - string: string, - double: Double, - float: Float, - int: Int32, - stringUnion: WithDefault<'foo' | 'bar', 'bar'>, - intUnion: WithDefault<1 | 2, 1>, - mixed: mixed, - - backgroundColor?: WithDefault, - height?: WithDefault, -}>; - -export default (codegenNativeComponent( - 'NativeComponent', -): HostComponent); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-array-union-added/NativeComponent.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-array-union-added/NativeComponent.js.flow deleted file mode 100644 index b713bfa1c1f..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-array-union-added/NativeComponent.js.flow +++ /dev/null @@ -1,24 +0,0 @@ -/** - * 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. - * - * @format - * @flow strict-local - */ - -import type {HostComponent} from 'react-native'; -import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; -import type {WithDefault} from 'react-native/Libraries/Types/CodegenTypes'; - -import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; - -export type Props = $ReadOnly<{ - ...ViewProps, - sizes?: WithDefault<$ReadOnlyArray<'small' | 'large' | 'huge'>, 'small'>, -}>; - -export default (codegenNativeComponent( - 'NativeComponent', -): HostComponent); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-array-union/NativeComponent.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-array-union/NativeComponent.js.flow deleted file mode 100644 index da55640b3d2..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-array-union/NativeComponent.js.flow +++ /dev/null @@ -1,24 +0,0 @@ -/** - * 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. - * - * @format - * @flow strict-local - */ - -import type {HostComponent} from 'react-native'; -import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; -import type {WithDefault} from 'react-native/Libraries/Types/CodegenTypes'; - -import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; - -export type Props = $ReadOnly<{ - ...ViewProps, - sizes?: WithDefault<$ReadOnlyArray<'small' | 'large'>, 'small'>, -}>; - -export default (codegenNativeComponent( - 'NativeComponent', -): HostComponent); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-changes/NativeComponent.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-changes/NativeComponent.js.flow deleted file mode 100644 index a816e4a42d6..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-changes/NativeComponent.js.flow +++ /dev/null @@ -1,29 +0,0 @@ -/** - * 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. - * - * @format - * @flow strict-local - */ - -import type {HostComponent} from 'react-native'; -import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; -import type { - Int32, - WithDefault, -} from 'react-native/Libraries/Types/CodegenTypes'; - -import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; - -export type Props = $ReadOnly<{ - ...ViewProps, - text: Int32, - backgroundColor?: WithDefault, - height?: WithDefault, -}>; - -export default (codegenNativeComponent( - 'NativeComponent', -): HostComponent); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-default-change/NativeComponent.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-default-change/NativeComponent.js.flow deleted file mode 100644 index f7768a1ab00..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-default-change/NativeComponent.js.flow +++ /dev/null @@ -1,29 +0,0 @@ -/** - * 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. - * - * @format - * @flow strict-local - */ - -import type {HostComponent} from 'react-native'; -import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; -import type { - Int32, - WithDefault, -} from 'react-native/Libraries/Types/CodegenTypes'; - -import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; - -export type Props = $ReadOnly<{ - ...ViewProps, - text: string, - backgroundColor?: WithDefault, - height?: WithDefault, -}>; - -export default (codegenNativeComponent( - 'NativeComponent', -): HostComponent); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-nested-object-added-optional-key/NativeComponent.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-nested-object-added-optional-key/NativeComponent.js.flow deleted file mode 100644 index 412d465a48c..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-nested-object-added-optional-key/NativeComponent.js.flow +++ /dev/null @@ -1,35 +0,0 @@ -/** - * 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. - * - * @format - * @flow strict-local - */ - -import type {HostComponent} from 'react-native'; -import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; -import type { - Float, - Int32, - WithDefault, -} from 'react-native/Libraries/Types/CodegenTypes'; - -import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; - -export type Props = $ReadOnly<{ - ...ViewProps, - text: string, - backgroundColor?: WithDefault, - height?: WithDefault, - pins: $ReadOnly<{ - x: Float, - y: Float, - color?: WithDefault, - }>, -}>; - -export default (codegenNativeComponent( - 'NativeComponent', -): HostComponent); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-nested-object-added-required-key/NativeComponent.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-nested-object-added-required-key/NativeComponent.js.flow deleted file mode 100644 index 31b5bf6aeb6..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-nested-object-added-required-key/NativeComponent.js.flow +++ /dev/null @@ -1,35 +0,0 @@ -/** - * 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. - * - * @format - * @flow strict-local - */ - -import type {HostComponent} from 'react-native'; -import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; -import type { - Float, - Int32, - WithDefault, -} from 'react-native/Libraries/Types/CodegenTypes'; - -import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; - -export type Props = $ReadOnly<{ - ...ViewProps, - text: string, - backgroundColor?: WithDefault, - height?: WithDefault, - pins: $ReadOnly<{ - x: Float, - y: Float, - color: string, - }>, -}>; - -export default (codegenNativeComponent( - 'NativeComponent', -): HostComponent); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-nested-object/NativeComponent.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-nested-object/NativeComponent.js.flow deleted file mode 100644 index 1c423bbae7e..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-nested-object/NativeComponent.js.flow +++ /dev/null @@ -1,34 +0,0 @@ -/** - * 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. - * - * @format - * @flow strict-local - */ - -import type {HostComponent} from 'react-native'; -import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; -import type { - Float, - Int32, - WithDefault, -} from 'react-native/Libraries/Types/CodegenTypes'; - -import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; - -export type Props = $ReadOnly<{ - ...ViewProps, - text: string, - backgroundColor?: WithDefault, - height?: WithDefault, - pins: $ReadOnly<{ - x: Float, - y: Float, - }>, -}>; - -export default (codegenNativeComponent( - 'NativeComponent', -): HostComponent); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-union-added/NativeComponent.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-union-added/NativeComponent.js.flow deleted file mode 100644 index 2a4fcf90d8f..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-union-added/NativeComponent.js.flow +++ /dev/null @@ -1,24 +0,0 @@ -/** - * 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. - * - * @format - * @flow strict-local - */ - -import type {HostComponent} from 'react-native'; -import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; -import type {WithDefault} from 'react-native/Libraries/Types/CodegenTypes'; - -import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; - -export type Props = $ReadOnly<{ - ...ViewProps, - size?: WithDefault<'small' | 'large' | 'huge', 'small'>, -}>; - -export default (codegenNativeComponent( - 'NativeComponent', -): HostComponent); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-union/NativeComponent.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-union/NativeComponent.js.flow deleted file mode 100644 index ce3187bd455..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props-union/NativeComponent.js.flow +++ /dev/null @@ -1,24 +0,0 @@ -/** - * 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. - * - * @format - * @flow strict-local - */ - -import type {HostComponent} from 'react-native'; -import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; -import type {WithDefault} from 'react-native/Libraries/Types/CodegenTypes'; - -import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; - -export type Props = $ReadOnly<{ - ...ViewProps, - size?: WithDefault<'small' | 'large', 'small'>, -}>; - -export default (codegenNativeComponent( - 'NativeComponent', -): HostComponent); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props/NativeComponent.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props/NativeComponent.js.flow deleted file mode 100644 index d8f9bd8777e..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component-with-props/NativeComponent.js.flow +++ /dev/null @@ -1,29 +0,0 @@ -/** - * 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. - * - * @format - * @flow strict-local - */ - -import type {HostComponent} from 'react-native'; -import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; -import type { - Int32, - WithDefault, -} from 'react-native/Libraries/Types/CodegenTypes'; - -import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; - -export type Props = $ReadOnly<{ - ...ViewProps, - text: string, - backgroundColor?: WithDefault, - height?: WithDefault, -}>; - -export default (codegenNativeComponent( - 'NativeComponent', -): HostComponent); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component/NativeComponent.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component/NativeComponent.js.flow deleted file mode 100644 index 56b3fba9ee6..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-component/NativeComponent.js.flow +++ /dev/null @@ -1,22 +0,0 @@ -/** - * 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. - * - * @format - * @flow strict-local - */ - -import type {HostComponent} from 'react-native'; -import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; - -import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; - -export type Props = $ReadOnly<{ - ...ViewProps, -}>; - -export default (codegenNativeComponent( - 'NativeComponent', -): HostComponent); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-before-after-types-removed/NativeModuleBeforeAfterTypes.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-before-after-types-removed/NativeModuleBeforeAfterTypes.js.flow deleted file mode 100644 index 93fbf957584..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-before-after-types-removed/NativeModuleBeforeAfterTypes.js.flow +++ /dev/null @@ -1,33 +0,0 @@ -/** - * 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 - */ - -/* eslint-disable no-unused-vars */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -type SimpleObject = {||}; - -type BeforeMismatchGeneric = {||}; - -type BeforeMatchingGeneric = {||}; -type AfterMatchingGeneric = {||}; - -export interface Spec extends TurboModule { - +simpleObject: (a: SimpleObject) => void; - +beforeMismatchGeneric: (a: BeforeMismatchGeneric) => void; - - +beforeMatchingGeneric: (a: BeforeMatchingGeneric) => void; - +afterMatchingGeneric: (a: AfterMatchingGeneric) => void; -} - -(TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-before-after-types-type-changed/NativeModuleBeforeAfterTypes.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-before-after-types-type-changed/NativeModuleBeforeAfterTypes.js.flow deleted file mode 100644 index e2b9af63ab9..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-before-after-types-type-changed/NativeModuleBeforeAfterTypes.js.flow +++ /dev/null @@ -1,73 +0,0 @@ -/** - * 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 - */ - -/* eslint-disable no-unused-vars */ -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -type SimpleObject = {||}; - -type BeforeMismatchGeneric = {||}; -type AfterMismatchGeneric = {||}; - -type BeforeMatchingGeneric = {||}; -type AfterMatchingGeneric = {||}; - -type BooleanType = boolean; -type StringType = string; - -type SimpleFunction = (a: string) => string; -type SimpleFunction2 = (a: string) => number; -type SimpleFunction3 = (foo: string) => string; -type SimpleFunction4 = (a: number) => string; - -type SimpleUnion = 'str1' | 'str2'; -type SimpleUnionLonger = 'str1' | 'str2' | 'str3'; -type SimpleUnion2 = 4 | 5; -type SimpleUnion3 = {} | {key: 'value'}; -type SimpleUnion4 = BooleanType | StringType | SimpleObject; - -type FunctionReferencingUnion = (a: SimpleUnion) => void; -type FunctionReferencingUnion2 = (a: SimpleUnion2) => void; - -type SimpleArray = Array; -// changed from Array to Array -type SimpleArrayChange = Array; - -export interface Spec extends TurboModule { - +exampleFunction: (a: SimpleObject) => void; - +simpleObject: (a: SimpleObject) => void; - +beforeMismatchGeneric: (a: BeforeMismatchGeneric) => void; - +afterMismatchGeneric: (a: AfterMismatchGeneric) => void; - - +beforeMatchingGeneric: (a: BeforeMatchingGeneric) => void; - +afterMatchingGeneric: (a: AfterMatchingGeneric) => void; - - +booleanType: (a: BooleanType) => void; - +stringType: (a: StringType) => void; - - +simpleFunction: (a: string) => string; - +simpleFunction2: (a: string) => number; - +simpleFunction3: (foo: string) => string; - +simpleFunction4: (a: number) => string; - - +simpleUnion: (a: SimpleUnion) => void; - +simpleUnionLonger: (a: SimpleUnionLonger) => void; - +simpleUnion2: (a: SimpleUnion2) => void; - +simpleUnion3: (a: SimpleUnion3) => void; - +simpleUnion4: (a: SimpleUnion4) => void; - - +simpleArray: (a: SimpleArray) => void; - +simpleArrayChange: (a: SimpleArrayChange) => void; - } - - (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', - ): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-before-after-types/NativeModuleBeforeAfterTypes.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-before-after-types/NativeModuleBeforeAfterTypes.js.flow deleted file mode 100644 index e5ba221a889..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-before-after-types/NativeModuleBeforeAfterTypes.js.flow +++ /dev/null @@ -1,66 +0,0 @@ -/** - * 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 - */ - -/* eslint-disable no-unused-vars */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -type SimpleObject = {}; - -type BeforeMismatchGeneric = {}; -type AfterMismatchGeneric = {}; - -type BeforeMatchingGeneric = {}; -type AfterMatchingGeneric = {}; - -type BooleanType = boolean; -type StringType = string; - -type SimpleUnion = 'str1' | 'str2'; -type SimpleUnionLonger = 'str1' | 'str2' | 'str3'; -type SimpleUnion2 = 4 | 5; -type SimpleUnion3 = {} | {key: 'value'}; -type SimpleUnion4 = BooleanType | StringType | SimpleObject; - -type SimpleArray = Array; -type SimpleArrayChange = Array; - - -export interface Spec extends TurboModule { - +exampleFunction: (a: SimpleObject) => void; - +simpleObject: (a: SimpleObject) => void; - +beforeMismatchGeneric: (a: BeforeMismatchGeneric) => void; - +afterMismatchGeneric: (a: AfterMismatchGeneric) => void; - - +beforeMatchingGeneric: (a: BeforeMatchingGeneric) => void; - +afterMatchingGeneric: (a: AfterMatchingGeneric) => void; - - +booleanType: (a: BooleanType) => void; - +stringType: (a: StringType) => void; - - +simpleFunction: (a: string) => string; - +simpleFunction2: (a: string) => number; - +simpleFunction3: (foo: string) => string; - +simpleFunction4: (a: number) => string; - - +simpleUnion: (a: SimpleUnion) => void; - +simpleUnionLonger: (a: SimpleUnionLonger) => void; - +simpleUnion2: (a: SimpleUnion2) => void; - +simpleUnion3: (a: SimpleUnion3) => void; - +simpleUnion4: (a: SimpleUnion4) => void; - - +simpleArray: (a: SimpleArray) => void; - +simpleArrayChange: (a: SimpleArrayChange) => void; -} - -(TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-changed/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-changed/NativeModule.js.flow deleted file mode 100644 index a7800a22f51..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-changed/NativeModule.js.flow +++ /dev/null @@ -1,24 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -export interface Spec extends TurboModule { - +exampleFunction: (a: string, b: number) => void; - +getConstants: () => { - +exampleConstant: string, - }; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-get-constants-added-optional-constant-readonly/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-get-constants-added-optional-constant-readonly/NativeModule.js.flow deleted file mode 100644 index 32b27c558c5..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-get-constants-added-optional-constant-readonly/NativeModule.js.flow +++ /dev/null @@ -1,24 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -export interface Spec extends TurboModule { - +exampleFunction: (a: string, b: number) => void; - +getConstants: () => $ReadOnly<{ - constant?: string, - }>; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-get-constants-added-optional-constant/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-get-constants-added-optional-constant/NativeModule.js.flow deleted file mode 100644 index 82885474f32..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-get-constants-added-optional-constant/NativeModule.js.flow +++ /dev/null @@ -1,24 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -export interface Spec extends TurboModule { - +exampleFunction: (a: string, b: number) => void; - +getConstants: () => { - +constant?: string, - }; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-get-constants-added-required-constant-readonly/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-get-constants-added-required-constant-readonly/NativeModule.js.flow deleted file mode 100644 index a1ae7696fe1..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-get-constants-added-required-constant-readonly/NativeModule.js.flow +++ /dev/null @@ -1,24 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -export interface Spec extends TurboModule { - +exampleFunction: (a: string, b: number) => void; - +getConstants: () => $ReadOnly<{ - constant: string, - }>; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-get-constants-added-required-constant/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-get-constants-added-required-constant/NativeModule.js.flow deleted file mode 100644 index ee6abb89868..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-get-constants-added-required-constant/NativeModule.js.flow +++ /dev/null @@ -1,24 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -export interface Spec extends TurboModule { - +exampleFunction: (a: string, b: number) => void; - +getConstants: () => { - +constant: string, - }; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-get-constants-readonly/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-get-constants-readonly/NativeModule.js.flow deleted file mode 100644 index 878d2267f2d..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-get-constants-readonly/NativeModule.js.flow +++ /dev/null @@ -1,22 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -export interface Spec extends TurboModule { - +exampleFunction: (a: string, b: number) => void; - +getConstants: () => $ReadOnly<{}>; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-get-constants/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-get-constants/NativeModule.js.flow deleted file mode 100644 index 633e17bca56..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-get-constants/NativeModule.js.flow +++ /dev/null @@ -1,22 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -export interface Spec extends TurboModule { - +exampleFunction: (a: string, b: number) => void; - +getConstants: () => {}; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-nested-alias-changed/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-nested-alias-changed/NativeModule.js.flow deleted file mode 100644 index 8a665abdf2d..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-nested-alias-changed/NativeModule.js.flow +++ /dev/null @@ -1,23 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -type MyType = () => Promise; - -export interface Spec extends TurboModule { - +exampleFunction: (a: MyType, b: number) => void; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-nested-alias/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-nested-alias/NativeModule.js.flow deleted file mode 100644 index 79bf39c71bb..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-nested-alias/NativeModule.js.flow +++ /dev/null @@ -1,23 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -type MyType = () => Promise; - -export interface Spec extends TurboModule { - +exampleFunction: (a: MyType, b: number) => void; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-nested-changed/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-nested-changed/NativeModule.js.flow deleted file mode 100644 index 2ee8a14bbc3..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-nested-changed/NativeModule.js.flow +++ /dev/null @@ -1,32 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -export interface Spec extends TurboModule { - +exampleFunction: ( - a: { - a1: string, - a2: number, - a3: string, - ... - }, - b: number, - ) => void; - +getConstants: () => { - +exampleConstant: string, - }; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-nested-nullable/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-nested-nullable/NativeModule.js.flow deleted file mode 100644 index 4762d412f49..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-nested-nullable/NativeModule.js.flow +++ /dev/null @@ -1,32 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -export interface Spec extends TurboModule { - +exampleFunction: ( - a: ?{ - a1: string, - a2?: number, - a3: string, - ... - }, - b: number, - ) => void; - +getConstants: () => { - +exampleConstant: string, - }; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-nested-optional/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-nested-optional/NativeModule.js.flow deleted file mode 100644 index eb7e82106bd..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-nested-optional/NativeModule.js.flow +++ /dev/null @@ -1,32 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -export interface Spec extends TurboModule { - +exampleFunction: ( - a: { - a1: string, - a2?: number, - a3: string, - ... - }, - b: number, - ) => void; - +getConstants: () => { - +exampleConstant: string, - }; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-nested/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-nested/NativeModule.js.flow deleted file mode 100644 index 6cf8cdf2f81..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-nested/NativeModule.js.flow +++ /dev/null @@ -1,31 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -export interface Spec extends TurboModule { - +exampleFunction: ( - a: { - a1: string, - a2: number, - ... - }, - b: number, - ) => void; - +getConstants: () => { - +exampleConstant: string, - }; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-type-diffing-types/NativeTypeDiffingTypes.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-type-diffing-types/NativeTypeDiffingTypes.js.flow deleted file mode 100644 index a215dd4bf21..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-type-diffing-types/NativeTypeDiffingTypes.js.flow +++ /dev/null @@ -1,218 +0,0 @@ -/** - * 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 - */ - -/* eslint-disable no-unused-vars */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; -import type {UnsafeObject} from 'react-native/Libraries/Types/CodegenTypes'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -type StringLiteral0 = 'foo'; -type StringLiteral1 = 'bar'; - -type NumericLiteral0 = 1; -type NumericLiteral1 = 2; - -type StringLiteralUnion0 = 'a' | 'b' | 'c'; -type StringLiteralUnion1 = 'a' | 'b' | 'c' | 'd'; -type StringLiteralUnion2 = 'a' | 'x' | 'c'; - -type Tuple0 = [string, number]; -type Tuple1 = [string, number, number]; -type Tuple2 = [number, number]; - -type ReferencedType = {...}; -type ReferencedType2 = {...}; -type ReferencedType3 = {prop0: string, ...}; - -type ReferenceType = ReferencedType; -type ReferenceType2 = ReferencedType2; -type ReferenceType3 = ReferencedType3; -type ReferenceGeneric = ReferencedType; -type ReferenceGeneric2 = ReferencedType; - -type ObjectTypeWithProps = { - prop1: string, - prop2: number, - prop3: boolean, - ... -}; -type ObjectTypeLessProps = { - prop1: string, - prop3: boolean, - ... -}; - -type ObjectTypeWithDifferentProps = { - prop0: string, - prop4: number, - prop5: boolean, - ... -}; - -type ObjectTypeWithNesting = { - prop1: { - subprop1: string, - subprop2: number, - ... - }, - prop2: number, - ... -}; -type ObjectTypeWithChanges = { - prop1: number, - prop2: { - subprop1: string, - subprp2: number, - ... - }, - ... -}; -type ObjectTypeWithNestedChanges = { - prop1: { - subprop1: string, - subprop2: string, - ... - }, - prop2: number, - ... -}; -type ObjectTypeWithTwoOptionals = { - prop1?: string, - prop2: number, - prop3?: boolean, - ... -}; -type ObjectTypeWithOptionalNestedChange = { - prop1?: { - subprop1: string, - subprop2: number, - subprop3: string, - ... - }, - prop2: number, - ... -}; - -type NonNullableType = Object; -type NullableType = ?Object; - -type GenericObjectType = Object; -type UnsafeObjectType = UnsafeObject; - -type OptionalTypeLessProps = ?{ - prop1: string, - prop3: boolean, - ... -}; - -type ObjectTypeLiteral1 = { - prop1: number, - prop2: { - subprop1: string, - subprp2: number, - }, -}; - -type ObjectTypeLiteral2 = { - prop1: number, - prop2: { - subprop1: string, - subprp2: number, - }, -}; - -type ObjectTypeLiteral1TypeAlias = ObjectTypeLiteral1; -type ObjectTypeLiteral2TypeAlias = ObjectTypeLiteral2; - -type MapWithKey = {[a: string]: ?number}; -type MapWithKey2 = {[a: string]: ?string}; - -enum Enum { - A = 1, - B = 2, - C = 3, - D = 4, -} -enum EnumWithTypeChange { - A = '1', - B = '2', - C = '3', - D = '4', -} -enum EnumWithRemoval { - A = 1, - B = 2, - C = 3, -} -enum EnumWithValueChange { - A = 1, - B = 2, - C = 3, - D = 14, -} - -enum EnumUnsorted { - C = 3, - D = 4, - B = 2, - A = 1, -} - -export interface Spec extends TurboModule { - +stringLiteral0: (a: StringLiteral0) => void; - +stringLiteral1: (a: StringLiteral1) => void; - - +numericLiteral0: (a: NumericLiteral0) => void; - +numericLiteral1: (a: NumericLiteral1) => void; - - +stringLiteralUnion0: (a: StringLiteralUnion0) => void; - +stringLiteralUnion1: (a: StringLiteralUnion1) => void; - +stringLiteralUnion2: (a: StringLiteralUnion2) => void; - - +referenceType: (a: ReferenceType) => void; - +referenceType2: (a: ReferenceType2) => void; - +referenceType3: (a: ReferenceType3) => void; - - +referenceGeneric: (a: ReferenceGeneric) => void; - +referenceGeneric2: (a: ReferenceGeneric2) => void; - - +objectTypeWithProps: (a: ObjectTypeWithProps) => void; - +objectTypeLessProps: (a: ObjectTypeLessProps) => void; - +objectTypeWithDifferentProps: (a: ObjectTypeWithDifferentProps) => void; - +objectTypeWithNesting: (a: ObjectTypeWithNesting) => void; - +objectTypeWithChanges: (a: ObjectTypeWithChanges) => void; - +objectTypeWithNestedChanges: (a: ObjectTypeWithNestedChanges) => void; - +objectTypeWithTwoOptionals: (a: ObjectTypeWithTwoOptionals) => void; - +objectTypeWithOptionalNestedChange: (a: ObjectTypeWithOptionalNestedChange) => void; - +nonNullableType: (a: NonNullableType) => void; - +nullableType: (a: NullableType) => void; - +genericObjectType: (a: GenericObjectType) => void; - +unsafeObjectType: (a: UnsafeObjectType) => void; - +optionalTypeLessProps: (a: OptionalTypeLessProps) => void; - +objectTypeLiteral1: (a: ObjectTypeLiteral1) => void; - +objectTypeLiteral2: (a: ObjectTypeLiteral2) => void; - +objectTypeLiteral1TypeAlias: (a: ObjectTypeLiteral1TypeAlias) => void; - +objectTypeLiteral2TypeAlias: (a: ObjectTypeLiteral2TypeAlias) => void; - +genericObjectType: (a: Object) => void; - - +mapWithKey: (a: MapWithKey) => void; - +mapWithKey2: (a: MapWithKey2) => void; - - +enum: (a: Enum) => void; - +enumWithTypeChange: (a: EnumWithTypeChange) => void; - +enumWithRemoval: (a: EnumWithRemoval) => void; - +enumWithValueChange: (a: EnumWithValueChange) => void; - +enumUnsorted: (a: EnumUnsorted) => void; -} - -(TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-dictionary-changed/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-dictionary-changed/NativeModule.js.flow deleted file mode 100644 index 90274b8f2ce..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-dictionary-changed/NativeModule.js.flow +++ /dev/null @@ -1,24 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -export interface Spec extends TurboModule { - +exampleFunction: (a: {[key: string]: string}, b: number) => void; - +getConstants: () => { - +exampleConstant: number, - }; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-dictionary/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-dictionary/NativeModule.js.flow deleted file mode 100644 index fdef3b52353..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-dictionary/NativeModule.js.flow +++ /dev/null @@ -1,24 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -export interface Spec extends TurboModule { - +exampleFunction: (a: {[key: string]: number}, b: number) => void; - +getConstants: () => { - +exampleConstant: number, - }; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-changes/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-changes/NativeModule.js.flow deleted file mode 100644 index 06ad4f8b5a7..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-changes/NativeModule.js.flow +++ /dev/null @@ -1,31 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -enum TestEnum { - A = 1, - B = 2, - C = 3, - D = 4, -} - -export interface Spec extends TurboModule { - +exampleFunction: (a: TestEnum, b: number) => void; - +getConstants: () => { - +exampleConstant: number, - }; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-from-native-changes/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-from-native-changes/NativeModule.js.flow deleted file mode 100644 index 1998ecb7d6c..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-from-native-changes/NativeModule.js.flow +++ /dev/null @@ -1,31 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -enum TestEnum { - A = 1, - B = 2, - C = 3, - D = 4, -} - -export interface Spec extends TurboModule { - +exampleFunction: (a: string, b: number) => void; - +getConstants: () => { - +exampleConstant: TestEnum, - }; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-from-native-type-changes/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-from-native-type-changes/NativeModule.js.flow deleted file mode 100644 index 4c980e0fe51..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-from-native-type-changes/NativeModule.js.flow +++ /dev/null @@ -1,30 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -enum TestEnum { - A = '1', - B = '2', - C = '3', -} - -export interface Spec extends TurboModule { - +exampleFunction: (a: string, b: number) => void; - +getConstants: () => { - +exampleConstant: TestEnum, - }; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-from-native-value-changes/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-from-native-value-changes/NativeModule.js.flow deleted file mode 100644 index 7bb2d076f27..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-from-native-value-changes/NativeModule.js.flow +++ /dev/null @@ -1,30 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -enum TestEnum { - A = 1, - B = 13, - C = 3, -} - -export interface Spec extends TurboModule { - +exampleFunction: (a: string, b: number) => void; - +getConstants: () => { - +exampleConstant: TestEnum, - }; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-from-native/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-from-native/NativeModule.js.flow deleted file mode 100644 index 31c57e02ee2..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-from-native/NativeModule.js.flow +++ /dev/null @@ -1,30 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -enum TestEnum { - A = 1, - B = 2, - C = 3, -} - -export interface Spec extends TurboModule { - +exampleFunction: (a: string, b: number) => void; - +getConstants: () => { - +exampleConstant: TestEnum, - }; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-type-changes/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-type-changes/NativeModule.js.flow deleted file mode 100644 index e0559fee938..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-type-changes/NativeModule.js.flow +++ /dev/null @@ -1,31 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -enum TestEnum { - A = '1', - B = '2', - C = '3', - D = '4', -} - -export interface Spec extends TurboModule { - +exampleFunction: (a: TestEnum, b: number) => void; - +getConstants: () => { - +exampleConstant: number, - }; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-value-changes/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-value-changes/NativeModule.js.flow deleted file mode 100644 index 4c488ecc59e..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum-value-changes/NativeModule.js.flow +++ /dev/null @@ -1,30 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -enum TestEnum { - A = 1, - B = 13, - C = 3, -} - -export interface Spec extends TurboModule { - +exampleFunction: (a: TestEnum, b: number) => void; - +getConstants: () => { - +exampleConstant: number, - }; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum/NativeModule.js.flow deleted file mode 100644 index 2514a8aa379..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-enum/NativeModule.js.flow +++ /dev/null @@ -1,30 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -enum TestEnum { - A = 1, - B = 2, - C = 3, -} - -export interface Spec extends TurboModule { - +exampleFunction: (a: TestEnum, b: number) => void; - +getConstants: () => { - +exampleConstant: number, - }; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-eventemitter-changes/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-eventemitter-changes/NativeModule.js.flow deleted file mode 100644 index a17ac145459..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-eventemitter-changes/NativeModule.js.flow +++ /dev/null @@ -1,31 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; -import type {EventEmitter} from 'react-native/Libraries/Types/CodegenTypes'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -export type ObjectStruct = { - a: number, - b: string, - c?: ?string, -}; - -export interface Spec extends TurboModule { - onPress: EventEmitter; - onClick: EventEmitter; - onChange: EventEmitter; - onSubmit: EventEmitter; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-eventemitter/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-eventemitter/NativeModule.js.flow deleted file mode 100644 index d4b83987e11..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-eventemitter/NativeModule.js.flow +++ /dev/null @@ -1,31 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; -import type {EventEmitter} from 'react-native/Libraries/Types/CodegenTypes'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -export type ObjectStruct = { - a: number, - b: string, - c?: ?string, -}; - -export interface Spec extends TurboModule { - onPress: EventEmitter; - onClick: EventEmitter; - onChange: EventEmitter; - onSubmit: EventEmitter; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-optional-argument/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-optional-argument/NativeModule.js.flow deleted file mode 100644 index 0ffe3ce3a1e..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-optional-argument/NativeModule.js.flow +++ /dev/null @@ -1,24 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -export interface Spec extends TurboModule { - +exampleFunction: (a: string, b: number, c?: number) => void; - +getConstants: () => { - +exampleConstant: number, - }; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-union-changes/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-union-changes/NativeModule.js.flow deleted file mode 100644 index b86c7841180..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-union-changes/NativeModule.js.flow +++ /dev/null @@ -1,26 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -type testUnion = 'a' | 'b' | 'c' | 'd'; - -export interface Spec extends TurboModule { - +exampleFunction: (a: testUnion, b: number) => void; - +getConstants: () => { - +exampleConstant: number, - }; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-union-confusing-string-literals/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-union-confusing-string-literals/NativeModule.js.flow deleted file mode 100644 index aff7f31947c..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-union-confusing-string-literals/NativeModule.js.flow +++ /dev/null @@ -1,26 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -type testUnion = 'a' | '0' | '1' | 'a long string'; - -export interface Spec extends TurboModule { - +exampleFunction: (a: testUnion, b: number) => void; - +getConstants: () => { - +exampleConstant: number, - }; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-union-from-native-changes/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-union-from-native-changes/NativeModule.js.flow deleted file mode 100644 index 0a10a45bb16..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-union-from-native-changes/NativeModule.js.flow +++ /dev/null @@ -1,26 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -type testUnion = 'a' | 'b' | 'c' | 'd'; - -export interface Spec extends TurboModule { - +exampleFunction: (a: string, b: number) => void; - +getConstants: () => { - +exampleConstant: testUnion, - }; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-union-from-native/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-union-from-native/NativeModule.js.flow deleted file mode 100644 index 53f5816c44e..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-union-from-native/NativeModule.js.flow +++ /dev/null @@ -1,26 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -type testUnion = 'a' | 'b' | 'c'; - -export interface Spec extends TurboModule { - +exampleFunction: (a: string, b: number) => void; - +getConstants: () => { - +exampleConstant: testUnion, - }; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-union-type-changes/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-union-type-changes/NativeModule.js.flow deleted file mode 100644 index 6cbbd9bcb4f..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-union-type-changes/NativeModule.js.flow +++ /dev/null @@ -1,26 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -type testUnion = 1 | 2 | 3; - -export interface Spec extends TurboModule { - +exampleFunction: (a: testUnion, b: number) => void; - +getConstants: () => { - +exampleConstant: number, - }; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-union/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-union/NativeModule.js.flow deleted file mode 100644 index 0015b1e1082..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module-with-union/NativeModule.js.flow +++ /dev/null @@ -1,26 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -type testUnion = 'a' | 'b' | 'c'; - -export interface Spec extends TurboModule { - +exampleFunction: (a: testUnion, b: number) => void; - +getConstants: () => { - +exampleConstant: number, - }; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module/NativeModule.js.flow b/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module/NativeModule.js.flow deleted file mode 100644 index eba04a1f8b6..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__fixtures__/native-module/NativeModule.js.flow +++ /dev/null @@ -1,24 +0,0 @@ -/** - * 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 - * @format - */ - -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; - -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; - -export interface Spec extends TurboModule { - +exampleFunction: (a: string, b: number) => void; - +getConstants: () => { - +exampleConstant: number, - }; -} - -export default (TurboModuleRegistry.getEnforcing( - 'NativeModuleTest', -): Spec); diff --git a/packages/react-native-compatibility-check/src/__tests__/__snapshots__/ErrorFormatting-test.js.snap b/packages/react-native-compatibility-check/src/__tests__/__snapshots__/ErrorFormatting-test.js.snap deleted file mode 100644 index 05f5b3a3bc4..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/__snapshots__/ErrorFormatting-test.js.snap +++ /dev/null @@ -1,792 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`codegen formattedSummarizeDiffSet allows a diff from native-component-with-command/NativeComponent to native-component-with-command/NativeComponent 1`] = ` -Object { - "incompatibilityReport": Object {}, - "status": "ok", -} -`; - -exports[`codegen formattedSummarizeDiffSet allows a diff from native-component-with-props-default-change/NativeComponent to native-component-with-props/NativeComponent 1`] = ` -Object { - "incompatibilityReport": Object {}, - "status": "ok", -} -`; - -exports[`codegen formattedSummarizeDiffSet allows a diff from native-module-before-after-types/NativeModuleBeforeAfterTypes to native-module-before-after-types-removed/NativeModuleBeforeAfterTypes 1`] = ` -Object { - "incompatibilityReport": Object {}, - "status": "ok", -} -`; - -exports[`codegen formattedSummarizeDiffSet allows a diff from native-module-get-constants-added-optional-constant/NativeModule to native-module-get-constants/NativeModule 1`] = ` -Object { - "incompatibilityReport": Object {}, - "status": "ok", -} -`; - -exports[`codegen formattedSummarizeDiffSet allows a diff from native-module-with-enum-from-native/NativeModule to native-module-with-enum-from-native-changes/NativeModule 1`] = ` -Object { - "incompatibilityReport": Object {}, - "status": "ok", -} -`; - -exports[`codegen formattedSummarizeDiffSet allows a diff from native-module-with-union-changes/NativeModule to native-module-with-union/NativeModule 1`] = ` -Object { - "incompatibilityReport": Object {}, - "status": "ok", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-component-with-command/NativeComponent to native-component-with-command-extra-arg/NativeComponent 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeComponent": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "incompatibleTypes", - "message": "NativeComponent: Object contained a property with a type mismatch - -- methodInt: has conflicting type changes - --new: (a: int, b: string)=>void - --old: (a: int)=>void - Function types have differing length of arguments - --new: (a: int, b: string)=>void - --old: (a: int)=>void", - }, - ], - }, - }, - "status": "incompatible", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-component-with-command-all-basic-types/NativeComponent to native-component-with-command-all-basic-types-arrays/NativeComponent 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeComponent": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "incompatibleTypes", - "message": "NativeComponent: Object contained a property with a type mismatch - -- methodInt: has conflicting type changes - --new: (a: Array)=>void - --old: (a: int)=>void - Parameter at index 0 did not match - --new: (a: Array)=>void - --old: (a: int)=>void - Type annotations are not the same. - --new: Array - --old: int", - }, - Object { - "errorCode": "incompatibleTypes", - "message": "NativeComponent: Object contained a property with a type mismatch - -- methodString: has conflicting type changes - --new: (a: Array)=>void - --old: (a: string)=>void - Parameter at index 0 did not match - --new: (a: Array)=>void - --old: (a: string)=>void - Type annotations are not the same. - --new: Array - --old: string", - }, - Object { - "errorCode": "incompatibleTypes", - "message": "NativeComponent: Object contained a property with a type mismatch - -- methodBool: has conflicting type changes - --new: (a: Array)=>void - --old: (a: boolean)=>void - Parameter at index 0 did not match - --new: (a: Array)=>void - --old: (a: boolean)=>void - Type annotations are not the same. - --new: Array - --old: boolean", - }, - Object { - "errorCode": "incompatibleTypes", - "message": "NativeComponent: Object contained a property with a type mismatch - -- methodFloat: has conflicting type changes - --new: (a: Array)=>void - --old: (a: float)=>void - Parameter at index 0 did not match - --new: (a: Array)=>void - --old: (a: float)=>void - Type annotations are not the same. - --new: Array - --old: float", - }, - Object { - "errorCode": "incompatibleTypes", - "message": "NativeComponent: Object contained a property with a type mismatch - -- methodDouble: has conflicting type changes - --new: (a: Array)=>void - --old: (a: double)=>void - Parameter at index 0 did not match - --new: (a: Array)=>void - --old: (a: double)=>void - Type annotations are not the same. - --new: Array - --old: double", - }, - ], - }, - }, - "status": "incompatible", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-component-with-command-changed/NativeComponent to native-component-with-command/NativeComponent 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeComponent": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "incompatibleTypes", - "message": "NativeComponent: Object contained a property with a type mismatch - -- methodInt: has conflicting type changes - --new: (a: int)=>void - --old: (a: string)=>void - Parameter at index 0 did not match - --new: (a: int)=>void - --old: (a: string)=>void - Type annotations are not the same. - --new: int - --old: string", - }, - ], - }, - }, - "status": "incompatible", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-component-with-props-added-required-prop/NativeComponent to native-component-with-props/NativeComponent 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeComponent": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "removedProps", - "message": "NativeComponent: Object removed required properties expected by native - -- width", - }, - ], - }, - }, - "status": "incompatible", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-component-with-props-array-union/NativeComponent to native-component-with-props-array-union-added/NativeComponent 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeComponent": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "addedUnionCases", - "message": "NativeComponent.sizes: Union added items, but native will not expect/support them - -- position 3 huge", - }, - ], - }, - }, - "status": "incompatible", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-component-with-props-changes/NativeComponent to native-component-with-props/NativeComponent 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeComponent": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "incompatibleTypes", - "message": "NativeComponent: Object contained a property with a type mismatch - -- text: has conflicting type changes - --new: string - --old: int - Type annotations are not the same. - --new: string - --old: int", - }, - ], - }, - }, - "status": "incompatible", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-component-with-props-union/NativeComponent to native-component-with-props-union-added/NativeComponent 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeComponent": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "addedUnionCases", - "message": "NativeComponent.size: Union added items, but native will not expect/support them - -- position 3 huge", - }, - ], - }, - }, - "status": "incompatible", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-module-before-after-types-removed/NativeModuleBeforeAfterTypes to native-module-before-after-types/NativeModuleBeforeAfterTypes 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeModuleBeforeAfterTypes": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "addedProps", - "message": "NativeModuleTest: Object added required properties, which native will not provide - -- afterMismatchGeneric - -- booleanType - -- exampleFunction - -- simpleArray - -- simpleArrayChange - -- simpleFunction - -- simpleFunction2 - -- simpleFunction3 - -- simpleFunction4 - -- simpleUnion - -- simpleUnion2 - -- simpleUnion3 - -- simpleUnion4 - -- simpleUnionLonger - -- stringType", - }, - ], - }, - }, - "status": "incompatible", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-module-before-after-types-type-changed/NativeModuleBeforeAfterTypes to native-module-before-after-types/NativeModuleBeforeAfterTypes 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeModuleBeforeAfterTypes": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "incompatibleTypes", - "message": "NativeModuleTest: Object contained a property with a type mismatch - -- simpleArrayChange: has conflicting type changes - --new: (a: Array)=>void - --old: (a: Array)=>void - Parameter at index 0 did not match - --new: (a: Array)=>void - --old: (a: Array)=>void - Type annotations are not the same. - --new: number - --old: string", - }, - ], - }, - }, - "status": "incompatible", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-module-changed/NativeModule to native-module/NativeModule 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeModule": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "incompatibleTypes", - "message": "NativeModuleTest: Object contained a property with a type mismatch - -- getConstants: has conflicting type changes - --new: ()=>{exampleConstant: number} - --old: ()=>{exampleConstant: string} - Function return types do not match - --new: ()=>{exampleConstant: number} - --old: ()=>{exampleConstant: string} - Object contained a property with a type mismatch - -- exampleConstant: has conflicting type changes - --new: number - --old: string - Type annotations are not the same. - --new: number - --old: string", - }, - ], - }, - }, - "status": "incompatible", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-module-nested/NativeModule to native-module-nested-optional/NativeModule 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeModule": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "optionalProps", - "message": "NativeModuleTest.exampleFunction parameter 0: Property made optional, but native requires it - -- a2", - }, - ], - }, - }, - "status": "incompatible", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-module-nested-alias-changed/NativeModule to native-module-nested-alias/NativeModule 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeModule": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "incompatibleTypes", - "message": "NativeModuleTest: Object contained a property with a type mismatch - -- exampleFunction: has conflicting type changes - --new: (a: ()=>Promise, b: number)=>void - --old: (a: ()=>Promise, b: number)=>void - Parameter at index 0 did not match - --new: (a: ()=>Promise, b: number)=>void - --old: (a: ()=>Promise, b: number)=>void - Function return types do not match - --new: ()=>Promise - --old: ()=>Promise - Type annotations are not the same. - --new: string - --old: number", - }, - ], - }, - }, - "status": "incompatible", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-module-nested-changed/NativeModule to native-module-nested/NativeModule 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeModule": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "removedProps", - "message": "NativeModuleTest.exampleFunction parameter 0: Object removed required properties expected by native - -- a3", - }, - ], - }, - }, - "status": "incompatible", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-module-nested-changed/NativeModule to native-module-nested-optional/NativeModule 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeModule": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "optionalProps", - "message": "NativeModuleTest.exampleFunction parameter 0: Property made optional, but native requires it - -- a2", - }, - ], - }, - }, - "status": "incompatible", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-module-nested-optional/NativeModule to native-module-nested-nullable/NativeModule 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeModule": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "nullableOfNonNull", - "message": "NativeModuleTest.exampleFunction parameter 0: Type made nullable, but native requires it - --new: ?{a1: string, a2?: number, a3: string} - --old: {a1: string, a2?: number, a3: string}", - }, - ], - }, - }, - "status": "incompatible", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-module-with-dictionary-changed/NativeModule to native-module-with-dictionary/NativeModule 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeModule": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "incompatibleTypes", - "message": "NativeModuleTest: Object contained a property with a type mismatch - -- exampleFunction: has conflicting type changes - --new: (a: {[string]: number, b: number)=>void - --old: (a: {[string]: string, b: number)=>void - Parameter at index 0 did not match - --new: (a: {[string]: number, b: number)=>void - --old: (a: {[string]: string, b: number)=>void - Type annotations are not the same. - --new: number - --old: string", - }, - ], - }, - }, - "status": "incompatible", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-module-with-enum/NativeModule to native-module-with-enum-changes/NativeModule 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeModule": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "addedEnumCases", - "message": "NativeModuleTest.exampleFunction parameter 0: Enum added items, but native will not expect/support them - -- Member D", - }, - ], - }, - }, - "status": "incompatible", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-module-with-enum-from-native-changes/NativeModule to native-module-with-enum-from-native/NativeModule 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeModule": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "removedEnumCases", - "message": "NativeModuleTest.getConstants.exampleConstant: Enum removed items, but native may still provide them - -- Member D", - }, - ], - }, - }, - "status": "incompatible", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-module-with-enum-from-native-type-changes/NativeModule to native-module-with-enum-from-native/NativeModule 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeModule": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "incompatibleTypes", - "message": "NativeModuleTest: Object contained a property with a type mismatch - -- getConstants: has conflicting type changes - --new: ()=>{exampleConstant: Enum} - --old: ()=>{exampleConstant: Enum} - Function return types do not match - --new: ()=>{exampleConstant: Enum} - --old: ()=>{exampleConstant: Enum} - Object contained a property with a type mismatch - -- exampleConstant: has conflicting type changes - --new: Enum - --old: Enum - EnumDeclaration member types are not the same - --new: Enum - --old: Enum", - }, - ], - }, - }, - "status": "incompatible", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-module-with-enum-from-native-value-changes/NativeModule to native-module-with-enum-from-native/NativeModule 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeModule": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "incompatibleTypes", - "message": "NativeModuleTest: Object contained a property with a type mismatch - -- getConstants: has conflicting type changes - --new: ()=>{exampleConstant: Enum} - --old: ()=>{exampleConstant: Enum} - Function return types do not match - --new: ()=>{exampleConstant: Enum} - --old: ()=>{exampleConstant: Enum} - Object contained a property with a type mismatch - -- exampleConstant: has conflicting type changes - --new: Enum - --old: Enum - Enum types do not match - --new: Enum {A = 1, B = 2, C = 3} - --old: Enum {A = 1, B = 13, C = 3} - Enum contained a member with a type mismatch - -- Member B: has conflicting changes - --new: 2 - --old: 13 - Numeric literals are not equal - --new: 2 - --old: 13", - }, - ], - }, - }, - "status": "incompatible", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-module-with-enum-type-changes/NativeModule to native-module-with-enum/NativeModule 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeModule": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "incompatibleTypes", - "message": "NativeModuleTest: Object contained a property with a type mismatch - -- exampleFunction: has conflicting type changes - --new: (a: Enum, b: number)=>void - --old: (a: Enum, b: number)=>void - Parameter at index 0 did not match - --new: (a: Enum, b: number)=>void - --old: (a: Enum, b: number)=>void - EnumDeclaration member types are not the same - --new: Enum - --old: Enum", - }, - ], - }, - }, - "status": "incompatible", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-module-with-enum-value-changes/NativeModule to native-module-with-enum/NativeModule 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeModule": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "incompatibleTypes", - "message": "NativeModuleTest: Object contained a property with a type mismatch - -- exampleFunction: has conflicting type changes - --new: (a: Enum, b: number)=>void - --old: (a: Enum, b: number)=>void - Parameter at index 0 did not match - --new: (a: Enum, b: number)=>void - --old: (a: Enum, b: number)=>void - Enum types do not match - --new: Enum {A = 1, B = 2, C = 3} - --old: Enum {A = 1, B = 13, C = 3} - Enum contained a member with a type mismatch - -- Member B: has conflicting changes - --new: 2 - --old: 13 - Numeric literals are not equal - --new: 2 - --old: 13", - }, - ], - }, - }, - "status": "incompatible", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-module-with-eventemitter-changes/NativeModule to native-module-with-eventemitter/NativeModule 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeModule": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "incompatibleTypes", - "message": "NativeModuleTest: Object contained properties with type mismatches - -- onChange: has conflicting type changes - --new: EventEmitter - --old: EventEmitter> - EventEmitter eventTypes are not equivalent - --new: EventEmitter - --old: EventEmitter> - Type annotations are not the same. - --new: {a: number, b: string, c?: ?string} - --old: Array - -- onClick: has conflicting type changes - --new: EventEmitter - --old: EventEmitter - EventEmitter eventTypes are not equivalent - --new: EventEmitter - --old: EventEmitter - Type annotations are not the same. - --new: string - --old: number - -- onPress: has conflicting type changes - --new: EventEmitter - --old: EventEmitter - EventEmitter eventTypes are not equivalent - --new: EventEmitter - --old: EventEmitter - Type annotations are not the same. - --new: void - --old: string - -- onSubmit: has conflicting type changes - --new: EventEmitter> - --old: EventEmitter - EventEmitter eventTypes are not equivalent - --new: EventEmitter> - --old: EventEmitter - Type annotations are not the same. - --new: Array - --old: {a: number, b: string, c?: ?string}", - }, - ], - }, - }, - "status": "incompatible", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-module-with-optional-argument/NativeModule to native-module/NativeModule 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeModule": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "incompatibleTypes", - "message": "NativeModuleTest: Object contained a property with a type mismatch - -- exampleFunction: has conflicting type changes - --new: (a: string, b: number)=>void - --old: (a: string, b: number, c?: number)=>void - Function types have differing length of arguments - --new: (a: string, b: number)=>void - --old: (a: string, b: number, c?: number)=>void", - }, - ], - }, - }, - "status": "incompatible", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-module-with-union/NativeModule to native-module-with-union-changes/NativeModule 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeModule": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "addedUnionCases", - "message": "NativeModuleTest.exampleFunction parameter 0: Union added items, but native will not expect/support them - -- position 4 d", - }, - ], - }, - }, - "status": "incompatible", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-module-with-union-confusing-string-literals/NativeModule to native-module-with-union/NativeModule 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeModule": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "incompatibleTypes", - "message": "NativeModuleTest: Object contained a property with a type mismatch - -- exampleFunction: has conflicting type changes - --new: (a: (a | b | c), b: number)=>void - --old: (a: (a | '0' | '1' | 'a long string'), b: number)=>void - Parameter at index 0 did not match - --new: (a: (a | b | c), b: number)=>void - --old: (a: (a | '0' | '1' | 'a long string'), b: number)=>void - Subtype of union at position 1 did not match - --new: (a | b | c) - --old: (a | '0' | '1' | 'a long string') - String literals are not equal - --new: b - --old: '0'", - }, - ], - }, - }, - "status": "incompatible", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-module-with-union-from-native-changes/NativeModule to native-module-with-union-from-native/NativeModule 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeModule": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "removedUnionCases", - "message": "NativeModuleTest.getConstants.exampleConstant: Union removed items, but native may still provide them - -- position 4 d", - }, - ], - }, - }, - "status": "incompatible", -} -`; - -exports[`codegen formattedSummarizeDiffSet reports a diff from native-module-with-union-type-changes/NativeModule to native-module-with-union/NativeModule 1`] = ` -Object { - "incompatibilityReport": Object { - "NativeModule": Object { - "framework": "ReactNative", - "incompatibleSpecs": Array [ - Object { - "errorCode": "incompatibleTypes", - "message": "NativeModuleTest: Object contained a property with a type mismatch - -- exampleFunction: has conflicting type changes - --new: (a: (a | b | c), b: number)=>void - --old: (a: Union, b: number)=>void - Parameter at index 0 did not match - --new: (a: (a | b | c), b: number)=>void - --old: (a: Union, b: number)=>void - Type annotations are not the same. - --new: (a | b | c) - --old: Union", - }, - ], - }, - }, - "status": "incompatible", -} -`; diff --git a/packages/react-native-compatibility-check/src/__tests__/utilities/getTestSchema.js b/packages/react-native-compatibility-check/src/__tests__/utilities/getTestSchema.js deleted file mode 100644 index 5b008a683da..00000000000 --- a/packages/react-native-compatibility-check/src/__tests__/utilities/getTestSchema.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * 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. - * - * @format - * @flow strict-local - * @oncall react_native - */ - -import type {SchemaType} from '@react-native/codegen/src/CodegenSchema'; - -import {FlowParser} from '@react-native/codegen/src/parsers/flow/parser'; -import path from 'path'; - -const flowParser = new FlowParser(); - -export function getTestSchema( - ...filenameComponents: Array -): SchemaType { - const filename = path.join(...filenameComponents); - - const schema = flowParser.parseFile(filename); - - return schema; -} diff --git a/packages/react-native-compatibility-check/src/convertPropToBasicTypes.js b/packages/react-native-compatibility-check/src/convertPropToBasicTypes.js deleted file mode 100644 index 1fdd80f73d1..00000000000 --- a/packages/react-native-compatibility-check/src/convertPropToBasicTypes.js +++ /dev/null @@ -1,104 +0,0 @@ -/** - * 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 strict-local - * @format - * @oncall react_native - */ - -import type { - ArrayTypeAnnotation, - CompleteTypeAnnotation, - ComponentArrayTypeAnnotation, - ObjectTypeAnnotation, - PropTypeAnnotation, -} from '@react-native/codegen/src/CodegenSchema'; - -export default function convertPropToBasicTypes( - inputType: PropTypeAnnotation | ComponentArrayTypeAnnotation['elementType'], -): CompleteTypeAnnotation { - let resultingType: CompleteTypeAnnotation; - - switch (inputType.type) { - case 'BooleanTypeAnnotation': - resultingType = { - type: 'BooleanTypeAnnotation', - }; - break; - case 'StringTypeAnnotation': - resultingType = { - type: 'StringTypeAnnotation', - }; - break; - case 'DoubleTypeAnnotation': - resultingType = { - type: 'DoubleTypeAnnotation', - }; - break; - - case 'FloatTypeAnnotation': - resultingType = { - type: 'FloatTypeAnnotation', - }; - break; - case 'Int32TypeAnnotation': - resultingType = { - type: 'Int32TypeAnnotation', - }; - break; - case 'StringEnumTypeAnnotation': - resultingType = { - type: 'StringLiteralUnionTypeAnnotation', - types: inputType.options.map(option => { - return { - type: 'StringLiteralTypeAnnotation', - value: option, - }; - }), - }; - break; - case 'Int32EnumTypeAnnotation': - // Compat check doesn't yet have support for - // NumberLiteralUnionTypeAnnotation - resultingType = { - type: 'AnyTypeAnnotation', - }; - break; - case 'ReservedPropTypeAnnotation': - resultingType = { - type: 'ReservedTypeAnnotation', - name: inputType.name, - }; - break; - case 'MixedTypeAnnotation': - resultingType = inputType; - break; - case 'ObjectTypeAnnotation': - resultingType = ({ - type: 'ObjectTypeAnnotation', - ...(inputType.baseTypes != null - ? {baseTypes: inputType.baseTypes} - : {}), - properties: inputType.properties.map(property => ({ - name: property.name, - optional: property.optional, - typeAnnotation: convertPropToBasicTypes(property.typeAnnotation), - })), - }: ObjectTypeAnnotation); - break; - case 'ArrayTypeAnnotation': - resultingType = ({ - type: 'ArrayTypeAnnotation', - elementType: convertPropToBasicTypes(inputType.elementType), - }: ArrayTypeAnnotation); - break; - default: - (inputType.type: empty); - throw new Error('Unexpected type ' + inputType.type); - } - - return resultingType; -} diff --git a/packages/react-native-compatibility-check/src/index.flow.js b/packages/react-native-compatibility-check/src/index.flow.js deleted file mode 100644 index ad79b4145ac..00000000000 --- a/packages/react-native-compatibility-check/src/index.flow.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * 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 strict-local - * @format - * @oncall react_native - */ - -export {compareSchemas} from './index.js'; diff --git a/packages/react-native-compatibility-check/src/index.js b/packages/react-native-compatibility-check/src/index.js deleted file mode 100644 index 264b9eed430..00000000000 --- a/packages/react-native-compatibility-check/src/index.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * 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 strict-local - * @format - * @oncall react_native - */ - -import type { - DiffSummary, - ExportableSchemaDiff, - FormattedDiffSummary, - SchemaDiff, -} from './DiffResults'; -import type {SchemaType} from '@react-native/codegen/src/CodegenSchema'; - -import {schemaDiffExporter} from './DiffResults.js'; -import {formatDiffSet} from './ErrorFormatting.js'; -import {buildSchemaDiff, summarizeDiffSet} from './VersionDiffing.js'; - -class CompatCheckResult { - #schemaDiff: Set; - #summary: ?DiffSummary; - - constructor(schemaDiff: Set) { - this.#schemaDiff = schemaDiff; - } - - getSummary(): DiffSummary { - if (this.#summary == null) { - this.#summary = summarizeDiffSet(this.#schemaDiff); - } - - return this.#summary; - } - - getErrors(): FormattedDiffSummary { - return formatDiffSet(this.getSummary()); - } - - getDebugInfo(): Array { - return Array.from(this.#schemaDiff, schemaDiffExporter); - } -} - -export function compareSchemas( - newSchema: SchemaType, - oldSchema: SchemaType, -): CompatCheckResult { - return new CompatCheckResult(buildSchemaDiff(newSchema, oldSchema)); -} diff --git a/scripts/build/config.js b/scripts/build/config.js index e24cb22c226..10160feb829 100644 --- a/scripts/build/config.js +++ b/scripts/build/config.js @@ -54,10 +54,6 @@ const buildConfig: BuildConfig = { emitTypeScriptDefs: true, target: 'node', }, - 'react-native-compatibility-check': { - emitTypeScriptDefs: true, - target: 'node', - }, }, }; diff --git a/yarn.lock b/yarn.lock index 9e4a445b9c3..24cf2d189f1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4438,15 +4438,6 @@ flow-parser@0.*: resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.245.0.tgz#d8ad7e706d280ce6d4189a206768c32f552b5099" integrity sha512-xUBkkpIDfDZHAebnDEX65FCVitJUctab82KFmtP5SY4cGly1vbuYNe6Muyp0NLXrgmBChVdoC2T+3/RUHi4Mww== -flow-remove-types@^2.237.2: - version "2.259.1" - resolved "https://registry.yarnpkg.com/flow-remove-types/-/flow-remove-types-2.259.1.tgz#ee78962cbd73d85f0e94183b354c43399903c734" - integrity sha512-H+ww7Q6c4xXFAoZGZnC37FJmA9Zzu3UpQ96q3/geCQiaZiTXmM7ZeN53DYpu4be8cvPEp15K0SZTOtaiGoWU5A== - dependencies: - hermes-parser "0.25.1" - pirates "^3.0.2" - vlq "^0.2.1" - for-each@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" @@ -6782,11 +6773,6 @@ node-int64@^0.4.0: resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== -node-modules-regexp@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" - integrity sha512-JMaRS9L4wSRIR+6PTVEikTrq/lMGEZR43a48ETeilY0Q0iMwVnccMFrUM1k+tNzmYuIU0Vh710bCUqHX+/+ctQ== - node-releases@^2.0.18: version "2.0.18" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f" @@ -7184,13 +7170,6 @@ pinpoint@^1.1.0: resolved "https://registry.yarnpkg.com/pinpoint/-/pinpoint-1.1.0.tgz#0cf7757a6977f1bf7f6a32207b709e377388e874" integrity sha512-+04FTD9x7Cls2rihLlo57QDCcHoLBGn5Dk51SwtFBWkUWLxZaBXyNVpCw1S+atvE7GmnFjeaRZ0WLq3UYuqAdg== -pirates@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-3.0.2.tgz#7e6f85413fd9161ab4e12b539b06010d85954bb9" - integrity sha512-c5CgUJq6H2k6MJz72Ak1F5sN9n9wlSlJyEnwvpm9/y3WB4E3pHBDT2c6PEiS1vyJvq2bUxUAIu0EGf8Cx4Ic7Q== - dependencies: - node-modules-regexp "^1.0.0" - pirates@^4.0.1, pirates@^4.0.4, pirates@^4.0.5, pirates@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" @@ -8765,11 +8744,6 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -vlq@^0.2.1: - version "0.2.3" - resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26" - integrity sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow== - vlq@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/vlq/-/vlq-1.0.1.tgz#c003f6e7c0b4c1edd623fd6ee50bbc0d6a1de468"