diff --git a/.circleci/config.yml b/.circleci/config.yml index 18d5af7b4d9dd6..206562552df160 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -588,9 +588,6 @@ jobs: test_ios: executor: reactnativeios parameters: - use_frameworks: - type: boolean - default: false run_unit_tests: description: Specifies whether unit tests should run. type: boolean @@ -647,13 +644,6 @@ jobs: name: Configure Watchman command: echo "{}" > .watchmanconfig - - when: - condition: << parameters.use_frameworks >> - steps: - - run: - name: Set USE_FRAMEWORKS=1 - command: echo "export USE_FRAMEWORKS=1" >> $BASH_ENV - - run: name: Setup the CocoaPods environment command: | @@ -724,10 +714,6 @@ jobs: # ------------------------- test_android: executor: reactnativeandroid - parameters: - run_disabled_tests: - type: boolean - default: false steps: - checkout - setup_artifacts @@ -741,18 +727,16 @@ jobs: - report_bundle_size: platform: android + - store_test_results: + path: ~/react-native/packages/react-native-gradle-plugin/build/test-results + + - store_test_results: + path: ~/react-native/packages/react-native/ReactAndroid/build/test-results + - store_artifacts: path: ~/react-native/packages/rn-tester/android/app/build/outputs/apk/ destination: rntester-apk - # Optionally, run disabled tests - - when: - condition: << parameters.run_disabled_tests >> - steps: - - run: echo "Failing tests may be moved here temporarily." - - run_e2e: - platform: android - # ------------------------- # JOBS: Test Android Docker Image # ------------------------- @@ -937,6 +921,11 @@ jobs: description: Which React Native architecture to use. Must be one of "OldArch", "NewArch". type: enum enum: ["NewArch", "OldArch"] + use_frameworks: + default: "StaticLibraries" + description: The dependency building and linking strategy to use. Must be one of "StaticLibraries", "StaticFrameworks", "DynamicFrameworks" + type: enum + enum: ["StaticLibraries", "StaticFrameworks", "DynamicFrameworks"] ruby_version: default: "2.6.10" description: The version of ruby that must be used @@ -971,6 +960,16 @@ jobs: export USE_HERMES=0 fi + if [[ << parameters.use_frameworks >> == "StaticFrameworks" ]]; then + export NO_FLIPPER=1 + export USE_FRAMEWORKS=static + fi + + if [[ << parameters.use_frameworks >> == "DynamicFrameworks" ]]; then + export NO_FLIPPER=1 + export USE_FRAMEWORKS=dynamic + fi + cd packages/rn-tester bundle install @@ -1602,8 +1601,7 @@ workflows: - build_hermesc_windows - test_js: run_disabled_tests: false - - test_android: - run_disabled_tests: false + - test_android - test_android_docker_image - test_android_template: requires: @@ -1653,11 +1651,6 @@ workflows: jsengine: "Hermes" flipper: "WithFlipper" use_frameworks: "DynamicFrameworks" - - architecture: "NewArch" - flavor: "Release" - jsengine: "Hermes" - flipper: "WithoutFlipper" - use_frameworks: "DynamicFrameworks" - architecture: "NewArch" flavor: "Release" jsengine: "JSC" @@ -1673,11 +1666,6 @@ workflows: jsengine: "JSC" flipper: "WithFlipper" use_frameworks: "DynamicFrameworks" - - architecture: "NewArch" - flavor: "Release" - jsengine: "JSC" - flipper: "WithoutFlipper" - use_frameworks: "DynamicFrameworks" - architecture: "OldArch" flavor: "Release" jsengine: "Hermes" @@ -1733,21 +1721,11 @@ workflows: jsengine: "Hermes" flipper: "WithFlipper" use_frameworks: "DynamicFrameworks" - - architecture: "NewArch" - flavor: "Debug" - jsengine: "Hermes" - flipper: "WithoutFlipper" - use_frameworks: "DynamicFrameworks" - architecture: "NewArch" flavor: "Debug" jsengine: "JSC" flipper: "WithFlipper" use_frameworks: "DynamicFrameworks" - - architecture: "NewArch" - flavor: "Debug" - jsengine: "JSC" - flipper: "WithoutFlipper" - use_frameworks: "DynamicFrameworks" - architecture: "OldArch" flavor: "Debug" jsengine: "Hermes" @@ -1777,6 +1755,7 @@ workflows: parameters: architecture: ["NewArch", "OldArch"] jsengine: ["Hermes", "JSC"] + use_frameworks: ["StaticLibraries", "StaticFrameworks", "DynamicFrameworks"] - test_ios: name: "Test iOS with Ruby 2.7.7" run_unit_tests: true @@ -1796,13 +1775,6 @@ workflows: matrix: parameters: jsengine: ["Hermes", "JSC"] - # DISABLED: USE_FRAMEWORKS=1 not supported by Flipper - # - test_ios: - # name: test_ios_frameworks - # use_frameworks: true - # run_unit_tests: true - # requires: - # - build_ios_frameworks - test_js: name: test_js_prev_lts executor: nodeprevlts diff --git a/.eslintrc.js b/.eslintrc.js index 2755223a478e90..622c41bf0d51c0 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -21,7 +21,7 @@ module.exports = { plugins: ['@react-native/eslint-plugin-specs', 'lint'], overrides: [ - // overriding the JS config from eslint-config-react-native-community config to ensure + // overriding the JS config from @react-native/eslint-config to ensure // that we use hermes-eslint for all js files { files: ['*.js'], diff --git a/.flowconfig b/.flowconfig index 3ccea162451b08..33da5ca8a7f069 100644 --- a/.flowconfig +++ b/.flowconfig @@ -75,4 +75,4 @@ untyped-import untyped-type-import [version] -^0.204.1 +^0.206.0 diff --git a/.flowconfig.android b/.flowconfig.android index 8e903250b89cb0..618bb734f08468 100644 --- a/.flowconfig.android +++ b/.flowconfig.android @@ -75,4 +75,4 @@ untyped-import untyped-type-import [version] -^0.204.1 +^0.206.0 diff --git a/.github/workflow-scripts/actOnLabel.js b/.github/workflow-scripts/actOnLabel.js index 923e6baa44b441..78571fd0ac0511 100644 --- a/.github/workflow-scripts/actOnLabel.js +++ b/.github/workflow-scripts/actOnLabel.js @@ -7,7 +7,7 @@ * @format */ -module.exports = async (github, context, label) => { +module.exports = async (github, context, labelWithContext) => { const closeIssue = async () => { await github.rest.issues.update({ issue_number: context.issue.number, @@ -45,7 +45,7 @@ module.exports = async (github, context, label) => { }); }; - switch (label) { + switch (labelWithContext.label) { case 'Type: Invalid': await addComment( `| :warning: | Issue is Invalid |\n` + @@ -102,11 +102,11 @@ module.exports = async (github, context, label) => { ); await requestAuthorFeedback(); return; - case 'Needs: Verify on Latest Version': + case 'Newer Patch Available': await addComment( `| :warning: | Newer Version of React Native is Available! |\n` + `| --- | --- |\n` + - `| :information_source: | You are on a supported minor version, but it looks like there's a newer patch available. Please [upgrade](https://reactnative.dev/docs/upgrading) to the highest patch for your minor or latest and verify if the issue persists (alternatively, create a new project and repro the issue in it). If it does not repro, please let us know so we can close out this issue. This helps us ensure we are looking at issues that still exist in the most recent releases. |`, + `| :information_source: | You are on a supported minor version, but it looks like there's a newer patch available - ${labelWithContext.newestPatch}. Please [upgrade](https://reactnative.dev/docs/upgrading) to the highest patch for your minor or latest and verify if the issue persists (alternatively, create a new project and repro the issue in it). If it does not repro, please let us know so we can close out this issue. This helps us ensure we are looking at issues that still exist in the most recent releases. |`, ); return; case 'Needs: Version Info': diff --git a/.github/workflows/addDescriptiveLabels.js b/.github/workflow-scripts/addDescriptiveLabels.js similarity index 100% rename from .github/workflows/addDescriptiveLabels.js rename to .github/workflow-scripts/addDescriptiveLabels.js diff --git a/.github/workflow-scripts/verifyVersion.js b/.github/workflow-scripts/verifyVersion.js index da66a1f2f0f700..b91efe898eed6e 100644 --- a/.github/workflow-scripts/verifyVersion.js +++ b/.github/workflow-scripts/verifyVersion.js @@ -23,7 +23,7 @@ module.exports = async (github, context) => { if (reportedVersionIsNightly(issueVersionUnparsed, issueVersion)) return; if (!issueVersion) { - return 'Needs: Version Info'; + return {label: 'Needs: Version Info'}; } // Ensure the version matches one we support @@ -43,7 +43,7 @@ module.exports = async (github, context) => { const latestVersion = parseVersionFromString(latestRelease.name); if (!isVersionSupported(issueVersion, latestVersion)) { - return 'Type: Unsupported Version'; + return {label: 'Type: Unsupported Version'}; } // We want to encourage users to repro the issue on the highest available patch for the given minor. @@ -52,7 +52,10 @@ module.exports = async (github, context) => { recentReleases, ); if (latestPatchForVersion > issueVersion.patch) { - return 'Needs: Verify on Latest Version'; + return { + label: 'Newer Patch Available', + newestPatch: `${issueVersion.major}.${issueVersion.minor}.${latestPatchForVersion}`, + }; } }; diff --git a/.github/workflows/on-issue-labeled.yml b/.github/workflows/on-issue-labeled.yml index f4e976bd3d9695..14f9d4e9c5d608 100644 --- a/.github/workflows/on-issue-labeled.yml +++ b/.github/workflows/on-issue-labeled.yml @@ -23,25 +23,25 @@ jobs: with: script: | const verifyVersion = require('./.github/workflow-scripts/verifyVersion.js') - const labelToAdd = await verifyVersion(github, context); + const labelWithContext = await verifyVersion(github, context); - if(labelToAdd) { + if(labelWithContext && labelWithContext.label) { await github.rest.issues.addLabels({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, - labels: [labelToAdd] + labels: [labelWithContext.label] }) const actOnLabel = require('./.github/workflow-scripts/actOnLabel.js') - await actOnLabel(github, context, labelToAdd) + await actOnLabel(github, context, labelWithContext) } - name: Add descriptive label uses: actions/github-script@v6 with: script: | - const addDescriptiveLabel = require('./.github/workflows/addDescriptiveLabels.js') + const addDescriptiveLabel = require('./.github/workflow-scripts/addDescriptiveLabels.js') await addDescriptiveLabel(github, context); # Reacts to the label that triggered this workflow (added manually or via other workflows) @@ -54,4 +54,4 @@ jobs: with: script: | const actOnLabel = require('./.github/workflow-scripts/actOnLabel.js') - await actOnLabel(github, context, context.payload.label.name) + await actOnLabel(github, context, {label: context.payload.label.name}) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01a79289c2f7d6..315c44efb08823 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## v0.71.8 + +### Fixed + +#### Android specific + +- Read GROUP name in gradle-plugin dependency code ([615d9aefc4](https://github.com/facebook/react-native/commit/615d9aefc4274ed7a193c0410ed7f86e90ad1bff) by [@douglowder](https://github.com/douglowder)) +- Bump RNGP to 0.71.18 ([4bf4c470fe](https://github.com/facebook/react-native/commit/4bf4c470fe4996af02f45c9a9d77c6a790a95362) by [@kelset](https://github.com/kelset)) + +#### iOS specific + +- Do not send extra onChangeText even wnen instantianting multiline TextView ([a804c0f22b](https://github.com/facebook/react-native/commit/a804c0f22b4b11b3d9632dc59a6da14f6c4325e3) by [@dmytrorykun](https://github.com/dmytrorykun)) + ## v0.71.7 ### Fixed diff --git a/build.gradle.kts b/build.gradle.kts index 6899ccd139409b..1c3ebaccc359de 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,7 +10,7 @@ plugins { id("com.android.library") version "7.4.2" apply false id("com.android.application") version "7.4.2" apply false id("de.undercouch.download") version "5.0.1" apply false - kotlin("android") version "1.7.22" apply false + kotlin("android") version "1.8.0" apply false } val reactAndroidProperties = java.util.Properties() diff --git a/package.json b/package.json index 105af07bdb8f5f..27e5216b7e6bb8 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "outputName": "js-test-results.xml" }, "scripts": { - "start": "react-native start", + "start": "cd packages/rn-tester && npm run start", + "android": "cd packages/rn-tester && npm run android", "test": "jest", "test-ci": "jest --maxWorkers=2 --ci --reporters=\"default\" --reporters=\"jest-junit\"", "flow": "flow", @@ -51,14 +52,14 @@ }, "devDependencies": { "@babel/core": "^7.20.0", - "@babel/eslint-parser": "^7.19.0", + "@babel/eslint-parser": "^7.20.0", "@babel/generator": "^7.20.0", - "@babel/plugin-transform-regenerator": "^7.0.0", + "@babel/plugin-transform-regenerator": "^7.20.0", "@definitelytyped/dtslint": "^0.0.127", "@jest/create-cache-key-function": "^29.2.1", "@react-native/metro-config": "^0.73.0", "@types/react": "^18.0.18", - "@typescript-eslint/parser": "^5.30.5", + "@typescript-eslint/parser": "^5.57.1", "async": "^3.2.2", "babel-plugin-transform-flow-enums": "^0.0.2", "clang-format": "^1.8.0", @@ -77,7 +78,7 @@ "eslint-plugin-react-native": "^4.0.0", "eslint-plugin-redundant-undefined": "^0.4.0", "eslint-plugin-relay": "^1.8.3", - "flow-bin": "^0.204.1", + "flow-bin": "^0.206.0", "hermes-eslint": "0.8.0", "inquirer": "^7.1.0", "jest": "^29.2.1", @@ -93,7 +94,7 @@ "react-test-renderer": "18.2.0", "shelljs": "^0.8.5", "signedsource": "^1.0.0", - "typescript": "4.1.3", + "typescript": "5.0.4", "ws": "^6.2.2" } } diff --git a/packages/assets/README.md b/packages/assets/README.md new file mode 100644 index 00000000000000..407cc5b53de5fd --- /dev/null +++ b/packages/assets/README.md @@ -0,0 +1,21 @@ +# @react-native/assets-registry + +[![Version][version-badge]][package] + +## Installation + +``` +yarn add --dev @react-native/assets-registry +``` + +*Note: We're using `yarn` to install deps. Feel free to change commands to use `npm` 3+ and `npx` if you like* + +[version-badge]: https://img.shields.io/npm/v/@react-native/assets-registry?style=flat-square +[package]: https://www.npmjs.com/package/@react-native/assets-registry + +## Testing + +To run the tests in this package, run the following commands from the React Native root folder: + +1. `yarn` to install the dependencies. You just need to run this once +2. `yarn jest packages/assets`. diff --git a/packages/assets/package.json b/packages/assets/package.json index d0e755dc894c81..cd55b751e227b2 100644 --- a/packages/assets/package.json +++ b/packages/assets/package.json @@ -2,12 +2,15 @@ "name": "@react-native/assets-registry", "version": "0.73.0", "description": "Asset support code for React Native.", + "license": "MIT", "repository": { "type": "git", - "url": "git@github.com:facebook/react-native.git", + "url": "https://github.com/facebook/react-native.git", "directory": "packages/assets" }, - "license": "MIT", + "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/assets#readme", + "keywords": ["assets", "registry", "react-native", "support"], + "bugs": "https://github.com/facebook/react-native/issues", "engines": { "node": ">=16" } diff --git a/packages/assets/path-support.js b/packages/assets/path-support.js index a6c30d42375a55..f0a85af33ff98d 100644 --- a/packages/assets/path-support.js +++ b/packages/assets/path-support.js @@ -82,7 +82,7 @@ function getAndroidResourceIdentifier(asset: PackagerAsset): string { function getBasePath(asset: PackagerAsset): string { const basePath = asset.httpServerLocation; - return basePath.startsWith('/') ? basePath.substr(1) : basePath; + return basePath.startsWith('/') ? basePath.slice(1) : basePath; } module.exports = { diff --git a/packages/babel-plugin-codegen/README.md b/packages/babel-plugin-codegen/README.md new file mode 100644 index 00000000000000..34194810ab2bf8 --- /dev/null +++ b/packages/babel-plugin-codegen/README.md @@ -0,0 +1,21 @@ +# @react-native/babel-plugin-codegen + +[![Version][version-badge]][package] + +## Installation + +``` +yarn add --dev @babel/core @react-native/babel-plugin-codegen +``` + +*Note: We're using `yarn` to install deps. Feel free to change commands to use `npm` 3+ and `npx` if you like* + +[version-badge]: https://img.shields.io/npm/v/@react-native/babel-plugin-codegen?style=flat-square +[package]: https://www.npmjs.com/package/@react-native/babel-plugin-codegen + +## Testing + +To run the tests in this package, run the following commands from the React Native root folder: + +1. `yarn` to install the dependencies. You just need to run this once +2. `yarn jest packages/babel-plugin-codegen`. diff --git a/packages/babel-plugin-codegen/package.json b/packages/babel-plugin-codegen/package.json index 7054377c039b11..3e3edcdb4ba5c6 100644 --- a/packages/babel-plugin-codegen/package.json +++ b/packages/babel-plugin-codegen/package.json @@ -1,12 +1,16 @@ { - "version": "0.73.0", "name": "@react-native/babel-plugin-codegen", + "version": "0.73.0", "description": "Babel plugin to generate native module and view manager code for React Native.", + "license": "MIT", "repository": { "type": "git", - "url": "git@github.com:facebook/react-native.git", + "url": "https://github.com/facebook/react-native.git", "directory": "packages/babel-plugin-codegen" }, + "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/babel-plugin-codegen#readme", + "keywords": ["babel", "plugin", "codegen", "react-native", "native-modules", "view-manager"], + "bugs": "https://github.com/facebook/react-native/issues", "engines": { "node": ">=16" }, @@ -18,6 +22,5 @@ }, "devDependencies": { "@babel/core": "^7.20.0" - }, - "license": "MIT" + } } diff --git a/packages/eslint-config-react-native-community/README.md b/packages/eslint-config-react-native/README.md similarity index 100% rename from packages/eslint-config-react-native-community/README.md rename to packages/eslint-config-react-native/README.md diff --git a/packages/eslint-config-react-native-community/index.js b/packages/eslint-config-react-native/index.js similarity index 100% rename from packages/eslint-config-react-native-community/index.js rename to packages/eslint-config-react-native/index.js diff --git a/packages/eslint-config-react-native-community/package.json b/packages/eslint-config-react-native/package.json similarity index 68% rename from packages/eslint-config-react-native-community/package.json rename to packages/eslint-config-react-native/package.json index 91894a928469c9..c71bff02bd7ae6 100644 --- a/packages/eslint-config-react-native-community/package.json +++ b/packages/eslint-config-react-native/package.json @@ -2,23 +2,25 @@ "name": "@react-native/eslint-config", "version": "0.73.0", "description": "ESLint config for React Native", - "main": "index.js", "license": "MIT", "repository": { "type": "git", - "url": "git@github.com:facebook/react-native.git", - "directory": "packages/eslint-config-react-native-community" + "url": "https://github.com/facebook/react-native.git", + "directory": "packages/eslint-config-react-native" }, - "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/eslint-config-react-native-community#readme", + "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/eslint-config-react-native#readme", + "keywords": ["eslint", "config", "react-native"], + "bugs": "https://github.com/facebook/react-native/issues", "engines": { "node": ">=16" }, + "main": "index.js", "dependencies": { "@babel/core": "^7.20.0", - "@babel/eslint-parser": "^7.19.0", + "@babel/eslint-parser": "^7.20.0", "@react-native/eslint-plugin": "^0.73.0", - "@typescript-eslint/eslint-plugin": "^5.30.5", - "@typescript-eslint/parser": "^5.30.5", + "@typescript-eslint/eslint-plugin": "^5.57.1", + "@typescript-eslint/parser": "^5.57.1", "eslint-config-prettier": "^8.5.0", "eslint-plugin-eslint-comments": "^3.2.0", "eslint-plugin-ft-flow": "^2.0.1", diff --git a/packages/eslint-plugin-react-native-community/package.json b/packages/eslint-plugin-react-native-community/package.json deleted file mode 100644 index 202a4dfb771ddc..00000000000000 --- a/packages/eslint-plugin-react-native-community/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "@react-native/eslint-plugin", - "version": "0.73.0", - "description": "ESLint rules for @react-native/eslint-config", - "main": "index.js", - "repository": { - "type": "git", - "url": "git@github.com:facebook/react-native.git", - "directory": "packages/eslint-plugin-react-native-community" - }, - "license": "MIT", - "engines": { - "node": ">=16" - } -} diff --git a/packages/eslint-plugin-react-native-community/README.md b/packages/eslint-plugin-react-native/README.md similarity index 67% rename from packages/eslint-plugin-react-native-community/README.md rename to packages/eslint-plugin-react-native/README.md index 1cf77b71d421f6..48fc9bcf67c1a0 100644 --- a/packages/eslint-plugin-react-native-community/README.md +++ b/packages/eslint-plugin-react-native/README.md @@ -1,6 +1,6 @@ # @react-native/eslint-plugin -This plugin is intended to be used in [`@react-native/eslint-config`](https://github.com/facebook/react-native/tree/HEAD/packages/eslint-config-react-native-community). You probably want to install that package instead. +This plugin is intended to be used in [`@react-native/eslint-config`](https://github.com/facebook/react-native/tree/HEAD/packages/eslint-config-react-native). You probably want to install that package instead. ## Installation @@ -25,3 +25,10 @@ Add to your eslint config (`.eslintrc`, or `eslintConfig` field in `package.json ### `platform-colors` Enforces that calls to `PlatformColor` and `DynamicColorIOS` are statically analyzable to enable performance optimizations. + +## Testing + +To run the tests in this package, run the following commands from the React Native root folder: + +1. `yarn` to install the dependencies. You just need to run this once +2. `yarn jest packages/eslint-plugin-react-native`. diff --git a/packages/eslint-plugin-react-native-community/__tests__/eslint-tester.js b/packages/eslint-plugin-react-native/__tests__/eslint-tester.js similarity index 100% rename from packages/eslint-plugin-react-native-community/__tests__/eslint-tester.js rename to packages/eslint-plugin-react-native/__tests__/eslint-tester.js diff --git a/packages/eslint-plugin-react-native-community/__tests__/platform-colors-test.js b/packages/eslint-plugin-react-native/__tests__/platform-colors-test.js similarity index 100% rename from packages/eslint-plugin-react-native-community/__tests__/platform-colors-test.js rename to packages/eslint-plugin-react-native/__tests__/platform-colors-test.js diff --git a/packages/eslint-plugin-react-native-community/index.js b/packages/eslint-plugin-react-native/index.js similarity index 100% rename from packages/eslint-plugin-react-native-community/index.js rename to packages/eslint-plugin-react-native/index.js diff --git a/packages/eslint-plugin-react-native/package.json b/packages/eslint-plugin-react-native/package.json new file mode 100644 index 00000000000000..becda76cc32ffc --- /dev/null +++ b/packages/eslint-plugin-react-native/package.json @@ -0,0 +1,18 @@ +{ + "name": "@react-native/eslint-plugin", + "version": "0.73.0", + "description": "ESLint rules for @react-native/eslint-config", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/facebook/react-native.git", + "directory": "packages/eslint-plugin-react-native" + }, + "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/eslint-plugin-react-native#readme", + "keywords": ["eslint", "rules", "eslint-config", "react-native"], + "bugs": "https://github.com/facebook/react-native/issues", + "engines": { + "node": ">=16" + }, + "main": "index.js" +} diff --git a/packages/eslint-plugin-react-native-community/platform-colors.js b/packages/eslint-plugin-react-native/platform-colors.js similarity index 100% rename from packages/eslint-plugin-react-native-community/platform-colors.js rename to packages/eslint-plugin-react-native/platform-colors.js diff --git a/packages/eslint-plugin-specs/README.md b/packages/eslint-plugin-specs/README.md new file mode 100644 index 00000000000000..824fe031ea64c1 --- /dev/null +++ b/packages/eslint-plugin-specs/README.md @@ -0,0 +1,21 @@ +# @react-native/eslint-plugin-specs + +[![Version][version-badge]][package] + +## Installation + +``` +yarn add --dev @react-native/eslint-plugin-specs +``` + +*Note: We're using `yarn` to install deps. Feel free to change commands to use `npm` 3+ and `npx` if you like* + +[version-badge]: https://img.shields.io/npm/v/@react-native/eslint-plugin-specs?style=flat-square +[package]: https://www.npmjs.com/package/@react-native/eslint-plugin-specs + +## Testing + +To run the tests in this package, run the following commands from the React Native root folder: + +1. `yarn` to install the dependencies. You just need to run this once +2. `yarn jest packages/eslint-plugin-specs`. diff --git a/packages/eslint-plugin-specs/package.json b/packages/eslint-plugin-specs/package.json index 76a91ea4b96cd8..8950f82a0ff850 100644 --- a/packages/eslint-plugin-specs/package.json +++ b/packages/eslint-plugin-specs/package.json @@ -2,29 +2,32 @@ "name": "@react-native/eslint-plugin-specs", "version": "0.73.0", "description": "ESLint rules to validate NativeModule and Component Specs", - "main": "index.js", + "license": "MIT", "repository": { "type": "git", - "url": "git@github.com:facebook/react-native.git", + "url": "https://github.com/facebook/react-native.git", "directory": "packages/eslint-plugin-specs" }, + "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/eslint-plugin-specs#readme", + "keywords": ["eslint", "rules", "react-native", "native-modules", "components", "specs"], + "bugs": "https://github.com/facebook/react-native/issues", "engines": { "node": ">=16" }, + "main": "index.js", "scripts": { "prepack": "node prepack.js", "postpack": "node postpack.js" }, "dependencies": { "@babel/core": "^7.20.0", - "@babel/eslint-parser": "^7.19.0", - "@babel/plugin-transform-flow-strip-types": "^7.0.0", - "@babel/preset-flow": "^7.18.0", + "@babel/eslint-parser": "^7.20.0", + "@babel/plugin-transform-flow-strip-types": "^7.20.0", + "@babel/preset-flow": "^7.20.0", "@react-native/codegen": "*", - "flow-parser": "^0.185.0", + "flow-parser": "^0.206.0", "make-dir": "^2.1.0", "pirates": "^4.0.1", "source-map-support": "0.5.0" - }, - "license": "MIT" + } } diff --git a/packages/eslint-plugin-specs/react-native-modules.js b/packages/eslint-plugin-specs/react-native-modules.js index 816ab33f2ab677..9f142919d9e075 100644 --- a/packages/eslint-plugin-specs/react-native-modules.js +++ b/packages/eslint-plugin-specs/react-native-modules.js @@ -69,7 +69,6 @@ function requireModuleParser() { buildModuleSchema: RNParserCommons.buildModuleSchema, createParserErrorCapturer: RNParserUtils.createParserErrorCapturer, parser: new RNFlowParser.FlowParser(), - resolveTypeAnnotation: RNFlowParserUtils.resolveTypeAnnotation, translateTypeAnnotation: RNModuleParser.flowTranslateTypeAnnotation, }; } @@ -149,7 +148,6 @@ function rule(context) { buildModuleSchema, createParserErrorCapturer, parser, - resolveTypeAnnotation, translateTypeAnnotation, } = requireModuleParser(); @@ -164,7 +162,6 @@ function rule(context) { ast, tryParse, parser, - resolveTypeAnnotation, translateTypeAnnotation, ); }); diff --git a/packages/hermes-inspector-msggen/README.md b/packages/hermes-inspector-msggen/README.md new file mode 100644 index 00000000000000..b2b98932e32dd4 --- /dev/null +++ b/packages/hermes-inspector-msggen/README.md @@ -0,0 +1,21 @@ +# @react-native/hermes-inspector-msggen + +[![Version][version-badge]][package] + +## Installation + +``` +yarn add --dev @babel/cli @babel/core @babel/preset-env @babel/preset-flow jest @react-native/hermes-inspector-msggen +``` + +*Note: We're using `yarn` to install deps. Feel free to change commands to use `npm` 3+ and `npx` if you like* + +[version-badge]: https://img.shields.io/npm/v/@react-native/hermes-inspector-msggen?style=flat-square +[package]: https://www.npmjs.com/package/@react-native/hermes-inspector-msggen + +## Testing + +To run the tests in this package, run the following commands from the React Native root folder: + +1. `yarn` to install the dependencies. You just need to run this once +2. `yarn jest packages/hermes-inspector-msggen`. diff --git a/packages/hermes-inspector-msggen/__tests__/CommandTest.js b/packages/hermes-inspector-msggen/__tests__/command-test.js similarity index 100% rename from packages/hermes-inspector-msggen/__tests__/CommandTest.js rename to packages/hermes-inspector-msggen/__tests__/command-test.js diff --git a/packages/hermes-inspector-msggen/__tests__/EventTest.js b/packages/hermes-inspector-msggen/__tests__/event-test.js similarity index 100% rename from packages/hermes-inspector-msggen/__tests__/EventTest.js rename to packages/hermes-inspector-msggen/__tests__/event-test.js diff --git a/packages/hermes-inspector-msggen/__tests__/GraphTest.js b/packages/hermes-inspector-msggen/__tests__/graph-test.js similarity index 84% rename from packages/hermes-inspector-msggen/__tests__/GraphTest.js rename to packages/hermes-inspector-msggen/__tests__/graph-test.js index b890c050ea8905..5d4043b80e0017 100644 --- a/packages/hermes-inspector-msggen/__tests__/GraphTest.js +++ b/packages/hermes-inspector-msggen/__tests__/graph-test.js @@ -25,8 +25,8 @@ beforeEach(() => { // checks id1 occurs after id2 in arr function expectOccursAfter(arr, id1, id2) { - let idx1 = arr.indexOf(id1); - let idx2 = arr.indexOf(id2); + const idx1 = arr.indexOf(id1); + const idx2 = arr.indexOf(id2); expect(idx1).not.toBe(-1); expect(idx2).not.toBe(-1); @@ -35,7 +35,9 @@ function expectOccursAfter(arr, id1, id2) { test('detects cycle', () => { graph.addEdge('C2', 'A1'); - expect(() => graph.traverse(['A2'])).toThrow(/^Not a DAG/); + + const {cycles} = graph.traverse(['A2']); + expect(cycles).toContainEqual({from: 'A1', to: 'B1'}); }); test('checks for presence of root', () => { @@ -43,10 +45,10 @@ test('checks for presence of root', () => { }); test('traverses partial graph', () => { - let ids = graph.traverse(['B1', 'A3']); + const {nodes: ids} = graph.traverse(['B1', 'A3']); // Check that expected nodes are there - let sortedIds = ids.slice().sort(); + const sortedIds = ids.slice().sort(); expect(sortedIds).toEqual(['A3', 'B1', 'B2', 'C1', 'C2', 'C3']); // Check that the result is topologically sorted @@ -59,10 +61,10 @@ test('traverses partial graph', () => { }); test('traverses complete graph', () => { - let ids = graph.traverse(['A1', 'A2', 'A3']); + const {nodes: ids} = graph.traverse(['A1', 'A2', 'A3']); // Check that expected nodes are there - let sortedIds = ids.slice().sort(); + const sortedIds = ids.slice().sort(); expect(sortedIds).toEqual(['A1', 'A2', 'A3', 'B1', 'B2', 'C1', 'C2', 'C3']); // Check that the result is topologically sorted diff --git a/packages/hermes-inspector-msggen/__tests__/HeaderWriterTest.js b/packages/hermes-inspector-msggen/__tests__/header-writer-test.js similarity index 95% rename from packages/hermes-inspector-msggen/__tests__/HeaderWriterTest.js rename to packages/hermes-inspector-msggen/__tests__/header-writer-test.js index da8bf0c03a6b50..5ba2bb2a1158b5 100644 --- a/packages/hermes-inspector-msggen/__tests__/HeaderWriterTest.js +++ b/packages/hermes-inspector-msggen/__tests__/header-writer-test.js @@ -40,8 +40,12 @@ test('emits type decl', () => { expectCodeIsEqual(stream.get(), ` struct debugger::Location : public Serializable { Location() = default; + Location(Location&&) = default; + Location(const Location&) = delete; explicit Location(const folly::dynamic &obj); folly::dynamic toDynamic() const override; + Location& operator=(const Location&) = delete; + Location& operator=(Location&&) = default; runtime::ScriptId scriptId{}; int lineNumber{}; diff --git a/packages/hermes-inspector-msggen/__tests__/ImplementationWriterTest.js b/packages/hermes-inspector-msggen/__tests__/implementation-writer-test.js similarity index 100% rename from packages/hermes-inspector-msggen/__tests__/ImplementationWriterTest.js rename to packages/hermes-inspector-msggen/__tests__/implementation-writer-test.js diff --git a/packages/hermes-inspector-msggen/__tests__/PropertyTest.js b/packages/hermes-inspector-msggen/__tests__/property-test.js similarity index 100% rename from packages/hermes-inspector-msggen/__tests__/PropertyTest.js rename to packages/hermes-inspector-msggen/__tests__/property-test.js diff --git a/packages/hermes-inspector-msggen/__tests__/TypeTest.js b/packages/hermes-inspector-msggen/__tests__/type-test.js similarity index 100% rename from packages/hermes-inspector-msggen/__tests__/TypeTest.js rename to packages/hermes-inspector-msggen/__tests__/type-test.js diff --git a/packages/hermes-inspector-msggen/package.json b/packages/hermes-inspector-msggen/package.json index ea8978f7810fbd..bc4611a469301d 100644 --- a/packages/hermes-inspector-msggen/package.json +++ b/packages/hermes-inspector-msggen/package.json @@ -1,8 +1,14 @@ { "name": "@react-native/hermes-inspector-msggen", - "private": true, "version": "0.72.0", + "private": true, + "description": "Hermes Inspector Message Generator for React Native", "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/facebook/react-native.git", + "directory": "packages/hermes-inspector-msggen" + }, "bin": { "msggen": "./bin/index.js" }, @@ -20,10 +26,10 @@ "yargs": "^17.6.2" }, "devDependencies": { - "@babel/cli": "^7.19.0", + "@babel/cli": "^7.20.0", "@babel/core": "^7.20.0", "@babel/preset-env": "^7.20.0", - "@babel/preset-flow": "^7.18.0", + "@babel/preset-flow": "^7.20.0", "jest": "^29.2.1" }, "jest": { diff --git a/packages/hermes-inspector-msggen/src/Converters.js b/packages/hermes-inspector-msggen/src/Converters.js index 8061ef1a41aa24..aa5dbf86552cb6 100644 --- a/packages/hermes-inspector-msggen/src/Converters.js +++ b/packages/hermes-inspector-msggen/src/Converters.js @@ -9,11 +9,11 @@ */ export function toCppNamespace(domain: string): string { - return domain.substr(0, 1).toLowerCase() + domain.substr(1); + return domain.slice(0, 1).toLowerCase() + domain.slice(1); } export function toCppType(type: string): string { - return type.substr(0, 1).toUpperCase() + type.substr(1); + return type.slice(0, 1).toUpperCase() + type.slice(1); } export type JsTypeString = diff --git a/packages/hermes-inspector-msggen/src/Property.js b/packages/hermes-inspector-msggen/src/Property.js index d50df01f50327f..fdad9bc6f7b306 100644 --- a/packages/hermes-inspector-msggen/src/Property.js +++ b/packages/hermes-inspector-msggen/src/Property.js @@ -114,8 +114,8 @@ function toDomainAndId( domain = curDomain; id = absOrRelRef; } else { - domain = absOrRelRef.substr(0, i); - id = absOrRelRef.substr(i + 1); + domain = absOrRelRef.slice(0, i); + id = absOrRelRef.slice(i + 1); } return [domain, id]; diff --git a/packages/metro-config/README.md b/packages/metro-config/README.md new file mode 100644 index 00000000000000..903a3b3a76d3df --- /dev/null +++ b/packages/metro-config/README.md @@ -0,0 +1,21 @@ +# @react-native/metro-config + +[![Version][version-badge]][package] + +## Installation + +``` +yarn add --dev @react-native/js-polyfills metro-config metro-react-native-babel-transformer metro-runtime @react-native/metro-config +``` + +*Note: We're using `yarn` to install deps. Feel free to change commands to use `npm` 3+ and `npx` if you like* + +[version-badge]: https://img.shields.io/npm/v/@react-native/metro-config?style=flat-square +[package]: https://www.npmjs.com/package/@react-native/metro-config + +## Testing + +To run the tests in this package, run the following commands from the React Native root folder: + +1. `yarn` to install the dependencies. You just need to run this once +2. `yarn jest packages/metro-config`. diff --git a/packages/metro-config/package.json b/packages/metro-config/package.json index fdb735021273e5..e86d78e60321ab 100644 --- a/packages/metro-config/package.json +++ b/packages/metro-config/package.json @@ -2,12 +2,15 @@ "name": "@react-native/metro-config", "version": "0.73.0", "description": "Metro configuration for React Native.", + "license": "MIT", "repository": { "type": "git", - "url": "git@github.com:facebook/react-native.git", + "url": "https://github.com/facebook/react-native.git", "directory": "packages/metro-config" }, - "license": "MIT", + "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/metro-config#readme", + "keywords": ["metro", "config", "react-native"], + "bugs": "https://github.com/facebook/react-native/issues", "engines": { "node": ">=16" }, diff --git a/packages/normalize-color/README.md b/packages/normalize-color/README.md new file mode 100644 index 00000000000000..20b618d930a592 --- /dev/null +++ b/packages/normalize-color/README.md @@ -0,0 +1,21 @@ +# @react-native/normalize-colors + +[![Version][version-badge]][package] + +## Installation + +``` +yarn add --dev @react-native/normalize-colors +``` + +*Note: We're using `yarn` to install deps. Feel free to change commands to use `npm` 3+ and `npx` if you like* + +[version-badge]: https://img.shields.io/npm/v/@react-native/normalize-colors?style=flat-square +[package]: https://www.npmjs.com/package/@react-native/normalize-colors + +## Testing + +To run the tests in this package, run the following commands from the React Native root folder: + +1. `yarn` to install the dependencies. You just need to run this once +2. `yarn jest packages/normalize-color`. diff --git a/packages/normalize-color/package.json b/packages/normalize-color/package.json index d3319212203e59..079c3fe4dabea3 100644 --- a/packages/normalize-color/package.json +++ b/packages/normalize-color/package.json @@ -2,12 +2,15 @@ "name": "@react-native/normalize-colors", "version": "0.73.0", "description": "Color normalization for React Native.", + "license": "MIT", "repository": { "type": "git", - "url": "git@github.com:facebook/react-native.git", + "url": "https://github.com/facebook/react-native.git", "directory": "packages/normalize-color" }, - "license": "MIT", + "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/normalize-color#readme", + "keywords": ["color", "normalization", "normalize-colors", "react-native"], + "bugs": "https://github.com/facebook/react-native/issues", "engines": { "node": ">=16" } diff --git a/packages/polyfills/README.md b/packages/polyfills/README.md new file mode 100644 index 00000000000000..91f0b04de013bc --- /dev/null +++ b/packages/polyfills/README.md @@ -0,0 +1,21 @@ +# @react-native/js-polyfills + +[![Version][version-badge]][package] + +## Installation + +``` +yarn add @react-native/js-polyfills +``` + +*Note: We're using `yarn` to install deps. Feel free to change commands to use `npm` 3+ and `npx` if you like* + +[version-badge]: https://img.shields.io/npm/v/@react-native/js-polyfills?style=flat-square +[package]: https://www.npmjs.com/package/@react-native/js-polyfills + +## Testing + +To run the tests in this package, run the following commands from the React Native root folder: + +1. `yarn` to install the dependencies. You just need to run this once +2. `yarn jest packages/polyfills`. diff --git a/packages/polyfills/console.js b/packages/polyfills/console.js index e843f4f74caa3c..338e1590cb3bc7 100644 --- a/packages/polyfills/console.js +++ b/packages/polyfills/console.js @@ -252,7 +252,7 @@ const inspect = (function () { return ' ' + line; }) .join('\n') - .substr(2); + .slice(2); } else { str = '\n' + @@ -274,7 +274,7 @@ const inspect = (function () { } name = JSON.stringify('' + key); if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { - name = name.substr(1, name.length - 2); + name = name.slice(1, name.length - 1); name = ctx.stylize(name, 'name'); } else { name = name diff --git a/packages/polyfills/package.json b/packages/polyfills/package.json index 79b644495b5a62..de11f640d1be8f 100644 --- a/packages/polyfills/package.json +++ b/packages/polyfills/package.json @@ -2,12 +2,15 @@ "name": "@react-native/js-polyfills", "version": "0.73.0", "description": "Polyfills for React Native.", + "license": "MIT", "repository": { "type": "git", - "url": "git@github.com:facebook/react-native.git", + "url": "https://github.com/facebook/react-native.git", "directory": "packages/polyfills" }, - "license": "MIT", + "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/polyfills#readme", + "keywords": ["polyfill", "polyfills", "js", "js-polyfills", "react-native"], + "bugs": "https://github.com/facebook/react-native/issues", "engines": { "node": ">=16" } diff --git a/packages/react-native-bots/package.json b/packages/react-native-bots/package.json index 43bbff5cbc2bcd..5a86115c8a9696 100644 --- a/packages/react-native-bots/package.json +++ b/packages/react-native-bots/package.json @@ -1,7 +1,15 @@ { "name": "@react-native/bots", + "description": "React Native Bots", "version": "0.0.0", "private": true, + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/facebook/react-native.git", + "directory": "packages/react-native-bots" + }, + "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/react-native-bots#readme", "engines": { "node": ">=16" }, diff --git a/packages/react-native-codegen-typescript-test/package.json b/packages/react-native-codegen-typescript-test/package.json index d023ab9435cdfe..f24dd96c9d5372 100644 --- a/packages/react-native-codegen-typescript-test/package.json +++ b/packages/react-native-codegen-typescript-test/package.json @@ -1,13 +1,14 @@ { "name": "@react-native/codegen-typescript-test", "version": "0.0.1", - "description": "⚛️ TypeScript related unit test for @react-native/codegen", - "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/react-native-typescript-test", + "description": "TypeScript related unit test for @react-native/codegen", + "license": "MIT", "repository": { "type": "git", - "url": "git@github.com:facebook/react-native.git", + "url": "https://github.com/facebook/react-native.git", "directory": "packages/react-native-codegen-typescript-test" }, + "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/react-native-typescript-test", "engines": { "node": ">=16" }, @@ -16,21 +17,20 @@ "clean": "rimraf lib && rimraf __generated__/*.ts", "prepare": "yarn run build" }, - "license": "MIT", "dependencies": { "@react-native/codegen": "*" }, "devDependencies": { "@babel/core": "^7.20.0", - "@babel/plugin-proposal-class-properties": "^7.0.0", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", - "@babel/plugin-proposal-object-rest-spread": "^7.0.0", - "@babel/plugin-proposal-optional-chaining": "^7.0.0", - "@babel/plugin-syntax-dynamic-import": "^7.0.0", - "@babel/plugin-transform-async-to-generator": "^7.0.0", - "@babel/plugin-transform-destructuring": "^7.0.0", - "@babel/plugin-transform-flow-strip-types": "^7.0.0", - "@babel/preset-env": "^7.14.0", + "@babel/plugin-proposal-class-properties": "^7.18.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.0", + "@babel/plugin-proposal-object-rest-spread": "^7.20.0", + "@babel/plugin-proposal-optional-chaining": "^7.20.0", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-transform-async-to-generator": "^7.20.0", + "@babel/plugin-transform-destructuring": "^7.20.0", + "@babel/plugin-transform-flow-strip-types": "^7.20.0", + "@babel/preset-env": "^7.20.0", "@types/jest": "^24.0.17", "jest": "^24.0.17", "rimraf": "^3.0.2" diff --git a/packages/react-native-codegen/README.md b/packages/react-native-codegen/README.md index 2380d87f716a3a..8f6856b1c8f073 100644 --- a/packages/react-native-codegen/README.md +++ b/packages/react-native-codegen/README.md @@ -15,7 +15,7 @@ yarn add --dev @react-native/codegen ## Testing -To run the tests in this package, run the following commands from the react Native root folder: +To run the tests in this package, run the following commands from the React Native root folder: 1. `yarn` to install the dependencies. You just need to run this once -2. `yarn jest react-native-codegen`. +2. `yarn jest packages/react-native-codegen`. diff --git a/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleH-test.js.snap b/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleH-test.js.snap index b6a85b3f1ac7a4..cee8760bb3bbef 100644 --- a/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleH-test.js.snap +++ b/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleH-test.js.snap @@ -193,7 +193,7 @@ enum NativeEnumTurboModuleStatusRegularEnum { Active, Paused, Off }; template <> struct Bridging { - static NativeEnumTurboModuleStatusRegularEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue, const std::shared_ptr &jsInvoker) { + static NativeEnumTurboModuleStatusRegularEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue) { std::string value = rawValue.utf8(rt); if (value == \\"Active\\") { return NativeEnumTurboModuleStatusRegularEnum::Active; @@ -225,7 +225,7 @@ enum NativeEnumTurboModuleStatusStrEnum { Active, Paused, Off }; template <> struct Bridging { - static NativeEnumTurboModuleStatusStrEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue, const std::shared_ptr &jsInvoker) { + static NativeEnumTurboModuleStatusStrEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue) { std::string value = rawValue.utf8(rt); if (value == \\"active\\") { return NativeEnumTurboModuleStatusStrEnum::Active; @@ -257,7 +257,7 @@ enum NativeEnumTurboModuleStatusNumEnum { Active, Paused, Off }; template <> struct Bridging { - static NativeEnumTurboModuleStatusNumEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue, const std::shared_ptr &jsInvoker) { + static NativeEnumTurboModuleStatusNumEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue) { double value = (double)rawValue.asNumber(); if (value == 2) { return NativeEnumTurboModuleStatusNumEnum::Active; @@ -289,7 +289,7 @@ enum NativeEnumTurboModuleStatusFractionEnum { Active, Paused, Off }; template <> struct Bridging { - static NativeEnumTurboModuleStatusFractionEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue, const std::shared_ptr &jsInvoker) { + static NativeEnumTurboModuleStatusFractionEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue) { double value = (double)rawValue.asNumber(); if (value == 0.2f) { return NativeEnumTurboModuleStatusFractionEnum::Active; @@ -2136,7 +2136,7 @@ enum NativeEnumTurboModuleStatusRegularEnum { Active, Paused, Off }; template <> struct Bridging { - static NativeEnumTurboModuleStatusRegularEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue, const std::shared_ptr &jsInvoker) { + static NativeEnumTurboModuleStatusRegularEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue) { std::string value = rawValue.utf8(rt); if (value == \\"Active\\") { return NativeEnumTurboModuleStatusRegularEnum::Active; @@ -2168,7 +2168,7 @@ enum NativeEnumTurboModuleStatusStrEnum { Active, Paused, Off }; template <> struct Bridging { - static NativeEnumTurboModuleStatusStrEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue, const std::shared_ptr &jsInvoker) { + static NativeEnumTurboModuleStatusStrEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue) { std::string value = rawValue.utf8(rt); if (value == \\"active\\") { return NativeEnumTurboModuleStatusStrEnum::Active; @@ -2200,7 +2200,7 @@ enum NativeEnumTurboModuleStatusNumEnum { Active, Paused, Off }; template <> struct Bridging { - static NativeEnumTurboModuleStatusNumEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue, const std::shared_ptr &jsInvoker) { + static NativeEnumTurboModuleStatusNumEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue) { double value = (double)rawValue.asNumber(); if (value == 2) { return NativeEnumTurboModuleStatusNumEnum::Active; @@ -2232,7 +2232,7 @@ enum NativeEnumTurboModuleStatusFractionEnum { Active, Paused, Off }; template <> struct Bridging { - static NativeEnumTurboModuleStatusFractionEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue, const std::shared_ptr &jsInvoker) { + static NativeEnumTurboModuleStatusFractionEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue) { double value = (double)rawValue.asNumber(); if (value == 0.2f) { return NativeEnumTurboModuleStatusFractionEnum::Active; diff --git a/packages/react-native-codegen/package.json b/packages/react-native-codegen/package.json index 4afe3082e0af20..02c5019becaa1b 100644 --- a/packages/react-native-codegen/package.json +++ b/packages/react-native-codegen/package.json @@ -1,13 +1,16 @@ { "name": "@react-native/codegen", "version": "0.73.0", - "description": "⚛️ Code generation tools for React Native", - "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/react-native-codegen", + "description": "Code generation tools for React Native", + "license": "MIT", "repository": { "type": "git", - "url": "git@github.com:facebook/react-native.git", + "url": "https://github.com/facebook/react-native.git", "directory": "packages/react-native-codegen" }, + "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/react-native-codegen#readme", + "keywords": ["code", "generation", "codegen", "tools", "react-native"], + "bugs": "https://github.com/facebook/react-native/issues", "engines": { "node": ">=16" }, @@ -16,27 +19,26 @@ "clean": "rimraf lib", "prepare": "yarn run build" }, - "license": "MIT", "files": [ "lib" ], "dependencies": { "@babel/parser": "^7.20.0", - "flow-parser": "^0.185.0", + "flow-parser": "^0.206.0", "jscodeshift": "^0.14.0", "nullthrows": "^1.1.1" }, "devDependencies": { "@babel/core": "^7.20.0", - "@babel/plugin-proposal-class-properties": "^7.0.0", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", - "@babel/plugin-proposal-object-rest-spread": "^7.0.0", - "@babel/plugin-proposal-optional-chaining": "^7.0.0", - "@babel/plugin-syntax-dynamic-import": "^7.0.0", - "@babel/plugin-transform-async-to-generator": "^7.0.0", - "@babel/plugin-transform-destructuring": "^7.0.0", - "@babel/plugin-transform-flow-strip-types": "^7.0.0", - "@babel/preset-env": "^7.14.0", + "@babel/plugin-proposal-class-properties": "^7.18.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.0", + "@babel/plugin-proposal-object-rest-spread": "^7.20.0", + "@babel/plugin-proposal-optional-chaining": "^7.20.0", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-transform-async-to-generator": "^7.20.0", + "@babel/plugin-transform-destructuring": "^7.20.0", + "@babel/plugin-transform-flow-strip-types": "^7.20.0", + "@babel/preset-env": "^7.20.0", "chalk": "^4.0.0", "glob": "^7.1.1", "invariant": "^2.2.4", diff --git a/packages/react-native-codegen/src/CodegenSchema.d.ts b/packages/react-native-codegen/src/CodegenSchema.d.ts index 78db904aa4c404..3482172d99009f 100644 --- a/packages/react-native-codegen/src/CodegenSchema.d.ts +++ b/packages/react-native-codegen/src/CodegenSchema.d.ts @@ -113,7 +113,11 @@ export type EventTypeAnnotation = | FloatTypeAnnotation | Int32TypeAnnotation | StringEnumTypeAnnotation - | ObjectTypeAnnotation; + | ObjectTypeAnnotation + | { + readonly type: 'ArrayTypeAnnotation'; + readonly elementType: EventTypeAnnotation + }; export type PropTypeAnnotation = | { @@ -291,6 +295,7 @@ export interface NativeModuleEnumDeclarationWithMembers { export interface NativeModuleGenericObjectTypeAnnotation { readonly type: 'GenericObjectTypeAnnotation'; + readonly dictionaryValueType?: Nullable | undefined; } export interface NativeModuleTypeAliasTypeAnnotation { @@ -352,4 +357,3 @@ export type NativeModuleReturnOnlyTypeAnnotation = | NativeModuleFunctionTypeAnnotation | NativeModulePromiseTypeAnnotation | VoidTypeAnnotation; - diff --git a/packages/react-native-codegen/src/CodegenSchema.js b/packages/react-native-codegen/src/CodegenSchema.js index 361d54ef75c596..f05a4f2e749ab3 100644 --- a/packages/react-native-codegen/src/CodegenSchema.js +++ b/packages/react-native-codegen/src/CodegenSchema.js @@ -128,7 +128,11 @@ export type EventTypeAnnotation = | Int32TypeAnnotation | MixedTypeAnnotation | StringEnumTypeAnnotation - | ObjectTypeAnnotation; + | ObjectTypeAnnotation + | $ReadOnly<{ + type: 'ArrayTypeAnnotation', + elementType: EventTypeAnnotation, + }>; export type PropTypeAnnotation = | $ReadOnly<{ @@ -324,6 +328,11 @@ export type NativeModuleEnumDeclarationWithMembers = { export type NativeModuleGenericObjectTypeAnnotation = $ReadOnly<{ type: 'GenericObjectTypeAnnotation', + + // a dictionary type is codegen as "Object" + // but we know all its members are in the same type + // when it happens, the following field is non-null + dictionaryValueType?: Nullable, }>; export type NativeModuleTypeAliasTypeAnnotation = $ReadOnly<{ diff --git a/packages/react-native-codegen/src/generators/components/CppHelpers.js b/packages/react-native-codegen/src/generators/components/CppHelpers.js index e1fbfb79dc1d7b..ccecb1bcd08073 100644 --- a/packages/react-native-codegen/src/generators/components/CppHelpers.js +++ b/packages/react-native-codegen/src/generators/components/CppHelpers.js @@ -49,6 +49,42 @@ function getCppTypeForAnnotation( } } +function getCppArrayTypeForAnnotation( + typeElement: EventTypeAnnotation, + structParts?: string[], +): string { + switch (typeElement.type) { + case 'BooleanTypeAnnotation': + case 'StringTypeAnnotation': + case 'DoubleTypeAnnotation': + case 'FloatTypeAnnotation': + case 'Int32TypeAnnotation': + case 'MixedTypeAnnotation': + return `std::vector<${getCppTypeForAnnotation(typeElement.type)}>`; + case 'StringEnumTypeAnnotation': + case 'ObjectTypeAnnotation': + if (!structParts) { + throw new Error( + `Trying to generate the event emitter for an Array of ${typeElement.type} without informations to generate the generic type`, + ); + } + return `std::vector<${generateEventStructName(structParts)}>`; + case 'ArrayTypeAnnotation': + return `std::vector<${getCppArrayTypeForAnnotation( + typeElement.elementType, + structParts, + )}>`; + default: + throw new Error( + `Can't determine array type with typeElement: ${JSON.stringify( + typeElement, + null, + 2, + )}`, + ); + } +} + function getImports( properties: | $ReadOnlyArray> @@ -222,6 +258,7 @@ function convertDefaultTypeToString( module.exports = { convertDefaultTypeToString, + getCppArrayTypeForAnnotation, getCppTypeForAnnotation, getEnumMaskName, getImports, diff --git a/packages/react-native-codegen/src/generators/components/GenerateEventEmitterCpp.js b/packages/react-native-codegen/src/generators/components/GenerateEventEmitterCpp.js index ff478d78feae4b..7a43aea0a2b54e 100644 --- a/packages/react-native-codegen/src/generators/components/GenerateEventEmitterCpp.js +++ b/packages/react-native-codegen/src/generators/components/GenerateEventEmitterCpp.js @@ -102,9 +102,12 @@ function generateSetter( variableName: string, propertyName: string, propertyParts: $ReadOnlyArray, + usingEvent: boolean, valueMapper: string => string = value => value, ) { - const eventChain = `$event.${[...propertyParts, propertyName].join('.')}`; + const eventChain = usingEvent + ? `$event.${[...propertyParts, propertyName].join('.')}` + : [propertyParts, propertyName].join('.'); return `${variableName}.setProperty(runtime, "${propertyName}", ${valueMapper( eventChain, )});`; @@ -116,6 +119,7 @@ function generateObjectSetter( propertyParts: $ReadOnlyArray, typeAnnotation: ObjectTypeAnnotation, extraIncludes: Set, + usingEvent: boolean, ) { return ` { @@ -126,6 +130,7 @@ function generateObjectSetter( typeAnnotation.properties, propertyParts.concat([propertyName]), extraIncludes, + usingEvent, ), 2, )} @@ -134,11 +139,165 @@ function generateObjectSetter( `.trim(); } +function setValueAtIndex( + propertyName: string, + indexVariable: string, + loopLocalVariable: string, + mappingFunction: string => string = value => value, +) { + return `${propertyName}.setValueAtIndex(runtime, ${indexVariable}++, ${mappingFunction( + loopLocalVariable, + )});`; +} + +function generateArraySetter( + variableName: string, + propertyName: string, + propertyParts: $ReadOnlyArray, + elementType: EventTypeAnnotation, + extraIncludes: Set, + usingEvent: boolean, +): string { + const eventChain = usingEvent + ? `$event.${[...propertyParts, propertyName].join('.')}` + : [propertyParts, propertyName].join('.'); + const indexVar = `${propertyName}Index`; + const innerLoopVar = `${propertyName}Value`; + return ` + auto ${propertyName} = jsi::Array(runtime, ${eventChain}.size()); + size_t ${indexVar} = 0; + for (auto ${innerLoopVar} : ${eventChain}) { + ${handleArrayElementType( + elementType, + propertyName, + indexVar, + innerLoopVar, + propertyParts, + extraIncludes, + usingEvent, + )} + } + ${variableName}.setProperty(runtime, "${propertyName}", ${propertyName}); + `; +} + +function handleArrayElementType( + elementType: EventTypeAnnotation, + propertyName: string, + indexVariable: string, + loopLocalVariable: string, + propertyParts: $ReadOnlyArray, + extraIncludes: Set, + usingEvent: boolean, +): string { + switch (elementType.type) { + case 'BooleanTypeAnnotation': + return setValueAtIndex( + propertyName, + indexVariable, + loopLocalVariable, + val => `(bool)${val}`, + ); + case 'StringTypeAnnotation': + case 'Int32TypeAnnotation': + case 'DoubleTypeAnnotation': + case 'FloatTypeAnnotation': + return setValueAtIndex(propertyName, indexVariable, loopLocalVariable); + case 'MixedTypeAnnotation': + return setValueAtIndex( + propertyName, + indexVariable, + loopLocalVariable, + val => `jsi::valueFromDynamic(runtime, ${val})`, + ); + case 'StringEnumTypeAnnotation': + return setValueAtIndex( + propertyName, + indexVariable, + loopLocalVariable, + val => `toString(${val})`, + ); + case 'ObjectTypeAnnotation': + return convertObjectTypeArray( + propertyName, + indexVariable, + loopLocalVariable, + propertyParts, + elementType, + extraIncludes, + ); + case 'ArrayTypeAnnotation': + return convertArrayTypeArray( + propertyName, + indexVariable, + loopLocalVariable, + propertyParts, + elementType, + extraIncludes, + usingEvent, + ); + default: + throw new Error( + `Received invalid elementType for array ${elementType.type}`, + ); + } +} + +function convertObjectTypeArray( + propertyName: string, + indexVariable: string, + loopLocalVariable: string, + propertyParts: $ReadOnlyArray, + objectTypeAnnotation: ObjectTypeAnnotation, + extraIncludes: Set, +): string { + return `auto ${propertyName}Object = jsi::Object(runtime); + ${generateSetters( + `${propertyName}Object`, + objectTypeAnnotation.properties, + [].concat([loopLocalVariable]), + extraIncludes, + false, + )} + ${setValueAtIndex(propertyName, indexVariable, `${propertyName}Object`)}`; +} + +function convertArrayTypeArray( + propertyName: string, + indexVariable: string, + loopLocalVariable: string, + propertyParts: $ReadOnlyArray, + eventTypeAnnotation: EventTypeAnnotation, + extraIncludes: Set, + usingEvent: boolean, +): string { + if (eventTypeAnnotation.type !== 'ArrayTypeAnnotation') { + throw new Error( + `Inconsistent eventTypeAnnotation received. Expected type = 'ArrayTypeAnnotation'; received = ${eventTypeAnnotation.type}`, + ); + } + return `auto ${propertyName}Array = jsi::Array(runtime, ${loopLocalVariable}.size()); + size_t ${indexVariable}Internal = 0; + for (auto ${loopLocalVariable}Internal : ${loopLocalVariable}) { + ${handleArrayElementType( + eventTypeAnnotation.elementType, + `${propertyName}Array`, + `${indexVariable}Internal`, + `${loopLocalVariable}Internal`, + propertyParts, + extraIncludes, + usingEvent, + )} + } + ${setValueAtIndex(propertyName, indexVariable, `${propertyName}Array`)}`; +} + function generateSetters( parentPropertyName: string, properties: $ReadOnlyArray>, propertyParts: $ReadOnlyArray, extraIncludes: Set, + usingEvent: boolean = true, ): string { const propSetters = properties .map(eventProperty => { @@ -153,6 +312,7 @@ function generateSetters( parentPropertyName, eventProperty.name, propertyParts, + usingEvent, ); case 'MixedTypeAnnotation': extraIncludes.add('#include '); @@ -160,6 +320,7 @@ function generateSetters( parentPropertyName, eventProperty.name, propertyParts, + usingEvent, prop => `jsi::valueFromDynamic(runtime, ${prop})`, ); case 'StringEnumTypeAnnotation': @@ -167,6 +328,7 @@ function generateSetters( parentPropertyName, eventProperty.name, propertyParts, + usingEvent, prop => `toString(${prop})`, ); case 'ObjectTypeAnnotation': @@ -176,6 +338,16 @@ function generateSetters( propertyParts, typeAnnotation, extraIncludes, + usingEvent, + ); + case 'ArrayTypeAnnotation': + return generateArraySetter( + parentPropertyName, + eventProperty.name, + propertyParts, + typeAnnotation.elementType, + extraIncludes, + usingEvent, ); default: (typeAnnotation.type: empty); diff --git a/packages/react-native-codegen/src/generators/components/GenerateEventEmitterH.js b/packages/react-native-codegen/src/generators/components/GenerateEventEmitterH.js index 4d9ddfbcb18b7b..b5d55033f063b4 100644 --- a/packages/react-native-codegen/src/generators/components/GenerateEventEmitterH.js +++ b/packages/react-native-codegen/src/generators/components/GenerateEventEmitterH.js @@ -14,6 +14,7 @@ const nullthrows = require('nullthrows'); const { getImports, + getCppArrayTypeForAnnotation, getCppTypeForAnnotation, generateEventStructName, } = require('./CppHelpers'); @@ -133,6 +134,17 @@ function getNativeTypeFromAnnotation( case 'StringEnumTypeAnnotation': case 'ObjectTypeAnnotation': return generateEventStructName([...nameParts, eventProperty.name]); + case 'ArrayTypeAnnotation': + const eventTypeAnnotation = eventProperty.typeAnnotation; + if (eventTypeAnnotation.type !== 'ArrayTypeAnnotation') { + throw new Error( + "Inconsistent Codegen state: type was ArrayTypeAnnotation at the beginning of the body and now it isn't", + ); + } + return getCppArrayTypeForAnnotation(eventTypeAnnotation.elementType, [ + ...nameParts, + eventProperty.name, + ]); default: (type: empty); throw new Error(`Received invalid event property type ${type}`); @@ -165,6 +177,33 @@ function generateEnum( ); } +function handleGenerateStructForArray( + structs: StructsMap, + name: string, + componentName: string, + elementType: EventTypeAnnotation, + nameParts: $ReadOnlyArray, +): void { + if (elementType.type === 'ObjectTypeAnnotation') { + generateStruct( + structs, + componentName, + nameParts.concat([name]), + nullthrows(elementType.properties), + ); + } else if (elementType.type === 'StringEnumTypeAnnotation') { + generateEnum(structs, elementType.options, nameParts.concat([name])); + } else if (elementType.type === 'ArrayTypeAnnotation') { + handleGenerateStructForArray( + structs, + name, + componentName, + elementType.elementType, + nameParts, + ); + } +} + function generateStruct( structs: StructsMap, componentName: string, @@ -194,6 +233,15 @@ function generateStruct( case 'FloatTypeAnnotation': case 'MixedTypeAnnotation': return; + case 'ArrayTypeAnnotation': + handleGenerateStructForArray( + structs, + name, + componentName, + typeAnnotation.elementType, + nameParts, + ); + return; case 'ObjectTypeAnnotation': generateStruct( structs, @@ -271,7 +319,7 @@ module.exports = { .map(moduleName => { const module = schema.modules[moduleName]; if (module.type !== 'Component') { - return; + return null; } const {components} = module; diff --git a/packages/react-native-codegen/src/generators/components/GenerateThirdPartyFabricComponentsProviderH.js b/packages/react-native-codegen/src/generators/components/GenerateThirdPartyFabricComponentsProviderH.js index cddb1302d754a4..40b168372af7c1 100644 --- a/packages/react-native-codegen/src/generators/components/GenerateThirdPartyFabricComponentsProviderH.js +++ b/packages/react-native-codegen/src/generators/components/GenerateThirdPartyFabricComponentsProviderH.js @@ -36,8 +36,12 @@ extern "C" { Class RCTThirdPartyFabricComponentsProvider(const char *name); +#ifndef RCT_DYNAMIC_FRAMEWORKS + ${lookupFuncs} +#endif + #ifdef __cplusplus } #endif diff --git a/packages/react-native-codegen/src/generators/components/GenerateThirdPartyFabricComponentsProviderObjCpp.js b/packages/react-native-codegen/src/generators/components/GenerateThirdPartyFabricComponentsProviderObjCpp.js index fcd7b528192635..06e964845d3f52 100644 --- a/packages/react-native-codegen/src/generators/components/GenerateThirdPartyFabricComponentsProviderObjCpp.js +++ b/packages/react-native-codegen/src/generators/components/GenerateThirdPartyFabricComponentsProviderObjCpp.js @@ -34,7 +34,9 @@ const FileTemplate = ({lookupMap}: {lookupMap: string}) => ` Class RCTThirdPartyFabricComponentsProvider(const char *name) { static std::unordered_map sFabricComponentsClassMap = { + #ifndef RCT_DYNAMIC_FRAMEWORKS ${lookupMap} + #endif }; auto p = sFabricComponentsClassMap.find(name); diff --git a/packages/react-native-codegen/src/generators/components/__test_fixtures__/fixtures.js b/packages/react-native-codegen/src/generators/components/__test_fixtures__/fixtures.js index e5401bb4e7146c..65f7a46d25ba2c 100644 --- a/packages/react-native-codegen/src/generators/components/__test_fixtures__/fixtures.js +++ b/packages/react-native-codegen/src/generators/components/__test_fixtures__/fixtures.js @@ -1206,6 +1206,99 @@ const EVENT_PROPS: SchemaType = { }, }, }, + { + name: 'onArrayEventType', + optional: true, + bubblingType: 'bubble', + typeAnnotation: { + type: 'EventTypeAnnotation', + argument: { + type: 'ObjectTypeAnnotation', + properties: [ + { + name: 'bool_array_event_prop', + optional: false, + typeAnnotation: { + type: 'ArrayTypeAnnotation', + elementType: { + type: 'BooleanTypeAnnotation', + }, + }, + }, + { + name: 'string_enum_event_prop', + optional: false, + typeAnnotation: { + type: 'ArrayTypeAnnotation', + elementType: { + type: 'StringEnumTypeAnnotation', + options: ['YES', 'NO'], + }, + }, + }, + { + name: 'array_array_event_prop', + optional: false, + typeAnnotation: { + type: 'ArrayTypeAnnotation', + elementType: { + type: 'ArrayTypeAnnotation', + elementType: { + type: 'StringTypeAnnotation', + }, + }, + }, + }, + { + name: 'array_object_event_prop', + optional: false, + typeAnnotation: { + type: 'ArrayTypeAnnotation', + elementType: { + type: 'ObjectTypeAnnotation', + properties: [ + { + name: 'lat', + optional: false, + typeAnnotation: { + type: 'DoubleTypeAnnotation', + }, + }, + { + name: 'lon', + optional: false, + typeAnnotation: { + type: 'DoubleTypeAnnotation', + }, + }, + { + name: 'names', + optional: false, + typeAnnotation: { + type: 'ArrayTypeAnnotation', + elementType: { + type: 'StringTypeAnnotation', + }, + }, + }, + ], + }, + }, + }, + { + name: 'array_mixed_event_prop', + optional: false, + typeAnnotation: { + type: 'ArrayTypeAnnotation', + elementType: { + type: 'MixedTypeAnnotation', + }, + }, + }, + ], + }, + }, + }, { name: 'onEventDirect', optional: true, diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateEventEmitterCpp-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateEventEmitterCpp-test.js.snap index 68fc88ff7a1818..2ec6051506eab0 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateEventEmitterCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateEventEmitterCpp-test.js.snap @@ -264,6 +264,70 @@ $payload.setProperty(runtime, \\"scale\\", $event.scale); } +void EventsNativeComponentEventEmitter::onArrayEventType(OnArrayEventType $event) const { + dispatchEvent(\\"arrayEventType\\", [$event=std::move($event)](jsi::Runtime &runtime) { + auto $payload = jsi::Object(runtime); + + auto bool_array_event_prop = jsi::Array(runtime, $event.bool_array_event_prop.size()); + size_t bool_array_event_propIndex = 0; + for (auto bool_array_event_propValue : $event.bool_array_event_prop) { + bool_array_event_prop.setValueAtIndex(runtime, bool_array_event_propIndex++, (bool)bool_array_event_propValue); + } + $payload.setProperty(runtime, \\"bool_array_event_prop\\", bool_array_event_prop); + + + auto string_enum_event_prop = jsi::Array(runtime, $event.string_enum_event_prop.size()); + size_t string_enum_event_propIndex = 0; + for (auto string_enum_event_propValue : $event.string_enum_event_prop) { + string_enum_event_prop.setValueAtIndex(runtime, string_enum_event_propIndex++, toString(string_enum_event_propValue)); + } + $payload.setProperty(runtime, \\"string_enum_event_prop\\", string_enum_event_prop); + + + auto array_array_event_prop = jsi::Array(runtime, $event.array_array_event_prop.size()); + size_t array_array_event_propIndex = 0; + for (auto array_array_event_propValue : $event.array_array_event_prop) { + auto array_array_event_propArray = jsi::Array(runtime, array_array_event_propValue.size()); + size_t array_array_event_propIndexInternal = 0; + for (auto array_array_event_propValueInternal : array_array_event_propValue) { + array_array_event_propArray.setValueAtIndex(runtime, array_array_event_propIndexInternal++, array_array_event_propValueInternal); + } + array_array_event_prop.setValueAtIndex(runtime, array_array_event_propIndex++, array_array_event_propArray); + } + $payload.setProperty(runtime, \\"array_array_event_prop\\", array_array_event_prop); + + + auto array_object_event_prop = jsi::Array(runtime, $event.array_object_event_prop.size()); + size_t array_object_event_propIndex = 0; + for (auto array_object_event_propValue : $event.array_object_event_prop) { + auto array_object_event_propObject = jsi::Object(runtime); + array_object_event_propObject.setProperty(runtime, \\"lat\\", array_object_event_propValue.lat); +array_object_event_propObject.setProperty(runtime, \\"lon\\", array_object_event_propValue.lon); + + auto names = jsi::Array(runtime, array_object_event_propValue.names.size()); + size_t namesIndex = 0; + for (auto namesValue : array_object_event_propValue.names) { + names.setValueAtIndex(runtime, namesIndex++, namesValue); + } + array_object_event_propObject.setProperty(runtime, \\"names\\", names); + + array_object_event_prop.setValueAtIndex(runtime, array_object_event_propIndex++, array_object_event_propObject); + } + $payload.setProperty(runtime, \\"array_object_event_prop\\", array_object_event_prop); + + + auto array_mixed_event_prop = jsi::Array(runtime, $event.array_mixed_event_prop.size()); + size_t array_mixed_event_propIndex = 0; + for (auto array_mixed_event_propValue : $event.array_mixed_event_prop) { + array_mixed_event_prop.setValueAtIndex(runtime, array_mixed_event_propIndex++, jsi::valueFromDynamic(runtime, array_mixed_event_propValue)); + } + $payload.setProperty(runtime, \\"array_mixed_event_prop\\", array_mixed_event_prop); + + return $payload; + }); +} + + void EventsNativeComponentEventEmitter::onEventDirect(OnEventDirect $event) const { dispatchEvent(\\"eventDirect\\", [$event=std::move($event)](jsi::Runtime &runtime) { auto $payload = jsi::Object(runtime); diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateEventEmitterH-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateEventEmitterH-test.js.snap index 31ee002d234a0c..ca4237ab4d7474 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateEventEmitterH-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateEventEmitterH-test.js.snap @@ -320,6 +320,32 @@ class EventsNativeComponentEventEmitter : public ViewEventEmitter { Float scale; }; + enum class OnArrayEventTypeString_enum_event_prop { + YES, + NO + }; + + static char const *toString(const OnArrayEventTypeString_enum_event_prop value) { + switch (value) { + case OnArrayEventTypeString_enum_event_prop::YES: return \\"YES\\"; + case OnArrayEventTypeString_enum_event_prop::NO: return \\"NO\\"; + } + } + + struct OnArrayEventTypeArray_object_event_prop { + double lat; + double lon; + std::vector names; + }; + + struct OnArrayEventType { + std::vector bool_array_event_prop; + std::vector string_enum_event_prop; + std::vector> array_array_event_prop; + std::vector array_object_event_prop; + std::vector array_mixed_event_prop; + }; + struct OnEventDirect { bool value; }; @@ -345,6 +371,8 @@ class EventsNativeComponentEventEmitter : public ViewEventEmitter { }; void onChange(OnChange value) const; + void onArrayEventType(OnArrayEventType value) const; + void onEventDirect(OnEventDirect value) const; void onOrientationChange(OnOrientationChange value) const; diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateThirdPartyFabricComponentsProviderH-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateThirdPartyFabricComponentsProviderH-test.js.snap index 82f6247e94f4f0..f1b25981b31701 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateThirdPartyFabricComponentsProviderH-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateThirdPartyFabricComponentsProviderH-test.js.snap @@ -23,6 +23,8 @@ extern \\"C\\" { Class RCTThirdPartyFabricComponentsProvider(const char *name); +#ifndef RCT_DYNAMIC_FRAMEWORKS + Class NoPropsNoEventsComponentCls(void) __attribute__((used)); // NO_PROPS_NO_EVENTS Class InterfaceOnlyComponentCls(void) __attribute__((used)); // INTERFACE_ONLY Class BooleanPropNativeComponentCls(void) __attribute__((used)); // BOOLEAN_PROP @@ -55,6 +57,8 @@ Class ExcludedAndroidComponentCls(void) __attribute__( Class MultiFileIncludedNativeComponentCls(void) __attribute__((used)); // EXCLUDE_IOS_TWO_COMPONENTS_DIFFERENT_FILES +#endif + #ifdef __cplusplus } #endif diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateThirdPartyFabricComponentsProviderObjCpp-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateThirdPartyFabricComponentsProviderObjCpp-test.js.snap index c766a6b679a9b5..eb6d622917a2d0 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateThirdPartyFabricComponentsProviderObjCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateThirdPartyFabricComponentsProviderObjCpp-test.js.snap @@ -21,6 +21,7 @@ Map { Class RCTThirdPartyFabricComponentsProvider(const char *name) { static std::unordered_map sFabricComponentsClassMap = { + #ifndef RCT_DYNAMIC_FRAMEWORKS {\\"NoPropsNoEventsComponent\\", NoPropsNoEventsComponentCls}, // NO_PROPS_NO_EVENTS @@ -80,6 +81,7 @@ Class RCTThirdPartyFabricComponentsProvider(const char {\\"MultiFileIncludedNativeComponent\\", MultiFileIncludedNativeComponentCls}, // EXCLUDE_IOS_TWO_COMPONENTS_DIFFERENT_FILES + #endif }; auto p = sFabricComponentsClassMap.find(name); diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateViewConfigJs-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateViewConfigJs-test.js.snap index bc616a220e0b6a..e88cd1abe901cc 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateViewConfigJs-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateViewConfigJs-test.js.snap @@ -394,6 +394,13 @@ export const __INTERNAL_VIEW_CONFIG = { }, }, + topArrayEventType: { + phasedRegistrationNames: { + captured: 'onArrayEventTypeCapture', + bubbled: 'onArrayEventType', + }, + }, + topEnd: { phasedRegistrationNames: { captured: 'onEndCapture', @@ -421,6 +428,7 @@ export const __INTERNAL_VIEW_CONFIG = { ...ConditionallyIgnoredEventHandlers({ onChange: true, + onArrayEventType: true, onEventDirect: true, onOrientationChange: true, onEnd: true, diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js index 0cf09e268390ce..8cd7acf64c8230 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js @@ -338,7 +338,7 @@ enum ${enumName} { ${values} }; template <> struct Bridging<${enumName}> { - static ${enumName} fromJs(jsi::Runtime &rt, ${fromValue}, const std::shared_ptr &jsInvoker) { + static ${enumName} fromJs(jsi::Runtime &rt, ${fromValue}) { ${fromValueConversion} ${fromCases} } diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap index 4f3f7b1d98c058..040a3e9613672c 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap @@ -211,7 +211,7 @@ enum SampleTurboModuleCxxNumEnum { ONE, TWO }; template <> struct Bridging { - static SampleTurboModuleCxxNumEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue, const std::shared_ptr &jsInvoker) { + static SampleTurboModuleCxxNumEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue) { double value = (double)rawValue.asNumber(); if (value == 1) { return SampleTurboModuleCxxNumEnum::ONE; @@ -239,7 +239,7 @@ enum SampleTurboModuleCxxFloatEnum { POINT_ZERO, POINT_ONE, POINT_TWO }; template <> struct Bridging { - static SampleTurboModuleCxxFloatEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue, const std::shared_ptr &jsInvoker) { + static SampleTurboModuleCxxFloatEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue) { double value = (double)rawValue.asNumber(); if (value == 0.0f) { return SampleTurboModuleCxxFloatEnum::POINT_ZERO; @@ -271,7 +271,7 @@ enum SampleTurboModuleCxxStringEnum { HELLO, GoodBye }; template <> struct Bridging { - static SampleTurboModuleCxxStringEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue, const std::shared_ptr &jsInvoker) { + static SampleTurboModuleCxxStringEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue) { std::string value = rawValue.utf8(rt); if (value == \\"hello\\") { return SampleTurboModuleCxxStringEnum::HELLO; @@ -1209,7 +1209,7 @@ enum SampleTurboModuleNumEnum { ONE, TWO }; template <> struct Bridging { - static SampleTurboModuleNumEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue, const std::shared_ptr &jsInvoker) { + static SampleTurboModuleNumEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue) { double value = (double)rawValue.asNumber(); if (value == 1) { return SampleTurboModuleNumEnum::ONE; @@ -1237,7 +1237,7 @@ enum SampleTurboModuleFloatEnum { POINT_ZERO, POINT_ONE, POINT_TWO }; template <> struct Bridging { - static SampleTurboModuleFloatEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue, const std::shared_ptr &jsInvoker) { + static SampleTurboModuleFloatEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue) { double value = (double)rawValue.asNumber(); if (value == 0.0f) { return SampleTurboModuleFloatEnum::POINT_ZERO; @@ -1269,7 +1269,7 @@ enum SampleTurboModuleStringEnum { HELLO, GoodBye }; template <> struct Bridging { - static SampleTurboModuleStringEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue, const std::shared_ptr &jsInvoker) { + static SampleTurboModuleStringEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue) { std::string value = rawValue.utf8(rt); if (value == \\"hello\\") { return SampleTurboModuleStringEnum::HELLO; diff --git a/packages/react-native-codegen/src/parsers/__tests__/error-utils-test.js b/packages/react-native-codegen/src/parsers/__tests__/error-utils-test.js index 5e3b7fa2ecc6bf..60ee91bf1a484d 100644 --- a/packages/react-native-codegen/src/parsers/__tests__/error-utils-test.js +++ b/packages/react-native-codegen/src/parsers/__tests__/error-utils-test.js @@ -34,6 +34,8 @@ const { throwIfPartialWithMoreParameter, throwIfMoreThanOneCodegenNativecommands, throwIfEventHasNoName, + throwIfBubblingTypeIsNull, + throwIfArgumentPropsAreNull, } = require('../error-utils'); const { UnsupportedModulePropertyParserError, @@ -950,3 +952,45 @@ describe('throwIfEventHasNoName', () => { }).not.toThrow(); }); }); + +describe('throwIfBubblingTypeIsNull', () => { + it('throw an error if unable to determine event bubbling type', () => { + const bubblingType = null; + const eventName = 'Event'; + + expect(() => { + throwIfBubblingTypeIsNull(bubblingType, eventName); + }).toThrowError( + `Unable to determine event bubbling type for "${eventName}"`, + ); + }); + + it('does not throw an error if able to determine event bubbling type', () => { + const bubblingType = 'direct'; + const eventName = 'Event'; + + expect(() => { + throwIfBubblingTypeIsNull(bubblingType, eventName); + }).not.toThrow(); + }); +}); + +describe('throwIfArgumentPropsAreNull', () => { + it('throws an error if unable to determine event arguments', () => { + const argumentProps = null; + const eventName = 'Event'; + + expect(() => { + throwIfArgumentPropsAreNull(argumentProps, eventName); + }).toThrowError(`Unable to determine event arguments for "${eventName}"`); + }); + + it('does not throw an error if able to determine event arguments', () => { + const argumentProps = [{}]; + const eventName = 'Event'; + + expect(() => { + throwIfArgumentPropsAreNull(argumentProps, eventName); + }).not.toThrow(); + }); +}); diff --git a/packages/react-native-codegen/src/parsers/__tests__/parsers-commons-test.js b/packages/react-native-codegen/src/parsers/__tests__/parsers-commons-test.js index 4704e445f75651..047bb00d8a545f 100644 --- a/packages/react-native-codegen/src/parsers/__tests__/parsers-commons-test.js +++ b/packages/react-native-codegen/src/parsers/__tests__/parsers-commons-test.js @@ -58,7 +58,6 @@ const flowParser = new FlowParser(); const {flowTranslateTypeAnnotation} = require('../flow/modules/index'); const typeScriptTranslateTypeAnnotation = require('../typescript/modules/index'); -const {resolveTypeAnnotation} = require('../flow/utils'); beforeEach(() => { jest.clearAllMocks(); @@ -409,7 +408,7 @@ describe('buildSchemaFromConfigType', () => { (_ast, _parser) => componentSchemaMock, ); const buildModuleSchemaMock = jest.fn( - (_0, _1, _2, _3, _4, _5) => moduleSchemaMock, + (_0, _1, _2, _3, _4) => moduleSchemaMock, ); const buildSchemaFromConfigTypeHelper = ( @@ -424,7 +423,6 @@ describe('buildSchemaFromConfigType', () => { buildComponentSchemaMock, buildModuleSchemaMock, parser, - resolveTypeAnnotation, flowTranslateTypeAnnotation, ); @@ -507,7 +505,6 @@ describe('buildSchemaFromConfigType', () => { astMock, expect.any(Function), parser, - resolveTypeAnnotation, flowTranslateTypeAnnotation, ); @@ -679,7 +676,6 @@ describe('buildSchema', () => { buildModuleSchema, Visitor, parser, - resolveTypeAnnotation, flowTranslateTypeAnnotation, ); @@ -713,7 +709,6 @@ describe('buildSchema', () => { buildModuleSchema, Visitor, flowParser, - resolveTypeAnnotation, flowTranslateTypeAnnotation, ); @@ -768,7 +763,6 @@ describe('buildSchema', () => { buildModuleSchema, Visitor, flowParser, - resolveTypeAnnotation, flowTranslateTypeAnnotation, ); @@ -1064,7 +1058,6 @@ describe('buildModuleSchema', () => { ast, tryParse, flowParser, - resolveTypeAnnotation, flowTranslateTypeAnnotation, ), ).toThrow(expected); @@ -1079,7 +1072,6 @@ describe('buildModuleSchema', () => { ast, tryParse, flowParser, - resolveTypeAnnotation, flowTranslateTypeAnnotation, ), ).not.toThrow(); @@ -1116,7 +1108,6 @@ describe('buildModuleSchema', () => { ast, tryParse, flowParser, - resolveTypeAnnotation, flowTranslateTypeAnnotation, ), ).toThrow(expected); @@ -1131,7 +1122,6 @@ describe('buildModuleSchema', () => { ast, tryParse, flowParser, - resolveTypeAnnotation, flowTranslateTypeAnnotation, ), ).not.toThrow(); @@ -1171,7 +1161,6 @@ describe('buildModuleSchema', () => { ast, tryParse, flowParser, - resolveTypeAnnotation, flowTranslateTypeAnnotation, ), ).toThrow(expected); @@ -1186,7 +1175,6 @@ describe('buildModuleSchema', () => { ast, tryParse, flowParser, - resolveTypeAnnotation, flowTranslateTypeAnnotation, ), ).not.toThrow(); @@ -1229,7 +1217,6 @@ describe('buildModuleSchema', () => { ast, tryParse, flowParser, - resolveTypeAnnotation, flowTranslateTypeAnnotation, ); diff --git a/packages/react-native-codegen/src/parsers/__tests__/parsers-test.js b/packages/react-native-codegen/src/parsers/__tests__/parsers-test.js index 9418c0539e8831..92366bc1812ca5 100644 --- a/packages/react-native-codegen/src/parsers/__tests__/parsers-test.js +++ b/packages/react-native-codegen/src/parsers/__tests__/parsers-test.js @@ -270,6 +270,59 @@ describe('FlowParser', () => { ).toEqual(expected); }); }); + + describe('isOptionalProperty', () => { + it('when property is optional', () => { + const property = { + value: { + type: 'TypeAnnotation', + }, + optional: true, + }; + + expect(parser.isOptionalProperty(property)).toEqual(true); + }); + + it('when property is not optional', () => { + const property = { + value: { + type: 'TypeAnnotation', + }, + optional: false, + }; + + expect(parser.isOptionalProperty(property)).toEqual(false); + }); + + it('when property value type is NullableTypeAnnotation', () => { + const property = { + value: { + type: 'NullableTypeAnnotation', + }, + optional: false, + }; + + expect(parser.isOptionalProperty(property)).toEqual(true); + }); + }); + + describe('typeAlias', () => { + it('returns typeAlias Property', () => { + expect(parser.typeAlias).toEqual('TypeAlias'); + }); + }); + + describe('enumDeclaration', () => { + it('returns enumDeclaration Property', () => { + expect(parser.enumDeclaration).toEqual('EnumDeclaration'); + }); + }); + + describe('interfaceDelcaration', () => { + it('returns interfaceDelcaration Property', () => { + expect(parser.interfaceDelcaration).toEqual('InterfaceDeclaration'); + }); + }); }); describe('TypeScriptParser', () => { @@ -531,4 +584,38 @@ describe('TypeScriptParser', () => { ).toEqual(expected); }); }); + + describe('isOptionalProperty', () => { + it('when property is optional', () => { + const property = { + optional: true, + }; + expect(parser.isOptionalProperty(property)).toEqual(true); + }); + + it('when property is undefined or not optional', () => { + const property = { + optional: false, + }; + expect(parser.isOptionalProperty(property)).toEqual(false); + }); + }); + + describe('typeAlias', () => { + it('returns typeAlias Property', () => { + expect(parser.typeAlias).toEqual('TSTypeAliasDeclaration'); + }); + }); + + describe('enumDeclaration', () => { + it('returns enumDeclaration Property', () => { + expect(parser.enumDeclaration).toEqual('TSEnumDeclaration'); + }); + }); + + describe('interfaceDelcaration', () => { + it('returns interfaceDelcaration Property', () => { + expect(parser.interfaceDelcaration).toEqual('TSInterfaceDeclaration'); + }); + }); }); diff --git a/packages/react-native-codegen/src/parsers/error-utils.js b/packages/react-native-codegen/src/parsers/error-utils.js index 57774b9938ec9c..55a46fe3726c13 100644 --- a/packages/react-native-codegen/src/parsers/error-utils.js +++ b/packages/react-native-codegen/src/parsers/error-utils.js @@ -319,6 +319,30 @@ function throwIfEventHasNoName(typeAnnotation: $FlowFixMe, parser: Parser) { } } +function throwIfBubblingTypeIsNull( + bubblingType: ?('direct' | 'bubble'), + eventName: string, +): 'direct' | 'bubble' { + if (!bubblingType) { + throw new Error( + `Unable to determine event bubbling type for "${eventName}"`, + ); + } + + return bubblingType; +} + +function throwIfArgumentPropsAreNull( + argumentProps: ?$ReadOnlyArray<$FlowFixMe>, + eventName: string, +): $ReadOnlyArray<$FlowFixMe> { + if (!argumentProps) { + throw new Error(`Unable to determine event arguments for "${eventName}"`); + } + + return argumentProps; +} + module.exports = { throwIfModuleInterfaceIsMisnamed, throwIfUnsupportedFunctionReturnTypeAnnotationParserError, @@ -340,4 +364,6 @@ module.exports = { throwIfConfigNotfound, throwIfMoreThanOneConfig, throwIfEventHasNoName, + throwIfBubblingTypeIsNull, + throwIfArgumentPropsAreNull, }; diff --git a/packages/react-native-codegen/src/parsers/flow/components/__test_fixtures__/fixtures.js b/packages/react-native-codegen/src/parsers/flow/components/__test_fixtures__/fixtures.js index 3a724b3411172b..64cefa676f6bf9 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/__test_fixtures__/fixtures.js +++ b/packages/react-native-codegen/src/parsers/flow/components/__test_fixtures__/fixtures.js @@ -84,6 +84,57 @@ const EVENT_DEFINITION = ` object_readonly_optional_both?: ?$ReadOnly<{ int32_optional_both?: ?Int32, }>, + + boolean_array_required: $ReadOnlyArray, + boolean_array_optional_key?: boolean[], + boolean_array_optional_value: ?$ReadOnlyArray, + boolean_array_optional_both?: ?boolean[], + + string_array_required: $ReadOnlyArray, + string_array_optional_key?: string[], + string_array_optional_value: ?$ReadOnlyArray, + string_array_optional_both?: ?string[], + + double_array_required: $ReadOnlyArray, + double_array_optional_key?: Double[], + double_array_optional_value: ?$ReadOnlyArray, + double_array_optional_both?: ?Double[], + + float_array_required: $ReadOnlyArray, + float_array_optional_key?: Float[], + float_array_optional_value: ?$ReadOnlyArray, + float_array_optional_both?: ?Float[], + + int32_array_required: $ReadOnlyArray, + int32_array_optional_key?: Int32[], + int32_array_optional_value: ?$ReadOnlyArray, + int32_array_optional_both?: ?Int32[], + + enum_array_required: $ReadOnlyArray<('small' | 'large')>, + enum_array_optional_key?: ('small' | 'large')[], + enum_array_optional_value: ?$ReadOnlyArray<('small' | 'large')>, + enum_array_optional_both?: ?('small' | 'large')[], + + object_array_required: $ReadOnlyArray<{ + boolean_required: boolean, + }>, + + object_array_optional_key?: { + string_optional_key?: string, + }[], + + object_array_optional_value: ?$ReadOnlyArray<{ + float_optional_value: ?Float, + }>, + + object_array_optional_both?: ?{ + int32_optional_both?: ?Int32, + }[], + + int32_array_array_required: $ReadOnlyArray<$ReadOnlyArray>, + int32_array_array_optional_key?: Int32[][], + int32_array_array_optional_value: ?$ReadOnlyArray<$ReadOnlyArray>, + int32_array_array_optional_both?: ?Int32[][], `; const ONE_OF_EACH_PROP_EVENT_DEFAULT_AND_OPTIONS = ` diff --git a/packages/react-native-codegen/src/parsers/flow/components/__tests__/__snapshots__/component-parser-test.js.snap b/packages/react-native-codegen/src/parsers/flow/components/__tests__/__snapshots__/component-parser-test.js.snap index f3ec2606cfc16c..dbcae681e81b9a 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/__tests__/__snapshots__/component-parser-test.js.snap +++ b/packages/react-native-codegen/src/parsers/flow/components/__tests__/__snapshots__/component-parser-test.js.snap @@ -1843,384 +1843,389 @@ exports[`RN Codegen Flow Parser can generate fixture COMMANDS_EVENTS_TYPES_EXPOR } ] } - } - ] - } - } - }, - { - 'name': 'onBubblingEventDefinedInlineWithPaperName', - 'optional': false, - 'bubblingType': 'bubble', - 'paperTopLevelNameDeprecated': 'paperBubblingEventDefinedInlineWithPaperName', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ + }, { - 'name': 'boolean_required', + 'name': 'boolean_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_key', + 'name': 'boolean_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_value', + 'name': 'boolean_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_both', + 'name': 'boolean_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'string_required', + 'name': 'string_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_key', + 'name': 'string_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_value', + 'name': 'string_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_both', + 'name': 'string_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'double_required', + 'name': 'double_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_key', + 'name': 'double_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_value', + 'name': 'double_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_both', + 'name': 'double_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'float_required', + 'name': 'float_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_key', + 'name': 'float_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_value', + 'name': 'float_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_both', + 'name': 'float_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'int32_required', + 'name': 'int32_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_key', + 'name': 'int32_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_value', + 'name': 'int32_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_both', + 'name': 'int32_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'enum_required', + 'name': 'enum_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_key', + 'name': 'enum_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_value', + 'name': 'enum_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_both', + 'name': 'enum_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'object_required', + 'name': 'object_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_key', + 'name': 'object_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_value', + 'name': 'object_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_both', + 'name': 'object_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_required_nested_2_layers', + 'name': 'int32_array_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'object_optional_nested_1_layer', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - }, - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } - }, - { - 'name': 'double_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' - } - }, - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } - }, - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - } - ] - } - } - ] - } - }, - { - 'name': 'object_readonly_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_key', + 'name': 'int32_array_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_value', + 'name': 'int32_array_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_both', + 'name': 'int32_array_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } } ] @@ -2228,9 +2233,10 @@ exports[`RN Codegen Flow Parser can generate fixture COMMANDS_EVENTS_TYPES_EXPOR } }, { - 'name': 'onDirectEventDefinedInline', + 'name': 'onBubblingEventDefinedInlineWithPaperName', 'optional': false, - 'bubblingType': 'direct', + 'bubblingType': 'bubble', + 'paperTopLevelNameDeprecated': 'paperBubblingEventDefinedInlineWithPaperName', 'typeAnnotation': { 'type': 'EventTypeAnnotation', 'argument': { @@ -2600,641 +2606,399 @@ exports[`RN Codegen Flow Parser can generate fixture COMMANDS_EVENTS_TYPES_EXPOR } ] } - } - ] - } - } - }, - { - 'name': 'onDirectEventDefinedInlineWithPaperName', - 'optional': false, - 'bubblingType': 'direct', - 'paperTopLevelNameDeprecated': 'paperDirectEventDefinedInlineWithPaperName', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ + }, { - 'name': 'boolean_required', + 'name': 'boolean_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_key', + 'name': 'boolean_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_value', + 'name': 'boolean_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_both', + 'name': 'boolean_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'string_required', + 'name': 'string_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_key', + 'name': 'string_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_value', + 'name': 'string_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_both', + 'name': 'string_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'double_required', + 'name': 'double_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_key', + 'name': 'double_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_value', + 'name': 'double_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_both', + 'name': 'double_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'float_required', + 'name': 'float_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_key', + 'name': 'float_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_value', + 'name': 'float_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_both', + 'name': 'float_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'int32_required', + 'name': 'int32_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_key', + 'name': 'int32_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_value', + 'name': 'int32_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_both', + 'name': 'int32_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'enum_required', + 'name': 'enum_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_key', + 'name': 'enum_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_value', + 'name': 'enum_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_both', + 'name': 'enum_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'object_required', + 'name': 'object_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } - } - ] - } - }, - { - 'name': 'object_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_value', + 'name': 'object_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_both', + 'name': 'object_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_required_nested_2_layers', - 'optional': false, + 'name': 'object_array_optional_both', + 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'object_optional_nested_1_layer', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - }, - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } - }, - { - 'name': 'double_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' - } - }, - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } - }, - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - } - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_readonly_required', + 'name': 'int32_array_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_key', + 'name': 'int32_array_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_value', + 'name': 'int32_array_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_both', + 'name': 'int32_array_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } } ] } } - } - ], - 'props': [], - 'commands': [ - { - 'name': 'scrollTo', - 'optional': false, - 'typeAnnotation': { - 'type': 'FunctionTypeAnnotation', - 'params': [ - { - 'name': 'y', - 'optional': false, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - }, - { - 'name': 'animated', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } - } - ], - 'returnTypeAnnotation': { - 'type': 'VoidTypeAnnotation' - } - } - } - ] - } - } - } - } -}" -`; - -exports[`RN Codegen Flow Parser can generate fixture COMMANDS_WITH_EXTERNAL_TYPES 1`] = ` -"{ - 'modules': { - 'Module': { - 'type': 'Component', - 'components': { - 'Module': { - 'extendsProps': [ - { - 'type': 'ReactNativeBuiltInType', - 'knownTypeName': 'ReactNativeCoreViewProps' - } - ], - 'events': [], - 'props': [], - 'commands': [ + }, { - 'name': 'scrollTo', + 'name': 'onDirectEventDefinedInline', 'optional': false, - 'typeAnnotation': { - 'type': 'FunctionTypeAnnotation', - 'params': [ - { - 'name': 'y', - 'optional': false, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - }, - { - 'name': 'animated', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } - } - ], - 'returnTypeAnnotation': { - 'type': 'VoidTypeAnnotation' - } - } - } - ] - } - } - } - } -}" -`; - -exports[`RN Codegen Flow Parser can generate fixture EVENTS_DEFINED_AS_NULL_INLINE 1`] = ` -"{ - 'modules': { - 'Module': { - 'type': 'Component', - 'components': { - 'Module': { - 'extendsProps': [ - { - 'type': 'ReactNativeBuiltInType', - 'knownTypeName': 'ReactNativeCoreViewProps' - } - ], - 'events': [ - { - 'name': 'onDirectEventDefinedInlineNull', - 'optional': false, - 'bubblingType': 'direct', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - }, - { - 'name': 'onDirectEventDefinedInlineNullOptionalKey', - 'optional': true, - 'bubblingType': 'direct', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - }, - { - 'name': 'onDirectEventDefinedInlineNullOptionalValue', - 'optional': true, - 'bubblingType': 'direct', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - }, - { - 'name': 'onDirectEventDefinedInlineNullOptionalBoth', - 'optional': true, - 'bubblingType': 'direct', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - }, - { - 'name': 'onDirectEventDefinedInlineNullWithPaperName', - 'optional': true, - 'bubblingType': 'direct', - 'paperTopLevelNameDeprecated': 'paperDirectEventDefinedInlineNullWithPaperName', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - }, - { - 'name': 'onBubblingEventDefinedInlineNull', - 'optional': false, - 'bubblingType': 'bubble', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - }, - { - 'name': 'onBubblingEventDefinedInlineNullOptionalKey', - 'optional': true, - 'bubblingType': 'bubble', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - }, - { - 'name': 'onBubblingEventDefinedInlineNullOptionalValue', - 'optional': true, - 'bubblingType': 'bubble', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - }, - { - 'name': 'onBubblingEventDefinedInlineNullOptionalBoth', - 'optional': true, - 'bubblingType': 'bubble', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - }, - { - 'name': 'onBubblingEventDefinedInlineNullWithPaperName', - 'optional': true, - 'bubblingType': 'bubble', - 'paperTopLevelNameDeprecated': 'paperBubblingEventDefinedInlineNullWithPaperName', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - } - ], - 'props': [], - 'commands': [] - } - } - } - } -}" -`; - -exports[`RN Codegen Flow Parser can generate fixture EVENTS_DEFINED_INLINE_WITH_ALL_TYPES 1`] = ` -"{ - 'modules': { - 'Module': { - 'type': 'Component', - 'components': { - 'Module': { - 'extendsProps': [ - { - 'type': 'ReactNativeBuiltInType', - 'knownTypeName': 'ReactNativeCoreViewProps' - } - ], - 'events': [ - { - 'name': 'onDirectEventDefinedInline', - 'optional': false, - 'bubblingType': 'direct', + 'bubblingType': 'direct', 'typeAnnotation': { 'type': 'EventTypeAnnotation', 'argument': { @@ -3604,383 +3368,389 @@ exports[`RN Codegen Flow Parser can generate fixture EVENTS_DEFINED_INLINE_WITH_ } ] } - } - ] - } - } - }, - { - 'name': 'onDirectEventDefinedInlineOptionalKey', - 'optional': true, - 'bubblingType': 'direct', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ + }, { - 'name': 'boolean_required', + 'name': 'boolean_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_key', + 'name': 'boolean_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_value', + 'name': 'boolean_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_both', + 'name': 'boolean_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'string_required', + 'name': 'string_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_key', + 'name': 'string_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_value', + 'name': 'string_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_both', + 'name': 'string_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'double_required', + 'name': 'double_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_key', + 'name': 'double_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_value', + 'name': 'double_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_both', + 'name': 'double_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'float_required', + 'name': 'float_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_key', + 'name': 'float_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_value', + 'name': 'float_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_both', + 'name': 'float_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'int32_required', + 'name': 'int32_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_key', + 'name': 'int32_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_value', + 'name': 'int32_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_both', + 'name': 'int32_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'enum_required', + 'name': 'enum_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_key', + 'name': 'enum_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_value', + 'name': 'enum_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_both', + 'name': 'enum_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'object_required', + 'name': 'object_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_key', + 'name': 'object_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_value', + 'name': 'object_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_both', + 'name': 'object_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - } - ] - } - }, - { - 'name': 'object_required_nested_2_layers', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'object_optional_nested_1_layer', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - }, - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } - }, - { - 'name': 'double_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' - } - }, - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } - }, - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - } - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_readonly_required', + 'name': 'int32_array_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_key', + 'name': 'int32_array_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_value', + 'name': 'int32_array_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_both', + 'name': 'int32_array_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } } ] @@ -3988,9 +3758,10 @@ exports[`RN Codegen Flow Parser can generate fixture EVENTS_DEFINED_INLINE_WITH_ } }, { - 'name': 'onDirectEventDefinedInlineOptionalValue', - 'optional': true, + 'name': 'onDirectEventDefinedInlineWithPaperName', + 'optional': false, 'bubblingType': 'direct', + 'paperTopLevelNameDeprecated': 'paperDirectEventDefinedInlineWithPaperName', 'typeAnnotation': { 'type': 'EventTypeAnnotation', 'argument': { @@ -4360,447 +4131,699 @@ exports[`RN Codegen Flow Parser can generate fixture EVENTS_DEFINED_INLINE_WITH_ } ] } - } - ] - } - } - }, - { - 'name': 'onDirectEventDefinedInlineOptionalBoth', - 'optional': true, - 'bubblingType': 'direct', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ + }, { - 'name': 'boolean_required', + 'name': 'boolean_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_key', + 'name': 'boolean_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_value', + 'name': 'boolean_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_both', + 'name': 'boolean_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'string_required', + 'name': 'string_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_key', + 'name': 'string_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_value', + 'name': 'string_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_both', + 'name': 'string_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'double_required', + 'name': 'double_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_key', + 'name': 'double_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_value', + 'name': 'double_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_both', + 'name': 'double_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'float_required', + 'name': 'float_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_key', + 'name': 'float_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_value', + 'name': 'float_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_both', + 'name': 'float_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'int32_required', + 'name': 'int32_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_key', + 'name': 'int32_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_value', + 'name': 'int32_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_both', + 'name': 'int32_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'enum_required', + 'name': 'enum_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_key', + 'name': 'enum_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_value', + 'name': 'enum_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_both', + 'name': 'enum_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'object_required', + 'name': 'object_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_key', + 'name': 'object_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_value', + 'name': 'object_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_both', + 'name': 'object_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_required_nested_2_layers', + 'name': 'int32_array_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'object_optional_nested_1_layer', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - }, - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } - }, - { - 'name': 'double_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' - } - }, - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } - }, - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - } - ] - } - } - ] - } - }, - { - 'name': 'object_readonly_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_key', + 'name': 'int32_array_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_value', + 'name': 'int32_array_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_both', + 'name': 'int32_array_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } } ] } } + } + ], + 'props': [], + 'commands': [ + { + 'name': 'scrollTo', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'params': [ + { + 'name': 'y', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'animated', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ], + 'returnTypeAnnotation': { + 'type': 'VoidTypeAnnotation' + } + } + } + ] + } + } + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture COMMANDS_WITH_EXTERNAL_TYPES 1`] = ` +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'extendsProps': [ + { + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } + ], + 'events': [], + 'props': [], + 'commands': [ + { + 'name': 'scrollTo', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'params': [ + { + 'name': 'y', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'animated', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ], + 'returnTypeAnnotation': { + 'type': 'VoidTypeAnnotation' + } + } + } + ] + } + } + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture EVENTS_DEFINED_AS_NULL_INLINE 1`] = ` +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'extendsProps': [ + { + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } + ], + 'events': [ + { + 'name': 'onDirectEventDefinedInlineNull', + 'optional': false, + 'bubblingType': 'direct', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } }, { - 'name': 'onDirectEventDefinedInlineWithPaperName', + 'name': 'onDirectEventDefinedInlineNullOptionalKey', 'optional': true, 'bubblingType': 'direct', - 'paperTopLevelNameDeprecated': 'paperDirectEventDefinedInlineWithPaperName', 'typeAnnotation': { 'type': 'EventTypeAnnotation', 'argument': { 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } - }, - { - 'name': 'boolean_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } - }, - { - 'name': 'boolean_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } - }, - { - 'name': 'boolean_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } - }, - { - 'name': 'string_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } - }, - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } - }, - { - 'name': 'string_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } + 'properties': [] + } + } + }, + { + 'name': 'onDirectEventDefinedInlineNullOptionalValue', + 'optional': true, + 'bubblingType': 'direct', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onDirectEventDefinedInlineNullOptionalBoth', + 'optional': true, + 'bubblingType': 'direct', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onDirectEventDefinedInlineNullWithPaperName', + 'optional': true, + 'bubblingType': 'direct', + 'paperTopLevelNameDeprecated': 'paperDirectEventDefinedInlineNullWithPaperName', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineNull', + 'optional': false, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineNullOptionalKey', + 'optional': true, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineNullOptionalValue', + 'optional': true, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineNullOptionalBoth', + 'optional': true, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineNullWithPaperName', + 'optional': true, + 'bubblingType': 'bubble', + 'paperTopLevelNameDeprecated': 'paperBubblingEventDefinedInlineNullWithPaperName', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + } + ], + 'props': [], + 'commands': [] + } + } + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture EVENTS_DEFINED_INLINE_WITH_ALL_TYPES 1`] = ` +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'extendsProps': [ + { + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } + ], + 'events': [ + { + 'name': 'onDirectEventDefinedInline', + 'optional': false, + 'bubblingType': 'direct', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } }, { 'name': 'string_optional_both', @@ -5117,383 +5140,389 @@ exports[`RN Codegen Flow Parser can generate fixture EVENTS_DEFINED_INLINE_WITH_ } ] } - } - ] - } - } - }, - { - 'name': 'onBubblingEventDefinedInline', - 'optional': false, - 'bubblingType': 'bubble', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ + }, { - 'name': 'boolean_required', + 'name': 'boolean_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_key', + 'name': 'boolean_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_value', + 'name': 'boolean_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_both', + 'name': 'boolean_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'string_required', + 'name': 'string_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_key', + 'name': 'string_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_value', + 'name': 'string_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_both', + 'name': 'string_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'double_required', + 'name': 'double_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_key', + 'name': 'double_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_value', + 'name': 'double_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_both', + 'name': 'double_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } }, { - 'name': 'float_required', + 'name': 'float_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_key', + 'name': 'float_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_value', + 'name': 'float_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_both', + 'name': 'float_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'int32_required', + 'name': 'int32_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_key', + 'name': 'int32_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_value', + 'name': 'int32_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_both', + 'name': 'int32_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'enum_required', + 'name': 'enum_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_key', + 'name': 'enum_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_value', + 'name': 'enum_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_both', + 'name': 'enum_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'object_required', + 'name': 'object_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_key', + 'name': 'object_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_value', + 'name': 'object_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_both', + 'name': 'object_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_required_nested_2_layers', + 'name': 'int32_array_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'object_optional_nested_1_layer', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - }, - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } - }, - { - 'name': 'double_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' - } - }, - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } - }, - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - } - ] - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_required', - 'optional': false, + 'name': 'int32_array_array_optional_key', + 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_key', + 'name': 'int32_array_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_value', + 'name': 'int32_array_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] - } - }, - { - 'name': 'object_readonly_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - } - ] + } } } ] @@ -5501,9 +5530,9 @@ exports[`RN Codegen Flow Parser can generate fixture EVENTS_DEFINED_INLINE_WITH_ } }, { - 'name': 'onBubblingEventDefinedInlineOptionalKey', + 'name': 'onDirectEventDefinedInlineOptionalKey', 'optional': true, - 'bubblingType': 'bubble', + 'bubblingType': 'direct', 'typeAnnotation': { 'type': 'EventTypeAnnotation', 'argument': { @@ -5873,383 +5902,389 @@ exports[`RN Codegen Flow Parser can generate fixture EVENTS_DEFINED_INLINE_WITH_ } ] } - } - ] - } - } - }, - { - 'name': 'onBubblingEventDefinedInlineOptionalValue', - 'optional': true, - 'bubblingType': 'bubble', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ + }, { - 'name': 'boolean_required', + 'name': 'boolean_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_key', + 'name': 'boolean_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_value', + 'name': 'boolean_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_both', + 'name': 'boolean_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'string_required', + 'name': 'string_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_key', + 'name': 'string_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_value', + 'name': 'string_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_both', + 'name': 'string_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'double_required', + 'name': 'double_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_key', + 'name': 'double_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_value', + 'name': 'double_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_both', + 'name': 'double_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'float_required', + 'name': 'float_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_key', + 'name': 'float_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_value', + 'name': 'float_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_both', + 'name': 'float_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'int32_required', + 'name': 'int32_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_key', + 'name': 'int32_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_value', + 'name': 'int32_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_both', + 'name': 'int32_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'enum_required', + 'name': 'enum_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_key', + 'name': 'enum_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_value', + 'name': 'enum_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_both', + 'name': 'enum_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'object_required', + 'name': 'object_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_key', + 'name': 'object_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_value', + 'name': 'object_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_both', + 'name': 'object_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_required_nested_2_layers', + 'name': 'int32_array_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'object_optional_nested_1_layer', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - }, - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } - }, - { - 'name': 'double_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' - } - }, - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } - }, - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - } - ] - } - } - ] - } - }, - { - 'name': 'object_readonly_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_key', + 'name': 'int32_array_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_value', + 'name': 'int32_array_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_both', + 'name': 'int32_array_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } } ] @@ -6257,9 +6292,9 @@ exports[`RN Codegen Flow Parser can generate fixture EVENTS_DEFINED_INLINE_WITH_ } }, { - 'name': 'onBubblingEventDefinedInlineOptionalBoth', + 'name': 'onDirectEventDefinedInlineOptionalValue', 'optional': true, - 'bubblingType': 'bubble', + 'bubblingType': 'direct', 'typeAnnotation': { 'type': 'EventTypeAnnotation', 'argument': { @@ -6629,720 +6664,6231 @@ exports[`RN Codegen Flow Parser can generate fixture EVENTS_DEFINED_INLINE_WITH_ } ] } - } - ] - } - } - }, - { - 'name': 'onBubblingEventDefinedInlineWithPaperName', - 'optional': true, - 'bubblingType': 'bubble', - 'paperTopLevelNameDeprecated': 'paperBubblingEventDefinedInlineWithPaperName', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ + }, { - 'name': 'boolean_required', + 'name': 'boolean_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_key', + 'name': 'boolean_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_value', + 'name': 'boolean_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_both', + 'name': 'boolean_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'string_required', + 'name': 'string_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_key', + 'name': 'string_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_value', + 'name': 'string_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_both', + 'name': 'string_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'double_required', + 'name': 'double_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_key', + 'name': 'double_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_value', + 'name': 'double_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_both', + 'name': 'double_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'float_required', + 'name': 'float_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_key', + 'name': 'float_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_value', + 'name': 'float_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_both', + 'name': 'float_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'int32_required', + 'name': 'int32_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_key', + 'name': 'int32_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_value', + 'name': 'int32_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_both', + 'name': 'int32_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'enum_required', + 'name': 'enum_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_key', + 'name': 'enum_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_value', + 'name': 'enum_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_both', + 'name': 'enum_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'object_required', + 'name': 'object_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_key', + 'name': 'object_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_value', + 'name': 'object_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_both', + 'name': 'object_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - } - ] - } - }, - { - 'name': 'object_required_nested_2_layers', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'object_optional_nested_1_layer', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - }, - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } - }, - { - 'name': 'double_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' - } - }, - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } - }, - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - } - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_readonly_required', + 'name': 'int32_array_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_key', + 'name': 'int32_array_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_value', + 'name': 'int32_array_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_both', + 'name': 'int32_array_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } } ] } } - } - ], - 'props': [], - 'commands': [] - } - } - } - } -}" -`; - -exports[`RN Codegen Flow Parser can generate fixture NO_PROPS_EVENTS_ONLY_DEPRECATED_VIEW_CONFIG_NAME_OPTION 1`] = ` -"{ - 'modules': { - 'Module': { - 'type': 'Component', - 'components': { - 'Module': { - 'deprecatedViewConfigName': 'DeprecateModuleName', - 'extendsProps': [ - { - 'type': 'ReactNativeBuiltInType', - 'knownTypeName': 'ReactNativeCoreViewProps' - } - ], - 'events': [], - 'props': [], - 'commands': [] - } - } - } - } -}" -`; - -exports[`RN Codegen Flow Parser can generate fixture OBJECT_PROP_TYPES_NO_EVENTS 1`] = ` -"{ - 'modules': { - 'Module': { - 'type': 'Component', - 'components': { - 'Module': { - 'extendsProps': [ - { - 'type': 'ReactNativeBuiltInType', - 'knownTypeName': 'ReactNativeCoreViewProps' - } - ], - 'events': [], - 'props': [ + }, { - 'name': 'boolean_required', - 'optional': false, + 'name': 'onDirectEventDefinedInlineOptionalBoth', + 'optional': true, + 'bubblingType': 'direct', 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation', - 'default': false - } - } - ] - } - }, - { - 'name': 'boolean_optional', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': true, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation', - 'default': false - } - } - ] - } - }, - { - 'name': 'string_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': false, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation', - 'default': null - } - } - ] - } - }, - { - 'name': 'string_optional', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation', - 'default': '' - } - } - ] - } - }, - { - 'name': 'double_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': false, - 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation', - 'default': 0 - } - } - ] - } - }, - { - 'name': 'double_optional', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': true, - 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation', - 'default': 0 - } - } - ] - } - }, - { - 'name': 'float_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': false, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation', - 'default': 0 - } - } - ] - } - }, - { - 'name': 'float_optional', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation', - 'default': 0 - } - } - ] - } - }, - { - 'name': 'int_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': false, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation', - 'default': 0 - } - } - ] - } - }, - { - 'name': 'int_optional', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation', - 'default': 0 - } - } - ] - } - }, - { - 'name': 'enum_optional', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': true, - 'typeAnnotation': { - 'type': 'ArrayTypeAnnotation', - 'elementType': { - 'type': 'StringEnumTypeAnnotation', - 'default': 'small', - 'options': [ - 'small', - 'large' - ] + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' } - } - } - ] - } - }, - { - 'name': 'image_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': false, - 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'ImageSourcePrimitive' - } - } - ] - } - }, - { - 'name': 'image_optional_key', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': true, - 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'ImageSourcePrimitive' - } - } - ] - } - }, - { - 'name': 'image_optional_value', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': true, - 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'ImageSourcePrimitive' - } - } - ] - } - }, - { - 'name': 'image_optional_both', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': true, - 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'ImageSourcePrimitive' - } - } - ] + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'boolean_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'string_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'double_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'float_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'int32_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'enum_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'object_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'int32_array_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + } + ] + } + } + }, + { + 'name': 'onDirectEventDefinedInlineWithPaperName', + 'optional': true, + 'bubblingType': 'direct', + 'paperTopLevelNameDeprecated': 'paperDirectEventDefinedInlineWithPaperName', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'boolean_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'string_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'double_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'float_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'int32_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'enum_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'object_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'int32_array_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + } + ] + } + } + }, + { + 'name': 'onBubblingEventDefinedInline', + 'optional': false, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'boolean_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'string_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'double_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'float_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'int32_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'enum_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'object_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'int32_array_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + } + ] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineOptionalKey', + 'optional': true, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'boolean_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'string_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'double_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'float_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'int32_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'enum_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'object_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'int32_array_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + } + ] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineOptionalValue', + 'optional': true, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'boolean_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'string_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'double_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'float_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'int32_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'enum_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'object_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'int32_array_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + } + ] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineOptionalBoth', + 'optional': true, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'boolean_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'string_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'double_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'float_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'int32_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'enum_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'object_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'int32_array_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + } + ] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineWithPaperName', + 'optional': true, + 'bubblingType': 'bubble', + 'paperTopLevelNameDeprecated': 'paperBubblingEventDefinedInlineWithPaperName', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'boolean_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'string_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'double_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'float_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'int32_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'enum_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'object_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'int32_array_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + } + ] + } + } + } + ], + 'props': [], + 'commands': [] + } + } + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture NO_PROPS_EVENTS_ONLY_DEPRECATED_VIEW_CONFIG_NAME_OPTION 1`] = ` +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'deprecatedViewConfigName': 'DeprecateModuleName', + 'extendsProps': [ + { + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } + ], + 'events': [], + 'props': [], + 'commands': [] + } + } + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture OBJECT_PROP_TYPES_NO_EVENTS 1`] = ` +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'extendsProps': [ + { + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } + ], + 'events': [], + 'props': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation', + 'default': false + } + } + ] + } + }, + { + 'name': 'boolean_optional', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation', + 'default': false + } + } + ] + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] + } + }, + { + 'name': 'string_optional', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': '' + } + } + ] + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation', + 'default': 0 + } + } + ] + } + }, + { + 'name': 'double_optional', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation', + 'default': 0 + } + } + ] + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation', + 'default': 0 + } + } + ] + } + }, + { + 'name': 'float_optional', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation', + 'default': 0 + } + } + ] + } + }, + { + 'name': 'int_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation', + 'default': 0 + } + } + ] + } + }, + { + 'name': 'int_optional', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation', + 'default': 0 + } + } + ] + } + }, + { + 'name': 'enum_optional', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'default': 'small', + 'options': [ + 'small', + 'large' + ] + } + } + } + ] + } + }, + { + 'name': 'image_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ImageSourcePrimitive' + } + } + ] + } + }, + { + 'name': 'image_optional_key', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ImageSourcePrimitive' + } + } + ] + } + }, + { + 'name': 'image_optional_value', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ImageSourcePrimitive' + } + } + ] + } + }, + { + 'name': 'image_optional_both', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ImageSourcePrimitive' + } + } + ] + } + }, + { + 'name': 'color_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + ] + } + }, + { + 'name': 'color_optional_key', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + ] + } + }, + { + 'name': 'color_optional_value', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + ] + } + }, + { + 'name': 'color_optional_both', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + ] + } + }, + { + 'name': 'processed_color_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + ] + } + }, + { + 'name': 'processed_color_optional_key', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + ] + } + }, + { + 'name': 'processed_color_optional_value', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + ] + } + }, + { + 'name': 'processed_color_optional_both', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + ] + } + }, + { + 'name': 'point_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'PointPrimitive' + } + } + ] + } + }, + { + 'name': 'point_optional_key', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'PointPrimitive' + } + } + ] } }, { - 'name': 'color_required', + 'name': 'point_optional_value', 'optional': false, 'typeAnnotation': { 'type': 'ObjectTypeAnnotation', 'properties': [ { 'name': 'prop', - 'optional': false, + 'optional': true, 'typeAnnotation': { 'type': 'ReservedPropTypeAnnotation', - 'name': 'ColorPrimitive' + 'name': 'PointPrimitive' } } ] } }, { - 'name': 'color_optional_key', + 'name': 'point_optional_both', 'optional': false, 'typeAnnotation': { 'type': 'ObjectTypeAnnotation', @@ -7352,31 +12898,31 @@ exports[`RN Codegen Flow Parser can generate fixture OBJECT_PROP_TYPES_NO_EVENTS 'optional': true, 'typeAnnotation': { 'type': 'ReservedPropTypeAnnotation', - 'name': 'ColorPrimitive' + 'name': 'PointPrimitive' } } ] } }, { - 'name': 'color_optional_value', + 'name': 'insets_required', 'optional': false, 'typeAnnotation': { 'type': 'ObjectTypeAnnotation', 'properties': [ { 'name': 'prop', - 'optional': true, + 'optional': false, 'typeAnnotation': { 'type': 'ReservedPropTypeAnnotation', - 'name': 'ColorPrimitive' + 'name': 'EdgeInsetsPrimitive' } } ] } }, { - 'name': 'color_optional_both', + 'name': 'insets_optional_key', 'optional': false, 'typeAnnotation': { 'type': 'ObjectTypeAnnotation', @@ -7386,31 +12932,31 @@ exports[`RN Codegen Flow Parser can generate fixture OBJECT_PROP_TYPES_NO_EVENTS 'optional': true, 'typeAnnotation': { 'type': 'ReservedPropTypeAnnotation', - 'name': 'ColorPrimitive' + 'name': 'EdgeInsetsPrimitive' } } ] } }, { - 'name': 'processed_color_required', + 'name': 'insets_optional_value', 'optional': false, 'typeAnnotation': { 'type': 'ObjectTypeAnnotation', 'properties': [ { 'name': 'prop', - 'optional': false, + 'optional': true, 'typeAnnotation': { 'type': 'ReservedPropTypeAnnotation', - 'name': 'ColorPrimitive' + 'name': 'EdgeInsetsPrimitive' } } ] } }, { - 'name': 'processed_color_optional_key', + 'name': 'insets_optional_both', 'optional': false, 'typeAnnotation': { 'type': 'ObjectTypeAnnotation', @@ -7420,31 +12966,31 @@ exports[`RN Codegen Flow Parser can generate fixture OBJECT_PROP_TYPES_NO_EVENTS 'optional': true, 'typeAnnotation': { 'type': 'ReservedPropTypeAnnotation', - 'name': 'ColorPrimitive' + 'name': 'EdgeInsetsPrimitive' } } ] } }, { - 'name': 'processed_color_optional_value', + 'name': 'dimension_required', 'optional': false, 'typeAnnotation': { 'type': 'ObjectTypeAnnotation', 'properties': [ { 'name': 'prop', - 'optional': true, + 'optional': false, 'typeAnnotation': { 'type': 'ReservedPropTypeAnnotation', - 'name': 'ColorPrimitive' + 'name': 'DimensionPrimitive' } } ] } }, { - 'name': 'processed_color_optional_both', + 'name': 'dimension_optional_key', 'optional': false, 'typeAnnotation': { 'type': 'ObjectTypeAnnotation', @@ -7454,31 +13000,31 @@ exports[`RN Codegen Flow Parser can generate fixture OBJECT_PROP_TYPES_NO_EVENTS 'optional': true, 'typeAnnotation': { 'type': 'ReservedPropTypeAnnotation', - 'name': 'ColorPrimitive' + 'name': 'DimensionPrimitive' } } ] } }, { - 'name': 'point_required', + 'name': 'dimension_optional_value', 'optional': false, 'typeAnnotation': { 'type': 'ObjectTypeAnnotation', 'properties': [ { 'name': 'prop', - 'optional': false, + 'optional': true, 'typeAnnotation': { 'type': 'ReservedPropTypeAnnotation', - 'name': 'PointPrimitive' + 'name': 'DimensionPrimitive' } } ] } }, { - 'name': 'point_optional_key', + 'name': 'dimension_optional_both', 'optional': false, 'typeAnnotation': { 'type': 'ObjectTypeAnnotation', @@ -7488,551 +13034,1906 @@ exports[`RN Codegen Flow Parser can generate fixture OBJECT_PROP_TYPES_NO_EVENTS 'optional': true, 'typeAnnotation': { 'type': 'ReservedPropTypeAnnotation', - 'name': 'PointPrimitive' + 'name': 'DimensionPrimitive' } } ] } }, { - 'name': 'point_optional_value', + 'name': 'object_required', 'optional': false, 'typeAnnotation': { 'type': 'ObjectTypeAnnotation', 'properties': [ { 'name': 'prop', - 'optional': true, + 'optional': false, 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'PointPrimitive' + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'nestedProp', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] } } ] } }, { - 'name': 'point_optional_both', - 'optional': false, + 'name': 'object_optional_key', + 'optional': true, 'typeAnnotation': { 'type': 'ObjectTypeAnnotation', 'properties': [ { 'name': 'prop', - 'optional': true, + 'optional': false, 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'PointPrimitive' + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'nestedProp', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'nestedProp', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'nestedProp', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] } } ] } - }, + } + ], + 'commands': [] + } + } + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture ONE_OF_EACH_PROP_EVENT_DEFAULT_AND_OPTIONS 1`] = ` +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'interfaceOnly': true, + 'paperComponentName': 'RCTModule', + 'extendsProps': [ + { + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } + ], + 'events': [ + { + 'name': 'onDirectEventDefinedInlineNull', + 'optional': false, + 'bubblingType': 'direct', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineNull', + 'optional': false, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + } + ], + 'props': [ + { + 'name': 'boolean_default_true_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation', + 'default': true + } + } + ], + 'commands': [] + } + } + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture ONE_OF_EACH_PROP_EVENT_DEFAULT_AND_OPTIONS_NO_CAST 1`] = ` +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'interfaceOnly': true, + 'excludedPlatforms': [ + 'android' + ], + 'paperComponentName': 'RCTModule', + 'extendsProps': [ + { + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } + ], + 'events': [ + { + 'name': 'onDirectEventDefinedInlineNull', + 'optional': false, + 'bubblingType': 'direct', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineNull', + 'optional': false, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + } + ], + 'props': [ + { + 'name': 'boolean_default_true_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation', + 'default': true + } + } + ], + 'commands': [] + } + } + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture PROPS_ALIASED_LOCALLY 1`] = ` +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'extendsProps': [ { - 'name': 'insets_required', + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } + ], + 'events': [], + 'props': [ + { + 'name': 'otherStringProp', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': false, - 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'EdgeInsetsPrimitive' - } - } - ] + 'type': 'StringTypeAnnotation', + 'default': null } }, { - 'name': 'insets_optional_key', + 'name': 'isEnabled', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': true, - 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'EdgeInsetsPrimitive' - } - } - ] + 'type': 'BooleanTypeAnnotation', + 'default': false } }, { - 'name': 'insets_optional_value', + 'name': 'label', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': true, - 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'EdgeInsetsPrimitive' - } - } - ] + 'type': 'StringTypeAnnotation', + 'default': null } }, { - 'name': 'insets_optional_both', + 'name': 'localType', 'optional': false, 'typeAnnotation': { 'type': 'ObjectTypeAnnotation', 'properties': [ { - 'name': 'prop', - 'optional': true, + 'name': 'otherStringProp', + 'optional': false, 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'EdgeInsetsPrimitive' + 'type': 'StringTypeAnnotation', + 'default': null } - } - ] - } - }, - { - 'name': 'dimension_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ + }, { - 'name': 'prop', + 'name': 'isEnabled', 'optional': false, 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'DimensionPrimitive' + 'type': 'BooleanTypeAnnotation', + 'default': false } - } - ] - } - }, - { - 'name': 'dimension_optional_key', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ + }, { - 'name': 'prop', - 'optional': true, + 'name': 'label', + 'optional': false, 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'DimensionPrimitive' + 'type': 'StringTypeAnnotation', + 'default': null } } ] } }, { - 'name': 'dimension_optional_value', + 'name': 'localArr', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': true, - 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'DimensionPrimitive' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'otherStringProp', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + }, + { + 'name': 'isEnabled', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation', + 'default': false + } + }, + { + 'name': 'label', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } } - } - ] + ] + } } - }, + } + ], + 'commands': [] + } + } + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture PROPS_AND_EVENTS_TYPES_EXPORTED 1`] = ` +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'extendsProps': [ { - 'name': 'dimension_optional_both', + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } + ], + 'events': [ + { + 'name': 'onBubblingEventDefinedInline', 'optional': false, + 'bubblingType': 'bubble', 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': true, - 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'DimensionPrimitive' + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'boolean_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'string_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'double_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'float_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'int32_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'enum_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'object_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'int32_array_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } } - } - ] + ] + } } }, { - 'name': 'object_required', + 'name': 'onBubblingEventDefinedInlineWithPaperName', 'optional': false, + 'bubblingType': 'bubble', + 'paperTopLevelNameDeprecated': 'paperBubblingEventDefinedInlineWithPaperName', 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'nestedProp', - 'optional': false, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation', - 'default': null + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } } + ] + } + }, + { + 'name': 'boolean_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' } - ] - } - } - ] - } - }, - { - 'name': 'object_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'nestedProp', - 'optional': false, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation', - 'default': null - } + } + }, + { + 'name': 'string_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' } - ] - } - } - ] - } - }, - { - 'name': 'object_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'nestedProp', - 'optional': false, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation', - 'default': null - } + } + }, + { + 'name': 'string_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' } - ] - } - } - ] - } - }, - { - 'name': 'object_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'nestedProp', - 'optional': false, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation', - 'default': null - } + } + }, + { + 'name': 'string_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'double_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'float_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'int32_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'enum_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'object_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] } - ] - } - } - ] - } - } - ], - 'commands': [] - } - } - } - } -}" -`; - -exports[`RN Codegen Flow Parser can generate fixture ONE_OF_EACH_PROP_EVENT_DEFAULT_AND_OPTIONS 1`] = ` -"{ - 'modules': { - 'Module': { - 'type': 'Component', - 'components': { - 'Module': { - 'interfaceOnly': true, - 'paperComponentName': 'RCTModule', - 'extendsProps': [ - { - 'type': 'ReactNativeBuiltInType', - 'knownTypeName': 'ReactNativeCoreViewProps' - } - ], - 'events': [ - { - 'name': 'onDirectEventDefinedInlineNull', - 'optional': false, - 'bubblingType': 'direct', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - }, - { - 'name': 'onBubblingEventDefinedInlineNull', - 'optional': false, - 'bubblingType': 'bubble', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - } - ], - 'props': [ - { - 'name': 'boolean_default_true_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation', - 'default': true - } - } - ], - 'commands': [] - } - } - } - } -}" -`; - -exports[`RN Codegen Flow Parser can generate fixture ONE_OF_EACH_PROP_EVENT_DEFAULT_AND_OPTIONS_NO_CAST 1`] = ` -"{ - 'modules': { - 'Module': { - 'type': 'Component', - 'components': { - 'Module': { - 'interfaceOnly': true, - 'excludedPlatforms': [ - 'android' - ], - 'paperComponentName': 'RCTModule', - 'extendsProps': [ - { - 'type': 'ReactNativeBuiltInType', - 'knownTypeName': 'ReactNativeCoreViewProps' - } - ], - 'events': [ - { - 'name': 'onDirectEventDefinedInlineNull', - 'optional': false, - 'bubblingType': 'direct', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - }, - { - 'name': 'onBubblingEventDefinedInlineNull', - 'optional': false, - 'bubblingType': 'bubble', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - } - ], - 'props': [ - { - 'name': 'boolean_default_true_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation', - 'default': true - } - } - ], - 'commands': [] - } - } - } - } -}" -`; - -exports[`RN Codegen Flow Parser can generate fixture PROPS_ALIASED_LOCALLY 1`] = ` -"{ - 'modules': { - 'Module': { - 'type': 'Component', - 'components': { - 'Module': { - 'extendsProps': [ - { - 'type': 'ReactNativeBuiltInType', - 'knownTypeName': 'ReactNativeCoreViewProps' - } - ], - 'events': [], - 'props': [ - { - 'name': 'otherStringProp', - 'optional': false, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation', - 'default': null - } - }, - { - 'name': 'isEnabled', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation', - 'default': false - } - }, - { - 'name': 'label', - 'optional': false, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation', - 'default': null - } - }, - { - 'name': 'localType', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'otherStringProp', - 'optional': false, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation', - 'default': null - } - }, - { - 'name': 'isEnabled', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation', - 'default': false - } - }, - { - 'name': 'label', - 'optional': false, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation', - 'default': null - } - } - ] - } - }, - { - 'name': 'localArr', - 'optional': false, - 'typeAnnotation': { - 'type': 'ArrayTypeAnnotation', - 'elementType': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ + } + }, + { + 'name': 'object_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + }, { - 'name': 'otherStringProp', + 'name': 'int32_array_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringTypeAnnotation', - 'default': null + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } } }, { - 'name': 'isEnabled', - 'optional': false, + 'name': 'int32_array_array_optional_key', + 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation', - 'default': false + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } } }, { - 'name': 'label', - 'optional': false, + 'name': 'int32_array_array_optional_value', + 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation', - 'default': null + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } } } ] } } - } - ], - 'commands': [] - } - } - } - } -}" -`; - -exports[`RN Codegen Flow Parser can generate fixture PROPS_AND_EVENTS_TYPES_EXPORTED 1`] = ` -"{ - 'modules': { - 'Module': { - 'type': 'Component', - 'components': { - 'Module': { - 'extendsProps': [ - { - 'type': 'ReactNativeBuiltInType', - 'knownTypeName': 'ReactNativeCoreViewProps' - } - ], - 'events': [ + }, { - 'name': 'onBubblingEventDefinedInline', + 'name': 'onDirectEventDefinedInline', 'optional': false, - 'bubblingType': 'bubble', + 'bubblingType': 'direct', 'typeAnnotation': { 'type': 'EventTypeAnnotation', 'argument': { @@ -8402,384 +15303,389 @@ exports[`RN Codegen Flow Parser can generate fixture PROPS_AND_EVENTS_TYPES_EXPO } ] } - } - ] - } - } - }, - { - 'name': 'onBubblingEventDefinedInlineWithPaperName', - 'optional': false, - 'bubblingType': 'bubble', - 'paperTopLevelNameDeprecated': 'paperBubblingEventDefinedInlineWithPaperName', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ + }, { - 'name': 'boolean_required', + 'name': 'boolean_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_key', + 'name': 'boolean_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_value', + 'name': 'boolean_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_both', + 'name': 'boolean_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'string_required', + 'name': 'string_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_key', + 'name': 'string_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_value', + 'name': 'string_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_both', + 'name': 'string_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'double_required', + 'name': 'double_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_key', + 'name': 'double_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_value', + 'name': 'double_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_both', + 'name': 'double_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'float_required', + 'name': 'float_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_key', + 'name': 'float_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_value', + 'name': 'float_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_both', + 'name': 'float_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'int32_required', + 'name': 'int32_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_key', + 'name': 'int32_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_value', + 'name': 'int32_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_both', + 'name': 'int32_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'enum_required', + 'name': 'enum_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] - } - }, - { - 'name': 'enum_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_value', + 'name': 'enum_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_both', + 'name': 'enum_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] - } - }, - { - 'name': 'object_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } - } - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'object_optional_key', + 'name': 'enum_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'object_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_value', + 'name': 'object_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_both', + 'name': 'object_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_required_nested_2_layers', - 'optional': false, + 'name': 'object_array_optional_both', + 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'object_optional_nested_1_layer', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - }, - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } - }, - { - 'name': 'double_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' - } - }, - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } - }, - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - } - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_readonly_required', + 'name': 'int32_array_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_key', + 'name': 'int32_array_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_value', + 'name': 'int32_array_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_both', + 'name': 'int32_array_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } } ] @@ -8787,9 +15693,10 @@ exports[`RN Codegen Flow Parser can generate fixture PROPS_AND_EVENTS_TYPES_EXPO } }, { - 'name': 'onDirectEventDefinedInline', + 'name': 'onDirectEventDefinedInlineWithPaperName', 'optional': false, 'bubblingType': 'direct', + 'paperTopLevelNameDeprecated': 'paperDirectEventDefinedInlineWithPaperName', 'typeAnnotation': { 'type': 'EventTypeAnnotation', 'argument': { @@ -9159,384 +16066,389 @@ exports[`RN Codegen Flow Parser can generate fixture PROPS_AND_EVENTS_TYPES_EXPO } ] } - } - ] - } - } - }, - { - 'name': 'onDirectEventDefinedInlineWithPaperName', - 'optional': false, - 'bubblingType': 'direct', - 'paperTopLevelNameDeprecated': 'paperDirectEventDefinedInlineWithPaperName', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ + }, { - 'name': 'boolean_required', + 'name': 'boolean_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_key', + 'name': 'boolean_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_value', + 'name': 'boolean_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_both', + 'name': 'boolean_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'string_required', + 'name': 'string_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_key', + 'name': 'string_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_value', + 'name': 'string_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_both', + 'name': 'string_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'double_required', + 'name': 'double_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_key', + 'name': 'double_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_value', + 'name': 'double_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_both', + 'name': 'double_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'float_required', + 'name': 'float_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_key', + 'name': 'float_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_value', + 'name': 'float_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_both', + 'name': 'float_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'int32_required', + 'name': 'int32_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_key', + 'name': 'int32_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_value', + 'name': 'int32_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_both', + 'name': 'int32_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'enum_required', + 'name': 'enum_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_key', + 'name': 'enum_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_value', + 'name': 'enum_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_both', + 'name': 'enum_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'object_required', + 'name': 'object_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_key', + 'name': 'object_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_value', + 'name': 'object_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_both', + 'name': 'object_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - } - ] - } - }, - { - 'name': 'object_required_nested_2_layers', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'object_optional_nested_1_layer', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - }, - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } - }, - { - 'name': 'double_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' - } - }, - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } - }, - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - } - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_readonly_required', + 'name': 'int32_array_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_key', + 'name': 'int32_array_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_value', + 'name': 'int32_array_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_both', + 'name': 'int32_array_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } } ] diff --git a/packages/react-native-codegen/src/parsers/flow/components/componentsUtils.js b/packages/react-native-codegen/src/parsers/flow/components/componentsUtils.js index 0ae12c7cbdc45c..7497c702579868 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/componentsUtils.js +++ b/packages/react-native-codegen/src/parsers/flow/components/componentsUtils.js @@ -10,10 +10,10 @@ 'use strict'; -import type {ASTNode} from '../utils'; import type {NamedShape} from '../../../CodegenSchema.js'; const {getValueFromTypes} = require('../utils.js'); -import type {TypeDeclarationMap, PropAST} from '../../utils'; +import type {TypeDeclarationMap, PropAST, ASTNode} from '../../utils'; +import type {BuildSchemaFN, Parser} from '../../parser'; function getProperties( typeName: string, @@ -34,7 +34,8 @@ function getTypeAnnotationForArray<+T>( typeAnnotation: $FlowFixMe, defaultValue: $FlowFixMe | null, types: TypeDeclarationMap, - buildSchema: (property: PropAST, types: TypeDeclarationMap) => ?NamedShape, + parser: Parser, + buildSchema: BuildSchemaFN, ): $FlowFixMe { const extractedTypeAnnotation = getValueFromTypes(typeAnnotation, types); if (extractedTypeAnnotation.type === 'NullableTypeAnnotation') { @@ -63,7 +64,7 @@ function getTypeAnnotationForArray<+T>( objectType.typeParameters.params[0].properties, types, ) - .map(prop => buildSchema(prop, types)) + .map(prop => buildSchema(prop, types, parser)) .filter(Boolean), }; } @@ -84,7 +85,7 @@ function getTypeAnnotationForArray<+T>( nestedObjectType.typeParameters.params[0].properties, types, ) - .map(prop => buildSchema(prop, types)) + .map(prop => buildSchema(prop, types, parser)) .filter(Boolean), }, }; @@ -233,7 +234,8 @@ function getTypeAnnotation<+T>( defaultValue: $FlowFixMe | null, withNullDefault: boolean, types: TypeDeclarationMap, - buildSchema: (property: PropAST, types: TypeDeclarationMap) => ?NamedShape, + parser: Parser, + buildSchema: BuildSchemaFN, ): $FlowFixMe { const typeAnnotation = getValueFromTypes(annotation, types); @@ -248,6 +250,7 @@ function getTypeAnnotation<+T>( typeAnnotation.typeParameters.params[0], defaultValue, types, + parser, buildSchema, ), }; @@ -263,7 +266,7 @@ function getTypeAnnotation<+T>( typeAnnotation.typeParameters.params[0].properties, types, ) - .map(prop => buildSchema(prop, types)) + .map(prop => buildSchema(prop, types, parser)) .filter(Boolean), }; } diff --git a/packages/react-native-codegen/src/parsers/flow/components/events.js b/packages/react-native-codegen/src/parsers/flow/components/events.js index 6afd8eb3be1d5b..f4f6d7b9ee19e9 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/events.js +++ b/packages/react-native-codegen/src/parsers/flow/components/events.js @@ -16,7 +16,12 @@ import type { EventTypeAnnotation, } from '../../../CodegenSchema.js'; import type {Parser} from '../../parser'; -const {throwIfEventHasNoName} = require('../../error-utils'); +const { + throwIfEventHasNoName, + throwIfBubblingTypeIsNull, + throwIfArgumentPropsAreNull, +} = require('../../error-utils'); +const {getEventArgument} = require('../../parsers-commons'); function getPropertyType( /* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's @@ -24,11 +29,9 @@ function getPropertyType( name, optional: boolean, typeAnnotation: $FlowFixMe, + parser: Parser, ): NamedShape { - const type = - typeAnnotation.type === 'GenericTypeAnnotation' - ? typeAnnotation.id.name - : typeAnnotation.type; + const type = extractTypeFromTypeAnnotation(typeAnnotation); switch (type) { case 'BooleanTypeAnnotation': @@ -76,6 +79,7 @@ function getPropertyType( name, optional, typeAnnotation.typeParameters.params[0], + parser, ); case 'ObjectTypeAnnotation': return { @@ -83,7 +87,9 @@ function getPropertyType( optional, typeAnnotation: { type: 'ObjectTypeAnnotation', - properties: typeAnnotation.properties.map(buildPropertiesForEvent), + properties: typeAnnotation.properties.map(member => + buildPropertiesForEvent(member, parser), + ), }, }; case 'UnionTypeAnnotation': @@ -103,12 +109,94 @@ function getPropertyType( type: 'MixedTypeAnnotation', }, }; + case 'ArrayTypeAnnotation': + case '$ReadOnlyArray': + return { + name, + optional, + typeAnnotation: extractArrayElementType(typeAnnotation, name, parser), + }; default: - (type: empty); throw new Error(`Unable to determine event type for "${name}": ${type}`); } } +function extractArrayElementType( + typeAnnotation: $FlowFixMe, + name: string, + parser: Parser, +): EventTypeAnnotation { + const type = extractTypeFromTypeAnnotation(typeAnnotation); + + switch (type) { + case 'BooleanTypeAnnotation': + return {type: 'BooleanTypeAnnotation'}; + case 'StringTypeAnnotation': + return {type: 'StringTypeAnnotation'}; + case 'Int32': + return {type: 'Int32TypeAnnotation'}; + case 'Float': + return {type: 'FloatTypeAnnotation'}; + case 'NumberTypeAnnotation': + case 'Double': + return { + type: 'DoubleTypeAnnotation', + }; + case 'UnionTypeAnnotation': + return { + type: 'StringEnumTypeAnnotation', + options: typeAnnotation.types.map(option => option.value), + }; + case 'UnsafeMixed': + return {type: 'MixedTypeAnnotation'}; + case 'ObjectTypeAnnotation': + return { + type: 'ObjectTypeAnnotation', + properties: typeAnnotation.properties.map(member => + buildPropertiesForEvent(member, parser), + ), + }; + case 'ArrayTypeAnnotation': + return { + type: 'ArrayTypeAnnotation', + elementType: extractArrayElementType( + typeAnnotation.elementType, + name, + parser, + ), + }; + case '$ReadOnlyArray': + const genericParams = typeAnnotation.typeParameters.params; + if (genericParams.length !== 1) { + throw new Error( + `Events only supports arrays with 1 Generic type. Found ${ + genericParams.length + } types:\n${prettify(genericParams)}`, + ); + } + return { + type: 'ArrayTypeAnnotation', + elementType: extractArrayElementType(genericParams[0], name, parser), + }; + default: + throw new Error( + `Unrecognized ${type} for Array ${name} in events.\n${prettify( + typeAnnotation, + )}`, + ); + } +} + +function prettify(jsonObject: $FlowFixMe): string { + return JSON.stringify(jsonObject, null, 2); +} + +function extractTypeFromTypeAnnotation(typeAnnotation: $FlowFixMe): string { + return typeAnnotation.type === 'GenericTypeAnnotation' + ? typeAnnotation.id.name + : typeAnnotation.type; +} + function findEventArgumentsAndType( parser: Parser, typeAnnotation: $FlowFixMe, @@ -136,7 +224,7 @@ function findEventArgumentsAndType( : null; if ( typeAnnotation.typeParameters.params[0].type === - 'NullLiteralTypeAnnotation' + parser.nullLiteralTypeAnnotation ) { return { argumentProps: [], @@ -168,27 +256,20 @@ function findEventArgumentsAndType( } } -/* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's - * LTI update could not be added via codemod */ -function buildPropertiesForEvent(property): NamedShape { +function buildPropertiesForEvent( + /* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's + * LTI update could not be added via codemod */ + property, + parser: Parser, +): NamedShape { const name = property.key.name; - const optional = - property.value.type === 'NullableTypeAnnotation' || property.optional; + const optional = parser.isOptionalProperty(property); let typeAnnotation = property.value.type === 'NullableTypeAnnotation' ? property.value.typeAnnotation : property.value; - return getPropertyType(name, optional, typeAnnotation); -} - -/* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's - * LTI update could not be added via codemod */ -function getEventArgument(argumentProps, name: $FlowFixMe) { - return { - type: 'ObjectTypeAnnotation', - properties: argumentProps.map(buildPropertiesForEvent), - }; + return getPropertyType(name, optional, typeAnnotation, parser); } function buildEventSchema( @@ -216,38 +297,42 @@ function buildEventSchema( const {argumentProps, bubblingType, paperTopLevelNameDeprecated} = findEventArgumentsAndType(parser, typeAnnotation, types); - if (bubblingType && argumentProps) { - if (paperTopLevelNameDeprecated != null) { - return { - name, - optional, - bubblingType, - paperTopLevelNameDeprecated, - typeAnnotation: { - type: 'EventTypeAnnotation', - argument: getEventArgument(argumentProps, name), - }, - }; - } + const nonNullableArgumentProps = throwIfArgumentPropsAreNull( + argumentProps, + name, + ); + const nonNullableBubblingType = throwIfBubblingTypeIsNull(bubblingType, name); + if (paperTopLevelNameDeprecated != null) { return { name, optional, - bubblingType, + bubblingType: nonNullableBubblingType, + paperTopLevelNameDeprecated, typeAnnotation: { type: 'EventTypeAnnotation', - argument: getEventArgument(argumentProps, name), + argument: getEventArgument( + nonNullableArgumentProps, + buildPropertiesForEvent, + parser, + ), }, }; } - if (argumentProps === null) { - throw new Error(`Unable to determine event arguments for "${name}"`); - } - - if (bubblingType === null) { - throw new Error(`Unable to determine event arguments for "${name}"`); - } + return { + name, + optional, + bubblingType: nonNullableBubblingType, + typeAnnotation: { + type: 'EventTypeAnnotation', + argument: getEventArgument( + nonNullableArgumentProps, + buildPropertiesForEvent, + parser, + ), + }, + }; } // $FlowFixMe[unclear-type] there's no flowtype for ASTs diff --git a/packages/react-native-codegen/src/parsers/flow/components/props.js b/packages/react-native-codegen/src/parsers/flow/components/props.js index a55b5a43025223..1542e8f4e8b554 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/props.js +++ b/packages/react-native-codegen/src/parsers/flow/components/props.js @@ -18,41 +18,14 @@ import type { import type {TypeDeclarationMap, PropAST} from '../../utils'; import type {Parser} from '../../parser'; -const { - flattenProperties, - getSchemaInfo, - getTypeAnnotation, -} = require('./componentsUtils.js'); +const {flattenProperties} = require('./componentsUtils.js'); +const {buildPropSchema} = require('../../parsers-commons'); type ExtendsForProp = null | { type: 'ReactNativeBuiltInType', knownTypeName: 'ReactNativeCoreViewProps', }; -function buildPropSchema( - property: PropAST, - types: TypeDeclarationMap, -): ?NamedShape { - const info = getSchemaInfo(property, types); - if (info == null) { - return null; - } - const {name, optional, typeAnnotation, defaultValue, withNullDefault} = info; - - return { - name, - optional, - typeAnnotation: getTypeAnnotation( - name, - typeAnnotation, - defaultValue, - withNullDefault, - types, - buildPropSchema, - ), - }; -} - function extendsForProp( prop: PropAST, types: TypeDeclarationMap, @@ -117,7 +90,7 @@ function getProps( } { const nonExtendsProps = removeKnownExtends(typeDefinition, types, parser); const props = flattenProperties(nonExtendsProps, types) - .map(property => buildPropSchema(property, types)) + .map(property => buildPropSchema(property, types, parser)) .filter(Boolean); return { diff --git a/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-snapshot-test.js.snap b/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-snapshot-test.js.snap index 6de97cbbc6b47a..00d66fd81de929 100644 --- a/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-snapshot-test.js.snap +++ b/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-snapshot-test.js.snap @@ -201,14 +201,26 @@ exports[`RN Codegen Flow Parser can generate fixture CXX_ONLY_NATIVE_MODULE 1`] 'typeAnnotation': { 'type': 'FunctionTypeAnnotation', 'returnTypeAnnotation': { - 'type': 'GenericObjectTypeAnnotation' + 'type': 'GenericObjectTypeAnnotation', + 'dictionaryValueType': { + 'type': 'NullableTypeAnnotation', + 'typeAnnotation': { + 'type': 'NumberTypeAnnotation' + } + } }, 'params': [ { 'name': 'arg', 'optional': false, 'typeAnnotation': { - 'type': 'GenericObjectTypeAnnotation' + 'type': 'GenericObjectTypeAnnotation', + 'dictionaryValueType': { + 'type': 'NullableTypeAnnotation', + 'typeAnnotation': { + 'type': 'NumberTypeAnnotation' + } + } } } ] @@ -220,14 +232,20 @@ exports[`RN Codegen Flow Parser can generate fixture CXX_ONLY_NATIVE_MODULE 1`] 'typeAnnotation': { 'type': 'FunctionTypeAnnotation', 'returnTypeAnnotation': { - 'type': 'GenericObjectTypeAnnotation' + 'type': 'GenericObjectTypeAnnotation', + 'dictionaryValueType': { + 'type': 'StringTypeAnnotation' + } }, 'params': [ { 'name': 'arg', 'optional': false, 'typeAnnotation': { - 'type': 'GenericObjectTypeAnnotation' + 'type': 'GenericObjectTypeAnnotation', + 'dictionaryValueType': { + 'type': 'StringTypeAnnotation' + } } } ] @@ -2165,7 +2183,11 @@ exports[`RN Codegen Flow Parser can generate fixture PROMISE_WITH_COMMONLY_USED_ 'returnTypeAnnotation': { 'type': 'PromiseTypeAnnotation', 'elementType': { - 'type': 'GenericObjectTypeAnnotation' + 'type': 'GenericObjectTypeAnnotation', + 'dictionaryValueType': { + 'type': 'TypeAliasTypeAnnotation', + 'name': 'CustomObject' + } } }, 'params': [] diff --git a/packages/react-native-codegen/src/parsers/flow/modules/index.js b/packages/react-native-codegen/src/parsers/flow/modules/index.js index 1b7b2503f70d25..1a21c605b1d407 100644 --- a/packages/react-native-codegen/src/parsers/flow/modules/index.js +++ b/packages/react-native-codegen/src/parsers/flow/modules/index.js @@ -20,9 +20,9 @@ import type { } from '../../../CodegenSchema'; import type {Parser} from '../../parser'; +const {resolveTypeAnnotation} = require('../utils'); import type {ParserErrorCapturer, TypeDeclarationMap} from '../../utils'; -const {resolveTypeAnnotation} = require('../utils'); const { unwrapNullable, wrapNullable, @@ -32,7 +32,7 @@ const { const { emitArrayType, emitFunction, - emitGenericObject, + emitDictionary, emitPromise, emitRootTag, emitUnion, @@ -60,7 +60,7 @@ function translateTypeAnnotation( parser: Parser, ): Nullable { const {nullable, typeAnnotation, typeResolutionStatus} = - resolveTypeAnnotation(flowTypeAnnotation, types); + resolveTypeAnnotation(flowTypeAnnotation, types, parser); switch (typeAnnotation.type) { case 'GenericTypeAnnotation': { @@ -152,7 +152,7 @@ function translateTypeAnnotation( // check the property type to prevent developers from using unsupported types // the return value from `translateTypeAnnotation` is unused const propertyType = indexers[0].value; - translateTypeAnnotation( + const valueType = translateTypeAnnotation( hasteModuleName, propertyType, types, @@ -163,7 +163,7 @@ function translateTypeAnnotation( parser, ); // no need to do further checking - return emitGenericObject(nullable); + return emitDictionary(nullable, valueType); } } diff --git a/packages/react-native-codegen/src/parsers/flow/parser.js b/packages/react-native-codegen/src/parsers/flow/parser.js index 626346ab28cd54..2b75c017604607 100644 --- a/packages/react-native-codegen/src/parsers/flow/parser.js +++ b/packages/react-native-codegen/src/parsers/flow/parser.js @@ -22,8 +22,26 @@ import type { NativeModuleEnumMap, } from '../../CodegenSchema'; import type {ParserType} from '../errors'; -import type {Parser} from '../parser'; -import type {ParserErrorCapturer, TypeDeclarationMap, PropAST} from '../utils'; +import type { + GetSchemaInfoFN, + GetTypeAnnotationFN, + Parser, + ResolveTypeAnnotationFN, +} from '../parser'; +import type { + ParserErrorCapturer, + TypeDeclarationMap, + PropAST, + TypeResolutionStatus, +} from '../utils'; + +const {resolveTypeAnnotation} = require('./utils'); +const invariant = require('invariant'); + +const { + getSchemaInfo, + getTypeAnnotation, +} = require('./components/componentsUtils'); const {flowTranslateTypeAnnotation} = require('./modules'); @@ -35,7 +53,6 @@ const {Visitor} = require('../parsers-primitives'); const {buildComponentSchema} = require('./components'); const {wrapComponentSchema} = require('../schema.js'); const {buildModuleSchema} = require('../parsers-commons.js'); -const {resolveTypeAnnotation} = require('./utils'); const fs = require('fs'); @@ -45,6 +62,11 @@ const { class FlowParser implements Parser { typeParameterInstantiation: string = 'TypeParameterInstantiation'; + typeAlias: string = 'TypeAlias'; + enumDeclaration: string = 'EnumDeclaration'; + interfaceDelcaration: string = 'InterfaceDeclaration'; + + nullLiteralTypeAnnotation: string = 'NullLiteralTypeAnnotation'; isProperty(property: $FlowFixMe): boolean { return property.type === 'ObjectTypeProperty'; @@ -106,7 +128,6 @@ class FlowParser implements Parser { buildModuleSchema, Visitor, this, - resolveTypeAnnotation, flowTranslateTypeAnnotation, ); } @@ -337,6 +358,93 @@ class FlowParser implements Parser { nameForArgument(prop: PropAST): $FlowFixMe { return prop.argument.id.name; } + + isOptionalProperty(property: $FlowFixMe): boolean { + return ( + property.value.type === 'NullableTypeAnnotation' || property.optional + ); + } + + getGetSchemaInfoFN(): GetSchemaInfoFN { + return getSchemaInfo; + } + + getGetTypeAnnotationFN(): GetTypeAnnotationFN { + return getTypeAnnotation; + } + + getResolvedTypeAnnotation( + typeAnnotation: $FlowFixMe, + types: TypeDeclarationMap, + ): { + nullable: boolean, + typeAnnotation: $FlowFixMe, + typeResolutionStatus: TypeResolutionStatus, + } { + invariant( + typeAnnotation != null, + 'resolveTypeAnnotation(): typeAnnotation cannot be null', + ); + + let node = typeAnnotation; + let nullable = false; + let typeResolutionStatus: TypeResolutionStatus = { + successful: false, + }; + + for (;;) { + if (node.type === 'NullableTypeAnnotation') { + nullable = true; + node = node.typeAnnotation; + continue; + } + + if (node.type !== 'GenericTypeAnnotation') { + break; + } + + const resolvedTypeAnnotation = types[node.id.name]; + if (resolvedTypeAnnotation == null) { + break; + } + + switch (resolvedTypeAnnotation.type) { + case 'TypeAlias': { + typeResolutionStatus = { + successful: true, + type: 'alias', + name: node.id.name, + }; + node = resolvedTypeAnnotation.right; + break; + } + case 'EnumDeclaration': { + typeResolutionStatus = { + successful: true, + type: 'enum', + name: node.id.name, + }; + node = resolvedTypeAnnotation.body; + break; + } + default: { + throw new TypeError( + `A non GenericTypeAnnotation must be a type declaration ('TypeAlias') or enum ('EnumDeclaration'). Instead, got the unsupported ${resolvedTypeAnnotation.type}.`, + ); + } + } + } + + return { + nullable: nullable, + typeAnnotation: node, + typeResolutionStatus, + }; + } + + getResolveTypeAnnotationFN(): ResolveTypeAnnotationFN { + return resolveTypeAnnotation; + } } module.exports = { diff --git a/packages/react-native-codegen/src/parsers/flow/utils.js b/packages/react-native-codegen/src/parsers/flow/utils.js index 3692cf16f89b7c..f2e125c3b853f2 100644 --- a/packages/react-native-codegen/src/parsers/flow/utils.js +++ b/packages/react-native-codegen/src/parsers/flow/utils.js @@ -10,10 +10,8 @@ 'use strict'; -import type {TypeResolutionStatus, TypeDeclarationMap} from '../utils'; - -// $FlowFixMe[unclear-type] there's no flowtype for ASTs -export type ASTNode = Object; +import type {TypeResolutionStatus, TypeDeclarationMap, ASTNode} from '../utils'; +import type {Parser} from '../../parsers/parser'; const invariant = require('invariant'); @@ -21,6 +19,7 @@ function resolveTypeAnnotation( // TODO(T71778680): This is an Flow TypeAnnotation. Flow-type this typeAnnotation: $FlowFixMe, types: TypeDeclarationMap, + parser: Parser, ): { nullable: boolean, typeAnnotation: $FlowFixMe, @@ -54,7 +53,7 @@ function resolveTypeAnnotation( } switch (resolvedTypeAnnotation.type) { - case 'TypeAlias': { + case parser.typeAlias: { typeResolutionStatus = { successful: true, type: 'alias', @@ -63,7 +62,7 @@ function resolveTypeAnnotation( node = resolvedTypeAnnotation.right; break; } - case 'EnumDeclaration': { + case parser.enumDeclaration: { typeResolutionStatus = { successful: true, type: 'enum', @@ -74,7 +73,7 @@ function resolveTypeAnnotation( } default: { throw new TypeError( - `A non GenericTypeAnnotation must be a type declaration ('TypeAlias') or enum ('EnumDeclaration'). Instead, got the unsupported ${resolvedTypeAnnotation.type}.`, + `A non GenericTypeAnnotation must be a type declaration ('${parser.typeAlias}') or enum ('${parser.enumDeclaration}'). Instead, got the unsupported ${resolvedTypeAnnotation.type}.`, ); } } diff --git a/packages/react-native-codegen/src/parsers/parser.js b/packages/react-native-codegen/src/parsers/parser.js index 066ad13293e5e6..e5c882601e80e7 100644 --- a/packages/react-native-codegen/src/parsers/parser.js +++ b/packages/react-native-codegen/src/parsers/parser.js @@ -22,7 +22,56 @@ import type { NativeModuleEnumMap, } from '../CodegenSchema'; import type {ParserType} from './errors'; -import type {ParserErrorCapturer, TypeDeclarationMap, PropAST} from './utils'; +import type { + ParserErrorCapturer, + TypeDeclarationMap, + PropAST, + ASTNode, + TypeResolutionStatus, +} from './utils'; + +export type GetTypeAnnotationFN = ( + name: string, + annotation: $FlowFixMe | ASTNode, + defaultValue: $FlowFixMe | void, + withNullDefault: boolean, + types: TypeDeclarationMap, + parser: Parser, + buildSchema: ( + property: PropAST, + types: TypeDeclarationMap, + parser: Parser, + ) => $FlowFixMe, +) => $FlowFixMe; + +export type SchemaInfo = { + name: string, + optional: boolean, + typeAnnotation: $FlowFixMe, + defaultValue: $FlowFixMe, + withNullDefault: boolean, +}; + +export type GetSchemaInfoFN = ( + property: PropAST, + types: TypeDeclarationMap, +) => ?SchemaInfo; + +export type BuildSchemaFN = ( + property: PropAST, + types: TypeDeclarationMap, + parser: Parser, +) => ?NamedShape; + +export type ResolveTypeAnnotationFN = ( + typeAnnotation: $FlowFixMe, + types: TypeDeclarationMap, + parser: Parser, +) => { + nullable: boolean, + typeAnnotation: $FlowFixMe, + typeResolutionStatus: TypeResolutionStatus, +}; /** * This is the main interface for Parsers of various languages. @@ -34,6 +83,26 @@ export interface Parser { */ typeParameterInstantiation: string; + /** + * TypeAlias property of the Parser + */ + typeAlias: string; + + /** + * enumDeclaration Property of the Parser + */ + enumDeclaration: string; + + /** + * InterfaceDelcaration property of the Parser + */ + interfaceDelcaration: string; + + /** + * This is the NullLiteralTypeAnnotation value + */ + nullLiteralTypeAnnotation: string; + /** * Given a declaration, it returns true if it is a property */ @@ -269,4 +338,26 @@ export interface Parser { * @returns: name property */ nameForArgument(prop: PropAST): $FlowFixMe; + + /** + * Given a property return if it is optional. + * @parameter property + * @returns: a boolean specifying if the Property is optional + */ + isOptionalProperty(property: $FlowFixMe): boolean; + + getGetTypeAnnotationFN(): GetTypeAnnotationFN; + + getGetSchemaInfoFN(): GetSchemaInfoFN; + + getResolvedTypeAnnotation( + typeAnnotation: $FlowFixMe, + types: TypeDeclarationMap, + ): { + nullable: boolean, + typeAnnotation: $FlowFixMe, + typeResolutionStatus: TypeResolutionStatus, + }; + + getResolveTypeAnnotationFN(): ResolveTypeAnnotationFN; } diff --git a/packages/react-native-codegen/src/parsers/parserMock.js b/packages/react-native-codegen/src/parsers/parserMock.js index 1263b469de553e..1df9b00a793492 100644 --- a/packages/react-native-codegen/src/parsers/parserMock.js +++ b/packages/react-native-codegen/src/parsers/parserMock.js @@ -10,7 +10,12 @@ 'use strict'; -import type {Parser} from './parser'; +import type { + GetSchemaInfoFN, + GetTypeAnnotationFN, + Parser, + ResolveTypeAnnotationFN, +} from './parser'; import type {ParserType} from './errors'; import type { UnionTypeAnnotationMemberType, @@ -23,7 +28,13 @@ import type { NativeModuleAliasMap, NativeModuleEnumMap, } from '../CodegenSchema'; -import type {ParserErrorCapturer, PropAST, TypeDeclarationMap} from './utils'; +import type { + ParserErrorCapturer, + PropAST, + TypeDeclarationMap, + TypeResolutionStatus, +} from './utils'; +import invariant from 'invariant'; // $FlowFixMe[untyped-import] there's no flowtype flow-parser const flowParser = require('flow-parser'); @@ -49,6 +60,11 @@ const schemaMock = { export class MockedParser implements Parser { typeParameterInstantiation: string = 'TypeParameterInstantiation'; + typeAlias: string = 'TypeAlias'; + enumDeclaration: string = 'EnumDeclaration'; + interfaceDelcaration: string = 'InterfaceDelcaration'; + + nullLiteralTypeAnnotation: string = 'NullLiteralTypeAnnotation'; isProperty(property: $FlowFixMe): boolean { return property.type === 'ObjectTypeProperty'; @@ -251,4 +267,105 @@ export class MockedParser implements Parser { nameForArgument(prop: PropAST): $FlowFixMe { return prop.expression.name; } + + isOptionalProperty(property: $FlowFixMe): boolean { + return property.optional || false; + } + + getGetTypeAnnotationFN(): GetTypeAnnotationFN { + return () => { + return {}; + }; + } + + getGetSchemaInfoFN(): GetSchemaInfoFN { + return () => { + return { + name: 'MockedSchema', + optional: false, + typeAnnotation: 'BooleanTypeAnnotation', + defaultValue: false, + withNullDefault: false, + }; + }; + } + + getResolveTypeAnnotationFN(): ResolveTypeAnnotationFN { + return () => { + return { + nullable: false, + typeAnnotation: null, + typeResolutionStatus: {successful: false}, + }; + }; + } + + getResolvedTypeAnnotation( + typeAnnotation: $FlowFixMe, + types: TypeDeclarationMap, + ): { + nullable: boolean, + typeAnnotation: $FlowFixMe, + typeResolutionStatus: TypeResolutionStatus, + } { + invariant( + typeAnnotation != null, + 'resolveTypeAnnotation(): typeAnnotation cannot be null', + ); + + let node = typeAnnotation; + let nullable = false; + let typeResolutionStatus: TypeResolutionStatus = { + successful: false, + }; + + for (;;) { + if (node.type === 'NullableTypeAnnotation') { + nullable = true; + node = node.typeAnnotation; + continue; + } + + if (node.type !== 'GenericTypeAnnotation') { + break; + } + + const resolvedTypeAnnotation = types[node.id.name]; + if (resolvedTypeAnnotation == null) { + break; + } + + switch (resolvedTypeAnnotation.type) { + case 'TypeAlias': { + typeResolutionStatus = { + successful: true, + type: 'alias', + name: node.id.name, + }; + node = resolvedTypeAnnotation.right; + break; + } + case 'EnumDeclaration': { + typeResolutionStatus = { + successful: true, + type: 'enum', + name: node.id.name, + }; + node = resolvedTypeAnnotation.body; + break; + } + default: { + throw new TypeError( + `A non GenericTypeAnnotation must be a type declaration ('TypeAlias') or enum ('EnumDeclaration'). Instead, got the unsupported ${resolvedTypeAnnotation.type}.`, + ); + } + } + } + + return { + nullable: nullable, + typeAnnotation: node, + typeResolutionStatus, + }; + } } diff --git a/packages/react-native-codegen/src/parsers/parsers-commons.js b/packages/react-native-codegen/src/parsers/parsers-commons.js index e98581ef28bf01..ab65836feb7617 100644 --- a/packages/react-native-codegen/src/parsers/parsers-commons.js +++ b/packages/react-native-codegen/src/parsers/parsers-commons.js @@ -23,6 +23,9 @@ import type { SchemaType, NativeModuleEnumMap, OptionsShape, + PropTypeAnnotation, + EventTypeAnnotation, + ObjectTypeAnnotation, } from '../CodegenSchema.js'; import type {Parser} from './parser'; @@ -319,7 +322,6 @@ function buildPropertySchema( enumMap: {...NativeModuleEnumMap}, tryParse: ParserErrorCapturer, cxxOnly: boolean, - resolveTypeAnnotation: $FlowFixMe, translateTypeAnnotation: $FlowFixMe, parser: Parser, ): NativeModulePropertyShape { @@ -334,7 +336,12 @@ function buildPropertySchema( : property.typeAnnotation; } - ({nullable, typeAnnotation: value} = resolveTypeAnnotation(value, types)); + const resolveTypeAnnotationFN = parser.getResolveTypeAnnotationFN(); + ({nullable, typeAnnotation: value} = resolveTypeAnnotationFN( + value, + types, + parser, + )); throwIfModuleTypeIsUnsupported( hasteModuleName, @@ -378,11 +385,9 @@ function buildSchemaFromConfigType( ast: $FlowFixMe, tryParse: ParserErrorCapturer, parser: Parser, - resolveTypeAnnotation: $FlowFixMe, translateTypeAnnotation: $FlowFixMe, ) => NativeModuleSchema, parser: Parser, - resolveTypeAnnotation: $FlowFixMe, translateTypeAnnotation: $FlowFixMe, ): SchemaType { switch (configType) { @@ -403,7 +408,6 @@ function buildSchemaFromConfigType( ast, tryParse, parser, - resolveTypeAnnotation, translateTypeAnnotation, ), ); @@ -445,14 +449,12 @@ function buildSchema( ast: $FlowFixMe, tryParse: ParserErrorCapturer, parser: Parser, - resolveTypeAnnotation: $FlowFixMe, translateTypeAnnotation: $FlowFixMe, ) => NativeModuleSchema, Visitor: ({isComponent: boolean, isModule: boolean}) => { [type: string]: (node: $FlowFixMe) => void, }, parser: Parser, - resolveTypeAnnotation: $FlowFixMe, translateTypeAnnotation: $FlowFixMe, ): SchemaType { // Early return for non-Spec JavaScript files @@ -474,7 +476,6 @@ function buildSchema( buildComponentSchema, buildModuleSchema, parser, - resolveTypeAnnotation, translateTypeAnnotation, ); } @@ -569,7 +570,6 @@ const buildModuleSchema = ( ast: $FlowFixMe, tryParse: ParserErrorCapturer, parser: Parser, - resolveTypeAnnotation: $FlowFixMe, translateTypeAnnotation: $FlowFixMe, ): NativeModuleSchema => { const language = parser.language(); @@ -637,7 +637,6 @@ const buildModuleSchema = ( enumMap, tryParse, cxxOnly, - resolveTypeAnnotation, translateTypeAnnotation, parser, ), @@ -852,6 +851,53 @@ function extendsForProp( } } +function buildPropSchema( + property: PropAST, + types: TypeDeclarationMap, + parser: Parser, +): ?NamedShape { + const getSchemaInfoFN = parser.getGetSchemaInfoFN(); + const info = getSchemaInfoFN(property, types); + if (info == null) { + return null; + } + const {name, optional, typeAnnotation, defaultValue, withNullDefault} = info; + + const getTypeAnnotationFN = parser.getGetTypeAnnotationFN(); + + return { + name, + optional, + typeAnnotation: getTypeAnnotationFN( + name, + typeAnnotation, + defaultValue, + withNullDefault, + types, + parser, + buildPropSchema, + ), + }; +} + +/* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's + * LTI update could not be added via codemod */ +function getEventArgument( + argumentProps: PropAST, + buildPropertiesForEvent: ( + property: PropAST, + parser: Parser, + ) => NamedShape, + parser: Parser, +): ObjectTypeAnnotation { + return { + type: 'ObjectTypeAnnotation', + properties: argumentProps.map(member => + buildPropertiesForEvent(member, parser), + ), + }; +} + module.exports = { wrapModuleSchema, unwrapNullable, @@ -872,4 +918,6 @@ module.exports = { getOptions, getCommandTypeNameAndOptionsExpression, extendsForProp, + buildPropSchema, + getEventArgument, }; diff --git a/packages/react-native-codegen/src/parsers/parsers-primitives.js b/packages/react-native-codegen/src/parsers/parsers-primitives.js index 849c3e756fb0b5..84ba85949d5e1a 100644 --- a/packages/react-native-codegen/src/parsers/parsers-primitives.js +++ b/packages/react-native-codegen/src/parsers/parsers-primitives.js @@ -309,6 +309,16 @@ function emitGenericObject( }); } +function emitDictionary( + nullable: boolean, + valueType: Nullable, +): Nullable { + return wrapNullable(nullable, { + type: 'GenericObjectTypeAnnotation', + dictionaryValueType: valueType, + }); +} + function emitObject( nullable: boolean, properties: Array<$FlowFixMe>, @@ -576,6 +586,7 @@ module.exports = { emitInt32, emitNumber, emitGenericObject, + emitDictionary, emitObject, emitPromise, emitRootTag, diff --git a/packages/react-native-codegen/src/parsers/typescript/components/__test_fixtures__/fixtures.js b/packages/react-native-codegen/src/parsers/typescript/components/__test_fixtures__/fixtures.js index 57aafa7b5562d4..7f81b17e6cc3fe 100644 --- a/packages/react-native-codegen/src/parsers/typescript/components/__test_fixtures__/fixtures.js +++ b/packages/react-native-codegen/src/parsers/typescript/components/__test_fixtures__/fixtures.js @@ -84,6 +84,57 @@ const EVENT_DEFINITION = ` object_readonly_optional_both?: Readonly<{ int32_optional_both?: Int32 | null | undefined; }> | null | undefined; + + boolean_array_required: boolean[]; + boolean_array_optional_key?: boolean[]; + boolean_array_optional_value: boolean[] | null | undefined; + boolean_array_optional_both?: boolean[] | null | undefined; + + string_array_required: string[]; + string_array_optional_key?: (string[]); + string_array_optional_value: (string[]) | null | undefined; + string_array_optional_both?: (string[] | null | undefined); + + double_array_required: Double[]; + double_array_optional_key?: Double[]; + double_array_optional_value: Double[] | null | undefined; + double_array_optional_both?: Double[] | null | undefined; + + float_array_required: Float[]; + float_array_optional_key?: Float[]; + float_array_optional_value: Float[] | null | undefined; + float_array_optional_both?: Float[] | null | undefined; + + int32_array_required: Int32[]; + int32_array_optional_key?: Int32[]; + int32_array_optional_value: Int32[] | null | undefined; + int32_array_optional_both?: Int32[] | null | undefined; + + enum_array_required: ('small' | 'large')[]; + enum_array_optional_key?: ('small' | 'large')[]; + enum_array_optional_value: ('small' | 'large')[] | null | undefined; + enum_array_optional_both?: ('small' | 'large')[] | null | undefined; + + object_array_required: { + boolean_required: boolean; + }[]; + + object_array_optional_key?: { + string_optional_key?: string; + }[]; + + object_array_optional_value: { + float_optional_value: Float | null | undefined; + }[] | null | undefined; + + object_array_optional_both?: { + int32_optional_both?: Int32 | null | undefined; + }[] | null | undefined; + + int32_array_array_required: Int32[][]; + int32_array_array_optional_key?: Int32[][]; + int32_array_array_optional_value: Int32[][] | null | undefined; + int32_array_array_optional_both?: Int32[][] | null | undefined; `; const ONE_OF_EACH_PROP_EVENT_DEFAULT_AND_OPTIONS = ` diff --git a/packages/react-native-codegen/src/parsers/typescript/components/__tests__/__snapshots__/typescript-component-parser-test.js.snap b/packages/react-native-codegen/src/parsers/typescript/components/__tests__/__snapshots__/typescript-component-parser-test.js.snap index 4211709793e576..59699c28576fb4 100644 --- a/packages/react-native-codegen/src/parsers/typescript/components/__tests__/__snapshots__/typescript-component-parser-test.js.snap +++ b/packages/react-native-codegen/src/parsers/typescript/components/__tests__/__snapshots__/typescript-component-parser-test.js.snap @@ -2548,384 +2548,389 @@ exports[`RN Codegen TypeScript Parser can generate fixture COMMANDS_EVENTS_TYPES } ] } - } - ] - } - } - }, - { - 'name': 'onBubblingEventDefinedInlineWithPaperName', - 'optional': false, - 'bubblingType': 'bubble', - 'paperTopLevelNameDeprecated': 'paperBubblingEventDefinedInlineWithPaperName', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ + }, { - 'name': 'boolean_required', + 'name': 'boolean_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_key', + 'name': 'boolean_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_value', + 'name': 'boolean_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_both', + 'name': 'boolean_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'string_required', + 'name': 'string_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_key', + 'name': 'string_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_value', + 'name': 'string_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_both', + 'name': 'string_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'double_required', + 'name': 'double_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_key', + 'name': 'double_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_value', + 'name': 'double_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_both', + 'name': 'double_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'float_required', + 'name': 'float_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_key', + 'name': 'float_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_value', + 'name': 'float_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_both', + 'name': 'float_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'int32_required', + 'name': 'int32_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_key', + 'name': 'int32_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_value', + 'name': 'int32_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_both', + 'name': 'int32_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'enum_required', + 'name': 'enum_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_key', + 'name': 'enum_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_value', + 'name': 'enum_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_both', + 'name': 'enum_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'object_required', + 'name': 'object_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_key', + 'name': 'object_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_value', + 'name': 'object_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_both', + 'name': 'object_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_required_nested_2_layers', + 'name': 'int32_array_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'object_optional_nested_1_layer', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - }, - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } - }, - { - 'name': 'double_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' - } - }, - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } - }, - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - } - ] - } - } - ] - } - }, - { - 'name': 'object_readonly_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_key', + 'name': 'int32_array_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_value', + 'name': 'int32_array_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_both', + 'name': 'int32_array_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } } ] @@ -2933,9 +2938,10 @@ exports[`RN Codegen TypeScript Parser can generate fixture COMMANDS_EVENTS_TYPES } }, { - 'name': 'onDirectEventDefinedInline', + 'name': 'onBubblingEventDefinedInlineWithPaperName', 'optional': false, - 'bubblingType': 'direct', + 'bubblingType': 'bubble', + 'paperTopLevelNameDeprecated': 'paperBubblingEventDefinedInlineWithPaperName', 'typeAnnotation': { 'type': 'EventTypeAnnotation', 'argument': { @@ -3305,641 +3311,399 @@ exports[`RN Codegen TypeScript Parser can generate fixture COMMANDS_EVENTS_TYPES } ] } - } - ] - } - } - }, - { - 'name': 'onDirectEventDefinedInlineWithPaperName', - 'optional': false, - 'bubblingType': 'direct', - 'paperTopLevelNameDeprecated': 'paperDirectEventDefinedInlineWithPaperName', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ + }, { - 'name': 'boolean_required', + 'name': 'boolean_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_key', + 'name': 'boolean_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_value', + 'name': 'boolean_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_both', + 'name': 'boolean_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'string_required', + 'name': 'string_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_key', + 'name': 'string_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_value', + 'name': 'string_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_both', + 'name': 'string_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'double_required', + 'name': 'double_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_key', + 'name': 'double_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_value', + 'name': 'double_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_both', + 'name': 'double_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'float_required', + 'name': 'float_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_key', + 'name': 'float_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_value', + 'name': 'float_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_both', + 'name': 'float_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'int32_required', + 'name': 'int32_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_key', + 'name': 'int32_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_value', + 'name': 'int32_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_both', + 'name': 'int32_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'enum_required', + 'name': 'enum_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_key', + 'name': 'enum_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_value', + 'name': 'enum_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_both', + 'name': 'enum_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'object_required', + 'name': 'object_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } - } - ] - } - }, - { - 'name': 'object_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_value', + 'name': 'object_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_both', + 'name': 'object_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_required_nested_2_layers', - 'optional': false, + 'name': 'object_array_optional_both', + 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'object_optional_nested_1_layer', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - }, - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } - }, - { - 'name': 'double_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' - } - }, - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } - }, - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - } - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_readonly_required', + 'name': 'int32_array_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_key', + 'name': 'int32_array_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_value', + 'name': 'int32_array_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_both', + 'name': 'int32_array_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } } ] } } - } - ], - 'props': [], - 'commands': [ - { - 'name': 'scrollTo', - 'optional': false, - 'typeAnnotation': { - 'type': 'FunctionTypeAnnotation', - 'params': [ - { - 'name': 'y', - 'optional': false, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - }, - { - 'name': 'animated', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } - } - ], - 'returnTypeAnnotation': { - 'type': 'VoidTypeAnnotation' - } - } - } - ] - } - } - } - } -}" -`; - -exports[`RN Codegen TypeScript Parser can generate fixture COMMANDS_WITH_EXTERNAL_TYPES 1`] = ` -"{ - 'modules': { - 'Module': { - 'type': 'Component', - 'components': { - 'Module': { - 'extendsProps': [ - { - 'type': 'ReactNativeBuiltInType', - 'knownTypeName': 'ReactNativeCoreViewProps' - } - ], - 'events': [], - 'props': [], - 'commands': [ + }, { - 'name': 'scrollTo', + 'name': 'onDirectEventDefinedInline', 'optional': false, - 'typeAnnotation': { - 'type': 'FunctionTypeAnnotation', - 'params': [ - { - 'name': 'y', - 'optional': false, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - }, - { - 'name': 'animated', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } - } - ], - 'returnTypeAnnotation': { - 'type': 'VoidTypeAnnotation' - } - } - } - ] - } - } - } - } -}" -`; - -exports[`RN Codegen TypeScript Parser can generate fixture EVENTS_DEFINED_AS_NULL_INLINE 1`] = ` -"{ - 'modules': { - 'Module': { - 'type': 'Component', - 'components': { - 'Module': { - 'extendsProps': [ - { - 'type': 'ReactNativeBuiltInType', - 'knownTypeName': 'ReactNativeCoreViewProps' - } - ], - 'events': [ - { - 'name': 'onDirectEventDefinedInlineNull', - 'optional': false, - 'bubblingType': 'direct', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - }, - { - 'name': 'onDirectEventDefinedInlineNullOptionalKey', - 'optional': true, - 'bubblingType': 'direct', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - }, - { - 'name': 'onDirectEventDefinedInlineNullOptionalValue', - 'optional': true, - 'bubblingType': 'direct', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - }, - { - 'name': 'onDirectEventDefinedInlineNullOptionalBoth', - 'optional': true, - 'bubblingType': 'direct', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - }, - { - 'name': 'onDirectEventDefinedInlineNullWithPaperName', - 'optional': true, - 'bubblingType': 'direct', - 'paperTopLevelNameDeprecated': 'paperDirectEventDefinedInlineNullWithPaperName', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - }, - { - 'name': 'onBubblingEventDefinedInlineNull', - 'optional': false, - 'bubblingType': 'bubble', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - }, - { - 'name': 'onBubblingEventDefinedInlineNullOptionalKey', - 'optional': true, - 'bubblingType': 'bubble', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - }, - { - 'name': 'onBubblingEventDefinedInlineNullOptionalValue', - 'optional': true, - 'bubblingType': 'bubble', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - }, - { - 'name': 'onBubblingEventDefinedInlineNullOptionalBoth', - 'optional': true, - 'bubblingType': 'bubble', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - }, - { - 'name': 'onBubblingEventDefinedInlineNullWithPaperName', - 'optional': true, - 'bubblingType': 'bubble', - 'paperTopLevelNameDeprecated': 'paperBubblingEventDefinedInlineNullWithPaperName', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - } - ], - 'props': [], - 'commands': [] - } - } - } - } -}" -`; - -exports[`RN Codegen TypeScript Parser can generate fixture EVENTS_DEFINED_INLINE_WITH_ALL_TYPES 1`] = ` -"{ - 'modules': { - 'Module': { - 'type': 'Component', - 'components': { - 'Module': { - 'extendsProps': [ - { - 'type': 'ReactNativeBuiltInType', - 'knownTypeName': 'ReactNativeCoreViewProps' - } - ], - 'events': [ - { - 'name': 'onDirectEventDefinedInline', - 'optional': false, - 'bubblingType': 'direct', + 'bubblingType': 'direct', 'typeAnnotation': { 'type': 'EventTypeAnnotation', 'argument': { @@ -4309,383 +4073,389 @@ exports[`RN Codegen TypeScript Parser can generate fixture EVENTS_DEFINED_INLINE } ] } - } - ] - } - } - }, - { - 'name': 'onDirectEventDefinedInlineOptionalKey', - 'optional': true, - 'bubblingType': 'direct', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ + }, { - 'name': 'boolean_required', + 'name': 'boolean_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_key', + 'name': 'boolean_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_value', + 'name': 'boolean_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_both', + 'name': 'boolean_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'string_required', + 'name': 'string_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_key', + 'name': 'string_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_value', + 'name': 'string_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_both', + 'name': 'string_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'double_required', + 'name': 'double_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_key', + 'name': 'double_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_value', + 'name': 'double_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_both', + 'name': 'double_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'float_required', + 'name': 'float_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_key', + 'name': 'float_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_value', + 'name': 'float_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_both', + 'name': 'float_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'int32_required', + 'name': 'int32_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_key', + 'name': 'int32_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_value', + 'name': 'int32_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_both', + 'name': 'int32_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'enum_required', + 'name': 'enum_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_key', + 'name': 'enum_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_value', + 'name': 'enum_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_both', + 'name': 'enum_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'object_required', + 'name': 'object_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_key', + 'name': 'object_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_value', + 'name': 'object_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_both', + 'name': 'object_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - } - ] - } - }, - { - 'name': 'object_required_nested_2_layers', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'object_optional_nested_1_layer', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - }, - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } - }, - { - 'name': 'double_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' - } - }, - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } - }, - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - } - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_readonly_required', + 'name': 'int32_array_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_key', + 'name': 'int32_array_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_value', + 'name': 'int32_array_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_both', + 'name': 'int32_array_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } } ] @@ -4693,9 +4463,10 @@ exports[`RN Codegen TypeScript Parser can generate fixture EVENTS_DEFINED_INLINE } }, { - 'name': 'onDirectEventDefinedInlineOptionalValue', - 'optional': true, + 'name': 'onDirectEventDefinedInlineWithPaperName', + 'optional': false, 'bubblingType': 'direct', + 'paperTopLevelNameDeprecated': 'paperDirectEventDefinedInlineWithPaperName', 'typeAnnotation': { 'type': 'EventTypeAnnotation', 'argument': { @@ -5065,447 +4836,699 @@ exports[`RN Codegen TypeScript Parser can generate fixture EVENTS_DEFINED_INLINE } ] } - } - ] - } - } - }, - { - 'name': 'onDirectEventDefinedInlineOptionalBoth', - 'optional': true, - 'bubblingType': 'direct', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ + }, { - 'name': 'boolean_required', + 'name': 'boolean_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_key', + 'name': 'boolean_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_value', + 'name': 'boolean_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_both', + 'name': 'boolean_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'string_required', + 'name': 'string_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_key', + 'name': 'string_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_value', + 'name': 'string_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_both', + 'name': 'string_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'double_required', + 'name': 'double_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_key', + 'name': 'double_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_value', + 'name': 'double_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_both', + 'name': 'double_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'float_required', + 'name': 'float_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_key', + 'name': 'float_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_value', + 'name': 'float_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_both', + 'name': 'float_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'int32_required', + 'name': 'int32_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_key', + 'name': 'int32_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_value', + 'name': 'int32_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_both', + 'name': 'int32_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'enum_required', + 'name': 'enum_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_key', + 'name': 'enum_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_value', + 'name': 'enum_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_both', + 'name': 'enum_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'object_required', + 'name': 'object_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_key', + 'name': 'object_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_value', + 'name': 'object_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_both', + 'name': 'object_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_required_nested_2_layers', + 'name': 'int32_array_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'object_optional_nested_1_layer', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - }, - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } - }, - { - 'name': 'double_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' - } - }, - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } - }, - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - } - ] - } - } - ] - } - }, - { - 'name': 'object_readonly_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_key', + 'name': 'int32_array_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_value', + 'name': 'int32_array_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_both', + 'name': 'int32_array_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } } ] } } + } + ], + 'props': [], + 'commands': [ + { + 'name': 'scrollTo', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'params': [ + { + 'name': 'y', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'animated', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ], + 'returnTypeAnnotation': { + 'type': 'VoidTypeAnnotation' + } + } + } + ] + } + } + } + } +}" +`; + +exports[`RN Codegen TypeScript Parser can generate fixture COMMANDS_WITH_EXTERNAL_TYPES 1`] = ` +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'extendsProps': [ + { + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } + ], + 'events': [], + 'props': [], + 'commands': [ + { + 'name': 'scrollTo', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'params': [ + { + 'name': 'y', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'animated', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ], + 'returnTypeAnnotation': { + 'type': 'VoidTypeAnnotation' + } + } + } + ] + } + } + } + } +}" +`; + +exports[`RN Codegen TypeScript Parser can generate fixture EVENTS_DEFINED_AS_NULL_INLINE 1`] = ` +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'extendsProps': [ + { + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } + ], + 'events': [ + { + 'name': 'onDirectEventDefinedInlineNull', + 'optional': false, + 'bubblingType': 'direct', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } }, { - 'name': 'onDirectEventDefinedInlineWithPaperName', + 'name': 'onDirectEventDefinedInlineNullOptionalKey', 'optional': true, 'bubblingType': 'direct', - 'paperTopLevelNameDeprecated': 'paperDirectEventDefinedInlineWithPaperName', 'typeAnnotation': { 'type': 'EventTypeAnnotation', 'argument': { 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } - }, - { - 'name': 'boolean_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } - }, - { - 'name': 'boolean_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } - }, - { - 'name': 'boolean_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } - }, - { - 'name': 'string_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } - }, - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } - }, - { - 'name': 'string_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } + 'properties': [] + } + } + }, + { + 'name': 'onDirectEventDefinedInlineNullOptionalValue', + 'optional': true, + 'bubblingType': 'direct', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onDirectEventDefinedInlineNullOptionalBoth', + 'optional': true, + 'bubblingType': 'direct', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onDirectEventDefinedInlineNullWithPaperName', + 'optional': true, + 'bubblingType': 'direct', + 'paperTopLevelNameDeprecated': 'paperDirectEventDefinedInlineNullWithPaperName', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineNull', + 'optional': false, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineNullOptionalKey', + 'optional': true, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineNullOptionalValue', + 'optional': true, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineNullOptionalBoth', + 'optional': true, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineNullWithPaperName', + 'optional': true, + 'bubblingType': 'bubble', + 'paperTopLevelNameDeprecated': 'paperBubblingEventDefinedInlineNullWithPaperName', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + } + ], + 'props': [], + 'commands': [] + } + } + } + } +}" +`; + +exports[`RN Codegen TypeScript Parser can generate fixture EVENTS_DEFINED_INLINE_WITH_ALL_TYPES 1`] = ` +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'extendsProps': [ + { + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } + ], + 'events': [ + { + 'name': 'onDirectEventDefinedInline', + 'optional': false, + 'bubblingType': 'direct', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } }, { 'name': 'string_optional_both', @@ -5822,383 +5845,389 @@ exports[`RN Codegen TypeScript Parser can generate fixture EVENTS_DEFINED_INLINE } ] } - } - ] - } - } - }, - { - 'name': 'onBubblingEventDefinedInline', - 'optional': false, - 'bubblingType': 'bubble', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ + }, { - 'name': 'boolean_required', + 'name': 'boolean_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_key', + 'name': 'boolean_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_value', + 'name': 'boolean_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_both', + 'name': 'boolean_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'string_required', + 'name': 'string_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_key', + 'name': 'string_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_value', + 'name': 'string_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_both', + 'name': 'string_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'double_required', + 'name': 'double_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_key', + 'name': 'double_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_value', + 'name': 'double_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_both', + 'name': 'double_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } }, { - 'name': 'float_required', + 'name': 'float_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_key', + 'name': 'float_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_value', + 'name': 'float_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_both', + 'name': 'float_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'int32_required', + 'name': 'int32_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_key', + 'name': 'int32_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_value', + 'name': 'int32_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_both', + 'name': 'int32_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'enum_required', + 'name': 'enum_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_key', + 'name': 'enum_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_value', + 'name': 'enum_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_both', + 'name': 'enum_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'object_required', + 'name': 'object_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_key', + 'name': 'object_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_value', + 'name': 'object_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_both', + 'name': 'object_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_required_nested_2_layers', + 'name': 'int32_array_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'object_optional_nested_1_layer', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - }, - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } - }, - { - 'name': 'double_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' - } - }, - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } - }, - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - } - ] - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_required', - 'optional': false, + 'name': 'int32_array_array_optional_key', + 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_key', + 'name': 'int32_array_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_value', + 'name': 'int32_array_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] - } - }, - { - 'name': 'object_readonly_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - } - ] + } } } ] @@ -6206,9 +6235,9 @@ exports[`RN Codegen TypeScript Parser can generate fixture EVENTS_DEFINED_INLINE } }, { - 'name': 'onBubblingEventDefinedInlineOptionalKey', + 'name': 'onDirectEventDefinedInlineOptionalKey', 'optional': true, - 'bubblingType': 'bubble', + 'bubblingType': 'direct', 'typeAnnotation': { 'type': 'EventTypeAnnotation', 'argument': { @@ -6578,383 +6607,389 @@ exports[`RN Codegen TypeScript Parser can generate fixture EVENTS_DEFINED_INLINE } ] } - } - ] - } - } - }, - { - 'name': 'onBubblingEventDefinedInlineOptionalValue', - 'optional': true, - 'bubblingType': 'bubble', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ + }, { - 'name': 'boolean_required', + 'name': 'boolean_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_key', + 'name': 'boolean_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_value', + 'name': 'boolean_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_both', + 'name': 'boolean_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'string_required', + 'name': 'string_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_key', + 'name': 'string_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_value', + 'name': 'string_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_both', + 'name': 'string_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'double_required', + 'name': 'double_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_key', + 'name': 'double_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_value', + 'name': 'double_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_both', + 'name': 'double_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'float_required', + 'name': 'float_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_key', + 'name': 'float_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_value', + 'name': 'float_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_both', + 'name': 'float_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'int32_required', + 'name': 'int32_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_key', + 'name': 'int32_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_value', + 'name': 'int32_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_both', + 'name': 'int32_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'enum_required', + 'name': 'enum_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_key', + 'name': 'enum_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_value', + 'name': 'enum_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_both', + 'name': 'enum_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'object_required', + 'name': 'object_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_key', + 'name': 'object_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_value', + 'name': 'object_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_both', + 'name': 'object_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_required_nested_2_layers', + 'name': 'int32_array_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'object_optional_nested_1_layer', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - }, - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } - }, - { - 'name': 'double_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' - } - }, - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } - }, - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - } - ] - } - } - ] - } - }, - { - 'name': 'object_readonly_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_key', + 'name': 'int32_array_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_value', + 'name': 'int32_array_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_both', + 'name': 'int32_array_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } } ] @@ -6962,9 +6997,9 @@ exports[`RN Codegen TypeScript Parser can generate fixture EVENTS_DEFINED_INLINE } }, { - 'name': 'onBubblingEventDefinedInlineOptionalBoth', + 'name': 'onDirectEventDefinedInlineOptionalValue', 'optional': true, - 'bubblingType': 'bubble', + 'bubblingType': 'direct', 'typeAnnotation': { 'type': 'EventTypeAnnotation', 'argument': { @@ -7334,720 +7369,6231 @@ exports[`RN Codegen TypeScript Parser can generate fixture EVENTS_DEFINED_INLINE } ] } - } - ] - } - } - }, - { - 'name': 'onBubblingEventDefinedInlineWithPaperName', - 'optional': true, - 'bubblingType': 'bubble', - 'paperTopLevelNameDeprecated': 'paperBubblingEventDefinedInlineWithPaperName', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ + }, { - 'name': 'boolean_required', + 'name': 'boolean_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_key', + 'name': 'boolean_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_value', + 'name': 'boolean_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_both', + 'name': 'boolean_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'string_required', + 'name': 'string_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_key', + 'name': 'string_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_value', + 'name': 'string_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_both', + 'name': 'string_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'double_required', + 'name': 'double_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_key', + 'name': 'double_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_value', + 'name': 'double_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_both', + 'name': 'double_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'float_required', + 'name': 'float_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_key', + 'name': 'float_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_value', + 'name': 'float_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_both', + 'name': 'float_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'int32_required', + 'name': 'int32_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_key', + 'name': 'int32_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_value', + 'name': 'int32_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_both', + 'name': 'int32_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'enum_required', + 'name': 'enum_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_key', + 'name': 'enum_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_value', + 'name': 'enum_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_both', + 'name': 'enum_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'object_required', + 'name': 'object_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_key', + 'name': 'object_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_value', + 'name': 'object_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_both', + 'name': 'object_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - } - ] - } - }, - { - 'name': 'object_required_nested_2_layers', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'object_optional_nested_1_layer', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - }, - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } - }, - { - 'name': 'double_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' - } - }, - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } - }, - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - } - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_readonly_required', + 'name': 'int32_array_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_key', + 'name': 'int32_array_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_value', + 'name': 'int32_array_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_both', + 'name': 'int32_array_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } } ] } } - } - ], - 'props': [], - 'commands': [] - } - } - } - } -}" -`; - -exports[`RN Codegen TypeScript Parser can generate fixture NO_PROPS_EVENTS_ONLY_DEPRECATED_VIEW_CONFIG_NAME_OPTION 1`] = ` -"{ - 'modules': { - 'Module': { - 'type': 'Component', - 'components': { - 'Module': { - 'deprecatedViewConfigName': 'DeprecateModuleName', - 'extendsProps': [ - { - 'type': 'ReactNativeBuiltInType', - 'knownTypeName': 'ReactNativeCoreViewProps' - } - ], - 'events': [], - 'props': [], - 'commands': [] - } - } - } - } -}" -`; - -exports[`RN Codegen TypeScript Parser can generate fixture OBJECT_PROP_TYPES_NO_EVENTS 1`] = ` -"{ - 'modules': { - 'Module': { - 'type': 'Component', - 'components': { - 'Module': { - 'extendsProps': [ - { - 'type': 'ReactNativeBuiltInType', - 'knownTypeName': 'ReactNativeCoreViewProps' - } - ], - 'events': [], - 'props': [ + }, { - 'name': 'boolean_required', - 'optional': false, + 'name': 'onDirectEventDefinedInlineOptionalBoth', + 'optional': true, + 'bubblingType': 'direct', 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation', - 'default': false - } - } - ] - } - }, - { - 'name': 'boolean_optional', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': true, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation', - 'default': false - } - } - ] - } - }, - { - 'name': 'string_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': false, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation', - 'default': null - } - } - ] - } - }, - { - 'name': 'string_optional', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation', - 'default': '' - } - } - ] - } - }, - { - 'name': 'double_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': false, - 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation', - 'default': 0 - } - } - ] - } - }, - { - 'name': 'double_optional', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': true, - 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation', - 'default': 0 - } - } - ] - } - }, - { - 'name': 'float_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': false, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation', - 'default': 0 - } - } - ] - } - }, - { - 'name': 'float_optional', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation', - 'default': 0 - } - } - ] - } - }, - { - 'name': 'int_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': false, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation', - 'default': 0 - } - } - ] - } - }, - { - 'name': 'int_optional', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation', - 'default': 0 - } - } - ] - } - }, - { - 'name': 'enum_optional', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': true, - 'typeAnnotation': { - 'type': 'ArrayTypeAnnotation', - 'elementType': { - 'type': 'StringEnumTypeAnnotation', - 'default': 'small', - 'options': [ - 'small', - 'large' - ] + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' } - } - } - ] - } - }, - { - 'name': 'image_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': false, - 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'ImageSourcePrimitive' - } - } - ] - } - }, - { - 'name': 'image_optional_key', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': true, - 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'ImageSourcePrimitive' - } - } - ] - } - }, - { - 'name': 'image_optional_value', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': true, - 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'ImageSourcePrimitive' - } - } - ] - } - }, - { - 'name': 'image_optional_both', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': true, - 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'ImageSourcePrimitive' - } - } - ] + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'boolean_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'string_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'double_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'float_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'int32_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'enum_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'object_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'int32_array_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + } + ] + } + } + }, + { + 'name': 'onDirectEventDefinedInlineWithPaperName', + 'optional': true, + 'bubblingType': 'direct', + 'paperTopLevelNameDeprecated': 'paperDirectEventDefinedInlineWithPaperName', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'boolean_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'string_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'double_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'float_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'int32_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'enum_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'object_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'int32_array_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + } + ] + } + } + }, + { + 'name': 'onBubblingEventDefinedInline', + 'optional': false, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'boolean_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'string_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'double_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'float_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'int32_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'enum_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'object_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'int32_array_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + } + ] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineOptionalKey', + 'optional': true, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'boolean_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'string_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'double_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'float_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'int32_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'enum_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'object_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'int32_array_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + } + ] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineOptionalValue', + 'optional': true, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'boolean_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'string_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'double_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'float_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'int32_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'enum_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'object_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'int32_array_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + } + ] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineOptionalBoth', + 'optional': true, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'boolean_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'string_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'double_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'float_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'int32_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'enum_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'object_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'int32_array_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + } + ] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineWithPaperName', + 'optional': true, + 'bubblingType': 'bubble', + 'paperTopLevelNameDeprecated': 'paperBubblingEventDefinedInlineWithPaperName', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'boolean_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'string_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'double_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'float_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'int32_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'enum_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'object_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'int32_array_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + } + ] + } + } + } + ], + 'props': [], + 'commands': [] + } + } + } + } +}" +`; + +exports[`RN Codegen TypeScript Parser can generate fixture NO_PROPS_EVENTS_ONLY_DEPRECATED_VIEW_CONFIG_NAME_OPTION 1`] = ` +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'deprecatedViewConfigName': 'DeprecateModuleName', + 'extendsProps': [ + { + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } + ], + 'events': [], + 'props': [], + 'commands': [] + } + } + } + } +}" +`; + +exports[`RN Codegen TypeScript Parser can generate fixture OBJECT_PROP_TYPES_NO_EVENTS 1`] = ` +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'extendsProps': [ + { + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } + ], + 'events': [], + 'props': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation', + 'default': false + } + } + ] + } + }, + { + 'name': 'boolean_optional', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation', + 'default': false + } + } + ] + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] + } + }, + { + 'name': 'string_optional', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': '' + } + } + ] + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation', + 'default': 0 + } + } + ] + } + }, + { + 'name': 'double_optional', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation', + 'default': 0 + } + } + ] + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation', + 'default': 0 + } + } + ] + } + }, + { + 'name': 'float_optional', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation', + 'default': 0 + } + } + ] + } + }, + { + 'name': 'int_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation', + 'default': 0 + } + } + ] + } + }, + { + 'name': 'int_optional', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation', + 'default': 0 + } + } + ] + } + }, + { + 'name': 'enum_optional', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'default': 'small', + 'options': [ + 'small', + 'large' + ] + } + } + } + ] + } + }, + { + 'name': 'image_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ImageSourcePrimitive' + } + } + ] + } + }, + { + 'name': 'image_optional_key', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ImageSourcePrimitive' + } + } + ] + } + }, + { + 'name': 'image_optional_value', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ImageSourcePrimitive' + } + } + ] + } + }, + { + 'name': 'image_optional_both', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ImageSourcePrimitive' + } + } + ] + } + }, + { + 'name': 'color_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + ] + } + }, + { + 'name': 'color_optional_key', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + ] + } + }, + { + 'name': 'color_optional_value', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + ] + } + }, + { + 'name': 'color_optional_both', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + ] + } + }, + { + 'name': 'processed_color_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + ] + } + }, + { + 'name': 'processed_color_optional_key', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + ] + } + }, + { + 'name': 'processed_color_optional_value', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + ] + } + }, + { + 'name': 'processed_color_optional_both', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + ] + } + }, + { + 'name': 'point_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'PointPrimitive' + } + } + ] + } + }, + { + 'name': 'point_optional_key', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'PointPrimitive' + } + } + ] } }, { - 'name': 'color_required', + 'name': 'point_optional_value', 'optional': false, 'typeAnnotation': { 'type': 'ObjectTypeAnnotation', 'properties': [ { 'name': 'prop', - 'optional': false, + 'optional': true, 'typeAnnotation': { 'type': 'ReservedPropTypeAnnotation', - 'name': 'ColorPrimitive' + 'name': 'PointPrimitive' } } ] } }, { - 'name': 'color_optional_key', + 'name': 'point_optional_both', 'optional': false, 'typeAnnotation': { 'type': 'ObjectTypeAnnotation', @@ -8057,31 +13603,31 @@ exports[`RN Codegen TypeScript Parser can generate fixture OBJECT_PROP_TYPES_NO_ 'optional': true, 'typeAnnotation': { 'type': 'ReservedPropTypeAnnotation', - 'name': 'ColorPrimitive' + 'name': 'PointPrimitive' } } ] } }, { - 'name': 'color_optional_value', + 'name': 'insets_required', 'optional': false, 'typeAnnotation': { 'type': 'ObjectTypeAnnotation', 'properties': [ { 'name': 'prop', - 'optional': true, + 'optional': false, 'typeAnnotation': { 'type': 'ReservedPropTypeAnnotation', - 'name': 'ColorPrimitive' + 'name': 'EdgeInsetsPrimitive' } } ] } }, { - 'name': 'color_optional_both', + 'name': 'insets_optional_key', 'optional': false, 'typeAnnotation': { 'type': 'ObjectTypeAnnotation', @@ -8091,31 +13637,31 @@ exports[`RN Codegen TypeScript Parser can generate fixture OBJECT_PROP_TYPES_NO_ 'optional': true, 'typeAnnotation': { 'type': 'ReservedPropTypeAnnotation', - 'name': 'ColorPrimitive' + 'name': 'EdgeInsetsPrimitive' } } ] } }, { - 'name': 'processed_color_required', + 'name': 'insets_optional_value', 'optional': false, 'typeAnnotation': { 'type': 'ObjectTypeAnnotation', 'properties': [ { 'name': 'prop', - 'optional': false, + 'optional': true, 'typeAnnotation': { 'type': 'ReservedPropTypeAnnotation', - 'name': 'ColorPrimitive' + 'name': 'EdgeInsetsPrimitive' } } ] } }, { - 'name': 'processed_color_optional_key', + 'name': 'insets_optional_both', 'optional': false, 'typeAnnotation': { 'type': 'ObjectTypeAnnotation', @@ -8125,31 +13671,31 @@ exports[`RN Codegen TypeScript Parser can generate fixture OBJECT_PROP_TYPES_NO_ 'optional': true, 'typeAnnotation': { 'type': 'ReservedPropTypeAnnotation', - 'name': 'ColorPrimitive' + 'name': 'EdgeInsetsPrimitive' } } ] } }, { - 'name': 'processed_color_optional_value', + 'name': 'dimension_required', 'optional': false, 'typeAnnotation': { 'type': 'ObjectTypeAnnotation', 'properties': [ { 'name': 'prop', - 'optional': true, + 'optional': false, 'typeAnnotation': { 'type': 'ReservedPropTypeAnnotation', - 'name': 'ColorPrimitive' + 'name': 'DimensionPrimitive' } } ] } }, { - 'name': 'processed_color_optional_both', + 'name': 'dimension_optional_key', 'optional': false, 'typeAnnotation': { 'type': 'ObjectTypeAnnotation', @@ -8159,31 +13705,31 @@ exports[`RN Codegen TypeScript Parser can generate fixture OBJECT_PROP_TYPES_NO_ 'optional': true, 'typeAnnotation': { 'type': 'ReservedPropTypeAnnotation', - 'name': 'ColorPrimitive' + 'name': 'DimensionPrimitive' } } ] } }, { - 'name': 'point_required', + 'name': 'dimension_optional_value', 'optional': false, 'typeAnnotation': { 'type': 'ObjectTypeAnnotation', 'properties': [ { 'name': 'prop', - 'optional': false, + 'optional': true, 'typeAnnotation': { 'type': 'ReservedPropTypeAnnotation', - 'name': 'PointPrimitive' + 'name': 'DimensionPrimitive' } } ] } }, { - 'name': 'point_optional_key', + 'name': 'dimension_optional_both', 'optional': false, 'typeAnnotation': { 'type': 'ObjectTypeAnnotation', @@ -8193,551 +13739,1906 @@ exports[`RN Codegen TypeScript Parser can generate fixture OBJECT_PROP_TYPES_NO_ 'optional': true, 'typeAnnotation': { 'type': 'ReservedPropTypeAnnotation', - 'name': 'PointPrimitive' + 'name': 'DimensionPrimitive' } } ] } }, { - 'name': 'point_optional_value', + 'name': 'object_required', 'optional': false, 'typeAnnotation': { 'type': 'ObjectTypeAnnotation', 'properties': [ { 'name': 'prop', - 'optional': true, + 'optional': false, 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'PointPrimitive' + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'nestedProp', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] } } ] } }, { - 'name': 'point_optional_both', - 'optional': false, + 'name': 'object_optional_key', + 'optional': true, 'typeAnnotation': { 'type': 'ObjectTypeAnnotation', 'properties': [ { 'name': 'prop', - 'optional': true, + 'optional': false, 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'PointPrimitive' + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'nestedProp', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'nestedProp', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'nestedProp', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] } } ] } - }, + } + ], + 'commands': [] + } + } + } + } +}" +`; + +exports[`RN Codegen TypeScript Parser can generate fixture ONE_OF_EACH_PROP_EVENT_DEFAULT_AND_OPTIONS 1`] = ` +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'interfaceOnly': true, + 'paperComponentName': 'RCTModule', + 'extendsProps': [ + { + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } + ], + 'events': [ + { + 'name': 'onDirectEventDefinedInlineNull', + 'optional': false, + 'bubblingType': 'direct', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineNull', + 'optional': false, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + } + ], + 'props': [ + { + 'name': 'boolean_default_true_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation', + 'default': true + } + } + ], + 'commands': [] + } + } + } + } +}" +`; + +exports[`RN Codegen TypeScript Parser can generate fixture ONE_OF_EACH_PROP_EVENT_DEFAULT_AND_OPTIONS_NO_CAST 1`] = ` +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'interfaceOnly': true, + 'excludedPlatforms': [ + 'android' + ], + 'paperComponentName': 'RCTModule', + 'extendsProps': [ + { + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } + ], + 'events': [ + { + 'name': 'onDirectEventDefinedInlineNull', + 'optional': false, + 'bubblingType': 'direct', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineNull', + 'optional': false, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + } + ], + 'props': [ + { + 'name': 'boolean_default_true_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation', + 'default': true + } + } + ], + 'commands': [] + } + } + } + } +}" +`; + +exports[`RN Codegen TypeScript Parser can generate fixture PROPS_ALIASED_LOCALLY 1`] = ` +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'extendsProps': [ { - 'name': 'insets_required', + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } + ], + 'events': [], + 'props': [ + { + 'name': 'otherStringProp', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': false, - 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'EdgeInsetsPrimitive' - } - } - ] + 'type': 'StringTypeAnnotation', + 'default': null } }, { - 'name': 'insets_optional_key', + 'name': 'isEnabled', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': true, - 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'EdgeInsetsPrimitive' - } - } - ] + 'type': 'BooleanTypeAnnotation', + 'default': false } }, { - 'name': 'insets_optional_value', + 'name': 'label', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': true, - 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'EdgeInsetsPrimitive' - } - } - ] + 'type': 'StringTypeAnnotation', + 'default': null } }, { - 'name': 'insets_optional_both', + 'name': 'localType', 'optional': false, 'typeAnnotation': { 'type': 'ObjectTypeAnnotation', 'properties': [ { - 'name': 'prop', - 'optional': true, + 'name': 'otherStringProp', + 'optional': false, 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'EdgeInsetsPrimitive' + 'type': 'StringTypeAnnotation', + 'default': null } - } - ] - } - }, - { - 'name': 'dimension_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ + }, { - 'name': 'prop', + 'name': 'isEnabled', 'optional': false, 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'DimensionPrimitive' + 'type': 'BooleanTypeAnnotation', + 'default': false } - } - ] - } - }, - { - 'name': 'dimension_optional_key', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ + }, { - 'name': 'prop', - 'optional': true, + 'name': 'label', + 'optional': false, 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'DimensionPrimitive' + 'type': 'StringTypeAnnotation', + 'default': null } } ] } }, { - 'name': 'dimension_optional_value', + 'name': 'localArr', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': true, - 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'DimensionPrimitive' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'otherStringProp', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + }, + { + 'name': 'isEnabled', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation', + 'default': false + } + }, + { + 'name': 'label', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } } - } - ] + ] + } } - }, + } + ], + 'commands': [] + } + } + } + } +}" +`; + +exports[`RN Codegen TypeScript Parser can generate fixture PROPS_AND_EVENTS_TYPES_EXPORTED 1`] = ` +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'extendsProps': [ { - 'name': 'dimension_optional_both', + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } + ], + 'events': [ + { + 'name': 'onBubblingEventDefinedInline', 'optional': false, + 'bubblingType': 'bubble', 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': true, - 'typeAnnotation': { - 'type': 'ReservedPropTypeAnnotation', - 'name': 'DimensionPrimitive' + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'boolean_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'string_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'double_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'float_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'int32_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'enum_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'object_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'int32_array_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } } - } - ] + ] + } } }, { - 'name': 'object_required', + 'name': 'onBubblingEventDefinedInlineWithPaperName', 'optional': false, + 'bubblingType': 'bubble', + 'paperTopLevelNameDeprecated': 'paperBubblingEventDefinedInlineWithPaperName', 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'nestedProp', - 'optional': false, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation', - 'default': null + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } } + ] + } + }, + { + 'name': 'boolean_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'boolean_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' } - ] - } - } - ] - } - }, - { - 'name': 'object_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'nestedProp', - 'optional': false, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation', - 'default': null - } + } + }, + { + 'name': 'string_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' } - ] - } - } - ] - } - }, - { - 'name': 'object_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'nestedProp', - 'optional': false, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation', - 'default': null - } + } + }, + { + 'name': 'string_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' } - ] - } - } - ] - } - }, - { - 'name': 'object_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'prop', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'nestedProp', - 'optional': false, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation', - 'default': null - } + } + }, + { + 'name': 'string_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'string_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'double_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'double_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'float_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'float_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'int32_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'int32_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'enum_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'enum_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'object_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] } - ] - } - } - ] - } - } - ], - 'commands': [] - } - } - } - } -}" -`; - -exports[`RN Codegen TypeScript Parser can generate fixture ONE_OF_EACH_PROP_EVENT_DEFAULT_AND_OPTIONS 1`] = ` -"{ - 'modules': { - 'Module': { - 'type': 'Component', - 'components': { - 'Module': { - 'interfaceOnly': true, - 'paperComponentName': 'RCTModule', - 'extendsProps': [ - { - 'type': 'ReactNativeBuiltInType', - 'knownTypeName': 'ReactNativeCoreViewProps' - } - ], - 'events': [ - { - 'name': 'onDirectEventDefinedInlineNull', - 'optional': false, - 'bubblingType': 'direct', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - }, - { - 'name': 'onBubblingEventDefinedInlineNull', - 'optional': false, - 'bubblingType': 'bubble', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - } - ], - 'props': [ - { - 'name': 'boolean_default_true_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation', - 'default': true - } - } - ], - 'commands': [] - } - } - } - } -}" -`; - -exports[`RN Codegen TypeScript Parser can generate fixture ONE_OF_EACH_PROP_EVENT_DEFAULT_AND_OPTIONS_NO_CAST 1`] = ` -"{ - 'modules': { - 'Module': { - 'type': 'Component', - 'components': { - 'Module': { - 'interfaceOnly': true, - 'excludedPlatforms': [ - 'android' - ], - 'paperComponentName': 'RCTModule', - 'extendsProps': [ - { - 'type': 'ReactNativeBuiltInType', - 'knownTypeName': 'ReactNativeCoreViewProps' - } - ], - 'events': [ - { - 'name': 'onDirectEventDefinedInlineNull', - 'optional': false, - 'bubblingType': 'direct', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - }, - { - 'name': 'onBubblingEventDefinedInlineNull', - 'optional': false, - 'bubblingType': 'bubble', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [] - } - } - } - ], - 'props': [ - { - 'name': 'boolean_default_true_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation', - 'default': true - } - } - ], - 'commands': [] - } - } - } - } -}" -`; - -exports[`RN Codegen TypeScript Parser can generate fixture PROPS_ALIASED_LOCALLY 1`] = ` -"{ - 'modules': { - 'Module': { - 'type': 'Component', - 'components': { - 'Module': { - 'extendsProps': [ - { - 'type': 'ReactNativeBuiltInType', - 'knownTypeName': 'ReactNativeCoreViewProps' - } - ], - 'events': [], - 'props': [ - { - 'name': 'otherStringProp', - 'optional': false, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation', - 'default': null - } - }, - { - 'name': 'isEnabled', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation', - 'default': false - } - }, - { - 'name': 'label', - 'optional': false, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation', - 'default': null - } - }, - { - 'name': 'localType', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'otherStringProp', - 'optional': false, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation', - 'default': null - } - }, - { - 'name': 'isEnabled', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation', - 'default': false - } - }, - { - 'name': 'label', - 'optional': false, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation', - 'default': null - } - } - ] - } - }, - { - 'name': 'localArr', - 'optional': false, - 'typeAnnotation': { - 'type': 'ArrayTypeAnnotation', - 'elementType': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ + } + }, + { + 'name': 'object_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + } + }, + { + 'name': 'object_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + }, { - 'name': 'otherStringProp', + 'name': 'int32_array_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringTypeAnnotation', - 'default': null + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } } }, { - 'name': 'isEnabled', - 'optional': false, + 'name': 'int32_array_array_optional_key', + 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation', - 'default': false + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } } }, { - 'name': 'label', - 'optional': false, + 'name': 'int32_array_array_optional_value', + 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation', - 'default': null + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + } + }, + { + 'name': 'int32_array_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } } } ] } } - } - ], - 'commands': [] - } - } - } - } -}" -`; - -exports[`RN Codegen TypeScript Parser can generate fixture PROPS_AND_EVENTS_TYPES_EXPORTED 1`] = ` -"{ - 'modules': { - 'Module': { - 'type': 'Component', - 'components': { - 'Module': { - 'extendsProps': [ - { - 'type': 'ReactNativeBuiltInType', - 'knownTypeName': 'ReactNativeCoreViewProps' - } - ], - 'events': [ + }, { - 'name': 'onBubblingEventDefinedInline', + 'name': 'onDirectEventDefinedInline', 'optional': false, - 'bubblingType': 'bubble', + 'bubblingType': 'direct', 'typeAnnotation': { 'type': 'EventTypeAnnotation', 'argument': { @@ -9107,384 +16008,389 @@ exports[`RN Codegen TypeScript Parser can generate fixture PROPS_AND_EVENTS_TYPE } ] } - } - ] - } - } - }, - { - 'name': 'onBubblingEventDefinedInlineWithPaperName', - 'optional': false, - 'bubblingType': 'bubble', - 'paperTopLevelNameDeprecated': 'paperBubblingEventDefinedInlineWithPaperName', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ + }, { - 'name': 'boolean_required', + 'name': 'boolean_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_key', + 'name': 'boolean_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_value', + 'name': 'boolean_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_both', + 'name': 'boolean_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'string_required', + 'name': 'string_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_key', + 'name': 'string_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_value', + 'name': 'string_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_both', + 'name': 'string_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'double_required', + 'name': 'double_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_key', + 'name': 'double_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_value', + 'name': 'double_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_both', + 'name': 'double_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'float_required', + 'name': 'float_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_key', + 'name': 'float_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_value', + 'name': 'float_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_both', + 'name': 'float_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'int32_required', + 'name': 'int32_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_key', + 'name': 'int32_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_value', + 'name': 'int32_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_both', + 'name': 'int32_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'enum_required', + 'name': 'enum_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] - } - }, - { - 'name': 'enum_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_value', + 'name': 'enum_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_both', + 'name': 'enum_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] - } - }, - { - 'name': 'object_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } - } - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'object_optional_key', + 'name': 'enum_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'object_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_value', + 'name': 'object_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_both', + 'name': 'object_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_required_nested_2_layers', - 'optional': false, + 'name': 'object_array_optional_both', + 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'object_optional_nested_1_layer', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - }, - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } - }, - { - 'name': 'double_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' - } - }, - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } - }, - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - } - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_readonly_required', + 'name': 'int32_array_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_key', + 'name': 'int32_array_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_value', + 'name': 'int32_array_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_both', + 'name': 'int32_array_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } } ] @@ -9492,9 +16398,10 @@ exports[`RN Codegen TypeScript Parser can generate fixture PROPS_AND_EVENTS_TYPE } }, { - 'name': 'onDirectEventDefinedInline', + 'name': 'onDirectEventDefinedInlineWithPaperName', 'optional': false, 'bubblingType': 'direct', + 'paperTopLevelNameDeprecated': 'paperDirectEventDefinedInlineWithPaperName', 'typeAnnotation': { 'type': 'EventTypeAnnotation', 'argument': { @@ -9864,384 +16771,389 @@ exports[`RN Codegen TypeScript Parser can generate fixture PROPS_AND_EVENTS_TYPE } ] } - } - ] - } - } - }, - { - 'name': 'onDirectEventDefinedInlineWithPaperName', - 'optional': false, - 'bubblingType': 'direct', - 'paperTopLevelNameDeprecated': 'paperDirectEventDefinedInlineWithPaperName', - 'typeAnnotation': { - 'type': 'EventTypeAnnotation', - 'argument': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ + }, { - 'name': 'boolean_required', + 'name': 'boolean_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_key', + 'name': 'boolean_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_value', + 'name': 'boolean_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'boolean_optional_both', + 'name': 'boolean_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } } }, { - 'name': 'string_required', + 'name': 'string_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_key', + 'name': 'string_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_value', + 'name': 'string_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'string_optional_both', + 'name': 'string_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } } }, { - 'name': 'double_required', + 'name': 'double_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_key', + 'name': 'double_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_value', + 'name': 'double_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'double_optional_both', + 'name': 'double_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } } }, { - 'name': 'float_required', + 'name': 'float_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_key', + 'name': 'float_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_value', + 'name': 'float_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'float_optional_both', + 'name': 'float_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } } }, { - 'name': 'int32_required', + 'name': 'int32_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_key', + 'name': 'int32_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_value', + 'name': 'int32_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'int32_optional_both', + 'name': 'int32_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } } }, { - 'name': 'enum_required', + 'name': 'enum_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_key', + 'name': 'enum_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_value', + 'name': 'enum_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'enum_optional_both', + 'name': 'enum_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'StringEnumTypeAnnotation', - 'options': [ - 'small', - 'large' - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } } }, { - 'name': 'object_required', + 'name': 'object_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_key', + 'name': 'object_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_value', + 'name': 'object_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_optional_both', + 'name': 'object_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - } - ] - } - }, - { - 'name': 'object_required_nested_2_layers', - 'optional': false, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'object_optional_nested_1_layer', - 'optional': true, - 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - }, - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } - }, - { - 'name': 'double_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'DoubleTypeAnnotation' - } - }, - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } - }, - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } - } - ] + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } } - } - ] + ] + } } }, { - 'name': 'object_readonly_required', + 'name': 'int32_array_array_required', 'optional': false, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'boolean_required', - 'optional': false, - 'typeAnnotation': { - 'type': 'BooleanTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_key', + 'name': 'int32_array_array_optional_key', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'string_optional_key', - 'optional': true, - 'typeAnnotation': { - 'type': 'StringTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_value', + 'name': 'int32_array_array_optional_value', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'float_optional_value', - 'optional': true, - 'typeAnnotation': { - 'type': 'FloatTypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } }, { - 'name': 'object_readonly_optional_both', + 'name': 'int32_array_array_optional_both', 'optional': true, 'typeAnnotation': { - 'type': 'ObjectTypeAnnotation', - 'properties': [ - { - 'name': 'int32_optional_both', - 'optional': true, - 'typeAnnotation': { - 'type': 'Int32TypeAnnotation' - } + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' } - ] + } } } ] diff --git a/packages/react-native-codegen/src/parsers/typescript/components/componentsUtils.js b/packages/react-native-codegen/src/parsers/typescript/components/componentsUtils.js index 763b85b874ce8b..26b9bddaceac19 100644 --- a/packages/react-native-codegen/src/parsers/typescript/components/componentsUtils.js +++ b/packages/react-native-codegen/src/parsers/typescript/components/componentsUtils.js @@ -9,13 +9,12 @@ */ 'use strict'; -import type {ASTNode} from '../utils'; -import type {NamedShape} from '../../../CodegenSchema.js'; const { parseTopLevelType, flattenIntersectionType, } = require('../parseTopLevelType'); -import type {TypeDeclarationMap, PropAST} from '../../utils'; +import type {TypeDeclarationMap, PropAST, ASTNode} from '../../utils'; +import type {BuildSchemaFN, Parser} from '../../parser'; function getProperties( typeName: string, @@ -111,7 +110,8 @@ function detectArrayType( typeAnnotation: $FlowFixMe | ASTNode, defaultValue: $FlowFixMe | void, types: TypeDeclarationMap, - buildSchema: (property: PropAST, types: TypeDeclarationMap) => ?NamedShape, + parser: Parser, + buildSchema: BuildSchemaFN, ): $FlowFixMe { // Covers: readonly T[] if ( @@ -126,6 +126,7 @@ function detectArrayType( typeAnnotation.typeAnnotation.elementType, defaultValue, types, + parser, buildSchema, ), }; @@ -140,6 +141,7 @@ function detectArrayType( typeAnnotation.elementType, defaultValue, types, + parser, buildSchema, ), }; @@ -158,6 +160,7 @@ function detectArrayType( typeAnnotation.typeParameters.params[0], defaultValue, types, + parser, buildSchema, ), }; @@ -169,11 +172,12 @@ function detectArrayType( function buildObjectType( rawProperties: Array<$FlowFixMe>, types: TypeDeclarationMap, - buildSchema: (property: PropAST, types: TypeDeclarationMap) => ?NamedShape, + parser: Parser, + buildSchema: BuildSchemaFN, ): $FlowFixMe { const flattenedProperties = flattenProperties(rawProperties, types); const properties = flattenedProperties - .map(prop => buildSchema(prop, types)) + .map(prop => buildSchema(prop, types, parser)) .filter(Boolean); return { @@ -189,17 +193,24 @@ function getCommonTypeAnnotation( typeAnnotation: $FlowFixMe, defaultValue: $FlowFixMe | void, types: TypeDeclarationMap, - buildSchema: (property: PropAST, types: TypeDeclarationMap) => ?NamedShape, + parser: Parser, + buildSchema: BuildSchemaFN, ): $FlowFixMe { switch (type) { case 'TSTypeLiteral': - return buildObjectType(typeAnnotation.members, types, buildSchema); + return buildObjectType( + typeAnnotation.members, + types, + parser, + buildSchema, + ); case 'TSInterfaceDeclaration': - return buildObjectType([typeAnnotation], types, buildSchema); + return buildObjectType([typeAnnotation], types, parser, buildSchema); case 'TSIntersectionType': return buildObjectType( flattenIntersectionType(typeAnnotation, types), types, + parser, buildSchema, ); case 'ImageSource': @@ -276,7 +287,8 @@ function getTypeAnnotationForArray( typeAnnotation: $FlowFixMe, defaultValue: $FlowFixMe | void, types: TypeDeclarationMap, - buildSchema: (property: PropAST, types: TypeDeclarationMap) => ?NamedShape, + parser: Parser, + buildSchema: BuildSchemaFN, ): $FlowFixMe { // unpack WithDefault, (T) or T|U const topLevelType = parseTopLevelType(typeAnnotation, types); @@ -297,6 +309,7 @@ function getTypeAnnotationForArray( extractedTypeAnnotation, defaultValue, types, + parser, buildSchema, ); if (arrayType) { @@ -322,6 +335,7 @@ function getTypeAnnotationForArray( extractedTypeAnnotation, defaultValue, types, + parser, buildSchema, ); if (common) { @@ -370,8 +384,10 @@ function getTypeAnnotation( name: string, annotation: $FlowFixMe | ASTNode, defaultValue: $FlowFixMe | void, + withNullDefault: boolean, // Just to make `getTypeAnnotation` signature match with the one from Flow types: TypeDeclarationMap, - buildSchema: (property: PropAST, types: TypeDeclarationMap) => ?NamedShape, + parser: Parser, + buildSchema: BuildSchemaFN, ): $FlowFixMe { // unpack WithDefault, (T) or T|U const topLevelType = parseTopLevelType(annotation, types); @@ -381,6 +397,7 @@ function getTypeAnnotation( typeAnnotation, defaultValue, types, + parser, buildSchema, ); if (arrayType) { @@ -400,6 +417,7 @@ function getTypeAnnotation( typeAnnotation, defaultValue, types, + parser, buildSchema, ); if (common) { @@ -435,6 +453,7 @@ type SchemaInfo = { optional: boolean, typeAnnotation: $FlowFixMe, defaultValue: $FlowFixMe, + withNullDefault: boolean, // Just to make `getTypeAnnotation` signature match with the one from Flow }; function getSchemaInfo( @@ -460,6 +479,7 @@ function getSchemaInfo( optional: property.optional || topLevelType.optional, typeAnnotation: topLevelType.type, defaultValue: topLevelType.defaultValue, + withNullDefault: false, // Just to make `getTypeAnnotation` signature match with the one from Flow }; } diff --git a/packages/react-native-codegen/src/parsers/typescript/components/events.js b/packages/react-native-codegen/src/parsers/typescript/components/events.js index e28f653de8c5c5..469be6b257aae9 100644 --- a/packages/react-native-codegen/src/parsers/typescript/components/events.js +++ b/packages/react-native-codegen/src/parsers/typescript/components/events.js @@ -19,8 +19,12 @@ import type {TypeDeclarationMap} from '../../utils'; import type {Parser} from '../../parser'; const {flattenProperties} = require('./componentsUtils'); const {parseTopLevelType} = require('../parseTopLevelType'); -const {throwIfEventHasNoName} = require('../../error-utils'); - +const { + throwIfEventHasNoName, + throwIfBubblingTypeIsNull, + throwIfArgumentPropsAreNull, +} = require('../../error-utils'); +const {getEventArgument} = require('../../parsers-commons'); function getPropertyType( /* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's * LTI update could not be added via codemod */ @@ -29,6 +33,7 @@ function getPropertyType( /* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's * LTI update could not be added via codemod */ annotation, + parser: Parser, ): NamedShape { const topLevelType = parseTopLevelType(annotation); const typeAnnotation = topLevelType.type; @@ -85,7 +90,9 @@ function getPropertyType( optional, typeAnnotation: { type: 'ObjectTypeAnnotation', - properties: typeAnnotation.members.map(buildPropertiesForEvent), + properties: typeAnnotation.members.map(member => + buildPropertiesForEvent(member, parser), + ), }, }; case 'TSUnionType': @@ -105,12 +112,87 @@ function getPropertyType( type: 'MixedTypeAnnotation', }, }; + case 'TSArrayType': + return { + name, + optional, + typeAnnotation: extractArrayElementType(typeAnnotation, name, parser), + }; default: (type: empty); throw new Error(`Unable to determine event type for "${name}": ${type}`); } } +function extractArrayElementType( + typeAnnotation: $FlowFixMe, + name: string, + parser: Parser, +): EventTypeAnnotation { + const type = extractTypeFromTypeAnnotation(typeAnnotation); + + switch (type) { + case 'TSParenthesizedType': + return extractArrayElementType( + typeAnnotation.typeAnnotation, + name, + parser, + ); + case 'TSBooleanKeyword': + return {type: 'BooleanTypeAnnotation'}; + case 'TSStringKeyword': + return {type: 'StringTypeAnnotation'}; + case 'Float': + return { + type: 'FloatTypeAnnotation', + }; + case 'Int32': + return { + type: 'Int32TypeAnnotation', + }; + case 'TSNumberKeyword': + case 'Double': + return { + type: 'DoubleTypeAnnotation', + }; + case 'TSUnionType': + return { + type: 'StringEnumTypeAnnotation', + options: typeAnnotation.types.map(option => option.literal.value), + }; + case 'TSTypeLiteral': + return { + type: 'ObjectTypeAnnotation', + properties: typeAnnotation.members.map(member => + buildPropertiesForEvent(member, parser), + ), + }; + case 'TSArrayType': + return { + type: 'ArrayTypeAnnotation', + elementType: extractArrayElementType( + typeAnnotation.elementType, + name, + parser, + ), + }; + default: + throw new Error( + `Unrecognized ${type} for Array ${name} in events.\n${JSON.stringify( + typeAnnotation, + null, + 2, + )}`, + ); + } +} + +function extractTypeFromTypeAnnotation(typeAnnotation: $FlowFixMe): string { + return typeAnnotation.type === 'TSTypeReference' + ? typeAnnotation.typeName.name + : typeAnnotation.type; +} + function findEventArgumentsAndType( parser: Parser, typeAnnotation: $FlowFixMe, @@ -156,7 +238,7 @@ function findEventArgumentsAndType( : null; switch (typeAnnotation.typeParameters.params[0].type) { - case 'TSNullKeyword': + case parser.nullLiteralTypeAnnotation: case 'TSUndefinedKeyword': return { argumentProps: [], @@ -193,23 +275,17 @@ function findEventArgumentsAndType( } } -/* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's - * LTI update could not be added via codemod */ -function buildPropertiesForEvent(property): NamedShape { +function buildPropertiesForEvent( + /* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's + * LTI update could not be added via codemod */ + property, + parser: Parser, +): NamedShape { const name = property.key.name; - const optional = property.optional || false; + const optional = parser.isOptionalProperty(property); let typeAnnotation = property.typeAnnotation.typeAnnotation; - return getPropertyType(name, optional, typeAnnotation); -} - -/* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's - * LTI update could not be added via codemod */ -function getEventArgument(argumentProps, name: $FlowFixMe) { - return { - type: 'ObjectTypeAnnotation', - properties: argumentProps.map(buildPropertiesForEvent), - }; + return getPropertyType(name, optional, typeAnnotation, parser); } // $FlowFixMe[unclear-type] TODO(T108222691): Use flow-types for @babel/parser @@ -219,7 +295,7 @@ function buildEventSchema( types: TypeDeclarationMap, property: EventTypeAST, parser: Parser, -): EventTypeShape { +): ?EventTypeShape { // unpack WithDefault, (T) or T|U const topLevelType = parseTopLevelType( property.typeAnnotation.typeAnnotation, @@ -232,34 +308,42 @@ function buildEventSchema( const {argumentProps, bubblingType, paperTopLevelNameDeprecated} = findEventArgumentsAndType(parser, typeAnnotation, types); - if (!argumentProps) { - throw new Error(`Unable to determine event arguments for "${name}"`); - } else if (!bubblingType) { - throw new Error(`Unable to determine event bubbling type for "${name}"`); - } else { - if (paperTopLevelNameDeprecated != null) { - return { - name, - optional, - bubblingType, - paperTopLevelNameDeprecated, - typeAnnotation: { - type: 'EventTypeAnnotation', - argument: getEventArgument(argumentProps, name), - }, - }; - } + const nonNullableArgumentProps = throwIfArgumentPropsAreNull( + argumentProps, + name, + ); + const nonNullableBubblingType = throwIfBubblingTypeIsNull(bubblingType, name); + if (paperTopLevelNameDeprecated != null) { return { name, optional, - bubblingType, + bubblingType: nonNullableBubblingType, + paperTopLevelNameDeprecated, typeAnnotation: { type: 'EventTypeAnnotation', - argument: getEventArgument(argumentProps, name), + argument: getEventArgument( + nonNullableArgumentProps, + buildPropertiesForEvent, + parser, + ), }, }; } + + return { + name, + optional, + bubblingType: nonNullableBubblingType, + typeAnnotation: { + type: 'EventTypeAnnotation', + argument: getEventArgument( + nonNullableArgumentProps, + buildPropertiesForEvent, + parser, + ), + }, + }; } function getEvents( @@ -267,9 +351,9 @@ function getEvents( types: TypeDeclarationMap, parser: Parser, ): $ReadOnlyArray { - return eventTypeAST.map(property => - buildEventSchema(types, property, parser), - ); + return eventTypeAST + .map(property => buildEventSchema(types, property, parser)) + .filter(Boolean); } module.exports = { diff --git a/packages/react-native-codegen/src/parsers/typescript/components/props.js b/packages/react-native-codegen/src/parsers/typescript/components/props.js index ab989186cc4d65..25d24698f5c24b 100644 --- a/packages/react-native-codegen/src/parsers/typescript/components/props.js +++ b/packages/react-native-codegen/src/parsers/typescript/components/props.js @@ -10,8 +10,6 @@ 'use strict'; -const {getSchemaInfo, getTypeAnnotation} = require('./componentsUtils.js'); - import type {NamedShape, PropTypeAnnotation} from '../../../CodegenSchema.js'; import type {TypeDeclarationMap, PropAST} from '../../utils'; import type {ExtendsPropsShape} from '../../../CodegenSchema.js'; @@ -19,26 +17,7 @@ import type {Parser} from '../../parser'; const {flattenProperties} = require('./componentsUtils.js'); const {parseTopLevelType} = require('../parseTopLevelType'); -const {extendsForProp} = require('../../parsers-commons'); - -function buildPropSchema( - property: PropAST, - types: TypeDeclarationMap, -): NamedShape { - const info = getSchemaInfo(property, types); - const {name, optional, typeAnnotation, defaultValue} = info; - return { - name, - optional, - typeAnnotation: getTypeAnnotation( - name, - typeAnnotation, - defaultValue, - types, - buildPropSchema, - ), - }; -} +const {buildPropSchema, extendsForProp} = require('../../parsers-commons'); function isEvent(typeAnnotation: $FlowFixMe): boolean { if (typeAnnotation.type !== 'TSTypeReference') { @@ -101,7 +80,9 @@ function getProps( } return { - props: componentPropAsts.map(property => buildPropSchema(property, types)), + props: componentPropAsts + .map(property => buildPropSchema(property, types, parser)) + .filter(Boolean), extendsProps, }; } diff --git a/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap b/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap index 6f7033c94407af..870a93494166d8 100644 --- a/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap +++ b/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap @@ -199,14 +199,26 @@ exports[`RN Codegen TypeScript Parser can generate fixture CXX_ONLY_NATIVE_MODUL 'typeAnnotation': { 'type': 'FunctionTypeAnnotation', 'returnTypeAnnotation': { - 'type': 'GenericObjectTypeAnnotation' + 'type': 'GenericObjectTypeAnnotation', + 'dictionaryValueType': { + 'type': 'NullableTypeAnnotation', + 'typeAnnotation': { + 'type': 'NumberTypeAnnotation' + } + } }, 'params': [ { 'name': 'arg', 'optional': false, 'typeAnnotation': { - 'type': 'GenericObjectTypeAnnotation' + 'type': 'GenericObjectTypeAnnotation', + 'dictionaryValueType': { + 'type': 'NullableTypeAnnotation', + 'typeAnnotation': { + 'type': 'NumberTypeAnnotation' + } + } } } ] @@ -218,14 +230,20 @@ exports[`RN Codegen TypeScript Parser can generate fixture CXX_ONLY_NATIVE_MODUL 'typeAnnotation': { 'type': 'FunctionTypeAnnotation', 'returnTypeAnnotation': { - 'type': 'GenericObjectTypeAnnotation' + 'type': 'GenericObjectTypeAnnotation', + 'dictionaryValueType': { + 'type': 'StringTypeAnnotation' + } }, 'params': [ { 'name': 'arg', 'optional': false, 'typeAnnotation': { - 'type': 'GenericObjectTypeAnnotation' + 'type': 'GenericObjectTypeAnnotation', + 'dictionaryValueType': { + 'type': 'StringTypeAnnotation' + } } } ] diff --git a/packages/react-native-codegen/src/parsers/typescript/modules/index.js b/packages/react-native-codegen/src/parsers/typescript/modules/index.js index d9e20011a181a3..d9cab074e77b40 100644 --- a/packages/react-native-codegen/src/parsers/typescript/modules/index.js +++ b/packages/react-native-codegen/src/parsers/typescript/modules/index.js @@ -28,14 +28,13 @@ import type { const {flattenIntersectionType} = require('../parseTopLevelType'); const {flattenProperties} = require('../components/componentsUtils'); -const {resolveTypeAnnotation} = require('../utils'); - const {parseObjectProperty} = require('../../parsers-commons'); +const {resolveTypeAnnotation} = require('../utils'); const { emitArrayType, emitFunction, - emitGenericObject, + emitDictionary, emitPromise, emitRootTag, emitUnion, @@ -190,7 +189,8 @@ function translateTypeAnnotation( parser: Parser, ): Nullable { const {nullable, typeAnnotation, typeResolutionStatus} = - resolveTypeAnnotation(typeScriptTypeAnnotation, types); + parser.getResolvedTypeAnnotation(typeScriptTypeAnnotation, types); + resolveTypeAnnotation(typeScriptTypeAnnotation, types, parser); switch (typeAnnotation.type) { case 'TSArrayType': { @@ -309,7 +309,7 @@ function translateTypeAnnotation( // check the property type to prevent developers from using unsupported types // the return value from `translateTypeAnnotation` is unused const propertyType = indexSignatures[0].typeAnnotation; - translateTypeAnnotation( + const valueType = translateTypeAnnotation( hasteModuleName, propertyType, types, @@ -320,7 +320,7 @@ function translateTypeAnnotation( parser, ); // no need to do further checking - return emitGenericObject(nullable); + return emitDictionary(nullable, valueType); } } diff --git a/packages/react-native-codegen/src/parsers/typescript/parser.js b/packages/react-native-codegen/src/parsers/typescript/parser.js index 86534b5cbdd809..7823a016c665da 100644 --- a/packages/react-native-codegen/src/parsers/typescript/parser.js +++ b/packages/react-native-codegen/src/parsers/typescript/parser.js @@ -22,8 +22,19 @@ import type { NativeModuleEnumMap, } from '../../CodegenSchema'; import type {ParserType} from '../errors'; -import type {Parser} from '../parser'; -import type {ParserErrorCapturer, TypeDeclarationMap, PropAST} from '../utils'; +import type { + GetSchemaInfoFN, + GetTypeAnnotationFN, + Parser, + ResolveTypeAnnotationFN, +} from '../parser'; +import type { + ParserErrorCapturer, + TypeDeclarationMap, + PropAST, + TypeResolutionStatus, +} from '../utils'; +const invariant = require('invariant'); const {typeScriptTranslateTypeAnnotation} = require('./modules'); @@ -35,8 +46,12 @@ const {Visitor} = require('../parsers-primitives'); const {buildComponentSchema} = require('./components'); const {wrapComponentSchema} = require('../schema.js'); const {buildModuleSchema} = require('../parsers-commons.js'); +const {parseTopLevelType} = require('./parseTopLevelType'); +const { + getSchemaInfo, + getTypeAnnotation, +} = require('./components/componentsUtils'); const {resolveTypeAnnotation} = require('./utils'); - const fs = require('fs'); const { @@ -45,6 +60,11 @@ const { class TypeScriptParser implements Parser { typeParameterInstantiation: string = 'TSTypeParameterInstantiation'; + typeAlias: string = 'TSTypeAliasDeclaration'; + enumDeclaration: string = 'TSEnumDeclaration'; + interfaceDelcaration: string = 'TSInterfaceDeclaration'; + + nullLiteralTypeAnnotation: string = 'TSNullKeyword'; isProperty(property: $FlowFixMe): boolean { return property.type === 'TSPropertySignature'; @@ -108,7 +128,6 @@ class TypeScriptParser implements Parser { buildModuleSchema, Visitor, this, - resolveTypeAnnotation, typeScriptTranslateTypeAnnotation, ); } @@ -336,6 +355,102 @@ class TypeScriptParser implements Parser { nameForArgument(prop: PropAST): $FlowFixMe { return prop.expression.name; } + + isOptionalProperty(property: $FlowFixMe): boolean { + return property.optional || false; + } + + getGetSchemaInfoFN(): GetSchemaInfoFN { + return getSchemaInfo; + } + + getGetTypeAnnotationFN(): GetTypeAnnotationFN { + return getTypeAnnotation; + } + + getResolvedTypeAnnotation( + // TODO(T108222691): Use flow-types for @babel/parser + typeAnnotation: $FlowFixMe, + types: TypeDeclarationMap, + ): { + nullable: boolean, + typeAnnotation: $FlowFixMe, + typeResolutionStatus: TypeResolutionStatus, + } { + invariant( + typeAnnotation != null, + 'resolveTypeAnnotation(): typeAnnotation cannot be null', + ); + + let node = + typeAnnotation.type === 'TSTypeAnnotation' + ? typeAnnotation.typeAnnotation + : typeAnnotation; + let nullable = false; + let typeResolutionStatus: TypeResolutionStatus = { + successful: false, + }; + + for (;;) { + const topLevelType = parseTopLevelType(node); + nullable = nullable || topLevelType.optional; + node = topLevelType.type; + + if (node.type !== 'TSTypeReference') { + break; + } + + const resolvedTypeAnnotation = types[node.typeName.name]; + if (resolvedTypeAnnotation == null) { + break; + } + + switch (resolvedTypeAnnotation.type) { + case 'TSTypeAliasDeclaration': { + typeResolutionStatus = { + successful: true, + type: 'alias', + name: node.typeName.name, + }; + node = resolvedTypeAnnotation.typeAnnotation; + break; + } + case 'TSInterfaceDeclaration': { + typeResolutionStatus = { + successful: true, + type: 'alias', + name: node.typeName.name, + }; + node = resolvedTypeAnnotation; + break; + } + case 'TSEnumDeclaration': { + typeResolutionStatus = { + successful: true, + type: 'enum', + name: node.typeName.name, + }; + node = resolvedTypeAnnotation; + break; + } + default: { + throw new TypeError( + `A non GenericTypeAnnotation must be a type declaration ('TSTypeAliasDeclaration'), an interface ('TSInterfaceDeclaration'), or enum ('TSEnumDeclaration'). Instead, got the unsupported ${resolvedTypeAnnotation.type}.`, + ); + } + } + } + + return { + nullable: nullable, + typeAnnotation: node, + typeResolutionStatus, + }; + } + + getResolveTypeAnnotationFN(): ResolveTypeAnnotationFN { + return resolveTypeAnnotation; + } } module.exports = { diff --git a/packages/react-native-codegen/src/parsers/typescript/utils.js b/packages/react-native-codegen/src/parsers/typescript/utils.js index ffb7145d620852..e7474f70cb04aa 100644 --- a/packages/react-native-codegen/src/parsers/typescript/utils.js +++ b/packages/react-native-codegen/src/parsers/typescript/utils.js @@ -10,19 +10,20 @@ 'use strict'; +// $FlowFixMe[unclear-type] Use flow-types for @babel/parser +export type ASTNode = Object; import type {TypeResolutionStatus, TypeDeclarationMap} from '../utils'; +import type {Parser} from '../../parsers/parser'; const {parseTopLevelType} = require('./parseTopLevelType'); -// $FlowFixMe[unclear-type] Use flow-types for @babel/parser -export type ASTNode = Object; - const invariant = require('invariant'); function resolveTypeAnnotation( // TODO(T108222691): Use flow-types for @babel/parser typeAnnotation: $FlowFixMe, types: TypeDeclarationMap, + parser: Parser, ): { nullable: boolean, typeAnnotation: $FlowFixMe, @@ -57,7 +58,7 @@ function resolveTypeAnnotation( } switch (resolvedTypeAnnotation.type) { - case 'TSTypeAliasDeclaration': { + case parser.typeAlias: { typeResolutionStatus = { successful: true, type: 'alias', @@ -66,7 +67,7 @@ function resolveTypeAnnotation( node = resolvedTypeAnnotation.typeAnnotation; break; } - case 'TSInterfaceDeclaration': { + case parser.interfaceDelcaration: { typeResolutionStatus = { successful: true, type: 'alias', @@ -75,7 +76,7 @@ function resolveTypeAnnotation( node = resolvedTypeAnnotation; break; } - case 'TSEnumDeclaration': { + case parser.enumDeclaration: { typeResolutionStatus = { successful: true, type: 'enum', @@ -86,7 +87,7 @@ function resolveTypeAnnotation( } default: { throw new TypeError( - `A non GenericTypeAnnotation must be a type declaration ('TSTypeAliasDeclaration'), an interface ('TSInterfaceDeclaration'), or enum ('TSEnumDeclaration'). Instead, got the unsupported ${resolvedTypeAnnotation.type}.`, + `A non GenericTypeAnnotation must be a type declaration ('${parser.typeAlias}'), an interface ('${parser.interfaceDelcaration}'), or enum ('${parser.enumDeclaration}'). Instead, got the unsupported ${resolvedTypeAnnotation.type}.`, ); } } diff --git a/packages/react-native-codegen/src/parsers/utils.js b/packages/react-native-codegen/src/parsers/utils.js index 56d93491273252..5c904c6c80fecf 100644 --- a/packages/react-native-codegen/src/parsers/utils.js +++ b/packages/react-native-codegen/src/parsers/utils.js @@ -37,6 +37,9 @@ export type ParserErrorCapturer = (fn: () => T) => ?T; // $FlowFixMe[unclear-type] there's no flowtype for ASTs export type PropAST = Object; +// $FlowFixMe[unclear-type] there's no flowtype for ASTs +export type ASTNode = Object; + function createParserErrorCapturer(): [ Array, ParserErrorCapturer, diff --git a/packages/react-native-gradle-plugin/README.md b/packages/react-native-gradle-plugin/README.md index 6d6889a8067989..7233d33cbd3f6a 100644 --- a/packages/react-native-gradle-plugin/README.md +++ b/packages/react-native-gradle-plugin/README.md @@ -14,3 +14,10 @@ yarn add @react-native/gradle-plugin [version-badge]: https://img.shields.io/npm/v/@react-native/gradle-plugin?style=flat-square [package]: https://www.npmjs.com/package/@react-native/gradle-plugin + +## Testing + +To run the tests in this package, run the following commands from the React Native root folder: + +1. `yarn` to install the dependencies. You just need to run this once +2. `yarn jest packages/react-native-gradle-plugin`. diff --git a/packages/react-native-gradle-plugin/build.gradle.kts b/packages/react-native-gradle-plugin/build.gradle.kts index aba364903b2857..33f4dc589d42f9 100644 --- a/packages/react-native-gradle-plugin/build.gradle.kts +++ b/packages/react-native-gradle-plugin/build.gradle.kts @@ -11,7 +11,7 @@ import org.gradle.configurationcache.extensions.serviceOf import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - kotlin("jvm") version "1.7.22" + kotlin("jvm") version "1.8.0" id("java-gradle-plugin") } @@ -33,7 +33,12 @@ group = "com.facebook.react" dependencies { implementation(gradleApi()) + + // The KGP/AGP version is defined by React Native Gradle plugin. + // Therefore we specify an implementation dep rather than a compileOnly. + implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0") implementation("com.android.tools.build:gradle:7.4.2") + implementation("com.google.code.gson:gson:2.8.9") implementation("com.google.guava:guava:31.0.1-jre") implementation("com.squareup:javapoet:1.13.0") @@ -54,6 +59,8 @@ java { targetCompatibility = JavaVersion.VERSION_11 } +kotlin { jvmToolchain(11) } + tasks.withType { kotlinOptions { jvmTarget = JavaVersion.VERSION_11.majorVersion diff --git a/packages/react-native-gradle-plugin/package.json b/packages/react-native-gradle-plugin/package.json index f7fe5796df65c5..f5eb0fd73a30eb 100644 --- a/packages/react-native-gradle-plugin/package.json +++ b/packages/react-native-gradle-plugin/package.json @@ -1,13 +1,16 @@ { "name": "@react-native/gradle-plugin", "version": "0.73.0", - "description": "⚛️ Gradle Plugin for React Native", - "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/react-native-gradle-plugin", + "description": "Gradle Plugin for React Native", + "license": "MIT", "repository": { "type": "git", - "url": "git@github.com:facebook/react-native.git", + "url": "https://github.com/facebook/react-native.git", "directory": "packages/react-native-gradle-plugin" }, + "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/react-native-gradle-plugin#readme", + "keywords": ["gradle", "plugin", "react-native"], + "bugs": "https://github.com/facebook/react-native/issues", "engines": { "node": ">=16" }, @@ -16,7 +19,6 @@ "clean": "./gradlew clean", "test": "./gradlew check" }, - "license": "MIT", "files": [ "settings.gradle.kts", "build.gradle.kts", diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactPlugin.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactPlugin.kt index 4c8a6ff9996020..8663111ce17768 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactPlugin.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactPlugin.kt @@ -18,7 +18,8 @@ import com.facebook.react.utils.AgpConfiguratorUtils.configureDevPorts import com.facebook.react.utils.BackwardCompatUtils.configureBackwardCompatibilityReactMap import com.facebook.react.utils.DependencyUtils.configureDependencies import com.facebook.react.utils.DependencyUtils.configureRepositories -import com.facebook.react.utils.DependencyUtils.readVersionString +import com.facebook.react.utils.DependencyUtils.readVersionAndGroupStrings +import com.facebook.react.utils.JdkConfiguratorUtils.configureJavaToolChains import com.facebook.react.utils.JsonUtils import com.facebook.react.utils.NdkConfiguratorUtils.configureReactNativeNdk import com.facebook.react.utils.ProjectUtils.needsCodegenFromPackageJson @@ -54,8 +55,10 @@ class ReactPlugin : Plugin { project.afterEvaluate { val reactNativeDir = extension.reactNativeDir.get().asFile val propertiesFile = File(reactNativeDir, "ReactAndroid/gradle.properties") - val versionString = readVersionString(propertiesFile) - configureDependencies(project, versionString) + val versionAndGroupStrings = readVersionAndGroupStrings(propertiesFile) + val versionString = versionAndGroupStrings.first + val groupString = versionAndGroupStrings.second + configureDependencies(project, versionString, groupString) configureRepositories(project, reactNativeDir) } @@ -63,6 +66,7 @@ class ReactPlugin : Plugin { configureBuildConfigFields(project) configureDevPorts(project) configureBackwardCompatibilityReactMap(project) + configureJavaToolChains(project) project.extensions.getByType(AndroidComponentsExtension::class.java).apply { onVariants(selector().all()) { variant -> diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt index 6679aba9c216eb..45b415f961c17b 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt @@ -13,6 +13,8 @@ import java.util.* import org.gradle.api.Project import org.gradle.api.artifacts.repositories.MavenArtifactRepository +internal const val DEFAULT_GROUP_STRING = "com.facebook.react" + internal object DependencyUtils { /** @@ -46,7 +48,11 @@ internal object DependencyUtils { * - Forcing the react-android/hermes-android version to the one specified in the package.json * - Substituting `react-native` with `react-android` and `hermes-engine` with `hermes-android`. */ - fun configureDependencies(project: Project, versionString: String) { + fun configureDependencies( + project: Project, + versionString: String, + groupString: String = DEFAULT_GROUP_STRING + ) { if (versionString.isBlank()) return project.rootProject.allprojects { eachProject -> eachProject.configurations.all { configuration -> @@ -56,32 +62,46 @@ internal object DependencyUtils { // implementation("com.facebook.react:react-native:+") and resolve the right dependency. configuration.resolutionStrategy.dependencySubstitution { it.substitute(it.module("com.facebook.react:react-native")) - .using(it.module("com.facebook.react:react-android:${versionString}")) + .using(it.module("${groupString}:react-android:${versionString}")) .because( "The react-native artifact was deprecated in favor of react-android due to https://github.com/facebook/react-native/issues/35210.") it.substitute(it.module("com.facebook.react:hermes-engine")) - .using(it.module("com.facebook.react:hermes-android:${versionString}")) + .using(it.module("${groupString}:hermes-android:${versionString}")) .because( "The hermes-engine artifact was deprecated in favor of hermes-android due to https://github.com/facebook/react-native/issues/35210.") + if (groupString != DEFAULT_GROUP_STRING) { + it.substitute(it.module("com.facebook.react:react-android")) + .using(it.module("${groupString}:react-android:${versionString}")) + .because( + "The react-android dependency was modified to use the correct Maven group.") + it.substitute(it.module("com.facebook.react:hermes-android")) + .using(it.module("${groupString}:hermes-android:${versionString}")) + .because( + "The hermes-android dependency was modified to use the correct Maven group.") + } } configuration.resolutionStrategy.force( - "com.facebook.react:react-android:${versionString}", - "com.facebook.react:hermes-android:${versionString}", + "${groupString}:react-android:${versionString}", + "${groupString}:hermes-android:${versionString}", ) } } } - fun readVersionString(propertiesFile: File): String { + fun readVersionAndGroupStrings(propertiesFile: File): Pair { val reactAndroidProperties = Properties() propertiesFile.inputStream().use { reactAndroidProperties.load(it) } - val versionString = reactAndroidProperties["VERSION_NAME"] as? String ?: "" + val versionStringFromFile = reactAndroidProperties["VERSION_NAME"] as? String ?: "" // If on a nightly, we need to fetch the -SNAPSHOT artifact from Sonatype. - return if (versionString.startsWith("0.0.0")) { - "$versionString-SNAPSHOT" - } else { - versionString - } + val versionString = + if (versionStringFromFile.startsWith("0.0.0") || "-nightly-" in versionStringFromFile) { + "$versionStringFromFile-SNAPSHOT" + } else { + versionStringFromFile + } + // Returns Maven group for repos using different group for Maven artifacts + val groupString = reactAndroidProperties["GROUP"] as? String ?: DEFAULT_GROUP_STRING + return Pair(versionString, groupString) } fun Project.mavenRepoFromUrl(url: String): MavenArtifactRepository = diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/JdkConfiguratorUtils.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/JdkConfiguratorUtils.kt new file mode 100644 index 00000000000000..c86484ab5249c5 --- /dev/null +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/JdkConfiguratorUtils.kt @@ -0,0 +1,33 @@ +/* + * 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. + */ + +package com.facebook.react.utils + +import com.android.build.api.variant.AndroidComponentsExtension +import org.gradle.api.JavaVersion +import org.gradle.api.Project +import org.jetbrains.kotlin.gradle.dsl.KotlinTopLevelExtension + +internal object JdkConfiguratorUtils { + /** + * Function that takes care of configuring the JDK toolchain for Application projects. As we do + * decide the JDK version based on the AGP version that RNGP brings over, here we can safely + * configure the toolchain to 11. + */ + fun configureJavaToolChains(project: Project) { + project.extensions.getByType(AndroidComponentsExtension::class.java).finalizeDsl { ext -> + ext.compileOptions.sourceCompatibility = JavaVersion.VERSION_11 + ext.compileOptions.targetCompatibility = JavaVersion.VERSION_11 + } + project.pluginManager.withPlugin("org.jetbrains.kotlin.android") { + project.extensions.getByType(KotlinTopLevelExtension::class.java).jvmToolchain(11) + } + project.pluginManager.withPlugin("org.jetbrains.kotlin.jvm") { + project.extensions.getByType(KotlinTopLevelExtension::class.java).jvmToolchain(11) + } + } +} diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt index 20e28696f1312f..28a33b85f8fc3f 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt @@ -40,16 +40,22 @@ internal object NdkConfiguratorUtils { // Parameters should be provided in an additive manner (do not override what // the user provided, but allow for sensible defaults). val cmakeArgs = ext.defaultConfig.externalNativeBuild.cmake.arguments - if ("-DPROJECT_BUILD_DIR" !in cmakeArgs) { + if (cmakeArgs.none { it.startsWith("-DPROJECT_BUILD_DIR") }) { cmakeArgs.add("-DPROJECT_BUILD_DIR=${project.buildDir}") } - if ("-DREACT_ANDROID_DIR" !in cmakeArgs) { + if (cmakeArgs.none { it.startsWith("-DREACT_ANDROID_DIR") }) { cmakeArgs.add( "-DREACT_ANDROID_DIR=${extension.reactNativeDir.file("ReactAndroid").get().asFile}") } - if ("-DANDROID_STL" !in cmakeArgs) { + if (cmakeArgs.none { it.startsWith("-DANDROID_STL") }) { cmakeArgs.add("-DANDROID_STL=c++_shared") } + // Due to the new NDK toolchain file, the C++ flags gets overridden between compilation + // units. This is causing some libraries to don't be compiled with -DANDROID and other + // crucial flags. This can be revisited once we bump to NDK 25/26 + if (cmakeArgs.none { it.startsWith("-DANDROID_USE_LEGACY_TOOLCHAIN_FILE") }) { + cmakeArgs.add("-DANDROID_USE_LEGACY_TOOLCHAIN_FILE=ON") + } val architectures = project.getReactNativeArchitectures() // abiFilters are split ABI are not compatible each other, so we set the abiFilters diff --git a/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt index 1b7c728cc4b4f6..f77c0bb3026b46 100644 --- a/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt +++ b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt @@ -12,7 +12,7 @@ import com.facebook.react.utils.DependencyUtils.configureDependencies import com.facebook.react.utils.DependencyUtils.configureRepositories import com.facebook.react.utils.DependencyUtils.mavenRepoFromURI import com.facebook.react.utils.DependencyUtils.mavenRepoFromUrl -import com.facebook.react.utils.DependencyUtils.readVersionString +import com.facebook.react.utils.DependencyUtils.readVersionAndGroupStrings import java.net.URI import org.gradle.api.artifacts.repositories.MavenArtifactRepository import org.gradle.testfixtures.ProjectBuilder @@ -226,6 +226,24 @@ class DependencyUtilsTest { assertTrue(libForcedModules.any { it.toString() == "com.facebook.react:hermes-android:1.2.3" }) } + @Test + fun configureDependencies_withVersionStringAndGroupString_appliesOnAllProjects() { + val rootProject = ProjectBuilder.builder().build() + val appProject = ProjectBuilder.builder().withName("app").withParent(rootProject).build() + val libProject = ProjectBuilder.builder().withName("lib").withParent(rootProject).build() + appProject.plugins.apply("com.android.application") + libProject.plugins.apply("com.android.library") + + configureDependencies(appProject, "1.2.3", "io.github.test") + + val appForcedModules = appProject.configurations.first().resolutionStrategy.forcedModules + val libForcedModules = libProject.configurations.first().resolutionStrategy.forcedModules + assertTrue(appForcedModules.any { it.toString() == "io.github.test:react-android:1.2.3" }) + assertTrue(appForcedModules.any { it.toString() == "io.github.test:hermes-android:1.2.3" }) + assertTrue(libForcedModules.any { it.toString() == "io.github.test:react-android:1.2.3" }) + assertTrue(libForcedModules.any { it.toString() == "io.github.test:hermes-android:1.2.3" }) + } + @Test fun readVersionString_withCorrectVersionString_returnsIt() { val propertiesFile = @@ -238,7 +256,7 @@ class DependencyUtilsTest { .trimIndent()) } - val versionString = readVersionString(propertiesFile) + val versionString = readVersionAndGroupStrings(propertiesFile).first assertEquals("1000.0.0", versionString) } @@ -255,7 +273,7 @@ class DependencyUtilsTest { .trimIndent()) } - val versionString = readVersionString(propertiesFile) + val versionString = readVersionAndGroupStrings(propertiesFile).first assertEquals("0.0.0-20221101-2019-cfe811ab1-SNAPSHOT", versionString) } @@ -271,7 +289,7 @@ class DependencyUtilsTest { .trimIndent()) } - val versionString = readVersionString(propertiesFile) + val versionString = readVersionAndGroupStrings(propertiesFile).first assertEquals("", versionString) } @@ -287,10 +305,43 @@ class DependencyUtilsTest { .trimIndent()) } - val versionString = readVersionString(propertiesFile) + val versionString = readVersionAndGroupStrings(propertiesFile).first assertEquals("", versionString) } + @Test + fun readGroupString_withCorrectGroupString_returnsIt() { + val propertiesFile = + tempFolder.newFile("gradle.properties").apply { + writeText( + """ + GROUP=io.github.test + ANOTHER_PROPERTY=true + """ + .trimIndent()) + } + + val groupString = readVersionAndGroupStrings(propertiesFile).second + + assertEquals("io.github.test", groupString) + } + + @Test + fun readGroupString_withEmptyGroupString_returnsDefault() { + val propertiesFile = + tempFolder.newFile("gradle.properties").apply { + writeText( + """ + ANOTHER_PROPERTY=true + """ + .trimIndent()) + } + + val groupString = readVersionAndGroupStrings(propertiesFile).second + + assertEquals("com.facebook.react", groupString) + } + @Test fun mavenRepoFromUrl_worksCorrectly() { val process = createProject() diff --git a/packages/react-native/Libraries/Alert/Alert.js.flow b/packages/react-native/Libraries/Alert/Alert.js.flow deleted file mode 100644 index be6f948f557add..00000000000000 --- a/packages/react-native/Libraries/Alert/Alert.js.flow +++ /dev/null @@ -1,49 +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 - */ - -export type AlertType = - | 'default' - | 'plain-text' - | 'secure-text' - | 'login-password'; -export type AlertButtonStyle = 'default' | 'cancel' | 'destructive'; -export type Buttons = Array<{ - text?: string, - onPress?: ?Function, - isPreferred?: boolean, - style?: AlertButtonStyle, - ... -}>; -type Options = { - cancelable?: ?boolean, - userInterfaceStyle?: 'unspecified' | 'light' | 'dark', - onDismiss?: ?() => void, - ... -}; - -declare class Alert { - static alert( - title: ?string, - message?: ?string, - buttons?: Buttons, - options?: Options, - ): void; - static prompt( - title: ?string, - message?: ?string, - callbackOrButtons?: ?(((text: string) => void) | Buttons), - type?: ?AlertType, - defaultValue?: string, - keyboardType?: string, - options?: Options, - ): void; -} - -module.exports = Alert; diff --git a/packages/react-native/Libraries/Animated/NativeAnimatedHelper.js b/packages/react-native/Libraries/Animated/NativeAnimatedHelper.js index 5a6c508fd0411e..a96287de26ddd8 100644 --- a/packages/react-native/Libraries/Animated/NativeAnimatedHelper.js +++ b/packages/react-native/Libraries/Animated/NativeAnimatedHelper.js @@ -28,9 +28,7 @@ import invariant from 'invariant'; // TODO T69437152 @petetheheat - Delete this fork when Fabric ships to 100%. const NativeAnimatedModule = - Platform.OS === 'ios' && global.RN$Bridgeless === true - ? NativeAnimatedTurboModule - : NativeAnimatedNonTurboModule; + NativeAnimatedNonTurboModule ?? NativeAnimatedTurboModule; let __nativeAnimatedNodeTagCount = 1; /* used for animated nodes */ let __nativeAnimationIdCount = 1; /* used for started animations */ diff --git a/packages/react-native/Libraries/Animated/NativeAnimatedModule.js b/packages/react-native/Libraries/Animated/NativeAnimatedModule.js index 9fc932e6b509cc..a080eb4d66eb0f 100644 --- a/packages/react-native/Libraries/Animated/NativeAnimatedModule.js +++ b/packages/react-native/Libraries/Animated/NativeAnimatedModule.js @@ -11,6 +11,7 @@ import type {TurboModule} from '../TurboModule/RCTExport'; import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; +import shouldUseTurboAnimatedModule from './shouldUseTurboAnimatedModule'; type EndResult = {finished: boolean, ...}; type EndCallback = (result: EndResult) => void; @@ -70,4 +71,7 @@ export interface Spec extends TurboModule { +queueAndExecuteBatchedOperations?: (operationsAndArgs: Array) => void; } -export default (TurboModuleRegistry.get('NativeAnimatedModule'): ?Spec); +const NativeModule: ?Spec = !shouldUseTurboAnimatedModule() + ? TurboModuleRegistry.get('NativeAnimatedModule') + : null; +export default NativeModule; diff --git a/packages/react-native/Libraries/Animated/NativeAnimatedTurboModule.js b/packages/react-native/Libraries/Animated/NativeAnimatedTurboModule.js index 58664ca8742173..f9ea5881232273 100644 --- a/packages/react-native/Libraries/Animated/NativeAnimatedTurboModule.js +++ b/packages/react-native/Libraries/Animated/NativeAnimatedTurboModule.js @@ -11,6 +11,7 @@ import type {TurboModule} from '../TurboModule/RCTExport'; import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; +import shouldUseTurboAnimatedModule from './shouldUseTurboAnimatedModule'; type EndResult = {finished: boolean, ...}; type EndCallback = (result: EndResult) => void; @@ -70,6 +71,8 @@ export interface Spec extends TurboModule { +queueAndExecuteBatchedOperations?: (operationsAndArgs: Array) => void; } -export default (TurboModuleRegistry.get( - 'NativeAnimatedTurboModule', -): ?Spec); +const NativeModule: ?Spec = shouldUseTurboAnimatedModule() + ? TurboModuleRegistry.get('NativeAnimatedTurboModule') + : null; + +export default NativeModule; diff --git a/packages/react-native/Libraries/Image/ImageBackground.js.flow b/packages/react-native/Libraries/Animated/shouldUseTurboAnimatedModule.js similarity index 50% rename from packages/react-native/Libraries/Image/ImageBackground.js.flow rename to packages/react-native/Libraries/Animated/shouldUseTurboAnimatedModule.js index ad91f1a4e78dea..c112ba99aca60c 100644 --- a/packages/react-native/Libraries/Image/ImageBackground.js.flow +++ b/packages/react-native/Libraries/Animated/shouldUseTurboAnimatedModule.js @@ -8,10 +8,10 @@ * @format */ -'use strict'; +import Platform from '../Utilities/Platform'; -import * as React from 'react'; -import type {ImageBackgroundProps} from './ImageProps'; +function shouldUseTurboAnimatedModule(): boolean { + return Platform.OS === 'ios' && global.RN$Bridgeless === true; +} -declare class ImageBackground extends React.Component {} -module.exports = ImageBackground; +export default shouldUseTurboAnimatedModule; diff --git a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h index 93b1543c7bacc4..2eb02eafb85d22 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h +++ b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h @@ -9,6 +9,7 @@ #import #import +@protocol RCTComponentViewProtocol; @class RCTSurfacePresenterBridgeAdapter; /** @@ -96,6 +97,14 @@ #if RCT_NEW_ARCH_ENABLED @property (nonatomic, strong) RCTSurfacePresenterBridgeAdapter *bridgeAdapter; +/// This method returns a map of Component Descriptors and Components classes that needs to be registered in the +/// new renderer. The Component Descriptor is a string which represent the name used in JS to refer to the native +/// component. The default implementation returns an empty dictionary. Subclasses can override this method to register +/// the required components. +/// +/// @return a dictionary that associate a component for the new renderer with his descriptor. +- (NSDictionary> *)thirdPartyFabricComponents; + /// This method controls whether the `turboModules` feature of the New Architecture is turned on or off. /// /// @note: This is required to be rendering on Fabric (i.e. on the New Architecture). diff --git a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm index fffea76a6c3459..c04d5e3fed067b 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm @@ -11,6 +11,8 @@ #if RCT_NEW_ARCH_ENABLED #import +#import +#import #import #import #import @@ -24,7 +26,10 @@ static NSString *const kRNConcurrentRoot = @"concurrentRoot"; -@interface RCTAppDelegate () { +@interface RCTAppDelegate () < + RCTTurboModuleManagerDelegate, + RCTCxxBridgeDelegate, + RCTComponentViewFactoryComponentProvider> { std::shared_ptr _reactNativeConfig; facebook::react::ContextContainer::Shared _contextContainer; std::shared_ptr _runtimeScheduler; @@ -64,6 +69,7 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( self.bridge.surfacePresenter = self.bridgeAdapter.surfacePresenter; [self unstable_registerLegacyComponents]; + [RCTComponentViewFactory currentComponentViewFactory].thirdPartyFabricComponentsProvider = self; #endif NSDictionary *initProps = [self prepareInitialProps]; @@ -163,6 +169,13 @@ - (Class)getModuleClassFromName:(const char *)name return RCTAppSetupDefaultModuleFromClass(moduleClass); } +#pragma mark - RCTComponentViewFactoryComponentProvider + +- (NSDictionary> *)thirdPartyFabricComponents +{ + return @{}; +} + #pragma mark - New Arch Enabled settings - (BOOL)turboModuleEnabled diff --git a/packages/react-native/Libraries/AppDelegate/React-RCTAppDelegate.podspec b/packages/react-native/Libraries/AppDelegate/React-RCTAppDelegate.podspec index 79d042eeaf53f9..a98f3aea404347 100644 --- a/packages/react-native/Libraries/AppDelegate/React-RCTAppDelegate.podspec +++ b/packages/react-native/Libraries/AppDelegate/React-RCTAppDelegate.podspec @@ -76,8 +76,19 @@ Pod::Spec.new do |s| s.dependency "RCTRequired" s.dependency "RCTTypeSafety" s.dependency "ReactCommon/turbomodule/core" + s.dependency "React-RCTNetwork" + s.dependency "React-RCTImage" + s.dependency "React-NativeModulesApple" + s.dependency "React-CoreModules" + + if ENV['USE_HERMES'] == nil || ENV['USE_HERMES'] == "1" + s.dependency "React-hermes" + else + s.dependency "React-jsc" + end if is_new_arch_enabled + s.dependency "React-Fabric" s.dependency "React-RCTFabric" s.dependency "React-graphics" diff --git a/packages/react-native/Libraries/Components/TextInput/InputAccessoryView.js.flow b/packages/react-native/Libraries/Components/TextInput/InputAccessoryView.js.flow deleted file mode 100644 index e2245cb84d76ba..00000000000000 --- a/packages/react-native/Libraries/Components/TextInput/InputAccessoryView.js.flow +++ /dev/null @@ -1,25 +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 * as React from 'react'; -import Platform from '../../Utilities/Platform'; -import StyleSheet, { - type ViewStyleProp, - type ColorValue, -} from '../../StyleSheet/StyleSheet'; - -type Props = $ReadOnly<{| - +children: React.Node, - nativeID?: ?string, - style?: ?ViewStyleProp, - backgroundColor?: ?ColorValue, -|}>; - -module.exports = class InputAccessoryView extends React.Component {}; diff --git a/packages/react-native/Libraries/Components/TextInput/__tests__/TextInput-test.js b/packages/react-native/Libraries/Components/TextInput/__tests__/TextInput-test.js index 6e9fbc1fd64299..3f0e8ed59278b6 100644 --- a/packages/react-native/Libraries/Components/TextInput/__tests__/TextInput-test.js +++ b/packages/react-native/Libraries/Components/TextInput/__tests__/TextInput-test.js @@ -322,7 +322,7 @@ describe('TextInput compat with web', () => { 'aria-label': 'label', 'aria-labelledby': 'labelledby', 'aria-level': 3, - // aria-live': 'polite', [TODO: https://github.com/facebook/react-native-deprecated-modules/pull/20] + 'aria-live': 'polite', 'aria-modal': true, 'aria-multiline': true, 'aria-multiselectable': true, @@ -381,6 +381,7 @@ describe('TextInput compat with web', () => { aria-label="label" aria-labelledby="labelledby" aria-level={3} + aria-live="polite" aria-modal={true} aria-multiline={true} aria-multiselectable={true} diff --git a/packages/react-native/Libraries/Components/View/ReactNativeViewAttributes.js b/packages/react-native/Libraries/Components/View/ReactNativeViewAttributes.js index f4ea0d2c1f5219..e27df43205f540 100644 --- a/packages/react-native/Libraries/Components/View/ReactNativeViewAttributes.js +++ b/packages/react-native/Libraries/Components/View/ReactNativeViewAttributes.js @@ -35,6 +35,7 @@ const UIView = { collapsable: true, needsOffscreenAlphaCompositing: true, style: ReactNativeStyleAttributes, + role: true, }; const RCTView = { diff --git a/packages/react-native/Libraries/DOM/Nodes/ReadOnlyCharacterData.js b/packages/react-native/Libraries/DOM/Nodes/ReadOnlyCharacterData.js index 6f3fb0f4ad7b96..6c9f87b43200b1 100644 --- a/packages/react-native/Libraries/DOM/Nodes/ReadOnlyCharacterData.js +++ b/packages/react-native/Libraries/DOM/Nodes/ReadOnlyCharacterData.js @@ -67,6 +67,6 @@ export default class ReadOnlyCharacterData extends ReadOnlyNode { ); } let adjustedCount = count < 0 || count > data.length ? data.length : count; - return data.substr(offset, adjustedCount); + return data.slice(offset, offset + adjustedCount); } } diff --git a/packages/react-native/Libraries/Image/ImageViewNativeComponent.js.flow b/packages/react-native/Libraries/Image/ImageViewNativeComponent.js.flow deleted file mode 100644 index 4bb29f02141311..00000000000000 --- a/packages/react-native/Libraries/Image/ImageViewNativeComponent.js.flow +++ /dev/null @@ -1,42 +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 {ResolvedAssetSource} from './AssetSourceResolver'; -import type {ImageProps} from './ImageProps'; -import type {ViewProps} from '../Components/View/ViewPropTypes'; -import {ConditionallyIgnoredEventHandlers} from '../NativeComponent/ViewConfigIgnore'; -import type {HostComponent} from '../Renderer/shims/ReactNativeTypes'; -import type { - ColorValue, - DangerouslyImpreciseStyle, - ImageStyleProp, -} from '../StyleSheet/StyleSheet'; -import Platform from '../Utilities/Platform'; - -type Props = $ReadOnly<{ - ...ImageProps, - ...ViewProps, - - style?: ImageStyleProp | DangerouslyImpreciseStyle, - - // iOS native props - tintColor?: ColorValue, - - // Android native props - shouldNotifyLoadEvents?: boolean, - src?: - | ?ResolvedAssetSource - | ?$ReadOnlyArray>, - headers?: ?{[string]: string}, - defaultSrc?: ?string, - loadingIndicatorSrc?: ?string, -}>; - -declare export default HostComponent; diff --git a/packages/react-native/Libraries/Image/TextInlineImageNativeComponent.js.flow b/packages/react-native/Libraries/Image/TextInlineImageNativeComponent.js.flow deleted file mode 100644 index 6726b15d47a29b..00000000000000 --- a/packages/react-native/Libraries/Image/TextInlineImageNativeComponent.js.flow +++ /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 - */ - -'use strict'; - -import type {HostComponent} from '../Renderer/shims/ReactNativeTypes'; -import type {ViewProps} from '../Components/View/ViewPropTypes'; -import type {ImageResizeMode} from './ImageResizeMode'; -import * as NativeComponentRegistry from '../NativeComponent/NativeComponentRegistry'; -import type {ColorValue} from '../StyleSheet/StyleSheet'; - -type NativeProps = $ReadOnly<{ - ...ViewProps, - resizeMode?: ?ImageResizeMode, - src?: ?$ReadOnlyArray>, - tintColor?: ?ColorValue, - headers?: ?{[string]: string}, -}>; - -declare export default HostComponent; diff --git a/packages/react-native/Libraries/Inspector/NetworkOverlay.js b/packages/react-native/Libraries/Inspector/NetworkOverlay.js index cedb60d2bce432..1e4d63f27fd9d2 100644 --- a/packages/react-native/Libraries/Inspector/NetworkOverlay.js +++ b/packages/react-native/Libraries/Inspector/NetworkOverlay.js @@ -64,7 +64,7 @@ function getStringByValue(value: any): string { } if (typeof value === 'string' && value.length > 500) { return String(value) - .substr(0, 500) + .slice(0, 500) .concat('\n***TRUNCATED TO 500 CHARACTERS***'); } return value; diff --git a/packages/react-native/Libraries/Lists/FlatList.d.ts b/packages/react-native/Libraries/Lists/FlatList.d.ts index b6b28675a7c6e1..5bbe2fa3b80c7a 100644 --- a/packages/react-native/Libraries/Lists/FlatList.d.ts +++ b/packages/react-native/Libraries/Lists/FlatList.d.ts @@ -12,6 +12,7 @@ import type { ListRenderItem, ViewToken, VirtualizedListProps, + ViewabilityConfig, } from '@react-native/virtualized-lists'; import type {ScrollViewComponent} from '../Components/ScrollView/ScrollView'; import type {StyleProp} from '../StyleSheet/StyleSheet'; @@ -144,7 +145,7 @@ export interface FlatListProps extends VirtualizedListProps { /** * See `ViewabilityHelper` for flow type and further documentation. */ - viewabilityConfig?: any | undefined; + viewabilityConfig?: ViewabilityConfig | undefined; /** * Note: may have bugs (missing content) in some circumstances - use at your own risk. diff --git a/packages/react-native/Libraries/Lists/FlatList.js b/packages/react-native/Libraries/Lists/FlatList.js index ddb929e6a80f4a..63e2de283821b1 100644 --- a/packages/react-native/Libraries/Lists/FlatList.js +++ b/packages/react-native/Libraries/Lists/FlatList.js @@ -36,7 +36,7 @@ type RequiredProps = {| * An array (or array-like list) of items to render. Other data types can be * used by targeting VirtualizedList directly. */ - data: ?$ArrayLike, + data: ?$ReadOnly<$ArrayLike>, |}; type OptionalProps = {| /** @@ -91,7 +91,7 @@ type OptionalProps = {| * specify `ItemSeparatorComponent`. */ getItemLayout?: ( - data: ?$ArrayLike, + data: ?$ReadOnly<$ArrayLike>, index: number, ) => { length: number, diff --git a/packages/react-native/Libraries/Lists/FlatList.js.flow b/packages/react-native/Libraries/Lists/FlatList.js.flow deleted file mode 100644 index 304a1006182186..00000000000000 --- a/packages/react-native/Libraries/Lists/FlatList.js.flow +++ /dev/null @@ -1,116 +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 - */ - -const React = require('react'); -const View = require('../Components/View/View'); - -import typeof ScrollViewNativeComponent from '../Components/ScrollView/ScrollViewNativeComponent'; -import {type ScrollResponderType} from '../Components/ScrollView/ScrollView'; -import type {ViewStyleProp} from '../StyleSheet/StyleSheet'; -import type { - RenderItemType, - RenderItemProps, - ViewToken, - ViewabilityConfigCallbackPair, -} from '@react-native/virtualized-lists'; -import {typeof VirtualizedList} from '@react-native/virtualized-lists'; - -type RequiredProps = {| - /** - * For simplicity, data is just a plain array. If you want to use something else, like an - * immutable list, use the underlying `VirtualizedList` directly. - */ - data: ?$ReadOnlyArray, -|}; -type OptionalProps = {| - renderItem?: ?RenderItemType, - columnWrapperStyle?: ViewStyleProp, - extraData?: any, - getItemLayout?: ( - data: ?Array, - index: number, - ) => { - length: number, - offset: number, - index: number, - ... - }, - horizontal?: ?boolean, - initialNumToRender?: ?number, - initialScrollIndex?: ?number, - inverted?: ?boolean, - keyExtractor?: ?(item: ItemT, index: number) => string, - numColumns?: number, - removeClippedSubviews?: boolean, - fadingEdgeLength?: ?number, - strictMode?: boolean, -|}; - -/** - * Default Props Helper Functions - * Use the following helper functions for default values - */ -type FlatListProps = {| - ...RequiredProps, - ...OptionalProps, -|}; - -type VirtualizedListProps = React.ElementConfig; - -export type Props = { - ...$Diff< - VirtualizedListProps, - { - getItem: $PropertyType, - getItemCount: $PropertyType, - getItemLayout: $PropertyType, - renderItem: $PropertyType, - keyExtractor: $PropertyType, - ... - }, - >, - ...FlatListProps, - ... -}; - -declare class FlatList extends React.PureComponent, void> { - scrollToEnd(params?: ?{animated?: ?boolean, ...}): void; - - scrollToIndex(params: { - animated?: ?boolean, - index: number, - viewOffset?: number, - viewPosition?: number, - ... - }): void; - scrollToItem(params: { - animated?: ?boolean, - item: ItemT, - viewPosition?: number, - ... - }): void; - scrollToOffset(params: {animated?: ?boolean, offset: number, ...}): void; - recordInteraction(): void; - - /** - * Displays the scroll indicators momentarily. - * - * @platform ios - */ - flashScrollIndicators(): void; - getScrollResponder(): ?ScrollResponderType; - getNativeScrollRef(): - | ?React.ElementRef - | ?React.ElementRef; - getScrollableNode(): any; - setNativeProps(props: {[string]: mixed, ...}): void; -} - -module.exports = FlatList; diff --git a/packages/react-native/Libraries/Lists/SectionList.js b/packages/react-native/Libraries/Lists/SectionList.js index 0f199487b92a23..6177b07d58dec3 100644 --- a/packages/react-native/Libraries/Lists/SectionList.js +++ b/packages/react-native/Libraries/Lists/SectionList.js @@ -244,6 +244,10 @@ export default class SectionList< const stickySectionHeadersEnabled = _stickySectionHeadersEnabled ?? Platform.OS === 'ios'; return ( + /* $FlowFixMe[incompatible-type] Error revealed after improved builtin + * React utility types */ + /* $FlowFixMe[incompatible-type] Error revealed after improved builtin + * React utility types */ - - {props.text} - - + + + + {props.text} + + + ); } -const buttonStyles = StyleSheet.create({ - safeArea: { - flex: 1, - // $FlowFixMe[sketchy-null-bool] - paddingBottom: DeviceInfo.getConstants().isIPhoneX_deprecated ? 30 : 0, - }, - content: { - alignItems: 'center', - height: 48, - justifyContent: 'center', - }, - label: { - color: LogBoxStyle.getTextColor(1), - fontSize: 14, - includeFontPadding: false, - lineHeight: 20, - }, -}); - const styles = StyleSheet.create({ root: { backgroundColor: LogBoxStyle.getBackgroundColor(1), @@ -97,6 +79,17 @@ const styles = StyleSheet.create({ button: { flex: 1, }, + buttonContent: { + alignItems: 'center', + height: 48, + justifyContent: 'center', + }, + buttonLabel: { + color: LogBoxStyle.getTextColor(1), + fontSize: 14, + includeFontPadding: false, + lineHeight: 20, + }, syntaxErrorText: { textAlign: 'center', width: '100%', diff --git a/packages/react-native/Libraries/LogBox/UI/LogBoxMessage.js b/packages/react-native/Libraries/LogBox/UI/LogBoxMessage.js index 805b47efec8987..096960c0e68cf9 100644 --- a/packages/react-native/Libraries/LogBox/UI/LogBoxMessage.js +++ b/packages/react-native/Libraries/LogBox/UI/LogBoxMessage.js @@ -138,17 +138,14 @@ function LogBoxMessage(props: Props): React.Node { const key = String(index); if (substitution.offset > prevOffset) { - const prevPart = content.substr( - prevOffset, - substitution.offset - prevOffset, - ); + const prevPart = content.slice(prevOffset, substitution.offset); createUnderLength(key, prevPart); } - const substitutionPart = content.substr( + const substitutionPart = content.slice( substitution.offset, - substitution.length, + substitution.offset + substitution.length, ); createUnderLength(key + '.5', substitutionPart, substitutionStyle); @@ -156,7 +153,7 @@ function LogBoxMessage(props: Props): React.Node { }, 0); if (lastOffset < content.length) { - const lastPart = content.substr(lastOffset); + const lastPart = content.slice(lastOffset); createUnderLength('-1', lastPart); } diff --git a/packages/react-native/Libraries/NativeComponent/BaseViewConfig.android.js b/packages/react-native/Libraries/NativeComponent/BaseViewConfig.android.js index 5cd505439ea78b..fef57a1aea9a91 100644 --- a/packages/react-native/Libraries/NativeComponent/BaseViewConfig.android.js +++ b/packages/react-native/Libraries/NativeComponent/BaseViewConfig.android.js @@ -179,6 +179,7 @@ const validAttributesForNonEventProps = { accessibilityActions: true, accessibilityValue: true, importantForAccessibility: true, + role: true, rotation: true, scaleX: true, scaleY: true, diff --git a/packages/react-native/Libraries/NativeComponent/BaseViewConfig.ios.js b/packages/react-native/Libraries/NativeComponent/BaseViewConfig.ios.js index 9c1e72fa1a1ab4..bb13443bf44a2d 100644 --- a/packages/react-native/Libraries/NativeComponent/BaseViewConfig.ios.js +++ b/packages/react-native/Libraries/NativeComponent/BaseViewConfig.ios.js @@ -198,6 +198,7 @@ const validAttributesForNonEventProps = { nativeID: true, pointerEvents: true, removeClippedSubviews: true, + role: true, borderRadius: true, borderColor: {process: require('../StyleSheet/processColor').default}, borderCurve: true, diff --git a/packages/react-native/Libraries/ReactNative/AppRegistry.d.ts b/packages/react-native/Libraries/ReactNative/AppRegistry.d.ts index fabfa126654537..b75715c6abc8ea 100644 --- a/packages/react-native/Libraries/ReactNative/AppRegistry.d.ts +++ b/packages/react-native/Libraries/ReactNative/AppRegistry.d.ts @@ -85,11 +85,6 @@ export namespace AppRegistry { displayMode?: number, ): void; - export function registerHeadlessTask( - appKey: string, - task: TaskProvider, - ): void; - export function getRunnable(appKey: string): Runnable | undefined; export function getRegistry(): {sections: string[]; runnables: Runnable[]}; diff --git a/packages/react-native/Libraries/ReactNative/AppRegistry.js b/packages/react-native/Libraries/ReactNative/AppRegistry.js index af3fa3aaf5cdfd..011bb45d45c84c 100644 --- a/packages/react-native/Libraries/ReactNative/AppRegistry.js +++ b/packages/react-native/Libraries/ReactNative/AppRegistry.js @@ -10,6 +10,7 @@ import type {RootTag} from '../Types/RootTagTypes'; import type {IPerformanceLogger} from '../Utilities/createPerformanceLogger'; +import type {DisplayModeType} from './DisplayMode'; import BatchedBridge from '../BatchedBridge/BatchedBridge'; import BugReporting from '../BugReporting/BugReporting'; @@ -36,23 +37,28 @@ export type ComponentProviderInstrumentationHook = ( export type AppConfig = { appKey: string, component?: ComponentProvider, - run?: Function, + run?: Runnable, section?: boolean, ... }; -export type Runnable = { - component?: ComponentProvider, - run: Function, - ... +type AppParameters = { + initialProps: $ReadOnly<{[string]: mixed, ...}>, + rootTag: RootTag, + fabric?: boolean, + concurrentRoot?: boolean, }; -export type Runnables = {[appKey: string]: Runnable, ...}; +export type Runnable = ( + appParameters: AppParameters, + displayMode: DisplayModeType, +) => void; +export type Runnables = {[appKey: string]: Runnable}; export type Registry = { - sections: Array, + sections: $ReadOnlyArray, runnables: Runnables, ... }; export type WrapperComponentProvider = ( - appParameters: any, + appParameters: Object, ) => React$ComponentType; const runnables: Runnables = {}; @@ -110,30 +116,28 @@ const AppRegistry = { componentProvider: ComponentProvider, section?: boolean, ): string { - let scopedPerformanceLogger = createPerformanceLogger(); - runnables[appKey] = { - componentProvider, - run: (appParameters, displayMode) => { - const concurrentRootEnabled = - appParameters.initialProps?.concurrentRoot || - appParameters.concurrentRoot; - renderApplication( - componentProviderInstrumentationHook( - componentProvider, - scopedPerformanceLogger, - ), - appParameters.initialProps, - appParameters.rootTag, - wrapperComponentProvider && wrapperComponentProvider(appParameters), - appParameters.fabric, - showArchitectureIndicator, + const scopedPerformanceLogger = createPerformanceLogger(); + runnables[appKey] = (appParameters, displayMode) => { + const concurrentRootEnabled = Boolean( + appParameters.initialProps?.concurrentRoot || + appParameters.concurrentRoot, + ); + renderApplication( + componentProviderInstrumentationHook( + componentProvider, scopedPerformanceLogger, - appKey === 'LogBox', - appKey, - coerceDisplayMode(displayMode), - concurrentRootEnabled, - ); - }, + ), + appParameters.initialProps, + appParameters.rootTag, + wrapperComponentProvider && wrapperComponentProvider(appParameters), + appParameters.fabric, + showArchitectureIndicator, + scopedPerformanceLogger, + appKey === 'LogBox', // is logbox + appKey, + displayMode, + concurrentRootEnabled, + ); }; if (section) { sections[appKey] = runnables[appKey]; @@ -141,8 +145,8 @@ const AppRegistry = { return appKey; }, - registerRunnable(appKey: string, run: Function): string { - runnables[appKey] = {run}; + registerRunnable(appKey: string, run: Runnable): string { + runnables[appKey] = run; return appKey; }, @@ -150,11 +154,11 @@ const AppRegistry = { AppRegistry.registerComponent(appKey, component, true); }, - getAppKeys(): Array { + getAppKeys(): $ReadOnlyArray { return Object.keys(runnables); }, - getSectionKeys(): Array { + getSectionKeys(): $ReadOnlyArray { return Object.keys(sections); }, @@ -188,7 +192,7 @@ const AppRegistry = { */ runApplication( appKey: string, - appParameters: any, + appParameters: AppParameters, displayMode?: number, ): void { if (appKey !== 'LogBox') { @@ -203,7 +207,7 @@ const AppRegistry = { ); } invariant( - runnables[appKey] && runnables[appKey].run, + runnables[appKey], `"${appKey}" has not been registered. This can happen if:\n` + '* Metro (the local dev server) is run from the wrong folder. ' + 'Check if Metro is running, stop it and restart it in the current project.\n' + @@ -211,7 +215,7 @@ const AppRegistry = { ); SceneTracker.setActiveScene({name: appKey}); - runnables[appKey].run(appParameters, displayMode); + runnables[appKey](appParameters, coerceDisplayMode(displayMode)); }, /** @@ -219,7 +223,7 @@ const AppRegistry = { */ setSurfaceProps( appKey: string, - appParameters: any, + appParameters: Object, displayMode?: number, ): void { if (appKey !== 'LogBox') { @@ -235,14 +239,14 @@ const AppRegistry = { ); } invariant( - runnables[appKey] && runnables[appKey].run, + runnables[appKey], `"${appKey}" has not been registered. This can happen if:\n` + '* Metro (the local dev server) is run from the wrong folder. ' + 'Check if Metro is running, stop it and restart it in the current project.\n' + "* A module failed to load due to an error and `AppRegistry.registerComponent` wasn't called.", ); - runnables[appKey].run(appParameters, displayMode); + runnables[appKey](appParameters, coerceDisplayMode(displayMode)); }, /** @@ -338,18 +342,27 @@ const AppRegistry = { }, }; -if (!(global.RN$Bridgeless === true)) { - BatchedBridge.registerCallableModule('AppRegistry', AppRegistry); +// Register LogBox as a default surface +AppRegistry.registerComponent('LogBox', () => { + if (__DEV__ && typeof jest === 'undefined') { + return require('../LogBox/LogBoxInspectorContainer').default; + } else { + return function NoOp() { + return null; + }; + } +}); - AppRegistry.registerComponent('LogBox', () => { - if (__DEV__) { - return require('../LogBox/LogBoxInspectorContainer').default; - } else { - return function NoOp() { - return null; - }; - } - }); +global.RN$AppRegistry = AppRegistry; + +// Backwards compat with SurfaceRegistry, remove me later +global.RN$SurfaceRegistry = { + renderSurface: AppRegistry.runApplication, + setSurfaceProps: AppRegistry.setSurfaceProps, +}; + +if (global.RN$Bridgeless !== true) { + BatchedBridge.registerCallableModule('AppRegistry', AppRegistry); } module.exports = AppRegistry; diff --git a/packages/react-native/Libraries/ReactNative/ReactFabricPublicInstance/__tests__/ReactFabricPublicInstance-test.js b/packages/react-native/Libraries/ReactNative/ReactFabricPublicInstance/__tests__/ReactFabricPublicInstance-test.js index a9684999cc8101..ea645dd3c87e10 100644 --- a/packages/react-native/Libraries/ReactNative/ReactFabricPublicInstance/__tests__/ReactFabricPublicInstance-test.js +++ b/packages/react-native/Libraries/ReactNative/ReactFabricPublicInstance/__tests__/ReactFabricPublicInstance-test.js @@ -157,7 +157,7 @@ async function mockRenderKeys( }); describe('measure', () => { - test('component.measure(...) invokes callback', async () => { + itif(!isWindows)('component.measure(...) invokes callback', async () => { const result = await mockRenderKeys([['foo']]); const fooRef = nullthrows(result?.[0]?.[0]); @@ -170,7 +170,7 @@ async function mockRenderKeys( expect(callback.mock.calls).toEqual([[10, 10, 100, 100, 0, 0]]); }); - test('unmounted.measure(...) does nothing', async () => { + itif(!isWindows)('unmounted.measure(...) does nothing', async () => { const result = await mockRenderKeys([['foo'], null]); const fooRef = nullthrows(result?.[0]?.[0]); const callback = jest.fn(); @@ -184,18 +184,21 @@ async function mockRenderKeys( }); describe('measureInWindow', () => { - it('component.measureInWindow(...) invokes callback', async () => { - const result = await mockRenderKeys([['foo']]); - const fooRef = nullthrows(result?.[0]?.[0]); + itif(!isWindows)( + 'component.measureInWindow(...) invokes callback', + async () => { + const result = await mockRenderKeys([['foo']]); + const fooRef = nullthrows(result?.[0]?.[0]); - const callback = jest.fn(); - fooRef.measureInWindow(callback); + const callback = jest.fn(); + fooRef.measureInWindow(callback); - expect( - nullthrows(FabricUIManager.getFabricUIManager()).measureInWindow, - ).toHaveBeenCalledTimes(1); - expect(callback.mock.calls).toEqual([[10, 10, 100, 100]]); - }); + expect( + nullthrows(FabricUIManager.getFabricUIManager()).measureInWindow, + ).toHaveBeenCalledTimes(1); + expect(callback.mock.calls).toEqual([[10, 10, 100, 100]]); + }, + ); itif(!isWindows)( 'unmounted.measureInWindow(...) does nothing', @@ -215,71 +218,83 @@ async function mockRenderKeys( }); describe('measureLayout', () => { - test('component.measureLayout(component, ...) invokes callback', async () => { - const result = await mockRenderKeys([['foo', 'bar']]); - const fooRef = nullthrows(result?.[0]?.[0]); - const barRef = nullthrows(result?.[0]?.[1]); + itif(!isWindows)( + 'component.measureLayout(component, ...) invokes callback', + async () => { + const result = await mockRenderKeys([['foo', 'bar']]); + const fooRef = nullthrows(result?.[0]?.[0]); + const barRef = nullthrows(result?.[0]?.[1]); - const successCallback = jest.fn(); - const failureCallback = jest.fn(); - fooRef.measureLayout(barRef, successCallback, failureCallback); + const successCallback = jest.fn(); + const failureCallback = jest.fn(); + fooRef.measureLayout(barRef, successCallback, failureCallback); - expect( - nullthrows(FabricUIManager.getFabricUIManager()).measureLayout, - ).toHaveBeenCalledTimes(1); - expect(successCallback.mock.calls).toEqual([[1, 1, 100, 100]]); - }); + expect( + nullthrows(FabricUIManager.getFabricUIManager()).measureLayout, + ).toHaveBeenCalledTimes(1); + expect(successCallback.mock.calls).toEqual([[1, 1, 100, 100]]); + }, + ); - test('unmounted.measureLayout(component, ...) does nothing', async () => { - const result = await mockRenderKeys([ - ['foo', 'bar'], - ['foo', null], - ]); - const fooRef = nullthrows(result?.[0]?.[0]); - const barRef = nullthrows(result?.[0]?.[1]); + itif(!isWindows)( + 'unmounted.measureLayout(component, ...) does nothing', + async () => { + const result = await mockRenderKeys([ + ['foo', 'bar'], + ['foo', null], + ]); + const fooRef = nullthrows(result?.[0]?.[0]); + const barRef = nullthrows(result?.[0]?.[1]); - const successCallback = jest.fn(); - const failureCallback = jest.fn(); - fooRef.measureLayout(barRef, successCallback, failureCallback); + const successCallback = jest.fn(); + const failureCallback = jest.fn(); + fooRef.measureLayout(barRef, successCallback, failureCallback); - expect( - nullthrows(FabricUIManager.getFabricUIManager()).measureLayout, - ).not.toHaveBeenCalled(); - expect(successCallback).not.toHaveBeenCalled(); - }); + expect( + nullthrows(FabricUIManager.getFabricUIManager()).measureLayout, + ).not.toHaveBeenCalled(); + expect(successCallback).not.toHaveBeenCalled(); + }, + ); - test('component.measureLayout(unmounted, ...) does nothing', async () => { - const result = await mockRenderKeys([ - ['foo', 'bar'], - [null, 'bar'], - ]); - const fooRef = nullthrows(result?.[0]?.[0]); - const barRef = nullthrows(result?.[0]?.[1]); + itif(!isWindows)( + 'component.measureLayout(unmounted, ...) does nothing', + async () => { + const result = await mockRenderKeys([ + ['foo', 'bar'], + [null, 'bar'], + ]); + const fooRef = nullthrows(result?.[0]?.[0]); + const barRef = nullthrows(result?.[0]?.[1]); - const successCallback = jest.fn(); - const failureCallback = jest.fn(); - fooRef.measureLayout(barRef, successCallback, failureCallback); + const successCallback = jest.fn(); + const failureCallback = jest.fn(); + fooRef.measureLayout(barRef, successCallback, failureCallback); - expect( - nullthrows(FabricUIManager.getFabricUIManager()).measureLayout, - ).not.toHaveBeenCalled(); - expect(successCallback).not.toHaveBeenCalled(); - }); + expect( + nullthrows(FabricUIManager.getFabricUIManager()).measureLayout, + ).not.toHaveBeenCalled(); + expect(successCallback).not.toHaveBeenCalled(); + }, + ); - test('unmounted.measureLayout(unmounted, ...) does nothing', async () => { - const result = await mockRenderKeys([['foo', 'bar'], null]); - const fooRef = nullthrows(result?.[0]?.[0]); - const barRef = nullthrows(result?.[0]?.[1]); + itif(!isWindows)( + 'unmounted.measureLayout(unmounted, ...) does nothing', + async () => { + const result = await mockRenderKeys([['foo', 'bar'], null]); + const fooRef = nullthrows(result?.[0]?.[0]); + const barRef = nullthrows(result?.[0]?.[1]); - const successCallback = jest.fn(); - const failureCallback = jest.fn(); - fooRef.measureLayout(barRef, successCallback, failureCallback); + const successCallback = jest.fn(); + const failureCallback = jest.fn(); + fooRef.measureLayout(barRef, successCallback, failureCallback); - expect( - nullthrows(FabricUIManager.getFabricUIManager()).measureLayout, - ).not.toHaveBeenCalled(); - expect(successCallback).not.toHaveBeenCalled(); - }); + expect( + nullthrows(FabricUIManager.getFabricUIManager()).measureLayout, + ).not.toHaveBeenCalled(); + expect(successCallback).not.toHaveBeenCalled(); + }, + ); }); }); }); diff --git a/packages/react-native/Libraries/Renderer/REVISION b/packages/react-native/Libraries/Renderer/REVISION index 79bd29cdb09d2d..03bc83933f6c18 100644 --- a/packages/react-native/Libraries/Renderer/REVISION +++ b/packages/react-native/Libraries/Renderer/REVISION @@ -1 +1 @@ -ec5e9c2a75749b0a470b7148738cb85bbb035958 +a389046a529c6d22ba5895dd7f5d4b0b8d17c345 diff --git a/packages/react-native/Libraries/Renderer/shims/ReactFabric.js b/packages/react-native/Libraries/Renderer/shims/ReactFabric.js index 8385a61ac40f4b..96f4a83be29cef 100644 --- a/packages/react-native/Libraries/Renderer/shims/ReactFabric.js +++ b/packages/react-native/Libraries/Renderer/shims/ReactFabric.js @@ -7,7 +7,7 @@ * @noformat * @flow * @nolint - * @generated SignedSource<> + * @generated SignedSource<> */ 'use strict'; @@ -24,9 +24,9 @@ if (__DEV__) { ReactFabric = require('../implementations/ReactFabric-prod'); } -if (global.RN$Bridgeless) { - global.RN$stopSurface = ReactFabric.stopSurface; -} else { +global.RN$stopSurface = ReactFabric.stopSurface; + +if (global.RN$Bridgeless !== true) { BatchedBridge.registerCallableModule('ReactFabric', ReactFabric); } diff --git a/packages/react-native/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js b/packages/react-native/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js index 74512b72977a3b..b5894d72c7a2ff 100644 --- a/packages/react-native/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js +++ b/packages/react-native/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js @@ -7,7 +7,7 @@ * @noformat * @flow strict-local * @nolint - * @generated SignedSource<> + * @generated SignedSource<<1b39316520f5af25f0a141d7d78b0809>> */ 'use strict'; @@ -108,6 +108,7 @@ exports.get = function (name: string): ViewConfig { 'View config getter callback for component `%s` must be a function (received `%s`).%s', name, callback === null ? 'null' : typeof callback, + // $FlowFixMe[recursive-definition] typeof name[0] === 'string' && /[a-z]/.test(name[0]) ? ' Make sure to start component names with a capital letter.' : '', diff --git a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts index df6b5c4afdaf86..8eb5e3c1e76ec7 100644 --- a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts +++ b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts @@ -18,7 +18,7 @@ type FlexAlignType = | 'stretch' | 'baseline'; -type DimensionValue = +export type DimensionValue = | number | 'auto' | `${number}%` @@ -69,13 +69,6 @@ export interface FlexStyle { flexShrink?: number | undefined; flexWrap?: 'wrap' | 'nowrap' | 'wrap-reverse' | undefined; height?: DimensionValue | undefined; - inset?: DimensionValue | undefined; - insetBlock?: DimensionValue | undefined; - insetBlockEnd?: DimensionValue | undefined; - insetBlockStart?: DimensionValue | undefined; - insetInline?: DimensionValue | undefined; - insetInlineEnd?: DimensionValue | undefined; - insetInlineStart?: DimensionValue | undefined; justifyContent?: | 'flex-start' | 'flex-end' @@ -86,15 +79,9 @@ export interface FlexStyle { | undefined; left?: DimensionValue | undefined; margin?: DimensionValue | undefined; - marginBlock?: DimensionValue | undefined; - marginBlockEnd?: DimensionValue | undefined; - marginBlockStart?: DimensionValue | undefined; marginBottom?: DimensionValue | undefined; marginEnd?: DimensionValue | undefined; marginHorizontal?: DimensionValue | undefined; - marginInline?: DimensionValue | undefined; - marginInlineEnd?: DimensionValue | undefined; - marginInlineStart?: DimensionValue | undefined; marginLeft?: DimensionValue | undefined; marginRight?: DimensionValue | undefined; marginStart?: DimensionValue | undefined; @@ -107,14 +94,8 @@ export interface FlexStyle { overflow?: 'visible' | 'hidden' | 'scroll' | undefined; padding?: DimensionValue | undefined; paddingBottom?: DimensionValue | undefined; - paddingBlock?: DimensionValue | undefined; - paddingBlockEnd?: DimensionValue | undefined; - paddingBlockStart?: DimensionValue | undefined; paddingEnd?: DimensionValue | undefined; paddingHorizontal?: DimensionValue | undefined; - paddingInline?: DimensionValue | undefined; - paddingInlineEnd?: DimensionValue | undefined; - paddingInlineStart?: DimensionValue | undefined; paddingLeft?: DimensionValue | undefined; paddingRight?: DimensionValue | undefined; paddingStart?: DimensionValue | undefined; diff --git a/packages/react-native/Libraries/Utilities/PolyfillFunctions.js b/packages/react-native/Libraries/Utilities/PolyfillFunctions.js index 61c6d8b8d491ac..09ae9658f7b561 100644 --- a/packages/react-native/Libraries/Utilities/PolyfillFunctions.js +++ b/packages/react-native/Libraries/Utilities/PolyfillFunctions.js @@ -32,7 +32,7 @@ function polyfillObjectProperty( ): void { const descriptor = Object.getOwnPropertyDescriptor<$FlowFixMe>(object, name); if (__DEV__ && descriptor) { - const backupName = `original${name[0].toUpperCase()}${name.substr(1)}`; + const backupName = `original${name[0].toUpperCase()}${name.slice(1)}`; Object.defineProperty(object, backupName, descriptor); } diff --git a/packages/react-native/Libraries/Utilities/createPerformanceLogger.js b/packages/react-native/Libraries/Utilities/createPerformanceLogger.js index 8891b4d1ac874c..0c09c750c7f094 100644 --- a/packages/react-native/Libraries/Utilities/createPerformanceLogger.js +++ b/packages/react-native/Libraries/Utilities/createPerformanceLogger.js @@ -16,7 +16,6 @@ import type { } from './IPerformanceLogger'; import * as Systrace from '../Performance/Systrace'; -import Performance from '../WebPerformance/Performance'; import infoLog from './infoLog'; const _cookies: {[key: string]: number, ...} = {}; @@ -27,9 +26,6 @@ const PRINT_TO_CONSOLE: false = false; // Type as false to prevent accidentally // used to separate these internally from other marks/measures const WEB_PERFORMANCE_PREFIX = 'global_perf_'; -// TODO: Remove once T143070419 is done -const performance = new Performance(); - export const getCurrentTimestamp: () => number = global.nativeQPLTimestamp ?? global.performance.now.bind(global.performance); diff --git a/packages/react-native/React/Base/RCTBridge.h b/packages/react-native/React/Base/RCTBridge.h index 9df17ebc5528ea..2a55a8a730d33f 100644 --- a/packages/react-native/React/Base/RCTBridge.h +++ b/packages/react-native/React/Base/RCTBridge.h @@ -56,6 +56,14 @@ RCT_EXTERN void RCTEnableTurboModuleEagerInit(BOOL enabled); RCT_EXTERN BOOL RCTTurboModuleManagerDelegateLockingDisabled(void); RCT_EXTERN void RCTDisableTurboModuleManagerDelegateLocking(BOOL enabled); +// Turn on TurboModule interop +RCT_EXTERN BOOL RCTTurboModuleInteropEnabled(void); +RCT_EXTERN void RCTEnableTurboModuleInterop(BOOL enabled); + +// Route all TurboModules through TurboModule interop +RCT_EXTERN BOOL RCTTurboModuleInteropForAllTurboModulesEnabled(void); +RCT_EXTERN void RCTEnableTurboModuleInteropForAllTurboModules(BOOL enabled); + typedef enum { kRCTGlobalScope, kRCTGlobalScopeUsingRetainJSCallback, @@ -133,11 +141,11 @@ RCT_EXTERN void RCTSetTurboModuleCleanupMode(RCTTurboModuleCleanupMode mode); - (void)setRCTTurboModuleRegistry:(id)turboModuleRegistry; /** - * This hook is called by the TurboModule infra with every TurboModule that's created. - * It allows the bridge to attach properties to TurboModules that give TurboModules + * This hook is called by the TurboModule infra with every ObjC module that's created. + * It allows the bridge to attach properties to ObjC modules that give those modules * access to Bridge APIs. */ -- (void)attachBridgeAPIsToTurboModule:(id)module; +- (void)attachBridgeAPIsToObjCModule:(id)module; /** * Convenience method for retrieving all modules conforming to a given protocol. diff --git a/packages/react-native/React/Base/RCTBridge.m b/packages/react-native/React/Base/RCTBridge.m index 702e338aa5ac08..b7eb3d7129031d 100644 --- a/packages/react-native/React/Base/RCTBridge.m +++ b/packages/react-native/React/Base/RCTBridge.m @@ -120,6 +120,26 @@ void RCTDisableTurboModuleManagerDelegateLocking(BOOL disabled) turboModuleManagerDelegateLockingDisabled = disabled; } +static BOOL turboModuleInteropEnabled = NO; +BOOL RCTTurboModuleInteropEnabled(void) +{ + return turboModuleInteropEnabled; +} +void RCTEnableTurboModuleInterop(BOOL enabled) +{ + turboModuleInteropEnabled = enabled; +} + +static BOOL useTurboModuleInteropForAllTurboModules = NO; +BOOL RCTTurboModuleInteropForAllTurboModulesEnabled(void) +{ + return useTurboModuleInteropForAllTurboModules; +} +void RCTEnableTurboModuleInteropForAllTurboModules(BOOL enabled) +{ + useTurboModuleInteropForAllTurboModules = enabled; +} + @interface RCTBridge () @end @@ -195,9 +215,9 @@ - (void)setRCTTurboModuleRegistry:(id)turboModuleRegistr [self.batchedBridge setRCTTurboModuleRegistry:turboModuleRegistry]; } -- (void)attachBridgeAPIsToTurboModule:(id)module +- (void)attachBridgeAPIsToObjCModule:(id)module { - [self.batchedBridge attachBridgeAPIsToTurboModule:module]; + [self.batchedBridge attachBridgeAPIsToObjCModule:module]; } - (void)didReceiveReloadCommand diff --git a/packages/react-native/React/Base/RCTJSScriptLoaderModule.h b/packages/react-native/React/Base/RCTJSScriptLoaderModule.h deleted file mode 100644 index f05d361a579411..00000000000000 --- a/packages/react-native/React/Base/RCTJSScriptLoaderModule.h +++ /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. - */ - -@class RCTSource; - -NS_ASSUME_NONNULL_BEGIN - -/** - * This protocol should be adopted when a turbo module needs to tell React Native to load a script. - * In bridge-less React Native, it is a replacement for [_bridge loadAndExecuteSplitBundleURL:]. - */ -@protocol RCTJSScriptLoaderModule - -@property (nonatomic, copy) void (^loadScript)(RCTSource *source); - -@end - -NS_ASSUME_NONNULL_END diff --git a/packages/react-native/React/Base/RCTRootView.h b/packages/react-native/React/Base/RCTRootView.h index 32eeb7ab007dcb..6ed9c5b8fc48f2 100644 --- a/packages/react-native/React/Base/RCTRootView.h +++ b/packages/react-native/React/Base/RCTRootView.h @@ -133,6 +133,11 @@ extern */ @property (nonatomic, weak, nullable) UIViewController *reactViewController; +/** + * The root view casted as UIView. Used by splash screen libraries. + */ +@property (nonatomic, strong, readonly) UIView *view; + /** * The React-managed contents view of the root view. */ diff --git a/packages/react-native/React/Base/RCTRootView.m b/packages/react-native/React/Base/RCTRootView.m index 5cb98b5ce9794d..a7b9b22881543f 100644 --- a/packages/react-native/React/Base/RCTRootView.m +++ b/packages/react-native/React/Base/RCTRootView.m @@ -116,6 +116,11 @@ - (instancetype)initWithBundleURL:(NSURL *)bundleURL RCT_NOT_IMPLEMENTED(-(instancetype)initWithFrame : (CGRect)frame) RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder) +- (UIView *)view +{ + return self; +} + - (BOOL)hasBridge { return _bridge != nil; diff --git a/packages/react-native/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.h b/packages/react-native/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.h index 3b2f7911464015..bb5a574e2ee1f5 100644 --- a/packages/react-native/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.h +++ b/packages/react-native/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.h @@ -34,6 +34,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, assign) RCTRootViewSizeFlexibility sizeFlexibility; @property (nonatomic, weak) id delegate; @property (nonatomic, weak) UIViewController *reactViewController; +@property (nonatomic, strong, readonly) UIView *view; @property (nonatomic, strong, readonly) UIView *contentView; @property (nonatomic, strong) UIView *loadingView; @property (nonatomic, assign) BOOL passThroughTouches; diff --git a/packages/react-native/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.mm b/packages/react-native/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.mm index 8f48551167f398..91ead4e7492774 100644 --- a/packages/react-native/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.mm +++ b/packages/react-native/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.mm @@ -134,6 +134,11 @@ - (NSString *)moduleName return super.surface.moduleName; } +- (UIView *)view +{ + return (UIView *)super.surface.view; +} + - (UIView *)contentView { return self; diff --git a/packages/react-native/React/CoreModules/RCTDevLoadingView.mm b/packages/react-native/React/CoreModules/RCTDevLoadingView.mm index 8ad0fc0d327562..02bdb96e1d507c 100644 --- a/packages/react-native/React/CoreModules/RCTDevLoadingView.mm +++ b/packages/react-native/React/CoreModules/RCTDevLoadingView.mm @@ -25,7 +25,7 @@ @interface RCTDevLoadingView () @end -#if RCT_DEV | RCT_ENABLE_LOADING_VIEW +#if RCT_DEV_MENU @implementation RCTDevLoadingView { UIWindow *_window; @@ -35,8 +35,6 @@ @implementation RCTDevLoadingView { dispatch_block_t _initialMessageBlock; } -@synthesize bundleManager = _bundleManager; - RCT_EXPORT_MODULE() - (instancetype)init @@ -66,15 +64,15 @@ + (BOOL)requiresMainQueueSetup - (void)clearInitialMessageDelay { - if (self->_initialMessageBlock != nil) { - dispatch_block_cancel(self->_initialMessageBlock); - self->_initialMessageBlock = nil; + if (_initialMessageBlock != nil) { + dispatch_block_cancel(_initialMessageBlock); + _initialMessageBlock = nil; } } - (void)showInitialMessageDelayed:(void (^)())initialMessage { - self->_initialMessageBlock = dispatch_block_create(static_cast(0), initialMessage); + _initialMessageBlock = dispatch_block_create(static_cast(0), initialMessage); // We delay the initial loading message to prevent flashing it // when loading progress starts quickly. To do that, we @@ -85,28 +83,9 @@ - (void)showInitialMessageDelayed:(void (^)())initialMessage dispatch_time(DISPATCH_TIME_NOW, 0.2 * NSEC_PER_SEC), dispatch_get_main_queue(), self->_initialMessageBlock); } -- (UIColor *)dimColor:(UIColor *)c -{ - // Given a color, return a slightly lighter or darker color for dim effect. - CGFloat h, s, b, a; - if ([c getHue:&h saturation:&s brightness:&b alpha:&a]) - return [UIColor colorWithHue:h saturation:s brightness:b < 0.5 ? b * 1.25 : b * 0.75 alpha:a]; - return nil; -} - -- (NSString *)getTextForHost -{ - NSURL *bundleURL = _bundleManager.bundleURL; - if (bundleURL == nil || bundleURL.fileURL) { - return @"React Native"; - } - - return [NSString stringWithFormat:@"%@:%@", bundleURL.host, bundleURL.port]; -} - - (void)showMessage:(NSString *)message color:(UIColor *)color backgroundColor:(UIColor *)backgroundColor { - if (!RCTDevLoadingViewGetEnabled() || self->_hiding) { + if (!RCTDevLoadingViewGetEnabled() || _hiding) { return; } @@ -173,7 +152,7 @@ - (void)showMessage:(NSString *)message color:(UIColor *)color backgroundColor:( [self clearInitialMessageDelay]; dispatch_async(dispatch_get_main_queue(), ^{ - self->_hiding = true; + self->_hiding = YES; const NSTimeInterval MIN_PRESENTED_TIME = 0.6; NSTimeInterval presentedTime = [[NSDate date] timeIntervalSinceDate:self->_showDate]; NSTimeInterval delay = MAX(0, MIN_PRESENTED_TIME - presentedTime); @@ -195,11 +174,11 @@ - (void)showMessage:(NSString *)message color:(UIColor *)color backgroundColor:( - (void)showProgressMessage:(NSString *)message { - if (self->_window != nil) { + if (_window != nil) { // This is an optimization. Since the progress can come in quickly, // we want to do the minimum amount of work to update the UI, // which is to only update the label text. - self->_label.text = message; + _label.text = message; return; } diff --git a/packages/react-native/React/CoreModules/RCTDevSettings.mm b/packages/react-native/React/CoreModules/RCTDevSettings.mm index e19a810d877364..d9b03ed38744b2 100644 --- a/packages/react-native/React/CoreModules/RCTDevSettings.mm +++ b/packages/react-native/React/CoreModules/RCTDevSettings.mm @@ -394,13 +394,9 @@ - (void)_profilingSettingDidChange #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" if (enabled) { - if (self.callableJSModules) { - [self.callableJSModules invokeModule:@"HMRClient" method:@"enable" withArgs:@[]]; - } + [self.callableJSModules invokeModule:@"HMRClient" method:@"enable" withArgs:@[]]; } else { - if (self.callableJSModules) { - [self.callableJSModules invokeModule:@"HMRClient" method:@"disable" withArgs:@[]]; - } + [self.callableJSModules invokeModule:@"HMRClient" method:@"disable" withArgs:@[]]; } #pragma clang diagnostic pop } @@ -483,22 +479,18 @@ - (void)setupHMRClientWithBundleURL:(NSURL *)bundleURL NSNumber *const port = urlComponents.port; NSString *const scheme = urlComponents.scheme; BOOL isHotLoadingEnabled = self.isHotLoadingEnabled; - if (self.callableJSModules) { - [self.callableJSModules invokeModule:@"HMRClient" - method:@"setup" - withArgs:@[ @"ios", path, host, RCTNullIfNil(port), @(isHotLoadingEnabled), scheme ]]; - } + [self.callableJSModules invokeModule:@"HMRClient" + method:@"setup" + withArgs:@[ @"ios", path, host, RCTNullIfNil(port), @(isHotLoadingEnabled), scheme ]]; } } - (void)setupHMRClientWithAdditionalBundleURL:(NSURL *)bundleURL { if (bundleURL && !bundleURL.fileURL) { // isHotLoadingAvailable check - if (self.callableJSModules) { - [self.callableJSModules invokeModule:@"HMRClient" - method:@"registerBundle" - withArgs:@[ [bundleURL absoluteString] ]]; - } + [self.callableJSModules invokeModule:@"HMRClient" + method:@"registerBundle" + withArgs:@[ [bundleURL absoluteString] ]]; } } diff --git a/packages/react-native/React/CxxBridge/RCTCxxBridge.mm b/packages/react-native/React/CxxBridge/RCTCxxBridge.mm index 45c29a24fc9467..d47c4aece7d309 100644 --- a/packages/react-native/React/CxxBridge/RCTCxxBridge.mm +++ b/packages/react-native/React/CxxBridge/RCTCxxBridge.mm @@ -64,7 +64,7 @@ #import #endif -#if (RCT_DEV | RCT_ENABLE_LOADING_VIEW) && __has_include() +#if RCT_DEV_MENU && __has_include() #import #endif @@ -245,14 +245,14 @@ - (void)setRCTTurboModuleRegistry:(id)turboModuleRegistr [_objCModuleRegistry setTurboModuleRegistry:_turboModuleRegistry]; } -- (void)attachBridgeAPIsToTurboModule:(id)module +- (void)attachBridgeAPIsToObjCModule:(id)module { RCTBridgeModuleDecorator *bridgeModuleDecorator = [[RCTBridgeModuleDecorator alloc] initWithViewRegistry:_viewRegistry_DEPRECATED moduleRegistry:_objCModuleRegistry bundleManager:_bundleManager callableJSModules:_callableJSModules]; - [bridgeModuleDecorator attachInteropAPIsToModule:(id)module]; + [bridgeModuleDecorator attachInteropAPIsToModule:module]; } - (std::shared_ptr)jsMessageThread @@ -476,7 +476,7 @@ - (void)start dispatch_group_enter(prepareBridge); __block NSData *sourceCode; -#if (RCT_DEV | RCT_ENABLE_LOADING_VIEW) && __has_include() +#if RCT_DEV_MENU && __has_include() { id loadingView = [self moduleForName:@"DevLoadingView" lazilyLoadIfNecessary:YES]; [loadingView showWithURL:self.bundleURL]; @@ -493,7 +493,7 @@ - (void)start dispatch_group_leave(prepareBridge); } onProgress:^(RCTLoadingProgress *progressData) { -#if (RCT_DEV | RCT_ENABLE_LOADING_VIEW) && __has_include() +#if RCT_DEV_MENU && __has_include() id loadingView = [weakSelf moduleForName:@"DevLoadingView" lazilyLoadIfNecessary:YES]; [loadingView updateProgress:progressData]; @@ -1092,7 +1092,7 @@ - (void)loadAndExecuteSplitBundleURL:(NSURL *)bundleURL __weak __typeof(self) weakSelf = self; [RCTJavaScriptLoader loadBundleAtURL:bundleURL onProgress:^(RCTLoadingProgress *progressData) { -#if (RCT_DEV_MENU | RCT_ENABLE_LOADING_VIEW) && __has_include() +#if (RCT_DEV_MENU | RCT_DEV_MENU) && __has_include() id loadingView = [weakSelf moduleForName:@"DevLoadingView" lazilyLoadIfNecessary:YES]; [loadingView updateProgress:progressData]; diff --git a/packages/react-native/React/DevSupport/RCTDevLoadingViewSetEnabled.m b/packages/react-native/React/DevSupport/RCTDevLoadingViewSetEnabled.m index 66361cfdd9bf28..9c121db16e2bd1 100644 --- a/packages/react-native/React/DevSupport/RCTDevLoadingViewSetEnabled.m +++ b/packages/react-native/React/DevSupport/RCTDevLoadingViewSetEnabled.m @@ -7,7 +7,7 @@ #import "RCTDevLoadingViewSetEnabled.h" -#if RCT_DEV | RCT_ENABLE_LOADING_VIEW +#if RCT_DEV_MENU static BOOL isDevLoadingViewEnabled = YES; #else static BOOL isDevLoadingViewEnabled = NO; diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm index 9d7b67f07d4dea..8b5b3d1b22ad28 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm @@ -14,6 +14,7 @@ #import #import #import +#import #import #import @@ -97,8 +98,18 @@ - (void)updateState:(State::Shared const &)state oldState:(State::Shared const & - (void)_setStateAndResubscribeImageResponseObserver:(ImageShadowNode::ConcreteState::Shared const &)state { if (_state) { - auto &observerCoordinator = _state->getData().getImageRequest().getObserverCoordinator(); + auto const &imageRequest = _state->getData().getImageRequest(); + auto &observerCoordinator = imageRequest.getObserverCoordinator(); observerCoordinator.removeObserver(_imageResponseObserverProxy); + if (CoreFeatures::cancelImageDownloadsOnRecycle) { + // Cancelling image request because we are no longer observing it. + // This is not 100% correct place to do this because we may want to + // re-create RCTImageComponentView with the same image and if it + // was cancelled before downloaded, download is not resumed. + // This will only become issue if we decouple life cycle of a + // ShadowNode from ComponentView, which is not something we do now. + imageRequest.cancel(); + } } _state = state; diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index 60e0697071d8ee..ecfe8bc408fd95 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -18,6 +18,10 @@ #import #import +#ifdef RCT_DYNAMIC_FRAMEWORKS +#import +#endif + using namespace facebook::react; @implementation RCTViewComponentView { @@ -30,6 +34,13 @@ @implementation RCTViewComponentView { NSSet *_Nullable _propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN; } +#ifdef RCT_DYNAMIC_FRAMEWORKS ++ (void)load +{ + [RCTComponentViewFactory.currentComponentViewFactory registerComponentViewClass:self]; +} +#endif + - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { @@ -710,21 +721,40 @@ - (NSString *)accessibilityValue } } + NSMutableArray *valueComponents = [NSMutableArray new]; + NSString *roleString = [NSString stringWithUTF8String:props.accessibilityRole.c_str()]; + + // In iOS, checkbox and radio buttons aren't recognized as traits. However, + // because our apps use checkbox and radio buttons often, we should announce + // these to screenreader users. (They should already be familiar with them + // from using web). + if ([roleString isEqualToString:@"checkbox"]) { + [valueComponents addObject:@"checkbox"]; + } + + if ([roleString isEqualToString:@"radio"]) { + [valueComponents addObject:@"radio button"]; + } + // Handle states which haven't already been handled. if (props.accessibilityState.checked == AccessibilityState::Checked) { - return @"checked"; + [valueComponents addObject:@"checked"]; } if (props.accessibilityState.checked == AccessibilityState::Unchecked) { - return @"unchecked"; + [valueComponents addObject:@"unchecked"]; } if (props.accessibilityState.checked == AccessibilityState::Mixed) { - return @"mixed"; + [valueComponents addObject:@"mixed"]; } if (props.accessibilityState.expanded) { - return @"expanded"; + [valueComponents addObject:@"expanded"]; } if (props.accessibilityState.busy) { - return @"busy"; + [valueComponents addObject:@"busy"]; + } + + if (valueComponents.count > 0) { + return [valueComponents componentsJoinedByString:@", "]; } return nil; diff --git a/packages/react-native/React/Fabric/Mounting/RCTComponentViewFactory.h b/packages/react-native/React/Fabric/Mounting/RCTComponentViewFactory.h index 771131d50f4407..15eb8f0b4c8b6d 100644 --- a/packages/react-native/React/Fabric/Mounting/RCTComponentViewFactory.h +++ b/packages/react-native/React/Fabric/Mounting/RCTComponentViewFactory.h @@ -16,12 +16,28 @@ NS_ASSUME_NONNULL_BEGIN void RCTInstallNativeComponentRegistryBinding(facebook::jsi::Runtime &runtime); +/** + * Protocol that can be implemented to provide some 3rd party components to Fabric. + * Fabric will check in this map whether there are some components that need to be registered. + */ +@protocol RCTComponentViewFactoryComponentProvider + +/** + * Return a dictionary of third party components where the `key` is the Component Handler and the `value` is a Class + * that conforms to `RCTComponentViewProtocol`. + */ +- (NSDictionary> *)thirdPartyFabricComponents; + +@end + /** * Registry of supported component view classes that can instantiate * view component instances by given component handle. */ @interface RCTComponentViewFactory : NSObject +@property (nonatomic, weak) id thirdPartyFabricComponentsProvider; + /** * Constructs and returns an instance of the class with a bunch of already registered standard components. */ diff --git a/packages/react-native/React/Fabric/Mounting/RCTComponentViewFactory.mm b/packages/react-native/React/Fabric/Mounting/RCTComponentViewFactory.mm index 0fe7f13d286722..8ed6f9a8319da8 100644 --- a/packages/react-native/React/Fabric/Mounting/RCTComponentViewFactory.mm +++ b/packages/react-native/React/Fabric/Mounting/RCTComponentViewFactory.mm @@ -49,7 +49,7 @@ void RCTInstallNativeComponentRegistryBinding(facebook::jsi::Runtime &runtime) return [[RCTComponentViewFactory currentComponentViewFactory] registerComponentIfPossible:componentNameByReactViewName(name)]; }; - NativeComponentRegistryBinding::install(runtime, std::move(hasComponentProvider)); + bindHasComponentProvider(runtime, std::move(hasComponentProvider)); } static Class RCTComponentViewClassWithName(const char *componentName) @@ -112,7 +112,19 @@ - (BOOL)registerComponentIfPossible:(std::string const &)name return YES; } - // Fallback 2: Try to use Paper Interop. + // Fallback 2: Ask the provider and check in the dictionary provided + if (self.thirdPartyFabricComponentsProvider) { + // Test whether a provider has been passed to avoid potentially expensive conversions + // between C++ and ObjC strings. + NSString *objcName = [NSString stringWithCString:name.c_str() encoding:NSUTF8StringEncoding]; + klass = self.thirdPartyFabricComponentsProvider.thirdPartyFabricComponents[objcName]; + if (klass) { + [self registerComponentViewClass:klass]; + return YES; + } + } + + // Fallback 3: Try to use Paper Interop. NSString *componentNameString = RCTNSStringFromString(name); if ([RCTLegacyViewManagerInteropComponentView isSupported:componentNameString]) { RCTLogNewArchitectureValidation( @@ -136,7 +148,7 @@ - (BOOL)registerComponentIfPossible:(std::string const &)name return YES; } - // Fallback 3: use if component doesn't exist. + // Fallback 4: use if component doesn't exist. auto flavor = std::make_shared(name); auto componentName = ComponentName{flavor->c_str()}; auto componentHandle = reinterpret_cast(componentName); diff --git a/packages/react-native/React/Fabric/Mounting/RCTMountingManager.mm b/packages/react-native/React/Fabric/Mounting/RCTMountingManager.mm index 086849f2be4951..0e7cc3f383cf69 100644 --- a/packages/react-native/React/Fabric/Mounting/RCTMountingManager.mm +++ b/packages/react-native/React/Fabric/Mounting/RCTMountingManager.mm @@ -17,6 +17,7 @@ #import #import #import +#import #import #import #import @@ -49,8 +50,10 @@ static void RCTPerformMountInstructions( { SystraceSection s("RCTPerformMountInstructions"); - [CATransaction begin]; - [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; + if (!CoreFeatures::disableTransactionCommit) { + [CATransaction begin]; + [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; + } for (auto const &mutation : mutations) { switch (mutation.type) { case ShadowViewMutation::Create: { @@ -149,7 +152,9 @@ static void RCTPerformMountInstructions( } } } - [CATransaction commit]; + if (!CoreFeatures::disableTransactionCommit) { + [CATransaction commit]; + } } @implementation RCTMountingManager { diff --git a/packages/react-native/React/Fabric/RCTSurfacePresenter.mm b/packages/react-native/React/Fabric/RCTSurfacePresenter.mm index d52cbdfe7632bc..7b09c995700cca 100644 --- a/packages/react-native/React/Fabric/RCTSurfacePresenter.mm +++ b/packages/react-native/React/Fabric/RCTSurfacePresenter.mm @@ -131,19 +131,6 @@ - (RCTScheduler *_Nullable)scheduler return _contextContainer; } -- (void)setContextContainer:(ContextContainer::Shared)contextContainer -{ - std::lock_guard lock(_schedulerLifeCycleMutex); - _contextContainer = contextContainer; - _mountingManager.contextContainer = contextContainer; -} - -- (RuntimeExecutor)runtimeExecutor -{ - std::lock_guard lock(_schedulerLifeCycleMutex); - return _runtimeExecutor; -} - - (void)setRuntimeExecutor:(RuntimeExecutor)runtimeExecutor { std::lock_guard lock(_schedulerLifeCycleMutex); @@ -281,8 +268,12 @@ - (RCTScheduler *)_createScheduler CoreFeatures::useNativeState = true; } - if (reactNativeConfig && reactNativeConfig->getBool("react_fabric:enable_nstextstorage_caching")) { - CoreFeatures::cacheNSTextStorage = true; + if (reactNativeConfig && reactNativeConfig->getBool("react_fabric:cancel_image_downloads_on_recycle")) { + CoreFeatures::cancelImageDownloadsOnRecycle = true; + } + + if (reactNativeConfig && reactNativeConfig->getBool("react_fabric:disable_transaction_commit")) { + CoreFeatures::disableTransactionCommit = true; } auto componentRegistryFactory = diff --git a/packages/react-native/React/React-RCTFabric.podspec b/packages/react-native/React/React-RCTFabric.podspec index a71035a63d90a6..0c399c1797afd3 100644 --- a/packages/react-native/React/React-RCTFabric.podspec +++ b/packages/react-native/React/React-RCTFabric.podspec @@ -35,6 +35,7 @@ header_search_paths = [ if ENV['USE_FRAMEWORKS'] header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\"" + header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-FabricImage/React_FabricImage.framework/Headers\"" header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/textlayoutmanager/platform/ios\"" header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/textinput/iostextinput\"" header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/imagemanager/platform/ios\"" @@ -59,7 +60,7 @@ Pod::Spec.new do |s| s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags s.header_dir = "React" s.module_name = "RCTFabric" - s.framework = "JavaScriptCore" + s.framework = ["JavaScriptCore", "MobileCoreServices"] s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => header_search_paths, "OTHER_CFLAGS" => "$(inherited) -DRN_FABRIC_ENABLED" + " " + folly_flags, @@ -72,7 +73,18 @@ Pod::Spec.new do |s| s.dependency "React-Fabric", version s.dependency "React-RCTImage", version s.dependency "React-ImageManager" + s.dependency "React-graphics" s.dependency "RCT-Folly/Fabric", folly_version + s.dependency "glog" + s.dependency "Yoga" + s.dependency "React-RCTText" + s.dependency "React-FabricImage" + + if ENV["USE_HERMES"] == nil || ENV["USE_HERMES"] == "1" + s.dependency "hermes-engine" + else + s.dependency "React-jsi" + end s.test_spec 'Tests' do |test_spec| test_spec.source_files = "Tests/**/*.{mm}" diff --git a/packages/react-native/React/Views/RCTView.m b/packages/react-native/React/Views/RCTView.m index dcb19bfafc25e2..fc678c2577af5e 100644 --- a/packages/react-native/React/Views/RCTView.m +++ b/packages/react-native/React/Views/RCTView.m @@ -310,7 +310,7 @@ - (NSString *)accessibilityValue @"timer" : @"timer", @"toolbar" : @"tool bar", @"checked" : @"checked", - @"unchecked" : @"not checked", + @"unchecked" : @"unchecked", @"busy" : @"busy", @"expanded" : @"expanded", @"collapsed" : @"collapsed", diff --git a/packages/react-native/ReactAndroid/build.gradle b/packages/react-native/ReactAndroid/build.gradle index 6f5cff2885209a..d65e409316adf2 100644 --- a/packages/react-native/ReactAndroid/build.gradle +++ b/packages/react-native/ReactAndroid/build.gradle @@ -444,9 +444,14 @@ android { ndkVersion rootProject.ext.ndkVersion } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + defaultConfig { - minSdkVersion(21) - targetSdkVersion(33) + minSdk = 21 + targetSdk = 33 versionCode(1) versionName("1.0") @@ -468,7 +473,10 @@ android { "-DREACT_BUILD_DIR=$buildDir", "-DANDROID_STL=c++_shared", "-DANDROID_TOOLCHAIN=clang", - "-DANDROID_PLATFORM=android-21" + "-DANDROID_PLATFORM=android-21", + // Due to https://github.com/android/ndk/issues/1693 we're losing Android + // specific compilation flags. This can be removed once we moved to NDK 25/26 + "-DANDROID_USE_LEGACY_TOOLCHAIN_FILE=ON" targets "jsijniprofiler", "reactnativeblob", @@ -659,13 +667,8 @@ android { } testOptions { - unitTests.all { - // Robolectric tests are downloading JARs at runtime. This allows to specify - // a local file mirror with REACT_NATIVE_ROBOLECTRIC_MIRROR to go in offline more. - if (System.getenv("REACT_NATIVE_ROBOLECTRIC_MIRROR") != null) { - systemProperty 'robolectric.offline', 'true' - systemProperty 'robolectric.dependency.dir', System.getenv("REACT_NATIVE_ROBOLECTRIC_MIRROR") - } + unitTests { + includeAndroidResources = true } } } @@ -723,11 +726,14 @@ react { jsRootDir = file("../Libraries") } +kotlin { + jvmToolchain(11) +} + tasks.withType(Test).all { // We add --add-opens flags to make sure we can run PowerMock tests on JDK >= 17 if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_17)) { jvmArgs += [ - "-XX:+AllowRedefinitionToAddDeleteMethods", "--illegal-access=permit", "--add-opens=java.base/java.lang=ALL-UNNAMED", "--add-opens=java.base/java.xml.internal=ALL-UNNAMED", diff --git a/packages/react-native/ReactAndroid/hermes-engine/build.gradle b/packages/react-native/ReactAndroid/hermes-engine/build.gradle index 3ad31d9debe078..ce03961aefa3d8 100644 --- a/packages/react-native/ReactAndroid/hermes-engine/build.gradle +++ b/packages/react-native/ReactAndroid/hermes-engine/build.gradle @@ -125,8 +125,8 @@ repositories { } android { - compileSdkVersion 31 - buildToolsVersion = "31.0.0" + compileSdkVersion 33 + buildToolsVersion = "33.0.0" namespace "com.facebook.hermes" // Used to override the NDK path/version on internal CI or by allowing @@ -139,7 +139,7 @@ android { } defaultConfig { - minSdkVersion 21 + minSdk = 21 externalNativeBuild { cmake { @@ -154,6 +154,9 @@ android { // We intentionally build Hermes with Intl support only. This is to simplify // the build setup and to avoid overcomplicating the build-type matrix. arguments "-DHERMES_ENABLE_INTL=True" + // Due to https://github.com/android/ndk/issues/1693 we're losing Android + // specific compilation flags. This can be removed once we moved to NDK 25/26 + arguments "-DANDROID_USE_LEGACY_TOOLCHAIN_FILE=ON" targets "libhermes" } } @@ -190,6 +193,15 @@ android { } } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + kotlin { + jvmToolchain(11) + } + sourceSets { main { manifest.srcFile "$hermesDir/android/hermes/src/main/AndroidManifest.xml" diff --git a/packages/react-native/ReactAndroid/src/androidTest/java/com/facebook/react/testing/ReactIntegrationTestCase.java b/packages/react-native/ReactAndroid/src/androidTest/java/com/facebook/react/testing/ReactIntegrationTestCase.java index e923c7a112b9b1..0c722420c0959a 100644 --- a/packages/react-native/ReactAndroid/src/androidTest/java/com/facebook/react/testing/ReactIntegrationTestCase.java +++ b/packages/react-native/ReactAndroid/src/androidTest/java/com/facebook/react/testing/ReactIntegrationTestCase.java @@ -76,14 +76,11 @@ public void shutDownContext() { final SimpleSettableFuture semaphore = new SimpleSettableFuture<>(); UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - if (contextToDestroy != null) { - contextToDestroy.destroy(); - } - semaphore.set(null); + () -> { + if (contextToDestroy != null) { + contextToDestroy.destroy(); } + semaphore.set(null); }); semaphore.getOrThrow(); } @@ -137,14 +134,10 @@ protected TimingModule createTimingModule() { final SimpleSettableFuture simpleSettableFuture = new SimpleSettableFuture(); UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - ReactChoreographer.initialize(); - TimingModule timingModule = - new TimingModule(getContext(), mock(DevSupportManager.class)); - simpleSettableFuture.set(timingModule); - } + () -> { + ReactChoreographer.initialize(); + TimingModule timingModule = new TimingModule(getContext(), mock(DevSupportManager.class)); + simpleSettableFuture.set(timingModule); }); try { return simpleSettableFuture.get(5000, TimeUnit.MILLISECONDS); @@ -188,15 +181,12 @@ protected void tearDown() throws Exception { protected static void initializeJavaModule(final BaseJavaModule javaModule) { final Semaphore semaphore = new Semaphore(0); UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - javaModule.initialize(); - if (javaModule instanceof LifecycleEventListener) { - ((LifecycleEventListener) javaModule).onHostResume(); - } - semaphore.release(); + () -> { + javaModule.initialize(); + if (javaModule instanceof LifecycleEventListener) { + ((LifecycleEventListener) javaModule).onHostResume(); } + semaphore.release(); }); try { SoftAssertions.assertCondition( diff --git a/packages/react-native/ReactAndroid/src/androidTest/js/TextInputTestModule.js b/packages/react-native/ReactAndroid/src/androidTest/js/TextInputTestModule.js index 68155efa64de45..321b1aea209b2c 100644 --- a/packages/react-native/ReactAndroid/src/androidTest/js/TextInputTestModule.js +++ b/packages/react-native/ReactAndroid/src/androidTest/js/TextInputTestModule.js @@ -47,7 +47,7 @@ class TokenizedTextExample extends React.Component { if (token[0].length === 0) { index = 1; } - parts.push(_text.substr(0, index)); + parts.push(_text.slice(0, index)); parts.push(token[0]); index = index + token[0].length; _text = _text.slice(index); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutor.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutor.java index b0e4f24d10d912..c8d81b725d282e 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutor.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutor.java @@ -26,11 +26,7 @@ public static void loadLibrary() throws UnsatisfiedLinkError { SoLoader.loadLibrary("hermes"); SoLoader.loadLibrary("hermes_executor"); // libhermes_executor is built differently for Debug & Release so we load the proper mode. - if (ReactBuildConfig.DEBUG == true) { - mode_ = "Debug"; - } else { - mode_ = "Release"; - } + mode_ = ReactBuildConfig.DEBUG ? "Debug" : "Release"; } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index c2a23b2c4c80f2..53b8e507d4a79c 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -555,6 +555,7 @@ private void toggleElementInspector() { * @deprecated Use {@link #onHostPause(Activity)} instead. */ @ThreadConfined(UI) + @Deprecated public void onHostPause() { UiThreadUtil.assertOnUiThread(); @@ -669,6 +670,7 @@ public void onViewDetachedFromWindow(View v) { * @deprecated use {@link #onHostDestroy(Activity)} instead */ @ThreadConfined(UI) + @Deprecated public void onHostDestroy() { UiThreadUtil.assertOnUiThread(); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/FallbackJSBundleLoader.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/FallbackJSBundleLoader.java index e2c669cb462389..c07c67b02f611c 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/FallbackJSBundleLoader.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/FallbackJSBundleLoader.java @@ -26,14 +26,14 @@ public final class FallbackJSBundleLoader extends JSBundleLoader { /* package */ static final String TAG = "FallbackJSBundleLoader"; // Loaders to delegate to, with the preferred one at the top. - private Stack mLoaders; + private final Stack mLoaders; // Reasons why we fell-back on previous loaders, in order of occurrence. private final ArrayList mRecoveredErrors = new ArrayList<>(); /** @param loaders Loaders for the sources to try, in descending order of preference. */ public FallbackJSBundleLoader(List loaders) { - mLoaders = new Stack(); + mLoaders = new Stack<>(); ListIterator it = loaders.listIterator(loaders.size()); while (it.hasPrevious()) { mLoaders.push(it.previous()); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JSBundleLoader.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JSBundleLoader.java index 6c3844205c21bf..800eeffbdb66f4 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JSBundleLoader.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JSBundleLoader.java @@ -9,11 +9,9 @@ import android.content.Context; import com.facebook.react.common.DebugServerException; +import java.util.Objects; -/** - * A class that stores JS bundle information and allows a {@link JSBundleLoaderDelegate} (e.g. - * {@link CatalystInstance}) to load a correct bundle through {@link ReactBridge}. - */ +/** A class that stores JS bundle information and allows a {@link JSBundleLoaderDelegate}. */ public abstract class JSBundleLoader { /** @@ -67,7 +65,8 @@ public String loadScript(JSBundleLoaderDelegate delegate) { delegate.loadScriptFromFile(cachedFileLocation, sourceURL, false); return sourceURL; } catch (Exception e) { - throw DebugServerException.makeGeneric(sourceURL, e.getMessage(), e); + throw DebugServerException.makeGeneric( + sourceURL, Objects.toString(e.getMessage(), ""), e); } } }; @@ -86,7 +85,8 @@ public String loadScript(JSBundleLoaderDelegate delegate) { delegate.loadSplitBundleFromFile(cachedFileLocation, sourceURL); return sourceURL; } catch (Exception e) { - throw DebugServerException.makeGeneric(sourceURL, e.getMessage(), e); + throw DebugServerException.makeGeneric( + sourceURL, Objects.toString(e.getMessage(), ""), e); } } }; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/NativeModule.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/NativeModule.java index 89e528d707de64..c5b1dfcf5439f6 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/NativeModule.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/NativeModule.java @@ -52,6 +52,7 @@ interface NativeMethod { * * @deprecated use {@link #invalidate()} instead. */ + @Deprecated void onCatalystInstanceDestroy(); /** Allow NativeModule to clean up. Called before {CatalystInstance#onHostDestroy} */ diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java index 8765116263c9fb..dfe32f2dd92704 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java @@ -516,6 +516,7 @@ public boolean startActivityForResult(Intent intent, int code, Bundle bundle) { } /** @deprecated DO NOT USE, this method will be removed in the near future. */ + @Deprecated public boolean isBridgeless() { return false; } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/BindingsInstaller.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/BindingsInstaller.java deleted file mode 100644 index 53d1c59e84d78b..00000000000000 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/BindingsInstaller.java +++ /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. - */ - -package com.facebook.react.bridgeless; - -import com.facebook.jni.HybridData; -import com.facebook.proguard.annotations.DoNotStrip; -import com.facebook.proguard.annotations.DoNotStripAny; -import com.facebook.soloader.SoLoader; - -@DoNotStripAny -public abstract class BindingsInstaller { - static { - SoLoader.loadLibrary("rninstance"); - } - - @DoNotStrip private final HybridData mHybridData; - - protected BindingsInstaller(HybridData hybridData) { - mHybridData = hybridData; - } -} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/BindingsInstaller.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/BindingsInstaller.kt new file mode 100644 index 00000000000000..8225c484bdcf56 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/BindingsInstaller.kt @@ -0,0 +1,22 @@ +/* + * 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. + */ + +package com.facebook.react.bridgeless + +import com.facebook.jni.HybridData +import com.facebook.proguard.annotations.DoNotStrip +import com.facebook.proguard.annotations.DoNotStripAny +import com.facebook.soloader.SoLoader + +@DoNotStripAny +abstract class BindingsInstaller(@field:DoNotStrip private val mHybridData: HybridData) { + companion object { + init { + SoLoader.loadLibrary("rninstance") + } + } +} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/BridgelessAtomicRef.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/BridgelessAtomicRef.java index 97463ba8f8df41..d613b497c9e1bd 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/BridgelessAtomicRef.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/BridgelessAtomicRef.java @@ -12,6 +12,7 @@ import android.annotation.SuppressLint; import androidx.annotation.Nullable; import com.facebook.infer.annotation.Nullsafe; +import java.util.Objects; @Nullsafe(Nullsafe.Mode.LOCAL) class BridgelessAtomicRef { @@ -30,8 +31,8 @@ enum State { Failure } - volatile State state; - volatile String failureMessage; + private volatile State state; + private volatile String failureMessage; public BridgelessAtomicRef(@Nullable T initialValue) { mValue = initialValue; @@ -77,7 +78,7 @@ public T getOrCreate(BridgelessAtomicRef.Provider provider) { synchronized (this) { state = State.Failure; String message = ex.getMessage(); - failureMessage = message != null ? message : "null"; + failureMessage = Objects.toString(message, "null"); notifyAll(); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/BridgelessReactContext.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/BridgelessReactContext.java index bfbc1f4ce44d54..b8ee4f666babaa 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/BridgelessReactContext.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/BridgelessReactContext.java @@ -151,7 +151,7 @@ public Collection getNativeModules() { @Override public void handleException(Exception e) { - mReactHost.handleException(e); + mReactHost.handleHostException(e); } public DefaultHardwareBackBtnHandler getDefaultHardwareBackBtnHandler() { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/JSEngineInstance.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/JSEngineInstance.java index d4adeef240de27..c7c2e32ebdea1c 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/JSEngineInstance.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/JSEngineInstance.java @@ -18,7 +18,7 @@ public abstract class JSEngineInstance { SoLoader.loadLibrary("rninstance"); } - @DoNotStrip private HybridData mHybridData; + @DoNotStrip private final HybridData mHybridData; protected JSEngineInstance(HybridData hybridData) { mHybridData = hybridData; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/JSTimerExecutor.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/JSTimerExecutor.java index 5dbfd5b215f58f..8d474db2a4b85f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/JSTimerExecutor.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/JSTimerExecutor.java @@ -16,25 +16,25 @@ import com.facebook.soloader.SoLoader; @Nullsafe(Nullsafe.Mode.LOCAL) -public class JSTimerExecutor implements JavaScriptTimerExecutor { +class JSTimerExecutor implements JavaScriptTimerExecutor { static { SoLoader.loadLibrary("rninstance"); } - @DoNotStrip private HybridData mHybridData; + @DoNotStrip private final HybridData mHybridData; public JSTimerExecutor(HybridData hybridData) { mHybridData = hybridData; } + private native void callTimers(WritableNativeArray timerIDs); + @Override public void callTimers(WritableArray timerIDs) { callTimers((WritableNativeArray) timerIDs); } - private native void callTimers(WritableNativeArray timerIDs); - @Override public void callIdleCallbacks(double frameTime) { // TODO T52558331 diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/README.md b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/README.md new file mode 100644 index 00000000000000..60660d655988c9 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/README.md @@ -0,0 +1,3 @@ +# Bridgeless Mode for Android + +This library is not ready for integration for production nor local experimentation. Expect breaking changes regularly if you use any of these APIs. Use at your own risk! diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/ReactHost.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/ReactHost.java index 35fd286db66aff..e822d6c7bd1f21 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/ReactHost.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/ReactHost.java @@ -54,6 +54,7 @@ import com.facebook.react.uimanager.events.BlackHoleEventDispatcher; import com.facebook.react.uimanager.events.EventDispatcher; import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -80,13 +81,11 @@ public class ReactHost { // TODO T61403233 Make this configurable by product code private static final boolean DEV = ReactBuildConfig.DEBUG; - + private static final String TAG = "ReactHost"; private static final int BRIDGELESS_MARKER_INSTANCE_KEY = 1; - public static final String TAG = "ReactHost"; - private final Context mContext; - private final ReactInstanceDelegate mReactInstanceDelegate; + private final ReactHostDelegate mReactHostDelegate; private final ComponentFactory mComponentFactory; private final ReactJsExceptionHandler mReactJsExceptionHandler; private final DevSupportManager mDevSupportManager; @@ -95,11 +94,11 @@ public class ReactHost { private final QueueThreadExceptionHandler mQueueThreadExceptionHandler; private final Set mAttachedSurfaces = Collections.synchronizedSet(new HashSet<>()); private final MemoryPressureRouter mMemoryPressureRouter; - private final MemoryPressureListener mMemoryPressureListener; + private MemoryPressureListener mMemoryPressureListener; private final boolean mAllowPackagerServerAccess; private final boolean mUseDevSupport; private final Collection mReactInstanceEventListeners = - Collections.synchronizedList(new ArrayList()); + Collections.synchronizedList(new ArrayList<>()); private final BridgelessAtomicRef> mReactInstanceTaskRef = new BridgelessAtomicRef<>( @@ -108,7 +107,7 @@ public class ReactHost { null, "forResult parameter supports null, but is not annotated as @Nullable"))); private final BridgelessAtomicRef mBridgelessReactContextRef = - new BridgelessAtomicRef<>(null); + new BridgelessAtomicRef<>(); private final AtomicReference mActivity = new AtomicReference<>(); private @Nullable DefaultHardwareBackBtnHandler mDefaultHardwareBackBtnHandler; @@ -122,7 +121,7 @@ public class ReactHost { public ReactHost( Context context, - ReactInstanceDelegate delegate, + ReactHostDelegate delegate, ComponentFactory componentFactory, boolean allowPackagerServerAccess, ReactJsExceptionHandler reactJsExceptionHandler, @@ -140,7 +139,7 @@ public ReactHost( public ReactHost( Context context, - ReactInstanceDelegate delegate, + ReactHostDelegate delegate, ComponentFactory componentFactory, Executor bgExecutor, Executor uiExecutor, @@ -148,12 +147,12 @@ public ReactHost( boolean allowPackagerServerAccess, boolean useDevSupport) { mContext = context; - mReactInstanceDelegate = delegate; + mReactHostDelegate = delegate; mComponentFactory = componentFactory; mBGExecutor = bgExecutor; mUIExecutor = uiExecutor; mReactJsExceptionHandler = reactJsExceptionHandler; - mQueueThreadExceptionHandler = ReactHost.this::handleException; + mQueueThreadExceptionHandler = ReactHost.this::handleHostException; mMemoryPressureRouter = new MemoryPressureRouter(context); mMemoryPressureListener = level -> @@ -164,13 +163,26 @@ public ReactHost( if (DEV) { mDevSupportManager = new BridgelessDevSupportManager( - ReactHost.this, mContext, mReactInstanceDelegate.getJSMainModulePath()); + ReactHost.this, mContext, mReactHostDelegate.getJSMainModulePath()); } else { mDevSupportManager = new DisabledDevSupportManager(); } mUseDevSupport = useDevSupport; } + private MemoryPressureListener createMemoryPressureListener(ReactInstance reactInstance) { + WeakReference weakReactInstance = new WeakReference<>(reactInstance); + return (level) -> { + mBGExecutor.execute( + () -> { + @Nullable ReactInstance strongReactInstance = weakReactInstance.get(); + if (strongReactInstance != null) { + strongReactInstance.handleMemoryPressure(level); + } + }); + }; + } + public LifecycleState getLifecycleState() { return mReactLifecycleStateManager.getLifecycleState(); } @@ -209,7 +221,7 @@ private Task old_preload() { destroy( "old_preload() failure: " + task.getError().getMessage(), task.getError()); - mReactInstanceDelegate.handleException(task.getError()); + mReactHostDelegate.handleInstanceException(task.getError()); } return task; @@ -234,7 +246,7 @@ private Task new_preload() { .continueWithTask( (task) -> { if (task.isFaulted()) { - mReactInstanceDelegate.handleException(task.getError()); + mReactHostDelegate.handleInstanceException(task.getError()); // Wait for destroy to finish return new_getOrCreateDestroyTask( "new_preload() failure: " + task.getError().getMessage(), @@ -401,7 +413,7 @@ private void moveToHostDestroy(@Nullable ReactContext currentContext) { * * @return The {@link BridgelessReactContext} associated with ReactInstance. */ - public @Nullable BridgelessReactContext getCurrentReactContext() { + public @Nullable ReactContext getCurrentReactContext() { return mBridgelessReactContextRef.getNullable(); } @@ -409,7 +421,8 @@ public DevSupportManager getDevSupportManager() { return assertNotNull(mDevSupportManager); } - public @Nullable Activity getCurrentActivity() { + @Nullable + /* package */ Activity getCurrentActivity() { return mActivity.get(); } @@ -421,7 +434,7 @@ public DevSupportManager getDevSupportManager() { * @return The real {@link EventDispatcher} if the instance is alive; otherwise, a {@link * BlackHoleEventDispatcher}. */ - public EventDispatcher getEventDispatcher() { + /* package */ EventDispatcher getEventDispatcher() { final ReactInstance reactInstance = mReactInstanceTaskRef.get().getResult(); if (reactInstance == null) { return BlackHoleEventDispatcher.get(); @@ -430,7 +443,8 @@ public EventDispatcher getEventDispatcher() { return reactInstance.getEventDispatcher(); } - public @Nullable FabricUIManager getUIManager() { + /* package */ @Nullable + FabricUIManager getUIManager() { final ReactInstance reactInstance = mReactInstanceTaskRef.get().getResult(); if (reactInstance == null) { return null; @@ -482,7 +496,7 @@ public MemoryPressureRouter getMemoryPressureRouter() { return mMemoryPressureRouter; } - public boolean isInstanceInitialized() { + /* package */ boolean isInstanceInitialized() { final ReactInstance reactInstance = mReactInstanceTaskRef.get().getResult(); return reactInstance != null; } @@ -552,12 +566,12 @@ public void removeReactInstanceEventListener(ReactInstanceEventListener listener }); } - /*package */ void handleException(Exception e) { - final String method = "handleException(message = \"" + e.getMessage() + "\")"; + /* package */ void handleHostException(Exception e) { + final String method = "handleHostException(message = \"" + e.getMessage() + "\")"; log(method); destroy(method, e); - mReactInstanceDelegate.handleException(e); + mReactHostDelegate.handleInstanceException(e); } /** @@ -596,13 +610,13 @@ public void removeReactInstanceEventListener(ReactInstanceEventListener listener } } - boolean isSurfaceAttached(ReactSurface surface) { + /* package */ boolean isSurfaceAttached(ReactSurface surface) { synchronized (mAttachedSurfaces) { return mAttachedSurfaces.contains(surface); } } - boolean isSurfaceWithModuleNameAttached(String moduleName) { + /* package */ boolean isSurfaceWithModuleNameAttached(String moduleName) { synchronized (mAttachedSurfaces) { for (ReactSurface surface : mAttachedSurfaces) { if (surface.getModuleName().equals(moduleName)) { @@ -613,7 +627,7 @@ boolean isSurfaceWithModuleNameAttached(String moduleName) { } } - interface VeniceThenable { + /* package */ interface VeniceThenable { void then(T t); } @@ -676,7 +690,7 @@ private Task callAfterGetOrCreateReactInstance( .continueWith( task -> { if (task.isFaulted()) { - handleException(task.getError()); + handleHostException(task.getError()); } return null; }, @@ -697,8 +711,6 @@ private BridgelessReactContext getOrCreateReactContext() { * *

If the ReactInstance is reloading, will return the reload task. If the ReactInstance is * destroying, will wait until destroy is finished, before creating. - * - * @return */ private Task getOrCreateReactInstanceTask() { if (ReactFeatureFlags.enableBridgelessArchitectureNewCreateReloadDestroy) { @@ -767,13 +779,17 @@ private Task new_getOrCreateReactInstanceTask() { final ReactInstance instance = new ReactInstance( reactContext, - mReactInstanceDelegate, + mReactHostDelegate, mComponentFactory, devSupportManager, mQueueThreadExceptionHandler, mReactJsExceptionHandler, mUseDevSupport); + if (ReactFeatureFlags + .unstable_bridgelessArchitectureMemoryPressureHackyBoltsFix) { + mMemoryPressureListener = createMemoryPressureListener(instance); + } mMemoryPressureRouter.addMemoryPressureListener(mMemoryPressureListener); log(method, "Loading JS Bundle"); @@ -857,13 +873,17 @@ private Task old_getOrCreateReactInstanceTask() { final ReactInstance instance = new ReactInstance( reactContext, - mReactInstanceDelegate, + mReactHostDelegate, mComponentFactory, devSupportManager, mQueueThreadExceptionHandler, mReactJsExceptionHandler, mUseDevSupport); + if (ReactFeatureFlags + .unstable_bridgelessArchitectureMemoryPressureHackyBoltsFix) { + mMemoryPressureListener = createMemoryPressureListener(instance); + } mMemoryPressureRouter.addMemoryPressureListener(mMemoryPressureListener); log(method, "Loading JS Bundle"); @@ -925,7 +945,7 @@ private Task getJSBundleLoader() { // Since metro is running, fetch the JS bundle from the server return loadJSBundleFromMetro(); } - return Task.forResult(mReactInstanceDelegate.getJSBundleLoader(mContext)); + return Task.forResult(mReactHostDelegate.getJSBundleLoader(mContext)); }, mBGExecutor); } else { @@ -940,7 +960,7 @@ private Task getJSBundleLoader() { * throws an exception, the task will fault, and we'll go through the ReactHost error * reporting pipeline. */ - return Task.call(() -> mReactInstanceDelegate.getJSBundleLoader(mContext)); + return Task.call(() -> mReactHostDelegate.getJSBundleLoader(mContext)); } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/ReactHostDelegate.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/ReactHostDelegate.kt new file mode 100644 index 00000000000000..890682936e0edc --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/ReactHostDelegate.kt @@ -0,0 +1,62 @@ +/* + * 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. + */ + +package com.facebook.react.bridgeless + +import android.content.Context +import com.facebook.infer.annotation.ThreadSafe +import com.facebook.react.ReactPackage +import com.facebook.react.bridge.JSBundleLoader +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.common.annotations.UnstableReactNativeAPI +import com.facebook.react.fabric.ReactNativeConfig +import com.facebook.react.turbomodule.core.TurboModuleManager +import com.facebook.react.turbomodule.core.TurboModuleManagerDelegate + +/** TODO: add javadoc for class and methods */ +@ThreadSafe +@UnstableReactNativeAPI +interface ReactHostDelegate { + val jSMainModulePath: String + + val bindingsInstaller: BindingsInstaller + + val reactPackages: List + + fun getJSBundleLoader(context: Context): JSBundleLoader + + fun getTurboModuleManagerDelegate(context: ReactApplicationContext): TurboModuleManagerDelegate + + fun getJSEngineInstance(context: ReactApplicationContext): JSEngineInstance + + fun handleInstanceException(e: Exception) + + fun getReactNativeConfig(turboModuleManager: TurboModuleManager): ReactNativeConfig + + @UnstableReactNativeAPI + class ReactHostDelegateBase( + override val jSMainModulePath: String, + override val bindingsInstaller: BindingsInstaller, + override val reactPackages: List, + private val jsBundleLoader: JSBundleLoader, + private val turboModuleManagerDelegate: TurboModuleManagerDelegate, + private val jsEngineInstance: JSEngineInstance, + private val reactNativeConfig: ReactNativeConfig, + private val exceptionHandler: (Exception) -> Unit = {} + ) : ReactHostDelegate { + override fun getJSBundleLoader(context: Context) = jsBundleLoader + + override fun getTurboModuleManagerDelegate(context: ReactApplicationContext) = + turboModuleManagerDelegate + + override fun getJSEngineInstance(context: ReactApplicationContext) = jsEngineInstance + + override fun getReactNativeConfig(turboModuleManager: TurboModuleManager) = reactNativeConfig + + override fun handleInstanceException(e: Exception) = exceptionHandler(e) + } +} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/ReactInstance.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/ReactInstance.java index c04059a96041e8..eb3f86afcbb656 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/ReactInstance.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/ReactInstance.java @@ -73,9 +73,9 @@ final class ReactInstance { private static final String TAG = ReactInstance.class.getSimpleName(); - @DoNotStrip private HybridData mHybridData; + @DoNotStrip private final HybridData mHybridData; - private final ReactInstanceDelegate mDelegate; + private final ReactHostDelegate mDelegate; private final BridgelessReactContext mBridgelessReactContext; private final ReactQueueConfiguration mQueueConfiguration; @@ -89,7 +89,7 @@ final class ReactInstance { /* package */ ReactInstance( BridgelessReactContext bridgelessReactContext, - ReactInstanceDelegate delegate, + ReactHostDelegate delegate, ComponentFactory componentFactory, DevSupportManager devSupportManager, QueueThreadExceptionHandler exceptionHandler, @@ -172,17 +172,15 @@ public void onHostDestroy() { new ComponentNameResolverManager( // Use unbuffered RuntimeExecutor to install binding unbufferedRuntimeExecutor, - new ComponentNameResolver() { - @Override - public String[] getComponentNames() { - Collection viewManagerNames = getViewManagerNames(); - if (viewManagerNames.size() < 1) { - FLog.e(TAG, "No ViewManager names found"); - return new String[0]; - } - return viewManagerNames.toArray(new String[0]); - } - }); + (ComponentNameResolver) + () -> { + Collection viewManagerNames = getViewManagerNames(); + if (viewManagerNames.size() < 1) { + FLog.e(TAG, "No ViewManager names found"); + return new String[0]; + } + return viewManagerNames.toArray(new String[0]); + }); // Set up TurboModules Systrace.beginSection( diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/ReactInstanceDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/ReactInstanceDelegate.java deleted file mode 100644 index 1c9a9e15134276..00000000000000 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/ReactInstanceDelegate.java +++ /dev/null @@ -1,40 +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. - */ - -package com.facebook.react.bridgeless; - -import android.content.Context; -import com.facebook.infer.annotation.ThreadSafe; -import com.facebook.react.ReactPackage; -import com.facebook.react.bridge.JSBundleLoader; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.fabric.ReactNativeConfig; -import com.facebook.react.turbomodule.core.TurboModuleManager; -import com.facebook.react.turbomodule.core.TurboModuleManagerDelegate; -import com.facebook.react.uimanager.ViewManager; -import java.util.List; - -@ThreadSafe -public interface ReactInstanceDelegate { - String getJSMainModulePath(); - - JSBundleLoader getJSBundleLoader(Context context); - - BindingsInstaller getBindingsInstaller(); - - TurboModuleManagerDelegate getTurboModuleManagerDelegate(ReactApplicationContext context); - - List getViewManagers(ReactApplicationContext context); - - JSEngineInstance getJSEngineInstance(ReactApplicationContext context); - - void handleException(Exception e); - - ReactNativeConfig getReactNativeConfig(TurboModuleManager turboModuleManager); - - List getReactPackages(); -} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/ReactSurface.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/ReactSurface.java index b6e8cf98febe00..c7898a1c5767ba 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/ReactSurface.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/ReactSurface.java @@ -32,7 +32,6 @@ @Nullsafe(Nullsafe.Mode.LOCAL) @ThreadSafe public class ReactSurface { - private static final String TAG = "ReactSurface"; private final AtomicReference mSurfaceView = new AtomicReference<>(null); @@ -180,14 +179,11 @@ public String getModuleName() { public void clear() { UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - ReactSurfaceView view = getView(); - if (view != null) { - view.removeAllViews(); - view.setId(View.NO_ID); - } + () -> { + ReactSurfaceView view = getView(); + if (view != null) { + view.removeAllViews(); + view.setId(View.NO_ID); } }); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/ReactSurfaceView.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/ReactSurfaceView.java index eae0988ba7e515..5d6832624c0c6e 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/ReactSurfaceView.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/ReactSurfaceView.java @@ -25,6 +25,7 @@ import com.facebook.react.uimanager.common.UIManagerType; import com.facebook.react.uimanager.events.EventDispatcher; import com.facebook.systrace.Systrace; +import java.util.Objects; /** A view created by {@link ReactSurface} that's responsible for rendering a React component. */ @Nullsafe(Nullsafe.Mode.LOCAL) @@ -161,10 +162,11 @@ public void onChildEndedNativeGesture(View childView, MotionEvent ev) { @Override public void handleException(Throwable t) { - if (mSurface.getReactHost() != null) { - String errorMessage = t.getMessage() == null ? "" : t.getMessage(); + ReactHost reactHost = mSurface.getReactHost(); + if (reactHost != null) { + String errorMessage = Objects.toString(t.getMessage(), ""); Exception e = new IllegalViewOperationException(errorMessage, this, t); - mSurface.getReactHost().handleException(e); + reactHost.handleHostException(e); } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/exceptionmanager/ReactJsExceptionHandler.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/exceptionmanager/ReactJsExceptionHandler.java index 470bf037bbb6de..a05e6471911a9b 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/exceptionmanager/ReactJsExceptionHandler.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridgeless/exceptionmanager/ReactJsExceptionHandler.java @@ -13,5 +13,5 @@ @DoNotStripAny public interface ReactJsExceptionHandler { - public void reportJsException(ReadableMapBuffer errorMap); + void reportJsException(ReadableMapBuffer errorMap); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/DebugServerException.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/DebugServerException.java index 33898324d69f83..4170256331f7d9 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/DebugServerException.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/DebugServerException.java @@ -9,6 +9,7 @@ import android.net.Uri; import android.text.TextUtils; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.facebook.common.logging.FLog; import org.json.JSONException; @@ -27,12 +28,13 @@ public class DebugServerException extends RuntimeException { + "\u2022 If you're on a physical device connected to the same machine, run 'adb reverse tcp: tcp:' to forward requests from your device\n" + "\u2022 If your device is on the same Wi-Fi network, set 'Debug server host & port for device' in 'Dev settings' to your machine's IP address and the port of the local dev server - e.g. 10.0.1.1:\n\n"; - public static DebugServerException makeGeneric(String url, String reason, Throwable t) { + public static DebugServerException makeGeneric( + @NonNull String url, @NonNull String reason, Throwable t) { return makeGeneric(url, reason, "", t); } public static DebugServerException makeGeneric( - String url, String reason, String extra, Throwable t) { + @NonNull String url, @NonNull String reason, @NonNull String extra, Throwable t) { Uri uri = Uri.parse(url); String message = GENERIC_ERROR_MESSAGE.replace("", String.valueOf(uri.getPort())); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/annotations/UnstableReactNativeAPI.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/annotations/UnstableReactNativeAPI.kt new file mode 100644 index 00000000000000..3996580c313e4d --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/annotations/UnstableReactNativeAPI.kt @@ -0,0 +1,15 @@ +/* + * 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. + */ + +package com.facebook.react.common.annotations + +@Retention(AnnotationRetention.RUNTIME) +@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) +@RequiresOptIn( + level = RequiresOptIn.Level.ERROR, + message = "This API is experimental and is likely to change or to be removed in the future") +annotation class UnstableReactNativeAPI diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/annotations/VisibleForTesting.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/annotations/VisibleForTesting.kt similarity index 78% rename from packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/annotations/VisibleForTesting.java rename to packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/annotations/VisibleForTesting.kt index 2b9e919775d4ea..5628249c45f290 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/annotations/VisibleForTesting.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/annotations/VisibleForTesting.kt @@ -5,10 +5,10 @@ * LICENSE file in the root directory of this source tree. */ -package com.facebook.react.common.annotations; +package com.facebook.react.common.annotations /** * Annotates a method that should have restricted visibility but it's required to be public for use * in test code only. */ -public @interface VisibleForTesting {} +annotation class VisibleForTesting diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java index fd479424f63787..3ee102049179f2 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java @@ -56,6 +56,9 @@ public class ReactFeatureFlags { */ public static boolean enableBridgelessArchitecture = false; + /** Server-side gating for a hacky fix to an ANR in the bridgeless core, related to Bolts task. */ + public static boolean unstable_bridgelessArchitectureMemoryPressureHackyBoltsFix = false; + /** * Does the bridgeless architecture log soft exceptions. Could be useful for tracking down issues. */ @@ -94,9 +97,6 @@ public class ReactFeatureFlags { /** Feature Flag to enable the pending event queue in fabric before mounting views */ public static boolean enableFabricPendingEventQueue = false; - /** Feature Flag to enable caching mechanism of text measurement at shadow node level */ - public static boolean enableTextMeasureCachePerShadowNode = false; - /** * Feature flag that controls how turbo modules are exposed to JS * diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevInternalSettings.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevInternalSettings.java index a6e67bf56ed13b..a68feb63a276db 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevInternalSettings.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevInternalSettings.java @@ -10,18 +10,16 @@ import android.content.Context; import android.content.SharedPreferences; import android.preference.PreferenceManager; -import com.facebook.react.common.annotations.VisibleForTesting; import com.facebook.react.common.build.ReactBuildConfig; import com.facebook.react.modules.debug.interfaces.DeveloperSettings; import com.facebook.react.packagerconnection.PackagerConnectionSettings; /** - * Helper class for accessing developers settings that should not be accessed outside of the package + * Helper class for accessing developers settings that can not be accessed outside of the package * {@link com.facebook.react.devsupport}. For accessing some of the settings by external modules * this class implements an external interface {@link DeveloperSettings}. */ -@VisibleForTesting -public class DevInternalSettings +class DevInternalSettings implements DeveloperSettings, SharedPreferences.OnSharedPreferenceChangeListener { private static final String PREFS_FPS_DEBUG_KEY = "fps_debug"; @@ -45,19 +43,11 @@ public DevInternalSettings(Context applicationContext, Listener listener) { mPackagerConnectionSettings = new PackagerConnectionSettings(applicationContext); } - public PackagerConnectionSettings getPackagerConnectionSettings() { - return mPackagerConnectionSettings; - } - @Override public boolean isFpsDebugEnabled() { return mPreferences.getBoolean(PREFS_FPS_DEBUG_KEY, false); } - public void setFpsDebugEnabled(boolean enabled) { - mPreferences.edit().putBoolean(PREFS_FPS_DEBUG_KEY, enabled).apply(); - } - @Override public boolean isAnimationFpsDebugEnabled() { return mPreferences.getBoolean(PREFS_ANIMATIONS_DEBUG_KEY, false); @@ -68,15 +58,12 @@ public boolean isJSDevModeEnabled() { return mPreferences.getBoolean(PREFS_JS_DEV_MODE_DEBUG_KEY, true); } - public void setJSDevModeEnabled(boolean value) { - mPreferences.edit().putBoolean(PREFS_JS_DEV_MODE_DEBUG_KEY, value).apply(); - } - @Override public boolean isJSMinifyEnabled() { return mPreferences.getBoolean(PREFS_JS_MINIFY_DEBUG_KEY, false); } + @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if (mListener != null) { if (PREFS_FPS_DEBUG_KEY.equals(key) @@ -88,22 +75,11 @@ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, Strin } } - public boolean isHotModuleReplacementEnabled() { - return mPreferences.getBoolean(PREFS_HOT_MODULE_REPLACEMENT_KEY, true); - } - - public void setHotModuleReplacementEnabled(boolean enabled) { - mPreferences.edit().putBoolean(PREFS_HOT_MODULE_REPLACEMENT_KEY, enabled).apply(); - } - + @Override public boolean isElementInspectorEnabled() { return mPreferences.getBoolean(PREFS_INSPECTOR_DEBUG_KEY, false); } - public void setElementInspectorEnabled(boolean enabled) { - mPreferences.edit().putBoolean(PREFS_INSPECTOR_DEBUG_KEY, enabled).apply(); - } - @Override public boolean isDeviceDebugEnabled() { return ReactBuildConfig.IS_INTERNAL_BUILD && ReactBuildConfig.DEBUG; @@ -129,6 +105,30 @@ public void addMenuItem(String title) { // Not supported. } + void setElementInspectorEnabled(boolean enabled) { + mPreferences.edit().putBoolean(PREFS_INSPECTOR_DEBUG_KEY, enabled).apply(); + } + + boolean isHotModuleReplacementEnabled() { + return mPreferences.getBoolean(PREFS_HOT_MODULE_REPLACEMENT_KEY, true); + } + + void setHotModuleReplacementEnabled(boolean enabled) { + mPreferences.edit().putBoolean(PREFS_HOT_MODULE_REPLACEMENT_KEY, enabled).apply(); + } + + void setJSDevModeEnabled(boolean value) { + mPreferences.edit().putBoolean(PREFS_JS_DEV_MODE_DEBUG_KEY, value).apply(); + } + + void setFpsDebugEnabled(boolean enabled) { + mPreferences.edit().putBoolean(PREFS_FPS_DEBUG_KEY, enabled).apply(); + } + + PackagerConnectionSettings getPackagerConnectionSettings() { + return mPackagerConnectionSettings; + } + public interface Listener { void onInternalSettingsChanged(); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java index a3fadbba2961a0..6ee95a79a664d5 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java @@ -9,6 +9,7 @@ import android.content.Context; import android.os.AsyncTask; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.facebook.common.logging.FLog; import com.facebook.infer.annotation.Assertions; @@ -16,10 +17,12 @@ import com.facebook.react.common.ReactConstants; import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener; import com.facebook.react.devsupport.interfaces.PackagerStatusCallback; +import com.facebook.react.modules.debug.interfaces.DeveloperSettings; import com.facebook.react.modules.systeminfo.AndroidInfoHelpers; import com.facebook.react.packagerconnection.FileIoHandler; import com.facebook.react.packagerconnection.JSPackagerClient; import com.facebook.react.packagerconnection.NotificationOnlyHandler; +import com.facebook.react.packagerconnection.PackagerConnectionSettings; import com.facebook.react.packagerconnection.ReconnectingWebSocket.ConnectionCallback; import com.facebook.react.packagerconnection.RequestHandler; import com.facebook.react.packagerconnection.RequestOnlyHandler; @@ -62,10 +65,6 @@ public class DevServerHelper { private static final String DEBUGGER_MSG_DISABLE = "{ \"id\":1,\"method\":\"Debugger.disable\" }"; - public interface OnServerContentChangeListener { - void onServerContentChanged(); - } - public interface PackagerCommandListener { void onPackagerConnected(); @@ -82,8 +81,6 @@ public interface PackagerCommandListener { Map customCommandHandlers(); } - public interface PackagerCustomCommandProvider {} - private enum BundleType { BUNDLE("bundle"), MAP("map"); @@ -99,7 +96,10 @@ public String typeID() { } } - private final DevInternalSettings mSettings; + private final DeveloperSettings mSettings; + + private final PackagerConnectionSettings mPackagerConnectionSettings; + private final OkHttpClient mClient; private final BundleDownloader mBundleDownloader; private final PackagerStatusCheck mPackagerStatusCheck; @@ -107,13 +107,15 @@ public String typeID() { private @Nullable JSPackagerClient mPackagerClient; private @Nullable InspectorPackagerConnection mInspectorPackagerConnection; - private InspectorPackagerConnection.BundleStatusProvider mBundlerStatusProvider; + private final InspectorPackagerConnection.BundleStatusProvider mBundlerStatusProvider; public DevServerHelper( - DevInternalSettings settings, + DeveloperSettings developerSettings, String packageName, - InspectorPackagerConnection.BundleStatusProvider bundleStatusProvider) { - mSettings = settings; + InspectorPackagerConnection.BundleStatusProvider bundleStatusProvider, + PackagerConnectionSettings packagerConnectionSettings) { + mSettings = developerSettings; + mPackagerConnectionSettings = packagerConnectionSettings; mBundlerStatusProvider = bundleStatusProvider; mClient = new OkHttpClient.Builder() @@ -181,10 +183,7 @@ public void onDisconnected() { mPackagerClient = new JSPackagerClient( - clientId, - mSettings.getPackagerConnectionSettings(), - handlers, - onPackagerConnectedCallback); + clientId, mPackagerConnectionSettings, handlers, onPackagerConnectedCallback); mPackagerClient.init(); return null; @@ -277,14 +276,14 @@ public String getWebsocketProxyURL() { return String.format( Locale.US, "ws://%s/debugger-proxy?role=client", - mSettings.getPackagerConnectionSettings().getDebugServerHost()); + mPackagerConnectionSettings.getDebugServerHost()); } private String getInspectorDeviceUrl() { return String.format( Locale.US, "http://%s/inspector/device?name=%s&app=%s", - mSettings.getPackagerConnectionSettings().getInspectorServerHost(), + mPackagerConnectionSettings.getInspectorServerHost(), AndroidInfoHelpers.getFriendlyDeviceName(), mPackageName); } @@ -315,8 +314,7 @@ public void downloadBundleFromURL( /** @return the host to use when connecting to the bundle server from the host itself. */ private String getHostForJSProxy() { // Use custom port if configured. Note that host stays "localhost". - String host = - Assertions.assertNotNull(mSettings.getPackagerConnectionSettings().getDebugServerHost()); + String host = Assertions.assertNotNull(mPackagerConnectionSettings.getDebugServerHost()); int portOffset = host.lastIndexOf(':'); if (portOffset > -1) { return "localhost" + host.substring(portOffset); @@ -346,15 +344,14 @@ private String createSplitBundleURL(String mainModuleID, String host) { private String createBundleURL( String mainModuleID, BundleType type, String host, boolean modulesOnly, boolean runModule) { boolean dev = getDevMode(); - boolean lazy = dev; return String.format( Locale.US, "http://%s/%s.%s?platform=android&dev=%s&lazy=%s&minify=%s&app=%s&modulesOnly=%s&runModule=%s", host, mainModuleID, type.typeID(), - dev, - lazy, + dev, // dev + dev, // lazy getJSMinifyMode(), mPackageName, modulesOnly ? "true" : "false", @@ -362,8 +359,7 @@ private String createBundleURL( } private String createBundleURL(String mainModuleID, BundleType type) { - return createBundleURL( - mainModuleID, type, mSettings.getPackagerConnectionSettings().getDebugServerHost()); + return createBundleURL(mainModuleID, type, mPackagerConnectionSettings.getDebugServerHost()); } private static String createResourceURL(String host, String resourcePath) { @@ -372,18 +368,15 @@ private static String createResourceURL(String host, String resourcePath) { public String getDevServerBundleURL(final String jsModulePath) { return createBundleURL( - jsModulePath, - BundleType.BUNDLE, - mSettings.getPackagerConnectionSettings().getDebugServerHost()); + jsModulePath, BundleType.BUNDLE, mPackagerConnectionSettings.getDebugServerHost()); } public String getDevServerSplitBundleURL(String jsModulePath) { - return createSplitBundleURL( - jsModulePath, mSettings.getPackagerConnectionSettings().getDebugServerHost()); + return createSplitBundleURL(jsModulePath, mPackagerConnectionSettings.getDebugServerHost()); } public void isPackagerRunning(final PackagerStatusCallback callback) { - String host = mSettings.getPackagerConnectionSettings().getDebugServerHost(); + String host = mPackagerConnectionSettings.getDebugServerHost(); if (host == null) { FLog.w(ReactConstants.TAG, "No packager host configured."); callback.onPackagerStatusFetched(false); @@ -396,7 +389,7 @@ private String createLaunchJSDevtoolsCommandUrl() { return String.format( Locale.US, "http://%s/launch-js-devtools", - mSettings.getPackagerConnectionSettings().getDebugServerHost()); + mPackagerConnectionSettings.getDebugServerHost()); } public void launchJSDevtools() { @@ -406,14 +399,13 @@ public void launchJSDevtools() { .enqueue( new Callback() { @Override - public void onFailure(Call call, IOException e) { + public void onFailure(@NonNull Call call, @NonNull IOException e) { // ignore HTTP call response, this is just to open a debugger page and there is no - // reason - // to report failures from here + // reason to report failures from here } @Override - public void onResponse(Call call, Response response) throws IOException { + public void onResponse(@NonNull Call call, @NonNull Response response) { // ignore HTTP call response - see above } }); @@ -443,23 +435,16 @@ public String getJSBundleURLForRemoteDebugging(String mainModuleName) { public @Nullable File downloadBundleResourceFromUrlSync( final String resourcePath, final File outputFile) { final String resourceURL = - createResourceURL( - mSettings.getPackagerConnectionSettings().getDebugServerHost(), resourcePath); + createResourceURL(mPackagerConnectionSettings.getDebugServerHost(), resourcePath); final Request request = new Request.Builder().url(resourceURL).build(); try (Response response = mClient.newCall(request).execute()) { if (!response.isSuccessful()) { return null; } - Sink output = null; - try { - output = Okio.sink(outputFile); + try (Sink output = Okio.sink(outputFile)) { Okio.buffer(response.body().source()).readAll(output); - } finally { - if (output != null) { - output.close(); - } } return outputFile; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java index 82cc5b393c90f8..b393db1675623d 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java @@ -17,13 +17,13 @@ import android.content.IntentFilter; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; -import android.graphics.Color; import android.graphics.Typeface; import android.hardware.SensorManager; import android.util.Pair; import android.view.Gravity; import android.view.View; import android.widget.EditText; +import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.Nullable; @@ -83,9 +83,6 @@ public interface CallbackWithBundleLoader { private static final String EXOPACKAGE_LOCATION_FORMAT = "/data/local/tmp/exopackage/%s//secondary-dex"; - public static final String EMOJI_HUNDRED_POINTS_SYMBOL = " \uD83D\uDCAF"; - public static final String EMOJI_FACE_WITH_NO_GOOD_GESTURE = " \uD83D\uDE45"; - private final Context mApplicationContext; private final ShakeDetector mShakeDetector; private final BroadcastReceiver mReloadAppBroadcastReceiver; @@ -104,24 +101,23 @@ public interface CallbackWithBundleLoader { private boolean mDevLoadingViewVisible = false; private int mPendingJSSplitBundleRequests = 0; private @Nullable ReactContext mCurrentContext; - private DevInternalSettings mDevSettings; + private final DevInternalSettings mDevSettings; private boolean mIsReceiverRegistered = false; private boolean mIsShakeDetectorStarted = false; private boolean mIsDevSupportEnabled = false; - private @Nullable RedBoxHandler mRedBoxHandler; + private @Nullable final RedBoxHandler mRedBoxHandler; private @Nullable String mLastErrorTitle; private @Nullable StackFrame[] mLastErrorStack; private @Nullable ErrorType mLastErrorType; private int mLastErrorCookie = 0; - private @Nullable DevBundleDownloadListener mBundleDownloadListener; + private @Nullable final DevBundleDownloadListener mBundleDownloadListener; private @Nullable List mErrorCustomizers; private @Nullable PackagerLocationCustomizer mPackagerLocationCustomizer; - private InspectorPackagerConnection.BundleStatus mBundleStatus; + private final InspectorPackagerConnection.BundleStatus mBundleStatus; - private @Nullable Map mCustomPackagerCommandHandlers; + private @Nullable final Map mCustomPackagerCommandHandlers; - private @Nullable Activity currentActivity; private @Nullable final SurfaceDelegateFactory mSurfaceDelegateFactory; public DevSupportManagerBase( @@ -138,38 +134,18 @@ public DevSupportManagerBase( mReactInstanceDevHelper = reactInstanceDevHelper; mApplicationContext = applicationContext; mJSAppBundleName = packagerPathForJSBundleName; - mDevSettings = - new DevInternalSettings( - applicationContext, - new DevInternalSettings.Listener() { - @Override - public void onInternalSettingsChanged() { - reloadSettings(); - } - }); + mDevSettings = new DevInternalSettings(applicationContext, this::reloadSettings); mBundleStatus = new InspectorPackagerConnection.BundleStatus(); mDevServerHelper = new DevServerHelper( mDevSettings, mApplicationContext.getPackageName(), - new InspectorPackagerConnection.BundleStatusProvider() { - @Override - public InspectorPackagerConnection.BundleStatus getBundleStatus() { - return mBundleStatus; - } - }); + () -> mBundleStatus, + mDevSettings.getPackagerConnectionSettings()); mBundleDownloadListener = devBundleDownloadListener; // Prepare shake gesture detector (will be started/stopped from #reload) - mShakeDetector = - new ShakeDetector( - new ShakeDetector.ShakeListener() { - @Override - public void onShake() { - showDevOptionsDialog(); - } - }, - minNumShakes); + mShakeDetector = new ShakeDetector(this::showDevOptionsDialog, minNumShakes); mCustomPackagerCommandHandlers = customPackagerCommandHandlers; @@ -280,38 +256,34 @@ public void registerErrorCustomizer(ErrorCustomizer errorCustomizer) { @Override public Pair processErrorCustomizers(Pair errorInfo) { - if (mErrorCustomizers == null) { - return errorInfo; - } else { + if (mErrorCustomizers != null) { for (ErrorCustomizer errorCustomizer : mErrorCustomizers) { Pair result = errorCustomizer.customizeErrorInfo(errorInfo); if (result != null) { errorInfo = result; } } - return errorInfo; } + return errorInfo; } @Override public void updateJSError( final String message, final ReadableArray details, final int errorCookie) { UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - // Since we only show the first JS error in a succession of JS errors, make sure we only - // update the error message for that error message. This assumes that updateJSError - // belongs to the most recent showNewJSError - if (!mRedBoxSurfaceDelegate.isShowing() || errorCookie != mLastErrorCookie) { - return; - } - - // The RedBox surface delegate will always show the latest error - updateLastErrorInfo( - message, StackTraceHelper.convertJsStackTrace(details), errorCookie, ErrorType.JS); - mRedBoxSurfaceDelegate.show(); + () -> { + // Since we only show the first JS error in a succession of JS errors, make sure we only + // update the error message for that error message. This assumes that updateJSError + // belongs to the most recent showNewJSError + if ((mRedBoxSurfaceDelegate != null && !mRedBoxSurfaceDelegate.isShowing()) + || errorCookie != mLastErrorCookie) { + return; } + + // The RedBox surface delegate will always show the latest error + updateLastErrorInfo( + message, StackTraceHelper.convertJsStackTrace(details), errorCookie, ErrorType.JS); + mRedBoxSurfaceDelegate.show(); }); } @@ -345,32 +317,28 @@ private void showNewError( final int errorCookie, final ErrorType errorType) { UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - // Keep a copy of the latest error to be shown by the RedBoxSurface - updateLastErrorInfo(message, stack, errorCookie, errorType); - - if (mRedBoxSurfaceDelegate == null) { - @Nullable SurfaceDelegate redBoxSurfaceDelegate = createSurfaceDelegate("RedBox"); - if (redBoxSurfaceDelegate != null) { - mRedBoxSurfaceDelegate = redBoxSurfaceDelegate; - } else { - mRedBoxSurfaceDelegate = - new RedBoxDialogSurfaceDelegate(DevSupportManagerBase.this); - } - - mRedBoxSurfaceDelegate.createContentView("RedBox"); + () -> { + // Keep a copy of the latest error to be shown by the RedBoxSurface + updateLastErrorInfo(message, stack, errorCookie, errorType); + + if (mRedBoxSurfaceDelegate == null) { + @Nullable SurfaceDelegate redBoxSurfaceDelegate = createSurfaceDelegate("RedBox"); + if (redBoxSurfaceDelegate != null) { + mRedBoxSurfaceDelegate = redBoxSurfaceDelegate; + } else { + mRedBoxSurfaceDelegate = new RedBoxDialogSurfaceDelegate(DevSupportManagerBase.this); } - if (mRedBoxSurfaceDelegate.isShowing()) { - // Sometimes errors cause multiple errors to be thrown in JS in quick succession. Only - // show the first and most actionable one. - return; - } + mRedBoxSurfaceDelegate.createContentView("RedBox"); + } - mRedBoxSurfaceDelegate.show(); + if (mRedBoxSurfaceDelegate.isShowing()) { + // Sometimes errors cause multiple errors to be thrown in JS in quick succession. Only + // show the first and most actionable one. + return; } + + mRedBoxSurfaceDelegate.show(); }); } @@ -411,62 +379,50 @@ public void onOptionSelected() { } options.put( mApplicationContext.getString(R.string.catalyst_debug_open), - new DevOptionHandler() { - @Override - public void onOptionSelected() { + () -> mDevServerHelper.openUrl( mCurrentContext, FLIPPER_DEBUGGER_URL, - mApplicationContext.getString(R.string.catalyst_open_flipper_error)); - } - }); + mApplicationContext.getString(R.string.catalyst_open_flipper_error))); options.put( mApplicationContext.getString(R.string.catalyst_devtools_open), - new DevOptionHandler() { - @Override - public void onOptionSelected() { + () -> mDevServerHelper.openUrl( mCurrentContext, FLIPPER_DEVTOOLS_URL, - mApplicationContext.getString(R.string.catalyst_open_flipper_error)); - } - }); + mApplicationContext.getString(R.string.catalyst_open_flipper_error))); } options.put( mApplicationContext.getString(R.string.catalyst_change_bundle_location), - new DevOptionHandler() { - @Override - public void onOptionSelected() { - Activity context = mReactInstanceDevHelper.getCurrentActivity(); - if (context == null || context.isFinishing()) { - FLog.e( - ReactConstants.TAG, - "Unable to launch change bundle location because react activity is not available"); - return; - } - - final EditText input = new EditText(context); - input.setHint("localhost:8081"); - - AlertDialog bundleLocationDialog = - new AlertDialog.Builder(context) - .setTitle( - mApplicationContext.getString(R.string.catalyst_change_bundle_location)) - .setView(input) - .setPositiveButton( - android.R.string.ok, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - String host = input.getText().toString(); - mDevSettings.getPackagerConnectionSettings().setDebugServerHost(host); - handleReloadJS(); - } - }) - .create(); - bundleLocationDialog.show(); + () -> { + Activity context = mReactInstanceDevHelper.getCurrentActivity(); + if (context == null || context.isFinishing()) { + FLog.e( + ReactConstants.TAG, + "Unable to launch change bundle location because react activity is not available"); + return; } + + final EditText input = new EditText(context); + input.setHint("localhost:8081"); + + AlertDialog bundleLocationDialog = + new AlertDialog.Builder(context) + .setTitle(mApplicationContext.getString(R.string.catalyst_change_bundle_location)) + .setView(input) + .setPositiveButton( + android.R.string.ok, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + String host = input.getText().toString(); + mDevSettings.getPackagerConnectionSettings().setDebugServerHost(host); + handleReloadJS(); + } + }) + .create(); + bundleLocationDialog.show(); }); options.put( @@ -485,58 +441,49 @@ public void onOptionSelected() { mDevSettings.isHotModuleReplacementEnabled() ? mApplicationContext.getString(R.string.catalyst_hot_reloading_stop) : mApplicationContext.getString(R.string.catalyst_hot_reloading), - new DevOptionHandler() { - @Override - public void onOptionSelected() { - boolean nextEnabled = !mDevSettings.isHotModuleReplacementEnabled(); - mDevSettings.setHotModuleReplacementEnabled(nextEnabled); - if (mCurrentContext != null) { - if (nextEnabled) { - mCurrentContext.getJSModule(HMRClient.class).enable(); - } else { - mCurrentContext.getJSModule(HMRClient.class).disable(); - } - } - if (nextEnabled && !mDevSettings.isJSDevModeEnabled()) { - Toast.makeText( - mApplicationContext, - mApplicationContext.getString(R.string.catalyst_hot_reloading_auto_enable), - Toast.LENGTH_LONG) - .show(); - mDevSettings.setJSDevModeEnabled(true); - handleReloadJS(); + () -> { + boolean nextEnabled = !mDevSettings.isHotModuleReplacementEnabled(); + mDevSettings.setHotModuleReplacementEnabled(nextEnabled); + if (mCurrentContext != null) { + if (nextEnabled) { + mCurrentContext.getJSModule(HMRClient.class).enable(); + } else { + mCurrentContext.getJSModule(HMRClient.class).disable(); } } + if (nextEnabled && !mDevSettings.isJSDevModeEnabled()) { + Toast.makeText( + mApplicationContext, + mApplicationContext.getString(R.string.catalyst_hot_reloading_auto_enable), + Toast.LENGTH_LONG) + .show(); + mDevSettings.setJSDevModeEnabled(true); + handleReloadJS(); + } }); options.put( mDevSettings.isFpsDebugEnabled() ? mApplicationContext.getString(R.string.catalyst_perf_monitor_stop) : mApplicationContext.getString(R.string.catalyst_perf_monitor), - new DevOptionHandler() { - @Override - public void onOptionSelected() { - if (!mDevSettings.isFpsDebugEnabled()) { - // Request overlay permission if needed when "Show Perf Monitor" option is selected - Context context = mReactInstanceDevHelper.getCurrentActivity(); - if (context == null) { - FLog.e(ReactConstants.TAG, "Unable to get reference to react activity"); - } else { - DebugOverlayController.requestPermission(context); - } + () -> { + if (!mDevSettings.isFpsDebugEnabled()) { + // Request overlay permission if needed when "Show Perf Monitor" option is selected + Context context = mReactInstanceDevHelper.getCurrentActivity(); + if (context == null) { + FLog.e(ReactConstants.TAG, "Unable to get reference to react activity"); + } else { + DebugOverlayController.requestPermission(context); } - mDevSettings.setFpsDebugEnabled(!mDevSettings.isFpsDebugEnabled()); } + mDevSettings.setFpsDebugEnabled(!mDevSettings.isFpsDebugEnabled()); }); options.put( mApplicationContext.getString(R.string.catalyst_settings), - new DevOptionHandler() { - @Override - public void onOptionSelected() { - Intent intent = new Intent(mApplicationContext, DevSettingsActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mApplicationContext.startActivity(intent); - } + () -> { + Intent intent = new Intent(mApplicationContext, DevSettingsActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mApplicationContext.startActivity(intent); }); if (mCustomDevOptions.size() > 0) { @@ -553,33 +500,36 @@ public void onOptionSelected() { return; } - final TextView textView = new TextView(getApplicationContext()); - textView.setText("React Native DevMenu (" + getUniqueTag() + ")"); - textView.setPadding(0, 50, 0, 0); - textView.setGravity(Gravity.CENTER); - textView.setTextColor(Color.BLACK); - textView.setTextSize(17); - textView.setTypeface(textView.getTypeface(), Typeface.BOLD); + final LinearLayout header = new LinearLayout(context); + header.setOrientation(LinearLayout.VERTICAL); + + final TextView title = new TextView(context); + title.setText(context.getString(R.string.catalyst_dev_menu_header, getUniqueTag())); + title.setPadding(0, 50, 0, 0); + title.setGravity(Gravity.CENTER); + title.setTextSize(16); + title.setTypeface(title.getTypeface(), Typeface.BOLD); + + final TextView jsExecutorLabel = new TextView(context); + jsExecutorLabel.setText( + context.getString(R.string.catalyst_dev_menu_sub_header, getJSExecutorDescription())); + jsExecutorLabel.setPadding(0, 20, 0, 0); + jsExecutorLabel.setGravity(Gravity.CENTER); + jsExecutorLabel.setTextSize(14); + + header.addView(title); + header.addView(jsExecutorLabel); mDevOptionsDialog = new AlertDialog.Builder(context) - .setCustomTitle(textView) + .setCustomTitle(header) .setItems( options.keySet().toArray(new String[0]), - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - optionHandlers[which].onOptionSelected(); - mDevOptionsDialog = null; - } - }) - .setOnCancelListener( - new DialogInterface.OnCancelListener() { - @Override - public void onCancel(DialogInterface dialog) { - mDevOptionsDialog = null; - } + (dialog, which) -> { + optionHandlers[which].onOptionSelected(); + mDevOptionsDialog = null; }) + .setOnCancelListener(dialog -> mDevOptionsDialog = null) .create(); mDevOptionsDialog.show(); if (mCurrentContext != null) { @@ -587,10 +537,14 @@ public void onCancel(DialogInterface dialog) { } } + private String getJSExecutorDescription() { + return getReactInstanceDevHelper().getJavaScriptExecutorFactory().toString(); + } + /** - * {@link ReactInstanceDevCommandsHandler} is responsible for enabling/disabling dev support when - * a React view is attached/detached or when application state changes (e.g. the application is - * backgrounded). + * {@link com.facebook.react.ReactInstanceManager} is responsible for enabling/disabling dev + * support when a React view is attached/detached or when application state changes (e.g. the + * application is backgrounded). */ @Override public void setDevSupportEnabled(boolean isDevSupportEnabled) { @@ -609,7 +563,7 @@ public DevInternalSettings getDevSettings() { } @Override - public RedBoxHandler getRedBoxHandler() { + public @Nullable RedBoxHandler getRedBoxHandler() { return mRedBoxHandler; } @@ -725,13 +679,7 @@ public void reloadSettings() { if (UiThreadUtil.isOnUiThread()) { reload(); } else { - UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - reload(); - } - }); + UiThreadUtil.runOnUiThread(this::reload); } } @@ -801,56 +749,42 @@ public void fetchSplitBundleAndCreateBundleLoader( final File bundleFile = new File(mJSSplitBundlesDir, bundlePath.replaceAll("/", "_") + ".jsbundle"); UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - showSplitBundleDevLoadingView(bundleUrl); - mDevServerHelper.downloadBundleFromURL( - new DevBundleDownloadListener() { - @Override - public void onSuccess() { - UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - hideSplitBundleDevLoadingView(); - } - }); - - @Nullable ReactContext context = mCurrentContext; - if (context == null || !context.hasActiveReactInstance()) { - return; - } - - JSBundleLoader bundleLoader = - JSBundleLoader.createCachedSplitBundleFromNetworkLoader( - bundleUrl, bundleFile.getAbsolutePath()); - - callback.onSuccess(bundleLoader); + () -> { + showSplitBundleDevLoadingView(bundleUrl); + mDevServerHelper.downloadBundleFromURL( + new DevBundleDownloadListener() { + @Override + public void onSuccess() { + UiThreadUtil.runOnUiThread(() -> hideSplitBundleDevLoadingView()); + + @Nullable ReactContext context = mCurrentContext; + if (context == null || !context.hasActiveReactInstance()) { + return; } - @Override - public void onProgress( - @Nullable String status, @Nullable Integer done, @Nullable Integer total) { - mDevLoadingViewManager.updateProgress(status, done, total); - } - - @Override - public void onFailure(Exception cause) { - UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - hideSplitBundleDevLoadingView(); - } - }); - callback.onError(bundleUrl, cause); - } - }, - bundleFile, - bundleUrl, - null); - } + JSBundleLoader bundleLoader = + JSBundleLoader.createCachedSplitBundleFromNetworkLoader( + bundleUrl, bundleFile.getAbsolutePath()); + + callback.onSuccess(bundleLoader); + } + + @Override + public void onProgress( + @Nullable String status, @Nullable Integer done, @Nullable Integer total) { + mDevLoadingViewManager.updateProgress(status, done, total); + } + + @Override + public void onFailure(Exception cause) { + UiThreadUtil.runOnUiThread( + DevSupportManagerBase.this::hideSplitBundleDevLoadingView); + callback.onError(bundleUrl, cause); + } + }, + bundleFile, + bundleUrl, + null); }); } @@ -869,13 +803,7 @@ private void hideSplitBundleDevLoadingView() { @Override public void isPackagerRunning(final PackagerStatusCallback callback) { - Runnable checkPackagerRunning = - new Runnable() { - @Override - public void run() { - mDevServerHelper.isPackagerRunning(callback); - } - }; + Runnable checkPackagerRunning = () -> mDevServerHelper.isPackagerRunning(callback); if (mPackagerLocationCustomizer != null) { mPackagerLocationCustomizer.run(checkPackagerRunning); } else { @@ -946,18 +874,7 @@ private void updateLastErrorInfo( public void reloadJSFromServer(final String bundleURL) { reloadJSFromServer( bundleURL, - new BundleLoadCallback() { - @Override - public void onSuccess() { - UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - mReactInstanceDevHelper.onJSBundleLoadedFromServer(); - } - }); - } - }); + () -> UiThreadUtil.runOnUiThread(mReactInstanceDevHelper::onJSBundleLoadedFromServer)); } public void reloadJSFromServer(final String bundleURL, final BundleLoadCallback callback) { @@ -1014,16 +931,12 @@ public void onFailure(final Exception cause) { private void reportBundleLoadingFailure(final Exception cause) { UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - if (cause instanceof DebugServerException) { - DebugServerException debugServerException = (DebugServerException) cause; - showNewJavaError(debugServerException.getMessage(), cause); - } else { - showNewJavaError( - mApplicationContext.getString(R.string.catalyst_reload_error), cause); - } + () -> { + if (cause instanceof DebugServerException) { + DebugServerException debugServerException = (DebugServerException) cause; + showNewJavaError(debugServerException.getMessage(), cause); + } else { + showNewJavaError(mApplicationContext.getString(R.string.catalyst_reload_error), cause); } }); } @@ -1047,12 +960,9 @@ public void setHotModuleReplacementEnabled(final boolean isHotModuleReplacementE } UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - mDevSettings.setHotModuleReplacementEnabled(isHotModuleReplacementEnabled); - handleReloadJS(); - } + () -> { + mDevSettings.setHotModuleReplacementEnabled(isHotModuleReplacementEnabled); + handleReloadJS(); }); } @@ -1063,12 +973,9 @@ public void setRemoteJSDebugEnabled(final boolean isRemoteJSDebugEnabled) { } UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - mDevSettings.setRemoteJSDebugEnabled(isRemoteJSDebugEnabled); - handleReloadJS(); - } + () -> { + mDevSettings.setRemoteJSDebugEnabled(isRemoteJSDebugEnabled); + handleReloadJS(); }); } @@ -1078,13 +985,7 @@ public void setFpsDebugEnabled(final boolean isFpsDebugEnabled) { return; } - UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - mDevSettings.setFpsDebugEnabled(isFpsDebugEnabled); - } - }); + UiThreadUtil.runOnUiThread(() -> mDevSettings.setFpsDebugEnabled(isFpsDebugEnabled)); } @Override @@ -1094,12 +995,9 @@ public void toggleElementInspector() { } UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - mDevSettings.setElementInspectorEnabled(!mDevSettings.isElementInspectorEnabled()); - mReactInstanceDevHelper.toggleElementInspector(); - } + () -> { + mDevSettings.setElementInspectorEnabled(!mDevSettings.isElementInspectorEnabled()); + mReactInstanceDevHelper.toggleElementInspector(); }); } @@ -1150,35 +1048,17 @@ public void onPackagerDisconnected() { public void onPackagerReloadCommand() { // Disable debugger to resume the JsVM & avoid thread locks while reloading mDevServerHelper.disableDebugger(); - UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - handleReloadJS(); - } - }); + UiThreadUtil.runOnUiThread(() -> handleReloadJS()); } @Override public void onPackagerDevMenuCommand() { - UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - showDevOptionsDialog(); - } - }); + UiThreadUtil.runOnUiThread(() -> showDevOptionsDialog()); } @Override public void onCaptureHeapCommand(final Responder responder) { - UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - handleCaptureHeap(responder); - } - }); + UiThreadUtil.runOnUiThread(() -> handleCaptureHeap(responder)); } @Override diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/PerftestDevSupportManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/PerftestDevSupportManager.java index 2be621fc38ff6a..d15eba912d99d8 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/PerftestDevSupportManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/PerftestDevSupportManager.java @@ -31,12 +31,8 @@ public void onInternalSettingsChanged() {} new DevServerHelper( mDevSettings, applicationContext.getPackageName(), - new InspectorPackagerConnection.BundleStatusProvider() { - @Override - public InspectorPackagerConnection.BundleStatus getBundleStatus() { - return mBundleStatus; - } - }); + (InspectorPackagerConnection.BundleStatusProvider) () -> mBundleStatus, + mDevSettings.getPackagerConnectionSettings()); } @Override diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java index f4e9e6e308e5a2..f9057468f37dc7 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java @@ -421,6 +421,7 @@ public void onCatalystInstanceDestroy() { mEventDispatcher.unregisterEventEmitter(FABRIC); mReactApplicationContext.unregisterComponentCallbacks(mViewManagerRegistry); + mViewManagerRegistry.invalidate(); // Remove lifecycle listeners (onHostResume, onHostPause) since the FabricUIManager is going // away. Then stop the mDispatchUIFrameCallback false will cause the choreographer diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java index 8863d0edca1bbb..f3fb5e0a0024bf 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java @@ -103,7 +103,6 @@ public SurfaceMountingManager( @NonNull MountItemExecutor mountItemExecutor, @NonNull ThemedReactContext reactContext) { mSurfaceId = surfaceId; - mJSResponderHandler = jsResponderHandler; mViewManagerRegistry = viewManagerRegistry; mRootViewManager = rootViewManager; @@ -196,42 +195,39 @@ private void addRootView(@NonNull final View rootView) { true)); Runnable runnable = - new Runnable() { - @Override - public void run() { - // The CPU has ticked since `addRootView` was called, so the surface could technically - // have already stopped here. - if (isStopped()) { - return; - } - - if (rootView.getId() == mSurfaceId) { - ReactSoftExceptionLogger.logSoftException( - TAG, - new IllegalViewOperationException( - "Race condition in addRootView detected. Trying to set an id of [" - + mSurfaceId - + "] on the RootView, but that id has already been set. ")); - } else if (rootView.getId() != View.NO_ID) { - FLog.e( - TAG, - "Trying to add RootTag to RootView that already has a tag: existing tag: [%d] new tag: [%d]", - rootView.getId(), - mSurfaceId); - throw new IllegalViewOperationException( - "Trying to add a root view with an explicit id already set. React Native uses " - + "the id field to track react tags and will overwrite this field. If that is fine, " - + "explicitly overwrite the id field to View.NO_ID before calling addRootView."); - } - rootView.setId(mSurfaceId); + () -> { + // The CPU has ticked since `addRootView` was called, so the surface could technically + // have already stopped here. + if (isStopped()) { + return; + } - if (rootView instanceof ReactRoot) { - ((ReactRoot) rootView).setRootViewTag(mSurfaceId); - } - mRootViewAttached = true; + if (rootView.getId() == mSurfaceId) { + ReactSoftExceptionLogger.logSoftException( + TAG, + new IllegalViewOperationException( + "Race condition in addRootView detected. Trying to set an id of [" + + mSurfaceId + + "] on the RootView, but that id has already been set. ")); + } else if (rootView.getId() != View.NO_ID) { + FLog.e( + TAG, + "Trying to add RootTag to RootView that already has a tag: existing tag: [%d] new tag: [%d]", + rootView.getId(), + mSurfaceId); + throw new IllegalViewOperationException( + "Trying to add a root view with an explicit id already set. React Native uses " + + "the id field to track react tags and will overwrite this field. If that is fine, " + + "explicitly overwrite the id field to View.NO_ID before calling addRootView."); + } + rootView.setId(mSurfaceId); - executeViewAttachMountItems(); + if (rootView instanceof ReactRoot) { + ((ReactRoot) rootView).setRootViewTag(mSurfaceId); } + mRootViewAttached = true; + + executeViewAttachMountItems(); }; if (UiThreadUtil.isOnUiThread()) { @@ -1105,21 +1101,26 @@ public void updateEventEmitter(int reactTag, @NonNull EventEmitterWrapper eventE previousEventEmitterWrapper.destroy(); } - if (viewState.mPendingEventQueue != null) { + Queue pendingEventQueue = viewState.mPendingEventQueue; + if (pendingEventQueue != null) { // Invoke pending event queued to the view state - for (ViewEvent viewEvent : viewState.mPendingEventQueue) { - if (viewEvent.canCoalesceEvent()) { - eventEmitter.dispatchUnique( - viewEvent.getEventName(), viewEvent.getParams(), viewEvent.getCustomCoalesceKey()); - } else { - eventEmitter.dispatch( - viewEvent.getEventName(), viewEvent.getParams(), viewEvent.getEventCategory()); - } + for (ViewEvent viewEvent : pendingEventQueue) { + dispatchEvent(eventEmitter, viewEvent); } viewState.mPendingEventQueue = null; } } + private void dispatchEvent(EventEmitterWrapper eventEmitter, ViewEvent viewEvent) { + if (viewEvent.canCoalesceEvent()) { + eventEmitter.dispatchUnique( + viewEvent.getEventName(), viewEvent.getParams(), viewEvent.getCustomCoalesceKey()); + } else { + eventEmitter.dispatch( + viewEvent.getEventName(), viewEvent.getParams(), viewEvent.getEventCategory()); + } + } + @UiThread public synchronized void setJSResponder( int reactTag, int initialReactTag, boolean blockNativeResponder) { @@ -1301,9 +1302,18 @@ public void enqueuePendingEvent(int reactTag, ViewEvent viewEvent) { // Cannot queue event without view state. Do nothing here. return; } - Assertions.assertCondition( - viewState.mEventEmitter == null, - "Only queue pending events when event emitter is null for the given view state"); + EventEmitterWrapper eventEmitter = viewState.mEventEmitter; + if (eventEmitter != null) { + // TODO T152630743: Verify threading for mEventEmitter + FLog.i( + TAG, + "Queue pending events when event emitter is null for the given view state, this should be dispatched instead - surfaceId: " + + mSurfaceId + + " reactTag: " + + reactTag); + dispatchEvent(eventEmitter, viewEvent); + return; + } if (viewState.mPendingEventQueue == null) { viewState.mPendingEventQueue = new LinkedList<>(); @@ -1342,6 +1352,7 @@ private ViewState( mViewManager = viewManager; } + @NonNull @Override public String toString() { boolean isLayoutOnly = mViewManager == null; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/common/ModuleDataCleaner.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/common/ModuleDataCleaner.java index fabc71170f32a2..ed1b526ad1710d 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/common/ModuleDataCleaner.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/common/ModuleDataCleaner.java @@ -43,6 +43,7 @@ public interface Cleanable { * * @deprecated */ + @Deprecated public static void cleanDataFromModules(CatalystInstance catalystInstance) { for (NativeModule nativeModule : catalystInstance.getNativeModules()) { if (nativeModule instanceof Cleanable) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java index b15a2984f20cdc..b8f10af4da9e2c 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java @@ -26,6 +26,7 @@ import com.facebook.react.common.MapBuilder; import com.facebook.react.common.ReactConstants; import com.facebook.react.uimanager.ReactAccessibilityDelegate.AccessibilityRole; +import com.facebook.react.uimanager.ReactAccessibilityDelegate.Role; import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.events.PointerEventHelper; import com.facebook.react.uimanager.util.ReactFindViewUtil; @@ -234,9 +235,10 @@ public void setAccessibilityHint(@NonNull T view, @Nullable String accessibility @ReactProp(name = ViewProps.ACCESSIBILITY_ROLE) public void setAccessibilityRole(@NonNull T view, @Nullable String accessibilityRole) { if (accessibilityRole == null) { - return; + view.setTag(R.id.accessibility_role, null); + } else { + view.setTag(R.id.accessibility_role, AccessibilityRole.fromValue(accessibilityRole)); } - view.setTag(R.id.accessibility_role, AccessibilityRole.fromValue(accessibilityRole)); } @Override @@ -380,6 +382,16 @@ public void setImportantForAccessibility( } } + @Override + @ReactProp(name = ViewProps.ROLE) + public void setRole(@NonNull T view, @Nullable String role) { + if (role == null) { + view.setTag(R.id.role, null); + } else { + view.setTag(R.id.role, Role.fromValue(role)); + } + } + @Override @Deprecated @ReactProp(name = ViewProps.ROTATION) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManagerAdapter.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManagerAdapter.java index afd33e22eb1ba5..3e3d7c8bdc33ba 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManagerAdapter.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManagerAdapter.java @@ -70,6 +70,9 @@ public void setShadowColor(@NonNull T view, int shadowColor) {} public void setImportantForAccessibility( @NonNull T view, @Nullable String importantForAccessibility) {} + @Override + public void setRole(@NonNull T view, @Nullable String role) {} + @Override public void setNativeId(@NonNull T view, String nativeId) {} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManagerDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManagerDelegate.java index bb809381494e5e..e59a1c4da3b80f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManagerDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManagerDelegate.java @@ -89,6 +89,9 @@ public void setProperty(T view, String propName, @Nullable Object value) { case ViewProps.IMPORTANT_FOR_ACCESSIBILITY: mViewManager.setImportantForAccessibility(view, (String) value); break; + case ViewProps.ROLE: + mViewManager.setRole(view, (String) value); + break; case ViewProps.NATIVE_ID: mViewManager.setNativeId(view, (String) value); break; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManagerInterface.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManagerInterface.java index 0a6a9a561d5c61..5887ff5ba31535 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManagerInterface.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManagerInterface.java @@ -52,6 +52,8 @@ public interface BaseViewManagerInterface { void setImportantForAccessibility(T view, @Nullable String importantForAccessibility); + void setRole(T view, @Nullable String role); + void setNativeId(T view, @Nullable String nativeId); void setAccessibilityLabelledBy(T view, @Nullable Dynamic nativeId); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSPointerDispatcher.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSPointerDispatcher.java index c2125fa3eed78a..bc904f755f9941 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSPointerDispatcher.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSPointerDispatcher.java @@ -7,6 +7,7 @@ package com.facebook.react.uimanager; +import android.graphics.Rect; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -63,10 +64,24 @@ public void onChildStartedNativeGesture( return; } - dispatchCancelEvent(motionEvent, eventDispatcher); + MotionEvent motionInRoot = convertMotionToRootFrame(childView, motionEvent); + + dispatchCancelEventForTarget(childView, motionInRoot, eventDispatcher); mChildHandlingNativeGesture = childView.getId(); } + private MotionEvent convertMotionToRootFrame(View childView, MotionEvent childMotion) { + MotionEvent motionInRoot = MotionEvent.obtain(childMotion); + final int cX = (int) childMotion.getX(); + final int cY = (int) childMotion.getY(); + Rect childCoords = new Rect(cX, cY, cX + 1, cY + 1); + // note: should be safe since we're only looking at descendants of the root + mRootViewGroup.offsetDescendantRectToMyCoords(childView, childCoords); + motionInRoot.setLocation(childCoords.left, childCoords.top); + + return motionInRoot; + } + public void onChildEndedNativeGesture() { // There should be only one child gesture at any given time. We can safely turn off the flag. mChildHandlingNativeGesture = -1; @@ -228,6 +243,7 @@ public void handleMotionEvent( // Calculate the targetTag, with special handling for when we exit the root view. In that case, // we use the root viewId of the last event int activeTargetTag; + View activeTargetView; List activeHitPath; if (isExitFromRoot) { @@ -238,7 +254,9 @@ public void handleMotionEvent( if (lastHitPath == null || lastHitPath.isEmpty()) { return; } - activeTargetTag = lastHitPath.get(lastHitPath.size() - 1).getViewId(); + ViewTarget activeTarget = lastHitPath.get(lastHitPath.size() - 1); + activeTargetTag = activeTarget.getViewId(); + activeTargetView = activeTarget.getView(); // Explicitly make the hit path for this cursor empty activeHitPath = new ArrayList<>(); @@ -248,7 +266,9 @@ public void handleMotionEvent( if (activeHitPath == null || activeHitPath.isEmpty()) { return; } - activeTargetTag = activeHitPath.get(0).getViewId(); + ViewTarget activeTarget = activeHitPath.get(0); + activeTargetTag = activeTarget.getViewId(); + activeTargetView = activeTarget.getView(); } handleHitStateDivergence(activeTargetTag, eventState, motionEvent, eventDispatcher); @@ -284,7 +304,7 @@ public void handleMotionEvent( onUp(activeTargetTag, eventState, motionEvent, eventDispatcher); break; case MotionEvent.ACTION_CANCEL: - dispatchCancelEvent(eventState, motionEvent, eventDispatcher); + dispatchCancelEventForTarget(activeTargetView, eventState, motionEvent, eventDispatcher); break; case MotionEvent.ACTION_HOVER_ENTER: // Ignore these events as enters will be calculated from HOVER_MOVE @@ -504,7 +524,8 @@ private void onMove( } } - private void dispatchCancelEvent(MotionEvent motionEvent, EventDispatcher eventDispatcher) { + private void dispatchCancelEventForTarget( + View targetView, MotionEvent motionEvent, EventDispatcher eventDispatcher) { Assertions.assertCondition( mChildHandlingNativeGesture == -1, "Expected to not have already sent a cancel for this gesture"); @@ -512,11 +533,14 @@ private void dispatchCancelEvent(MotionEvent motionEvent, EventDispatcher eventD int activeIndex = motionEvent.getActionIndex(); int activePointerId = motionEvent.getPointerId(activeIndex); PointerEventState eventState = createEventState(activePointerId, motionEvent); - dispatchCancelEvent(eventState, motionEvent, eventDispatcher); + dispatchCancelEventForTarget(targetView, eventState, motionEvent, eventDispatcher); } - private void dispatchCancelEvent( - PointerEventState eventState, MotionEvent motionEvent, EventDispatcher eventDispatcher) { + private void dispatchCancelEventForTarget( + View targetView, + PointerEventState eventState, + MotionEvent motionEvent, + EventDispatcher eventDispatcher) { // This means the gesture has already ended, via some other CANCEL or UP event. This is not // expected to happen very often as it would mean some child View has decided to intercept the // touch stream and start a native gesture only upon receiving the UP/CANCEL event. @@ -532,18 +556,31 @@ private void dispatchCancelEvent( isAnyoneListeningForBubblingEvent(activeHitPath, EVENT.CANCEL, EVENT.CANCEL_CAPTURE); if (listeningForCancel) { int targetTag = activeHitPath.get(0).getViewId(); + + // cancel events need to report client coordinates of (0, 0) and offset coordinates relative + // to the root view + int[] childOffset = getChildOffsetRelativeToRoot(targetView); + PointerEventState normalizedEventState = + normalizeToRoot(eventState, childOffset[0], childOffset[1]); Assertions.assertNotNull(eventDispatcher) .dispatchEvent( PointerEvent.obtain( - PointerEventHelper.POINTER_CANCEL, targetTag, eventState, motionEvent)); + PointerEventHelper.POINTER_CANCEL, + targetTag, + normalizedEventState, + motionEvent)); } - // TODO(luwe) - Need to fire pointer out here as well: + // Need to fire pointer out + pointer leave here as well: // https://w3c.github.io/pointerevents/#dfn-suppress-a-pointer-event-stream + List outViewTargets = + filterByShouldDispatch(activeHitPath, EVENT.OUT, EVENT.OUT_CAPTURE, false); List leaveViewTargets = filterByShouldDispatch(activeHitPath, EVENT.LEAVE, EVENT.LEAVE_CAPTURE, false); // dispatch from target -> root + dispatchEventForViewTargets( + PointerEventHelper.POINTER_OUT, eventState, motionEvent, outViewTargets, eventDispatcher); dispatchEventForViewTargets( PointerEventHelper.POINTER_LEAVE, eventState, @@ -558,6 +595,44 @@ private void dispatchCancelEvent( } } + // returns child (0, 0) relative to root coordinate system + private int[] getChildOffsetRelativeToRoot(View childView) { + Rect childCoords = new Rect(0, 0, 1, 1); + mRootViewGroup.offsetDescendantRectToMyCoords(childView, childCoords); + return new int[] {childCoords.top, childCoords.left}; + } + + // Returns a copy of `original` with coordinates zeroed relative to the provided root coordinates. + // In particular, + // - the event (client) coordinates will all be set to 0 + // - the offset coordinates will be set to the root coordinates + private PointerEventState normalizeToRoot(PointerEventState original, float rootX, float rootY) { + Map newOffsets = new HashMap<>(original.getOffsetByPointerId()); + Map newEventCoords = new HashMap<>(original.getEventCoordinatesByPointerId()); + + for (Map.Entry offsetEntry : newOffsets.entrySet()) { + float[] offsetValue = offsetEntry.getValue(); + offsetValue[0] = rootX; + offsetValue[1] = rootY; + } + + for (Map.Entry eventCoordsEntry : newEventCoords.entrySet()) { + float[] eventCoordsValue = eventCoordsEntry.getValue(); + eventCoordsValue[0] = 0; + eventCoordsValue[1] = 0; + } + + return new PointerEventState( + original.getPrimaryPointerId(), + original.getActivePointerId(), + original.getLastButtonState(), + original.getSurfaceId(), + newOffsets, + new HashMap<>(original.getHitPathByPointerId()), + newEventCoords, + new HashSet<>(original.getHoveringPointerIds())); + } + private static void debugPrintHitPath(List hitPath) { StringBuilder builder = new StringBuilder("hitPath: "); for (ViewTarget viewTarget : hitPath) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java index 626232ed0f3998..531e4591ba6a99 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java @@ -96,6 +96,87 @@ private void scheduleAccessibilityEventSender(View host) { mHandler.sendMessageDelayed(msg, TIMEOUT_SEND_ACCESSIBILITY_EVENT); } + /** + * An ARIA Role representable by View's `role` prop. Ordinals should be kept in sync with + * `facebook::react::Role`. + */ + public enum Role { + ALERT, + ALERTDIALOG, + APPLICATION, + ARTICLE, + BANNER, + BUTTON, + CELL, + CHECKBOX, + COLUMNHEADER, + COMBOBOX, + COMPLEMENTARY, + CONTENTINFO, + DEFINITION, + DIALOG, + DIRECTORY, + DOCUMENT, + FEED, + FIGURE, + FORM, + GRID, + GROUP, + HEADING, + IMG, + LINK, + LIST, + LISTITEM, + LOG, + MAIN, + MARQUEE, + MATH, + MENU, + MENUBAR, + MENUITEM, + METER, + NAVIGATION, + NONE, + NOTE, + OPTION, + PRESENTATION, + PROGRESSBAR, + RADIO, + RADIOGROUP, + REGION, + ROW, + ROWGROUP, + ROWHEADER, + SCROLLBAR, + SEARCHBOX, + SEPARATOR, + SLIDER, + SPINBUTTON, + STATUS, + SUMMARY, + SWITCH, + TAB, + TABLE, + TABLIST, + TABPANEL, + TERM, + TIMER, + TOOLBAR, + TOOLTIP, + TREE, + TREEGRID, + TREEITEM; + + public static @Nullable Role fromValue(@Nullable String value) { + for (Role role : Role.values()) { + if (role.name().equalsIgnoreCase(value)) { + return role; + } + } + return null; + } + } + /** * These roles are defined by Google's TalkBack screen reader, and this list should be kept up to * date with their implementation. Details can be seen in their source code here: @@ -221,6 +302,75 @@ public static AccessibilityRole fromValue(@Nullable String value) { } throw new IllegalArgumentException("Invalid accessibility role value: " + value); } + + public static @Nullable AccessibilityRole fromRole(Role role) { + switch (role) { + case ALERT: + return AccessibilityRole.ALERT; + case BUTTON: + return AccessibilityRole.BUTTON; + case CHECKBOX: + return AccessibilityRole.CHECKBOX; + case COMBOBOX: + return AccessibilityRole.COMBOBOX; + case GRID: + return AccessibilityRole.GRID; + case HEADING: + return AccessibilityRole.HEADER; + case IMG: + return AccessibilityRole.IMAGE; + case LINK: + return AccessibilityRole.LINK; + case LIST: + return AccessibilityRole.LIST; + case MENU: + return AccessibilityRole.MENU; + case MENUBAR: + return AccessibilityRole.MENUBAR; + case MENUITEM: + return AccessibilityRole.MENUITEM; + case NONE: + return AccessibilityRole.NONE; + case PROGRESSBAR: + return AccessibilityRole.PROGRESSBAR; + case RADIO: + return AccessibilityRole.RADIO; + case RADIOGROUP: + return AccessibilityRole.RADIOGROUP; + case SCROLLBAR: + return AccessibilityRole.SCROLLBAR; + case SEARCHBOX: + return AccessibilityRole.SEARCH; + case SLIDER: + return AccessibilityRole.ADJUSTABLE; + case SPINBUTTON: + return AccessibilityRole.SPINBUTTON; + case SUMMARY: + return AccessibilityRole.SUMMARY; + case SWITCH: + return AccessibilityRole.SWITCH; + case TAB: + return AccessibilityRole.TAB; + case TABLIST: + return AccessibilityRole.TABLIST; + case TIMER: + return AccessibilityRole.TIMER; + case TOOLBAR: + return AccessibilityRole.TOOLBAR; + default: + // No mapping from ARIA role to AccessibilityRole + return null; + } + } + + public static @Nullable AccessibilityRole fromViewTag(View view) { + Role role = (Role) view.getTag(R.id.role); + if (role != null) { + return AccessibilityRole.fromRole(role); + } else { + return (AccessibilityRole) view.getTag(R.id.accessibility_role); + } + } } private final HashMap mAccessibilityActionsMap; @@ -267,8 +417,7 @@ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCo ? AccessibilityNodeInfoCompat.ACTION_COLLAPSE : AccessibilityNodeInfoCompat.ACTION_EXPAND); } - final AccessibilityRole accessibilityRole = - (AccessibilityRole) host.getTag(R.id.accessibility_role); + final AccessibilityRole accessibilityRole = AccessibilityRole.fromViewTag(host); final String accessibilityHint = (String) host.getTag(R.id.accessibility_hint); if (accessibilityRole != null) { setRole(info, accessibilityRole, host.getContext()); @@ -551,7 +700,8 @@ public static void setDelegate( || view.getTag(R.id.accessibility_actions) != null || view.getTag(R.id.react_test_id) != null || view.getTag(R.id.accessibility_collection_item) != null - || view.getTag(R.id.accessibility_links) != null)) { + || view.getTag(R.id.accessibility_links) != null + || view.getTag(R.id.role) != null)) { ViewCompat.setAccessibilityDelegate( view, new ReactAccessibilityDelegate(view, originalFocus, originalImportantForAccessibility)); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/RootView.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/RootView.java index ca8fa5f65849ee..4e0e1723368e05 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/RootView.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/RootView.java @@ -20,6 +20,7 @@ public interface RootView { void onChildStartedNativeGesture(View childView, MotionEvent ev); /** @deprecated */ + @Deprecated void onChildStartedNativeGesture(MotionEvent ev); /** diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java index ed4ec63c05d5b3..f15004e38e91d2 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java @@ -792,6 +792,7 @@ public void onHostDestroy() {} public void onCatalystInstanceDestroyed() { mViewOperationsEnabled = false; + mViewManagers.invalidate(); } public void setViewHierarchyUpdateDebugListener( diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagerRegistry.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagerRegistry.java index 995f6eea70333a..1f3c219250a71f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagerRegistry.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagerRegistry.java @@ -103,12 +103,28 @@ public void onSurfaceStopped(final int surfaceId) { viewManagers = new ArrayList<>(mViewManagers.values()); } Runnable runnable = - new Runnable() { - @Override - public void run() { - for (ViewManager viewManager : viewManagers) { - viewManager.onSurfaceStopped(surfaceId); - } + () -> { + for (ViewManager viewManager : viewManagers) { + viewManager.onSurfaceStopped(surfaceId); + } + }; + if (UiThreadUtil.isOnUiThread()) { + runnable.run(); + } else { + UiThreadUtil.runOnUiThread(runnable); + } + } + + /** Called on instance destroy */ + public void invalidate() { + final List viewManagers; + synchronized (this) { + viewManagers = new ArrayList<>(mViewManagers.values()); + } + Runnable runnable = + () -> { + for (ViewManager viewManager : viewManagers) { + viewManager.invalidate(); } }; if (UiThreadUtil.isOnUiThread()) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java index 3f76fa7dd3d9b1..cc9f7178e65919 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java @@ -166,6 +166,7 @@ public class ViewProps { public static final String ACCESSIBILITY_VALUE = "accessibilityValue"; public static final String ACCESSIBILITY_LABELLED_BY = "accessibilityLabelledBy"; public static final String IMPORTANT_FOR_ACCESSIBILITY = "importantForAccessibility"; + public static final String ROLE = "role"; // DEPRECATED public static final String ROTATION = "rotation"; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/PointerEvent.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/PointerEvent.java index bdcab7b048a6e7..9b5bc00a973376 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/PointerEvent.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/PointerEvent.java @@ -356,6 +356,10 @@ public boolean supportsHover(int pointerId) { return mHoveringPointerIds.contains(pointerId); } + public Set getHoveringPointerIds() { + return mHoveringPointerIds; + } + public final Map getOffsetByPointerId() { return mOffsetByPointerId; } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/drawer/ReactDrawerLayout.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/drawer/ReactDrawerLayout.java index 40392887a1c781..d5d3931b00b2cd 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/drawer/ReactDrawerLayout.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/drawer/ReactDrawerLayout.java @@ -42,8 +42,8 @@ public ReactDrawerLayout(ReactContext reactContext) { public void onInitializeAccessibilityNodeInfo( View host, AccessibilityNodeInfoCompat info) { super.onInitializeAccessibilityNodeInfo(host, info); - final AccessibilityRole accessibilityRole = - (AccessibilityRole) host.getTag(R.id.accessibility_role); + + final AccessibilityRole accessibilityRole = AccessibilityRole.fromViewTag(host); if (accessibilityRole != null) { info.setClassName(AccessibilityRole.getValue(accessibilityRole)); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewAccessibilityDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewAccessibilityDelegate.java index 6cf22db90c04e1..adbb78611c6515 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewAccessibilityDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewAccessibilityDelegate.java @@ -17,6 +17,7 @@ import com.facebook.react.bridge.ReactSoftExceptionLogger; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.uimanager.ReactAccessibilityDelegate; +import com.facebook.react.uimanager.ReactAccessibilityDelegate.AccessibilityRole; public class ReactScrollViewAccessibilityDelegate extends AccessibilityDelegateCompat { private final String TAG = ReactScrollViewAccessibilityDelegate.class.getSimpleName(); @@ -105,7 +106,7 @@ private void onInitializeAccessibilityEventInternal(View view, AccessibilityEven } } - if (isVisible == true && accessibilityCollectionItem != null) { + if (isVisible && accessibilityCollectionItem != null) { if (firstVisibleIndex == null) { firstVisibleIndex = accessibilityCollectionItem.getInt("itemIndex"); } @@ -122,8 +123,8 @@ private void onInitializeAccessibilityEventInternal(View view, AccessibilityEven private void onInitializeAccessibilityNodeInfoInternal( View view, AccessibilityNodeInfoCompat info) { - final ReactAccessibilityDelegate.AccessibilityRole accessibilityRole = - (ReactAccessibilityDelegate.AccessibilityRole) view.getTag(R.id.accessibility_role); + + final AccessibilityRole accessibilityRole = AccessibilityRole.fromViewTag(view); if (accessibilityRole != null) { ReactAccessibilityDelegate.setRole(info, accessibilityRole, view.getContext()); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java index 12c1c5e05728a9..4fd3a8165f4294 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java @@ -26,6 +26,8 @@ import com.facebook.react.uimanager.LayoutShadowNode; import com.facebook.react.uimanager.NativeViewHierarchyOptimizer; import com.facebook.react.uimanager.PixelUtil; +import com.facebook.react.uimanager.ReactAccessibilityDelegate.AccessibilityRole; +import com.facebook.react.uimanager.ReactAccessibilityDelegate.Role; import com.facebook.react.uimanager.ReactShadowNode; import com.facebook.react.uimanager.ViewProps; import com.facebook.react.uimanager.annotations.ReactProp; @@ -36,7 +38,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; /** * {@link ReactShadowNode} abstract class for spannable text nodes. @@ -180,7 +181,11 @@ private static void buildSpannedFromShadowNode( new SetSpanOperation( start, end, new ReactBackgroundColorSpan(textShadowNode.mBackgroundColor))); } - if (textShadowNode.mIsAccessibilityLink) { + boolean roleIsLink = + textShadowNode.mRole != null + ? textShadowNode.mRole == Role.LINK + : textShadowNode.mAccessibilityRole == AccessibilityRole.LINK; + if (roleIsLink) { ops.add( new SetSpanOperation(start, end, new ReactClickableSpan(textShadowNode.getReactTag()))); } @@ -325,7 +330,9 @@ protected Spannable spannedFromShadowNode( protected int mColor; protected boolean mIsBackgroundColorSet = false; protected int mBackgroundColor; - protected boolean mIsAccessibilityLink = false; + + protected @Nullable AccessibilityRole mAccessibilityRole = null; + protected @Nullable Role mRole = null; protected int mNumberOfLines = UNSET; protected int mTextAlign = Gravity.NO_GRAVITY; @@ -499,9 +506,17 @@ public void setBackgroundColor(@Nullable Integer color) { } @ReactProp(name = ViewProps.ACCESSIBILITY_ROLE) - public void setIsAccessibilityLink(@Nullable String accessibilityRole) { + public void setAccessibilityRole(@Nullable String accessibilityRole) { + if (isVirtual()) { + mAccessibilityRole = AccessibilityRole.fromValue(accessibilityRole); + markUpdated(); + } + } + + @ReactProp(name = ViewProps.ROLE) + public void setRole(@Nullable String role) { if (isVirtual()) { - mIsAccessibilityLink = Objects.equals(accessibilityRole, "link"); + mRole = Role.fromValue(role); markUpdated(); } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java index 7b5d0c1dd32eaf..f683c24f74d760 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java @@ -75,6 +75,16 @@ public void setAdjustFontSizeToFit(ReactTextView view, boolean adjustsFontSizeTo view.setAdjustFontSizeToFit(adjustsFontSizeToFit); } + @ReactProp(name = ViewProps.FONT_SIZE) + public void setFontSize(ReactTextView view, float fontSize) { + view.setFontSize(fontSize); + } + + @ReactProp(name = ViewProps.LETTER_SPACING, defaultFloat = Float.NaN) + public void setLetterSpacing(ReactTextView view, float letterSpacing) { + view.setLetterSpacing(letterSpacing); + } + @ReactProp(name = ViewProps.TEXT_ALIGN_VERTICAL) public void setTextAlignVertical(ReactTextView view, @Nullable String textAlignVertical) { if (textAlignVertical == null || "auto".equals(textAlignVertical)) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java index 6e742793eafe49..6cda1af267c0e0 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java @@ -18,6 +18,7 @@ import android.text.TextUtils; import android.text.method.LinkMovementMethod; import android.text.util.Linkify; +import android.util.TypedValue; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; @@ -57,6 +58,8 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie private int mNumberOfLines; private TextUtils.TruncateAt mEllipsizeLocation; private boolean mAdjustsFontSizeToFit; + private float mFontSize = Float.NaN; + private float mLetterSpacing = Float.NaN; private int mLinkifyMaskType; private boolean mNotifyOnInlineViewLayout; private boolean mTextIsSelectable; @@ -378,7 +381,7 @@ public void setText(ReactTextUpdate update) { // operation // TODO T56559197: remove this condition when we migrate 100% to Fabric if (paddingLeft != UNSET - && paddingBottom != UNSET + && paddingTop != UNSET && paddingRight != UNSET && paddingBottom != UNSET) { @@ -582,6 +585,29 @@ public void setAdjustFontSizeToFit(boolean adjustsFontSizeToFit) { mAdjustsFontSizeToFit = adjustsFontSizeToFit; } + public void setFontSize(float fontSize) { + mFontSize = + mAdjustsFontSizeToFit + ? (float) Math.ceil(PixelUtil.toPixelFromSP(fontSize)) + : (float) Math.ceil(PixelUtil.toPixelFromDIP(fontSize)); + + applyTextAttributes(); + } + + public void setLetterSpacing(float letterSpacing) { + if (Float.isNaN(letterSpacing)) { + return; + } + + float letterSpacingPixels = PixelUtil.toPixelFromDIP(letterSpacing); + + // `letterSpacingPixels` and `getEffectiveFontSize` are both in pixels, + // yielding an accurate em value. + mLetterSpacing = letterSpacingPixels / mFontSize; + + applyTextAttributes(); + } + public void setEllipsizeLocation(TextUtils.TruncateAt ellipsizeLocation) { mEllipsizeLocation = ellipsizeLocation; } @@ -651,4 +677,17 @@ protected boolean dispatchHoverEvent(MotionEvent event) { return super.dispatchHoverEvent(event); } + + private void applyTextAttributes() { + // Workaround for an issue where text can be cut off with an ellipsis when + // using certain font sizes and padding. Sets the provided text size and + // letter spacing to ensure consistent rendering and prevent cut-off. + if (!Float.isNaN(mFontSize)) { + setTextSize(TypedValue.COMPLEX_UNIT_PX, mFontSize); + } + + if (!Float.isNaN(mLetterSpacing)) { + super.setLetterSpacing(mLetterSpacing); + } + } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java index bc53523c81549e..eb03a50743f0d6 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java @@ -19,7 +19,8 @@ import com.facebook.react.common.ReactConstants; import com.facebook.react.common.mapbuffer.MapBuffer; import com.facebook.react.uimanager.PixelUtil; -import com.facebook.react.uimanager.ReactAccessibilityDelegate; +import com.facebook.react.uimanager.ReactAccessibilityDelegate.AccessibilityRole; +import com.facebook.react.uimanager.ReactAccessibilityDelegate.Role; import com.facebook.react.uimanager.ReactStylesDiffMap; import com.facebook.react.uimanager.ViewProps; import java.util.ArrayList; @@ -56,6 +57,8 @@ public class TextAttributeProps { public static final short TA_KEY_IS_HIGHLIGHTED = 22; public static final short TA_KEY_LAYOUT_DIRECTION = 23; public static final short TA_KEY_ACCESSIBILITY_ROLE = 24; + public static final short TA_KEY_LINE_BREAK_STRATEGY = 25; + public static final short TA_KEY_ROLE = 26; public static final int UNSET = -1; @@ -103,9 +106,8 @@ public class TextAttributeProps { protected boolean mIsLineThroughTextDecorationSet = false; protected boolean mIncludeFontPadding = true; - protected @Nullable ReactAccessibilityDelegate.AccessibilityRole mAccessibilityRole = null; - protected boolean mIsAccessibilityRoleSet = false; - protected boolean mIsAccessibilityLink = false; + protected @Nullable AccessibilityRole mAccessibilityRole = null; + protected @Nullable Role mRole = null; protected int mFontStyle = UNSET; protected int mFontWeight = UNSET; @@ -214,6 +216,9 @@ public static TextAttributeProps fromMapBuffer(MapBuffer props) { case TA_KEY_ACCESSIBILITY_ROLE: result.setAccessibilityRole(entry.getStringValue()); break; + case TA_KEY_ROLE: + result.setRole(Role.values()[entry.getIntValue()]); + break; } } @@ -254,6 +259,7 @@ public static TextAttributeProps fromReadableMap(ReactStylesDiffMap props) { result.setTextTransform(getStringProp(props, PROP_TEXT_TRANSFORM)); result.setLayoutDirection(getStringProp(props, ViewProps.LAYOUT_DIRECTION)); result.setAccessibilityRole(getStringProp(props, ViewProps.ACCESSIBILITY_ROLE)); + result.setRole(getStringProp(props, ViewProps.ROLE)); return result; } @@ -618,15 +624,25 @@ private void setTextTransform(@Nullable String textTransform) { } private void setAccessibilityRole(@Nullable String accessibilityRole) { - if (accessibilityRole != null) { - mIsAccessibilityRoleSet = true; - mAccessibilityRole = - ReactAccessibilityDelegate.AccessibilityRole.fromValue(accessibilityRole); - mIsAccessibilityLink = - mAccessibilityRole.equals(ReactAccessibilityDelegate.AccessibilityRole.LINK); + if (accessibilityRole == null) { + mAccessibilityRole = null; + } else { + mAccessibilityRole = AccessibilityRole.fromValue(accessibilityRole); + } + } + + private void setRole(@Nullable String role) { + if (role == null) { + mRole = null; + } else { + mRole = Role.fromValue(role); } } + private void setRole(Role role) { + mRole = role; + } + public static int getTextBreakStrategy(@Nullable String textBreakStrategy) { int androidTextBreakStrategy = DEFAULT_BREAK_STRATEGY; if (textBreakStrategy != null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java index 44195221646b0b..040171ed008225 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java @@ -33,6 +33,8 @@ import com.facebook.react.bridge.WritableArray; import com.facebook.react.common.build.ReactBuildConfig; import com.facebook.react.uimanager.PixelUtil; +import com.facebook.react.uimanager.ReactAccessibilityDelegate.AccessibilityRole; +import com.facebook.react.uimanager.ReactAccessibilityDelegate.Role; import com.facebook.react.uimanager.ReactStylesDiffMap; import com.facebook.react.uimanager.ViewProps; import com.facebook.yoga.YogaConstants; @@ -126,7 +128,11 @@ private static void buildSpannableFromFragment( sb.length(), new TextInlineViewPlaceholderSpan(reactTag, (int) width, (int) height))); } else if (end >= start) { - if (textAttributes.mIsAccessibilityLink) { + boolean roleIsLink = + textAttributes.mRole != null + ? textAttributes.mRole == Role.LINK + : textAttributes.mAccessibilityRole == AccessibilityRole.LINK; + if (roleIsLink) { ops.add(new SetSpanOperation(start, end, new ReactClickableSpan(reactTag))); } if (textAttributes.mIsColorSet) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java index bc0a56384b9229..9216703108829a 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java @@ -33,6 +33,8 @@ import com.facebook.react.common.mapbuffer.MapBuffer; import com.facebook.react.common.mapbuffer.ReadableMapBuffer; import com.facebook.react.uimanager.PixelUtil; +import com.facebook.react.uimanager.ReactAccessibilityDelegate.AccessibilityRole; +import com.facebook.react.uimanager.ReactAccessibilityDelegate.Role; import com.facebook.yoga.YogaConstants; import com.facebook.yoga.YogaMeasureMode; import com.facebook.yoga.YogaMeasureOutput; @@ -146,7 +148,11 @@ private static void buildSpannableFromFragment( sb.length(), new TextInlineViewPlaceholderSpan(reactTag, (int) width, (int) height))); } else if (end >= start) { - if (textAttributes.mIsAccessibilityLink) { + boolean roleIsLink = + textAttributes.mRole != null + ? textAttributes.mRole == Role.LINK + : textAttributes.mAccessibilityRole == AccessibilityRole.LINK; + if (roleIsLink) { ops.add(new SetSpanOperation(start, end, new ReactClickableSpan(reactTag))); } if (textAttributes.mIsColorSet) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactMapBufferPropSetter.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactMapBufferPropSetter.kt index a7effcdab1752e..7447e45313a52c 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactMapBufferPropSetter.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactMapBufferPropSetter.kt @@ -10,6 +10,7 @@ package com.facebook.react.views.view import android.graphics.Color import android.graphics.Rect import androidx.core.view.ViewCompat +import com.facebook.react.R import com.facebook.react.bridge.DynamicFromObject import com.facebook.react.bridge.JavaOnlyArray import com.facebook.react.bridge.JavaOnlyMap @@ -17,6 +18,7 @@ import com.facebook.react.bridge.ReadableMap import com.facebook.react.common.mapbuffer.MapBuffer import com.facebook.react.uimanager.PixelUtil import com.facebook.react.uimanager.PointerEvents +import com.facebook.react.uimanager.ReactAccessibilityDelegate.Role object ReactMapBufferPropSetter { // ViewProps values @@ -64,6 +66,7 @@ object ReactMapBufferPropSetter { private const val VP_POINTER_OVER_CAPTURE = 44 private const val VP_BORDER_CURVES = 45 // iOS only private const val VP_FG_COLOR = 46 // iOS only? + private const val VP_ROLE = 47 // Yoga values private const val YG_BORDER_WIDTH = 100 @@ -180,6 +183,9 @@ object ReactMapBufferPropSetter { VP_IMPORTANT_FOR_ACCESSIBILITY -> { view.importantForAccessibility(entry.intValue) } + VP_ROLE -> { + view.role(entry.intValue) + } VP_NATIVE_BACKGROUND -> { viewManager.nativeBackground(view, entry.mapBufferValue) } @@ -422,6 +428,10 @@ object ReactMapBufferPropSetter { ViewCompat.setImportantForAccessibility(this, mode) } + private fun ReactViewGroup.role(value: Int) { + setTag(R.id.role, Role.values()[value]) + } + private fun ReactViewGroup.pointerEvents(value: Int) { val pointerEvents = when (value) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManagerWrapper.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManagerWrapper.kt index f99677b1703ac3..69518a1524ba56 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManagerWrapper.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManagerWrapper.kt @@ -17,7 +17,7 @@ import com.facebook.react.uimanager.ThemedReactContext import com.facebook.react.uimanager.ViewManager /** Temporary to help trace the cause of T151032868 */ -class ReactViewReturnTypeException(message: String) : Exception(message) +class ReactViewReturnTypeException(message: String, e: Throwable) : Exception(message, e) interface ReactViewManagerWrapper { fun createView( @@ -55,19 +55,15 @@ interface ReactViewManagerWrapper { stateWrapper: StateWrapper?, jsResponderHandler: JSResponderHandler ): View { - val manager = - viewManager.createView( - reactTag, - reactContext, - props as? ReactStylesDiffMap, - stateWrapper, - jsResponderHandler) - // Throwing to try capture information about the cause of T151032868, remove after. - if (manager == null) { + try { + return viewManager.createView( + reactTag, reactContext, props as? ReactStylesDiffMap, stateWrapper, jsResponderHandler) + } catch (e: NullPointerException) { + // Throwing to try capture information about the cause of T151032868, remove after. throw ReactViewReturnTypeException( - "DefaultViewManagerWrapper::createView(${viewManager.getName()}, ${viewManager::class.java}) can't return null") + "DefaultViewManagerWrapper::createView(${viewManager.getName()}, ${viewManager::class.java}) can't return null", + e) } - return manager } override fun updateProperties(viewToUpdate: View, props: Any?) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNative.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNative.java index 524a93b3bd4288..74f4a98cb473d6 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNative.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNative.java @@ -32,13 +32,13 @@ public class YogaNative { // YGNode related static native long jni_YGNodeNewJNI(); static native long jni_YGNodeNewWithConfigJNI(long configPointer); - static native void jni_YGNodeFreeJNI(long nativePointer); + static native void jni_YGNodeDeallocateJNI(long nativePointer); static native void jni_YGNodeResetJNI(long nativePointer); static native void jni_YGNodeInsertChildJNI(long nativePointer, long childPointer, int index); static native void jni_YGNodeSwapChildJNI(long nativePointer, long childPointer, int index); static native void jni_YGNodeSetIsReferenceBaselineJNI(long nativePointer, boolean isReferenceBaseline); static native boolean jni_YGNodeIsReferenceBaselineJNI(long nativePointer); - static native void jni_YGNodeClearChildrenJNI(long nativePointer); + static native void jni_YGNodeRemoveAllChildrenJNI(long nativePointer); static native void jni_YGNodeRemoveChildJNI(long nativePointer, long childPointer); static native void jni_YGNodeCalculateLayoutJNI(long nativePointer, float width, float height, long[] nativePointers, YogaNodeJNIBase[] nodes); static native void jni_YGNodeMarkDirtyJNI(long nativePointer); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIBase.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIBase.java index 2420d999181b36..9100e64c817b44 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIBase.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIBase.java @@ -155,7 +155,7 @@ public YogaNodeJNIBase cloneWithoutChildren() { private void clearChildren() { mChildren = null; - YogaNative.jni_YGNodeClearChildrenJNI(mNativePointer); + YogaNative.jni_YGNodeRemoveAllChildrenJNI(mNativePointer); } public YogaNodeJNIBase removeChildAt(int i) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIFinalizer.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIFinalizer.java index 424006e978d8d3..ab617c7f16ff6c 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIFinalizer.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIFinalizer.java @@ -29,7 +29,7 @@ public void freeNatives() { if (mNativePointer != 0) { long nativePointer = mNativePointer; mNativePointer = 0; - YogaNative.jni_YGNodeFreeJNI(nativePointer); + YogaNative.jni_YGNodeDeallocateJNI(nativePointer); } } } diff --git a/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt b/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt index 824d4216c95724..78f2b949d92eee 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt +++ b/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt @@ -190,7 +190,6 @@ add_executable(reactnative_unittest -fexceptions -frtti -std=c++17 - -DANDROID -DHERMES_ENABLE_DEBUGGER) target_link_libraries(reactnative_unittest diff --git a/packages/react-native/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.h b/packages/react-native/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.h index 69f11392d3fd4c..13950445a7b0ca 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.h +++ b/packages/react-native/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.h @@ -5,6 +5,8 @@ * LICENSE file in the root directory of this source tree. */ +#include + const short int LAYOUT_EDGE_SET_FLAG_INDEX = 0; const short int LAYOUT_WIDTH_INDEX = 1; const short int LAYOUT_HEIGHT_INDEX = 2; @@ -36,14 +38,14 @@ class YGNodeEdges { YGNodeEdges(YGNodeRef node) { auto context = YGNodeContext{}; - context.asVoidPtr = node->getContext(); + context.asVoidPtr = YGNodeGetContext(node); edges_ = context.edgesSet; } void setOn(YGNodeRef node) { auto context = YGNodeContext{}; context.edgesSet = edges_; - node->setContext(context.asVoidPtr); + YGNodeSetContext(node, context.asVoidPtr); } bool has(Edge edge) { return (edges_ & edge) == edge; } diff --git a/packages/react-native/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNIVanilla.cpp b/packages/react-native/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNIVanilla.cpp index 3a30cdf0104d02..0a95d991976a8b 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNIVanilla.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNIVanilla.cpp @@ -7,18 +7,19 @@ #include "jni.h" #include "YGJNIVanilla.h" -#include #include #include "YGJNI.h" #include "common.h" #include "YGJTypesVanilla.h" -#include #include #include #include "YogaJniException.h" +// TODO: Reconcile missing layoutContext functionality from callbacks in the C +// API and use that +#include + using namespace facebook::yoga::vanillajni; -using facebook::yoga::detail::Log; static inline ScopedLocalRef YGNodeJobject( YGNodeRef node, @@ -34,11 +35,14 @@ static inline YGConfigRef _jlong2YGConfigRef(jlong addr) { return reinterpret_cast(static_cast(addr)); } -static jlong jni_YGConfigNewJNI(JNIEnv* env, jobject obj) { +static jlong jni_YGConfigNewJNI(JNIEnv* /*env*/, jobject /*obj*/) { return reinterpret_cast(YGConfigNew()); } -static void jni_YGConfigFreeJNI(JNIEnv* env, jobject obj, jlong nativePointer) { +static void jni_YGConfigFreeJNI( + JNIEnv* /*env*/, + jobject /*obj*/, + jlong nativePointer) { const YGConfigRef config = _jlong2YGConfigRef(nativePointer); // unique_ptr will destruct the underlying global_ref, if present. auto context = std::unique_ptr>{ @@ -47,8 +51,8 @@ static void jni_YGConfigFreeJNI(JNIEnv* env, jobject obj, jlong nativePointer) { } static void jni_YGConfigSetExperimentalFeatureEnabledJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer, jint feature, jboolean enabled) { @@ -58,8 +62,8 @@ static void jni_YGConfigSetExperimentalFeatureEnabledJNI( } static void jni_YGConfigSetUseWebDefaultsJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer, jboolean useWebDefaults) { const YGConfigRef config = _jlong2YGConfigRef(nativePointer); @@ -67,8 +71,8 @@ static void jni_YGConfigSetUseWebDefaultsJNI( } static void jni_YGConfigSetPrintTreeFlagJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer, jboolean enable) { const YGConfigRef config = _jlong2YGConfigRef(nativePointer); @@ -76,38 +80,29 @@ static void jni_YGConfigSetPrintTreeFlagJNI( } static void jni_YGConfigSetPointScaleFactorJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer, jfloat pixelsInPoint) { const YGConfigRef config = _jlong2YGConfigRef(nativePointer); YGConfigSetPointScaleFactor(config, pixelsInPoint); } -static void YGPrint(YGNodeRef node, void* layoutContext) { - if (auto obj = YGNodeJobject(node, layoutContext)) { - // TODO cout << obj.get()->toString() << endl; - } else { - Log::log( - node, - YGLogLevelError, - nullptr, - "Java YGNode was GCed during layout calculation\n"); - } -} - static void jni_YGConfigSetUseLegacyStretchBehaviourJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer, jboolean useLegacyStretchBehaviour) { const YGConfigRef config = _jlong2YGConfigRef(nativePointer); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" YGConfigSetUseLegacyStretchBehaviour(config, useLegacyStretchBehaviour); +#pragma clang diagnostic pop } static void jni_YGConfigSetErrataJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer, jint errata) { const YGConfigRef config = _jlong2YGConfigRef(nativePointer); @@ -115,34 +110,33 @@ static void jni_YGConfigSetErrataJNI( } static jint jni_YGConfigGetErrataJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer) { const YGConfigRef config = _jlong2YGConfigRef(nativePointer); return static_cast(YGConfigGetErrata(config)); } -static jlong jni_YGNodeNewJNI(JNIEnv* env, jobject obj) { +static jlong jni_YGNodeNewJNI(JNIEnv* /*env*/, jobject /*obj*/) { const YGNodeRef node = YGNodeNew(); - node->setContext(YGNodeContext{}.asVoidPtr); - node->setPrintFunc(YGPrint); + YGNodeSetContext(node, YGNodeContext{}.asVoidPtr); return reinterpret_cast(node); } static jlong jni_YGNodeNewWithConfigJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong configPointer) { const YGNodeRef node = YGNodeNewWithConfig(_jlong2YGConfigRef(configPointer)); - node->setContext(YGNodeContext{}.asVoidPtr); + YGNodeSetContext(node, YGNodeContext{}.asVoidPtr); return reinterpret_cast(node); } static int YGJNILogFunc( const YGConfigRef config, - const YGNodeRef node, + const YGNodeRef /*node*/, YGLogLevel level, - void* layoutContext, + void* /*layoutContext*/, const char* format, va_list args) { int result = vsnprintf(NULL, 0, format, args); @@ -184,7 +178,7 @@ static int YGJNILogFunc( static void jni_YGConfigSetLoggerJNI( JNIEnv* env, - jobject obj, + jobject /*obj*/, jlong nativePointer, jobject logger) { const YGConfigRef config = _jlong2YGConfigRef(nativePointer); @@ -208,24 +202,30 @@ static void jni_YGConfigSetLoggerJNI( } } -static void jni_YGNodeFreeJNI(JNIEnv* env, jobject obj, jlong nativePointer) { +static void jni_YGNodeDeallocateJNI( + JNIEnv* /*env*/, + jobject /*obj*/, + jlong nativePointer) { if (nativePointer == 0) { return; } const YGNodeRef node = _jlong2YGNodeRef(nativePointer); - YGNodeFree(node); + YGNodeDeallocate(node); } -static void jni_YGNodeResetJNI(JNIEnv* env, jobject obj, jlong nativePointer) { +static void jni_YGNodeResetJNI( + JNIEnv* /*env*/, + jobject /*obj*/, + jlong nativePointer) { const YGNodeRef node = _jlong2YGNodeRef(nativePointer); - void* context = node->getContext(); + void* context = YGNodeGetContext(node); YGNodeReset(node); - node->setContext(context); + YGNodeSetContext(node, context); } static void jni_YGNodeInsertChildJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer, jlong childPointer, jint index) { @@ -234,8 +234,8 @@ static void jni_YGNodeInsertChildJNI( } static void jni_YGNodeSwapChildJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer, jlong childPointer, jint index) { @@ -244,8 +244,8 @@ static void jni_YGNodeSwapChildJNI( } static void jni_YGNodeSetIsReferenceBaselineJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer, jboolean isReferenceBaseline) { YGNodeSetIsReferenceBaseline( @@ -253,23 +253,23 @@ static void jni_YGNodeSetIsReferenceBaselineJNI( } static jboolean jni_YGNodeIsReferenceBaselineJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer) { return YGNodeIsReferenceBaseline(_jlong2YGNodeRef(nativePointer)); } -static void jni_YGNodeClearChildrenJNI( - JNIEnv* env, - jobject obj, +static void jni_YGNodeRemoveAllChildrenJNI( + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer) { const YGNodeRef node = _jlong2YGNodeRef(nativePointer); - node->clearChildren(); + YGNodeRemoveAllChildren(node); } static void jni_YGNodeRemoveChildJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer, jlong childPointer) { YGNodeRemoveChild( @@ -281,16 +281,11 @@ static void YGTransferLayoutOutputsRecursive( jobject thiz, YGNodeRef root, void* layoutContext) { - if (!root->getHasNewLayout()) { + if (!YGNodeGetHasNewLayout(root)) { return; } auto obj = YGNodeJobject(root, layoutContext); if (!obj) { - Log::log( - root, - YGLogLevelError, - nullptr, - "Java YGNode was GCed during layout calculation\n"); return; } @@ -351,7 +346,7 @@ static void YGTransferLayoutOutputsRecursive( env->SetFloatArrayRegion(arrFinal.get(), 0, arrSize, arr); env->SetObjectField(obj.get(), arrField, arrFinal.get()); - root->setHasNewLayout(false); + YGNodeSetHasNewLayout(root, false); for (uint32_t i = 0; i < YGNodeGetChildCount(root); i++) { YGTransferLayoutOutputsRecursive( @@ -400,102 +395,102 @@ static void jni_YGNodeCalculateLayoutJNI( } static void jni_YGNodeMarkDirtyJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer) { YGNodeMarkDirty(_jlong2YGNodeRef(nativePointer)); } static void jni_YGNodeMarkDirtyAndPropagateToDescendantsJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer) { YGNodeMarkDirtyAndPropagateToDescendants(_jlong2YGNodeRef(nativePointer)); } static jboolean jni_YGNodeIsDirtyJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer) { - return (jboolean) _jlong2YGNodeRef(nativePointer)->isDirty(); + return (jboolean) YGNodeIsDirty(_jlong2YGNodeRef(nativePointer)); } static void jni_YGNodeCopyStyleJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong dstNativePointer, jlong srcNativePointer) { YGNodeCopyStyle( _jlong2YGNodeRef(dstNativePointer), _jlong2YGNodeRef(srcNativePointer)); } -#define YG_NODE_JNI_STYLE_PROP(javatype, type, name) \ - static javatype jni_YGNodeStyleGet##name##JNI( \ - JNIEnv* env, jobject obj, jlong nativePointer) { \ - return (javatype) YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer)); \ +#define YG_NODE_JNI_STYLE_PROP(javatype, type, name) \ + static javatype jni_YGNodeStyleGet##name##JNI( \ + JNIEnv* /*env*/, jobject /*obj*/, jlong nativePointer) { \ + return (javatype) YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer)); \ + } \ + \ + static void jni_YGNodeStyleSet##name##JNI( \ + JNIEnv* /*env*/, jobject /*obj*/, jlong nativePointer, javatype value) { \ + YGNodeStyleSet##name( \ + _jlong2YGNodeRef(nativePointer), static_cast(value)); \ + } + +#define YG_NODE_JNI_STYLE_UNIT_PROP(name) \ + static jlong jni_YGNodeStyleGet##name##JNI( \ + JNIEnv* /*env*/, jobject /*obj*/, jlong nativePointer) { \ + return YogaValue::asJavaLong( \ + YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer))); \ } \ \ static void jni_YGNodeStyleSet##name##JNI( \ - JNIEnv* env, jobject obj, jlong nativePointer, javatype value) { \ + JNIEnv* /*env*/, jobject /*obj*/, jlong nativePointer, jfloat value) { \ YGNodeStyleSet##name( \ - _jlong2YGNodeRef(nativePointer), static_cast(value)); \ - } - -#define YG_NODE_JNI_STYLE_UNIT_PROP(name) \ - static jlong jni_YGNodeStyleGet##name##JNI( \ - JNIEnv* env, jobject obj, jlong nativePointer) { \ - return YogaValue::asJavaLong( \ - YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer))); \ - } \ - \ - static void jni_YGNodeStyleSet##name##JNI( \ - JNIEnv* env, jobject obj, jlong nativePointer, jfloat value) { \ - YGNodeStyleSet##name( \ - _jlong2YGNodeRef(nativePointer), static_cast(value)); \ - } \ - \ - static void jni_YGNodeStyleSet##name##PercentJNI( \ - JNIEnv* env, jobject obj, jlong nativePointer, jfloat value) { \ - YGNodeStyleSet##name##Percent( \ - _jlong2YGNodeRef(nativePointer), static_cast(value)); \ + _jlong2YGNodeRef(nativePointer), static_cast(value)); \ + } \ + \ + static void jni_YGNodeStyleSet##name##PercentJNI( \ + JNIEnv* /*env*/, jobject /*obj*/, jlong nativePointer, jfloat value) { \ + YGNodeStyleSet##name##Percent( \ + _jlong2YGNodeRef(nativePointer), static_cast(value)); \ } #define YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(name) \ YG_NODE_JNI_STYLE_UNIT_PROP(name) \ static void jni_YGNodeStyleSet##name##AutoJNI( \ - JNIEnv* env, jobject obj, jlong nativePointer) { \ + JNIEnv* /*env*/, jobject /*obj*/, jlong nativePointer) { \ YGNodeStyleSet##name##Auto(_jlong2YGNodeRef(nativePointer)); \ } -#define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \ - static jlong jni_YGNodeStyleGet##name##JNI( \ - JNIEnv* env, jobject obj, jlong nativePointer, jint edge) { \ - return YogaValue::asJavaLong(YGNodeStyleGet##name( \ - _jlong2YGNodeRef(nativePointer), static_cast(edge))); \ - } \ - \ - static void jni_YGNodeStyleSet##name##JNI( \ - JNIEnv* env, \ - jobject obj, \ - jlong nativePointer, \ - jint edge, \ - jfloat value) { \ - YGNodeStyleSet##name( \ - _jlong2YGNodeRef(nativePointer), \ - static_cast(edge), \ - static_cast(value)); \ - } \ - \ - static void jni_YGNodeStyleSet##name##PercentJNI( \ - JNIEnv* env, \ - jobject obj, \ - jlong nativePointer, \ - jint edge, \ - jfloat value) { \ - YGNodeStyleSet##name##Percent( \ - _jlong2YGNodeRef(nativePointer), \ - static_cast(edge), \ - static_cast(value)); \ +#define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \ + static jlong jni_YGNodeStyleGet##name##JNI( \ + JNIEnv* /*env*/, jobject /*obj*/, jlong nativePointer, jint edge) { \ + return YogaValue::asJavaLong(YGNodeStyleGet##name( \ + _jlong2YGNodeRef(nativePointer), static_cast(edge))); \ + } \ + \ + static void jni_YGNodeStyleSet##name##JNI( \ + JNIEnv* /*env*/, \ + jobject /*obj*/, \ + jlong nativePointer, \ + jint edge, \ + jfloat value) { \ + YGNodeStyleSet##name( \ + _jlong2YGNodeRef(nativePointer), \ + static_cast(edge), \ + static_cast(value)); \ + } \ + \ + static void jni_YGNodeStyleSet##name##PercentJNI( \ + JNIEnv* /*env*/, \ + jobject /*obj*/, \ + jlong nativePointer, \ + jint edge, \ + jfloat value) { \ + YGNodeStyleSet##name##Percent( \ + _jlong2YGNodeRef(nativePointer), \ + static_cast(edge), \ + static_cast(value)); \ } YG_NODE_JNI_STYLE_PROP(jint, YGDirection, Direction); @@ -523,8 +518,8 @@ YG_NODE_JNI_STYLE_UNIT_PROP(MaxHeight); YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(Position); static jlong jni_YGNodeStyleGetMarginJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer, jint edge) { YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer); @@ -536,8 +531,8 @@ static jlong jni_YGNodeStyleGetMarginJNI( } static void jni_YGNodeStyleSetMarginJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer, jint edge, jfloat margin) { @@ -548,8 +543,8 @@ static void jni_YGNodeStyleSetMarginJNI( } static void jni_YGNodeStyleSetMarginPercentJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer, jint edge, jfloat percent) { @@ -560,8 +555,8 @@ static void jni_YGNodeStyleSetMarginPercentJNI( } static void jni_YGNodeStyleSetMarginAutoJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer, jint edge) { YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer); @@ -570,8 +565,8 @@ static void jni_YGNodeStyleSetMarginAutoJNI( } static jlong jni_YGNodeStyleGetPaddingJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer, jint edge) { YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer); @@ -583,8 +578,8 @@ static jlong jni_YGNodeStyleGetPaddingJNI( } static void jni_YGNodeStyleSetPaddingJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer, jint edge, jfloat padding) { @@ -595,8 +590,8 @@ static void jni_YGNodeStyleSetPaddingJNI( } static void jni_YGNodeStyleSetPaddingPercentJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer, jint edge, jfloat percent) { @@ -607,8 +602,8 @@ static void jni_YGNodeStyleSetPaddingPercentJNI( } static jfloat jni_YGNodeStyleGetBorderJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer, jint edge) { YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer); @@ -619,8 +614,8 @@ static jfloat jni_YGNodeStyleGetBorderJNI( } static void jni_YGNodeStyleSetBorderJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer, jint edge, jfloat border) { @@ -674,11 +669,6 @@ static YGSize YGJNIMeasureFunc( return YGSize{*measuredWidth, *measuredHeight}; } else { - Log::log( - node, - YGLogLevelError, - nullptr, - "Java YGNode was GCed during layout calculation\n"); return YGSize{ widthMode == YGMeasureModeUndefined ? 0 : width, heightMode == YGMeasureModeUndefined ? 0 : height, @@ -687,8 +677,8 @@ static YGSize YGJNIMeasureFunc( } static void jni_YGNodeSetHasMeasureFuncJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer, jboolean hasMeasureFunc) { _jlong2YGNodeRef(nativePointer) @@ -714,34 +704,42 @@ static float YGJNIBaselineFunc( } static void jni_YGNodeSetHasBaselineFuncJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer, jboolean hasBaselineFunc) { _jlong2YGNodeRef(nativePointer) ->setBaselineFunc(hasBaselineFunc ? YGJNIBaselineFunc : nullptr); } -static void jni_YGNodePrintJNI(JNIEnv* env, jobject obj, jlong nativePointer) { +static void jni_YGNodePrintJNI( + JNIEnv* /*env*/, + jobject /*obj*/, + jlong nativePointer) { #ifdef DEBUG const YGNodeRef node = _jlong2YGNodeRef(nativePointer); YGNodePrint( node, (YGPrintOptions) (YGPrintOptionsStyle | YGPrintOptionsLayout | YGPrintOptionsChildren)); +#else + (void) nativePointer; #endif } -static jlong jni_YGNodeCloneJNI(JNIEnv* env, jobject obj, jlong nativePointer) { +static jlong jni_YGNodeCloneJNI( + JNIEnv* /*env*/, + jobject /*obj*/, + jlong nativePointer) { auto node = _jlong2YGNodeRef(nativePointer); const YGNodeRef clonedYogaNode = YGNodeClone(node); - clonedYogaNode->setContext(node->getContext()); + YGNodeSetContext(clonedYogaNode, YGNodeGetContext(node)); return reinterpret_cast(clonedYogaNode); } static jfloat jni_YGNodeStyleGetGapJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer, jint gutter) { return (jfloat) YGNodeStyleGetGap( @@ -749,8 +747,8 @@ static jfloat jni_YGNodeStyleGetGapJNI( } static void jni_YGNodeStyleSetGapJNI( - JNIEnv* env, - jobject obj, + JNIEnv* /*env*/, + jobject /*obj*/, jlong nativePointer, jint gutter, jfloat gapLength) { @@ -788,7 +786,7 @@ static JNINativeMethod methods[] = { (void*) jni_YGConfigSetLoggerJNI}, {"jni_YGNodeNewJNI", "()J", (void*) jni_YGNodeNewJNI}, {"jni_YGNodeNewWithConfigJNI", "(J)J", (void*) jni_YGNodeNewWithConfigJNI}, - {"jni_YGNodeFreeJNI", "(J)V", (void*) jni_YGNodeFreeJNI}, + {"jni_YGNodeDeallocateJNI", "(J)V", (void*) jni_YGNodeDeallocateJNI}, {"jni_YGNodeResetJNI", "(J)V", (void*) jni_YGNodeResetJNI}, {"jni_YGNodeInsertChildJNI", "(JJI)V", (void*) jni_YGNodeInsertChildJNI}, {"jni_YGNodeSwapChildJNI", "(JJI)V", (void*) jni_YGNodeSwapChildJNI}, @@ -798,7 +796,9 @@ static JNINativeMethod methods[] = { {"jni_YGNodeIsReferenceBaselineJNI", "(J)Z", (void*) jni_YGNodeIsReferenceBaselineJNI}, - {"jni_YGNodeClearChildrenJNI", "(J)V", (void*) jni_YGNodeClearChildrenJNI}, + {"jni_YGNodeRemoveAllChildrenJNI", + "(J)V", + (void*) jni_YGNodeRemoveAllChildrenJNI}, {"jni_YGNodeRemoveChildJNI", "(JJ)V", (void*) jni_YGNodeRemoveChildJNI}, {"jni_YGNodeCalculateLayoutJNI", "(JFF[J[Lcom/facebook/yoga/YogaNodeJNIBase;)V", diff --git a/packages/react-native/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJTypesVanilla.h b/packages/react-native/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJTypesVanilla.h index 1b4d62dfae49fc..506c304909a37c 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJTypesVanilla.h +++ b/packages/react-native/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJTypesVanilla.h @@ -5,11 +5,13 @@ * LICENSE file in the root directory of this source tree. */ -#include "jni.h" -#include -#include #include +#include + +#include + #include "common.h" +#include "jni.h" class PtrJNodeMapVanilla { std::map ptrsToIdxs_; diff --git a/packages/react-native/ReactAndroid/src/main/jni/first-party/yogajni/jni/corefunctions.cpp b/packages/react-native/ReactAndroid/src/main/jni/first-party/yogajni/jni/corefunctions.cpp index 1f8c3f75c66ed0..bbdcebd323df77 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/first-party/yogajni/jni/corefunctions.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/first-party/yogajni/jni/corefunctions.cpp @@ -56,6 +56,7 @@ JNIEXPORT JNIEnv* getCurrentEnv() { } void logErrorMessageAndDie(const char* message) { + (void) message; VANILLAJNI_LOG_ERROR( "VanillaJni", "Aborting due to error detected in native code: %s", diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/Binding.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/Binding.cpp index 08d1fa767eeee3..1a0dbb9afd5572 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/Binding.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/Binding.cpp @@ -131,8 +131,7 @@ void Binding::startSurface( surfaceHandlerRegistry_.emplace(surfaceId, std::move(surfaceHandler)); } - auto &mountingManager = - verifyMountingManager("FabricUIManagerBinding::startSurface"); + auto *mountingManager = getMountingManager("startSurface"); if (!mountingManager) { return; } @@ -202,8 +201,7 @@ void Binding::startSurfaceWithConstraints( surfaceHandlerRegistry_.emplace(surfaceId, std::move(surfaceHandler)); } - auto &mountingManager = verifyMountingManager( - "FabricUIManagerBinding::startSurfaceWithConstraints"); + auto *mountingManager = getMountingManager("startSurfaceWithConstraints"); if (!mountingManager) { return; } @@ -255,8 +253,7 @@ void Binding::stopSurface(jint surfaceId) { scheduler->unregisterSurface(surfaceHandler); } - auto &mountingManager = - verifyMountingManager("FabricUIManagerBinding::stopSurface"); + auto *mountingManager = getMountingManager("stopSurface"); if (!mountingManager) { return; } @@ -272,8 +269,7 @@ void Binding::registerSurface(SurfaceHandlerBinding *surfaceHandlerBinding) { } scheduler->registerSurface(surfaceHandler); - auto &mountingManager = - verifyMountingManager("FabricUIManagerBinding::registerSurface"); + auto *mountingManager = getMountingManager("registerSurface"); if (!mountingManager) { return; } @@ -289,8 +285,7 @@ void Binding::unregisterSurface(SurfaceHandlerBinding *surfaceHandlerBinding) { } scheduler->unregisterSurface(surfaceHandler); - auto &mountingManager = - verifyMountingManager("FabricUIManagerBinding::unregisterSurface"); + auto *mountingManager = getMountingManager("unregisterSurface"); if (!mountingManager) { return; } @@ -373,7 +368,7 @@ void Binding::installFabricUIManager( auto globalJavaUiManager = make_global(javaUIManager); mountingManager_ = - std::make_shared(config, globalJavaUiManager); + std::make_unique(config, globalJavaUiManager); ContextContainer::Shared contextContainer = std::make_shared(); @@ -421,8 +416,6 @@ void Binding::installFabricUIManager( "CalculateTransformedFramesEnabled", getFeatureFlagValue("calculateTransformedFramesEnabled")); - CoreFeatures::cacheLastTextMeasurement = - getFeatureFlagValue("enableTextMeasureCachePerShadowNode"); CoreFeatures::enablePropIteratorSetter = getFeatureFlagValue("enableCppPropsIteratorSetter"); CoreFeatures::useNativeState = getFeatureFlagValue("useNativeState"); @@ -469,19 +462,18 @@ void Binding::uninstallFabricUIManager() { reactNativeConfig_ = nullptr; } -const std::shared_ptr &Binding::verifyMountingManager( - const char *locationHint) { +FabricMountingManager *Binding::getMountingManager(const char *locationHint) { std::shared_lock lock(installMutex_); if (!mountingManager_) { - LOG(ERROR) << locationHint << " mounting manager disappeared."; + LOG(ERROR) << "FabricMountingManager::" << locationHint + << " mounting manager disappeared"; } - return mountingManager_; + return mountingManager_.get(); } void Binding::schedulerDidFinishTransaction( const MountingCoordinator::Shared &mountingCoordinator) { - auto &mountingManager = - verifyMountingManager("Binding::schedulerDidFinishTransaction"); + auto *mountingManager = getMountingManager("schedulerDidFinishTransaction"); if (!mountingManager) { return; } @@ -500,27 +492,18 @@ void Binding::schedulerDidRequestPreliminaryViewAllocation( return; } - preallocateView(surfaceId, shadowNode); -} - -void Binding::preallocateView( - SurfaceId surfaceId, - ShadowNode const &shadowNode) { - auto name = std::string(shadowNode.getComponentName()); - auto shadowView = ShadowView(shadowNode); - auto &mountingManager = verifyMountingManager("Binding::preallocateView"); + auto *mountingManager = getMountingManager("preallocateView"); if (!mountingManager) { return; } - mountingManager->preallocateShadowView(surfaceId, shadowView); + mountingManager->preallocateShadowView(surfaceId, ShadowView(shadowNode)); } void Binding::schedulerDidDispatchCommand( const ShadowView &shadowView, std::string const &commandName, folly::dynamic const &args) { - auto &mountingManager = - verifyMountingManager("Binding::schedulerDidDispatchCommand"); + auto *mountingManager = getMountingManager("schedulerDidDispatchCommand"); if (!mountingManager) { return; } @@ -530,8 +513,8 @@ void Binding::schedulerDidDispatchCommand( void Binding::schedulerDidSendAccessibilityEvent( const ShadowView &shadowView, std::string const &eventType) { - auto &mountingManager = - verifyMountingManager("Binding::schedulerDidSendAccessibilityEvent"); + auto *mountingManager = + getMountingManager("schedulerDidSendAccessibilityEvent"); if (!mountingManager) { return; } @@ -542,8 +525,7 @@ void Binding::schedulerDidSetIsJSResponder( ShadowView const &shadowView, bool isJSResponder, bool blockNativeResponder) { - auto &mountingManager = - verifyMountingManager("Binding::schedulerDidSetIsJSResponder"); + auto *mountingManager = getMountingManager("schedulerDidSetIsJSResponder"); if (!mountingManager) { return; } @@ -552,7 +534,7 @@ void Binding::schedulerDidSetIsJSResponder( } void Binding::onAnimationStarted() { - auto &mountingManager = verifyMountingManager("Binding::onAnimationStarted"); + auto *mountingManager = getMountingManager("onAnimationStarted"); if (!mountingManager) { return; } @@ -560,7 +542,7 @@ void Binding::onAnimationStarted() { } void Binding::onAllAnimationsComplete() { - auto &mountingManager = verifyMountingManager("Binding::onAnimationComplete"); + auto *mountingManager = getMountingManager("onAnimationComplete"); if (!mountingManager) { return; } diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/Binding.h b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/Binding.h index a1f443b1bcaa5b..8ce55648ca4551 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/Binding.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/Binding.h @@ -116,8 +116,6 @@ class Binding : public jni::HybridClass, bool isJSResponder, bool blockNativeResponder) override; - void preallocateView(SurfaceId surfaceId, ShadowNode const &shadowNode); - void setPixelDensity(float pointScaleFactor); void driveCxxAnimations(); @@ -126,11 +124,10 @@ class Binding : public jni::HybridClass, // Private member variables std::shared_mutex installMutex_; - std::shared_ptr mountingManager_; + std::unique_ptr mountingManager_; std::shared_ptr scheduler_; - const std::shared_ptr &verifyMountingManager( - const char *locationHint); + FabricMountingManager *getMountingManager(const char *locationHint); // LayoutAnimations void onAnimationStarted() override; diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp index 0b1d3acb99ce3c..cde2d633044c45 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp @@ -118,8 +118,7 @@ static inline void computeBufferSizes( std::vector &cppUpdatePaddingMountItems, std::vector &cppUpdateLayoutMountItems, std::vector &cppUpdateOverflowInsetMountItems, - std::vector &cppUpdateEventEmitterMountItems, - ShadowViewMutationList &cppViewMutations) { + std::vector &cppUpdateEventEmitterMountItems) { CppMountItem::Type lastType = CppMountItem::Type::Undefined; int numSameType = 0; for (auto const &mountItem : cppCommonMountItems) { @@ -178,11 +177,6 @@ static inline void computeBufferSizes( cppDeleteMountItems.size(), batchMountItemIntsSize, batchMountItemObjectsSize); - - if (cppViewMutations.size() > 0) { - batchMountItemIntsSize++; - batchMountItemObjectsSize++; - } } static inline void writeIntBufferTypePreamble( @@ -278,7 +272,7 @@ void FabricMountingManager::executeMount( std::vector cppUpdateLayoutMountItems; std::vector cppUpdateOverflowInsetMountItems; std::vector cppUpdateEventEmitterMountItems; - auto cppViewMutations = ShadowViewMutationList(); + { std::lock_guard allocatedViewsLock(allocatedViewsMutex_); @@ -497,8 +491,7 @@ void FabricMountingManager::executeMount( cppUpdatePaddingMountItems, cppUpdateLayoutMountItems, cppUpdateOverflowInsetMountItems, - cppUpdateEventEmitterMountItems, - cppViewMutations); + cppUpdateEventEmitterMountItems); static auto createMountItemsIntBufferBatchContainer = JFabricUIManager::javaClassStatic() diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.h b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.h index a4386d3432e5b5..de75d0d76b31db 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.h @@ -25,6 +25,7 @@ class FabricMountingManager final { FabricMountingManager( std::shared_ptr &config, jni::global_ref &javaUIManager); + FabricMountingManager(const FabricMountingManager &) = delete; void onSurfaceStart(SurfaceId surfaceId); diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/uimanager/ComponentNameResolverManager.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/uimanager/ComponentNameResolverManager.cpp index 15731e44c44087..909b1d8c720b38 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/uimanager/ComponentNameResolverManager.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/uimanager/ComponentNameResolverManager.cpp @@ -67,8 +67,7 @@ void ComponentNameResolverManager::installJSIBindings() { return thizz->componentNames_.find(name) != thizz->componentNames_.end(); }; - react::NativeComponentRegistryBinding::install( - runtime, std::move(viewManagerProvider)); + bindHasComponentProvider(runtime, std::move(viewManagerProvider)); }); } diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-af/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-af/strings.xml index 24e1b69fe6b4ef..be441f6e6398ad 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-af/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-af/strings.xml @@ -3,4 +3,6 @@ + Toestelspesifieke ontwikkelaarkieslys vir reaksies (%1$s) + Wys %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ar/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ar/strings.xml index 9ee5b1218296dd..39018d371fe9f6 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ar/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ar/strings.xml @@ -3,4 +3,6 @@ + التفاعل مع قائمة التطوير الأصلي (%1$s) + تشغيل %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-bg/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-bg/strings.xml index 09b7b31c671dab..88472622ff9dfa 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-bg/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-bg/strings.xml @@ -3,4 +3,5 @@ + Управление на %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-bn/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-bn/strings.xml index b5d516623ef92f..0f2812a24ef0f7 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-bn/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-bn/strings.xml @@ -3,4 +3,6 @@ + রিয়েকশন নেটিভ ডেভেলপার মেনু (%1$s) + %1$s চলছে diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-cs/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-cs/strings.xml index b556b85f3bc390..ca0aeddeb5cbdf 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-cs/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-cs/strings.xml @@ -3,4 +3,6 @@ + Nabídka React Native Dev (%1$s) + Spuštěno: %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-da/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-da/strings.xml index 1fd6723b3bae1f..0656358b2b90bd 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-da/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-da/strings.xml @@ -3,4 +3,5 @@ + Kører %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-el/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-el/strings.xml index 0604fa12ac1e99..e619a3f967bf8c 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-el/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-el/strings.xml @@ -3,4 +3,5 @@ + Προβάλλεται: %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-en-rGB/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-en-rGB/strings.xml index 49147780ee63b5..63bb3b42ae9d72 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-en-rGB/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-en-rGB/strings.xml @@ -3,4 +3,5 @@ + React native dev menu (%1$s) diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-es-rES/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-es-rES/strings.xml index 025a080a25a9f8..4aba889d969b0e 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-es-rES/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-es-rES/strings.xml @@ -3,4 +3,6 @@ + Menú del desarrollador de React Native (%1$s) + Se está ejecutando %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-es/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-es/strings.xml index bfb1514177a8c5..084c9b7f192c3c 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-es/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-es/strings.xml @@ -3,4 +3,6 @@ + Menú de desarrollador nativo de reacción (%1$s) + Se está ejecutando %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-et/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-et/strings.xml index e17476d14d8823..ef1ea85b10f17c 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-et/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-et/strings.xml @@ -3,4 +3,6 @@ + React Native’i arendaja menüü (%1$s) + Töötab %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-fa/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-fa/strings.xml index 72270d97102a7c..9717fb6ab20f78 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-fa/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-fa/strings.xml @@ -3,4 +3,5 @@ + اجرای %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-fb-rLS/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-fb-rLS/strings.xml index d531cc7909261f..448b9c7e8f40e2 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-fb-rLS/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-fb-rLS/strings.xml @@ -3,4 +3,6 @@ + React Native Dev Menu (%1$s)\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@ + Running %1$s\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@ diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-fb/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-fb/strings.xml index aee984ff543edb..05438a4eb22e30 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-fb/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-fb/strings.xml @@ -3,4 +3,6 @@ + [React Native Dev Menu (%1$s)#f560753940a8856cdc2de8717c0295df:1] + [Running %1$s#c566f94d6bbe163799a3235b4b55f9d1:1] diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-fi/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-fi/strings.xml index 7c49d51816ed44..9fdab18be3958c 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-fi/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-fi/strings.xml @@ -3,4 +3,6 @@ + Reagointien natiivikehittäjävalikko (%1$s) + Näytetään %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-fr-rCA/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-fr-rCA/strings.xml index d5fe3fb4a959d0..12dae28ef0c509 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-fr-rCA/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-fr-rCA/strings.xml @@ -3,4 +3,5 @@ + %1$s en cours diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-fr/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-fr/strings.xml index 64b98fc6a925f6..f81cf0999513b5 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-fr/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-fr/strings.xml @@ -3,4 +3,5 @@ + En cours %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-gu/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-gu/strings.xml index 2a2946b617eb63..139d0c2fe58a07 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-gu/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-gu/strings.xml @@ -3,4 +3,6 @@ + મૂળ ડેવ મેનૂ (%1$s) પર પ્રતિક્રિયા આપો + %1$s ચાલુ છે diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ha/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ha/strings.xml index 084b1b6aac0de0..5fda75f3b55d41 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ha/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ha/strings.xml @@ -3,4 +3,6 @@ + Mazaɓar Martanin Native Dev (%1$s) + Gudanar da %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-hi/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-hi/strings.xml index 3bca368f01586b..ba20ef7f4979fe 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-hi/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-hi/strings.xml @@ -3,4 +3,6 @@ + रिएक्शन नेटिव डेवलपर मेनू (%1$s) + %1$s चला रहे हैं diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-hr/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-hr/strings.xml index 97250a3e1f6a4c..e63ea44730384f 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-hr/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-hr/strings.xml @@ -3,4 +3,6 @@ + React native dev izbornik (%1$s) + Pokretanje %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-hu/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-hu/strings.xml index 7c28e052110cd6..12a1941326e363 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-hu/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-hu/strings.xml @@ -3,4 +3,6 @@ + React Native-fejlesztői menü – (%1$s) + Futó %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-in/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-in/strings.xml index 6d32bd7238156f..46a9c671951166 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-in/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-in/strings.xml @@ -3,4 +3,6 @@ + Menanggapi Menu Dev Asli (%1$s) + Menjalankan %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-it/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-it/strings.xml index 89dcf449cfb41d..90c67bb8e04b5d 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-it/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-it/strings.xml @@ -3,4 +3,6 @@ + Menu sviluppatori React Native (%1$s) + %1$s in esecuzione diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-iw/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-iw/strings.xml index dcca08e175b5d0..db5d49d33dc55e 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-iw/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-iw/strings.xml @@ -3,4 +3,6 @@ + תפריט מקומי למפתחים (%1$s) + %1$s בפעילות diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ja/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ja/strings.xml index 437a25fe2bea8f..7650e689bee8e8 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ja/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ja/strings.xml @@ -3,4 +3,6 @@ + React Native開発メニュー(%1$s) + %1$sの実行中 diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-jv/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-jv/strings.xml index 5bc93b9a564110..700a52183bc544 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-jv/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-jv/strings.xml @@ -3,4 +3,6 @@ + Menu React Native Dev (%1$s) + Lagi tayang %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ka/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ka/strings.xml index 1c2a251fabd607..4b39c6aace90e5 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ka/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ka/strings.xml @@ -3,4 +3,5 @@ + React Native-ის დეველოპერთა მენიუ (%1$s) diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-km/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-km/strings.xml index d6ed5fadf8cf0f..4d3512a5a0f517 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-km/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-km/strings.xml @@ -3,4 +3,6 @@ + ប្រតិកម្ម​ម៉ឺនុយ​​អភិវឌ្ឍដើម (%1$s) + ដំណើរការ %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-kn/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-kn/strings.xml index b4a93b39ff0be2..2e276ebb0b2adf 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-kn/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-kn/strings.xml @@ -3,4 +3,6 @@ + ಸ್ಥಳೀಯ ದೇವ್ ಮೆನುವನ್ನು ಪ್ರತಿಕ್ರಿಯಿಸಿ (%1$s) + %1$s ರನ್ ಆಗುತ್ತಿದೆ diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ko/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ko/strings.xml index ba310011f0d554..33a74608b61423 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ko/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ko/strings.xml @@ -3,4 +3,6 @@ + React Native 개발자 메뉴 (%1$s) + %1$s 실행 중 diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-lt/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-lt/strings.xml index c3177bbf23299d..285da215ee4f94 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-lt/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-lt/strings.xml @@ -3,4 +3,6 @@ + Reagavimo savasis kūrėjo meniu „(%1$s)“ + Rodoma „%1$s“ diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-mk/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-mk/strings.xml index 1c76e1bb07c64e..f9f5f25ffb8d46 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-mk/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-mk/strings.xml @@ -3,4 +3,6 @@ + Реакција на нативно програмерско мени (%1$s) + Се извршува %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ml/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ml/strings.xml index 5d568f33232987..4bb7b371717d46 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ml/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ml/strings.xml @@ -3,4 +3,6 @@ + പ്രതികരണ നേറ്റീവ് ഡെവ മെനു (%1$s) + റൺ ചെയ്യുന്നു %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-mr/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-mr/strings.xml index ad239221c0e924..9ac80326166d9b 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-mr/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-mr/strings.xml @@ -3,4 +3,6 @@ + मुळ डीईव्ही मेनू प्रतिक्रिया द्या (%1$s) + प्रसारित होत आहे %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ms/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ms/strings.xml index 443eca7a57e1f8..0134ed075df3f6 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ms/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ms/strings.xml @@ -3,4 +3,6 @@ + Menu Pembangun Asli Bereaksi (%1$s) + Sedang berjalan %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-my/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-my/strings.xml index 65abfdbf7bd192..06efd24185cb8a 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-my/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-my/strings.xml @@ -3,4 +3,6 @@ + Native Dev မီနူး (%1$s) ကို တုံ့ပြန်ရန် + %1$s ကို ပြသနေပါတယ် diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-nb/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-nb/strings.xml index 873742c208ac05..33f899f194932b 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-nb/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-nb/strings.xml @@ -3,4 +3,6 @@ + React Native-utviklermenyen (%1$s) + Kjører %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-nl/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-nl/strings.xml index 75355cf16bd979..4e674738996e75 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-nl/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-nl/strings.xml @@ -3,4 +3,6 @@ + Native ontwikkelaarsmenu (%1$s) opnieuw activeren + %1$s actief diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-pa/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-pa/strings.xml index ea45e686429267..4ce2dfcd6a392f 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-pa/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-pa/strings.xml @@ -3,4 +3,6 @@ + ਨੇਟਿਵ ਡਿਵੈ ਮੀਨੂ (%1$s) \'ਤੇ ਪ੍ਰਤੀਕਿਰਿਆ ਦਿਓ + %1$s ਚੱਲ ਰਿਹਾ ਹੈ diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-pl/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-pl/strings.xml index 4f53d3ec705bb8..71d4ae55203e63 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-pl/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-pl/strings.xml @@ -3,4 +3,6 @@ + Menu dewelopera React Native (%1$s) + Wyświetlanie: %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-pt-rPT/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-pt-rPT/strings.xml index a0d4564f7f0932..42aee5be861113 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-pt-rPT/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-pt-rPT/strings.xml @@ -3,4 +3,6 @@ + Menu de desenvolvimento do React Native (%1$s) + A apresentar %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-pt/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-pt/strings.xml index 3a24466f7006cd..6db39e0de3e36d 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-pt/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-pt/strings.xml @@ -3,4 +3,6 @@ + Menu de desenvolvedor de reações nativas (%1$s) + %1$s em veiculação diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ro/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ro/strings.xml index 445f1af124553e..4f8c3b4aa4bd00 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ro/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ro/strings.xml @@ -3,4 +3,6 @@ + Meniu dezvoltare React Native (%1$s) + %1$s în derulare diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ru/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ru/strings.xml index 1105ec010ea037..fac0a47b8c4cb3 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ru/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ru/strings.xml @@ -3,4 +3,6 @@ + Меню разработчика React Native (%1$s) + Текущий показ %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-si/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-si/strings.xml index 2153d88a0669fb..87265ae2dcf341 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-si/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-si/strings.xml @@ -3,4 +3,6 @@ + (%1$s) React Native Dev මෙනුව + %1$s ප්‍රචාරය කරමින් පවතී diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sk/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sk/strings.xml index 2d1768d211d54d..79b4fef8e92b1c 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sk/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sk/strings.xml @@ -3,4 +3,6 @@ + Natívna vývojárska ponuka reakcie (%1$s) + Spustené: %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sl/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sl/strings.xml index a8d2a680928b58..55b867432646c9 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sl/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sl/strings.xml @@ -3,4 +3,5 @@ + V teku %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sq/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sq/strings.xml index a225539656b409..96e5af862b88ab 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sq/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sq/strings.xml @@ -3,4 +3,5 @@ + Menyja e zhvilluesit e React Native (%1$s) diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sr/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sr/strings.xml index 47782d7cf1000e..8ee23f06dd336e 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sr/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sr/strings.xml @@ -3,4 +3,6 @@ + React Native мени за програмере: (%1$s) + Покренуто: %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sv/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sv/strings.xml index 2eed9288127946..92892f1a2c2fbd 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sv/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sv/strings.xml @@ -3,4 +3,5 @@ + Kör %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sw/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sw/strings.xml index 6dea5b85bb9a65..a8c044f2fa07a1 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sw/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sw/strings.xml @@ -3,4 +3,5 @@ + Linaendeshwa %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ta/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ta/strings.xml index f8bfd1c350e5e0..7c8fd6d4c97ccf 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ta/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ta/strings.xml @@ -3,4 +3,6 @@ + ரியாக்ட் நேட்டிவ் டேவ் மெனு (%1$s) + இயங்குகிறது %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-te/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-te/strings.xml index 241b213130fe0a..1d82e8321cf8f5 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-te/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-te/strings.xml @@ -3,4 +3,6 @@ + స్థానిక డెవలపర్ మెనూ (%1$s)పై ప్రతిస్పందించండి + %1$s ప్రదర్శించబడుతోంది diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-th/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-th/strings.xml index a4206503879525..07c8dc11c82f79 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-th/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-th/strings.xml @@ -3,4 +3,6 @@ + แสดงความรู้สึกต่อเมนูผู้พัฒนาแบบเนทีฟ (%1$s) + กำลังเผยแพร่ %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-tl/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-tl/strings.xml index dadacb703c930c..d6fcf1a1b5bc7c 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-tl/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-tl/strings.xml @@ -3,4 +3,5 @@ + Tumatakbong %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-tr/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-tr/strings.xml index 755cf862c5eb9e..715bbfd559c3bf 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-tr/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-tr/strings.xml @@ -3,4 +3,5 @@ + %1$s çalıştırıyor diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-uk/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-uk/strings.xml index bf3cc46d1cb490..beb6810c29f03b 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-uk/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-uk/strings.xml @@ -3,4 +3,6 @@ + Меню розробника React Native «(%1$s)» + Поточний показ «%1$s» diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ur/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ur/strings.xml index 6d76f390ea068a..497b0851e2c147 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ur/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-ur/strings.xml @@ -3,4 +3,5 @@ + %1$s چل رہا ہے diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-vi/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-vi/strings.xml index 706622a3be9832..e9d23c6df6ddf4 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-vi/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-vi/strings.xml @@ -3,4 +3,6 @@ + Menu phát triển React Native (%1$s) + Đang chạy %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-zh-rCN/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-zh-rCN/strings.xml index c50c06c1a71bf2..f613227f53490b 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-zh-rCN/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-zh-rCN/strings.xml @@ -3,4 +3,6 @@ + React Native 开发者菜单(%1$s) + 正在运行%1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-zh-rHK/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-zh-rHK/strings.xml index 067865f00e1e61..6eaf7cdea6d5cd 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-zh-rHK/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-zh-rHK/strings.xml @@ -3,4 +3,6 @@ + React Native 開發人員選單(%1$s) + 正在執行%1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-zh-rTW/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-zh-rTW/strings.xml index c56baa9ccc27f0..57cfc00727ce94 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-zh-rTW/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-zh-rTW/strings.xml @@ -3,4 +3,6 @@ + React Native 開發人員功能表(%1$s) + 正在執行%1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values/strings.xml index 1b9c4ffefa28e4..6149af00047c69 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values/strings.xml @@ -1,5 +1,5 @@ - + Reload Failed to load bundle. Try restarting the bundler or reconnecting your device. Change Bundle Location @@ -26,4 +26,6 @@ Loading from %1$s… Disable Sampling Profiler Enable Sampling Profiler + React Native Dev Menu (%1$s) + Running %1$s diff --git a/packages/react-native/ReactAndroid/src/main/res/views/uimanager/values/ids.xml b/packages/react-native/ReactAndroid/src/main/res/views/uimanager/values/ids.xml index 6324b85af44673..d2928f810dfb90 100644 --- a/packages/react-native/ReactAndroid/src/main/res/views/uimanager/values/ids.xml +++ b/packages/react-native/ReactAndroid/src/main/res/views/uimanager/values/ids.xml @@ -44,4 +44,7 @@ + + + diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/ReactActivityDelegateTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/ReactActivityDelegateTest.kt index dcf9da8ed02ee3..2912a9c193645b 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/ReactActivityDelegateTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/ReactActivityDelegateTest.kt @@ -7,6 +7,7 @@ package com.facebook.react +import android.app.Activity import android.os.Bundle import org.junit.Assert.* import org.junit.Test @@ -16,10 +17,12 @@ import org.robolectric.RobolectricTestRunner @RunWith(RobolectricTestRunner::class) class ReactActivityDelegateTest { + val nullDelegate: Activity? = null + @Test fun delegateWithFabricEnabled_populatesInitialPropsCorrectly() { val delegate = - object : ReactActivityDelegate(null, "test-delegate") { + object : ReactActivityDelegate(nullDelegate, "test-delegate") { override fun isFabricEnabled() = true public val inspectLaunchOptions: Bundle? get() = composeLaunchOptions() @@ -33,7 +36,7 @@ class ReactActivityDelegateTest { @Test fun delegateWithoutFabricEnabled_hasNullInitialProperties() { val delegate = - object : ReactActivityDelegate(null, "test-delegate") { + object : ReactActivityDelegate(nullDelegate, "test-delegate") { override fun isFabricEnabled() = false public val inspectLaunchOptions: Bundle? get() = composeLaunchOptions() @@ -45,7 +48,7 @@ class ReactActivityDelegateTest { @Test fun delegateWithFabricEnabled_composesInitialPropertiesCorrectly() { val delegate = - object : ReactActivityDelegate(null, "test-delegate") { + object : ReactActivityDelegate(nullDelegate, "test-delegate") { override fun isFabricEnabled() = true override fun getLaunchOptions(): Bundle = Bundle().apply { putString("test-property", "test-value") } diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/RootViewTest.java b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/RootViewTest.java deleted file mode 100644 index 3346b5205526e8..00000000000000 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/RootViewTest.java +++ /dev/null @@ -1,252 +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. - */ - -package com.facebook.react; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.graphics.Rect; -import android.view.MotionEvent; -import com.facebook.react.bridge.Arguments; -import com.facebook.react.bridge.CatalystInstance; -import com.facebook.react.bridge.JavaOnlyArray; -import com.facebook.react.bridge.JavaOnlyMap; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContext; -import com.facebook.react.bridge.ReactTestHelper; -import com.facebook.react.bridge.WritableArray; -import com.facebook.react.bridge.WritableMap; -import com.facebook.react.common.SystemClock; -import com.facebook.react.uimanager.DisplayMetricsHolder; -import com.facebook.react.uimanager.UIManagerModule; -import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.EventDispatcher; -import com.facebook.react.uimanager.events.RCTEventEmitter; -import java.util.Date; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.rule.PowerMockRule; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; - -@PrepareForTest({Arguments.class, SystemClock.class}) -@RunWith(RobolectricTestRunner.class) -@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "androidx.*", "android.*"}) -public class RootViewTest { - - @Rule public PowerMockRule rule = new PowerMockRule(); - - private ReactContext mReactContext; - private CatalystInstance mCatalystInstanceMock; - - @Before - public void setUp() { - final long ts = SystemClock.uptimeMillis(); - PowerMockito.mockStatic(Arguments.class); - PowerMockito.when(Arguments.createArray()) - .thenAnswer( - new Answer() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - return new JavaOnlyArray(); - } - }); - PowerMockito.when(Arguments.createMap()) - .thenAnswer( - new Answer() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - return new JavaOnlyMap(); - } - }); - PowerMockito.mockStatic(SystemClock.class); - PowerMockito.when(SystemClock.uptimeMillis()) - .thenAnswer( - new Answer() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - return ts; - } - }); - - mCatalystInstanceMock = ReactTestHelper.createMockCatalystInstance(); - mReactContext = spy(new ReactApplicationContext(RuntimeEnvironment.application)); - mReactContext.initializeWithInstance(mCatalystInstanceMock); - DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(mReactContext); - - UIManagerModule uiManagerModuleMock = mock(UIManagerModule.class); - when(mCatalystInstanceMock.getNativeModule(UIManagerModule.class)) - .thenReturn(uiManagerModuleMock); - } - - @Test - public void testTouchEmitter() { - ReactInstanceManager instanceManager = mock(ReactInstanceManager.class); - when(instanceManager.getCurrentReactContext()).thenReturn(mReactContext); - - UIManagerModule uiManager = mock(UIManagerModule.class); - EventDispatcher eventDispatcher = mock(EventDispatcher.class); - RCTEventEmitter eventEmitterModuleMock = mock(RCTEventEmitter.class); - when(mCatalystInstanceMock.getNativeModule(UIManagerModule.class)).thenReturn(uiManager); - when(uiManager.getEventDispatcher()).thenReturn(eventDispatcher); - - int rootViewId = 7; - - ReactRootView rootView = new ReactRootView(mReactContext); - rootView.setId(rootViewId); - rootView.setRootViewTag(rootViewId); - rootView.startReactApplication(instanceManager, ""); - rootView.simulateAttachForTesting(); - - long ts = SystemClock.currentTimeMillis(); - - // Test ACTION_DOWN event - rootView.onTouchEvent(MotionEvent.obtain(100, ts, MotionEvent.ACTION_DOWN, 0, 0, 0)); - - ArgumentCaptor downEventCaptor = ArgumentCaptor.forClass(Event.class); - verify(eventDispatcher).dispatchEvent(downEventCaptor.capture()); - verifyNoMoreInteractions(eventDispatcher); - - downEventCaptor.getValue().dispatch(eventEmitterModuleMock); - - ArgumentCaptor downActionTouchesArgCaptor = - ArgumentCaptor.forClass(JavaOnlyArray.class); - verify(eventEmitterModuleMock) - .receiveTouches( - eq("topTouchStart"), downActionTouchesArgCaptor.capture(), any(JavaOnlyArray.class)); - verifyNoMoreInteractions(eventEmitterModuleMock); - - assertThat(downActionTouchesArgCaptor.getValue().size()).isEqualTo(1); - assertThat(downActionTouchesArgCaptor.getValue().getMap(0)) - .isEqualTo( - JavaOnlyMap.of( - "pageX", - 0., - "pageY", - 0., - "locationX", - 0., - "locationY", - 0., - "target", - rootViewId, - "timestamp", - (double) ts, - "identifier", - 0., - "targetSurface", - -1)); - - // Test ACTION_UP event - reset(eventEmitterModuleMock, eventDispatcher); - - ArgumentCaptor upEventCaptor = ArgumentCaptor.forClass(Event.class); - ArgumentCaptor upActionTouchesArgCaptor = - ArgumentCaptor.forClass(JavaOnlyArray.class); - - rootView.onTouchEvent(MotionEvent.obtain(50, ts, MotionEvent.ACTION_UP, 0, 0, 0)); - verify(eventDispatcher).dispatchEvent(upEventCaptor.capture()); - verifyNoMoreInteractions(eventDispatcher); - - upEventCaptor.getValue().dispatch(eventEmitterModuleMock); - verify(eventEmitterModuleMock) - .receiveTouches( - eq("topTouchEnd"), upActionTouchesArgCaptor.capture(), any(WritableArray.class)); - verifyNoMoreInteractions(eventEmitterModuleMock); - - assertThat(upActionTouchesArgCaptor.getValue().size()).isEqualTo(1); - assertThat(upActionTouchesArgCaptor.getValue().getMap(0)) - .isEqualTo( - JavaOnlyMap.of( - "pageX", - 0., - "pageY", - 0., - "locationX", - 0., - "locationY", - 0., - "target", - rootViewId, - "timestamp", - (double) ts, - "identifier", - 0., - "targetSurface", - -1)); - - // Test other action - reset(eventDispatcher); - rootView.onTouchEvent( - MotionEvent.obtain(50, new Date().getTime(), MotionEvent.ACTION_HOVER_MOVE, 0, 0, 0)); - verifyNoMoreInteractions(eventDispatcher); - } - - @Test - public void testRemountApplication() { - ReactInstanceManager instanceManager = mock(ReactInstanceManager.class); - - ReactRootView rootView = new ReactRootView(mReactContext); - - rootView.startReactApplication(instanceManager, ""); - rootView.unmountReactApplication(); - rootView.startReactApplication(instanceManager, ""); - } - - @Test - public void testCheckForKeyboardEvents() { - ReactInstanceManager instanceManager = mock(ReactInstanceManager.class); - - when(instanceManager.getCurrentReactContext()).thenReturn(mReactContext); - ReactRootView rootView = - new ReactRootView(mReactContext) { - @Override - public void getWindowVisibleDisplayFrame(Rect outRect) { - if (outRect.bottom == 0) { - outRect.bottom += 100; - outRect.right += 370; - } else { - outRect.bottom += 370; - } - } - }; - - rootView.startReactApplication(instanceManager, ""); - rootView.simulateCheckForKeyboardForTesting(); - - WritableMap params = Arguments.createMap(); - WritableMap endCoordinates = Arguments.createMap(); - double screenHeight = 470.0; - double keyboardHeight = 100.0; - params.putDouble("duration", 0.0); - endCoordinates.putDouble("width", screenHeight - keyboardHeight); - endCoordinates.putDouble("screenX", 0.0); - endCoordinates.putDouble("height", screenHeight - keyboardHeight); - endCoordinates.putDouble("screenY", keyboardHeight); - params.putMap("endCoordinates", endCoordinates); - params.putString("easing", "keyboard"); - - verify(mReactContext, Mockito.times(1)).emitDeviceEvent("keyboardDidShow", params); - } -} diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/RootViewTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/RootViewTest.kt new file mode 100644 index 00000000000000..9be2b225b03b3c --- /dev/null +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/RootViewTest.kt @@ -0,0 +1,224 @@ +/* + * 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. + */ + +package com.facebook.react + +import android.app.Activity +import android.graphics.Insets +import android.graphics.Rect +import android.view.MotionEvent +import android.view.WindowInsets +import com.facebook.react.bridge.Arguments +import com.facebook.react.bridge.CatalystInstance +import com.facebook.react.bridge.JavaOnlyArray +import com.facebook.react.bridge.JavaOnlyMap +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.bridge.ReactContext +import com.facebook.react.bridge.ReactTestHelper +import com.facebook.react.bridge.WritableArray +import com.facebook.react.common.SystemClock +import com.facebook.react.uimanager.DisplayMetricsHolder +import com.facebook.react.uimanager.UIManagerModule +import com.facebook.react.uimanager.events.Event +import com.facebook.react.uimanager.events.EventDispatcher +import com.facebook.react.uimanager.events.RCTEventEmitter +import java.util.Date +import org.assertj.core.api.Assertions.* +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor +import org.mockito.ArgumentMatchers +import org.mockito.Mockito.* +import org.powermock.api.mockito.PowerMockito.mockStatic +import org.powermock.api.mockito.PowerMockito.`when` as whenever +import org.powermock.core.classloader.annotations.PowerMockIgnore +import org.powermock.core.classloader.annotations.PrepareForTest +import org.powermock.modules.junit4.rule.PowerMockRule +import org.robolectric.Robolectric +import org.robolectric.RobolectricTestRunner +import org.robolectric.RuntimeEnvironment + +@PrepareForTest(Arguments::class, SystemClock::class) +@RunWith(RobolectricTestRunner::class) +@PowerMockIgnore("org.mockito.*", "org.robolectric.*", "androidx.*", "android.*") +class RootViewTest { + @get:Rule var rule = PowerMockRule() + + private lateinit var reactContext: ReactContext + private lateinit var catalystInstanceMock: CatalystInstance + + @Before + fun setUp() { + val ts = SystemClock.uptimeMillis() + mockStatic(SystemClock::class.java) + mockStatic(Arguments::class.java) + whenever(Arguments.createArray()).thenAnswer { JavaOnlyArray() } + whenever(Arguments.createMap()).thenAnswer { JavaOnlyMap() } + whenever(SystemClock.uptimeMillis()).thenAnswer { ts } + + catalystInstanceMock = ReactTestHelper.createMockCatalystInstance() + reactContext = spy(ReactApplicationContext(RuntimeEnvironment.application)) + reactContext.initializeWithInstance(catalystInstanceMock) + + DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(reactContext) + val uiManagerModuleMock = mock(UIManagerModule::class.java) + whenever(catalystInstanceMock.getNativeModule(UIManagerModule::class.java)) + .thenReturn(uiManagerModuleMock) + } + + @Test + fun testTouchEmitter() { + val instanceManager = mock(ReactInstanceManager::class.java) + whenever(instanceManager.currentReactContext).thenReturn(reactContext) + val uiManager = mock(UIManagerModule::class.java) + val eventDispatcher = mock(EventDispatcher::class.java) + val eventEmitterModuleMock = mock(RCTEventEmitter::class.java) + whenever(catalystInstanceMock.getNativeModule(UIManagerModule::class.java)) + .thenReturn(uiManager) + whenever(uiManager.eventDispatcher).thenReturn(eventDispatcher) + + // RootView IDs is React Native follow the 11, 21, 31, ... progression. + val rootViewId = 11 + val rootView = ReactRootView(reactContext) + rootView.id = rootViewId + rootView.rootViewTag = rootViewId + rootView.startReactApplication(instanceManager, "") + rootView.simulateAttachForTesting() + val ts = SystemClock.currentTimeMillis() + + // Test ACTION_DOWN event + rootView.onTouchEvent(MotionEvent.obtain(100, ts, MotionEvent.ACTION_DOWN, 0f, 0f, 0)) + + val downEventCaptor = ArgumentCaptor.forClass(Event::class.java) + verify(eventDispatcher).dispatchEvent(downEventCaptor.capture()) + verifyNoMoreInteractions(eventDispatcher) + downEventCaptor.value.dispatch(eventEmitterModuleMock) + val downActionTouchesArgCaptor = ArgumentCaptor.forClass(JavaOnlyArray::class.java) + verify(eventEmitterModuleMock) + .receiveTouches( + ArgumentMatchers.eq("topTouchStart"), + downActionTouchesArgCaptor.capture(), + ArgumentMatchers.any(JavaOnlyArray::class.java)) + verifyNoMoreInteractions(eventEmitterModuleMock) + assertThat(downActionTouchesArgCaptor.value.size()).isEqualTo(1) + assertThat(downActionTouchesArgCaptor.value.getMap(0)) + .isEqualTo( + JavaOnlyMap.of( + "pageX", + 0.0, + "pageY", + 0.0, + "locationX", + 0.0, + "locationY", + 0.0, + "target", + rootViewId, + "timestamp", + ts.toDouble(), + "identifier", + 0.0, + "targetSurface", + -1)) + + // Test ACTION_UP event + reset(eventEmitterModuleMock, eventDispatcher) + val upEventCaptor = ArgumentCaptor.forClass(Event::class.java) + val upActionTouchesArgCaptor = ArgumentCaptor.forClass(JavaOnlyArray::class.java) + + rootView.onTouchEvent(MotionEvent.obtain(50, ts, MotionEvent.ACTION_UP, 0f, 0f, 0)) + + verify(eventDispatcher).dispatchEvent(upEventCaptor.capture()) + verifyNoMoreInteractions(eventDispatcher) + upEventCaptor.value.dispatch(eventEmitterModuleMock) + verify(eventEmitterModuleMock) + .receiveTouches( + ArgumentMatchers.eq("topTouchEnd"), + upActionTouchesArgCaptor.capture(), + ArgumentMatchers.any(WritableArray::class.java)) + verifyNoMoreInteractions(eventEmitterModuleMock) + assertThat(upActionTouchesArgCaptor.value.size()).isEqualTo(1) + assertThat(upActionTouchesArgCaptor.value.getMap(0)) + .isEqualTo( + JavaOnlyMap.of( + "pageX", + 0.0, + "pageY", + 0.0, + "locationX", + 0.0, + "locationY", + 0.0, + "target", + rootViewId, + "timestamp", + ts.toDouble(), + "identifier", + 0.0, + "targetSurface", + -1)) + + // Test other action + reset(eventDispatcher) + + rootView.onTouchEvent( + MotionEvent.obtain(50, Date().time, MotionEvent.ACTION_HOVER_MOVE, 0f, 0f, 0)) + + verifyNoMoreInteractions(eventDispatcher) + } + + @Test + fun testRemountApplication() { + val instanceManager = mock(ReactInstanceManager::class.java) + val rootView = ReactRootView(reactContext) + rootView.startReactApplication(instanceManager, "") + rootView.unmountReactApplication() + rootView.startReactApplication(instanceManager, "") + } + + @Test + fun testCheckForKeyboardEvents() { + val instanceManager = mock(ReactInstanceManager::class.java) + val activity = Robolectric.buildActivity(Activity::class.java).create().get() + whenever(instanceManager.currentReactContext).thenReturn(reactContext) + val rootView: ReactRootView = + object : ReactRootView(activity) { + override fun getWindowVisibleDisplayFrame(outRect: Rect) { + if (outRect.bottom == 0) { + outRect.bottom += 100 + outRect.right += 370 + } else { + outRect.bottom += 370 + } + } + + override fun getRootWindowInsets() = + WindowInsets.Builder() + .setInsets(WindowInsets.Type.ime(), Insets.of(0, 0, 0, 370)) + .setVisible(WindowInsets.Type.ime(), true) + .build() + } + + rootView.startReactApplication(instanceManager, "") + rootView.simulateCheckForKeyboardForTesting() + + val params = Arguments.createMap() + val endCoordinates = Arguments.createMap() + val screenHeight = 470.0 + val keyboardHeight = 100.0 + params.putDouble("duration", 0.0) + endCoordinates.putDouble("width", screenHeight - keyboardHeight) + endCoordinates.putDouble("screenX", 0.0) + endCoordinates.putDouble("height", screenHeight - keyboardHeight) + endCoordinates.putDouble("screenY", keyboardHeight) + params.putMap("endCoordinates", endCoordinates) + params.putString("easing", "keyboard") + verify(reactContext, times(1)).emitDeviceEvent("keyboardDidShow", params) + } +} diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridgeless/ReactHostDelegateTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridgeless/ReactHostDelegateTest.kt new file mode 100644 index 00000000000000..19aefb0df07763 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridgeless/ReactHostDelegateTest.kt @@ -0,0 +1,53 @@ +/* + * 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. + */ + +package com.facebook.react.bridgeless + +import com.facebook.react.ReactPackage +import com.facebook.react.bridge.JSBundleLoader +import com.facebook.react.common.annotations.UnstableReactNativeAPI +import com.facebook.react.fabric.ReactNativeConfig +import com.facebook.react.turbomodule.core.TurboModuleManagerDelegate +import com.facebook.testutils.shadows.ShadowSoLoader +import org.assertj.core.api.Assertions.assertThat +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config + +@RunWith(RobolectricTestRunner::class) +@OptIn(UnstableReactNativeAPI::class) +@Config(shadows = [ShadowSoLoader::class]) +class ReactHostDelegateTest { + + /** Mock test for ReactInstanceDelegate, used to setup the process to create a stable API */ + @Test + fun testReactInstanceDelegateCreation() { + val jsBundleLoader: JSBundleLoader = Mockito.mock(JSBundleLoader::class.java) + val reactPackage: ReactPackage = Mockito.mock(ReactPackage::class.java) + val bindingsInstallerMock: BindingsInstaller = Mockito.mock(BindingsInstaller::class.java) + val turboModuleManagerDelegateMock: TurboModuleManagerDelegate = + Mockito.mock(TurboModuleManagerDelegate::class.java) + val jsEngineInstanceMock: JSEngineInstance = Mockito.mock(JSEngineInstance::class.java) + val reactNativeConfigMock: ReactNativeConfig = Mockito.mock(ReactNativeConfig::class.java) + val reactPackages = listOf(reactPackage) + val jsMainModulePathMocked = "mockedJSMainModulePath" + val delegate = + ReactHostDelegate.ReactHostDelegateBase( + jsMainModulePathMocked, + jsBundleLoader = jsBundleLoader, + reactPackages = reactPackages, + bindingsInstaller = bindingsInstallerMock, + jsEngineInstance = jsEngineInstanceMock, + reactNativeConfig = reactNativeConfigMock, + turboModuleManagerDelegate = turboModuleManagerDelegateMock, + exceptionHandler = {}) + + assertThat(delegate.jSMainModulePath).isEqualTo(jsMainModulePathMocked) + } +} diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridgeless/ReactHostTest.java b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridgeless/ReactHostTest.java index ae01c6783cda11..7ce2af4a1ade2d 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridgeless/ReactHostTest.java +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridgeless/ReactHostTest.java @@ -55,7 +55,7 @@ @Ignore("Ignore for now as these tests fail in OSS only") public class ReactHostTest { - private ReactInstanceDelegate mReactInstanceDelegate; + private ReactHostDelegate mReactHostDelegate; private ReactInstance mReactInstance; private MemoryPressureRouter mMemoryPressureRouter; private BridgelessDevSupportManager mDevSupportManager; @@ -72,7 +72,7 @@ public void setUp() throws Exception { mActivityController = Robolectric.buildActivity(Activity.class).create().start().resume(); - mReactInstanceDelegate = mock(ReactInstanceDelegate.class); + mReactHostDelegate = mock(ReactHostDelegate.class); mReactInstance = mock(ReactInstance.class); mMemoryPressureRouter = mock(MemoryPressureRouter.class); mDevSupportManager = mock(BridgelessDevSupportManager.class); @@ -84,13 +84,13 @@ public void setUp() throws Exception { whenNew(BridgelessDevSupportManager.class).withAnyArguments().thenReturn(mDevSupportManager); doReturn(mJSBundleLoader) - .when(mReactInstanceDelegate) + .when(mReactHostDelegate) .getJSBundleLoader(ArgumentMatchers.any()); mReactHost = new ReactHost( mActivityController.get().getApplication(), - mReactInstanceDelegate, + mReactHostDelegate, mComponentFactory, false, null, diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridgeless/ReactSurfaceTest.java b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridgeless/ReactSurfaceTest.java index 76eff368cdcd4c..aeba7ffe654698 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridgeless/ReactSurfaceTest.java +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridgeless/ReactSurfaceTest.java @@ -35,7 +35,7 @@ @RunWith(RobolectricTestRunner.class) public class ReactSurfaceTest { - @Mock ReactInstanceDelegate mReactInstanceDelegate; + @Mock ReactHostDelegate mReactHostDelegate; @Mock EventDispatcher mEventDispatcher; private ReactHost mReactHost; @@ -49,7 +49,7 @@ public void setUp() { mContext = Robolectric.buildActivity(Activity.class).create().get(); - mReactHost = spy(new ReactHost(mContext, mReactInstanceDelegate, null, false, null, false)); + mReactHost = spy(new ReactHost(mContext, mReactHostDelegate, null, false, null, false)); doAnswer(mockedStartSurface()).when(mReactHost).startSurface(any(ReactSurface.class)); doAnswer(mockedStartSurface()).when(mReactHost).prerenderSurface(any(ReactSurface.class)); doAnswer(mockedStopSurface()).when(mReactHost).stopSurface(any(ReactSurface.class)); diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/BaseViewManagerTest.java b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/BaseViewManagerTest.java index 95642f5edd9538..83e32f7287ab1f 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/BaseViewManagerTest.java +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/BaseViewManagerTest.java @@ -14,6 +14,7 @@ import com.facebook.react.bridge.JavaOnlyMap; import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.ReactAccessibilityDelegate.AccessibilityRole; +import com.facebook.react.uimanager.ReactAccessibilityDelegate.Role; import com.facebook.react.views.view.ReactViewGroup; import com.facebook.react.views.view.ReactViewManager; import java.util.Locale; @@ -78,4 +79,10 @@ public void testAccessibilityStateSelected() { assertThat(mView.getTag(R.id.accessibility_state)).isEqualTo(accessibilityState); assertThat(mView.isSelected()).isEqualTo(true); } + + @Test + public void testRoleList() { + mViewManager.setRole(mView, "list"); + assertThat(mView.getTag(R.id.role)).isEqualTo(Role.LIST); + } } diff --git a/packages/react-native/ReactAndroid/src/test/resources/robolectric.properties b/packages/react-native/ReactAndroid/src/test/resources/robolectric.properties index b0d79302d02b6a..824645ee0384ff 100644 --- a/packages/react-native/ReactAndroid/src/test/resources/robolectric.properties +++ b/packages/react-native/ReactAndroid/src/test/resources/robolectric.properties @@ -1,2 +1,2 @@ # Set this to minimum supported API level for React Native. -sdk=21 +sdk=33 diff --git a/packages/react-native/ReactCommon/React-Fabric.podspec b/packages/react-native/ReactCommon/React-Fabric.podspec index e15f4bc1614e97..4102565442373e 100644 --- a/packages/react-native/ReactCommon/React-Fabric.podspec +++ b/packages/react-native/ReactCommon/React-Fabric.podspec @@ -47,6 +47,16 @@ Pod::Spec.new do |s| s.dependency "RCTTypeSafety", version s.dependency "ReactCommon/turbomodule/core", version s.dependency "React-jsi", version + s.dependency "React-logger" + s.dependency "glog" + s.dependency "DoubleConversion" + s.dependency "React-Core" + + if ENV["USE_HERMES"] == nil || ENV["USE_HERMES"] == "1" + s.dependency "hermes-engine" + else + s.dependency "React-jsi" + end s.subspec "animations" do |ss| ss.dependency folly_dep_name, folly_version @@ -83,11 +93,11 @@ Pod::Spec.new do |s| "\"$(PODS_TARGET_SRCROOT)/ReactCommon\"", "\"$(PODS_ROOT)/RCT-Folly\"", "\"$(PODS_ROOT)/Headers/Private/Yoga\"", + "\"$(PODS_TARGET_SRCROOT)\"", ] if ENV['USE_FRAMEWORKS'] header_search_path = header_search_path + [ - "\"$(PODS_TARGET_SRCROOT)\"", "\"$(PODS_ROOT)/DoubleConversion\"", "\"$(PODS_CONFIGURATION_BUILD_DIR)/React-Codegen/React_Codegen.framework/Headers\"", "\"$(PODS_CONFIGURATION_BUILD_DIR)/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\"", @@ -121,13 +131,6 @@ Pod::Spec.new do |s| end s.subspec "components" do |ss| - ss.subspec "image" do |sss| - sss.dependency folly_dep_name, folly_version - sss.compiler_flags = folly_compiler_flags - sss.source_files = "react/renderer/components/image/**/*.{m,mm,cpp,h}" - sss.exclude_files = "react/renderer/components/image/tests" - sss.header_dir = "react/renderer/components/image" - end ss.subspec "inputaccessory" do |sss| sss.dependency folly_dep_name, folly_version diff --git a/packages/react-native/ReactCommon/React-FabricImage.podspec b/packages/react-native/ReactCommon/React-FabricImage.podspec new file mode 100644 index 00000000000000..e5a4be90b50d90 --- /dev/null +++ b/packages/react-native/ReactCommon/React-FabricImage.podspec @@ -0,0 +1,87 @@ +# 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. + +require "json" + +package = JSON.parse(File.read(File.join(__dir__, "..", "package.json"))) +version = package['version'] + +source = { :git => 'https://github.com/facebook/react-native.git' } +if version == '1000.0.0' + # This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in. + source[:commit] = `git rev-parse HEAD`.strip if system("git rev-parse --git-dir > /dev/null 2>&1") +else + source[:tag] = "v#{version}" +end + +folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32 -Wno-gnu-zero-variadic-macro-arguments' +folly_version = '2021.07.22.00' +folly_dep_name = 'RCT-Folly/Fabric' +boost_compiler_flags = '-Wno-documentation' +react_native_path = ".." + +header_search_path = [ + "\"$(PODS_ROOT)/boost\"", + "\"$(PODS_TARGET_SRCROOT)/ReactCommon\"", + "\"$(PODS_ROOT)/RCT-Folly\"", + "\"$(PODS_ROOT)/Headers/Private/Yoga\"", +] + +if ENV['USE_FRAMEWORKS'] + header_search_path = header_search_path + [ + "\"$(PODS_TARGET_SRCROOT)\"", + "\"$(PODS_ROOT)/DoubleConversion\"", + "\"$(PODS_CONFIGURATION_BUILD_DIR)/React-Codegen/React_Codegen.framework/Headers\"", + "\"$(PODS_CONFIGURATION_BUILD_DIR)/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/imagemanager/platform/ios\"", + "\"$(PODS_TARGET_SRCROOT)/react/renderer/textlayoutmanager/platform/ios\"", + "\"$(PODS_TARGET_SRCROOT)/react/renderer/components/textinput/iostextinput\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\"" + ] +end + +Pod::Spec.new do |s| + s.name = "React-FabricImage" + s.version = version + s.summary = "Image Component for Fabric for React Native." + s.homepage = "https://reactnative.dev/" + s.license = package["license"] + s.author = "Meta Platforms, Inc. and its affiliates" + s.platforms = { :ios => min_ios_version_supported } + s.source = source + s.source_files = "react/renderer/components/image/**/*.{m,mm,cpp,h}" + s.exclude_files = "react/renderer/components/image/tests" + s.header_dir = "react/renderer/components/image" + s.compiler_flags = folly_compiler_flags + s.pod_target_xcconfig = { "USE_HEADERMAP" => "YES", + "CLANG_CXX_LANGUAGE_STANDARD" => "c++17", + "HEADER_SEARCH_PATHS" => header_search_path.join(" ") + } + + if ENV['USE_FRAMEWORKS'] + s.header_mappings_dir = './' + s.module_name = 'React_FabricImage' + end + + s.dependency folly_dep_name, folly_version + s.dependency "React-graphics", version + s.dependency "React-jsiexecutor", version + s.dependency "RCTRequired", version + s.dependency "RCTTypeSafety", version + s.dependency "ReactCommon/turbomodule/core", version + s.dependency "React-jsi", version + s.dependency "React-logger" + s.dependency "glog" + s.dependency "DoubleConversion" + s.dependency "React-ImageManager" + s.dependency "React-Fabric" + s.dependency "Yoga" + + if ENV["USE_HERMES"] == nil || ENV["USE_HERMES"] == "1" + s.dependency "hermes-engine" + else + s.dependency "React-jsi" + end +end diff --git a/packages/react-native/ReactCommon/react/bridgeless/README.md b/packages/react-native/ReactCommon/react/bridgeless/README.md new file mode 100644 index 00000000000000..31b0a095904cc4 --- /dev/null +++ b/packages/react-native/ReactCommon/react/bridgeless/README.md @@ -0,0 +1,3 @@ +# Bridgeless Mode for iOS + +This library is not ready for integration for production nor local experimentation. Expect breaking changes regularly if you use any of these APIs. Use at your own risk! diff --git a/packages/react-native/ReactCommon/react/bridgeless/ReactInstance.cpp b/packages/react-native/ReactCommon/react/bridgeless/ReactInstance.cpp index 701780b6c55b59..07edae1f8dcc00 100644 --- a/packages/react-native/ReactCommon/react/bridgeless/ReactInstance.cpp +++ b/packages/react-native/ReactCommon/react/bridgeless/ReactInstance.cpp @@ -155,6 +155,12 @@ static void defineReadOnlyGlobal( jsi::Runtime &runtime, std::string propName, jsi::Value &&value) { + if (runtime.global().hasProperty(runtime, propName.c_str())) { + throw jsi::JSError( + runtime, + "Tried to redefine read-only global \"" + propName + + "\", but read-only globals can only be defined once."); + } jsi::Object jsObject = runtime.global().getProperty(runtime, "Object").asObject(runtime); jsi::Function defineProperty = jsObject.getProperty(runtime, "defineProperty") diff --git a/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTHost+Internal.h b/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTHost+Internal.h new file mode 100644 index 00000000000000..7d3f5cf3e08bc7 --- /dev/null +++ b/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTHost+Internal.h @@ -0,0 +1,14 @@ +/* + * 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. + */ + +#import "RCTHost.h" + +@interface RCTHost (Internal) + +- (void)registerSegmentWithId:(NSNumber *)segmentId path:(NSString *)path; + +@end diff --git a/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTHost.h b/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTHost.h index 338acf48017d07..96fd88a7afd641 100644 --- a/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTHost.h +++ b/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTHost.h @@ -18,27 +18,26 @@ NS_ASSUME_NONNULL_BEGIN @class RCTFabricSurface; +@class RCTHost; @class RCTJSThreadManager; @class RCTModuleRegistry; -@class RCTPerformanceLogger; @protocol RCTInstanceDelegate; FB_RUNTIME_PROTOCOL @protocol RCTTurboModuleManagerDelegate; -/** - * This notification fires just before RCTHost releases it's RCTInstance reference. - */ -RCT_EXTERN NSString *const RCTHostWillReloadNotification; - -/** - * This notification fires just after RCTHost releases it's RCTInstance reference. - */ -RCT_EXTERN NSString *const RCTHostDidReloadNotification; +typedef std::shared_ptr (^RCTHostJSEngineProvider)(void); @protocol RCTHostDelegate -- (std::shared_ptr)getJSEngine; - (NSURL *)getBundleURL; +- (std::shared_ptr)createContextContainer; + +- (void)host:(RCTHost *)host + didReceiveJSErrorStack:(NSArray *> *)stack + message:(NSString *)message + exceptionId:(NSUInteger)exceptionId + isFatal:(BOOL)isFatal; +- (void)hostDidStart:(RCTHost *)host; @end @@ -47,21 +46,19 @@ RCT_EXTERN NSString *const RCTHostDidReloadNotification; * RCTHost is long lived, while an instance may be deallocated and re-initialized. Some examples of when this happens: * CMD+R reload in DEV or a JS crash. The host should be the single owner of an RCTInstance. */ -@interface RCTHost : NSObject +@interface RCTHost : NSObject - (instancetype)initWithHostDelegate:(id)hostDelegate - instanceDelegate:(id)instanceDelegate turboModuleManagerDelegate:(id)turboModuleManagerDelegate bindingsInstallFunc:(facebook::react::ReactInstance::BindingsInstallFunc)bindingsInstallFunc - jsErrorHandlingFunc:(facebook::react::JsErrorHandler::JsErrorHandlingFunc)jsErrorHandlingFunc - NS_DESIGNATED_INITIALIZER FB_OBJC_DIRECT; + jsEngineProvider:(RCTHostJSEngineProvider)jsEngineProvider NS_DESIGNATED_INITIALIZER FB_OBJC_DIRECT; /** * This function initializes an RCTInstance if one does not yet exist. This function is currently only called on the * main thread, but it should be threadsafe. * TODO T74233481 - Verify if this function is threadsafe. */ -- (void)preload; +- (void)start; - (RCTFabricSurface *)createSurfaceWithModuleName:(NSString *)moduleName mode:(facebook::react::DisplayMode)displayMode @@ -70,14 +67,16 @@ RCT_EXTERN NSString *const RCTHostDidReloadNotification; - (RCTFabricSurface *)createSurfaceWithModuleName:(NSString *)moduleName initialProperties:(NSDictionary *)properties FB_OBJC_DIRECT; -- (RCTJSThreadManager *)getJSThreadManager FB_OBJC_DIRECT; - - (RCTModuleRegistry *)getModuleRegistry FB_OBJC_DIRECT; -- (RCTPerformanceLogger *)getPerformanceLogger FB_OBJC_DIRECT; - - (RCTSurfacePresenter *)getSurfacePresenter FB_OBJC_DIRECT; +/** + * Calls a method on a JS module that has been registered with `registerCallableModule`. Used to invoke a JS function + * from platform code. + */ +- (void)callFunctionOnJSModule:(NSString *)moduleName method:(NSString *)method args:(NSArray *)args; + @end NS_ASSUME_NONNULL_END diff --git a/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTHost.mm b/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTHost.mm index 7a251ccc9e9c11..7b86e035198e1d 100644 --- a/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTHost.mm +++ b/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTHost.mm @@ -6,6 +6,7 @@ */ #import "RCTHost.h" +#import "RCTHost+Internal.h" #import #import @@ -14,26 +15,23 @@ #import #import #import +#import #import using namespace facebook::react; -NSString *const RCTHostWillReloadNotification = @"RCTHostWillReloadNotification"; -NSString *const RCTHostDidReloadNotification = @"RCTHostDidReloadNotification"; - -@interface RCTHost () +@interface RCTHost () @end @implementation RCTHost { RCTInstance *_instance; - __weak id _instanceDelegate; __weak id _hostDelegate; __weak id _turboModuleManagerDelegate; NSURL *_oldDelegateBundleURL; NSURL *_bundleURL; RCTBundleManager *_bundleManager; facebook::react::ReactInstance::BindingsInstallFunc _bindingsInstallFunc; - JsErrorHandler::JsErrorHandlingFunc _jsErrorHandlingFunc; + RCTHostJSEngineProvider _jsEngineProvider; // All the surfaces that need to be started after main bundle execution NSMutableArray *_surfaceStartBuffer; @@ -55,53 +53,47 @@ + (void)initialize has been expressed. */ - (instancetype)initWithHostDelegate:(id)hostDelegate - instanceDelegate:(id)instanceDelegate turboModuleManagerDelegate:(id)turboModuleManagerDelegate bindingsInstallFunc:(facebook::react::ReactInstance::BindingsInstallFunc)bindingsInstallFunc - jsErrorHandlingFunc:(JsErrorHandler::JsErrorHandlingFunc)jsErrorHandlingFunc; + jsEngineProvider:(RCTHostJSEngineProvider)jsEngineProvider { - RCTAssert( - hostDelegate && instanceDelegate && turboModuleManagerDelegate, - @"RCTHost cannot be instantiated with any nil init params."); - if (self = [super init]) { _hostDelegate = hostDelegate; - _instanceDelegate = instanceDelegate; _turboModuleManagerDelegate = turboModuleManagerDelegate; _surfaceStartBuffer = [NSMutableArray new]; _bundleManager = [RCTBundleManager new]; _bindingsInstallFunc = bindingsInstallFunc; _moduleRegistry = [RCTModuleRegistry new]; - _jsErrorHandlingFunc = jsErrorHandlingFunc; + _jsEngineProvider = [jsEngineProvider copy]; - __weak RCTHost *weakHost = self; + __weak RCTHost *weakSelf = self; auto bundleURLGetter = ^NSURL *() { - RCTHost *strongHost = weakHost; - if (!strongHost) { + RCTHost *strongSelf = weakSelf; + if (!strongSelf) { return nil; } - return strongHost->_bundleURL; + return strongSelf->_bundleURL; }; auto bundleURLSetter = ^(NSURL *bundleURL) { - RCTHost *strongHost = weakHost; - if (!strongHost) { + RCTHost *strongSelf = weakSelf; + if (!strongSelf) { return; } - strongHost->_bundleURL = bundleURL; + strongSelf->_bundleURL = bundleURL; }; auto defaultBundleURLGetter = ^NSURL *() { - RCTHost *strongHost = weakHost; - if (!strongHost) { + RCTHost *strongSelf = weakSelf; + if (!strongSelf) { return nil; } - return [strongHost->_hostDelegate getBundleURL]; + return [strongSelf->_hostDelegate getBundleURL]; }; [_bundleManager setBridgelessBundleURLGetter:bundleURLGetter @@ -117,17 +109,17 @@ - (instancetype)initWithHostDelegate:(id)hostDelegate * JS calls before the main JSBundle finishes execution, and execute them after. */ _onInitialBundleLoad = ^{ - RCTHost *strongHost = weakHost; - if (!strongHost) { + RCTHost *strongSelf = weakSelf; + if (!strongSelf) { return; } NSArray *unstartedSurfaces = @[]; { - std::lock_guard guard{strongHost->_surfaceStartBufferMutex}; - unstartedSurfaces = [NSArray arrayWithArray:strongHost->_surfaceStartBuffer]; - strongHost->_surfaceStartBuffer = nil; + std::lock_guard guard{strongSelf->_surfaceStartBufferMutex}; + unstartedSurfaces = [NSArray arrayWithArray:strongSelf->_surfaceStartBuffer]; + strongSelf->_surfaceStartBuffer = nil; } for (RCTFabricSurface *surface in unstartedSurfaces) { @@ -143,9 +135,9 @@ - (instancetype)initWithHostDelegate:(id)hostDelegate return self; } -#pragma mark - Public API +#pragma mark - Public -- (void)preload +- (void)start { if (_instance) { RCTLogWarn( @@ -154,14 +146,14 @@ - (void)preload } [self _refreshBundleURL]; RCTReloadCommandSetBundleURL(_bundleURL); - _instance = [[RCTInstance alloc] initWithDelegate:_instanceDelegate - jsEngineInstance:[_hostDelegate getJSEngine] + _instance = [[RCTInstance alloc] initWithDelegate:self + jsEngineInstance:[self _provideJSEngine] bundleManager:_bundleManager turboModuleManagerDelegate:_turboModuleManagerDelegate onInitialBundleLoad:_onInitialBundleLoad bindingsInstallFunc:_bindingsInstallFunc - moduleRegistry:_moduleRegistry - jsErrorHandlingFunc:_jsErrorHandlingFunc]; + moduleRegistry:_moduleRegistry]; + [_hostDelegate hostDidStart:self]; } - (RCTFabricSurface *)createSurfaceWithModuleName:(NSString *)moduleName @@ -191,32 +183,25 @@ - (RCTFabricSurface *)createSurfaceWithModuleName:(NSString *)moduleName initial return [self createSurfaceWithModuleName:moduleName mode:DisplayMode::Visible initialProperties:properties]; } -- (RCTJSThreadManager *)getJSThreadManager -{ - return [_instance jsThreadManager]; -} - - (RCTModuleRegistry *)getModuleRegistry { return _moduleRegistry; } -- (RCTPerformanceLogger *)getPerformanceLogger +- (RCTSurfacePresenter *)getSurfacePresenter { - return [_instance performanceLogger]; + return [_instance surfacePresenter]; } -- (RCTSurfacePresenter *)getSurfacePresenter +- (void)callFunctionOnJSModule:(NSString *)moduleName method:(NSString *)method args:(NSArray *)args { - return [_instance surfacePresenter]; + [_instance callFunctionOnJSModule:moduleName method:method args:args]; } #pragma mark - RCTReloadListener - (void)didReceiveReloadCommand { - [[NSNotificationCenter defaultCenter] - postNotification:[NSNotification notificationWithName:RCTHostWillReloadNotification object:nil]]; [_instance invalidate]; _instance = nil; [self _refreshBundleURL]; @@ -228,47 +213,65 @@ - (void)didReceiveReloadCommand _surfaceStartBuffer = [NSMutableArray arrayWithArray:[self _getAttachedSurfaces]]; } - _instance = [[RCTInstance alloc] initWithDelegate:_instanceDelegate - jsEngineInstance:[_hostDelegate getJSEngine] + _instance = [[RCTInstance alloc] initWithDelegate:self + jsEngineInstance:[self _provideJSEngine] bundleManager:_bundleManager turboModuleManagerDelegate:_turboModuleManagerDelegate onInitialBundleLoad:_onInitialBundleLoad bindingsInstallFunc:_bindingsInstallFunc - moduleRegistry:_moduleRegistry - jsErrorHandlingFunc:_jsErrorHandlingFunc]; - [[NSNotificationCenter defaultCenter] - postNotification:[NSNotification notificationWithName:RCTHostDidReloadNotification object:nil]]; + moduleRegistry:_moduleRegistry]; + [_hostDelegate hostDidStart:self]; for (RCTFabricSurface *surface in [self _getAttachedSurfaces]) { [surface resetWithSurfacePresenter:[self getSurfacePresenter]]; } } -// TODO (T74233481) - Should raw instance be accessed in this class like this? These functions shouldn't be called very -// early in startup, but could add some intelligent guards here. -#pragma mark - ReactInstanceForwarding - -- (void)callFunctionOnModule:(NSString *)moduleName method:(NSString *)method args:(NSArray *)args +- (void)dealloc { - [_instance callFunctionOnModule:moduleName method:method args:args]; + [_instance invalidate]; } -- (void)loadScript:(RCTSource *)source +#pragma mark - RCTInstanceDelegate + +- (std::shared_ptr)createContextContainer { - [_instance loadScript:source]; + return [_hostDelegate createContextContainer]; } -- (void)registerSegmentWithId:(NSNumber *)segmentId path:(NSString *)path +- (void)instance:(RCTInstance *)instance didReceiveErrorMap:(facebook::react::MapBuffer)errorMap { - [_instance registerSegmentWithId:segmentId path:path]; + NSString *message = [NSString stringWithCString:errorMap.getString(JSErrorHandlerKey::kErrorMessage).c_str() + encoding:[NSString defaultCStringEncoding]]; + std::vector frames = errorMap.getMapBufferList(JSErrorHandlerKey::kAllStackFrames); + NSMutableArray *> *stack = [NSMutableArray new]; + for (facebook::react::MapBuffer const &mapBuffer : frames) { + NSDictionary *frame = @{ + @"file" : [NSString stringWithCString:mapBuffer.getString(JSErrorHandlerKey::kFrameFileName).c_str() + encoding:[NSString defaultCStringEncoding]], + @"methodName" : [NSString stringWithCString:mapBuffer.getString(JSErrorHandlerKey::kFrameMethodName).c_str() + encoding:[NSString defaultCStringEncoding]], + @"lineNumber" : [NSNumber numberWithInt:mapBuffer.getInt(JSErrorHandlerKey::kFrameLineNumber)], + @"column" : [NSNumber numberWithInt:mapBuffer.getInt(JSErrorHandlerKey::kFrameColumnNumber)], + }; + [stack addObject:frame]; + } + [_hostDelegate host:self + didReceiveJSErrorStack:stack + message:message + exceptionId:errorMap.getInt(JSErrorHandlerKey::kExceptionId) + isFatal:errorMap.getBool(JSErrorHandlerKey::kIsFatal)]; } -- (void)dealloc +#pragma mark - Internal + +- (void)registerSegmentWithId:(NSNumber *)segmentId path:(NSString *)path { - [_instance invalidate]; + [_instance registerSegmentWithId:segmentId path:path]; } #pragma mark - Private + - (void)_refreshBundleURL FB_OBJC_DIRECT { // Reset the _bundleURL ivar if the RCTHost delegate presents a new bundleURL @@ -299,4 +302,13 @@ - (void)_attachSurface:(RCTFabricSurface *)surface FB_OBJC_DIRECT return surfaces; } +- (std::shared_ptr)_provideJSEngine +{ + RCTAssert(_jsEngineProvider, @"_jsEngineProvider must be non-nil"); + std::shared_ptr jsEngine = _jsEngineProvider(); + RCTAssert(jsEngine != nullptr, @"_jsEngineProvider must return a nonnull pointer"); + + return jsEngine; +} + @end diff --git a/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTHostCreationHelpers.h b/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTHostCreationHelpers.h new file mode 100644 index 00000000000000..5006e14ef0c63a --- /dev/null +++ b/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTHostCreationHelpers.h @@ -0,0 +1,29 @@ +/* + * 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. + */ + +#import +#import + +#import "RCTHost.h" + +@class RCTHost; + +@protocol RCTHostDelegate; +@protocol RCTTurboModuleManagerDelegate; + +NS_ASSUME_NONNULL_BEGIN + +RCT_EXTERN_C_BEGIN + +RCTHost *RCTHostCreateDefault( + id hostDelegate, + id turboModuleManagerDelegate, + RCTHostJSEngineProvider jsEngineProvider); + +RCT_EXTERN_C_END + +NS_ASSUME_NONNULL_END diff --git a/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTHostCreationHelpers.mm b/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTHostCreationHelpers.mm new file mode 100644 index 00000000000000..31d1af728d2691 --- /dev/null +++ b/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTHostCreationHelpers.mm @@ -0,0 +1,19 @@ +/* + * 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. + */ + +#import "RCTHostCreationHelpers.h" + +RCTHost *RCTHostCreateDefault( + id hostDelegate, + id turboModuleManagerDelegate, + RCTHostJSEngineProvider jsEngineProvider) +{ + return [[RCTHost alloc] initWithHostDelegate:hostDelegate + turboModuleManagerDelegate:turboModuleManagerDelegate + bindingsInstallFunc:nullptr + jsEngineProvider:jsEngineProvider]; +} diff --git a/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTInstance.h b/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTInstance.h index 69f6484aa94a13..ed49c7938dfa9a 100644 --- a/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTInstance.h +++ b/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTInstance.h @@ -11,19 +11,21 @@ #import #import #import +#import #import +NS_ASSUME_NONNULL_BEGIN + /** * A utility to enable diagnostics mode at runtime. Useful for test runs. * The flags are comma-separated string tokens, or an empty string when * nothing is enabled. */ RCT_EXTERN NSString *RCTInstanceRuntimeDiagnosticFlags(void); -RCT_EXTERN void RCTInstanceSetRuntimeDiagnosticFlags(NSString *flags); - -NS_ASSUME_NONNULL_BEGIN +RCT_EXTERN void RCTInstanceSetRuntimeDiagnosticFlags(NSString *_Nullable flags); @class RCTBundleManager; +@class RCTInstance; @class RCTJSThreadManager; @class RCTModuleRegistry; @class RCTPerformanceLogger; @@ -33,35 +35,11 @@ NS_ASSUME_NONNULL_BEGIN FB_RUNTIME_PROTOCOL @protocol RCTTurboModuleManagerDelegate; -// TODO (T74233481) - Delete this. Communication between Product Code <> RCTInstance should go through RCTHost. @protocol RCTInstanceDelegate -@required - - (std::shared_ptr)createContextContainer; -@end - -/** - * A set of functions which are forwarded through RCTHost, RCTInstance to ReactInstance. - */ -@protocol ReactInstanceForwarding - -/** - * Calls a method on a JS module that has been registered with `registerCallableModule`. Used to invoke a JS function - * from platform code. - */ -- (void)callFunctionOnModule:(NSString *)moduleName method:(NSString *)method args:(NSArray *)args; - -/** - * Loads the JS bundle asynchronously. - */ -- (void)loadScript:(RCTSource *)source; - -/** - * Registers a new JS segment. - */ -- (void)registerSegmentWithId:(NSNumber *)segmentId path:(NSString *)path; +- (void)instance:(RCTInstance *)instance didReceiveErrorMap:(facebook::react::MapBuffer)errorMap; @end @@ -72,7 +50,7 @@ typedef void (^_Null_unspecified RCTInstanceInitialBundleLoadCompletionBlock)(); * Native. RCTInstance should never be instantiated in product code, but rather accessed through RCTHost. The host * ensures that any access to the instance is safe, and manages instance lifecycle. */ -@interface RCTInstance : NSObject +@interface RCTInstance : NSObject - (instancetype)initWithDelegate:(id)delegate jsEngineInstance:(std::shared_ptr)jsEngineInstance @@ -80,15 +58,13 @@ typedef void (^_Null_unspecified RCTInstanceInitialBundleLoadCompletionBlock)(); turboModuleManagerDelegate:(id)turboModuleManagerDelegate onInitialBundleLoad:(RCTInstanceInitialBundleLoadCompletionBlock)onInitialBundleLoad bindingsInstallFunc:(facebook::react::ReactInstance::BindingsInstallFunc)bindingsInstallFunc - moduleRegistry:(RCTModuleRegistry *)moduleRegistry - jsErrorHandlingFunc:(facebook::react::JsErrorHandler::JsErrorHandlingFunc)jsErrorHandlingFunc - FB_OBJC_DIRECT; + moduleRegistry:(RCTModuleRegistry *)moduleRegistry NS_DESIGNATED_INITIALIZER FB_OBJC_DIRECT; -- (void)invalidate; +- (void)callFunctionOnJSModule:(NSString *)moduleName method:(NSString *)method args:(NSArray *)args; -@property (nonatomic, readonly, strong, FB_DIRECT) RCTJSThreadManager *jsThreadManager; +- (void)registerSegmentWithId:(NSNumber *)segmentId path:(NSString *)path; -@property (nonatomic, readonly, strong) RCTPerformanceLogger *performanceLogger; +- (void)invalidate; @property (nonatomic, readonly, strong) RCTSurfacePresenter *surfacePresenter; diff --git a/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTInstance.mm b/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTInstance.mm index b0db0c4094646b..3873592bf54517 100644 --- a/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTInstance.mm +++ b/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTInstance.mm @@ -19,7 +19,6 @@ #import #import #import -#import #import #import #import @@ -38,7 +37,7 @@ #import "RCTJSThreadManager.h" #import "RCTPerformanceLoggerUtils.h" -#if (RCT_DEV | RCT_ENABLE_LOADING_VIEW) && __has_include() +#if RCT_DEV_MENU && __has_include() #import #import #endif @@ -69,18 +68,21 @@ @implementation RCTInstance { __weak id _appTMMDelegate; __weak id _delegate; RCTSurfacePresenter *_surfacePresenter; + RCTPerformanceLogger *_performanceLogger; RCTDisplayLink *_displayLink; RCTInstanceInitialBundleLoadCompletionBlock _onInitialBundleLoad; ReactInstance::BindingsInstallFunc _bindingsInstallFunc; RCTTurboModuleManager *_turboModuleManager; - JsErrorHandler::JsErrorHandlingFunc _jsErrorHandlingFunc; std::mutex _invalidationMutex; std::atomic _valid; + RCTJSThreadManager *_jsThreadManager; // APIs supporting interop with native modules and view managers RCTBridgeModuleDecorator *_bridgeModuleDecorator; } +#pragma mark - Public + - (instancetype)initWithDelegate:(id)delegate jsEngineInstance:(std::shared_ptr)jsEngineInstance bundleManager:(RCTBundleManager *)bundleManager @@ -88,7 +90,6 @@ - (instancetype)initWithDelegate:(id)delegate onInitialBundleLoad:(RCTInstanceInitialBundleLoadCompletionBlock)onInitialBundleLoad bindingsInstallFunc:(ReactInstance::BindingsInstallFunc)bindingsInstallFunc moduleRegistry:(RCTModuleRegistry *)moduleRegistry - jsErrorHandlingFunc:(JsErrorHandler::JsErrorHandlingFunc)jsErrorHandlingFunc; { if (self = [super init]) { _performanceLogger = [RCTPerformanceLogger new]; @@ -101,32 +102,108 @@ - (instancetype)initWithDelegate:(id)delegate _jsThreadManager = [RCTJSThreadManager new]; _onInitialBundleLoad = onInitialBundleLoad; _bindingsInstallFunc = bindingsInstallFunc; - _jsErrorHandlingFunc = jsErrorHandlingFunc; _bridgeModuleDecorator = [[RCTBridgeModuleDecorator alloc] initWithViewRegistry:[RCTViewRegistry new] moduleRegistry:moduleRegistry bundleManager:bundleManager callableJSModules:[RCTCallableJSModules new]]; { - __weak __typeof(self) weakInstance = self; + __weak __typeof(self) weakSelf = self; [_bridgeModuleDecorator.callableJSModules setBridgelessJSModuleMethodInvoker:^( NSString *moduleName, NSString *methodName, NSArray *args, dispatch_block_t onComplete) { // TODO: Make RCTInstance call onComplete - [weakInstance callFunctionOnModule:moduleName method:methodName args:args]; + [weakSelf callFunctionOnJSModule:moduleName method:methodName args:args]; }]; } [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(notifyEventDispatcherObserversOfEvent_DEPRECATED:) + selector:@selector(_notifyEventDispatcherObserversOfEvent_DEPRECATED:) name:@"RCTNotifyEventDispatcherObserversOfEvent_DEPRECATED" object:nil]; - [self start]; + [self _start]; } return self; } -- (void)start +- (void)callFunctionOnJSModule:(NSString *)moduleName method:(NSString *)method args:(NSArray *)args +{ + if (_valid) { + _reactInstance->callFunctionOnModule( + [moduleName UTF8String], [method UTF8String], convertIdToFollyDynamic(args ?: @[])); + } +} + +- (void)invalidate +{ + std::lock_guard lock(_invalidationMutex); + _valid = false; + + [_surfacePresenter suspend]; + [_jsThreadManager dispatchToJSThread:^{ + /** + * Every TurboModule is invalidated on its own method queue. + * TurboModuleManager invalidate blocks the calling thread until all TurboModules are invalidated. + */ + [self->_turboModuleManager invalidate]; + + // Clean up all the Resources + self->_reactInstance = nullptr; + self->_jsEngineInstance = nullptr; + self->_appTMMDelegate = nil; + self->_delegate = nil; + self->_displayLink = nil; + + self->_turboModuleManager = nil; + self->_performanceLogger = nil; + + // Terminate the JavaScript thread, so that no other work executes after this block. + self->_jsThreadManager = nil; + }]; +} + +- (void)registerSegmentWithId:(NSNumber *)segmentId path:(NSString *)path +{ + if (_valid) { + _reactInstance->registerSegment(static_cast([segmentId unsignedIntValue]), path.UTF8String); + } +} + +#pragma mark - RCTTurboModuleManagerDelegate + +- (Class)getModuleClassFromName:(const char *)name +{ + if ([_appTMMDelegate respondsToSelector:@selector(getModuleClassFromName:)]) { + return [_appTMMDelegate getModuleClassFromName:name]; + } + + return nil; +} + +- (id)getModuleInstanceFromClass:(Class)moduleClass +{ + if ([_appTMMDelegate respondsToSelector:@selector(getModuleInstanceFromClass:)]) { + id module = [_appTMMDelegate getModuleInstanceFromClass:moduleClass]; + [self _attachBridgelessAPIsToModule:module]; + return module; + } + + return nil; +} + +- (std::shared_ptr)getTurboModule:(const std::string &)name + jsInvoker:(std::shared_ptr)jsInvoker +{ + if ([_appTMMDelegate respondsToSelector:@selector(getTurboModule:jsInvoker:)]) { + return [_appTMMDelegate getTurboModule:name jsInvoker:jsInvoker]; + } + + return nullptr; +} + +#pragma mark - Private + +- (void)_start { // Set up timers auto objCTimerRegistry = std::make_unique(); @@ -136,9 +213,12 @@ - (void)start auto timerManager = std::make_shared(std::move(objCTimerRegistry)); objCTimerRegistryRawPtr->setTimerManager(timerManager); + __weak __typeof(self) weakSelf = self; + auto jsErrorHandlingFunc = [=](MapBuffer errorMap) { [weakSelf _handleJSErrorMap:std::move(errorMap)]; }; + // Create the React Instance _reactInstance = std::make_unique( - _jsEngineInstance->createJSRuntime(), _jsThreadManager.jsMessageThread, timerManager, _jsErrorHandlingFunc); + _jsEngineInstance->createJSRuntime(), _jsThreadManager.jsMessageThread, timerManager, jsErrorHandlingFunc); _valid = true; RuntimeExecutor bufferedRuntimeExecutor = _reactInstance->getBufferedRuntimeExecutor(); @@ -157,6 +237,9 @@ - (void)start RCTLogSetBridgelessCallableJSModules(_bridgeModuleDecorator.callableJSModules); auto contextContainer = [_delegate createContextContainer]; + if (!contextContainer) { + contextContainer = std::make_shared(); + } contextContainer->insert( "RCTImageLoader", facebook::react::wrapManagedObject([_turboModuleManager moduleForName:"RCTImageLoader"])); contextContainer->insert( @@ -184,8 +267,6 @@ - (void)start // DisplayLink is used to call timer callbacks. _displayLink = [RCTDisplayLink new]; - __weak __typeof(self) weakSelf = self; - ReactInstance::JSRuntimeFlags options = { .isProfiling = false, .runtimeDiagnosticFlags = [RCTInstanceRuntimeDiagnosticFlags() UTF8String]}; _reactInstance->initializeRuntime(options, [=](jsi::Runtime &runtime) { @@ -218,55 +299,18 @@ - (void)start // Attempt to load bundle synchronously, fallback to asynchronously. [strongSelf->_performanceLogger markStartForTag:RCTPLScriptDownload]; - [strongSelf loadJSBundle:[strongSelf->_bridgeModuleDecorator.bundleManager bundleURL]]; + [strongSelf _loadJSBundle:[strongSelf->_bridgeModuleDecorator.bundleManager bundleURL]]; }); [_performanceLogger markStopForTag:RCTPLReactInstanceInit]; } -#pragma mark - RCTTurboModuleManagerDelegate -- (Class)getModuleClassFromName:(const char *)name -{ - if ([_appTMMDelegate respondsToSelector:@selector(getModuleClassFromName:)]) { - return [_appTMMDelegate getModuleClassFromName:name]; - } - - return nil; -} - -- (id)getModuleInstanceFromClass:(Class)moduleClass -{ - if ([_appTMMDelegate respondsToSelector:@selector(getModuleInstanceFromClass:)]) { - id module = [_appTMMDelegate getModuleInstanceFromClass:moduleClass]; - [self _attachBridgelessAPIsToModule:module]; - return module; - } - - return nil; -} - -- (std::shared_ptr)getTurboModule:(const std::string &)name - jsInvoker:(std::shared_ptr)jsInvoker -{ - if ([_appTMMDelegate respondsToSelector:@selector(getTurboModule:jsInvoker:)]) { - return [_appTMMDelegate getTurboModule:name jsInvoker:jsInvoker]; - } - - return nullptr; -} - - (void)_attachBridgelessAPIsToModule:(id)module FB_OBJC_DIRECT { - __weak RCTInstance *weakInstance = self; - if ([module respondsToSelector:@selector(setLoadScript:)]) { - ((id)module).loadScript = ^(RCTSource *source) { - [weakInstance loadScript:(source)]; - }; - } - + __weak RCTInstance *weakSelf = self; if ([module respondsToSelector:@selector(setDispatchToJSThread:)]) { ((id)module).dispatchToJSThread = ^(dispatch_block_t block) { - __strong __typeof(self) strongSelf = weakInstance; + __strong __typeof(self) strongSelf = weakSelf; if (strongSelf && strongSelf->_valid) { strongSelf->_reactInstance->getBufferedRuntimeExecutor()([=](jsi::Runtime &runtime) { block(); }); @@ -275,7 +319,7 @@ - (void)_attachBridgelessAPIsToModule:(id)module FB_OBJC_DIRECT } if ([module respondsToSelector:@selector(setSurfacePresenter:)]) { - [module performSelector:@selector(setSurfacePresenter:) withObject:self->_surfacePresenter]; + [module performSelector:@selector(setSurfacePresenter:) withObject:_surfacePresenter]; } // Replaces bridge.isInspectable @@ -292,33 +336,9 @@ - (void)_attachBridgelessAPIsToModule:(id)module FB_OBJC_DIRECT [_bridgeModuleDecorator attachInteropAPIsToModule:(id)module]; } -#pragma mark - ReactInstanceForwarding - -- (void)callFunctionOnModule:(NSString *)moduleName method:(NSString *)method args:(NSArray *)args +- (void)_loadJSBundle:(NSURL *)sourceURL FB_OBJC_DIRECT { - if (_valid) { - _reactInstance->callFunctionOnModule( - [moduleName UTF8String], [method UTF8String], convertIdToFollyDynamic(args ?: @[])); - } -} - -- (void)loadScript:(RCTSource *)source -{ - [self loadScriptFromSource:source]; -} - -- (void)registerSegmentWithId:(NSNumber *)segmentId path:(NSString *)path -{ - if (_valid) { - self->_reactInstance->registerSegment(static_cast([segmentId unsignedIntValue]), path.UTF8String); - } -} - -#pragma mark - Private - -- (void)loadJSBundle:(NSURL *)sourceURL FB_OBJC_DIRECT -{ -#if (RCT_DEV | RCT_ENABLE_LOADING_VIEW) && __has_include() +#if RCT_DEV_MENU && __has_include() { id loadingView = (id)[_turboModuleManager moduleForName:"DevLoadingView"]; @@ -326,7 +346,6 @@ - (void)loadJSBundle:(NSURL *)sourceURL FB_OBJC_DIRECT } #endif - __weak RCTPerformanceLogger *weakPerformanceLogger = _performanceLogger; __weak __typeof(self) weakSelf = self; [RCTJavaScriptLoader loadBundleAtURL:sourceURL onProgress:^(RCTLoadingProgress *progressData) { @@ -335,7 +354,7 @@ - (void)loadJSBundle:(NSURL *)sourceURL FB_OBJC_DIRECT return; } -#if (RCT_DEV | RCT_ENABLE_LOADING_VIEW) && __has_include() +#if RCT_DEV_MENU && __has_include() id loadingView = (id)[strongSelf->_turboModuleManager moduleForName:"DevLoadingView"]; [loadingView updateProgress:progressData]; @@ -353,26 +372,26 @@ - (void)loadJSBundle:(NSURL *)sourceURL FB_OBJC_DIRECT [strongSelf invalidate]; return; } - // DevSettings module is needed by loadScriptFromSource's callback so prior initialization is required + // DevSettings module is needed by _loadScriptFromSource's callback so prior initialization is required RCTDevSettings *const devSettings = (RCTDevSettings *)[strongSelf->_turboModuleManager moduleForName:"DevSettings"]; - [strongSelf loadScriptFromSource:source]; + [strongSelf _loadScriptFromSource:source]; // Set up hot module reloading in Dev only. - [weakPerformanceLogger markStopForTag:RCTPLScriptDownload]; + [strongSelf->_performanceLogger markStopForTag:RCTPLScriptDownload]; [devSettings setupHMRClientWithBundleURL:sourceURL]; }]; } -- (void)loadScriptFromSource:(RCTSource *)source FB_OBJC_DIRECT +- (void)_loadScriptFromSource:(RCTSource *)source FB_OBJC_DIRECT { - std::lock_guard lock(self->_invalidationMutex); + std::lock_guard lock(_invalidationMutex); if (!_valid) { return; } auto script = std::make_unique(source.data); const auto *url = deriveSourceURL(source.url).UTF8String; - self->_reactInstance->loadScript(std::move(script), url); + _reactInstance->loadScript(std::move(script), url); [[NSNotificationCenter defaultCenter] postNotificationName:@"RCTInstanceDidLoadBundle" object:nil]; if (_onInitialBundleLoad) { @@ -381,7 +400,7 @@ - (void)loadScriptFromSource:(RCTSource *)source FB_OBJC_DIRECT } } -- (void)notifyEventDispatcherObserversOfEvent_DEPRECATED:(NSNotification *)notification +- (void)_notifyEventDispatcherObserversOfEvent_DEPRECATED:(NSNotification *)notification { NSDictionary *userInfo = notification.userInfo; id event = [userInfo objectForKey:@"event"]; @@ -394,32 +413,9 @@ - (void)notifyEventDispatcherObserversOfEvent_DEPRECATED:(NSNotification *)notif } } -- (void)invalidate +- (void)_handleJSErrorMap:(facebook::react::MapBuffer)errorMap { - std::lock_guard lock(self->_invalidationMutex); - self->_valid = false; - - [_surfacePresenter suspend]; - [_jsThreadManager dispatchToJSThread:^{ - /** - * Every TurboModule is invalidated on its own method queue. - * TurboModuleManager invalidate blocks the calling thread until all TurboModules are invalidated. - */ - [self->_turboModuleManager invalidate]; - - // Clean up all the Resources - self->_reactInstance = nullptr; - self->_jsEngineInstance = nullptr; - self->_appTMMDelegate = nil; - self->_delegate = nil; - self->_displayLink = nil; - - self->_turboModuleManager = nil; - self->_performanceLogger = nil; - - // Terminate the JavaScript thread, so that no other work executes after this block. - self->_jsThreadManager = nil; - }]; + [_delegate instance:self didReceiveErrorMap:std::move(errorMap)]; } @end diff --git a/packages/react-native/ReactCommon/react/bridgeless/tests/hermes/ReactInstanceTest.cpp b/packages/react-native/ReactCommon/react/bridgeless/tests/hermes/ReactInstanceTest.cpp index 63a5ccc79fca6f..ca3f34f14d35d9 100644 --- a/packages/react-native/ReactCommon/react/bridgeless/tests/hermes/ReactInstanceTest.cpp +++ b/packages/react-native/ReactCommon/react/bridgeless/tests/hermes/ReactInstanceTest.cpp @@ -12,9 +12,9 @@ #include #include -#include #include #include +#include #include using ::testing::_; diff --git a/packages/react-native/ReactCommon/react/bridging/Bridging.h b/packages/react-native/ReactCommon/react/bridging/Bridging.h index 26cf99b5208302..b8a02290d1aee1 100644 --- a/packages/react-native/ReactCommon/react/bridging/Bridging.h +++ b/packages/react-native/ReactCommon/react/bridging/Bridging.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include diff --git a/packages/react-native/ReactCommon/react/bridging/Dynamic.h b/packages/react-native/ReactCommon/react/bridging/Dynamic.h new file mode 100644 index 00000000000000..be9555b49d594c --- /dev/null +++ b/packages/react-native/ReactCommon/react/bridging/Dynamic.h @@ -0,0 +1,26 @@ +/* + * 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. + */ + +#pragma once + +#include +#include + +namespace facebook::react { + +template <> +struct Bridging { + static folly::dynamic fromJs(jsi::Runtime &rt, const jsi::Value &value) { + return jsi::dynamicFromValue(rt, value); + } + + static jsi::Value toJs(jsi::Runtime &rt, const folly::dynamic &value) { + return jsi::valueFromDynamic(rt, value); + } +}; + +} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/bridging/tests/BridgingTest.cpp b/packages/react-native/ReactCommon/react/bridging/tests/BridgingTest.cpp index 995bce42e62d2a..6d739619f90df5 100644 --- a/packages/react-native/ReactCommon/react/bridging/tests/BridgingTest.cpp +++ b/packages/react-native/ReactCommon/react/bridging/tests/BridgingTest.cpp @@ -532,4 +532,90 @@ TEST_F(BridgingTest, supportTest) { EXPECT_FALSE((bridging::supportsToJs, jsi::Function>)); } +TEST_F(BridgingTest, dynamicTest) { + // Null + auto nullFromJsResult = + bridging::fromJs(rt, jsi::Value::null(), invoker); + EXPECT_TRUE(nullFromJsResult.isNull()); + + auto nullToJsResult = bridging::toJs(rt, nullptr, invoker); + EXPECT_TRUE(nullToJsResult.isNull()); + + // Boolean + auto booleanFromJsResult = + bridging::fromJs(rt, jsi::Value(true), invoker); + EXPECT_TRUE(booleanFromJsResult.isBool()); + EXPECT_TRUE(booleanFromJsResult.asBool()); + + auto booleanToJsResult = bridging::toJs(rt, true, invoker); + EXPECT_TRUE(booleanToJsResult.isBool()); + EXPECT_TRUE(booleanToJsResult.asBool()); + + // Number + auto numberFromJsResult = + bridging::fromJs(rt, jsi::Value(1.2), invoker); + EXPECT_TRUE(numberFromJsResult.isNumber()); + EXPECT_DOUBLE_EQ(1.2, numberFromJsResult.asDouble()); + + auto numberToJsResult = bridging::toJs(rt, 1.2, invoker); + EXPECT_TRUE(numberToJsResult.isNumber()); + EXPECT_DOUBLE_EQ(1.2, numberToJsResult.asNumber()); + + // String + auto stringFromJsResult = bridging::fromJs( + rt, jsi::Value(jsi::String::createFromAscii(rt, "hello")), invoker); + EXPECT_TRUE(stringFromJsResult.isString()); + EXPECT_EQ("hello"s, stringFromJsResult.asString()); + + auto stringToJsResult = bridging::toJs(rt, "hello", invoker); + EXPECT_TRUE(stringToJsResult.isString()); + EXPECT_EQ("hello"s, stringToJsResult.asString(rt).utf8(rt)); + + // Array + auto arrayFromJsResult = bridging::fromJs( + rt, + jsi::Value(jsi::Array::createWithElements(rt, "foo", "bar")), + invoker); + EXPECT_TRUE(arrayFromJsResult.isArray()); + EXPECT_EQ(2, arrayFromJsResult.size()); + EXPECT_EQ("foo"s, arrayFromJsResult[0].asString()); + EXPECT_EQ("bar"s, arrayFromJsResult[1].asString()); + + auto arrayToJsResult = bridging::toJs( + rt, folly::dynamic::array("foo", "bar"), invoker); + EXPECT_TRUE(arrayToJsResult.isObject()); + EXPECT_TRUE(arrayToJsResult.asObject(rt).isArray(rt)); + auto arrayToJsResultArray = arrayToJsResult.asObject(rt).asArray(rt); + EXPECT_EQ(2, arrayToJsResultArray.size(rt)); + EXPECT_EQ( + "foo"s, + arrayToJsResultArray.getValueAtIndex(rt, 0).asString(rt).utf8(rt)); + EXPECT_EQ( + "bar"s, + arrayToJsResultArray.getValueAtIndex(rt, 1).asString(rt).utf8(rt)); + + // Object + auto jsiObject = jsi::Object(rt); + jsiObject.setProperty(rt, "foo", "bar"); + auto objectFromJsResult = bridging::fromJs( + rt, jsi::Value(std::move(jsiObject)), invoker); + + EXPECT_TRUE(objectFromJsResult.isObject()); + EXPECT_EQ(1, objectFromJsResult.size()); + EXPECT_EQ("bar"s, objectFromJsResult["foo"].asString()); + + auto objectToJsResult = bridging::toJs( + rt, folly::dynamic::object("foo", "bar"), invoker); + EXPECT_TRUE(objectToJsResult.isObject()); + auto objectToJsResultObject = objectToJsResult.asObject(rt); + EXPECT_EQ( + "bar"s, + objectToJsResultObject.getProperty(rt, "foo").asString(rt).utf8(rt)); + + // Undefined + auto undefinedFromJsResult = + bridging::fromJs(rt, jsi::Value::undefined(), invoker); + EXPECT_TRUE(undefinedFromJsResult.isNull()); +} + } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.cpp b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.cpp index e85c253cdf847a..e7039b5850934b 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.cpp @@ -68,6 +68,12 @@ static void defineReadOnlyGlobal( jsi::Runtime &runtime, std::string propName, jsi::Value &&value) { + if (runtime.global().hasProperty(runtime, propName.c_str())) { + throw jsi::JSError( + runtime, + "Tried to redefine read-only global \"" + propName + + "\", but read-only globals can only be defined once."); + } jsi::Object jsObject = runtime.global().getProperty(runtime, "Object").asObject(runtime); jsi::Function defineProperty = jsObject.getProperty(runtime, "defineProperty") diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.h b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.h new file mode 100644 index 00000000000000..914153bff44e86 --- /dev/null +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.h @@ -0,0 +1,95 @@ +/* + * 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. + */ + +#pragma once + +#import +#import + +#import +#import + +#import "RCTTurboModule.h" + +namespace facebook { +namespace react { + +class JSI_EXPORT ObjCInteropTurboModule : public ObjCTurboModule { + public: + struct MethodDescriptor { + std::string methodName; + SEL selector; + int jsArgCount; + TurboModuleMethodValueKind jsReturnKind; + }; + + ObjCInteropTurboModule(const ObjCTurboModule::InitParams ¶ms); + + std::vector getPropertyNames(facebook::jsi::Runtime &runtime) override; + + protected: + jsi::Value create(jsi::Runtime &runtime, const jsi::PropNameID &propName) override; + + /** + * Why is this overriden? + * + * Purpose: Converts native module method returns from Objective C values to JavaScript values. + * + * ObjCTurboModule converts returns by returnType. But, Legacy native modules convert returns by the Objective C type: + * React Native cannot infer a method's returnType from the RCT_EXPORT_METHOD annotations. + */ + jsi::Value convertReturnIdToJSIValue( + jsi::Runtime &runtime, + const char *methodName, + TurboModuleMethodValueKind returnType, + id result) override; + + /** + * Why is this overriden? + * + * Purpose: Get a native module method's argument's type, given the method name, and argument index. + * + * This override is meant to serve as a performance optimization. + * + * ObjCTurboModule computes the method argument types from the RCT_EXPORT_METHOD macros lazily. + * ObjCInteropTurboModule computes all the method argument types eagerly on module init. + * + * ObjCInteropTurboModule overrides getArgumentTypeName, so ObjCTurboModule doesn't end up re-computing the argument + * type names again. + */ + NSString *getArgumentTypeName(jsi::Runtime &runtime, NSString *methodName, int argIndex) override; + + /** + * Why is this overriden? + * + * Purpose: Convert arguments from JavaScript values to Objective C values. Assign the Objective C argument to the + * method invocation. + * + * ObjCTurboModule tries to minimize reliance on RCTConvert for argument conversion. Why: RCTConvert relies on the + * RCT_EXPORT_METHOD macros, which we want to remove long term. But, Legacy native modules rely heavily on RCTConvert + * for argument conversion. + */ + void setInvocationArg( + jsi::Runtime &runtime, + const char *methodName, + const std::string &objCArgType, + const jsi::Value &arg, + size_t i, + NSInvocation *inv, + NSMutableArray *retainedObjectsForInvocation) override; + + private: + std::vector methodDescriptors_; + NSDictionary *> *methodArgumentTypeNames_; + jsi::Value constantsCache_; + + const jsi::Value &getConstants(jsi::Runtime &runtime); + bool exportsConstants(); +}; + +} // namespace react +} // namespace facebook diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.mm b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.mm new file mode 100644 index 00000000000000..9bd3395d37d1f7 --- /dev/null +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.mm @@ -0,0 +1,654 @@ +/* + * 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. + */ + +#include "RCTInteropTurboModule.h" + +#import +#import + +#import +#import +#import +#import +#import +#import + +namespace facebook { +namespace react { + +namespace { + +// This is used for generating short exception strings. +std::string getType(jsi::Runtime &rt, const jsi::Value &v) +{ + if (v.isUndefined()) { + return "undefined"; + } else if (v.isNull()) { + return "null"; + } else if (v.isBool()) { + return v.getBool() ? "true" : "false"; + } else if (v.isNumber()) { + return "number"; + } else if (v.isString()) { + return "string"; + } else if (v.isSymbol()) { + return "symbol"; + } else if (v.isBigInt()) { + return "bigint"; + } else if (v.isObject()) { + jsi::Object vObj = v.getObject(rt); + return vObj.isFunction(rt) ? "function" : vObj.isArray(rt) ? "array" : "object"; + } else { + return "unknown"; + } +} + +std::vector getMethodInfos(Class moduleClass) +{ + std::vector methodInfos; + + Class cls = moduleClass; + while (cls && cls != [NSObject class] && cls != [NSProxy class]) { + unsigned int methodCount; + Method *methods = class_copyMethodList(object_getClass(cls), &methodCount); + + for (unsigned int i = 0; i < methodCount; i++) { + Method method = methods[i]; + SEL selector = method_getName(method); + if ([NSStringFromSelector(selector) hasPrefix:@"__rct_export__"]) { + IMP imp = method_getImplementation(method); + const RCTMethodInfo *methodInfo = ((const RCTMethodInfo *(*)(id, SEL))imp)(moduleClass, selector); + methodInfos.push_back(methodInfo); + } + } + + free(methods); + cls = class_getSuperclass(cls); + } + + return methodInfos; +} + +NSString *getJSMethodName(const RCTMethodInfo *methodInfo) +{ + std::string jsName = methodInfo->jsName; + if (jsName != "") { + return @(jsName.c_str()); + } + + NSString *methodName = @(methodInfo->objcName); + NSRange colonRange = [methodName rangeOfString:@":"]; + if (colonRange.location != NSNotFound) { + methodName = [methodName substringToIndex:colonRange.location]; + } + methodName = [methodName stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + RCTAssert( + methodName.length, + @"%s is not a valid JS function name, please" + " supply an alternative using RCT_REMAP_METHOD()", + methodInfo->objcName); + + return methodName; +} + +class ObjCInteropTurboModuleParseException : public std::runtime_error { + public: + ObjCInteropTurboModuleParseException(std::string moduleName, std::string methodName, std::string message) + : std::runtime_error( + "Failed to create module \"" + moduleName + "\": Error while parsing method " + moduleName + "." + + methodName + ": " + message) + { + } +}; + +struct ExportedMethod { + NSString *methodName; + NSArray *argumentTypes; + std::string returnType; + SEL selector; +}; + +std::vector parseExportedMethods(std::string moduleName, Class moduleClass) +{ + std::vector methodInfos = getMethodInfos(moduleClass); + std::vector methods; + methods.reserve(methodInfos.size()); + + for (const RCTMethodInfo *methodInfo : methodInfos) { + NSString *jsMethodName = getJSMethodName(methodInfo); + NSArray *arguments; + SEL objCMethodSelector = NSSelectorFromString(RCTParseMethodSignature(methodInfo->objcName, &arguments)); + NSMethodSignature *objCMethodSignature = [moduleClass instanceMethodSignatureForSelector:objCMethodSelector]; + std::string objCMethodReturnType = [objCMethodSignature methodReturnType]; + + if (objCMethodSignature.numberOfArguments - 2 != [arguments count]) { + std::string message = "Parsed argument count (i.e: " + std::to_string([arguments count]) + + ") != Objective C method signature argument count (i.e: " + + std::to_string(objCMethodSignature.numberOfArguments - 2) + ")."; + throw ObjCInteropTurboModuleParseException(moduleName, [jsMethodName UTF8String], message); + } + + NSMutableArray *argumentTypes = [NSMutableArray new]; + for (NSUInteger i = 0; i < [arguments count]; i += 1) { + [argumentTypes addObject:arguments[i].type]; + } + + if ([argumentTypes count] == 1) { + std::string lastArgType = [argumentTypes[[argumentTypes count] - 1] UTF8String]; + if (lastArgType == "RCTPromiseResolveBlock" || lastArgType == "RCTPromiseRejectBlock") { + std::string message = + "Methods that return promises must accept a RCTPromiseResolveBlock followed by a RCTPromiseRejectBlock. This method just accepts a " + + lastArgType + "."; + throw ObjCInteropTurboModuleParseException(moduleName, [jsMethodName UTF8String], message); + } + } else if ([argumentTypes count] > 1) { + std::string lastArgType = [argumentTypes[[argumentTypes count] - 1] UTF8String]; + std::string secondLastArgType = [argumentTypes[[argumentTypes count] - 2] UTF8String]; + if ((secondLastArgType == "RCTPromiseResolveBlock" && lastArgType != "RCTPromiseRejectBlock") || + (secondLastArgType != "RCTPromiseResolveBlock" && lastArgType == "RCTPromiseRejectBlock")) { + std::string message = + "Methods that return promises must accept a RCTPromiseResolveBlock followed by a RCTPromiseRejectBlock. This method accepts a " + + secondLastArgType + " followed by a " + lastArgType + "."; + throw ObjCInteropTurboModuleParseException(moduleName, [jsMethodName UTF8String], message); + } + } + + methods.push_back( + {.methodName = jsMethodName, + .argumentTypes = argumentTypes, + .returnType = objCMethodReturnType, + .selector = objCMethodSelector}); + } + + return methods; +} + +SEL selectorForType(NSString *type) +{ + const char *input = type.UTF8String; + return NSSelectorFromString([RCTParseType(&input) stringByAppendingString:@":"]); +} + +template +T RCTConvertTo(SEL selector, id json) +{ + T (*convert)(id, SEL, id) = (__typeof__(convert))objc_msgSend; + return convert([RCTConvert class], selector, json); +} + +} // namespace + +ObjCInteropTurboModule::ObjCInteropTurboModule(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params), constantsCache_(jsi::Value::undefined()) +{ + std::vector methods = parseExportedMethods(name_, [params.instance class]); + methodDescriptors_.reserve(methods.size()); + + NSMutableDictionary *> *methodArgTypeNames = [NSMutableDictionary new]; + methodArgumentTypeNames_ = methodArgTypeNames; + + for (const ExportedMethod &method : methods) { + const int numArgs = [method.argumentTypes count]; + const bool isPromiseMethod = + numArgs >= 2 && [method.argumentTypes[numArgs - 1] isEqualToString:@"RCTPromiseRejectBlock"]; + + const int jsArgCount = isPromiseMethod ? numArgs - 2 : numArgs; + + /** + * In the TurboModule system, only promises and voids are special. So, set those. + * In the else case, just assume ObjectKind. This will be ignored by the interop layer. + * In the else case, the interop layer will just call into ::convertReturnIdToJSIValue() + */ + const TurboModuleMethodValueKind returnKind = isPromiseMethod ? PromiseKind + : method.returnType == @encode(void) ? VoidKind + : ObjectKind; + + methodMap_[[method.methodName UTF8String]] = MethodMetadata{static_cast(jsArgCount), nullptr}; + + for (NSUInteger i = 0; i < numArgs; i += 1) { + NSString *typeName = method.argumentTypes[i]; + + if ([typeName hasPrefix:@"JS::"]) { + NSString *rctCxxConvertSelector = + [[typeName stringByReplacingOccurrencesOfString:@"::" withString:@"_"] stringByAppendingString:@":"]; + setMethodArgConversionSelector(method.methodName, i, rctCxxConvertSelector); + } + } + + methodArgTypeNames[method.methodName] = method.argumentTypes; + methodDescriptors_.push_back({ + .methodName = [method.methodName UTF8String], + .selector = method.selector, + .jsArgCount = jsArgCount, + .jsReturnKind = returnKind, + }); + } + + if ([params.instance respondsToSelector:@selector(constantsToExport)]) { + methodDescriptors_.push_back({ + .methodName = "getConstants", .selector = @selector(constantsToExport), .jsArgCount = 0, + .jsReturnKind = ObjectKind, + }); + } else { + static SEL getConstantsSelector = NSSelectorFromString(@"getConstants"); + if ([params.instance respondsToSelector:getConstantsSelector]) { + methodDescriptors_.push_back({ + .methodName = "getConstants", + .selector = getConstantsSelector, + .jsArgCount = 0, + .jsReturnKind = ObjectKind, + }); + } + } +} + +jsi::Value ObjCInteropTurboModule::create(jsi::Runtime &runtime, const jsi::PropNameID &propName) +{ + for (size_t i = 0; i < methodDescriptors_.size(); i += 1) { + if (methodDescriptors_[i].methodName == propName.utf8(runtime)) { + if (propName.utf8(runtime) == "getConstants") { + return jsi::Function::createFromHostFunction( + runtime, + propName, + static_cast(methodDescriptors_[i].jsArgCount), + [this, i](jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, size_t count) mutable { + if (!this->constantsCache_.isUndefined()) { + return jsi::Value(rt, this->constantsCache_); + } + + // TODO: Dispatch getConstants to the main queue, if the module requires main queue setup + jsi::Value ret = this->invokeObjCMethod( + rt, + this->methodDescriptors_[i].jsReturnKind, + this->methodDescriptors_[i].methodName, + this->methodDescriptors_[i].selector, + args, + count); + + bool isRetValid = ret.isUndefined() || ret.isNull() || + (ret.isObject() && !ret.asObject(rt).isFunction(rt) && !ret.asObject(rt).isArray(rt)); + + if (!isRetValid) { + std::string methodJsSignature = name_ + ".getConstants()"; + std::string errorPrefix = methodJsSignature + ": "; + throw jsi::JSError( + rt, + errorPrefix + "Expected return value to be null, undefined, or a plain object. But, got: " + + getType(rt, ret)); + } + + if (ret.isUndefined() || ret.isNull()) { + this->constantsCache_ = jsi::Object(rt); + } else { + this->constantsCache_ = jsi::Value(rt, ret); + } + + return ret; + }); + } + + return jsi::Function::createFromHostFunction( + runtime, + propName, + static_cast(methodDescriptors_[i].jsArgCount), + [this, i](jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, size_t count) { + return this->invokeObjCMethod( + rt, + this->methodDescriptors_[i].jsReturnKind, + this->methodDescriptors_[i].methodName, + this->methodDescriptors_[i].selector, + args, + count); + }); + } + } + + jsi::Object constants = getConstants(runtime).asObject(runtime); + jsi::Value constant = constants.getProperty(runtime, propName); + + if (!constant.isUndefined()) { + // TODO(T145105887): Output warning. Tried to access a constant as a + // property on the native module object. Please migrate to getConstants(). + } + + return constant; +} + +void ObjCInteropTurboModule::setInvocationArg( + jsi::Runtime &runtime, + const char *methodNameCStr, + const std::string &objCArgType, + const jsi::Value &jsiArg, + size_t index, + NSInvocation *inv, + NSMutableArray *retainedObjectsForInvocation) +{ + NSString *methodName = @(methodNameCStr); + std::string methodJsSignature = name_ + "." + methodNameCStr + "()"; + + NSString *argumentType = getArgumentTypeName(runtime, methodName, index); + std::string errorPrefix = methodJsSignature + ": Error while converting JavaScript argument " + + std::to_string(index) + " to Objective C type " + [argumentType UTF8String] + ". "; + + SEL selector = selectorForType(argumentType); + + if ([RCTConvert respondsToSelector:selector]) { + id objCArg = TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_); + + if (objCArgType == @encode(char)) { + char arg = RCTConvertTo(selector, objCArg); + [inv setArgument:&arg atIndex:(index) + 2]; + return; + } + + if (objCArgType == @encode(unsigned char)) { + unsigned char arg = RCTConvertTo(selector, objCArg); + [inv setArgument:&arg atIndex:(index) + 2]; + return; + } + + if (objCArgType == @encode(short)) { + short arg = RCTConvertTo(selector, objCArg); + [inv setArgument:&arg atIndex:(index) + 2]; + return; + } + + if (objCArgType == @encode(unsigned short)) { + unsigned short arg = RCTConvertTo(selector, objCArg); + [inv setArgument:&arg atIndex:(index) + 2]; + return; + } + + if (objCArgType == @encode(int)) { + int arg = RCTConvertTo(selector, objCArg); + [inv setArgument:&arg atIndex:(index) + 2]; + return; + } + + if (objCArgType == @encode(unsigned int)) { + unsigned int arg = RCTConvertTo(selector, objCArg); + [inv setArgument:&arg atIndex:(index) + 2]; + return; + } + + if (objCArgType == @encode(long)) { + long arg = RCTConvertTo(selector, objCArg); + [inv setArgument:&arg atIndex:(index) + 2]; + return; + } + + if (objCArgType == @encode(unsigned long)) { + unsigned long arg = RCTConvertTo(selector, objCArg); + [inv setArgument:&arg atIndex:(index) + 2]; + return; + } + + if (objCArgType == @encode(long long)) { + long long arg = RCTConvertTo(selector, objCArg); + [inv setArgument:&arg atIndex:(index) + 2]; + return; + } + + if (objCArgType == @encode(unsigned long long)) { + unsigned long long arg = RCTConvertTo(selector, objCArg); + [inv setArgument:&arg atIndex:(index) + 2]; + return; + } + + if (objCArgType == @encode(float)) { + float arg = RCTConvertTo(selector, objCArg); + [inv setArgument:&arg atIndex:(index) + 2]; + return; + } + + if (objCArgType == @encode(double)) { + double arg = RCTConvertTo(selector, objCArg); + [inv setArgument:&arg atIndex:(index) + 2]; + return; + } + + if (objCArgType == @encode(BOOL)) { + BOOL arg = RCTConvertTo(selector, objCArg); + [inv setArgument:&arg atIndex:(index) + 2]; + return; + } + + if (objCArgType == @encode(SEL)) { + SEL arg = RCTConvertTo(selector, objCArg); + [inv setArgument:&arg atIndex:(index) + 2]; + return; + } + + if (objCArgType == @encode(const char *)) { + const char *arg = RCTConvertTo(selector, objCArg); + [inv setArgument:&arg atIndex:(index) + 2]; + return; + } + + if (objCArgType == @encode(void *)) { + void *arg = RCTConvertTo(selector, objCArg); + [inv setArgument:&arg atIndex:(index) + 2]; + return; + } + + if (objCArgType == @encode(id)) { + id arg = RCTConvertTo(selector, objCArg); + if (arg) { + [retainedObjectsForInvocation addObject:arg]; + } + [inv setArgument:&arg atIndex:(index) + 2]; + return; + } + + if (objCArgType[0] == _C_STRUCT_B) { + NSMethodSignature *typeSignature = [RCTConvert methodSignatureForSelector:selector]; + NSInvocation *typeInvocation = [NSInvocation invocationWithMethodSignature:typeSignature]; + typeInvocation.selector = selector; + typeInvocation.target = [RCTConvert class]; + + void *returnValue = malloc(typeSignature.methodReturnLength); + if (!returnValue) { + // CWE - 391 : Unchecked error condition + // https://www.cvedetails.com/cwe-details/391/Unchecked-Error-Condition.html + // https://eli.thegreenplace.net/2009/10/30/handling-out-of-memory-conditions-in-c + abort(); + } + [typeInvocation setArgument:&objCArg atIndex:2]; + [typeInvocation invoke]; + + [typeInvocation getReturnValue:returnValue]; + [inv setArgument:returnValue atIndex:index + 2]; + free(returnValue); + return; + } + + const char *BLOCK_TYPE = @encode(__typeof__(^{ + })); + + if (objCArgType == BLOCK_TYPE) { + /** + * RCTModuleMethod doesn't actually call into RCTConvert in this case. + */ + id arg = [objCArg copy]; + if (arg) { + [retainedObjectsForInvocation addObject:arg]; + } + [inv setArgument:&arg atIndex:(index) + 2]; + return; + } + + throw jsi::JSError(runtime, errorPrefix + "Objective C type " + [argumentType UTF8String] + " is unsupported."); + } + + if ([argumentType isEqualToString:@"RCTResponseSenderBlock"]) { + if (!(jsiArg.isObject() && jsiArg.asObject(runtime).isFunction(runtime))) { + throw jsi::JSError( + runtime, errorPrefix + "JavaScript argument must be a function. Got " + getType(runtime, jsiArg)); + } + + RCTResponseSenderBlock arg = + (RCTResponseSenderBlock)TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_); + if (arg) { + [retainedObjectsForInvocation addObject:arg]; + } + [inv setArgument:&arg atIndex:(index) + 2]; + return; + } + + if ([argumentType isEqualToString:@"RCTResponseErrorBlock"]) { + if (!(jsiArg.isObject() && jsiArg.asObject(runtime).isFunction(runtime))) { + throw jsi::JSError( + runtime, errorPrefix + "JavaScript argument must be a function. Got " + getType(runtime, jsiArg)); + } + + RCTResponseSenderBlock senderBlock = + (RCTResponseSenderBlock)TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_); + RCTResponseErrorBlock arg = ^(NSError *error) { + senderBlock(@[ RCTJSErrorFromNSError(error) ]); + }; + [retainedObjectsForInvocation addObject:arg]; + [inv setArgument:&arg atIndex:(index) + 2]; + return; + } + + if ([argumentType isEqualToString:@"RCTPromiseResolveBlock"] || + [argumentType isEqualToString:@"RCTPromiseRejectBlock"]) { + throw jsi::JSError( + runtime, + errorPrefix + "The TurboModule interop layer should not convert JavaScript arguments to " + + [argumentType UTF8String] + + " inside ObjCinteropTurboModule::setInvocationArg(). Please report this as an issue."); + } + + if ([argumentType hasPrefix:@"JS::"]) { + NSString *selectorNameForCxxType = + [[argumentType stringByReplacingOccurrencesOfString:@"::" withString:@"_"] stringByAppendingString:@":"]; + selector = NSSelectorFromString(selectorNameForCxxType); + + bool isPlainObject = jsiArg.isObject() && !jsiArg.asObject(runtime).isFunction(runtime) && + !jsiArg.asObject(runtime).isArray(runtime); + if (!isPlainObject) { + throw jsi::JSError( + runtime, errorPrefix + "JavaScript argument must be a plain object. Got " + getType(runtime, jsiArg)); + } + + id arg = TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_); + + RCTManagedPointer *(*convert)(id, SEL, id) = (__typeof__(convert))objc_msgSend; + RCTManagedPointer *box = convert([RCTCxxConvert class], selector, arg); + + void *pointer = box.voidPointer; + [inv setArgument:&pointer atIndex:index + 2]; + [retainedObjectsForInvocation addObject:box]; + return; + } +} + +jsi::Value ObjCInteropTurboModule::convertReturnIdToJSIValue( + jsi::Runtime &runtime, + const char *methodNameCStr, + TurboModuleMethodValueKind returnType, + id result) +{ + std::string methodJsSignature = name_ + "." + methodNameCStr + "()"; + std::string errorPrefix = + methodJsSignature + ": Error while converting return Objective C value to JavaScript type. "; + + if (returnType == VoidKind) { + return jsi::Value::undefined(); + } + + if (result == (id)kCFNull || result == nil) { + return jsi::Value::null(); + } + + jsi::Value returnValue = TurboModuleConvertUtils::convertObjCObjectToJSIValue(runtime, result); + if (!returnValue.isUndefined()) { + return returnValue; + } + + throw jsi::JSError(runtime, methodJsSignature + "Objective C type was unsupported."); +} + +NSString *ObjCInteropTurboModule::getArgumentTypeName(jsi::Runtime &runtime, NSString *methodName, int argIndex) +{ + const char *methodNameCStr = [methodName UTF8String]; + std::string methodJsSignature = name_ + "." + methodNameCStr + "()"; + std::string errorPrefix = + methodJsSignature + ": Error while trying to get Objective C type of parameter " + std::to_string(argIndex) + "."; + + if (methodArgumentTypeNames_[methodName] == nil) { + throw jsi::JSError(runtime, errorPrefix + "No parameter types found for method."); + } + + if ([methodArgumentTypeNames_[methodName] count] <= argIndex) { + int paramCount = [methodArgumentTypeNames_[methodName] count]; + throw jsi::JSError(runtime, errorPrefix + "Method has only " + std::to_string(paramCount) + " parameter types."); + } + + return methodArgumentTypeNames_[methodName][argIndex]; +} + +bool ObjCInteropTurboModule::exportsConstants() +{ + for (size_t i = 0; i < methodDescriptors_.size(); i += 1) { + if (methodDescriptors_[i].methodName == "getConstants") { + return true; + } + } + + return false; +} + +const jsi::Value &ObjCInteropTurboModule::getConstants(jsi::Runtime &runtime) +{ + if (!constantsCache_.isUndefined()) { + return constantsCache_; + } + + if (!exportsConstants()) { + constantsCache_ = jsi::Object(runtime); + return constantsCache_; + } + + jsi::Value getConstantsProp = get(runtime, jsi::PropNameID::forAscii(runtime, "getConstants")); + + if (getConstantsProp.isObject()) { + jsi::Object getConstantsObj = getConstantsProp.asObject(runtime); + if (getConstantsObj.isFunction(runtime)) { + jsi::Function getConstantsFn = getConstantsObj.asFunction(runtime); + getConstantsFn.call(runtime); + return constantsCache_; + } + } + + // Unable to invoke the getConstants() method. + // Maybe the module didn't define a getConstants() method. + // Default constants to {}, so no constants are spread into the NativeModule + constantsCache_ = jsi::Object(runtime); + return constantsCache_; +} + +std::vector ObjCInteropTurboModule::getPropertyNames(facebook::jsi::Runtime &runtime) +{ + std::vector propNames = ObjCTurboModule::getPropertyNames(runtime); + + jsi::Object constants = getConstants(runtime).asObject(runtime); + jsi::Array constantNames = constants.getPropertyNames(runtime); + + for (size_t i = 0; i < constantNames.size(runtime); i += 1) { + jsi::Value constantName = constantNames.getValueAtIndex(runtime, i); + if (constantName.isString()) { + propNames.push_back(jsi::PropNameID::forString(runtime, constantName.asString(runtime))); + } + } + + return propNames; +} + +} // namespace react +} // namespace facebook diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h index b971372e9b837d..5b91c5b949da05 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h @@ -28,6 +28,11 @@ namespace facebook::react { class CallbackWrapper; class Instance; +namespace TurboModuleConvertUtils { +jsi::Value convertObjCObjectToJSIValue(jsi::Runtime &runtime, id value); +id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr jsInvoker); +} + /** * ObjC++ specific TurboModule base class. */ @@ -36,7 +41,7 @@ class JSI_EXPORT ObjCTurboModule : public TurboModule { // TODO(T65603471): Should we unify this with a Fabric abstraction? struct InitParams { std::string moduleName; - id instance; + id instance; std::shared_ptr jsInvoker; std::shared_ptr nativeInvoker; bool isSyncModule; @@ -46,18 +51,63 @@ class JSI_EXPORT ObjCTurboModule : public TurboModule { jsi::Value invokeObjCMethod( jsi::Runtime &runtime, - TurboModuleMethodValueKind valueKind, + TurboModuleMethodValueKind returnType, const std::string &methodName, SEL selector, const jsi::Value *args, size_t count); - id instance_; + id instance_; std::shared_ptr nativeInvoker_; protected: void setMethodArgConversionSelector(NSString *methodName, int argIndex, NSString *fnName); + /** + * Why is this virtual? + * + * Purpose: Converts native module method returns from Objective C values to JavaScript values. + * + * ObjCTurboModule uses TurboModuleMethodValueKind to convert returns from Objective C values to JavaScript values. + * ObjCInteropTurboModule just blindly converts returns from Objective C values to JavaScript values by runtime type, + * because it cannot infer TurboModuleMethodValueKind from the RCT_EXPORT_METHOD annotations. + */ + virtual jsi::Value convertReturnIdToJSIValue( + jsi::Runtime &runtime, + const char *methodName, + TurboModuleMethodValueKind returnType, + id result); + + /** + * Why is this virtual? + * + * Purpose: Get a native module method's argument's type, given the method name, and argument index. + * + * ObjCInteropTurboModule computes the argument type names eagerly on module init. So, make this method virtual. That + * way, ObjCInteropTurboModule doesn't end up computing the argument types twice: once on module init, and second on + * method dispatch. + */ + virtual NSString *getArgumentTypeName(jsi::Runtime &runtime, NSString *methodName, int argIndex); + + /** + * Why is this virtual? + * + * Purpose: Convert arguments from JavaScript values to Objective C values. Assign the Objective C argument to the + * method invocation. + * + * ObjCInteropTurboModule relies heavily on RCTConvert to convert arguments from JavaScript values to Objective C + * values. ObjCTurboModule tries to minimize reliance on RCTConvert: RCTConvert uses the RCT_EXPORT_METHOD macros, + * which we want to remove long term from React Native. + */ + virtual void setInvocationArg( + jsi::Runtime &runtime, + const char *methodName, + const std::string &objCArgType, + const jsi::Value &arg, + size_t i, + NSInvocation *inv, + NSMutableArray *retainedObjectsForInvocation); + private: // Does the NativeModule dispatch async methods to the JS thread? const bool isSyncModule_; @@ -65,6 +115,8 @@ class JSI_EXPORT ObjCTurboModule : public TurboModule { /** * TODO(ramanpreet): * Investigate an optimization that'll let us get rid of this NSMutableDictionary. + * Perhaps, have the code-generated TurboModule subclass implement + * getMethodArgConversionSelector below. */ NSMutableDictionary *methodArgConversionSelectors_; NSDictionary *> *methodArgumentTypeNames_; @@ -72,18 +124,17 @@ class JSI_EXPORT ObjCTurboModule : public TurboModule { bool isMethodSync(TurboModuleMethodValueKind returnType); BOOL hasMethodArgConversionSelector(NSString *methodName, int argIndex); SEL getMethodArgConversionSelector(NSString *methodName, int argIndex); - NSString *getArgumentTypeName(NSString *methodName, int argIndex); - NSInvocation *getMethodInvocation( + NSInvocation *createMethodInvocation( jsi::Runtime &runtime, - TurboModuleMethodValueKind returnType, + bool isSync, const char *methodName, SEL selector, const jsi::Value *args, size_t count, NSMutableArray *retainedObjectsForInvocation); - jsi::Value performMethodInvocation( + id performMethodInvocation( jsi::Runtime &runtime, - TurboModuleMethodValueKind returnType, + bool isSync, const char *methodName, NSInvocation *inv, NSMutableArray *retainedObjectsForInvocation); diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm index 1bf1658dcf20c5..ce9a0ffcf3035d 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm @@ -29,6 +29,7 @@ using namespace facebook; using namespace facebook::react; +using namespace facebook::react::TurboModuleConvertUtils; static int32_t getUniqueId() { @@ -36,6 +37,10 @@ static int32_t getUniqueId() return counter++; } +namespace facebook { +namespace react { + +namespace TurboModuleConvertUtils { /** * All static helper functions are ObjC++ specific. */ @@ -54,7 +59,6 @@ static int32_t getUniqueId() return jsi::String::createFromUtf8(runtime, [value UTF8String] ?: ""); } -static jsi::Value convertObjCObjectToJSIValue(jsi::Runtime &runtime, id value); static jsi::Object convertNSDictionaryToJSIObject(jsi::Runtime &runtime, NSDictionary *value) { jsi::Object result = jsi::Object(runtime); @@ -82,7 +86,7 @@ static int32_t getUniqueId() return result; } -static jsi::Value convertObjCObjectToJSIValue(jsi::Runtime &runtime, id value) +jsi::Value convertObjCObjectToJSIValue(jsi::Runtime &runtime, id value) { if ([value isKindOfClass:[NSString class]]) { return convertNSStringToJSIString(runtime, (NSString *)value); @@ -101,8 +105,6 @@ static int32_t getUniqueId() return jsi::Value::undefined(); } -static id -convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr jsInvoker); static NSString *convertJSIStringToNSString(jsi::Runtime &runtime, const jsi::String &value) { return [NSString stringWithUTF8String:value.utf8(runtime).c_str()]; @@ -140,8 +142,7 @@ static int32_t getUniqueId() static RCTResponseSenderBlock convertJSIFunctionToCallback(jsi::Runtime &runtime, const jsi::Function &value, std::shared_ptr jsInvoker); -static id -convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr jsInvoker) +id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr jsInvoker) { if (value.isUndefined() || value.isNull()) { return nil; @@ -211,8 +212,6 @@ static int32_t getUniqueId() return [callback copy]; } -namespace facebook::react { - static jsi::Value createJSRuntimeError(jsi::Runtime &runtime, const std::string &message) { return runtime.global().getPropertyAsFunction(runtime, "Error").call(runtime, message); @@ -237,6 +236,8 @@ static int32_t getUniqueId() return {runtime, std::move(error)}; } +} + jsi::Value ObjCTurboModule::createPromise(jsi::Runtime &runtime, std::string methodName, PromiseInvocationBlock invoke) { if (!invoke) { @@ -373,28 +374,26 @@ static int32_t getUniqueId() * - ObjC module methods will be always be called from JS thread. * They may decide to dispatch to a different queue as needed. */ -jsi::Value ObjCTurboModule::performMethodInvocation( +id ObjCTurboModule::performMethodInvocation( jsi::Runtime &runtime, - TurboModuleMethodValueKind returnType, + bool isSync, const char *methodName, NSInvocation *inv, NSMutableArray *retainedObjectsForInvocation) { __block id result; - jsi::Runtime *rt = &runtime; - __weak id weakModule = instance_; + __weak id weakModule = instance_; const char *moduleName = name_.c_str(); std::string methodNameStr{methodName}; __block int32_t asyncCallCounter = 0; - bool wasMethodSync = isMethodSync(returnType); void (^block)() = ^{ - id strongModule = weakModule; + id strongModule = weakModule; if (!strongModule) { return; } - if (wasMethodSync) { + if (isSync) { TurboModulePerfLogger::syncMethodCallExecutionStart(moduleName, methodNameStr.c_str()); } else { TurboModulePerfLogger::asyncMethodCallExecutionStart(moduleName, methodNameStr.c_str(), asyncCallCounter); @@ -408,25 +407,35 @@ static int32_t getUniqueId() [retainedObjectsForInvocation removeAllObjects]; } - if (!wasMethodSync) { + if (!isSync) { TurboModulePerfLogger::asyncMethodCallExecutionEnd(moduleName, methodNameStr.c_str(), asyncCallCounter); return; } - TurboModulePerfLogger::syncMethodCallExecutionEnd(moduleName, methodNameStr.c_str()); - TurboModulePerfLogger::syncMethodCallReturnConversionStart(moduleName, methodNameStr.c_str()); - void *rawResult; [inv getReturnValue:&rawResult]; result = (__bridge id)rawResult; + TurboModulePerfLogger::syncMethodCallExecutionEnd(moduleName, methodNameStr.c_str()); }; - if (wasMethodSync) { + if (isSync) { block(); + return result; } else { asyncCallCounter = getUniqueId(); TurboModulePerfLogger::asyncMethodCallDispatch(moduleName, methodName); nativeInvoker_->invokeAsync([block]() -> void { block(); }); + return nil; + } +} + +jsi::Value ObjCTurboModule::convertReturnIdToJSIValue( + jsi::Runtime &runtime, + const char *methodName, + TurboModuleMethodValueKind returnType, + id result) +{ + if (returnType == VoidKind) { return jsi::Value::undefined(); } @@ -442,32 +451,31 @@ static int32_t getUniqueId() break; } case BooleanKind: { - returnValue = convertNSNumberToJSIBoolean(*rt, (NSNumber *)result); + returnValue = convertNSNumberToJSIBoolean(runtime, (NSNumber *)result); break; } case NumberKind: { - returnValue = convertNSNumberToJSINumber(*rt, (NSNumber *)result); + returnValue = convertNSNumberToJSINumber(runtime, (NSNumber *)result); break; } case StringKind: { - returnValue = convertNSStringToJSIString(*rt, (NSString *)result); + returnValue = convertNSStringToJSIString(runtime, (NSString *)result); break; } case ObjectKind: { - returnValue = convertNSDictionaryToJSIObject(*rt, (NSDictionary *)result); + returnValue = convertNSDictionaryToJSIObject(runtime, (NSDictionary *)result); break; } case ArrayKind: { - returnValue = convertNSArrayToJSIArray(*rt, (NSArray *)result); + returnValue = convertNSArrayToJSIArray(runtime, (NSArray *)result); break; } case FunctionKind: - throw std::runtime_error("convertInvocationResultToJSIValue: FunctionKind is not supported yet."); + throw std::runtime_error("convertReturnIdToJSIValue: FunctionKind is not supported yet."); case PromiseKind: - throw std::runtime_error("convertInvocationResultToJSIValue: PromiseKind wasn't handled properly."); + throw std::runtime_error("convertReturnIdToJSIValue: PromiseKind wasn't handled properly."); } - TurboModulePerfLogger::syncMethodCallReturnConversionEnd(moduleName, methodName); return returnValue; } @@ -482,7 +490,7 @@ static int32_t getUniqueId() * Note: This is only being introduced for backward compatibility. It will be removed * in the future. */ -NSString *ObjCTurboModule::getArgumentTypeName(NSString *methodName, int argIndex) +NSString *ObjCTurboModule::getArgumentTypeName(jsi::Runtime &runtime, NSString *methodName, int argIndex) { if (!methodArgumentTypeNames_) { NSMutableDictionary *> *methodArgumentTypeNames = [NSMutableDictionary new]; @@ -529,9 +537,109 @@ static int32_t getUniqueId() return nil; } -NSInvocation *ObjCTurboModule::getMethodInvocation( +void ObjCTurboModule::setInvocationArg( jsi::Runtime &runtime, - TurboModuleMethodValueKind returnType, + const char *methodName, + const std::string &objCArgType, + const jsi::Value &arg, + size_t i, + NSInvocation *inv, + NSMutableArray *retainedObjectsForInvocation) +{ + if (arg.isBool()) { + bool v = arg.getBool(); + + /** + * JS type checking ensures the Objective C argument here is either a BOOL or NSNumber*. + */ + if (objCArgType == @encode(id)) { + id objCArg = [NSNumber numberWithBool:v]; + [inv setArgument:(void *)&objCArg atIndex:i + 2]; + [retainedObjectsForInvocation addObject:objCArg]; + } else { + [inv setArgument:(void *)&v atIndex:i + 2]; + } + + return; + } + + if (arg.isNumber()) { + double v = arg.getNumber(); + + /** + * JS type checking ensures the Objective C argument here is either a double or NSNumber*. + */ + if (objCArgType == @encode(id)) { + id objCArg = [NSNumber numberWithDouble:v]; + [inv setArgument:(void *)&objCArg atIndex:i + 2]; + [retainedObjectsForInvocation addObject:objCArg]; + } else { + [inv setArgument:(void *)&v atIndex:i + 2]; + } + + return; + } + + /** + * Convert arg to ObjC objects. + */ + id objCArg = convertJSIValueToObjCObject(runtime, arg, jsInvoker_); + if (objCArg) { + NSString *methodNameNSString = @(methodName); + + /** + * Convert objects using RCTConvert. + */ + if (objCArgType == @encode(id)) { + NSString *argumentType = getArgumentTypeName(runtime, methodNameNSString, i); + if (argumentType != nil) { + NSString *rctConvertMethodName = [NSString stringWithFormat:@"%@:", argumentType]; + SEL rctConvertSelector = NSSelectorFromString(rctConvertMethodName); + + if ([RCTConvert respondsToSelector:rctConvertSelector]) { + // Message dispatch logic from old infra + id (*convert)(id, SEL, id) = (__typeof__(convert))objc_msgSend; + id convertedObjCArg = convert([RCTConvert class], rctConvertSelector, objCArg); + + [inv setArgument:(void *)&convertedObjCArg atIndex:i + 2]; + if (convertedObjCArg) { + [retainedObjectsForInvocation addObject:convertedObjCArg]; + } + return; + } + } + } + + /** + * Convert objects using RCTCxxConvert to structs. + */ + if ([objCArg isKindOfClass:[NSDictionary class]] && hasMethodArgConversionSelector(methodNameNSString, i)) { + SEL methodArgConversionSelector = getMethodArgConversionSelector(methodNameNSString, i); + + // Message dispatch logic from old infra (link: + // https://github.com/facebook/react-native/commit/6783694158057662fd7b11fc123c339b2b21bfe6#diff-263fc157dfce55895cdc16495b55d190R350) + RCTManagedPointer *(*convert)(id, SEL, id) = (__typeof__(convert))objc_msgSend; + RCTManagedPointer *box = convert([RCTCxxConvert class], methodArgConversionSelector, objCArg); + + void *pointer = box.voidPointer; + [inv setArgument:&pointer atIndex:i + 2]; + [retainedObjectsForInvocation addObject:box]; + return; + } + } + + /** + * Insert converted args unmodified. + */ + [inv setArgument:(void *)&objCArg atIndex:i + 2]; + if (objCArg) { + [retainedObjectsForInvocation addObject:objCArg]; + } +} + +NSInvocation *ObjCTurboModule::createMethodInvocation( + jsi::Runtime &runtime, + bool isSync, const char *methodName, SEL selector, const jsi::Value *args, @@ -539,9 +647,9 @@ static int32_t getUniqueId() NSMutableArray *retainedObjectsForInvocation) { const char *moduleName = name_.c_str(); - const id module = instance_; + const id module = instance_; - if (isMethodSync(returnType)) { + if (isSync) { TurboModulePerfLogger::syncMethodCallArgConversionStart(moduleName, methodName); } else { TurboModulePerfLogger::asyncMethodCallArgConversionStart(moduleName, methodName); @@ -554,101 +662,13 @@ static int32_t getUniqueId() NSMethodSignature *methodSignature = [[module class] instanceMethodSignatureForSelector:selector]; for (size_t i = 0; i < count; i++) { - const jsi::Value *arg = &args[i]; + const jsi::Value &arg = args[i]; const std::string objCArgType = [methodSignature getArgumentTypeAtIndex:i + 2]; - if (arg->isBool()) { - bool v = arg->getBool(); - - /** - * JS type checking ensures the Objective C argument here is either a BOOL or NSNumber*. - */ - if (objCArgType == @encode(id)) { - id objCArg = [NSNumber numberWithBool:v]; - [inv setArgument:(void *)&objCArg atIndex:i + 2]; - [retainedObjectsForInvocation addObject:objCArg]; - } else { - [inv setArgument:(void *)&v atIndex:i + 2]; - } - - continue; - } - - if (arg->isNumber()) { - double v = arg->getNumber(); - - /** - * JS type checking ensures the Objective C argument here is either a double or NSNumber*. - */ - if (objCArgType == @encode(id)) { - id objCArg = [NSNumber numberWithDouble:v]; - [inv setArgument:(void *)&objCArg atIndex:i + 2]; - [retainedObjectsForInvocation addObject:objCArg]; - } else { - [inv setArgument:(void *)&v atIndex:i + 2]; - } - - continue; - } - - /** - * Convert arg to ObjC objects. - */ - id objCArg = convertJSIValueToObjCObject(runtime, *arg, jsInvoker_); - if (objCArg) { - NSString *methodNameNSString = @(methodName); - - /** - * Convert objects using RCTConvert. - */ - if (objCArgType == @encode(id)) { - NSString *argumentType = getArgumentTypeName(methodNameNSString, i); - if (argumentType != nil) { - NSString *rctConvertMethodName = [NSString stringWithFormat:@"%@:", argumentType]; - SEL rctConvertSelector = NSSelectorFromString(rctConvertMethodName); - - if ([RCTConvert respondsToSelector:rctConvertSelector]) { - // Message dispatch logic from old infra - id (*convert)(id, SEL, id) = (__typeof__(convert))objc_msgSend; - id convertedObjCArg = convert([RCTConvert class], rctConvertSelector, objCArg); - - [inv setArgument:(void *)&convertedObjCArg atIndex:i + 2]; - if (convertedObjCArg) { - [retainedObjectsForInvocation addObject:convertedObjCArg]; - } - continue; - } - } - } - - /** - * Convert objects using RCTCxxConvert to structs. - */ - if ([objCArg isKindOfClass:[NSDictionary class]] && hasMethodArgConversionSelector(methodNameNSString, i)) { - SEL methodArgConversionSelector = getMethodArgConversionSelector(methodNameNSString, i); - - // Message dispatch logic from old infra (link: - // https://github.com/facebook/react-native/commit/6783694158057662fd7b11fc123c339b2b21bfe6#diff-263fc157dfce55895cdc16495b55d190R350) - RCTManagedPointer *(*convert)(id, SEL, id) = (__typeof__(convert))objc_msgSend; - RCTManagedPointer *box = convert([RCTCxxConvert class], methodArgConversionSelector, objCArg); - - void *pointer = box.voidPointer; - [inv setArgument:&pointer atIndex:i + 2]; - [retainedObjectsForInvocation addObject:box]; - continue; - } - } - - /** - * Insert converted args unmodified. - */ - [inv setArgument:(void *)&objCArg atIndex:i + 2]; - if (objCArg) { - [retainedObjectsForInvocation addObject:objCArg]; - } + setInvocationArg(runtime, methodName, objCArgType, arg, i, inv, retainedObjectsForInvocation); } - if (isMethodSync(returnType)) { + if (isSync) { TurboModulePerfLogger::syncMethodCallArgConversionEnd(moduleName, methodName); } else { TurboModulePerfLogger::asyncMethodCallArgConversionEnd(moduleName, methodName); @@ -688,25 +708,38 @@ static int32_t getUniqueId() } NSMutableArray *retainedObjectsForInvocation = [NSMutableArray arrayWithCapacity:count + 2]; - NSInvocation *inv = - getMethodInvocation(runtime, returnType, methodName, selector, args, count, retainedObjectsForInvocation); - - jsi::Value returnValue = returnType == PromiseKind - ? createPromise( - runtime, - methodNameStr, - ^(RCTPromiseResolveBlock resolveBlock, RCTPromiseRejectBlock rejectBlock) { - RCTPromiseResolveBlock resolveCopy = [resolveBlock copy]; - RCTPromiseRejectBlock rejectCopy = [rejectBlock copy]; - - [inv setArgument:(void *)&resolveCopy atIndex:count + 2]; - [inv setArgument:(void *)&rejectCopy atIndex:count + 3]; - [retainedObjectsForInvocation addObject:resolveCopy]; - [retainedObjectsForInvocation addObject:rejectCopy]; - // The return type becomes void in the ObjC side. - performMethodInvocation(runtime, VoidKind, methodName, inv, retainedObjectsForInvocation); - }) - : performMethodInvocation(runtime, returnType, methodName, inv, retainedObjectsForInvocation); + NSInvocation *inv = createMethodInvocation( + runtime, isMethodSync(returnType), methodName, selector, args, count, retainedObjectsForInvocation); + + jsi::Value returnValue = jsi::Value::undefined(); + + if (returnType == PromiseKind) { + returnValue = createPromise( + runtime, methodNameStr, ^(RCTPromiseResolveBlock resolveBlock, RCTPromiseRejectBlock rejectBlock) { + RCTPromiseResolveBlock resolveCopy = [resolveBlock copy]; + RCTPromiseRejectBlock rejectCopy = [rejectBlock copy]; + + [inv setArgument:(void *)&resolveCopy atIndex:count + 2]; + [inv setArgument:(void *)&rejectCopy atIndex:count + 3]; + [retainedObjectsForInvocation addObject:resolveCopy]; + [retainedObjectsForInvocation addObject:rejectCopy]; + // The return type becomes void in the ObjC side. + performMethodInvocation(runtime, isMethodSync(VoidKind), methodName, inv, retainedObjectsForInvocation); + }); + } else { + id result = + performMethodInvocation(runtime, isMethodSync(returnType), methodName, inv, retainedObjectsForInvocation); + + if (isMethodSync(returnType)) { + TurboModulePerfLogger::syncMethodCallReturnConversionStart(moduleName, methodName); + } + + returnValue = convertReturnIdToJSIValue(runtime, methodName, returnType, result); + + if (isMethodSync(returnType)) { + TurboModulePerfLogger::syncMethodCallReturnConversionEnd(moduleName, methodName); + } + } if (isMethodSync(returnType)) { TurboModulePerfLogger::syncMethodCallEnd(moduleName, methodName); @@ -751,4 +784,5 @@ static int32_t getUniqueId() methodArgConversionSelectors_[methodName][argIndex] = selectorValue; } +} } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.h b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.h index 23c8d93365adff..23aea9ac38b0bc 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.h +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.h @@ -38,6 +38,18 @@ RCT_EXTERN void RCTTurboModuleSetBindingMode(facebook::react::TurboModuleBinding jsInvoker: (std::shared_ptr)jsInvoker; +/** + * Return a pre-initialized list of leagcy native modules. + * These modules shouldn't be TurboModule-compatible (i.e: they should not conform to RCTTurboModule). + * + * This method is only used by the TurboModule interop layer. + * + * It must match the signature of RCTBridgeDelegate extraModulesForBridge: + * - (NSArray> *)extraModulesForBridge:(RCTBridge *)bridge; + */ +- (NSArray> *)extraModulesForBridge:(RCTBridge *)bridge + __attribute((deprecated("Please make all native modules returned from this method TurboModule-compatible."))); + @end @interface RCTTurboModuleManager : NSObject diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.mm b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.mm index 3295a3462b442a..4b8ab526f04404 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.mm +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.mm @@ -6,6 +6,7 @@ */ #import "RCTTurboModuleManager.h" +#import "RCTInteropTurboModule.h" #import #import @@ -38,7 +39,7 @@ void RCTTurboModuleSetBindingMode(TurboModuleBindingMode bindingMode) } /** - * A global variable whose address we use to associate method queues to id objects. + * A global variable whose address we use to associate method queues to id objects. */ static char kAssociatedMethodQueueKey; @@ -49,18 +50,17 @@ int32_t getUniqueId() return counter++; } -class TurboModuleHolder { +class ModuleHolder { private: const int32_t moduleId_; - id module_; + id module_; bool isTryingToCreateModule_; bool isDoneCreatingModule_; std::mutex mutex_; std::condition_variable cv_; public: - TurboModuleHolder() - : moduleId_(getUniqueId()), module_(nil), isTryingToCreateModule_(false), isDoneCreatingModule_(false) + ModuleHolder() : moduleId_(getUniqueId()), module_(nil), isTryingToCreateModule_(false), isDoneCreatingModule_(false) { } @@ -69,12 +69,12 @@ int32_t getModuleId() const return moduleId_; } - void setModule(id module) + void setModule(id module) { module_ = module; } - id getModule() const + id getModule() const { return module_; } @@ -167,18 +167,22 @@ @implementation RCTTurboModuleManager { * We need to come up with a mechanism to allow modules to specify whether * they want to be long-lived or short-lived. * - * All instances of TurboModuleHolder are owned by the _turboModuleHolders map. - * We only reference TurboModuleHolders via pointers to entries in the _turboModuleHolders map. + * All instances of ModuleHolder are owned by the _moduleHolders map. + * We only reference ModuleHolders via pointers to entries in the _moduleHolders map. */ - std::unordered_map _turboModuleHolders; + std::unordered_map _moduleHolders; std::unordered_map> _turboModuleCache; + std::unordered_map> _legacyModuleCache; // Enforce synchronous access into _delegate std::mutex _turboModuleManagerDelegateMutex; - // Enforce synchronous access to _invalidating and _turboModuleHolders - std::mutex _turboModuleHoldersMutex; + // Enforce synchronous access to _invalidating and _moduleHolders + std::mutex _moduleHoldersMutex; std::atomic _invalidating; + + NSDictionary> *_legacyEagerlyInitializedModules; + NSDictionary *_legacyEagerlyRegisteredModuleClasses; } - (instancetype)initWithBridge:(RCTBridge *)bridge @@ -191,6 +195,27 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge _bridge = bridge; _invalidating = false; + if (RCTTurboModuleInteropEnabled()) { + NSMutableDictionary> *legacyInitializedModules = [NSMutableDictionary new]; + + if ([_delegate respondsToSelector:@selector(extraModulesForBridge:)]) { + for (id module in [_delegate extraModulesForBridge:nil]) { + if (!RCT_IS_TURBO_MODULE_INSTANCE(module)) { + [legacyInitializedModules setObject:module forKey:RCTBridgeModuleNameForClass([module class])]; + } + } + } + _legacyEagerlyInitializedModules = legacyInitializedModules; + + NSMutableDictionary *legacyEagerlyRegisteredModuleClasses = [NSMutableDictionary new]; + for (Class moduleClass in RCTGetModuleClasses()) { + if (!RCT_IS_TURBO_MODULE_CLASS(moduleClass)) { + [legacyEagerlyRegisteredModuleClasses setObject:moduleClass forKey:RCTBridgeModuleNameForClass(moduleClass)]; + } + } + _legacyEagerlyRegisteredModuleClasses = legacyEagerlyRegisteredModuleClasses; + } + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(bridgeWillInvalidateModules:) name:RCTBridgeWillInvalidateModulesNotification @@ -257,12 +282,13 @@ - (void)notifyAboutTurboModuleSetup:(const char *)name /** * Step 2: Look for platform-specific modules. */ - id module = [self provideRCTTurboModule:moduleName]; + id module = + !RCTTurboModuleInteropEnabled() || [self _isTurboModule:moduleName] ? [self _provideObjCModule:moduleName] : nil; TurboModulePerfLogger::moduleJSRequireEndingStart(moduleName); // If we request that a TurboModule be created, its respective ObjC class must exist - // If the class doesn't exist, then provideRCTTurboModule returns nil + // If the class doesn't exist, then _provideObjCModule returns nil if (!module) { return nullptr; } @@ -299,6 +325,74 @@ - (void)notifyAboutTurboModuleSetup:(const char *)name return turboModule; } + /** + * Step 2e: Return an exact sub-class of ObjC TurboModule + * + * Use respondsToSelector: below to infer conformance to @protocol(RCTTurboModule). Using conformsToProtocol: is + * expensive. + */ + if ([module respondsToSelector:@selector(getTurboModule:)]) { + ObjCTurboModule::InitParams params = { + .moduleName = moduleName, + .instance = module, + .jsInvoker = _jsInvoker, + .nativeInvoker = nativeInvoker, + .isSyncModule = methodQueue == RCTJSThread, + }; + + auto turboModule = [(id)module getTurboModule:params]; + if (turboModule == nullptr) { + RCTLogError(@"TurboModule \"%@\"'s getTurboModule: method returned nil.", moduleClass); + } + _turboModuleCache.insert({moduleName, turboModule}); + return turboModule; + } + + return nullptr; +} + +- (std::shared_ptr)provideLegacyModule:(const char *)moduleName +{ + auto legacyModuleLookup = _legacyModuleCache.find(moduleName); + if (legacyModuleLookup != _legacyModuleCache.end()) { + TurboModulePerfLogger::moduleJSRequireBeginningCacheHit(moduleName); + TurboModulePerfLogger::moduleJSRequireBeginningEnd(moduleName); + return legacyModuleLookup->second; + } + + TurboModulePerfLogger::moduleJSRequireBeginningEnd(moduleName); + + // Create platform-specific native module object + id module = [self _isLegacyModule:moduleName] ? [self _provideObjCModule:moduleName] : nil; + + TurboModulePerfLogger::moduleJSRequireEndingStart(moduleName); + + // If we request that a TurboModule be created, its respective ObjC class must exist + // If the class doesn't exist, then provideRCTBridgeModule returns nil + if (!module) { + return nullptr; + } + + Class moduleClass = [module class]; + + dispatch_queue_t methodQueue = (dispatch_queue_t)objc_getAssociatedObject(module, &kAssociatedMethodQueueKey); + if (methodQueue == nil) { + RCTLogError(@"Legacy NativeModule \"%@\" was not associated with a method queue.", moduleClass); + } + + // Create a native call invoker from module's method queue + std::shared_ptr nativeInvoker = std::make_shared(methodQueue); + + // If module is a legacy cxx module, return TurboCxxModule + if ([moduleClass isSubclassOfClass:RCTCxxModule.class]) { + // Use TurboCxxModule compat class to wrap the CxxModule instance. + // This is only for migration convenience, despite less performant. + auto turboModule = std::make_shared([((RCTCxxModule *)module) createModule], _jsInvoker); + _legacyModuleCache.insert({moduleName, turboModule}); + return turboModule; + } + + // Create interop module ObjCTurboModule::InitParams params = { .moduleName = moduleName, .instance = module, @@ -307,49 +401,65 @@ - (void)notifyAboutTurboModuleSetup:(const char *)name .isSyncModule = methodQueue == RCTJSThread, }; - /** - * Step 2e: Return an exact sub-class of ObjC TurboModule - */ - auto turboModule = [module getTurboModule:params]; - if (turboModule == nullptr) { - RCTLogError(@"TurboModule \"%@\"'s getTurboModule: method returned nil.", moduleClass); - } - _turboModuleCache.insert({moduleName, turboModule}); + auto turboModule = std::make_shared(params); + _legacyModuleCache.insert({moduleName, turboModule}); return turboModule; } -- (TurboModuleHolder *)_getOrCreateTurboModuleHolder:(const char *)moduleName +- (BOOL)_isTurboModule:(const char *)moduleName { - std::lock_guard guard(_turboModuleHoldersMutex); + if (RCTTurboModuleInteropForAllTurboModulesEnabled()) { + return NO; + } + + Class moduleClass = [self _getModuleClassFromName:moduleName]; + return moduleClass != nil && + (RCT_IS_TURBO_MODULE_CLASS(moduleClass) && ![moduleClass isSubclassOfClass:RCTCxxModule.class]); +} + +- (BOOL)_isLegacyModule:(const char *)moduleName +{ + if (RCTTurboModuleInteropForAllTurboModulesEnabled()) { + return YES; + } + + Class moduleClass = [self _getModuleClassFromName:moduleName]; + return moduleClass != nil && + (!RCT_IS_TURBO_MODULE_CLASS(moduleClass) || [moduleClass isSubclassOfClass:RCTCxxModule.class]); +} + +- (ModuleHolder *)_getOrCreateModuleHolder:(const char *)moduleName +{ + std::lock_guard guard(_moduleHoldersMutex); if (_invalidating) { return nullptr; } - return &_turboModuleHolders[moduleName]; + return &_moduleHolders[moduleName]; } /** - * Given a name for a TurboModule, return an ObjC object which is the instance - * of that TurboModule ObjC class. If no TurboModule exist with the provided name, + * Given a name for a NativeModule, return an ObjC object which is the instance + * of that NativeModule ObjC class. If no NativeModule exist with the provided name, * return nil. * - * Note: All TurboModule instances are cached, which means they're all long-lived + * Note: All NativeModule instances are cached, which means they're all long-lived * (for now). */ -- (id)provideRCTTurboModule:(const char *)moduleName +- (id)_provideObjCModule:(const char *)moduleName { if (strncmp("RCT", moduleName, 3) == 0) { moduleName = [[[NSString stringWithUTF8String:moduleName] substringFromIndex:3] UTF8String]; } - TurboModuleHolder *moduleHolder = [self _getOrCreateTurboModuleHolder:moduleName]; + ModuleHolder *moduleHolder = [self _getOrCreateModuleHolder:moduleName]; if (!moduleHolder) { return nil; } TurboModulePerfLogger::moduleCreateStart(moduleName, moduleHolder->getModuleId()); - id module = [self _provideRCTTurboModule:moduleName moduleHolder:moduleHolder shouldPerfLog:YES]; + id module = [self _provideObjCModule:moduleName moduleHolder:moduleHolder shouldPerfLog:YES]; if (module) { TurboModulePerfLogger::moduleCreateEnd(moduleName, moduleHolder->getModuleId()); @@ -360,9 +470,9 @@ - (TurboModuleHolder *)_getOrCreateTurboModuleHolder:(const char *)moduleName return module; } -- (id)_provideRCTTurboModule:(const char *)moduleName - moduleHolder:(TurboModuleHolder *)moduleHolder - shouldPerfLog:(BOOL)shouldPerfLog +- (id)_provideObjCModule:(const char *)moduleName + moduleHolder:(ModuleHolder *)moduleHolder + shouldPerfLog:(BOOL)shouldPerfLog { bool shouldCreateModule = false; @@ -383,34 +493,23 @@ - (TurboModuleHolder *)_getOrCreateTurboModuleHolder:(const char *)moduleName } if (shouldCreateModule) { - Class moduleClass; - /** * Step 2a: Resolve platform-specific class. */ - if (RCTTurboModuleManagerDelegateLockingDisabled()) { - moduleClass = [_delegate getModuleClassFromName:moduleName]; - } else { - std::lock_guard delegateGuard(_turboModuleManagerDelegateMutex); - moduleClass = [_delegate getModuleClassFromName:moduleName]; - } - - if (!moduleClass) { - moduleClass = getFallbackClassFromName(moduleName); - } + Class moduleClass = [self _getModuleClassFromName:moduleName]; - __block id module = nil; + __block id module = nil; - if ([moduleClass conformsToProtocol:@protocol(RCTTurboModule)]) { + if ([self _shouldCreateObjCModule:moduleClass]) { __weak __typeof(self) weakSelf = self; dispatch_block_t work = ^{ auto strongSelf = weakSelf; if (!strongSelf) { return; } - module = [strongSelf _createAndSetUpRCTTurboModule:moduleClass - moduleName:moduleName - moduleId:moduleHolder->getModuleId()]; + module = [strongSelf _createAndSetUpObjCModule:moduleClass + moduleName:moduleName + moduleId:moduleHolder->getModuleId()]; }; if ([self _requiresMainQueueSetup:moduleClass]) { @@ -459,34 +558,35 @@ - (TurboModuleHolder *)_getOrCreateTurboModuleHolder:(const char *)moduleName return moduleHolder->getModule(); } +- (BOOL)_shouldCreateObjCModule:(Class)moduleClass +{ + if (RCTTurboModuleInteropEnabled()) { + return [moduleClass conformsToProtocol:@protocol(RCTBridgeModule)]; + } + + return [moduleClass conformsToProtocol:@protocol(RCTTurboModule)]; +} + /** - * Given a TurboModule class, and its name, create and initialize it synchronously. + * Given a NativeModule class, and its name, create and initialize it synchronously. * * This method can be called synchronously from two different contexts: - * - The thread that calls provideRCTTurboModule: - * - The main thread (if the TurboModule requires main queue init), blocking the thread that calls - * provideRCTTurboModule:. + * - The thread that calls _provideObjCModule: + * - The main thread (if the NativeModule requires main queue init), blocking the thread that calls + * _provideObjCModule:. */ -- (id)_createAndSetUpRCTTurboModule:(Class)moduleClass - moduleName:(const char *)moduleName - moduleId:(int32_t)moduleId +- (id)_createAndSetUpObjCModule:(Class)moduleClass + moduleName:(const char *)moduleName + moduleId:(int32_t)moduleId { - id module = nil; + id module = nil; /** * Step 2b: Ask hosting application/delegate to instantiate this class */ TurboModulePerfLogger::moduleCreateConstructStart(moduleName, moduleId); - if (RCTTurboModuleManagerDelegateLockingDisabled()) { - module = [_delegate getModuleInstanceFromClass:moduleClass]; - } else { - std::lock_guard delegateGuard(_turboModuleManagerDelegateMutex); - module = [_delegate getModuleInstanceFromClass:moduleClass]; - } - if (!module) { - module = [moduleClass new]; - } + module = [self _getModuleInstanceFromClass:moduleClass]; TurboModulePerfLogger::moduleCreateConstructEnd(moduleName, moduleId); TurboModulePerfLogger::moduleCreateSetUpStart(moduleName, moduleId); @@ -572,24 +672,24 @@ - (TurboModuleHolder *)_getOrCreateTurboModuleHolder:(const char *)moduleName } /** - * Decorate TurboModules with bridgeless-compatible APIs that call into the bridge. + * Decorate NativeModules with bridgeless-compatible APIs that call into the bridge. */ if (_bridge) { - [_bridge attachBridgeAPIsToTurboModule:module]; + [_bridge attachBridgeAPIsToObjCModule:module]; } /** - * If the TurboModule conforms to RCTInitializing, invoke its initialize method. + * If the NativeModule conforms to RCTInitializing, invoke its initialize method. */ if ([module respondsToSelector:@selector(initialize)]) { [(id)module initialize]; } /** - * Attach method queue to id object. - * This is necessary because the id object can be eagerly created/initialized before the method - * queue is required. The method queue is required for an id for JS -> Native calls. So, we need it - * before we create the id's TurboModule jsi::HostObject in provideTurboModule:. + * Attach method queue to id object. + * This is necessary because the id object can be eagerly created/initialized before the method + * queue is required. The method queue is required for an id for JS -> Native calls. So, we need it + * before we create the id's TurboModule jsi::HostObject in provideTurboModule:. */ objc_setAssociatedObject(module, &kAssociatedMethodQueueKey, methodQueue, OBJC_ASSOCIATION_RETAIN); @@ -611,7 +711,7 @@ - (TurboModuleHolder *)_getOrCreateTurboModuleHolder:(const char *)moduleName } /** - * Broadcast that this TurboModule was created. + * Broadcast that this NativeModule was created. * * TODO(T41180176): Investigate whether we can delete this after TM * rollout. @@ -626,11 +726,61 @@ - (TurboModuleHolder *)_getOrCreateTurboModuleHolder:(const char *)moduleName return module; } +- (Class)_getModuleClassFromName:(const char *)moduleName +{ + NSString *moduleNameStr = @(moduleName); + if (_legacyEagerlyInitializedModules && _legacyEagerlyInitializedModules[moduleNameStr]) { + return [_legacyEagerlyInitializedModules[moduleNameStr] class]; + } + + if (_legacyEagerlyRegisteredModuleClasses && _legacyEagerlyRegisteredModuleClasses[moduleNameStr]) { + return _legacyEagerlyRegisteredModuleClasses[moduleNameStr]; + } + + Class moduleClass; + if (RCTTurboModuleManagerDelegateLockingDisabled()) { + moduleClass = [_delegate getModuleClassFromName:moduleName]; + } else { + std::lock_guard delegateGuard(_turboModuleManagerDelegateMutex); + moduleClass = [_delegate getModuleClassFromName:moduleName]; + } + + if (!moduleClass) { + moduleClass = getFallbackClassFromName(moduleName); + } + return moduleClass; +} + +- (id)_getModuleInstanceFromClass:(Class)moduleClass +{ + NSString *moduleNameStr = RCTBridgeModuleNameForClass(moduleClass); + if (_legacyEagerlyInitializedModules && _legacyEagerlyInitializedModules[moduleNameStr]) { + return _legacyEagerlyInitializedModules[moduleNameStr]; + } + + if (_legacyEagerlyRegisteredModuleClasses && _legacyEagerlyRegisteredModuleClasses[moduleNameStr]) { + return [_legacyEagerlyRegisteredModuleClasses[moduleNameStr] new]; + } + + id module = nil; + if (RCTTurboModuleManagerDelegateLockingDisabled()) { + module = (id)[_delegate getModuleInstanceFromClass:moduleClass]; + } else { + std::lock_guard delegateGuard(_turboModuleManagerDelegateMutex); + module = (id)[_delegate getModuleInstanceFromClass:moduleClass]; + } + if (!module) { + module = [moduleClass new]; + } + + return module; +} + /** - * Should this TurboModule be created and initialized on the main queue? + * Should this NativeModule be created and initialized on the main queue? * - * For TurboModule ObjC classes that implement requiresMainQueueInit, return the result of this method. - * For TurboModule ObjC classes that don't. Return true if they have a custom init or constantsToExport method. + * For NativeModule ObjC classes that implement requiresMainQueueInit, return the result of this method. + * For NativeModule ObjC classes that don't. Return true if they have a custom init or constantsToExport method. */ - (BOOL)_requiresMainQueueSetup:(Class)moduleClass { @@ -668,7 +818,7 @@ - (BOOL)_requiresMainQueueSetup:(Class)moduleClass if (requiresMainQueueSetup) { RCTLogWarn( @"Module %@ requires main queue setup since it overrides `%s` but doesn't implement " - "`requiresMainQueueSetup`. In a future release React Native will default to initializing all native modules " + "`requiresMainQueueSetup`. In a future release React Native will default to initializing all NativeModules " "on a background thread unless explicitly opted-out of.", moduleClass, hasConstantsToExport ? "constantsToExport" @@ -723,8 +873,43 @@ - (void)installJSBindingWithRuntimeExecutor:(facebook::react::RuntimeExecutor &) return turboModule; }; - runtimeExecutor([turboModuleProvider = std::move(turboModuleProvider)](jsi::Runtime &runtime) { - TurboModuleBinding::install(runtime, sTurboModuleBindingMode, std::move(turboModuleProvider)); + if (!RCTTurboModuleInteropEnabled()) { + runtimeExecutor([turboModuleProvider = std::move(turboModuleProvider)](jsi::Runtime &runtime) { + TurboModuleBinding::install(runtime, sTurboModuleBindingMode, std::move(turboModuleProvider)); + }); + return; + } + + auto legacyModuleProvider = [self](const std::string &name) -> std::shared_ptr { + auto moduleName = name.c_str(); + + TurboModulePerfLogger::moduleJSRequireBeginningStart(moduleName); + auto moduleWasNotInitialized = ![self moduleIsInitialized:moduleName]; + + /** + * By default, all TurboModules are long-lived. + * Additionally, if a TurboModule with the name `name` isn't found, then we + * trigger an assertion failure. + */ + auto turboModule = [self provideLegacyModule:moduleName]; + + if (moduleWasNotInitialized && [self moduleIsInitialized:moduleName]) { + [self notifyAboutTurboModuleSetup:moduleName]; + } + + if (turboModule) { + TurboModulePerfLogger::moduleJSRequireEndingEnd(moduleName); + } else { + TurboModulePerfLogger::moduleJSRequireEndingFail(moduleName); + } + + return turboModule; + }; + + runtimeExecutor([turboModuleProvider = std::move(turboModuleProvider), + legacyModuleProvider = std::move(legacyModuleProvider)](jsi::Runtime &runtime) { + TurboModuleBinding::install( + runtime, sTurboModuleBindingMode, std::move(turboModuleProvider), std::move(legacyModuleProvider)); }); } @@ -743,7 +928,7 @@ - (id)moduleForName:(const char *)moduleName warnOnLookupFailure:(BOOL)warnOnLoo return nil; } - id module = [self provideRCTTurboModule:moduleName]; + id module = [self _provideObjCModule:moduleName]; if (warnOnLookupFailure && !module) { RCTLogError(@"Unable to find module for %@", [NSString stringWithUTF8String:moduleName]); @@ -754,8 +939,8 @@ - (id)moduleForName:(const char *)moduleName warnOnLookupFailure:(BOOL)warnOnLoo - (BOOL)moduleIsInitialized:(const char *)moduleName { - std::unique_lock guard(_turboModuleHoldersMutex); - return _turboModuleHolders.find(moduleName) != _turboModuleHolders.end(); + std::unique_lock guard(_moduleHoldersMutex); + return _moduleHolders.find(moduleName) != _moduleHolders.end(); } #pragma mark Invalidation logic @@ -788,8 +973,8 @@ - (void)invalidate - (void)_enterInvalidatingState { - // This should halt all insertions into _turboModuleHolders - std::lock_guard guard(_turboModuleHoldersMutex); + // This should halt all insertions into _moduleHolders + std::lock_guard guard(_moduleHoldersMutex); _invalidating = true; } @@ -798,25 +983,25 @@ - (void)_invalidateModules // Backward-compatibility: RCTInvalidating handling. dispatch_group_t moduleInvalidationGroup = dispatch_group_create(); - for (auto &pair : _turboModuleHolders) { + for (auto &pair : _moduleHolders) { std::string moduleName = pair.first; - TurboModuleHolder *moduleHolder = &pair.second; + ModuleHolder *moduleHolder = &pair.second; /** - * We could start tearing down ReactNative before a TurboModule is fully initialized. In this case, we should wait - * for TurboModule init to finish before calling invalidate on it. So, we call _provideRCTTurboModule:moduleHolder, - * because it's guaranteed to return a fully initialized NativeModule. + * We could start tearing down ReactNative before a NativeModule is fully initialized. In this case, we should wait + * for NativeModule init to finish before calling invalidate on it. So, we call + * _provideObjCModule:moduleHolder, because it's guaranteed to return a fully initialized NativeModule. */ - id module = [self _provideRCTTurboModule:moduleName.c_str() - moduleHolder:moduleHolder - shouldPerfLog:NO]; + id module = [self _provideObjCModule:moduleName.c_str() + moduleHolder:moduleHolder + shouldPerfLog:NO]; if ([module respondsToSelector:@selector(invalidate)]) { dispatch_queue_t methodQueue = (dispatch_queue_t)objc_getAssociatedObject(module, &kAssociatedMethodQueueKey); if (methodQueue == nil) { RCTLogError( - @"TurboModuleManager: Couldn't invalidate TurboModule \"%@\", because its method queue is nil.", + @"TurboModuleManager: Couldn't invalidate NativeModule \"%@\", because its method queue is nil.", [module class]); continue; } @@ -844,8 +1029,9 @@ - (void)_invalidateModules RCTLogError(@"TurboModuleManager: Timed out waiting for modules to be invalidated"); } - _turboModuleHolders.clear(); + _moduleHolders.clear(); _turboModuleCache.clear(); + _legacyModuleCache.clear(); } @end diff --git a/packages/react-native/ReactCommon/react/nativemodule/samples/ReactCommon-Samples.podspec b/packages/react-native/ReactCommon/react/nativemodule/samples/ReactCommon-Samples.podspec index 20bc81f09dd1df..ddccfded01041d 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/samples/ReactCommon-Samples.podspec +++ b/packages/react-native/ReactCommon/react/nativemodule/samples/ReactCommon-Samples.podspec @@ -55,5 +55,7 @@ Pod::Spec.new do |s| if using_hermes s.dependency "hermes-engine" + else + s.dependency "React-jsi" end end diff --git a/packages/react-native/ReactCommon/react/renderer/attributedstring/CMakeLists.txt b/packages/react-native/ReactCommon/react/renderer/attributedstring/CMakeLists.txt index b5399e44e48daa..cc34a3fe959a90 100644 --- a/packages/react-native/ReactCommon/react/renderer/attributedstring/CMakeLists.txt +++ b/packages/react-native/ReactCommon/react/renderer/attributedstring/CMakeLists.txt @@ -26,6 +26,7 @@ target_link_libraries(react_render_attributedstring glog glog_init react_debug + rrc_view react_render_core react_render_debug react_render_graphics diff --git a/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp b/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp index 2112a70a3d2019..dfeaafef0d2ca7 100644 --- a/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp +++ b/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp @@ -101,6 +101,7 @@ void TextAttributes::apply(TextAttributes textAttributes) { accessibilityRole = textAttributes.accessibilityRole.has_value() ? textAttributes.accessibilityRole : accessibilityRole; + role = textAttributes.role.has_value() ? textAttributes.role : role; } #pragma mark - Operators @@ -126,6 +127,7 @@ bool TextAttributes::operator==(const TextAttributes &rhs) const { isHighlighted, layoutDirection, accessibilityRole, + role, textTransform) == std::tie( rhs.foregroundColor, @@ -147,6 +149,7 @@ bool TextAttributes::operator==(const TextAttributes &rhs) const { rhs.isHighlighted, rhs.layoutDirection, rhs.accessibilityRole, + rhs.role, rhs.textTransform) && floatEquality(opacity, rhs.opacity) && floatEquality(fontSize, rhs.fontSize) && @@ -215,6 +218,7 @@ SharedDebugStringConvertibleList TextAttributes::getDebugProps() const { debugStringConvertibleItem("isHighlighted", isHighlighted), debugStringConvertibleItem("layoutDirection", layoutDirection), debugStringConvertibleItem("accessibilityRole", accessibilityRole), + debugStringConvertibleItem("role", role), }; } #endif diff --git a/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.h b/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.h index fd552ca7817850..a681e9b4837145 100644 --- a/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.h +++ b/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.h @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -80,6 +81,7 @@ class TextAttributes : public DebugStringConvertible { // construction. std::optional layoutDirection{}; std::optional accessibilityRole{}; + std::optional role{}; #pragma mark - Operations @@ -131,7 +133,8 @@ struct hash { textAttributes.textShadowColor, textAttributes.isHighlighted, textAttributes.layoutDirection, - textAttributes.accessibilityRole); + textAttributes.accessibilityRole, + textAttributes.role); } }; } // namespace std diff --git a/packages/react-native/ReactCommon/react/renderer/attributedstring/conversions.h b/packages/react-native/ReactCommon/react/renderer/attributedstring/conversions.h index 20383dd113ba96..0d54c7e774935d 100644 --- a/packages/react-native/ReactCommon/react/renderer/attributedstring/conversions.h +++ b/packages/react-native/ReactCommon/react/renderer/attributedstring/conversions.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -641,150 +642,6 @@ inline std::string toString(const TextDecorationStyle &textDecorationStyle) { return "solid"; } -inline std::string toString(const AccessibilityRole &accessibilityRole) { - switch (accessibilityRole) { - case AccessibilityRole::None: - return "none"; - case AccessibilityRole::Button: - return "button"; - case AccessibilityRole::Link: - return "link"; - case AccessibilityRole::Search: - return "search"; - case AccessibilityRole::Image: - return "image"; - case AccessibilityRole::Imagebutton: - return "imagebutton"; - case AccessibilityRole::Keyboardkey: - return "keyboardkey"; - case AccessibilityRole::Text: - return "text"; - case AccessibilityRole::Adjustable: - return "adjustable"; - case AccessibilityRole::Summary: - return "summary"; - case AccessibilityRole::Header: - return "header"; - case AccessibilityRole::Alert: - return "alert"; - case AccessibilityRole::Checkbox: - return "checkbox"; - case AccessibilityRole::Combobox: - return "combobox"; - case AccessibilityRole::Menu: - return "menu"; - case AccessibilityRole::Menubar: - return "menubar"; - case AccessibilityRole::Menuitem: - return "menuitem"; - case AccessibilityRole::Progressbar: - return "progressbar"; - case AccessibilityRole::Radio: - return "radio"; - case AccessibilityRole::Radiogroup: - return "radiogroup"; - case AccessibilityRole::Scrollbar: - return "scrollbar"; - case AccessibilityRole::Spinbutton: - return "spinbutton"; - case AccessibilityRole::Switch: - return "switch"; - case AccessibilityRole::Tab: - return "tab"; - case AccessibilityRole::TabBar: - return "tabbar"; - case AccessibilityRole::Tablist: - return "tablist"; - case AccessibilityRole::Timer: - return "timer"; - case AccessibilityRole::Toolbar: - return "toolbar"; - } - - LOG(ERROR) << "Unsupported AccessibilityRole value"; - react_native_expect(false); - // sane default for prod - return "none"; -} - -inline void fromRawValue( - const PropsParserContext &context, - const RawValue &value, - AccessibilityRole &result) { - react_native_expect(value.hasType()); - if (value.hasType()) { - auto string = (std::string)value; - if (string == "none") { - result = AccessibilityRole::None; - } else if (string == "button" || string == "togglebutton") { - result = AccessibilityRole::Button; - } else if (string == "link") { - result = AccessibilityRole::Link; - } else if (string == "search") { - result = AccessibilityRole::Search; - } else if (string == "image") { - result = AccessibilityRole::Image; - } else if (string == "imagebutton") { - result = AccessibilityRole::Imagebutton; - } else if (string == "keyboardkey") { - result = AccessibilityRole::Keyboardkey; - } else if (string == "text") { - result = AccessibilityRole::Text; - } else if (string == "adjustable") { - result = AccessibilityRole::Adjustable; - } else if (string == "summary") { - result = AccessibilityRole::Summary; - } else if (string == "header") { - result = AccessibilityRole::Header; - } else if (string == "alert") { - result = AccessibilityRole::Alert; - } else if (string == "checkbox") { - result = AccessibilityRole::Checkbox; - } else if (string == "combobox") { - result = AccessibilityRole::Combobox; - } else if (string == "menu") { - result = AccessibilityRole::Menu; - } else if (string == "menubar") { - result = AccessibilityRole::Menubar; - } else if (string == "menuitem") { - result = AccessibilityRole::Menuitem; - } else if (string == "progressbar") { - result = AccessibilityRole::Progressbar; - } else if (string == "radio") { - result = AccessibilityRole::Radio; - } else if (string == "radiogroup") { - result = AccessibilityRole::Radiogroup; - } else if (string == "scrollbar") { - result = AccessibilityRole::Scrollbar; - } else if (string == "spinbutton") { - result = AccessibilityRole::Spinbutton; - } else if (string == "switch") { - result = AccessibilityRole::Switch; - } else if (string == "tab") { - result = AccessibilityRole::Tab; - } else if (string == "tabbar") { - result = AccessibilityRole::TabBar; - } else if (string == "tablist") { - result = AccessibilityRole::Tablist; - } else if (string == "timer") { - result = AccessibilityRole::Timer; - } else if (string == "toolbar") { - result = AccessibilityRole::Toolbar; - } else { - LOG(ERROR) << "Unsupported AccessibilityRole value: " << string; - react_native_expect(false); - // sane default for prod - result = AccessibilityRole::None; - } - return; - } - - LOG(ERROR) << "Unsupported AccessibilityRole type"; - react_native_expect(false); - // sane default for prod - result = AccessibilityRole::None; -} - inline std::string toString(const HyphenationFrequency &hyphenationFrequency) { switch (hyphenationFrequency) { case HyphenationFrequency::None: @@ -1111,6 +968,7 @@ constexpr static MapBuffer::Key TA_KEY_IS_HIGHLIGHTED = 22; constexpr static MapBuffer::Key TA_KEY_LAYOUT_DIRECTION = 23; constexpr static MapBuffer::Key TA_KEY_ACCESSIBILITY_ROLE = 24; constexpr static MapBuffer::Key TA_KEY_LINE_BREAK_STRATEGY = 25; +constexpr static MapBuffer::Key TA_KEY_ROLE = 26; // constants for ParagraphAttributes serialization constexpr static MapBuffer::Key PA_KEY_MAX_NUMBER_OF_LINES = 0; @@ -1263,6 +1121,9 @@ inline MapBuffer toMapBuffer(const TextAttributes &textAttributes) { builder.putString( TA_KEY_ACCESSIBILITY_ROLE, toString(*textAttributes.accessibilityRole)); } + if (textAttributes.role.has_value()) { + builder.putInt(TA_KEY_ROLE, static_cast(*textAttributes.role)); + } return builder.build(); } diff --git a/packages/react-native/ReactCommon/react/renderer/attributedstring/primitives.h b/packages/react-native/ReactCommon/react/renderer/attributedstring/primitives.h index 75c5ce77f0d9b9..30a6e002dafdf5 100644 --- a/packages/react-native/ReactCommon/react/renderer/attributedstring/primitives.h +++ b/packages/react-native/ReactCommon/react/renderer/attributedstring/primitives.h @@ -105,37 +105,6 @@ enum class TextDecorationLineType { enum class TextDecorationStyle { Solid, Double, Dotted, Dashed }; -enum class AccessibilityRole { - None, - Button, - Link, - Search, - Image, - Imagebutton, - Keyboardkey, - Text, - Adjustable, - Summary, - Header, - Alert, - Checkbox, - Combobox, - Menu, - Menubar, - Menuitem, - Progressbar, - Radio, - Radiogroup, - Scrollbar, - Spinbutton, - Switch, - Tab, - TabBar, - Tablist, - Timer, - Toolbar, -}; - enum class TextTransform { None, Uppercase, @@ -223,13 +192,6 @@ struct hash { } }; -template <> -struct hash { - size_t operator()(const facebook::react::AccessibilityRole &v) const { - return hash()(static_cast(v)); - } -}; - template <> struct hash { size_t operator()(const facebook::react::TextTransform &v) const { diff --git a/packages/react-native/ReactCommon/react/renderer/componentregistry/componentNameByReactViewName.cpp b/packages/react-native/ReactCommon/react/renderer/componentregistry/componentNameByReactViewName.cpp index f50a76ab01fa79..de9e32008760d8 100644 --- a/packages/react-native/ReactCommon/react/renderer/componentregistry/componentNameByReactViewName.cpp +++ b/packages/react-native/ReactCommon/react/renderer/componentregistry/componentNameByReactViewName.cpp @@ -6,6 +6,7 @@ */ #include "componentNameByReactViewName.h" +#include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/componentregistry/native/NativeComponentRegistryBinding.cpp b/packages/react-native/ReactCommon/react/renderer/componentregistry/native/NativeComponentRegistryBinding.cpp index d3e071d0f2f71b..17c8a78ef0a512 100644 --- a/packages/react-native/ReactCommon/react/renderer/componentregistry/native/NativeComponentRegistryBinding.cpp +++ b/packages/react-native/ReactCommon/react/renderer/componentregistry/native/NativeComponentRegistryBinding.cpp @@ -7,60 +7,22 @@ #include "NativeComponentRegistryBinding.h" +#include #include #include -using namespace facebook; - namespace facebook::react { /** - * Public API to install the NativeComponentRegistryBinding. + * Public API to install the Native Component Registry bindings. */ -NativeComponentRegistryBinding::NativeComponentRegistryBinding( - const HasComponentProviderFunctionType &&hasComponentProvider) - : hasComponentProvider_(hasComponentProvider) {} - -void NativeComponentRegistryBinding::install( +void bindHasComponentProvider( jsi::Runtime &runtime, - const HasComponentProviderFunctionType &&hasComponentProvider) { + HasComponentProviderFunctionType &&provider) { runtime.global().setProperty( runtime, "__nativeComponentRegistry__hasComponent", - jsi::Function::createFromHostFunction( - runtime, - jsi::PropNameID::forAscii( - runtime, "__nativeComponentRegistry__hasComponent"), - 1, - [binding = std::make_shared( - std::move(hasComponentProvider))]( - jsi::Runtime &rt, - const jsi::Value &thisVal, - const jsi::Value *args, - size_t count) { - return binding->jsProxy(rt, thisVal, args, count); - })); -} - -bool NativeComponentRegistryBinding::hasComponent(const std::string &name) { - return hasComponentProvider_(name); -} - -jsi::Value NativeComponentRegistryBinding::jsProxy( - jsi::Runtime &runtime, - const jsi::Value & /*thisVal*/, - const jsi::Value *args, - size_t count) { - if (count != 1) { - throw std::invalid_argument( - "__nativeComponentRegistry__hasComponent must be called with 1 argument"); - } - std::string moduleName = args[0].getString(runtime).utf8(runtime); - jsi::Value nullSchema = jsi::Value::undefined(); - - bool result = hasComponent(moduleName); - - return {result}; + bridging::toJs(runtime, provider, {})); } } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/componentregistry/native/NativeComponentRegistryBinding.h b/packages/react-native/ReactCommon/react/renderer/componentregistry/native/NativeComponentRegistryBinding.h index ce60ff514d57cd..de5ce1cd9c0c6b 100644 --- a/packages/react-native/ReactCommon/react/renderer/componentregistry/native/NativeComponentRegistryBinding.h +++ b/packages/react-native/ReactCommon/react/renderer/componentregistry/native/NativeComponentRegistryBinding.h @@ -20,40 +20,12 @@ namespace facebook::react { using HasComponentProviderFunctionType = std::function; -/** - * Represents the JavaScript binding for the HasComponent global function. +/* + * Installs HasComponentProviderFunction into JavaScript runtime. + * Thread synchronization must be enforced externally. */ -class NativeComponentRegistryBinding { - public: - /* - * Installs NativeComponentRegistryBinding into JavaScript runtime. - * Thread synchronization must be enforced externally. - */ - static void install( - jsi::Runtime &runtime, - const HasComponentProviderFunctionType &&provider); - - NativeComponentRegistryBinding( - const HasComponentProviderFunctionType &&provider); - - /** - * Returns if there's a component registered with the name received as a - * parameter - */ - bool hasComponent(const std::string &name); - - private: - /** - * A lookup function exposed to JS to determine if a component is registered - * in the native platform. - */ - jsi::Value jsProxy( - jsi::Runtime &runtime, - const jsi::Value &thisVal, - const jsi::Value *args, - size_t count); - - HasComponentProviderFunctionType hasComponentProvider_; -}; +void bindHasComponentProvider( + jsi::Runtime &runtime, + HasComponentProviderFunctionType &&provider); } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/components/text/BaseTextProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/text/BaseTextProps.cpp index d83b9f73188d89..1d54aaf6829de7 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/text/BaseTextProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/text/BaseTextProps.cpp @@ -183,6 +183,13 @@ static TextAttributes convertRawProp( sourceTextAttributes.accessibilityRole, defaultTextAttributes.accessibilityRole); + textAttributes.role = convertRawProp( + context, + rawProps, + "role", + sourceTextAttributes.role, + defaultTextAttributes.role); + // Color (accessed in this order by ViewProps) textAttributes.opacity = convertRawProp( context, @@ -293,6 +300,7 @@ void BaseTextProps::setProp( textAttributes, accessibilityRole, "accessibilityRole"); + REBUILD_FIELD_SWITCH_CASE(defaults, value, textAttributes, role, "role"); REBUILD_FIELD_SWITCH_CASE( defaults, value, textAttributes, opacity, "opacity"); REBUILD_FIELD_SWITCH_CASE( diff --git a/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphLayoutManager.cpp b/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphLayoutManager.cpp index 1f4cbc4a4974ee..c4a5e886c70d66 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphLayoutManager.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphLayoutManager.cpp @@ -15,40 +15,18 @@ TextMeasurement ParagraphLayoutManager::measure( AttributedString const &attributedString, ParagraphAttributes const ¶graphAttributes, LayoutConstraints layoutConstraints) const { - bool cacheLastTextMeasurement = CoreFeatures::cacheLastTextMeasurement; - if (cacheLastTextMeasurement && - (layoutConstraints.maximumSize.width == availableWidth_ || - layoutConstraints.maximumSize.width == - cachedTextMeasurement_.size.width)) { - /* Yoga has requested measurement for this size before. Let's use cached - * value. `TextLayoutManager` might not have cached this because it could be - * using different width to generate cache key. This happens because Yoga - * switches between available width and exact width but since we already - * know exact width, it is wasteful to calculate it again. - */ - return cachedTextMeasurement_; - } - if (CoreFeatures::cacheNSTextStorage) { - size_t newHash = folly::hash::hash_combine( - 0, - textAttributedStringHashLayoutWise(attributedString), - paragraphAttributes); + if (CoreFeatures::cacheLastTextMeasurement) { + bool shouldMeasure = shoudMeasureString( + attributedString, paragraphAttributes, layoutConstraints); - if (!hostTextStorage_ || newHash != hash_) { - hostTextStorage_ = textLayoutManager_->getHostTextStorage( - attributedString, paragraphAttributes, layoutConstraints); - hash_ = newHash; + if (shouldMeasure) { + cachedTextMeasurement_ = textLayoutManager_->measure( + AttributedStringBox(attributedString), + paragraphAttributes, + layoutConstraints, + hostTextStorage_); + lastAvailableWidth_ = layoutConstraints.maximumSize.width; } - } - - if (cacheLastTextMeasurement) { - cachedTextMeasurement_ = textLayoutManager_->measure( - AttributedStringBox(attributedString), - paragraphAttributes, - layoutConstraints, - hostTextStorage_); - - availableWidth_ = layoutConstraints.maximumSize.width; return cachedTextMeasurement_; } else { @@ -56,8 +34,41 @@ TextMeasurement ParagraphLayoutManager::measure( AttributedStringBox(attributedString), paragraphAttributes, layoutConstraints, - hostTextStorage_); + nullptr); + } +} + +bool ParagraphLayoutManager::shoudMeasureString( + AttributedString const &attributedString, + ParagraphAttributes const ¶graphAttributes, + LayoutConstraints layoutConstraints) const { + size_t newHash = folly::hash::hash_combine( + 0, + textAttributedStringHashLayoutWise(attributedString), + paragraphAttributes); + + if (newHash != paragraphInputHash_) { + // AttributedString or ParagraphAttributes have changed. + // Must create new host text storage and trigger measure. + hostTextStorage_ = textLayoutManager_->getHostTextStorage( + attributedString, paragraphAttributes, layoutConstraints); + paragraphInputHash_ = newHash; + return true; // Must measure again. + } + + bool hasMaximumSizeChanged = + layoutConstraints.maximumSize.width != lastAvailableWidth_; + Float threshold = 0.01; + bool doesMaximumSizeMatchLastMeasurement = + std::abs( + layoutConstraints.maximumSize.width - + cachedTextMeasurement_.size.width) < threshold; + if (hasMaximumSizeChanged && !doesMaximumSizeMatchLastMeasurement) { + hostTextStorage_ = textLayoutManager_->getHostTextStorage( + attributedString, paragraphAttributes, layoutConstraints); + return true; } + return false; } LinesMeasurements ParagraphLayoutManager::measureLines( diff --git a/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphLayoutManager.h b/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphLayoutManager.h index d262db62b8c9ee..9583aae501baeb 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphLayoutManager.h +++ b/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphLayoutManager.h @@ -52,20 +52,41 @@ class ParagraphLayoutManager { private: std::shared_ptr mutable textLayoutManager_{}; + + /* + * Stores opaque pointer to `NSTextStorage` on iOS. nullptr on Android. + * TODO: In the future, we may want to cache Android's text storage. + */ std::shared_ptr mutable hostTextStorage_{}; + /* + * Hash of AttributedString and ParagraphAttributes last used to + * measure. Result of that measure is stored in cachedTextMeasurement_. + * The available width defined for the measurement is stored in + * lastAvailableWidth_. + */ + size_t mutable paragraphInputHash_{}; + /* The width Yoga set as maximum width. - * Yoga sometimes calls measure twice with two - * different maximum width. One if available space. + * Yoga calls measure twice with two + * different maximum width. One of available space. * The other one is exact space needed for the string. * This happens when node is dirtied but its size is not affected. * To deal with this inefficiency, we cache `TextMeasurement` for each * `ParagraphShadowNode`. If Yoga tries to re-measure with available width * or exact width, we provide it with the cached value. */ - Float mutable availableWidth_{}; + Float mutable lastAvailableWidth_{}; TextMeasurement mutable cachedTextMeasurement_{}; - size_t mutable hash_{}; + /* + * Checks whether the inputs into text measurement meaningfully affect + * text measurement result. Returns true if inputs have changed and measure is + * needed. + */ + bool shoudMeasureString( + AttributedString const &attributedString, + ParagraphAttributes const ¶graphAttributes, + LayoutConstraints layoutConstraints) const; }; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityPrimitives.h b/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityPrimitives.h index 6e934df39f517f..108216ae65211d 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityPrimitives.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityPrimitives.h @@ -136,4 +136,131 @@ enum class AccessibilityLiveRegion : uint8_t { Assertive, }; +enum class AccessibilityRole { + None, + Button, + Dropdownlist, + Togglebutton, + Link, + Search, + Image, + Keyboardkey, + Text, + Adjustable, + Imagebutton, + Header, + Summary, + Alert, + Checkbox, + Combobox, + Menu, + Menubar, + Menuitem, + Progressbar, + Radio, + Radiogroup, + Scrollbar, + Spinbutton, + Switch, + Tab, + Tabbar, + Tablist, + Timer, + List, + Toolbar, + Grid, + Pager, + Scrollview, + Horizontalscrollview, + Viewgroup, + Webview, + Drawerlayout, + Slidingdrawer, + Iconmenu, +}; + +enum class Role { + Alert, + Alertdialog, + Application, + Article, + Banner, + Button, + Cell, + Checkbox, + Columnheader, + Combobox, + Complementary, + Contentinfo, + Definition, + Dialog, + Directory, + Document, + Feed, + Figure, + Form, + Grid, + Group, + Heading, + Img, + Link, + List, + Listitem, + Log, + Main, + Marquee, + Math, + Menu, + Menubar, + Menuitem, + Meter, + Navigation, + None, + Note, + Option, + Presentation, + Progressbar, + Radio, + Radiogroup, + Region, + Row, + Rowgroup, + Rowheader, + Scrollbar, + Searchbox, + Separator, + Slider, + Spinbutton, + Status, + Summary, + Switch, + Tab, + Table, + Tablist, + Tabpanel, + Term, + Timer, + Toolbar, + Tooltip, + Tree, + Treegrid, + Treeitem, +}; + } // namespace facebook::react + +namespace std { +template <> +struct hash { + size_t operator()(const facebook::react::AccessibilityRole &v) const { + return hash()(static_cast(v)); + } +}; + +template <> +struct hash { + size_t operator()(const facebook::react::Role &v) const { + return hash()(static_cast(v)); + } +}; +} // namespace std diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp index 8861f69c95a39a..ad6cf1ce83d8ac 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp @@ -171,6 +171,14 @@ AccessibilityProps::AccessibilityProps( "importantForAccessibility", sourceProps.importantForAccessibility, ImportantForAccessibility::Auto)), + role( + CoreFeatures::enablePropIteratorSetter ? sourceProps.role + : convertRawProp( + context, + rawProps, + "role", + sourceProps.role, + {})), testId( CoreFeatures::enablePropIteratorSetter ? sourceProps.testId : convertRawProp( @@ -227,6 +235,7 @@ void AccessibilityProps::setProp( RAW_SET_PROP_SWITCH_CASE_BASIC(onAccessibilityEscape); RAW_SET_PROP_SWITCH_CASE_BASIC(onAccessibilityAction); RAW_SET_PROP_SWITCH_CASE_BASIC(importantForAccessibility); + RAW_SET_PROP_SWITCH_CASE_BASIC(role); RAW_SET_PROP_SWITCH_CASE(testId, "testID"); case CONSTEXPR_RAW_PROPS_KEY_HASH("accessibilityRole"): { AccessibilityTraits traits = AccessibilityTraits::None; diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityProps.h b/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityProps.h index 87f60e7b14ce03..4b6cc6cf6befd9 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityProps.h @@ -57,6 +57,7 @@ class AccessibilityProps { bool onAccessibilityAction{}; ImportantForAccessibility importantForAccessibility{ ImportantForAccessibility::Auto}; + Role role{Role::None}; std::string testId{""}; #pragma mark - DebugStringConvertible diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityPropsMapBuffer.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityPropsMapBuffer.cpp index c866cb23a4636f..a9fa5e60e2c9a7 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityPropsMapBuffer.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityPropsMapBuffer.cpp @@ -158,6 +158,10 @@ void AccessibilityProps::propsDiffMapBuffer( } builder.putInt(AP_IMPORTANT_FOR_ACCESSIBILITY, value); } + + if (oldProps.role != newProps.role) { + builder.putInt(AP_ROLE, static_cast(newProps.role)); + } } #endif diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityPropsMapBuffer.h b/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityPropsMapBuffer.h index 37dd41eeec911d..51d96ee40a0755 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityPropsMapBuffer.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityPropsMapBuffer.h @@ -14,6 +14,9 @@ namespace facebook::react { +// TODO: "AP" (Accessibility Props) are interleaved with "VP" (View Props). +// Ordinals must be unique between them. + constexpr MapBuffer::Key AP_ACCESSIBILITY_ACTIONS = 0; constexpr MapBuffer::Key AP_ACCESSIBILITY_HINT = 1; constexpr MapBuffer::Key AP_ACCESSIBILITY_LABEL = 2; @@ -25,6 +28,8 @@ constexpr MapBuffer::Key AP_ACCESSIBILITY_VALUE = 7; constexpr MapBuffer::Key AP_ACCESSIBLE = 8; constexpr MapBuffer::Key AP_IMPORTANT_FOR_ACCESSIBILITY = 19; +constexpr MapBuffer::Key AP_ROLE = 47; + // AccessibilityAction values constexpr MapBuffer::Key ACCESSIBILITY_ACTION_NAME = 0; constexpr MapBuffer::Key ACCESSIBILITY_ACTION_LABEL = 1; diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/ConcreteViewShadowNode.h b/packages/react-native/ReactCommon/react/renderer/components/view/ConcreteViewShadowNode.h index eb40350b0c5f94..28f345a294731f 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/ConcreteViewShadowNode.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/ConcreteViewShadowNode.h @@ -83,23 +83,6 @@ class ConcreteViewShadowNode : public ConcreteShadowNode< return BaseShadowNode::getConcreteProps().transform; } -#pragma mark - DebugStringConvertible - -#if RN_DEBUG_STRING_CONVERTIBLE - SharedDebugStringConvertibleList getDebugProps() const override { - auto list = SharedDebugStringConvertibleList{}; - - auto basePropsList = ShadowNode::getDebugProps(); - std::move( - basePropsList.begin(), basePropsList.end(), std::back_inserter(list)); - - list.push_back(std::make_shared( - "layout", "", LayoutableShadowNode::getDebugProps())); - - return list; - } -#endif - private: void initialize() noexcept { auto &props = BaseShadowNode::getConcreteProps(); diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp index 75e6c1b15ee66a..fb4e57deaff801 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp @@ -120,9 +120,13 @@ YogaLayoutableShadowNode::YogaLayoutableShadowNode( } } + YGConfigRef previousConfig = YGNodeGetConfig( + &static_cast(sourceShadowNode) + .yogaNode_); + yogaNode_.setContext(this); yogaNode_.setOwner(nullptr); - yogaNode_.setConfig(&initializeYogaConfig(yogaConfig_)); + yogaNode_.setConfig(&initializeYogaConfig(yogaConfig_, previousConfig)); updateYogaChildrenOwnersIfNeeded(); // This is the only legit place where we can dirty cloned Yoga node. @@ -742,10 +746,17 @@ YogaLayoutableShadowNode &YogaLayoutableShadowNode::shadowNodeFromContext( *static_cast(yogaNode->getContext())); } -YGConfig &YogaLayoutableShadowNode::initializeYogaConfig(YGConfig &config) { +YGConfig &YogaLayoutableShadowNode::initializeYogaConfig( + YGConfig &config, + const YGConfigRef previousConfig) { YGConfigSetCloneNodeFunc( &config, YogaLayoutableShadowNode::yogaNodeCloneCallbackConnector); YGConfigSetErrata(&config, YGErrataAll); + if (previousConfig != nullptr) { + YGConfigSetPointScaleFactor( + &config, YGConfigGetPointScaleFactor(previousConfig)); + } + #ifdef RN_DEBUG_YOGA_LOGGER YGConfigSetPrintTreeFlag(&config, true); #endif diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.h b/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.h index 9ad7f28cf03312..9456b0ccc0b1a7 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.h @@ -132,7 +132,9 @@ class YogaLayoutableShadowNode : public LayoutableShadowNode { */ void adoptYogaChild(size_t index); - static YGConfig &initializeYogaConfig(YGConfig &config); + static YGConfig &initializeYogaConfig( + YGConfig &config, + YGConfigRef previousConfig = nullptr); static YGNode *yogaNodeCloneCallbackConnector( YGNode *oldYogaNode, YGNode *parentYogaNode, diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/accessibilityPropsConversions.h b/packages/react-native/ReactCommon/react/renderer/components/view/accessibilityPropsConversions.h index cc918cb9e2c8fd..9ee16674181ede 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/accessibilityPropsConversions.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/accessibilityPropsConversions.h @@ -298,4 +298,486 @@ inline void fromRawValue( } } +inline std::string toString(const AccessibilityRole &accessibilityRole) { + switch (accessibilityRole) { + case AccessibilityRole::None: + return "none"; + case AccessibilityRole::Button: + return "button"; + case AccessibilityRole::Dropdownlist: + return "dropdownlist"; + case AccessibilityRole::Togglebutton: + return "togglebutton"; + case AccessibilityRole::Link: + return "link"; + case AccessibilityRole::Search: + return "search"; + case AccessibilityRole::Image: + return "image"; + case AccessibilityRole::Keyboardkey: + return "keyboardkey"; + case AccessibilityRole::Text: + return "text"; + case AccessibilityRole::Adjustable: + return "adjustable"; + case AccessibilityRole::Imagebutton: + return "imagebutton"; + case AccessibilityRole::Header: + return "header"; + case AccessibilityRole::Summary: + return "summary"; + case AccessibilityRole::Alert: + return "alert"; + case AccessibilityRole::Checkbox: + return "checkbox"; + case AccessibilityRole::Combobox: + return "combobox"; + case AccessibilityRole::Menu: + return "menu"; + case AccessibilityRole::Menubar: + return "menubar"; + case AccessibilityRole::Menuitem: + return "menuitem"; + case AccessibilityRole::Progressbar: + return "progressbar"; + case AccessibilityRole::Radio: + return "radio"; + case AccessibilityRole::Radiogroup: + return "radiogroup"; + case AccessibilityRole::Scrollbar: + return "scrollbar"; + case AccessibilityRole::Spinbutton: + return "spinbutton"; + case AccessibilityRole::Switch: + return "switch"; + case AccessibilityRole::Tab: + return "tab"; + case AccessibilityRole::Tabbar: + return "tabbar"; + case AccessibilityRole::Tablist: + return "tablist"; + case AccessibilityRole::Timer: + return "timer"; + case AccessibilityRole::List: + return "timer"; + case AccessibilityRole::Toolbar: + return "toolbar"; + case AccessibilityRole::Grid: + return "grid"; + case AccessibilityRole::Pager: + return "pager"; + case AccessibilityRole::Scrollview: + return "scrollview"; + case AccessibilityRole::Horizontalscrollview: + return "horizontalscrollview"; + case AccessibilityRole::Viewgroup: + return "viewgroup"; + case AccessibilityRole::Webview: + return "webview"; + case AccessibilityRole::Drawerlayout: + return "drawerlayout"; + case AccessibilityRole::Slidingdrawer: + return "slidingdrawer"; + case AccessibilityRole::Iconmenu: + return "iconmenu"; + } + + LOG(ERROR) << "Unsupported AccessibilityRole value"; + react_native_expect(false); + // sane default for prod + return "none"; +} + +inline void fromRawValue( + const PropsParserContext &context, + const RawValue &value, + AccessibilityRole &result) { + react_native_expect(value.hasType()); + if (value.hasType()) { + auto string = (std::string)value; + if (string == "none") { + result = AccessibilityRole::None; + } else if (string == "button") { + result = AccessibilityRole::Button; + } else if (string == "dropdownlist") { + result = AccessibilityRole::Dropdownlist; + } else if (string == "togglebutton") { + result = AccessibilityRole::Togglebutton; + } else if (string == "link") { + result = AccessibilityRole::Link; + } else if (string == "search") { + result = AccessibilityRole::Search; + } else if (string == "image") { + result = AccessibilityRole::Image; + } else if (string == "keyboardkey") { + result = AccessibilityRole::Keyboardkey; + } else if (string == "text") { + result = AccessibilityRole::Text; + } else if (string == "adjustable") { + result = AccessibilityRole::Adjustable; + } else if (string == "imagebutton") { + result = AccessibilityRole::Imagebutton; + } else if (string == "header") { + result = AccessibilityRole::Header; + } else if (string == "summary") { + result = AccessibilityRole::Summary; + } else if (string == "alert") { + result = AccessibilityRole::Alert; + } else if (string == "checkbox") { + result = AccessibilityRole::Checkbox; + } else if (string == "combobox") { + result = AccessibilityRole::Combobox; + } else if (string == "menu") { + result = AccessibilityRole::Menu; + } else if (string == "menubar") { + result = AccessibilityRole::Menubar; + } else if (string == "menuitem") { + result = AccessibilityRole::Menuitem; + } else if (string == "progressbar") { + result = AccessibilityRole::Progressbar; + } else if (string == "radio") { + result = AccessibilityRole::Radio; + } else if (string == "radiogroup") { + result = AccessibilityRole::Radiogroup; + } else if (string == "scrollbar") { + result = AccessibilityRole::Scrollbar; + } else if (string == "spinbutton") { + result = AccessibilityRole::Spinbutton; + } else if (string == "switch") { + result = AccessibilityRole::Switch; + } else if (string == "tab") { + result = AccessibilityRole::Tab; + } else if (string == "tabbar") { + result = AccessibilityRole::Tabbar; + } else if (string == "tablist") { + result = AccessibilityRole::Tablist; + } else if (string == "timer") { + result = AccessibilityRole::Timer; + } else if (string == "toolbar") { + result = AccessibilityRole::Toolbar; + } else if (string == "grid") { + result = AccessibilityRole::Grid; + } else if (string == "pager") { + result = AccessibilityRole::Pager; + } else if (string == "scrollview") { + result = AccessibilityRole::Scrollview; + } else if (string == "horizontalscrollview") { + result = AccessibilityRole::Horizontalscrollview; + } else if (string == "viewgroup") { + result = AccessibilityRole::Viewgroup; + } else if (string == "webview") { + result = AccessibilityRole::Webview; + } else if (string == "drawerlayout") { + result = AccessibilityRole::Drawerlayout; + } else if (string == "slidingdrawer") { + result = AccessibilityRole::Slidingdrawer; + } else if (string == "iconmenu") { + result = AccessibilityRole::Iconmenu; + } else { + LOG(ERROR) << "Unsupported AccessibilityRole value: " << string; + react_native_expect(false); + // sane default for prod + result = AccessibilityRole::None; + } + return; + } + + LOG(ERROR) << "Unsupported AccessibilityRole type"; + react_native_expect(false); + // sane default for prod + result = AccessibilityRole::None; +} + +inline std::string toString(const Role &role) { + switch (role) { + case Role::Alert: + return "alert"; + case Role::Alertdialog: + return "alertdialog"; + case Role::Application: + return "application"; + case Role::Article: + return "article"; + case Role::Banner: + return "banner"; + case Role::Button: + return "button"; + case Role::Cell: + return "cell"; + case Role::Checkbox: + return "checkbox"; + case Role::Columnheader: + return "columnheader"; + case Role::Combobox: + return "combobox"; + case Role::Complementary: + return "complementary"; + case Role::Contentinfo: + return "contentinfo"; + case Role::Definition: + return "definition"; + case Role::Dialog: + return "dialog"; + case Role::Directory: + return "directory"; + case Role::Document: + return "document"; + case Role::Feed: + return "feed"; + case Role::Figure: + return "figure"; + case Role::Form: + return "form"; + case Role::Grid: + return "grid"; + case Role::Group: + return "group"; + case Role::Heading: + return "heading"; + case Role::Img: + return "img"; + case Role::Link: + return "link"; + case Role::List: + return "list"; + case Role::Listitem: + return "listitem"; + case Role::Log: + return "log"; + case Role::Main: + return "main"; + case Role::Marquee: + return "marquee"; + case Role::Math: + return "math"; + case Role::Menu: + return "menu"; + case Role::Menubar: + return "menubar"; + case Role::Menuitem: + return "menuitem"; + case Role::Meter: + return "meter"; + case Role::Navigation: + return "navigation"; + case Role::None: + return "none"; + case Role::Note: + return "note"; + case Role::Option: + return "option"; + case Role::Presentation: + return "presentation"; + case Role::Progressbar: + return "progressbar"; + case Role::Radio: + return "radio"; + case Role::Radiogroup: + return "radiogroup"; + case Role::Region: + return "region"; + case Role::Row: + return "row"; + case Role::Rowgroup: + return "rowgroup"; + case Role::Rowheader: + return "rowheader"; + case Role::Scrollbar: + return "scrollbar"; + case Role::Searchbox: + return "searchbox"; + case Role::Separator: + return "separator"; + case Role::Slider: + return "slider"; + case Role::Spinbutton: + return "spinbutton"; + case Role::Status: + return "status"; + case Role::Summary: + return "summary"; + case Role::Switch: + return "switch"; + case Role::Tab: + return "tab"; + case Role::Table: + return "table"; + case Role::Tablist: + return "tablist"; + case Role::Tabpanel: + return "tabpanel"; + case Role::Term: + return "term"; + case Role::Timer: + return "timer"; + case Role::Toolbar: + return "toolbar"; + case Role::Tooltip: + return "tooltip"; + case Role::Tree: + return "tree"; + case Role::Treegrid: + return "treegrid"; + case Role::Treeitem: + return "treeitem"; + } + + LOG(ERROR) << "Unsupported Role value"; + react_native_expect(false); + // sane default for prod + return "none"; +} + +inline void fromRawValue( + const PropsParserContext &context, + const RawValue &value, + Role &result) { + react_native_expect(value.hasType()); + if (value.hasType()) { + auto string = (std::string)value; + if (string == "alert") { + result = Role::Alert; + } else if (string == "alertdialog") { + result = Role::Alertdialog; + } else if (string == "application") { + result = Role::Application; + } else if (string == "article") { + result = Role::Article; + } else if (string == "banner") { + result = Role::Banner; + } else if (string == "button") { + result = Role::Button; + } else if (string == "cell") { + result = Role::Cell; + } else if (string == "checkbox") { + result = Role::Checkbox; + } else if (string == "columnheader") { + result = Role::Columnheader; + } else if (string == "combobox") { + result = Role::Combobox; + } else if (string == "complementary") { + result = Role::Complementary; + } else if (string == "contentinfo") { + result = Role::Contentinfo; + } else if (string == "definition") { + result = Role::Definition; + } else if (string == "dialog") { + result = Role::Dialog; + } else if (string == "directory") { + result = Role::Directory; + } else if (string == "document") { + result = Role::Document; + } else if (string == "feed") { + result = Role::Feed; + } else if (string == "figure") { + result = Role::Figure; + } else if (string == "form") { + result = Role::Form; + } else if (string == "grid") { + result = Role::Grid; + } else if (string == "group") { + result = Role::Group; + } else if (string == "heading") { + result = Role::Heading; + } else if (string == "img") { + result = Role::Img; + } else if (string == "link") { + result = Role::Link; + } else if (string == "list") { + result = Role::List; + } else if (string == "listitem") { + result = Role::Listitem; + } else if (string == "log") { + result = Role::Log; + } else if (string == "main") { + result = Role::Main; + } else if (string == "marquee") { + result = Role::Marquee; + } else if (string == "math") { + result = Role::Math; + } else if (string == "menu") { + result = Role::Menu; + } else if (string == "menubar") { + result = Role::Menubar; + } else if (string == "menuitem") { + result = Role::Menuitem; + } else if (string == "meter") { + result = Role::Meter; + } else if (string == "navigation") { + result = Role::Navigation; + } else if (string == "none") { + result = Role::None; + } else if (string == "note") { + result = Role::Note; + } else if (string == "option") { + result = Role::Option; + } else if (string == "presentation") { + result = Role::Presentation; + } else if (string == "progressbar") { + result = Role::Progressbar; + } else if (string == "radio") { + result = Role::Radio; + } else if (string == "radiogroup") { + result = Role::Radiogroup; + } else if (string == "region") { + result = Role::Region; + } else if (string == "row") { + result = Role::Row; + } else if (string == "rowgroup") { + result = Role::Rowgroup; + } else if (string == "rowheader") { + result = Role::Rowheader; + } else if (string == "scrollbar") { + result = Role::Scrollbar; + } else if (string == "searchbox") { + result = Role::Searchbox; + } else if (string == "separator") { + result = Role::Separator; + } else if (string == "slider") { + result = Role::Slider; + } else if (string == "spinbutton") { + result = Role::Spinbutton; + } else if (string == "status") { + result = Role::Status; + } else if (string == "summary") { + result = Role::Summary; + } else if (string == "switch") { + result = Role::Switch; + } else if (string == "tab") { + result = Role::Tab; + } else if (string == "table") { + result = Role::Table; + } else if (string == "tablist") { + result = Role::Tablist; + } else if (string == "tabpanel") { + result = Role::Tabpanel; + } else if (string == "term") { + result = Role::Term; + } else if (string == "timer") { + result = Role::Timer; + } else if (string == "toolbar") { + result = Role::Toolbar; + } else if (string == "tooltip") { + result = Role::Tooltip; + } else if (string == "tree") { + result = Role::Tree; + } else if (string == "treegrid") { + result = Role::Treegrid; + } else if (string == "treeitem") { + result = Role::Treeitem; + } else { + LOG(ERROR) << "Unsupported Role value: " << string; + react_native_expect(false); + // sane default for prod + result = Role::None; + } + return; + } + + LOG(ERROR) << "Unsupported Role type"; + react_native_expect(false); + // sane default for prod + result = Role::None; +} + } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h b/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h index c5dc7d638c033a..85191d843731df 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -408,19 +407,14 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, YGStyle::ValueRepr &result) { - // For bug compatibility, pass "auto" as YGValueUndefined - static bool treatAutoAsUndefined = - context.contextContainer - .at>("ReactNativeConfig") - ->getBool("react_fabric:treat_auto_as_undefined"); - if (value.hasType()) { result = yogaStyleValueFromFloat((Float)value); return; } else if (value.hasType()) { const auto stringValue = (std::string)value; if (stringValue == "auto") { - result = treatAutoAsUndefined ? YGValueUndefined : YGValueAuto; + result = context.treatAutoAsYGValueUndefined() ? YGValueUndefined + : YGValueAuto; return; } else { if (stringValue.back() == '%') { @@ -455,18 +449,8 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, YGFloatOptional &result) { - if (value.hasType()) { - result = YGFloatOptional((float)value); - return; - } else if (value.hasType()) { - const auto stringValue = (std::string)value; - if (stringValue == "auto") { - result = YGFloatOptional(); - return; - } - } - LOG(ERROR) << "Could not parse YGFloatOptional"; - react_native_expect(false); + result = value.hasType() ? YGFloatOptional((float)value) + : YGFloatOptional(); } inline Float toRadians( diff --git a/packages/react-native/ReactCommon/react/renderer/core/CMakeLists.txt b/packages/react-native/ReactCommon/react/renderer/core/CMakeLists.txt index d776881dda16b4..cbbaa6f1f3999e 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/CMakeLists.txt +++ b/packages/react-native/ReactCommon/react/renderer/core/CMakeLists.txt @@ -23,6 +23,7 @@ target_link_libraries(react_render_core folly_runtime glog jsi + react_config react_debug react_render_debug react_render_graphics diff --git a/packages/react-native/ReactCommon/react/renderer/core/ConcreteState.h b/packages/react-native/ReactCommon/react/renderer/core/ConcreteState.h index 952437e43ef73b..640342d1965ff5 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ConcreteState.h +++ b/packages/react-native/ReactCommon/react/renderer/core/ConcreteState.h @@ -43,7 +43,7 @@ class ConcreteState : public State { ShadowNodeFamily::Shared const &family) : State(data, family) {} - virtual ~ConcreteState() = default; + ~ConcreteState() override = default; /* * Returns stored data. @@ -101,9 +101,10 @@ class ConcreteState : public State { return getData().getDynamic(); } - void updateState(folly::dynamic data) const override { - updateState(std::move(Data(getData(), data))); + void updateState(folly::dynamic &&data) const override { + updateState(Data(getData(), std::move(data))); } + MapBuffer getMapBuffer() const override { return getData().getMapBuffer(); } diff --git a/packages/react-native/ReactCommon/react/renderer/core/CoreFeatures.cpp b/packages/react-native/ReactCommon/react/renderer/core/CoreFeatures.cpp index f095e117ec8110..351a257d67877e 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/CoreFeatures.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/CoreFeatures.cpp @@ -13,7 +13,8 @@ bool CoreFeatures::enablePropIteratorSetter = false; bool CoreFeatures::enableMapBuffer = false; bool CoreFeatures::blockPaintForUseLayoutEffect = false; bool CoreFeatures::useNativeState = false; -bool CoreFeatures::cacheNSTextStorage = false; bool CoreFeatures::cacheLastTextMeasurement = false; +bool CoreFeatures::cancelImageDownloadsOnRecycle = false; +bool CoreFeatures::disableTransactionCommit = false; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/core/CoreFeatures.h b/packages/react-native/ReactCommon/react/renderer/core/CoreFeatures.h index 69b7f87d3b5840..f9a07875d270f2 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/CoreFeatures.h +++ b/packages/react-native/ReactCommon/react/renderer/core/CoreFeatures.h @@ -34,15 +34,20 @@ class CoreFeatures { // in simple data passing scenarios with JS static bool useNativeState; - // Creating NSTextStorage is relatively expensive operation and we were - // creating it twice. Once when measuring text and once when rendering it. - // This flag caches it inside ParagraphState. - static bool cacheNSTextStorage; - // Yoga might measure multiple times the same Text with the same constraints // This flag enables a caching mechanism to avoid subsequents measurements // of the same Text with the same constrainst. + // On iOS, we also cache NSTextStorage. static bool cacheLastTextMeasurement; + + // Fabric was not cancelling image downloads when was removed + // from view hierarchy. This feature flag enables this feature. + static bool cancelImageDownloadsOnRecycle; + + // On iOS, every transaction is wrapperd in [CATransaction begin] and + // [CATransaction end] This feature flag disables it to measure its impact in + // production. + static bool disableTransactionCommit; }; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.cpp index 87a612befd4fe7..3bc848f468512a 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.cpp @@ -335,36 +335,42 @@ ShadowNode::Shared LayoutableShadowNode::findNodeAtPoint( #if RN_DEBUG_STRING_CONVERTIBLE SharedDebugStringConvertibleList LayoutableShadowNode::getDebugProps() const { - auto list = SharedDebugStringConvertibleList{}; + auto list = ShadowNode::getDebugProps(); + + auto layoutInfo = SharedDebugStringConvertibleList{}; if (!getIsLayoutClean()) { - list.push_back(std::make_shared("dirty")); + layoutInfo.push_back(std::make_shared("dirty")); } auto layoutMetrics = getLayoutMetrics(); auto defaultLayoutMetrics = LayoutMetrics(); - list.push_back(std::make_shared( + layoutInfo.push_back(std::make_shared( "frame", toString(layoutMetrics.frame))); if (layoutMetrics.borderWidth != defaultLayoutMetrics.borderWidth) { - list.push_back(std::make_shared( + layoutInfo.push_back(std::make_shared( "borderWidth", toString(layoutMetrics.borderWidth))); } if (layoutMetrics.contentInsets != defaultLayoutMetrics.contentInsets) { - list.push_back(std::make_shared( + layoutInfo.push_back(std::make_shared( "contentInsets", toString(layoutMetrics.contentInsets))); } if (layoutMetrics.displayType == DisplayType::None) { - list.push_back(std::make_shared("hidden")); + layoutInfo.push_back( + std::make_shared("hidden")); } if (layoutMetrics.layoutDirection == LayoutDirection::RightToLeft) { - list.push_back(std::make_shared("rtl")); + layoutInfo.push_back(std::make_shared("rtl")); } + list.push_back( + std::make_shared("layout", "", layoutInfo)); + return list; } #endif diff --git a/packages/react-native/ReactCommon/react/renderer/core/PropsParserContext.cpp b/packages/react-native/ReactCommon/react/renderer/core/PropsParserContext.cpp new file mode 100644 index 00000000000000..0ceb9fe39e8733 --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/core/PropsParserContext.cpp @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#include "PropsParserContext.h" + +#include + +namespace facebook::react { + +bool PropsParserContext::treatAutoAsYGValueUndefined() const { + if (treatAutoAsYGValueUndefined_ == std::nullopt) { + auto config = + contextContainer.find>( + "ReactNativeConfig"); + treatAutoAsYGValueUndefined_ = config && *config != nullptr + ? (*config)->getBool("react_fabric:treat_auto_as_undefined") + : false; + } + + return *treatAutoAsYGValueUndefined_; +} + +} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/core/PropsParserContext.h b/packages/react-native/ReactCommon/react/renderer/core/PropsParserContext.h index 04ec16f72f19e0..f79bd86b01e8de 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/PropsParserContext.h +++ b/packages/react-native/ReactCommon/react/renderer/core/PropsParserContext.h @@ -7,6 +7,8 @@ #pragma once +#include + #include #include @@ -16,12 +18,23 @@ namespace facebook::react { // It should be used as infrequently as possible - most props can and should // be parsed without any context. struct PropsParserContext { + PropsParserContext( + SurfaceId const surfaceId, + ContextContainer const &contextContainer) + : surfaceId(surfaceId), contextContainer(contextContainer) {} + // Non-copyable PropsParserContext(const PropsParserContext &) = delete; PropsParserContext &operator=(const PropsParserContext &) = delete; SurfaceId const surfaceId; ContextContainer const &contextContainer; + + // Temporary feature flags + bool treatAutoAsYGValueUndefined() const; + + private: + mutable std::optional treatAutoAsYGValueUndefined_; }; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.h b/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.h index 0710143e9bea03..265dc9a921e56c 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.h +++ b/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.h @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -225,4 +226,8 @@ class ShadowNode : public Sealable, ShadowNodeTraits traits_; }; +static_assert( + std::has_virtual_destructor::value, + "ShadowNode must have a virtual destructor"); + } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/core/State.h b/packages/react-native/ReactCommon/react/renderer/core/State.h index d29558d96ea9e5..23932be1b4a8c3 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/State.h +++ b/packages/react-native/ReactCommon/react/renderer/core/State.h @@ -67,7 +67,7 @@ class State { #ifdef ANDROID virtual folly::dynamic getDynamic() const = 0; virtual MapBuffer getMapBuffer() const = 0; - virtual void updateState(folly::dynamic data) const = 0; + virtual void updateState(folly::dynamic &&data) const = 0; #endif protected: diff --git a/packages/react-native/ReactCommon/react/renderer/core/tests/ShadowNodeTest.cpp b/packages/react-native/ReactCommon/react/renderer/core/tests/ShadowNodeTest.cpp index 7a403ede529d5f..65e6705cb582a5 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/tests/ShadowNodeTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/tests/ShadowNodeTest.cpp @@ -221,9 +221,11 @@ TEST_F(ShadowNodeTest, handleCloneFunction) { // Those two nodes are *not* same. EXPECT_NE(nodeAB_, nodeABClone); +#ifndef ANDROID // `secondNodeClone` is an instance of `TestShadowNode`. EXPECT_NE( std::dynamic_pointer_cast(nodeABClone), nullptr); +#endif // Both nodes have same content. EXPECT_EQ(nodeAB_->getTag(), nodeABClone->getTag()); @@ -244,13 +246,9 @@ TEST_F(ShadowNodeTest, handleState) { auto traits = TestShadowNode::BaseTraits(); auto props = std::make_shared(); - auto fragment = ShadowNodeFragment{ - /* .props = */ props, - /* .children = */ ShadowNode::emptySharedShadowNodeSharedList(), - /* .state = */ {}}; auto const initialState = - componentDescriptor_.createInitialState(fragment, family); + componentDescriptor_.createInitialState(props, family); auto firstNode = std::make_shared( ShadowNodeFragment{ @@ -277,18 +275,18 @@ TEST_F(ShadowNodeTest, handleState) { TestShadowNode::ConcreteState::Shared _state = std::static_pointer_cast( initialState); - _state->updateState(TestState{42}); + _state->updateState(TestState()); - thirdNode->setStateData({9001}); + thirdNode->setStateData(TestState()); // State object are compared by pointer, not by value. EXPECT_EQ(firstNode->getState(), secondNode->getState()); EXPECT_NE(firstNode->getState(), thirdNode->getState()); - secondNode->setStateData(TestState{42}); + secondNode->setStateData(TestState()); EXPECT_NE(firstNode->getState(), secondNode->getState()); // State cannot be changed for sealed shadow node. secondNode->sealRecursive(); EXPECT_DEATH_IF_SUPPORTED( - { secondNode->setStateData(TestState{42}); }, + { secondNode->setStateData(TestState()); }, "Attempt to mutate a sealed object."); } diff --git a/packages/react-native/ReactCommon/react/renderer/core/tests/TestComponent.h b/packages/react-native/ReactCommon/react/renderer/core/tests/TestComponent.h index a0c97b9c320b2b..f740e365ef177f 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/tests/TestComponent.h +++ b/packages/react-native/ReactCommon/react/renderer/core/tests/TestComponent.h @@ -18,6 +18,12 @@ #include #include +#ifdef ANDROID +#include +#include +#include +#endif + /** * This defines a set of TestComponent classes: Props, ShadowNode, * ComponentDescriptor. To be used for testing purpose. @@ -25,9 +31,20 @@ namespace facebook::react { -class TestState { - public: - int number; +struct TestState { + TestState() = default; + +#ifdef ANDROID + TestState(TestState const &previousState, folly::dynamic &&data){}; + + folly::dynamic getDynamic() const { + return {}; + } + + MapBuffer getMapBuffer() const { + return MapBufferBuilder::EMPTY(); + } +#endif }; static const char TestComponentName[] = "Test"; diff --git a/packages/react-native/ReactCommon/react/renderer/imagemanager/ImageRequest.h b/packages/react-native/ReactCommon/react/renderer/imagemanager/ImageRequest.h index eaf4b1f6bf302c..78c1b4c8112704 100644 --- a/packages/react-native/ReactCommon/react/renderer/imagemanager/ImageRequest.h +++ b/packages/react-native/ReactCommon/react/renderer/imagemanager/ImageRequest.h @@ -34,20 +34,24 @@ class ImageRequest final { /* * The move constructor. */ - ImageRequest(ImageRequest &&other) noexcept; + ImageRequest(ImageRequest &&other) noexcept = default; /* * `ImageRequest` does not support copying by design. */ ImageRequest(const ImageRequest &other) = delete; - ~ImageRequest(); - /** * Set cancelation function. */ void setCancelationFunction(std::function cancelationFunction); + /* + * Calls cancel function if one is defined. Should be when downloading + * image isn't needed anymore. E.g. was removed. + */ + void cancel() const; + /* * Returns the Image Source associated with the request. */ diff --git a/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/cxx/react/renderer/imagemanager/ImageRequest.cpp b/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/cxx/react/renderer/imagemanager/ImageRequest.cpp index ce53a1b65cab3a..a502f65d9c305c 100644 --- a/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/cxx/react/renderer/imagemanager/ImageRequest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/cxx/react/renderer/imagemanager/ImageRequest.cpp @@ -18,17 +18,6 @@ ImageRequest::ImageRequest( // Not implemented. } -ImageRequest::ImageRequest(ImageRequest &&other) noexcept - : imageSource_(std::move(other.imageSource_)), - telemetry_(std::move(other.telemetry_)), - coordinator_(std::move(other.coordinator_)) { - // Not implemented. -} - -ImageRequest::~ImageRequest() { - // Not implemented. -} - const ImageResponseObserverCoordinator &ImageRequest::getObserverCoordinator() const { // Not implemented diff --git a/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/ios/React-ImageManager.podspec b/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/ios/React-ImageManager.podspec index d6fbd78c6d0348..0ef251588cc351 100644 --- a/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/ios/React-ImageManager.podspec +++ b/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/ios/React-ImageManager.podspec @@ -61,4 +61,5 @@ Pod::Spec.new do |s| s.dependency "React-Fabric" s.dependency "React-Core/Default" s.dependency "React-RCTImage" + s.dependency "glog" end diff --git a/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/ImageRequest.cpp b/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/ImageRequest.cpp index e073cc6dfff469..cca7918e2d6d2c 100644 --- a/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/ImageRequest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/ImageRequest.cpp @@ -16,27 +16,17 @@ ImageRequest::ImageRequest( coordinator_ = std::make_shared(); } -ImageRequest::ImageRequest(ImageRequest &&other) noexcept - : imageSource_(std::move(other.imageSource_)), - telemetry_(std::move(other.telemetry_)), - coordinator_(std::move(other.coordinator_)) { - other.coordinator_ = nullptr; - other.cancelRequest_ = nullptr; - other.telemetry_ = nullptr; - other.imageSource_ = {}; +void ImageRequest::setCancelationFunction( + std::function cancelationFunction) { + cancelRequest_ = cancelationFunction; } -ImageRequest::~ImageRequest() { +void ImageRequest::cancel() const { if (cancelRequest_) { cancelRequest_(); } } -void ImageRequest::setCancelationFunction( - std::function cancelationFunction) { - cancelRequest_ = cancelationFunction; -} - const ImageSource &ImageRequest::getImageSource() const { return imageSource_; } diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/Differentiator.cpp b/packages/react-native/ReactCommon/react/renderer/mounting/Differentiator.cpp index 5ac18021200b01..79ecdc34220872 100644 --- a/packages/react-native/ReactCommon/react/renderer/mounting/Differentiator.cpp +++ b/packages/react-native/ReactCommon/react/renderer/mounting/Differentiator.cpp @@ -219,7 +219,7 @@ static void sliceChildShadowNodeViewPairsRecursivelyV2( auto &childShadowNode = *sharedChildShadowNode; #ifndef ANDROID - // Temporary disabled on Android because the mounting infrastructure + // T153547836: Disabled on Android because the mounting infrastructure // is not fully ready yet. if (childShadowNode.getTraits().check(ShadowNodeTraits::Trait::Hidden)) { continue; diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp b/packages/react-native/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp index d3a3f8d129b3ca..7ab89855bfba11 100644 --- a/packages/react-native/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp @@ -768,10 +768,25 @@ TEST_F(StackingContextTest, zIndexAndFlattenedNodes) { }); testViewTree_([](StubViewTree const &viewTree) { - // 5 views in total. +#ifdef ANDROID + // T153547836: Android still mounts views with + // ShadowNodeTraits::Trait::Hidden + + EXPECT_EQ(viewTree.size(), 8); + + // nodeBB_ forms a stacking context + EXPECT_EQ(viewTree.getRootStubView().children.size(), 5); + + // The root view subviews are [6, 10, 9, 5]. + EXPECT_EQ(viewTree.getRootStubView().children.at(0)->tag, 6); + EXPECT_EQ(viewTree.getRootStubView().children.at(1)->tag, 10); + EXPECT_EQ(viewTree.getRootStubView().children.at(2)->tag, 9); + EXPECT_EQ(viewTree.getRootStubView().children.at(3)->tag, 5); + EXPECT_EQ(viewTree.getRootStubView().children.at(4)->tag, 3); +#else EXPECT_EQ(viewTree.size(), 5); - // The root view has all 5 subviews. + // The root view has all 4 subviews. EXPECT_EQ(viewTree.getRootStubView().children.size(), 4); // The root view subviews are [6, 10, 9, 5]. @@ -779,6 +794,7 @@ TEST_F(StackingContextTest, zIndexAndFlattenedNodes) { EXPECT_EQ(viewTree.getRootStubView().children.at(1)->tag, 9); EXPECT_EQ(viewTree.getRootStubView().children.at(2)->tag, 5); EXPECT_EQ(viewTree.getRootStubView().children.at(3)->tag, 3); +#endif }); } diff --git a/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp b/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp index 90d558985b9567..f800ed581a678c 100644 --- a/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp +++ b/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp @@ -131,6 +131,9 @@ Scheduler::Scheduler( CoreFeatures::blockPaintForUseLayoutEffect = reactNativeConfig_->getBool( "react_fabric:block_paint_for_use_layout_effect"); + CoreFeatures::cacheLastTextMeasurement = + reactNativeConfig_->getBool("react_fabric:enable_text_measure_cache"); + if (animationDelegate != nullptr) { animationDelegate->setComponentDescriptorRegistry( componentDescriptorRegistry_); diff --git a/packages/react-native/ReactCommon/react/renderer/templateprocessor/tests/UITemplateProcessorTest.cpp b/packages/react-native/ReactCommon/react/renderer/templateprocessor/tests/UITemplateProcessorTest.cpp index 66de70df621b3b..21e8111da3936e 100644 --- a/packages/react-native/ReactCommon/react/renderer/templateprocessor/tests/UITemplateProcessorTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/templateprocessor/tests/UITemplateProcessorTest.cpp @@ -104,13 +104,13 @@ TEST(UITemplateProcessorTest, testSimpleBytecode) { #ifndef NDEBUG LOG(INFO) << std::endl << root1->getDebugDescription(); #endif - auto props1 = std::dynamic_pointer_cast(root1->getProps()); + auto props1 = std::static_pointer_cast(root1->getProps()); EXPECT_NEAR(props1->opacity, 0.5, 0.001); ASSERT_STREQ(props1->testId.c_str(), "root"); auto children1 = root1->getChildren(); EXPECT_EQ(children1.size(), 1); auto child_props1 = - std::dynamic_pointer_cast(children1.at(0)->getProps()); + std::static_pointer_cast(children1.at(0)->getProps()); ASSERT_STREQ(child_props1->testId.c_str(), "child"); } @@ -143,12 +143,12 @@ TEST(UITemplateProcessorTest, testConditionalBytecode) { #ifndef NDEBUG LOG(INFO) << std::endl << root1->getDebugDescription(); #endif - auto props1 = std::dynamic_pointer_cast(root1->getProps()); + auto props1 = std::static_pointer_cast(root1->getProps()); ASSERT_STREQ(props1->testId.c_str(), "root"); auto children1 = root1->getChildren(); EXPECT_EQ(children1.size(), 1); auto child_props1 = - std::dynamic_pointer_cast(children1.at(0)->getProps()); + std::static_pointer_cast(children1.at(0)->getProps()); ASSERT_STREQ(child_props1->testId.c_str(), "cond_true"); mockSimpleTestValue_ = false; @@ -160,7 +160,7 @@ TEST(UITemplateProcessorTest, testConditionalBytecode) { *componentDescriptorRegistry, nativeModuleRegistry, mockReactNativeConfig_); - auto child_props2 = std::dynamic_pointer_cast( + auto child_props2 = std::static_pointer_cast( root2->getChildren().at(0)->getProps()); ASSERT_STREQ(child_props2->testId.c_str(), "cond_false"); } diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm index dca3ab892c8d15..68388d1c839880 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm @@ -297,6 +297,12 @@ inline static CGFloat RCTEffectiveFontSizeMultiplierFromTextAttributes(const Tex case AccessibilityRole::Button: attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("button"); break; + case AccessibilityRole::Dropdownlist: + attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("dropdownlist"); + break; + case AccessibilityRole::Togglebutton: + attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("togglebutton"); + break; case AccessibilityRole::Link: attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("link"); break; @@ -306,9 +312,6 @@ inline static CGFloat RCTEffectiveFontSizeMultiplierFromTextAttributes(const Tex case AccessibilityRole::Image: attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("image"); break; - case AccessibilityRole::Imagebutton: - attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("imagebutton"); - break; case AccessibilityRole::Keyboardkey: attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("keyboardkey"); break; @@ -318,12 +321,15 @@ inline static CGFloat RCTEffectiveFontSizeMultiplierFromTextAttributes(const Tex case AccessibilityRole::Adjustable: attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("adjustable"); break; - case AccessibilityRole::Summary: - attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("summary"); + case AccessibilityRole::Imagebutton: + attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("imagebutton"); break; case AccessibilityRole::Header: attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("header"); break; + case AccessibilityRole::Summary: + attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("summary"); + break; case AccessibilityRole::Alert: attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("alert"); break; @@ -363,7 +369,7 @@ inline static CGFloat RCTEffectiveFontSizeMultiplierFromTextAttributes(const Tex case AccessibilityRole::Tab: attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("tab"); break; - case AccessibilityRole::TabBar: + case AccessibilityRole::Tabbar: attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("tabbar"); break; case AccessibilityRole::Tablist: @@ -372,9 +378,39 @@ inline static CGFloat RCTEffectiveFontSizeMultiplierFromTextAttributes(const Tex case AccessibilityRole::Timer: attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("timer"); break; + case AccessibilityRole::List: + attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("list"); + break; case AccessibilityRole::Toolbar: attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("toolbar"); break; + case AccessibilityRole::Grid: + attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("grid"); + break; + case AccessibilityRole::Pager: + attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("pager"); + break; + case AccessibilityRole::Scrollview: + attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("scrollview"); + break; + case AccessibilityRole::Horizontalscrollview: + attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("horizontalscrollview"); + break; + case AccessibilityRole::Viewgroup: + attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("viewgroup"); + break; + case AccessibilityRole::Webview: + attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("webview"); + break; + case AccessibilityRole::Drawerlayout: + attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("drawerlayout"); + break; + case AccessibilityRole::Slidingdrawer: + attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("slidingdrawer"); + break; + case AccessibilityRole::Iconmenu: + attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("iconmenu"); + break; }; } diff --git a/packages/react-native/ReactCommon/react/renderer/timeline/Timeline.cpp b/packages/react-native/ReactCommon/react/renderer/timeline/Timeline.cpp index 5fb3bab3948270..7508623581617a 100644 --- a/packages/react-native/ReactCommon/react/renderer/timeline/Timeline.cpp +++ b/packages/react-native/ReactCommon/react/renderer/timeline/Timeline.cpp @@ -110,7 +110,8 @@ void Timeline::rewind(TimelineSnapshot const &snapshot) const noexcept { -> RootShadowNode::Unshared { return std::static_pointer_cast( rootShadowNode->ShadowNode::clone({})); - }); + }, + {}); assert(rewinding_ && ""); rewinding_ = false; diff --git a/packages/react-native/ReactCommon/react/renderer/timeline/TimelineController.cpp b/packages/react-native/ReactCommon/react/renderer/timeline/TimelineController.cpp index 82f31db63dbc96..68749cc6c2e485 100644 --- a/packages/react-native/ReactCommon/react/renderer/timeline/TimelineController.cpp +++ b/packages/react-native/ReactCommon/react/renderer/timeline/TimelineController.cpp @@ -15,8 +15,7 @@ namespace facebook::react { TimelineHandler TimelineController::enable(SurfaceId surfaceId) const { assert(uiManager_); - auto shadowTreePtr = (ShadowTree const *){}; - + ShadowTree const *shadowTreePtr = nullptr; uiManager_->getShadowTreeRegistry().visit( surfaceId, [&](ShadowTree const &shadowTree) { shadowTreePtr = &shadowTree; }); @@ -24,7 +23,7 @@ TimelineHandler TimelineController::enable(SurfaceId surfaceId) const { assert(shadowTreePtr); { - std::unique_lock lock(timelinesMutex_); + std::unique_lock lock(timelinesMutex_); auto timeline = std::make_unique(*shadowTreePtr); auto handler = TimelineHandler{*timeline}; @@ -34,7 +33,7 @@ TimelineHandler TimelineController::enable(SurfaceId surfaceId) const { } void TimelineController::disable(TimelineHandler &&handler) const { - std::unique_lock lock(timelinesMutex_); + std::unique_lock lock(timelinesMutex_); auto iterator = timelines_.find(handler.getSurfaceId()); assert(iterator != timelines_.end()); @@ -56,7 +55,7 @@ RootShadowNode::Unshared TimelineController::shadowTreeWillCommit( ShadowTree const &shadowTree, RootShadowNode::Shared const &oldRootShadowNode, RootShadowNode::Unshared const &newRootShadowNode) const noexcept { - std::shared_lock lock(timelinesMutex_); + std::shared_lock lock(timelinesMutex_); assert(uiManager_ && "`uiManager_` must not be `nullptr`."); diff --git a/packages/react-native/ReactCommon/react/renderer/timeline/TimelineController.h b/packages/react-native/ReactCommon/react/renderer/timeline/TimelineController.h index f328677e05d082..fe09e203cc9f18 100644 --- a/packages/react-native/ReactCommon/react/renderer/timeline/TimelineController.h +++ b/packages/react-native/ReactCommon/react/renderer/timeline/TimelineController.h @@ -8,6 +8,7 @@ #pragma once #include +#include #include @@ -64,7 +65,7 @@ class TimelineController final : public UIManagerCommitHook { /* * Protects all the data members. */ - mutable butter::shared_mutex timelinesMutex_; + mutable std::shared_mutex timelinesMutex_; /* * Owning collection of all running `Timeline` instances. diff --git a/packages/react-native/ReactCommon/yoga/CMakeLists.txt b/packages/react-native/ReactCommon/yoga/CMakeLists.txt index ff370aa76ebd05..644c6cb1b132e0 100644 --- a/packages/react-native/ReactCommon/yoga/CMakeLists.txt +++ b/packages/react-native/ReactCommon/yoga/CMakeLists.txt @@ -6,17 +6,9 @@ cmake_minimum_required(VERSION 3.13) set(CMAKE_VERBOSE_MAKEFILE on) -add_compile_options( - -fexceptions - -frtti - -O3 - -Wall - -Wpedantic - -Wno-gnu-zero-variadic-macro-arguments) +# Yoga by default does not enable optimizations in debug builds. Enable -O2 +# for all builds in RN for faster debug app performance (at the cost of not +# being able to debug inside Yoga) +set(CMAKE_BUILD_TYPE Release) -file(GLOB_RECURSE yogacore_SRC CONFIGURE_DEPENDS yoga/*.cpp) -add_library(yogacore STATIC ${yogacore_SRC}) - -target_include_directories(yogacore PUBLIC .) - -target_link_libraries(yogacore android log) +add_subdirectory(yoga) diff --git a/packages/react-native/ReactCommon/yoga/cmake/project-defaults.cmake b/packages/react-native/ReactCommon/yoga/cmake/project-defaults.cmake new file mode 100644 index 00000000000000..87f0e6b791a614 --- /dev/null +++ b/packages/react-native/ReactCommon/yoga/cmake/project-defaults.cmake @@ -0,0 +1,50 @@ +# 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. + +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_VISIBILITY_PRESET hidden) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +add_compile_definitions($<$:DEBUG>) + +if(MSVC) + +add_compile_options( + # Don't omit frame pointers (e.g. for crash dumps) + /Oy- + # "Standard C++ exception handling" (C++ stack unwinding including extern c) + /EHsc + # Enable warnings and warnings as errors + /W3 + /WX + # Disable RTTI + $<$:/GR-> + # Use /O2 (Maximize Speed) + $<$:/O2>) + +else() + +add_compile_options( + # Don't omit frame pointers (e.g. for crash dumps) + -fno-omit-frame-pointer + # Enable exception handling + -fexceptions + # Enable warnings and warnings as errors + -Wall + -Werror + # Disable RTTI + $<$:-fno-rtti> + # Use -O2 (prioritize speed) + $<$:-O2> + # Enable separate sections per function/data item + $<$:-ffunction-sections> + $<$:-fdata-sections>) + +add_link_options( + # Discard unused sections + $<$:$<$:-Wl,--gc-sections>> + $<$:$<$:-Wl,-dead_strip>>) + +endif() diff --git a/packages/react-native/ReactCommon/yoga/cmake/yoga-config.cmake.in b/packages/react-native/ReactCommon/yoga/cmake/yoga-config.cmake.in new file mode 100644 index 00000000000000..80b2dc51c838f1 --- /dev/null +++ b/packages/react-native/ReactCommon/yoga/cmake/yoga-config.cmake.in @@ -0,0 +1,10 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/yogaTargets.cmake") + +check_required_components(yoga) \ No newline at end of file diff --git a/packages/react-native/ReactCommon/yoga/yoga/BitUtils.h b/packages/react-native/ReactCommon/yoga/yoga/BitUtils.h index c8247e1390cf4f..e544defae72248 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/BitUtils.h +++ b/packages/react-native/ReactCommon/yoga/yoga/BitUtils.h @@ -10,7 +10,8 @@ #include #include #include -#include "YGEnums.h" + +#include namespace facebook { namespace yoga { diff --git a/packages/react-native/ReactCommon/yoga/yoga/CMakeLists.txt b/packages/react-native/ReactCommon/yoga/yoga/CMakeLists.txt index e51f36795388b5..b6eca1ac7232de 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/CMakeLists.txt +++ b/packages/react-native/ReactCommon/yoga/yoga/CMakeLists.txt @@ -4,7 +4,7 @@ # LICENSE file in the root directory of this source tree. -cmake_minimum_required(VERSION 3.13) +cmake_minimum_required(VERSION 3.13...3.26) project(yogacore) set(CMAKE_VERBOSE_MAKEFILE on) diff --git a/packages/react-native/ReactCommon/yoga/yoga/CompactValue.h b/packages/react-native/ReactCommon/yoga/yoga/CompactValue.h index 26859330f3ba16..20462ce35d4fcc 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/CompactValue.h +++ b/packages/react-native/ReactCommon/yoga/yoga/CompactValue.h @@ -7,6 +7,13 @@ #pragma once +#include +#include +#include + +#include +#include + #if defined(__has_include) && __has_include() // needed to be able to evaluate defined(__cpp_lib_bit_cast) #include @@ -20,11 +27,6 @@ #else #include #endif -#include "YGValue.h" -#include "YGMacros.h" -#include -#include -#include static_assert( std::numeric_limits::is_iec559, diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGConfig.cpp b/packages/react-native/ReactCommon/yoga/yoga/YGConfig.cpp index 3c24ee4775f609..5bf85f4a1b82df 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGConfig.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/YGConfig.cpp @@ -7,7 +7,18 @@ #include "YGConfig.h" -using namespace facebook::yoga::detail; +using namespace facebook::yoga; + +namespace facebook { +namespace yoga { +bool configUpdateInvalidatesLayout(YGConfigRef a, YGConfigRef b) { + return a->getErrata() != b->getErrata() || + a->getEnabledExperiments() != b->getEnabledExperiments() || + a->getPointScaleFactor() != b->getPointScaleFactor() || + a->useWebDefaults() != b->useWebDefaults(); +} +} // namespace yoga +} // namespace facebook YGConfig::YGConfig(YGLogger logger) : cloneNodeCallback_{nullptr} { setLogger(logger); @@ -40,14 +51,30 @@ bool YGConfig::isExperimentalFeatureEnabled( return experimentalFeatures_.test(feature); } +ExperimentalFeatureSet YGConfig::getEnabledExperiments() const { + return experimentalFeatures_; +} + void YGConfig::setErrata(YGErrata errata) { errata_ = errata; } +void YGConfig::addErrata(YGErrata errata) { + errata_ |= errata; +} + +void YGConfig::removeErrata(YGErrata errata) { + errata_ &= (~errata); +} + YGErrata YGConfig::getErrata() const { return errata_; } +bool YGConfig::hasErrata(YGErrata errata) const { + return (errata_ & errata) != YGErrataNone; +} + void YGConfig::setPointScaleFactor(float pointScaleFactor) { pointScaleFactor_ = pointScaleFactor; } diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGConfig.h b/packages/react-native/ReactCommon/yoga/yoga/YGConfig.h index 4d4038de9f6e4d..d7c7f49fde979f 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGConfig.h +++ b/packages/react-native/ReactCommon/yoga/yoga/YGConfig.h @@ -7,14 +7,20 @@ #pragma once -#include "Yoga-internal.h" -#include "Yoga.h" +#include + #include "BitUtils.h" +#include "Yoga-internal.h" namespace facebook { namespace yoga { -namespace detail { +// Whether moving a node from config "a" to config "b" should dirty previously +// calculated layout results. +bool configUpdateInvalidatesLayout(YGConfigRef a, YGConfigRef b); + +// Internal variants of log functions, currently used only by JNI bindings. +// TODO: Reconcile this with the public API using LogWithContextFn = int (*)( YGConfigRef config, YGNodeRef node, @@ -28,8 +34,12 @@ using CloneWithContextFn = YGNodeRef (*)( int childIndex, void* cloneContext); +using ExperimentalFeatureSet = + facebook::yoga::detail::EnumBitset; + #pragma pack(push) #pragma pack(1) +// Packed structure of <32-bit options to miminize size per node. struct YGConfigFlags { bool useWebDefaults : 1; bool printTree : 1; @@ -38,7 +48,6 @@ struct YGConfigFlags { }; #pragma pack(pop) -} // namespace detail } // namespace yoga } // namespace facebook @@ -55,9 +64,13 @@ struct YOGA_EXPORT YGConfig { YGExperimentalFeature feature, bool enabled); bool isExperimentalFeatureEnabled(YGExperimentalFeature feature) const; + facebook::yoga::ExperimentalFeatureSet getEnabledExperiments() const; void setErrata(YGErrata errata); + void addErrata(YGErrata errata); + void removeErrata(YGErrata errata); YGErrata getErrata() const; + bool hasErrata(YGErrata errata) const; void setPointScaleFactor(float pointScaleFactor); float getPointScaleFactor() const; @@ -66,13 +79,12 @@ struct YOGA_EXPORT YGConfig { void* getContext() const; void setLogger(YGLogger logger); - void setLogger(facebook::yoga::detail::LogWithContextFn logger); + void setLogger(facebook::yoga::LogWithContextFn logger); void setLogger(std::nullptr_t); void log(YGConfig*, YGNode*, YGLogLevel, void*, const char*, va_list) const; void setCloneNodeCallback(YGCloneNodeFunc cloneNode); - void setCloneNodeCallback( - facebook::yoga::detail::CloneWithContextFn cloneNode); + void setCloneNodeCallback(facebook::yoga::CloneWithContextFn cloneNode); void setCloneNodeCallback(std::nullptr_t); YGNodeRef cloneNode( YGNodeRef node, @@ -82,17 +94,16 @@ struct YOGA_EXPORT YGConfig { private: union { - facebook::yoga::detail::CloneWithContextFn withContext; + facebook::yoga::CloneWithContextFn withContext; YGCloneNodeFunc noContext; } cloneNodeCallback_; union { - facebook::yoga::detail::LogWithContextFn withContext; + facebook::yoga::LogWithContextFn withContext; YGLogger noContext; } logger_; - facebook::yoga::detail::YGConfigFlags flags_{}; - facebook::yoga::detail::EnumBitset - experimentalFeatures_{}; + facebook::yoga::YGConfigFlags flags_{}; + facebook::yoga::ExperimentalFeatureSet experimentalFeatures_{}; YGErrata errata_ = YGErrataNone; float pointScaleFactor_ = 1.0f; void* context_ = nullptr; diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGEnums.cpp b/packages/react-native/ReactCommon/yoga/yoga/YGEnums.cpp index 50cc418a9145ad..96b424a3bfd6e9 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGEnums.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/YGEnums.cpp @@ -7,7 +7,7 @@ // @generated by enums.py -#include "YGEnums.h" +#include const char* YGAlignToString(const YGAlign value) { switch (value) { diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGEnums.h b/packages/react-native/ReactCommon/yoga/yoga/YGEnums.h index eb4fbe7273b51f..72146fe279867e 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGEnums.h +++ b/packages/react-native/ReactCommon/yoga/yoga/YGEnums.h @@ -8,7 +8,7 @@ // @generated by enums.py #pragma once -#include "YGMacros.h" +#include // clang-format off diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGMacros.h b/packages/react-native/ReactCommon/yoga/yoga/YGMacros.h index 0ce8c2eed4ce10..cd137117d27d52 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGMacros.h +++ b/packages/react-native/ReactCommon/yoga/yoga/YGMacros.h @@ -19,6 +19,14 @@ #define YG_EXTERN_C_END #endif +#if defined(__cplusplus) +#define YG_DEPRECATED(message) [[deprecated(message)]] +#elif defined(_MSC_VER) +#define YG_DEPRECATED(message) __declspec(deprecated(message)) +#else +#define YG_DEPRECATED(message) __attribute__((deprecated(message))) +#endif + #ifdef _WINDLL #define WIN_EXPORT __declspec(dllexport) #else diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGNode.cpp b/packages/react-native/ReactCommon/yoga/yoga/YGNode.cpp index d2b3d5c7174edd..cd323b54122ee9 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGNode.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/YGNode.cpp @@ -21,7 +21,7 @@ YGNode::YGNode(const YGConfigRef config) : config_{config} { if (config->useWebDefaults()) { useWebDefaults(); } -}; +} YGNode::YGNode(YGNode&& node) { context_ = node.context_; @@ -269,6 +269,11 @@ void YGNode::setConfig(YGConfigRef config) { config, config->useWebDefaults() == config_->useWebDefaults(), "UseWebDefaults may not be changed after constructing a YGNode"); + + if (yoga::configUpdateInvalidatesLayout(config_, config)) { + markDirtyAndPropagate(); + } + config_ = config; } diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGNode.h b/packages/react-native/ReactCommon/yoga/yoga/YGNode.h index 6f9cab38e5b9c3..e3c202f2b9f684 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGNode.h +++ b/packages/react-native/ReactCommon/yoga/yoga/YGNode.h @@ -118,6 +118,8 @@ struct YOGA_EXPORT YGNode { float baseline(float width, float height, void* layoutContext); + bool hasErrata(YGErrata errata) const { return config_->hasErrata(errata); } + YGDirtiedFunc getDirtied() const { return dirtied_; } // For Performance reasons passing as reference. diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGNodePrint.cpp b/packages/react-native/ReactCommon/yoga/yoga/YGNodePrint.cpp index 7e53549c26a83c..d4d3499a3f8ae5 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGNodePrint.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/YGNodePrint.cpp @@ -6,9 +6,12 @@ */ #ifdef DEBUG -#include "YGNodePrint.h" + #include -#include "YGEnums.h" + +#include + +#include "YGNodePrint.h" #include "YGNode.h" #include "Yoga-internal.h" #include "Utils.h" diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGNodePrint.h b/packages/react-native/ReactCommon/yoga/yoga/YGNodePrint.h index f06d457c4dd019..ac550e9611c295 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGNodePrint.h +++ b/packages/react-native/ReactCommon/yoga/yoga/YGNodePrint.h @@ -11,7 +11,7 @@ #include -#include "Yoga.h" +#include namespace facebook { namespace yoga { diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGStyle.h b/packages/react-native/ReactCommon/yoga/yoga/YGStyle.h index 20ce4e056256b9..4f182d0691ec3f 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGStyle.h +++ b/packages/react-native/ReactCommon/yoga/yoga/YGStyle.h @@ -11,11 +11,12 @@ #include #include #include + +#include + #include "CompactValue.h" -#include "YGEnums.h" #include "YGFloatOptional.h" #include "Yoga-internal.h" -#include "Yoga.h" #include "BitUtils.h" class YOGA_EXPORT YGStyle { diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGValue.cpp b/packages/react-native/ReactCommon/yoga/yoga/YGValue.cpp index 89ff41bab117c1..194d22caa87882 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGValue.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/YGValue.cpp @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#include "YGValue.h" +#include const YGValue YGValueZero = {0, YGUnitPoint}; const YGValue YGValueUndefined = {YGUndefined, YGUnitUndefined}; diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGValue.h b/packages/react-native/ReactCommon/yoga/yoga/YGValue.h index 11beb3ec8b74ac..59f6f5e46196f1 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGValue.h +++ b/packages/react-native/ReactCommon/yoga/yoga/YGValue.h @@ -7,28 +7,11 @@ #pragma once -#include -#include "YGEnums.h" -#include "YGMacros.h" +#include +#include -#if defined(_MSC_VER) && defined(__clang__) -#define COMPILING_WITH_CLANG_ON_WINDOWS -#endif -#if defined(COMPILING_WITH_CLANG_ON_WINDOWS) -#include -constexpr float YGUndefined = std::numeric_limits::quiet_NaN(); -#else YG_EXTERN_C_BEGIN -// Not defined in MSVC++ -#ifndef NAN -static const uint32_t __nan = 0x7fc00000; -#define NAN (*(const float*) __nan) -#endif - -#define YGUndefined NAN -#endif - typedef struct YGValue { float value; YGUnit unit; @@ -38,13 +21,17 @@ YOGA_EXPORT extern const YGValue YGValueAuto; YOGA_EXPORT extern const YGValue YGValueUndefined; YOGA_EXPORT extern const YGValue YGValueZero; -#if !defined(COMPILING_WITH_CLANG_ON_WINDOWS) YG_EXTERN_C_END -#endif -#undef COMPILING_WITH_CLANG_ON_WINDOWS #ifdef __cplusplus +#include +constexpr float YGUndefined = std::numeric_limits::quiet_NaN(); +#else +#include +#define YGUndefined NAN +#endif +#ifdef __cplusplus inline bool operator==(const YGValue& lhs, const YGValue& rhs) { if (lhs.unit != rhs.unit) { return false; @@ -69,27 +56,4 @@ inline bool operator!=(const YGValue& lhs, const YGValue& rhs) { inline YGValue operator-(const YGValue& value) { return {-value.value, value.unit}; } - -namespace facebook { -namespace yoga { -namespace literals { - -inline YGValue operator"" _pt(long double value) { - return YGValue{static_cast(value), YGUnitPoint}; -} -inline YGValue operator"" _pt(unsigned long long value) { - return operator"" _pt(static_cast(value)); -} - -inline YGValue operator"" _percent(long double value) { - return YGValue{static_cast(value), YGUnitPercent}; -} -inline YGValue operator"" _percent(unsigned long long value) { - return operator"" _percent(static_cast(value)); -} - -} // namespace literals -} // namespace yoga -} // namespace facebook - #endif diff --git a/packages/react-native/ReactCommon/yoga/yoga/Yoga-internal.h b/packages/react-native/ReactCommon/yoga/yoga/Yoga-internal.h index e6f370d6bfa5d2..5c5f11c77b0672 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/Yoga-internal.h +++ b/packages/react-native/ReactCommon/yoga/yoga/Yoga-internal.h @@ -11,8 +11,10 @@ #include #include #include + +#include + #include "CompactValue.h" -#include "Yoga.h" using YGVector = std::vector; @@ -25,6 +27,10 @@ void YGNodeCalculateLayoutWithContext( YGDirection ownerDirection, void* layoutContext); +// Deallocates a Yoga Node. Unlike YGNodeFree, does not remove the node from +// its parent or children. +void YGNodeDeallocate(YGNodeRef node); + YG_EXTERN_C_END namespace facebook { diff --git a/packages/react-native/ReactCommon/yoga/yoga/Yoga.cpp b/packages/react-native/ReactCommon/yoga/yoga/Yoga.cpp index 6201efb0252ea9..798972c0a420ce 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/Yoga.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/Yoga.cpp @@ -5,28 +5,20 @@ * LICENSE file in the root directory of this source tree. */ -#include "Yoga.h" -#include "log.h" #include #include #include #include #include + +#include + +#include "log.h" #include "Utils.h" #include "YGNode.h" #include "YGNodePrint.h" #include "Yoga-internal.h" #include "event/event.h" -#ifdef _MSC_VER -#include - -/* define fmaxf if < VC12 */ -#if _MSC_VER < 1800 -__forceinline const float fmaxf(const float a, const float b) { - return (a > b) ? a : b; -} -#endif -#endif using namespace facebook::yoga; using detail::Log; @@ -50,8 +42,8 @@ static int YGDefaultLog( #ifdef ANDROID #include static int YGAndroidLog( - const YGConfigRef config, - const YGNodeRef node, + const YGConfigRef /*config*/, + const YGNodeRef /*node*/, YGLogLevel level, const char* format, va_list args) { @@ -238,6 +230,10 @@ YOGA_EXPORT void YGNodeFree(const YGNodeRef node) { } node->clearChildren(); + YGNodeDeallocate(node); +} + +YOGA_EXPORT void YGNodeDeallocate(const YGNodeRef node) { Event::publish(node, {node->getConfig()}); delete node; } @@ -849,7 +845,7 @@ YOGA_EXPORT void YGNodeStyleSetMinWidthPercent( } YOGA_EXPORT YGValue YGNodeStyleGetMinWidth(const YGNodeConstRef node) { return node->getStyle().minDimensions()[YGDimensionWidth]; -}; +} YOGA_EXPORT void YGNodeStyleSetMinHeight( const YGNodeRef node, @@ -867,7 +863,7 @@ YOGA_EXPORT void YGNodeStyleSetMinHeightPercent( } YOGA_EXPORT YGValue YGNodeStyleGetMinHeight(const YGNodeConstRef node) { return node->getStyle().minDimensions()[YGDimensionHeight]; -}; +} YOGA_EXPORT void YGNodeStyleSetMaxWidth( const YGNodeRef node, @@ -885,7 +881,7 @@ YOGA_EXPORT void YGNodeStyleSetMaxWidthPercent( } YOGA_EXPORT YGValue YGNodeStyleGetMaxWidth(const YGNodeConstRef node) { return node->getStyle().maxDimensions()[YGDimensionWidth]; -}; +} YOGA_EXPORT void YGNodeStyleSetMaxHeight( const YGNodeRef node, @@ -903,7 +899,7 @@ YOGA_EXPORT void YGNodeStyleSetMaxHeightPercent( } YOGA_EXPORT YGValue YGNodeStyleGetMaxHeight(const YGNodeConstRef node) { return node->getStyle().maxDimensions()[YGDimensionHeight]; -}; +} #define YG_NODE_LAYOUT_PROPERTY_IMPL(type, name, instanceName) \ YOGA_EXPORT type YGNodeLayoutGet##name(const YGNodeRef node) { \ @@ -937,18 +933,18 @@ YOGA_EXPORT YGValue YGNodeStyleGetMaxHeight(const YGNodeConstRef node) { return node->getLayout().instanceName[edge]; \ } -YG_NODE_LAYOUT_PROPERTY_IMPL(float, Left, position[YGEdgeLeft]); -YG_NODE_LAYOUT_PROPERTY_IMPL(float, Top, position[YGEdgeTop]); -YG_NODE_LAYOUT_PROPERTY_IMPL(float, Right, position[YGEdgeRight]); -YG_NODE_LAYOUT_PROPERTY_IMPL(float, Bottom, position[YGEdgeBottom]); -YG_NODE_LAYOUT_PROPERTY_IMPL(float, Width, dimensions[YGDimensionWidth]); -YG_NODE_LAYOUT_PROPERTY_IMPL(float, Height, dimensions[YGDimensionHeight]); -YG_NODE_LAYOUT_PROPERTY_IMPL(YGDirection, Direction, direction()); -YG_NODE_LAYOUT_PROPERTY_IMPL(bool, HadOverflow, hadOverflow()); +YG_NODE_LAYOUT_PROPERTY_IMPL(float, Left, position[YGEdgeLeft]) +YG_NODE_LAYOUT_PROPERTY_IMPL(float, Top, position[YGEdgeTop]) +YG_NODE_LAYOUT_PROPERTY_IMPL(float, Right, position[YGEdgeRight]) +YG_NODE_LAYOUT_PROPERTY_IMPL(float, Bottom, position[YGEdgeBottom]) +YG_NODE_LAYOUT_PROPERTY_IMPL(float, Width, dimensions[YGDimensionWidth]) +YG_NODE_LAYOUT_PROPERTY_IMPL(float, Height, dimensions[YGDimensionHeight]) +YG_NODE_LAYOUT_PROPERTY_IMPL(YGDirection, Direction, direction()) +YG_NODE_LAYOUT_PROPERTY_IMPL(bool, HadOverflow, hadOverflow()) -YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(float, Margin, margin); -YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(float, Border, border); -YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(float, Padding, padding); +YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(float, Margin, margin) +YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(float, Border, border) +YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(float, Padding, padding) std::atomic gCurrentGenerationCount(0); @@ -2988,7 +2984,7 @@ static void YGNodelayoutImpl( availableInnerMainDim = maxInnerMainDim; } else { bool useLegacyStretchBehaviour = - node->getConfig()->getErrata() & YGErrataStretchFlexBasis; + node->hasErrata(YGErrataStretchFlexBasis); if (!useLegacyStretchBehaviour && ((!YGFloatIsUndefined( @@ -4083,6 +4079,10 @@ YOGA_EXPORT void YGConfigSetPointScaleFactor( } } +YOGA_EXPORT float YGConfigGetPointScaleFactor(const YGConfigRef config) { + return config->getPointScaleFactor(); +} + static void YGRoundToPixelGrid( const YGNodeRef node, const double pointScaleFactor, @@ -4313,16 +4313,16 @@ YOGA_EXPORT void YGConfigSetUseWebDefaults( YOGA_EXPORT bool YGConfigGetUseLegacyStretchBehaviour( const YGConfigRef config) { - return config->getErrata() & YGErrataStretchFlexBasis; + return config->hasErrata(YGErrataStretchFlexBasis); } YOGA_EXPORT void YGConfigSetUseLegacyStretchBehaviour( const YGConfigRef config, const bool useLegacyStretchBehaviour) { if (useLegacyStretchBehaviour) { - config->setErrata(config->getErrata() | YGErrataStretchFlexBasis); + config->addErrata(YGErrataStretchFlexBasis); } else { - config->setErrata(config->getErrata() & ~YGErrataStretchFlexBasis); + config->removeErrata(YGErrataStretchFlexBasis); } } diff --git a/packages/react-native/ReactCommon/yoga/yoga/Yoga.h b/packages/react-native/ReactCommon/yoga/yoga/Yoga.h index 69901dda9d21ed..de07aeac8b712a 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/Yoga.h +++ b/packages/react-native/ReactCommon/yoga/yoga/Yoga.h @@ -18,9 +18,9 @@ #include #endif -#include "YGEnums.h" -#include "YGMacros.h" -#include "YGValue.h" +#include +#include +#include YG_EXTERN_C_BEGIN @@ -317,14 +317,26 @@ WIN_EXPORT void YGAssertWithConfig( WIN_EXPORT void YGConfigSetPointScaleFactor( YGConfigRef config, float pixelsInPoint); +WIN_EXPORT float YGConfigGetPointScaleFactor(YGConfigRef config); // Yoga previously had an error where containers would take the maximum space // possible instead of the minimum like they are supposed to. In practice this // resulted in implicit behaviour similar to align-self: stretch; Because this // was such a long-standing bug we must allow legacy users to switch back to // this behaviour. -WIN_EXPORT bool YGConfigGetUseLegacyStretchBehaviour(YGConfigRef config); -WIN_EXPORT void YGConfigSetUseLegacyStretchBehaviour( +WIN_EXPORT YG_DEPRECATED( + "Please use " + "\"YGConfigGetErrata()\"") bool YGConfigGetUseLegacyStretchBehaviour(YGConfigRef + config); +WIN_EXPORT +YG_DEPRECATED( + "\"YGConfigSetUseLegacyStretchBehaviour\" will be removed in the next " + "release. Usage should be replaced with \"YGConfigSetErrata(YGErrataAll)\" " + "to opt out of all future breaking conformance fixes, or " + "\"YGConfigSetErrata(YGErrataStretchFlexBasis)\" to opt out of the " + "specific conformance fix previously disabled by " + "\"UseLegacyStretchBehaviour\".") +void YGConfigSetUseLegacyStretchBehaviour( YGConfigRef config, bool useLegacyStretchBehaviour); diff --git a/packages/react-native/ReactCommon/yoga/yoga/log.cpp b/packages/react-native/ReactCommon/yoga/yoga/log.cpp index dbf7b4376e669c..6cdd3f69f478b3 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/log.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/log.cpp @@ -5,9 +5,9 @@ * LICENSE file in the root directory of this source tree. */ -#include "log.h" +#include -#include "Yoga.h" +#include "log.h" #include "YGConfig.h" #include "YGNode.h" diff --git a/packages/react-native/ReactCommon/yoga/yoga/log.h b/packages/react-native/ReactCommon/yoga/yoga/log.h index 1d270e82e40b9f..419724e22338e3 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/log.h +++ b/packages/react-native/ReactCommon/yoga/yoga/log.h @@ -7,7 +7,7 @@ #pragma once -#include "YGEnums.h" +#include struct YGNode; struct YGConfig; diff --git a/packages/react-native/build.gradle.kts b/packages/react-native/build.gradle.kts index 217bf9379b9543..6ac661e1d42c6f 100644 --- a/packages/react-native/build.gradle.kts +++ b/packages/react-native/build.gradle.kts @@ -14,5 +14,5 @@ plugins { id("com.android.library") version "7.4.2" apply false id("com.android.application") version "7.4.2" apply false id("de.undercouch.download") version "5.0.1" apply false - kotlin("android") version "1.7.22" apply false + kotlin("android") version "1.8.0" apply false } diff --git a/packages/react-native/package.json b/packages/react-native/package.json index 75678a7e3287bf..31ff4085f1175b 100644 --- a/packages/react-native/package.json +++ b/packages/react-native/package.json @@ -1,13 +1,29 @@ { "name": "react-native", "version": "1000.0.0", - "bin": "./cli.js", "description": "A framework for building native apps using React", "license": "MIT", - "repository": "github:facebook/react-native", + "repository": { + "type": "git", + "url": "https://github.com/facebook/react-native.git", + "directory": "packages/react-native" + }, + "homepage": "https://reactnative.dev/", + "keywords": [ + "react", + "react-native", + "android", + "ios", + "mobile", + "cross-platform", + "app-framework", + "mobile-development" + ], + "bugs": "https://github.com/facebook/react-native/issues", "engines": { "node": ">=16" }, + "bin": "./cli.js", "types": "types", "jest-junit": { "outputDirectory": "reports/junit", @@ -90,10 +106,10 @@ "@react-native/virtualized-lists": "^0.73.0", "abort-controller": "^3.0.0", "anser": "^1.4.9", - "base64-js": "^1.1.2", + "base64-js": "^1.5.1", "deprecated-react-native-prop-types": "4.1.0", "event-target-shim": "^5.0.1", - "flow-enums-runtime": "^0.0.5", + "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "jest-environment-node": "^29.2.1", "jsc-android": "^250231.0.0", @@ -104,11 +120,11 @@ "nullthrows": "^1.1.1", "pretty-format": "^26.5.2", "promise": "^8.3.0", - "react-devtools-core": "^4.27.2", + "react-devtools-core": "^4.27.7", "react-refresh": "^0.4.0", "react-shallow-renderer": "^16.15.0", "regenerator-runtime": "^0.13.2", - "scheduler": "^0.23.0", + "scheduler": "0.24.0-canary-efb381bbf-20230505", "stacktrace-parser": "^0.1.10", "whatwg-fetch": "^3.0.0", "ws": "^6.2.2", diff --git a/packages/react-native/scripts/cocoapods/__tests__/codegen_utils-test.rb b/packages/react-native/scripts/cocoapods/__tests__/codegen_utils-test.rb index c68fedeec10768..da138e23b86950 100644 --- a/packages/react-native/scripts/cocoapods/__tests__/codegen_utils-test.rb +++ b/packages/react-native/scripts/cocoapods/__tests__/codegen_utils-test.rb @@ -544,6 +544,7 @@ def get_podspec_no_fabric_no_script [ "\"$(PODS_ROOT)/boost\"", "\"$(PODS_ROOT)/RCT-Folly\"", + "\"$(PODS_ROOT)/DoubleConversion\"", "\"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\"", "\"$(PODS_ROOT)/Headers/Private/React-Fabric\"", "\"$(PODS_ROOT)/Headers/Private/React-RCTFabric\"", @@ -551,6 +552,7 @@ def get_podspec_no_fabric_no_script ].join(' ') }, 'dependencies': { + "DoubleConversion": [], "FBReactNativeSpec": [], "RCT-Folly": [], "RCTRequired": [], @@ -562,7 +564,8 @@ def get_podspec_no_fabric_no_script "ReactCommon/turbomodule/bridging": [], "ReactCommon/turbomodule/core": [], "hermes-engine": [], - 'React-NativeModulesApple': [], + "React-NativeModulesApple": [], + "glog": [], } } end @@ -586,7 +589,7 @@ def get_podspec_when_use_frameworks specs = get_podspec_no_fabric_no_script() specs["pod_target_xcconfig"]["FRAMEWORK_SEARCH_PATHS"].concat([]) - specs["pod_target_xcconfig"]["HEADER_SEARCH_PATHS"].concat(" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_TARGET_SRCROOT)\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-Fabric/React_Fabric.framework/Headers\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-graphics/React_graphics.framework/Headers\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\" \"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers\" \"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-NativeModulesApple/React_NativeModulesApple.framework/Headers\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-RCTFabric/RCTFabric.framework/Headers\"") + specs["pod_target_xcconfig"]["HEADER_SEARCH_PATHS"].concat(" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_TARGET_SRCROOT)\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-Fabric/React_Fabric.framework/Headers\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-FabricImage/React_FabricImage.framework/Headers\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-graphics/React_graphics.framework/Headers\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\" \"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers\" \"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-NativeModulesApple/React_NativeModulesApple.framework/Headers\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-RCTFabric/RCTFabric.framework/Headers\"") specs[:dependencies].merge!({ 'React-graphics': [], diff --git a/packages/react-native/scripts/cocoapods/__tests__/fabric-test.rb b/packages/react-native/scripts/cocoapods/__tests__/fabric-test.rb index 0b47cd891d0b4c..6e91c455f3f379 100644 --- a/packages/react-native/scripts/cocoapods/__tests__/fabric-test.rb +++ b/packages/react-native/scripts/cocoapods/__tests__/fabric-test.rb @@ -46,9 +46,10 @@ def test_setupFabric_whenNewArchEnabled_installPods end def check_installed_pods(prefix) - assert_equal($podInvocationCount, 5) + assert_equal(6, $podInvocationCount) check_pod("React-Fabric", :path => "#{prefix}/ReactCommon") + check_pod("React-FabricImage", :path => "#{prefix}/ReactCommon") check_pod("React-graphics", :path => "#{prefix}/ReactCommon/react/renderer/graphics") check_pod("React-RCTFabric", :path => "#{prefix}/React", :modular_headers => true) check_pod("RCT-Folly/Fabric", :podspec => "#{prefix}/third-party-podspecs/RCT-Folly.podspec") diff --git a/packages/react-native/scripts/cocoapods/__tests__/flipper-test.rb b/packages/react-native/scripts/cocoapods/__tests__/flipper-test.rb index d30b5bc7d98771..2c0659ecc4cd13 100644 --- a/packages/react-native/scripts/cocoapods/__tests__/flipper-test.rb +++ b/packages/react-native/scripts/cocoapods/__tests__/flipper-test.rb @@ -82,7 +82,7 @@ def test_postInstall_updatesThePodCorrectly assert_equal(config.build_settings['SWIFT_VERSION'], '4.1') end - reactCore_target = installer.target_with_name("React-Core") + reactCore_target = installer.target_with_name("React-RCTAppDelegate") reactCore_target.build_configurations.each do |config| if config.name == 'Debug' || config.name == 'CustomConfig' then assert_equal(config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'], ['$(inherited)', 'FB_SONARKIT_ENABLED=1']) @@ -144,6 +144,14 @@ def prepare_mocked_installer BuildConfigurationMock.new("Release", is_debug: false), BuildConfigurationMock.new("CustomConfig", is_debug: true), ] + ), + TargetMock.new( + "React-RCTAppDelegate", + [ + BuildConfigurationMock.new("Debug", is_debug: true), + BuildConfigurationMock.new("Release", is_debug: false), + BuildConfigurationMock.new("CustomConfig", is_debug: true), + ] ) ] ) diff --git a/packages/react-native/scripts/cocoapods/__tests__/jsengine-test.rb b/packages/react-native/scripts/cocoapods/__tests__/jsengine-test.rb index d604176dfe26b0..84ef4a6c346279 100644 --- a/packages/react-native/scripts/cocoapods/__tests__/jsengine-test.rb +++ b/packages/react-native/scripts/cocoapods/__tests__/jsengine-test.rb @@ -105,7 +105,9 @@ def test_setupHermes_whenHermesScriptSucceeds_installsPods assert_equal($podInvocation["React-jsi"][:path], "../../ReactCommon/jsi") assert_equal($podInvocation["React-hermes"][:path], "../../ReactCommon/hermes") assert_equal($podInvocation["libevent"][:version], "~> 2.1.12") - assert_equal($podInvocation["hermes-engine"][:podspec], "../../sdks/hermes/hermes-engine.podspec") + hermes_engine_pod_invocation = $podInvocation["hermes-engine"] + assert_equal(hermes_engine_pod_invocation[:podspec], "../../sdks/hermes-engine/hermes-engine.podspec") + assert_equal(hermes_engine_pod_invocation[:tag], "") end def test_setupHermes_installsPods_installsFabricSubspecWhenFabricEnabled @@ -118,7 +120,9 @@ def test_setupHermes_installsPods_installsFabricSubspecWhenFabricEnabled # Assert assert_equal($podInvocationCount, 4) assert_equal($podInvocation["React-jsi"][:path], "../../ReactCommon/jsi") - assert_equal($podInvocation["hermes-engine"][:podspec], "../../sdks/hermes/hermes-engine.podspec") + hermes_engine_pod_invocation = $podInvocation["hermes-engine"] + assert_equal(hermes_engine_pod_invocation[:podspec], "../../sdks/hermes-engine/hermes-engine.podspec") + assert_equal(hermes_engine_pod_invocation[:tag], "") assert_equal($podInvocation["React-hermes"][:path], "../../ReactCommon/hermes") assert_equal($podInvocation["libevent"][:version], "~> 2.1.12") end diff --git a/packages/react-native/scripts/cocoapods/__tests__/new_architecture-test.rb b/packages/react-native/scripts/cocoapods/__tests__/new_architecture-test.rb index 79e66936efe082..c97349ed15df31 100644 --- a/packages/react-native/scripts/cocoapods/__tests__/new_architecture-test.rb +++ b/packages/react-native/scripts/cocoapods/__tests__/new_architecture-test.rb @@ -129,7 +129,7 @@ def test_installModulesDependencies_whenNewArchEnabledAndNewArchAndNoSearchPaths # Assert assert_equal(spec.compiler_flags, NewArchitectureHelper.folly_compiler_flags) - assert_equal(spec.pod_target_xcconfig["HEADER_SEARCH_PATHS"], "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/Headers/Private/Yoga\" \"$(PODS_ROOT)/DoubleConversion\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\"") + assert_equal(spec.pod_target_xcconfig["HEADER_SEARCH_PATHS"], "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/Headers/Private/Yoga\" \"$(PODS_ROOT)/DoubleConversion\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-FabricImage/React_FabricImage.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\"") assert_equal(spec.pod_target_xcconfig["CLANG_CXX_LANGUAGE_STANDARD"], "c++17") assert_equal(spec.pod_target_xcconfig["OTHER_CPLUSPLUSFLAGS"], "$(inherited) -DRCT_NEW_ARCH_ENABLED=1 -DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1") assert_equal( @@ -137,13 +137,18 @@ def test_installModulesDependencies_whenNewArchEnabledAndNewArchAndNoSearchPaths [ { :dependency_name => "React-Core" }, { :dependency_name => "RCT-Folly", "version"=>"2021.07.22.00" }, + { :dependency_name => "glog" }, { :dependency_name => "React-RCTFabric" }, { :dependency_name => "React-Codegen" }, { :dependency_name => "RCTRequired" }, { :dependency_name => "RCTTypeSafety" }, { :dependency_name => "ReactCommon/turbomodule/bridging" }, { :dependency_name => "ReactCommon/turbomodule/core" }, - { :dependency_name => "React-NativeModulesApple" } + { :dependency_name => "React-NativeModulesApple" }, + { :dependency_name => "Yoga" }, + { :dependency_name => "React-Fabric" }, + { :dependency_name => "React-graphics" }, + { :dependency_name => "hermes-engine" } ]) end @@ -161,13 +166,14 @@ def test_installModulesDependencies_whenNewArchDisabledAndSearchPathsAndCompiler # Assert assert_equal(spec.compiler_flags, "-Wno-nullability-completeness #{NewArchitectureHelper.folly_compiler_flags}") - assert_equal(spec.pod_target_xcconfig["HEADER_SEARCH_PATHS"], "#{other_flags} \"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/Headers/Private/Yoga\" \"$(PODS_ROOT)/DoubleConversion\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\"") + assert_equal(spec.pod_target_xcconfig["HEADER_SEARCH_PATHS"], "#{other_flags} \"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/Headers/Private/Yoga\" \"$(PODS_ROOT)/DoubleConversion\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-FabricImage/React_FabricImage.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\"") assert_equal(spec.pod_target_xcconfig["CLANG_CXX_LANGUAGE_STANDARD"], "c++17") assert_equal( spec.dependencies, [ { :dependency_name => "React-Core" }, { :dependency_name => "RCT-Folly", "version"=>"2021.07.22.00" }, + { :dependency_name => "glog" } ] ) end diff --git a/packages/react-native/scripts/cocoapods/__tests__/test_utils/podSpy.rb b/packages/react-native/scripts/cocoapods/__tests__/test_utils/podSpy.rb index 76da694cf85f73..0c777f83fdcb19 100644 --- a/packages/react-native/scripts/cocoapods/__tests__/test_utils/podSpy.rb +++ b/packages/react-native/scripts/cocoapods/__tests__/test_utils/podSpy.rb @@ -26,7 +26,7 @@ def podSpy_cleanUp $podInvocationCount = 0 end -def pod(name, version = nil, path: nil, configurations: nil, modular_headers: nil, podspec: nil) +def pod(name, version = nil, path: nil, configurations: nil, modular_headers: nil, podspec: nil, tag: nil) $podInvocationCount += 1 params = {} if version != nil then params[:version] = version end @@ -34,5 +34,6 @@ def pod(name, version = nil, path: nil, configurations: nil, modular_headers: ni if configurations != nil then params[:configurations] = configurations end if modular_headers != nil then params[:modular_headers] = modular_headers end if podspec != nil then params[:podspec] = podspec end + if tag != nil then params[:tag] = tag end $podInvocation[name] = params end diff --git a/packages/react-native/scripts/cocoapods/__tests__/utils-test.rb b/packages/react-native/scripts/cocoapods/__tests__/utils-test.rb index 510c4032825a0c..954630097e25a0 100644 --- a/packages/react-native/scripts/cocoapods/__tests__/utils-test.rb +++ b/packages/react-native/scripts/cocoapods/__tests__/utils-test.rb @@ -577,7 +577,7 @@ def test_updateSearchPaths_whenUseFrameworks_addsSearchPaths if pod_name == "SecondTarget" target_installation_result.native_target.build_configurations.each do |config| received_search_path = config.build_settings["HEADER_SEARCH_PATHS"] - expected_Search_path = "$(inherited) \"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_ROOT)/boost\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Graphics/React_graphics.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/imagemanager/platform/ios\"" + expected_Search_path = "$(inherited) \"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_ROOT)/boost\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-FabricImage/React_FabricImage.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Graphics/React_graphics.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/imagemanager/platform/ios\"" assert_equal(received_search_path, expected_Search_path) end else @@ -677,74 +677,6 @@ def test_applyFlagsForFabric_whenFabricDisabled_doNothing assert_equal(config.build_settings["OTHER_CFLAGS"], "$(inherited)") end end - - # ============================= # - # Test - Enable Hermes Profiler # - # ============================= # - - def test_enableHermesProfiler_whenEnableHermesProfileIsTrue_setsFlagsInRelease - # Arrange - first_target = prepare_target("FirstTarget") - second_target = prepare_target("SecondTarget") - third_target = prepare_target("ThirdTarget", "com.apple.product-type.bundle") - user_project_mock = UserProjectMock.new("a/path", [ - prepare_config("Debug"), - prepare_config("Release"), - ], - :native_targets => [ - first_target, - second_target - ] - ) - pods_projects_mock = PodsProjectMock.new([third_target], {"hermes-engine" => {}}) - installer = InstallerMock.new(pods_projects_mock, [ - AggregatedProjectMock.new(user_project_mock) - ]) - - # Act - ReactNativePodsUtils.enable_hermes_profiler(installer, enable_hermes_profiler: true) - - # Assert - installer.target_installation_results.pod_target_installation_results.each do |pod_name, target_installation_result| - target_installation_result.native_target.build_configurations.each do |config| - if config.name != "Release" - assert_nil(config.build_settings["OTHER_CFLAGS"]) - else - assert_equal(config.build_settings["OTHER_CFLAGS"], "$(inherited) -DRCT_REMOTE_PROFILE=1") - end - end - end - end - - def test_enableHermesProfiler_whenEnableHermesProfileIsFalse_doesNothing - # Arrange - first_target = prepare_target("FirstTarget") - second_target = prepare_target("SecondTarget") - third_target = prepare_target("ThirdTarget", "com.apple.product-type.bundle") - user_project_mock = UserProjectMock.new("a/path", [ - prepare_config("Debug"), - prepare_config("Release"), - ], - :native_targets => [ - first_target, - second_target - ] - ) - pods_projects_mock = PodsProjectMock.new([third_target], {"hermes-engine" => {}}) - installer = InstallerMock.new(pods_projects_mock, [ - AggregatedProjectMock.new(user_project_mock) - ]) - - # Act - ReactNativePodsUtils.enable_hermes_profiler(installer) - - # Assert - installer.target_installation_results.pod_target_installation_results.each do |pod_name, target_installation_result| - target_installation_result.native_target.build_configurations.each do |config| - assert_nil(config.build_settings["OTHER_CFLAGS"]) - end - end - end end # ===== # diff --git a/packages/react-native/scripts/cocoapods/codegen_utils.rb b/packages/react-native/scripts/cocoapods/codegen_utils.rb index b16aeb94424902..c980f05762de45 100644 --- a/packages/react-native/scripts/cocoapods/codegen_utils.rb +++ b/packages/react-native/scripts/cocoapods/codegen_utils.rb @@ -80,6 +80,7 @@ def get_react_codegen_spec(package_json_file, folly_version: '2021.07.22.00', fa header_search_paths = [ "\"$(PODS_ROOT)/boost\"", "\"$(PODS_ROOT)/RCT-Folly\"", + "\"$(PODS_ROOT)/DoubleConversion\"", "\"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\"", "\"$(PODS_ROOT)/Headers/Private/React-Fabric\"", "\"$(PODS_ROOT)/Headers/Private/React-RCTFabric\"", @@ -92,6 +93,7 @@ def get_react_codegen_spec(package_json_file, folly_version: '2021.07.22.00', fa "\"$(PODS_ROOT)/DoubleConversion\"", "\"$(PODS_TARGET_SRCROOT)\"", "\"$(PODS_CONFIGURATION_BUILD_DIR)/React-Fabric/React_Fabric.framework/Headers\"", + "\"$(PODS_CONFIGURATION_BUILD_DIR)/React-FabricImage/React_FabricImage.framework/Headers\"", "\"$(PODS_CONFIGURATION_BUILD_DIR)/React-graphics/React_graphics.framework/Headers\"", "\"$(PODS_CONFIGURATION_BUILD_DIR)/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\"", "\"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers\"", @@ -128,7 +130,9 @@ def get_react_codegen_spec(package_json_file, folly_version: '2021.07.22.00', fa "React-jsi": [], "ReactCommon/turbomodule/bridging": [], "ReactCommon/turbomodule/core": [], - "React-NativeModulesApple": [], + "React-NativeModulesApple": [], + "glog": [], + "DoubleConversion": [], } } diff --git a/packages/react-native/scripts/cocoapods/fabric.rb b/packages/react-native/scripts/cocoapods/fabric.rb index 1bd3cb2fb9db9b..3e186dc6c428d5 100644 --- a/packages/react-native/scripts/cocoapods/fabric.rb +++ b/packages/react-native/scripts/cocoapods/fabric.rb @@ -13,4 +13,5 @@ def setup_fabric!(react_native_path: "../node_modules/react-native", new_arch_en pod 'React-RCTFabric', :path => "#{react_native_path}/React", :modular_headers => true pod 'React-ImageManager', :path => "#{react_native_path}/ReactCommon/react/renderer/imagemanager/platform/ios" pod 'RCT-Folly/Fabric', :podspec => "#{react_native_path}/third-party-podspecs/RCT-Folly.podspec" + pod 'React-FabricImage', :path => "#{react_native_path}/ReactCommon" end diff --git a/packages/react-native/scripts/cocoapods/flipper.rb b/packages/react-native/scripts/cocoapods/flipper.rb index 2465a5be891f0f..73371c1df603b1 100644 --- a/packages/react-native/scripts/cocoapods/flipper.rb +++ b/packages/react-native/scripts/cocoapods/flipper.rb @@ -77,8 +77,8 @@ def flipper_post_install(installer) end end - # Enable flipper for React-Core Debug configuration - if target.name == 'React-Core' + # Enable flipper for React-RCTAppDelegate Debug configuration + if target.name == 'React-RCTAppDelegate' target.build_configurations.each do |config| if config.debug? config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = ['$(inherited)', 'FB_SONARKIT_ENABLED=1'] diff --git a/packages/react-native/scripts/cocoapods/jsengine.rb b/packages/react-native/scripts/cocoapods/jsengine.rb index 25ed410bb4c9d3..e4b2dd4e315284 100644 --- a/packages/react-native/scripts/cocoapods/jsengine.rb +++ b/packages/react-native/scripts/cocoapods/jsengine.rb @@ -30,7 +30,11 @@ def setup_hermes!(react_native_path: "../node_modules/react-native", fabric_enab abort unless prep_status == 0 pod 'React-jsi', :path => "#{react_native_path}/ReactCommon/jsi" - pod 'hermes-engine', :podspec => "#{react_native_path}/sdks/hermes/hermes-engine.podspec" + # This `:tag => hermestag` below is only to tell CocoaPods to update hermes-engine when React Native version changes. + # We have custom logic to compute the source for hermes-engine. See sdks/hermes-engine/* + hermestag_file = File.join(react_native_path, "sdks", ".hermesversion") + hermestag = File.exist?(hermestag_file) ? File.read(hermestag_file).strip : '' + pod 'hermes-engine', :podspec => "#{react_native_path}/sdks/hermes-engine/hermes-engine.podspec", :tag => hermestag pod 'React-hermes', :path => "#{react_native_path}/ReactCommon/hermes" pod 'libevent', '~> 2.1.12' end diff --git a/packages/react-native/scripts/cocoapods/new_architecture.rb b/packages/react-native/scripts/cocoapods/new_architecture.rb index c56815784bd21b..a6eac31d9c58cb 100644 --- a/packages/react-native/scripts/cocoapods/new_architecture.rb +++ b/packages/react-native/scripts/cocoapods/new_architecture.rb @@ -67,6 +67,16 @@ def self.modify_flags_for_new_architecture(installer, is_new_arch_enabled) end end + # Set "RCT_DYNAMIC_FRAMEWORKS=1" if pod are installed with USE_FRAMEWORKS=dynamic + # This helps with backward compatibility. + if pod_name == 'React-RCTFabric' && ENV['USE_FRAMEWORKS'] == 'dynamic' + rct_dynamic_framework_flag = " -DRCT_DYNAMIC_FRAMEWORKS=1" + target_installation_result.native_target.build_configurations.each do |config| + prev_build_settings = config.build_settings['OTHER_CPLUSPLUSFLAGS'] != nil ? config.build_settings['OTHER_CPLUSPLUSFLAGS'] : "$(inherithed)" + config.build_settings['OTHER_CPLUSPLUSFLAGS'] = prev_build_settings + rct_dynamic_framework_flag + end + end + target_installation_result.native_target.build_configurations.each do |config| if config.name == "Release" current_flags = config.build_settings['OTHER_CPLUSPLUSFLAGS'] != nil ? config.build_settings['OTHER_CPLUSPLUSFLAGS'] : "$(inherited)" @@ -93,6 +103,7 @@ def self.install_modules_dependencies(spec, new_arch_enabled, folly_version) header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers\"" header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\"" header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\"" + header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-FabricImage/React_FabricImage.framework/Headers\"" header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers\"" header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\"" header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\"" @@ -107,6 +118,7 @@ def self.install_modules_dependencies(spec, new_arch_enabled, folly_version) spec.dependency "React-Core" spec.dependency "RCT-Folly", '2021.07.22.00' + spec.dependency "glog" if new_arch_enabled current_config["OTHER_CPLUSPLUSFLAGS"] = @@new_arch_cpp_flags @@ -118,6 +130,15 @@ def self.install_modules_dependencies(spec, new_arch_enabled, folly_version) spec.dependency "ReactCommon/turbomodule/bridging" spec.dependency "ReactCommon/turbomodule/core" spec.dependency "React-NativeModulesApple" + spec.dependency "Yoga" + spec.dependency "React-Fabric" + spec.dependency "React-graphics" + + if ENV["USE_HERMES"] == nil || ENV["USE_HERMES"] == "1" + spec.dependency "hermes-engine" + else + spec.dependency "React-jsi" + end end spec.pod_target_xcconfig = current_config diff --git a/packages/react-native/scripts/cocoapods/utils.rb b/packages/react-native/scripts/cocoapods/utils.rb index 92a621d994d049..2bed5260603e25 100644 --- a/packages/react-native/scripts/cocoapods/utils.rb +++ b/packages/react-native/scripts/cocoapods/utils.rb @@ -220,13 +220,6 @@ def self.update_search_paths(installer) end end - def self.enable_hermes_profiler(installer, enable_hermes_profiler: false) - return if !enable_hermes_profiler - - Pod::UI.puts "[Hermes Profiler] Enable Hermes Sample profiler" - self.add_compiler_flag_to_pods(installer, "-DRCT_REMOTE_PROFILE=1", configuration: "Release") - end - # ========= # # Utilities # # ========= # @@ -361,6 +354,7 @@ def self.set_rctfabric_search_paths(target_installation_result) ReactNativePodsUtils.update_header_paths_if_depends_on(target_installation_result, "React-RCTFabric", [ "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-FabricImage/React_FabricImage.framework/Headers\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Graphics/React_graphics.framework/Headers\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\"", ]) @@ -384,6 +378,7 @@ def self.react_native_pods "React-Core", "React-CoreModules", "React-Fabric", + "React-FabricImage", "React-ImageManager", "React-RCTActionSheet", "React-RCTAnimation", diff --git a/packages/react-native/scripts/react_native_pods.rb b/packages/react-native/scripts/react_native_pods.rb index 0437407b2f4cee..8b786505cbff8b 100644 --- a/packages/react-native/scripts/react_native_pods.rb +++ b/packages/react-native/scripts/react_native_pods.rb @@ -222,11 +222,10 @@ def use_flipper!(versions = {}, configurations: ['Debug']) # - mac_catalyst_enabled: whether we are running the Pod on a Mac Catalyst project or not. # - enable_hermes_profiler: whether the hermes profiler should be turned on in Release mode def react_native_post_install( - installer, react_native_path = "../node_modules/react-native", - mac_catalyst_enabled: false, - enable_hermes_profiler: false + installer, + react_native_path = "../node_modules/react-native", + mac_catalyst_enabled: false ) - enable_hermes_profiler = enable_hermes_profiler || ENV["ENABLE_HERMES_PROFILER"] == "1" ReactNativePodsUtils.turn_off_resource_bundle_react_core(installer) ReactNativePodsUtils.apply_mac_catalyst_patches(installer) if mac_catalyst_enabled @@ -242,13 +241,11 @@ def react_native_post_install( ReactNativePodsUtils.update_search_paths(installer) ReactNativePodsUtils.set_node_modules_user_settings(installer, react_native_path) ReactNativePodsUtils.apply_flags_for_fabric(installer, fabric_enabled: fabric_enabled) - ReactNativePodsUtils.enable_hermes_profiler(installer, enable_hermes_profiler: enable_hermes_profiler) NewArchitectureHelper.set_clang_cxx_language_standard_if_needed(installer) is_new_arch_enabled = ENV['RCT_NEW_ARCH_ENABLED'] == "1" NewArchitectureHelper.modify_flags_for_new_architecture(installer, is_new_arch_enabled) - Pod::UI.puts "Pod install took #{Time.now.to_i - $START_TIME} [s] to run".green end diff --git a/packages/react-native/template/android/app/build.gradle b/packages/react-native/template/android/app/build.gradle index 5b1826b4127e0b..eb8f4efa97a841 100644 --- a/packages/react-native/template/android/app/build.gradle +++ b/packages/react-native/template/android/app/build.gradle @@ -1,3 +1,10 @@ +/* + * 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. + */ + apply plugin: "com.android.application" apply plugin: "org.jetbrains.kotlin.android" apply plugin: "com.facebook.react" @@ -108,8 +115,6 @@ dependencies { // The version of react-native is set by the React Native Gradle Plugin implementation("com.facebook.react:react-android") - implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.0.0") - debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { exclude group:'com.squareup.okhttp3', module:'okhttp' diff --git a/packages/react-native/template/android/build.gradle b/packages/react-native/template/android/build.gradle index cdbc9026f3552a..4b2e41b3b30e1c 100644 --- a/packages/react-native/template/android/build.gradle +++ b/packages/react-native/template/android/build.gradle @@ -9,7 +9,7 @@ buildscript { // We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP. ndkVersion = "23.1.7779620" - kotlinVersion = "1.7.22" + kotlinVersion = "1.8.0" } repositories { google() @@ -18,6 +18,6 @@ buildscript { dependencies { classpath("com.android.tools.build:gradle") classpath("com.facebook.react:react-native-gradle-plugin") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") } } diff --git a/packages/react-native/template/package.json b/packages/react-native/template/package.json index 06f0f4e2a9bad6..f5572d74706171 100644 --- a/packages/react-native/template/package.json +++ b/packages/react-native/template/package.json @@ -16,10 +16,10 @@ "devDependencies": { "@babel/core": "^7.20.0", "@babel/preset-env": "^7.20.0", - "@babel/runtime": "^7.12.5", + "@babel/runtime": "^7.20.0", "@react-native/eslint-config": "^0.73.0", "@react-native/metro-config": "^0.73.0", - "@tsconfig/react-native": "^3.0.0", + "@react-native/typescript-config": "^0.73.0", "@types/react": "^18.0.24", "@types/react-test-renderer": "^18.0.0", "babel-jest": "^29.2.1", @@ -28,7 +28,7 @@ "metro-react-native-babel-preset": "0.76.2", "prettier": "^2.4.1", "react-test-renderer": "18.2.0", - "typescript": "4.8.4" + "typescript": "5.0.4" }, "engines": { "node": ">=16" diff --git a/packages/react-native/template/tsconfig.json b/packages/react-native/template/tsconfig.json index 45a6c707223871..304ab4e2d83d02 100644 --- a/packages/react-native/template/tsconfig.json +++ b/packages/react-native/template/tsconfig.json @@ -1,3 +1,3 @@ { - "extends": "@tsconfig/react-native/tsconfig.json" + "extends": "@react-native/typescript-config/tsconfig.json" } diff --git a/packages/react-native/types/experimental.d.ts b/packages/react-native/types/experimental.d.ts new file mode 100644 index 00000000000000..c58c9ffa10ac00 --- /dev/null +++ b/packages/react-native/types/experimental.d.ts @@ -0,0 +1,136 @@ +/** + * 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 + */ + +/** + * These are types for things that are present for New Architecture enabled apps + * which is currently considered experimental. + * + * To load the types declared here in an actual project, there are three ways. + * + * 1. If your `tsconfig.json` already has a `"types"` array in the `"compilerOptions"` section, + * is to add `"react-native/types/experimental"` to the `"types"` array. + * + * 2. Alternatively, a specific import syntax can to be used from a typescript file. + * This module does not exist in reality, which is why the {} is important: + * + * ```ts + * import {} from 'react-native/types/experimental' + * ``` + * + * 3. It is also possible to include it through a triple-slash reference: + * + * ```ts + * /// + * ``` + * + * Either the import or the reference only needs to appear once, anywhere in the project. + */ + +import {DimensionValue} from 'react-native/Libraries/StyleSheet/StyleSheetTypes'; + +export {}; + +declare module '.' { + export interface FlexStyle { + /** + * Equivalent to `top`, `bottom`, `right` and `left` + */ + inset?: DimensionValue | undefined; + + /** + * Equivalent to `top`, `bottom` + */ + insetBlock?: DimensionValue | undefined; + + /** + * Equivalent to `bottom` + */ + insetBlockEnd?: DimensionValue | undefined; + + /** + * Equivalent to `top` + */ + insetBlockStart?: DimensionValue | undefined; + + /** + * Equivalent to `right` and `left` + */ + insetInline?: DimensionValue | undefined; + + /** + * Equivalent to `right` or `left` + */ + insetInlineEnd?: DimensionValue | undefined; + + /** + * Equivalent to `right` or `left` + */ + insetInlineStart?: DimensionValue | undefined; + + /** + * Equivalent to `marginVertical` + */ + marginBlock?: DimensionValue | undefined; + + /** + * Equivalent to `marginBottom` + */ + marginBlockEnd?: DimensionValue | undefined; + + /** + * Equivalent to `marginTop` + */ + marginBlockStart?: DimensionValue | undefined; + + /** + * Equivalent to `marginHorizontal` + */ + marginInline?: DimensionValue | undefined; + + /** + * Equivalent to `marginEnd` + */ + marginInlineEnd?: DimensionValue | undefined; + + /** + * Equivalent to `marginStart` + */ + marginInlineStart?: DimensionValue | undefined; + + /** + * Equivalent to `paddingVertical` + */ + paddingBlock?: DimensionValue | undefined; + + /** + * Equivalent to `paddingBottom` + */ + paddingBlockEnd?: DimensionValue | undefined; + + /** + * Equivalent to `paddingTop` + */ + paddingBlockStart?: DimensionValue | undefined; + + /** + * Equivalent to `paddingHorizontal` + */ + paddingInline?: DimensionValue | undefined; + + /** + * Equivalent to `paddingEnd` + */ + paddingInlineEnd?: DimensionValue | undefined; + + /** + * Equivalent to `paddingStart` + */ + paddingInlineStart?: DimensionValue | undefined; + } +} diff --git a/packages/react-native/types/index.d.ts b/packages/react-native/types/index.d.ts index 5177707cc0f7b4..b01002dbc6dc1d 100644 --- a/packages/react-native/types/index.d.ts +++ b/packages/react-native/types/index.d.ts @@ -103,6 +103,7 @@ export * from '../Libraries/Components/View/View'; export * from '../Libraries/Components/View/ViewAccessibility'; export * from '../Libraries/Components/View/ViewPropTypes'; export * from '../Libraries/Components/Button'; +export * from '../Libraries/DevToolsSettings/DevToolsSettingsManager'; export * from '../Libraries/EventEmitter/NativeEventEmitter'; export * from '../Libraries/EventEmitter/RCTDeviceEventEmitter'; export * from '../Libraries/EventEmitter/RCTNativeAppEventEmitter'; diff --git a/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.h b/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.h index 6d7adce1eabb5b..60f930debdfbed 100644 --- a/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.h +++ b/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.h @@ -5,6 +5,7 @@ * LICENSE file in the root directory of this source tree. */ +#import #import #import @@ -12,6 +13,8 @@ NS_ASSUME_NONNULL_BEGIN @interface RNTMyNativeViewComponentView : RCTViewComponentView +@property (nonatomic, copy) RCTBubblingEventBlock onIntArrayChanged; + - (UIColor *)UIColorFromHexString:(const std::string)hexString; @end diff --git a/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.mm b/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.mm index 7fe66d4050d776..5e14c832f9fb08 100644 --- a/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.mm +++ b/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.mm @@ -28,6 +28,14 @@ + (ComponentDescriptorProvider)componentDescriptorProvider return concreteComponentDescriptorProvider(); } +// Load is not invoked if it is not defined, therefore, we must ask to update this. +// See the Apple documentation: https://developer.apple.com/documentation/objectivec/nsobject/1418815-load?language=objc +// "[...] but only if the newly loaded class or category implements a method that can respond." ++ (void)load +{ + [super load]; +} + - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { @@ -58,6 +66,44 @@ - (UIColor *)UIColorFromHexString:(const std::string)hexString - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps { + const auto &oldViewProps = *std::static_pointer_cast(_props); + const auto &newViewProps = *std::static_pointer_cast(props); + + if (oldViewProps.values != newViewProps.values) { + if (_eventEmitter) { + std::vector newVector = {}; + std::vector newBoolVector = {}; + std::vector newFloatVector = {}; + std::vector newDoubleVector = {}; + std::vector newYesNoVector = {}; + std::vector newStringVector = {}; + std::vector newLatLonVector = {}; + std::vector> newIntVectorVector = {}; + for (auto val : newViewProps.values) { + newVector.push_back(val * 2); + newBoolVector.push_back(val % 2 ? true : false); + newFloatVector.push_back(val * 3.14); + newDoubleVector.push_back(val / 3.14); + newYesNoVector.push_back( + val % 2 ? RNTMyNativeViewEventEmitter::OnIntArrayChangedYesNos::Yep + : RNTMyNativeViewEventEmitter::OnIntArrayChangedYesNos::Nope); + newStringVector.push_back(std::to_string(val)); + newLatLonVector.push_back({-1.0 * val, 2.0 * val}); + newIntVectorVector.push_back({val, val, val}); + } + RNTMyNativeViewEventEmitter::OnIntArrayChanged value = { + newVector, + newBoolVector, + newFloatVector, + newDoubleVector, + newYesNoVector, + newStringVector, + newLatLonVector, + newIntVectorVector}; + std::static_pointer_cast(_eventEmitter)->onIntArrayChanged(value); + } + } + [super updateProps:props oldProps:oldProps]; } diff --git a/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewManager.mm b/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewManager.mm index 83d8f231d4259d..6729d8f12cb071 100644 --- a/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewManager.mm +++ b/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewManager.mm @@ -18,6 +18,10 @@ @implementation RNTMyNativeViewManager RCT_EXPORT_VIEW_PROPERTY(backgroundColor, UIColor) +RCT_EXPORT_VIEW_PROPERTY(onIntArrayChanged, RCTBubblingEventBlock) + +RCT_EXPORT_VIEW_PROPERTY(values, NSArray *) + RCT_EXPORT_METHOD(callNativeMethodToChangeBackgroundColor : (nonnull NSNumber *)reactTag color : (NSString *)color) { [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary *viewRegistry) { diff --git a/packages/rn-tester/NativeComponentExample/js/MyNativeView.js b/packages/rn-tester/NativeComponentExample/js/MyNativeView.js index 51a31ae468b3f8..c74c0f084e7648 100644 --- a/packages/rn-tester/NativeComponentExample/js/MyNativeView.js +++ b/packages/rn-tester/NativeComponentExample/js/MyNativeView.js @@ -98,7 +98,22 @@ export default function MyNativeView(props: {}): React.Node { return ( Fabric View - + { + console.log(event.nativeEvent.values); + console.log(event.nativeEvent.boolValues); + console.log(event.nativeEvent.floats); + console.log(event.nativeEvent.doubles); + console.log(event.nativeEvent.yesNos); + console.log(event.nativeEvent.strings); + console.log(event.nativeEvent.latLons); + console.log(event.nativeEvent.multiArrays); + }} + /> Legacy View , + boolValues: $ReadOnlyArray, + floats: $ReadOnlyArray, + doubles: $ReadOnlyArray, + yesNos: $ReadOnlyArray<'yep' | 'nope'>, + strings: $ReadOnlyArray, + latLons: $ReadOnlyArray<{|lat: Double, lon: Double|}>, + multiArrays: $ReadOnlyArray<$ReadOnlyArray>, +}>; + type NativeProps = $ReadOnly<{| ...ViewProps, opacity?: Float, + values: $ReadOnlyArray, + + // Events + onIntArrayChanged?: ?BubblingEventHandler, |}>; export type MyNativeViewType = HostComponent; diff --git a/packages/rn-tester/README.md b/packages/rn-tester/README.md index 688b061cbe8f9f..07eb33e3d2afc9 100644 --- a/packages/rn-tester/README.md +++ b/packages/rn-tester/README.md @@ -5,10 +5,11 @@ The RNTester showcases React Native views and modules. ## Running this app Before running the app, make sure you ran: - - git clone https://github.com/facebook/react-native.git - cd react-native - yarn install +```sh +git clone https://github.com/facebook/react-native.git +cd react-native +yarn install +``` ### Running on iOS @@ -29,11 +30,12 @@ If you are still having a problem after doing the clean up (which can happen if Both macOS and Xcode are required. 1. `cd packages/rn-tester` -1. Install [Bundler](https://bundler.io/): `gem install bundler`. We use bundler to install the right version of [CocoaPods](https://cocoapods.org/) locally. -1. Install Bundler and CocoaPods dependencies: `bundle install && bundle exec pod install` or `yarn setup-ios-hermes`. In order to use JSC instead of Hermes engine, run: `USE_HERMES=0 bundle exec pod install` or `yarn setup-ios-jsc` instead. -1. Open the generated `RNTesterPods.xcworkspace`. This is not checked in, as it is generated by CocoaPods. Do not open `RNTesterPods.xcodeproj` directly. +2. Install [Bundler](https://bundler.io/): `gem install bundler`. We use bundler to install the right version of [CocoaPods](https://cocoapods.org/) locally. +3. Install Bundler and CocoaPods dependencies: `bundle install && bundle exec pod install` or `yarn setup-ios-hermes`. In order to use JSC instead of Hermes engine, run: `USE_HERMES=0 bundle exec pod install` or `yarn setup-ios-jsc` instead. +4. Open the generated `RNTesterPods.xcworkspace`. This is not checked in, as it is generated by CocoaPods. Do not open `RNTesterPods.xcodeproj` directly. #### Note for M1 users + If you own a Mac M1 laptop, you need to run some different commands to install and run cocoapods. - `sudo arch -x86_64 gem install ffi`: this installs the `ffi` package to load dynamically-linked libraries. @@ -44,7 +46,6 @@ If you own a Mac M1 laptop, you need to run some different commands to install a You'll need to have all the [prerequisites](https://reactnative.dev/contributing/how-to-build-from-source#prerequisites) (SDK, NDK) for Building React Native installed. Start an Android emulator. - ```sh cd packages/rn-tester # In order to use Hermes engine, run `yarn install-android-hermes` instead. @@ -65,11 +66,12 @@ Follow the same setup as running with gradle. Install Buck from [here](https://buckbuild.com/setup/install.html). Run the following commands from the react-native folder: - - ./gradlew :ReactAndroid:packageReactNdkLibsForBuck - buck fetch rntester - buck install -r rntester - ./scripts/packager.sh +```sh +./gradlew :ReactAndroid:packageReactNdkLibsForBuck +buck fetch rntester +buck install -r rntester +./scripts/packager.sh +``` _Note: The native libs are still built using gradle. Full build with buck is coming soon(tm)._ diff --git a/packages/rn-tester/RNTester/AppDelegate.mm b/packages/rn-tester/RNTester/AppDelegate.mm index d3f3f355f948f6..bb1cbe68f73ee8 100644 --- a/packages/rn-tester/RNTester/AppDelegate.mm +++ b/packages/rn-tester/RNTester/AppDelegate.mm @@ -49,6 +49,7 @@ #endif #ifdef RN_FABRIC_ENABLED +#import #import #import #import @@ -60,6 +61,10 @@ #import #endif +#if RCT_NEW_ARCH_ENABLED +#import +#endif + #if DEBUG #ifdef FB_SONARKIT_ENABLED #import @@ -85,6 +90,12 @@ @interface AppDelegate () } @end +#if RCT_NEW_ARCH_ENABLED +/// Declare conformance to `RCTComponentViewFactoryComponentProvider` +@interface AppDelegate () +@end +#endif + static NSString *const kRNConcurrentRoot = @"concurrentRoot"; @implementation AppDelegate @@ -110,6 +121,10 @@ - (BOOL)application:(__unused UIApplication *)application didFinishLaunchingWith // Appetizer.io params check NSDictionary *initProps = [self prepareInitialProps]; +#if RCT_NEW_ARCH_ENABLED + [RCTComponentViewFactory currentComponentViewFactory].thirdPartyFabricComponentsProvider = self; +#endif + #ifdef RN_FABRIC_ENABLED _bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:_bridge contextContainer:_contextContainer]; @@ -333,4 +348,13 @@ - (void)application:(__unused UIApplication *)application #endif +#pragma mark - RCTComponentViewFactoryComponentProvider + +#if RCT_NEW_ARCH_ENABLED +- (nonnull NSDictionary> *)thirdPartyFabricComponents +{ + return @{@"RNTMyNativeView" : RNTMyNativeViewComponentView.class}; +} +#endif + @end diff --git a/packages/rn-tester/RNTesterUnitTests/RCTBundleURLProviderTests.m b/packages/rn-tester/RNTesterUnitTests/RCTBundleURLProviderTests.m index 37f45cc4ff0066..4da7d3fa59d145 100644 --- a/packages/rn-tester/RNTesterUnitTests/RCTBundleURLProviderTests.m +++ b/packages/rn-tester/RNTesterUnitTests/RCTBundleURLProviderTests.m @@ -15,12 +15,12 @@ static NSString *const testFile = @"test.jsbundle"; static NSString *const mainBundle = @"main.jsbundle"; -static NSURL *mainBundleURL() +static NSURL *mainBundleURL(void) { return [[[NSBundle mainBundle] bundleURL] URLByAppendingPathComponent:mainBundle]; } -static NSURL *localhostBundleURL() +static NSURL *localhostBundleURL(void) { return [NSURL URLWithString: @@ -30,7 +30,7 @@ testFile]]; } -static NSURL *ipBundleURL() +static NSURL *ipBundleURL(void) { return [NSURL URLWithString: diff --git a/packages/rn-tester/android/app/_BUCK b/packages/rn-tester/android/app/_BUCK deleted file mode 100644 index ba612dfab6988e..00000000000000 --- a/packages/rn-tester/android/app/_BUCK +++ /dev/null @@ -1,39 +0,0 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "KEYSTORE_TARGET", "react_native_dep", "react_native_target", "rn_android_binary", "rn_android_library", "rn_android_resource") - -rn_android_binary( - name = "app", - keystore = KEYSTORE_TARGET, - manifest = "src/main/AndroidManifest.xml", - deps = [ - ":rntester-lib", - ], -) - -rn_android_library( - name = "rntester-lib", - srcs = glob(["src/main/java/**/*.java"]), - deps = [ - ":res", - react_native_dep("libraries/soloader/java/com/facebook/soloader:soloader"), - react_native_dep("third-party/android/androidx:annotation"), - react_native_dep("third-party/android/androidx:appcompat"), - react_native_dep("third-party/android/androidx:core"), - react_native_dep("third-party/android/androidx:fragment"), - react_native_dep("third-party/android/androidx:legacy-support-core-utils"), - react_native_dep("third-party/java/jsr-305:jsr-305"), - react_native_target("java/com/facebook/react:react"), - react_native_target("java/com/facebook/react/common:build_config"), - react_native_target("java/com/facebook/react/modules/core:core"), - react_native_target("java/com/facebook/react/views/text:text"), - react_native_target("java/com/facebook/react/shell:shell"), - react_native_target("jni/prebuilt:android-jsc"), - # .so files are prebuilt by Gradle with `./gradlew :ReactAndroid:packageReactNdkLibsForBuck` - react_native_target("jni/prebuilt:reactnative-libs"), - ], -) - -rn_android_resource( - name = "res", - package = "com.facebook.react.uiapp", - res = "src/main/res", -) diff --git a/packages/rn-tester/android/app/build.gradle b/packages/rn-tester/android/app/build.gradle index b597120366fa47..e9e68fee660565 100644 --- a/packages/rn-tester/android/app/build.gradle +++ b/packages/rn-tester/android/app/build.gradle @@ -116,21 +116,13 @@ android { defaultConfig { applicationId "com.facebook.react.uiapp" - minSdkVersion 21 - targetSdkVersion 33 + minSdk = 21 + targetSdk = 33 versionCode 1 versionName "1.0" testBuildType System.getProperty('testBuildType', 'debug') // This will later be used to control the test apk build type testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' } - signingConfigs { - release { - storeFile file(MYAPP_RELEASE_STORE_FILE) - storePassword MYAPP_RELEASE_STORE_PASSWORD - keyAlias MYAPP_RELEASE_KEY_ALIAS - keyPassword MYAPP_RELEASE_KEY_PASSWORD - } - } externalNativeBuild { cmake { version cmakeVersion @@ -145,15 +137,10 @@ android { } } buildTypes { - debug { - debuggable true - signingConfig signingConfigs.release - } release { - debuggable false minifyEnabled enableProguardInReleaseBuilds - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - signingConfig signingConfigs.release + proguardFiles getDefaultProguardFile('proguard-android.txt') + signingConfig signingConfigs.debug } } sourceSets.main { @@ -173,8 +160,6 @@ dependencies { // Consume Hermes as built from source only for the Hermes variant. hermesImplementation(project(":packages:react-native:ReactAndroid:hermes-engine")) - implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0" - debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") diff --git a/packages/rn-tester/android/app/gradle.properties b/packages/rn-tester/android/app/gradle.properties index b6ce28ca151ced..1d6bf9759649a1 100644 --- a/packages/rn-tester/android/app/gradle.properties +++ b/packages/rn-tester/android/app/gradle.properties @@ -1,11 +1,6 @@ org.gradle.parallel=true # This is causing issue with dependencies task: https://github.com/gradle/gradle/issues/9645#issuecomment-530746758 # org.gradle.configureondemand=true -MYAPP_RELEASE_STORE_FILE=my-release-key.keystore -MYAPP_RELEASE_KEY_ALIAS=androiddebugkey -MYAPP_RELEASE_STORE_PASSWORD=android -MYAPP_RELEASE_KEY_PASSWORD=android - android.useAndroidX=true android.enableJetifier=true @@ -13,6 +8,6 @@ android.enableJetifier=true FLIPPER_VERSION=0.182.0 # RN-Tester is building with NewArch always enabled -newArchEnabled=false +newArchEnabled=true # RN-Tester is running with Hermes enabled and filtering variants with enableHermesOnlyInVariants hermesEnabled=true diff --git a/packages/rn-tester/android/app/my-release-key.keystore b/packages/rn-tester/android/app/my-release-key.keystore deleted file mode 100644 index 364e105ed39fbf..00000000000000 Binary files a/packages/rn-tester/android/app/my-release-key.keystore and /dev/null differ diff --git a/packages/rn-tester/android/app/proguard-rules.pro b/packages/rn-tester/android/app/proguard-rules.pro deleted file mode 100644 index 10279099c39e6c..00000000000000 --- a/packages/rn-tester/android/app/proguard-rules.pro +++ /dev/null @@ -1,15 +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. - -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the proguardFiles -# directive in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: diff --git a/packages/rn-tester/android/app/src/main/AndroidManifest.xml b/packages/rn-tester/android/app/src/main/AndroidManifest.xml index 3e0f6056edda0b..14257864c5fbc6 100644 --- a/packages/rn-tester/android/app/src/main/AndroidManifest.xml +++ b/packages/rn-tester/android/app/src/main/AndroidManifest.xml @@ -35,7 +35,8 @@ android:name=".RNTesterApplication" android:allowBackup="true" android:banner="@drawable/tv_banner" - android:icon="@drawable/launcher_icon" + android:icon="@mipmap/ic_launcher" + android:roundIcon="@mipmap/ic_launcher_round" android:label="@string/app_name" android:theme="@style/AppTheme"> ints) { + WritableMap payload = Arguments.createMap(); + + WritableArray newIntArray = Arguments.createArray(); + WritableArray newBoolArray = Arguments.createArray(); + WritableArray newFloatArray = Arguments.createArray(); + WritableArray newDoubleArray = Arguments.createArray(); + WritableArray newYesNoArray = Arguments.createArray(); + WritableArray newStringArray = Arguments.createArray(); + WritableArray newObjectArray = Arguments.createArray(); + WritableArray newArrayArray = Arguments.createArray(); + + for (Integer i : ints) { + newIntArray.pushInt(i * 2); + newBoolArray.pushBoolean(i % 2 == 1); + newFloatArray.pushDouble(i * 3.14); + newDoubleArray.pushDouble(i / 3.14); + newYesNoArray.pushString(i % 2 == 1 ? "yep" : "nope"); + newStringArray.pushString(i.toString()); + + WritableMap latLon = Arguments.createMap(); + latLon.putDouble("lat", -1.0 * i); + latLon.putDouble("lon", 2.0 * i); + newObjectArray.pushMap(latLon); + + WritableArray innerArray = Arguments.createArray(); + innerArray.pushInt(i); + innerArray.pushInt(i); + innerArray.pushInt(i); + newArrayArray.pushArray(innerArray); + } + + payload.putArray("values", newIntArray); + payload.putArray("boolValues", newBoolArray); + payload.putArray("floats", newFloatArray); + payload.putArray("doubles", newDoubleArray); + payload.putArray("yesNos", newYesNoArray); + payload.putArray("strings", newStringArray); + payload.putArray("latLons", newObjectArray); + payload.putArray("multiArrays", newArrayArray); + + ReactContext reactContext = (ReactContext) getContext(); + int surfaceId = UIManagerHelper.getSurfaceId(reactContext); + EventDispatcher eventDispatcher = + UIManagerHelper.getEventDispatcherForReactTag(reactContext, getId()); + Event event = new OnIntArrayChangedEvent(surfaceId, getId(), payload); + + if (eventDispatcher != null) { + eventDispatcher.dispatchEvent(event); + } + } + + class OnIntArrayChangedEvent extends Event { + private WritableMap mPayload; + + public OnIntArrayChangedEvent(int surfaceId, int viewId, WritableMap payload) { + super(surfaceId, viewId); + this.mPayload = payload; + } + + @Override + public String getEventName() { + return "onIntArrayChanged"; + } + + @Override + protected WritableMap getEventData() { + return mPayload; + } + } } diff --git a/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/component/MyNativeViewManager.java b/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/component/MyNativeViewManager.java index d8c8b731acb3cf..05d23b978aad00 100644 --- a/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/component/MyNativeViewManager.java +++ b/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/component/MyNativeViewManager.java @@ -11,6 +11,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.common.MapBuilder; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.uimanager.SimpleViewManager; import com.facebook.react.uimanager.ThemedReactContext; @@ -19,6 +20,10 @@ import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.viewmanagers.RNTMyNativeViewManagerDelegate; import com.facebook.react.viewmanagers.RNTMyNativeViewManagerInterface; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** View manager for {@link MyNativeView} components. */ @ReactModule(name = MyNativeViewManager.REACT_CLASS) @@ -67,4 +72,29 @@ public void callNativeMethodToChangeBackgroundColor(MyNativeView view, String co public void setOpacity(@NonNull MyNativeView view, float opacity) { super.setOpacity(view, opacity); } + + @Override + @ReactProp(name = "values") + public void setValues(@NonNull MyNativeView view, @Nullable ReadableArray value) { + List mValues = new ArrayList(); + for (int i = 0; i < value.size(); i++) { + mValues.add(value.getInt(i)); + } + view.emitOnArrayChangedEvent(mValues); + } + + @Override + public final Map getExportedCustomBubblingEventTypeConstants() { + Map eventTypeConstants = new HashMap(); + eventTypeConstants.putAll( + MapBuilder.builder() + .put( + "onIntArrayChanged", + MapBuilder.of( + "phasedRegistrationNames", + MapBuilder.of( + "bubbled", "onIntArrayChanged", "captured", "onIntArrayChangedCapture"))) + .build()); + return eventTypeConstants; + } } diff --git a/packages/rn-tester/android/app/src/main/res/drawable/ic_launcher_background.xml b/packages/rn-tester/android/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 00000000000000..f3baaded29af3b --- /dev/null +++ b/packages/rn-tester/android/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/rn-tester/android/app/src/main/res/drawable/ic_launcher_foreground.xml b/packages/rn-tester/android/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 00000000000000..4ff27896d09bea --- /dev/null +++ b/packages/rn-tester/android/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,23 @@ + + + + + + diff --git a/packages/rn-tester/android/app/src/main/res/drawable/launcher_icon.png b/packages/rn-tester/android/app/src/main/res/drawable/launcher_icon.png deleted file mode 100644 index a4aa3bd6d9acdc..00000000000000 Binary files a/packages/rn-tester/android/app/src/main/res/drawable/launcher_icon.png and /dev/null differ diff --git a/packages/rn-tester/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/packages/rn-tester/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 00000000000000..50ec886232535e --- /dev/null +++ b/packages/rn-tester/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/packages/rn-tester/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/packages/rn-tester/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 00000000000000..50ec886232535e --- /dev/null +++ b/packages/rn-tester/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/packages/rn-tester/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/packages/rn-tester/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 00000000000000..21a22e50f23be1 Binary files /dev/null and b/packages/rn-tester/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/packages/rn-tester/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/packages/rn-tester/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 00000000000000..7be461f34f10c0 Binary files /dev/null and b/packages/rn-tester/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/packages/rn-tester/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/packages/rn-tester/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 00000000000000..761b8813248575 Binary files /dev/null and b/packages/rn-tester/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/packages/rn-tester/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/packages/rn-tester/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 00000000000000..86adfdb7b61e5d Binary files /dev/null and b/packages/rn-tester/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/packages/rn-tester/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/packages/rn-tester/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 00000000000000..7e73de98bc1d60 Binary files /dev/null and b/packages/rn-tester/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/packages/rn-tester/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/packages/rn-tester/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 00000000000000..5553d426c186cf Binary files /dev/null and b/packages/rn-tester/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/packages/rn-tester/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/packages/rn-tester/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 00000000000000..c695cac7e095d6 Binary files /dev/null and b/packages/rn-tester/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/packages/rn-tester/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/packages/rn-tester/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 00000000000000..32fd7a2e3f8156 Binary files /dev/null and b/packages/rn-tester/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/packages/rn-tester/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/packages/rn-tester/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 00000000000000..a50331bc40ce4c Binary files /dev/null and b/packages/rn-tester/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/packages/rn-tester/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/packages/rn-tester/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 00000000000000..877e6d2def6ee7 Binary files /dev/null and b/packages/rn-tester/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/packages/rn-tester/android/app/src/main/res/values/styles.xml b/packages/rn-tester/android/app/src/main/res/values/styles.xml index 42c90f3e99a984..7ba83a2ad5a2c9 100644 --- a/packages/rn-tester/android/app/src/main/res/values/styles.xml +++ b/packages/rn-tester/android/app/src/main/res/values/styles.xml @@ -1,9 +1,8 @@ - diff --git a/packages/rn-tester/js/components/ListExampleShared.js b/packages/rn-tester/js/components/ListExampleShared.js index cbe749a83c9dc8..32ddc5633f39c3 100644 --- a/packages/rn-tester/js/components/ListExampleShared.js +++ b/packages/rn-tester/js/components/ListExampleShared.js @@ -38,7 +38,7 @@ function genItemData(i: number): Item { const itemHash = Math.abs(hashCode('Item ' + i)); return { title: 'Item ' + i, - text: LOREM_IPSUM.substr(0, (itemHash % 301) + 20), + text: LOREM_IPSUM.slice(0, (itemHash % 301) + 20), key: String(i), pressed: false, }; diff --git a/packages/rn-tester/js/examples/ActivityIndicator/ActivityIndicatorExample.js b/packages/rn-tester/js/examples/ActivityIndicator/ActivityIndicatorExample.js index b2d7c9e8ad849e..97df4046375aa7 100644 --- a/packages/rn-tester/js/examples/ActivityIndicator/ActivityIndicatorExample.js +++ b/packages/rn-tester/js/examples/ActivityIndicator/ActivityIndicatorExample.js @@ -8,7 +8,7 @@ * @flow strict-local */ -import type {Node} from 'React'; +import type {Node} from 'react'; import React, {useCallback, useEffect, useRef, useState} from 'react'; import {ActivityIndicator, StyleSheet, View} from 'react-native'; diff --git a/packages/rn-tester/js/examples/Crash/CrashExample.js b/packages/rn-tester/js/examples/Crash/CrashExample.js index 01b55b70ebbfe6..a1fe3a2cfe0849 100644 --- a/packages/rn-tester/js/examples/Crash/CrashExample.js +++ b/packages/rn-tester/js/examples/Crash/CrashExample.js @@ -8,7 +8,7 @@ * @flow strict-local */ -import type {Node} from 'React'; +import type {Node} from 'react'; import {Button} from 'react-native'; import React from 'react'; diff --git a/packages/rn-tester/js/examples/Experimental/W3CPointerEventPlatformTests/PointerEventPointerCancelTouch.js b/packages/rn-tester/js/examples/Experimental/W3CPointerEventPlatformTests/PointerEventPointerCancelTouch.js index 09dc77c1cf1336..8059b8f9d65572 100644 --- a/packages/rn-tester/js/examples/Experimental/W3CPointerEventPlatformTests/PointerEventPointerCancelTouch.js +++ b/packages/rn-tester/js/examples/Experimental/W3CPointerEventPlatformTests/PointerEventPointerCancelTouch.js @@ -157,10 +157,11 @@ function PointerEventPointerCancelTouchTestCase( } const styles = StyleSheet.create({ - scrollContainer: {width: '100%', height: '100%'}, + scrollContainer: {width: '100%', height: 100}, target: { backgroundColor: 'black', padding: 32, + height: 200, }, }); diff --git a/packages/rn-tester/js/examples/SectionList/SectionListBaseExample.js b/packages/rn-tester/js/examples/SectionList/SectionListBaseExample.js index f1312dcbb59112..8df947c8d935a4 100644 --- a/packages/rn-tester/js/examples/SectionList/SectionListBaseExample.js +++ b/packages/rn-tester/js/examples/SectionList/SectionListBaseExample.js @@ -103,6 +103,8 @@ const SectionListBaseExample: React.AbstractComponent< keyExtractor={(item, index) => item + index} style={styles.list} renderItem={Item} + /* $FlowFixMe[prop-missing] Error revealed after improved builtin React + * utility types */ renderSectionHeader={({section: {title}}) => ( {title} )} diff --git a/packages/rn-tester/js/examples/Text/TextExample.android.js b/packages/rn-tester/js/examples/Text/TextExample.android.js index 8234bde9a39088..018f1bd28b335f 100644 --- a/packages/rn-tester/js/examples/Text/TextExample.android.js +++ b/packages/rn-tester/js/examples/Text/TextExample.android.js @@ -676,6 +676,10 @@ class TextExample extends React.Component<{...}> { Maximum of one line no matter now much I write here. If I keep writing it{"'"}ll just truncate after one line + + Maximum of one line no matter now much I write here. If I keep + writing it{"'"}ll just truncate after one line + Maximum of two lines no matter now much I write here. If I keep writing it{"'"}ll just truncate after two lines diff --git a/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js b/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js index 353379409ffe6a..c05948b0639800 100644 --- a/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js +++ b/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js @@ -438,7 +438,7 @@ class TokenizedTextExample extends React.Component< if (token[0].length === 0) { index = 1; } - parts.push(_text.substr(0, index)); + parts.push(_text.slice(0, index)); parts.push(token[0]); index = index + token[0].length; _text = _text.slice(index); diff --git a/packages/rn-tester/js/examples/TurboModule/NativeCxxModuleExampleExample.js b/packages/rn-tester/js/examples/TurboModule/NativeCxxModuleExampleExample.js index 9e18022e84cfb4..3aeb55e8040770 100644 --- a/packages/rn-tester/js/examples/TurboModule/NativeCxxModuleExampleExample.js +++ b/packages/rn-tester/js/examples/TurboModule/NativeCxxModuleExampleExample.js @@ -231,7 +231,7 @@ class NativeCxxModuleExampleExample extends React.Component<{||}, State> { item} renderItem={({item}: {item: Examples, ...}) => ( diff --git a/packages/rn-tester/package.json b/packages/rn-tester/package.json index 5ac1f9a39501d0..009da93bf1bb77 100644 --- a/packages/rn-tester/package.json +++ b/packages/rn-tester/package.json @@ -1,13 +1,12 @@ { - "private": true, "name": "@react-native/tester", "version": "0.0.1", - "license": "MIT", + "private": true, "description": "React Native tester app.", - "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/rn-tester", + "license": "MIT", "repository": { "type": "git", - "url": "git@github.com:facebook/react-native.git", + "url": "https://github.com/facebook/react-native.git", "directory": "packages/rn-tester" }, "engines": { @@ -15,6 +14,7 @@ }, "scripts": { "start": "react-native start", + "android": "react-native run-android --mode HermesDebug --appId 'com.facebook.react.uiapp' --main-activity 'com.facebook.react.uiapp.RNTesterActivity'", "install-android-jsc": "../../gradlew :packages:rn-tester:android:app:installJscDebug", "install-android-hermes": "../../gradlew :packages:rn-tester:android:app:installHermesDebug", "clean-android": "rm -rf android/app/build", @@ -23,7 +23,7 @@ "clean-ios": "rm -rf build/generated/ios Pods Podfile.lock" }, "dependencies": { - "flow-enums-runtime": "^0.0.5", + "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "nullthrows": "^1.1.1" }, diff --git a/packages/rn-tester/react-native.config.js b/packages/rn-tester/react-native.config.js index 845ae99d8cdc9e..099000c501058d 100644 --- a/packages/rn-tester/react-native.config.js +++ b/packages/rn-tester/react-native.config.js @@ -29,5 +29,8 @@ module.exports = { ios: { sourceDir: '.', }, + android: { + sourceDir: '../../', + }, }, }; diff --git a/packages/typescript-config/README.md b/packages/typescript-config/README.md new file mode 100644 index 00000000000000..baa6d6a1581724 --- /dev/null +++ b/packages/typescript-config/README.md @@ -0,0 +1,5 @@ +# @react-native/typescript-config + +This package provides the default `tsconfig.json` used by newly built React Native apps. + +This template is customized for specific versions of React Native, and should be updated in sync with the rest of your app. diff --git a/packages/typescript-config/package.json b/packages/typescript-config/package.json new file mode 100644 index 00000000000000..896de154d849f7 --- /dev/null +++ b/packages/typescript-config/package.json @@ -0,0 +1,15 @@ +{ + "name": "@react-native/typescript-config", + "version": "0.73.0", + "description": "Default TypeScript configuration for React Native apps", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/facebook/react-native.git", + "directory": "packages/typescript-config" + }, + "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/typescript-config#readme", + "keywords": ["typescript", "tsconfig", "react-native"], + "bugs": "https://github.com/facebook/react-native/issues", + "main": "tsconfig.json" +} diff --git a/packages/typescript-config/tsconfig.json b/packages/typescript-config/tsconfig.json new file mode 100644 index 00000000000000..3bb1451e792d9a --- /dev/null +++ b/packages/typescript-config/tsconfig.json @@ -0,0 +1,46 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "React Native", + "compilerOptions": { + "target": "esnext", + "module": "es2015", + "types": ["react-native", "jest"], + "lib": [ + "es2019", + "es2020.bigint", + "es2020.date", + "es2020.number", + "es2020.promise", + "es2020.string", + "es2020.symbol.wellknown", + "es2021.promise", + "es2021.string", + "es2021.weakref", + "es2022.array", + "es2022.object", + "es2022.string" + ], + "allowJs": true, + "jsx": "react-native", + "noEmit": true, + "isolatedModules": true, + "strict": true, + "moduleResolution": "bundler", + "customConditions": ["react-native"], + "allowImportingTsExtensions": true, + "allowArbitraryExtensions": true, + "resolveJsonModule": true, + "resolvePackageJsonImports": false, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "skipLibCheck": true, + // Causes issues with package.json "exports" + "forceConsistentCasingInFileNames": false + }, + "exclude": [ + "node_modules", + "babel.config.js", + "metro.config.js", + "jest.config.js" + ] + } diff --git a/packages/virtualized-lists/README.md b/packages/virtualized-lists/README.md new file mode 100644 index 00000000000000..78481f7944ac5e --- /dev/null +++ b/packages/virtualized-lists/README.md @@ -0,0 +1,21 @@ +# @react-native/virtualized-lists + +[![Version][version-badge]][package] + +## Installation + +``` +yarn add @react-native/virtualized-lists +``` + +*Note: We're using `yarn` to install deps. Feel free to change commands to use `npm` 3+ and `npx` if you like* + +[version-badge]: https://img.shields.io/npm/v/@react-native/virtualized-lists?style=flat-square +[package]: https://www.npmjs.com/package/@react-native/virtualized-lists + +## Testing + +To run the tests in this package, run the following commands from the React Native root folder: + +1. `yarn` to install the dependencies. You just need to run this once +2. `yarn jest packages/virtualized-lists`. diff --git a/packages/virtualized-lists/package.json b/packages/virtualized-lists/package.json index 021635f292d309..00b078ac22af4c 100644 --- a/packages/virtualized-lists/package.json +++ b/packages/virtualized-lists/package.json @@ -2,12 +2,15 @@ "name": "@react-native/virtualized-lists", "version": "0.73.0", "description": "Virtualized lists for React Native.", + "license": "MIT", "repository": { "type": "git", - "url": "git@github.com:facebook/react-native.git", + "url": "https://github.com/facebook/react-native.git", "directory": "packages/virtualized-lists" }, - "license": "MIT", + "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/virtualized-lists#readme", + "keywords": ["lists", "virtualized-lists", "section-lists", "react-native"], + "bugs": "https://github.com/facebook/react-native/issues", "engines": { "node": ">=16" }, diff --git a/scripts/__tests__/publish-npm-test.js b/scripts/__tests__/publish-npm-test.js index 6c539e284e1c9e..d0944faaa342c8 100644 --- a/scripts/__tests__/publish-npm-test.js +++ b/scripts/__tests__/publish-npm-test.js @@ -75,53 +75,62 @@ describe('publish-npm', () => { describe('nightly', () => { it('should publish', () => { - execMock.mockReturnValueOnce({code: 0}).mockReturnValueOnce({code: 0}); + execMock + .mockReturnValueOnce({stdout: '0.81.0-rc.1\n', code: 0}) + .mockReturnValueOnce({code: 0}) + .mockReturnValueOnce({code: 0}); + const expectedVersion = '0.82.0-nightly-20230420-currentco'; publishNpm('nightly'); - const expectedVersion = '0.0.0-20230420-2352-currentco'; expect(publishAndroidArtifactsToMavenMock).toHaveBeenCalledWith( expectedVersion, true, ); expect(execMock.mock.calls[0][0]).toBe( + `npm view react-native dist-tags.next`, + ); + expect(execMock.mock.calls[1][0]).toBe( `node scripts/set-rn-version.js --to-version ${expectedVersion} --build-type nightly`, ); - expect(execMock.mock.calls[1][0]).toBe('npm publish --tag nightly'); + expect(execMock.mock.calls[2][0]).toBe('npm publish --tag nightly'); expect(echoMock).toHaveBeenCalledWith( `Published to npm ${expectedVersion}`, ); expect(exitMock).toHaveBeenCalledWith(0); - expect(execMock.mock.calls).toHaveLength(2); + expect(execMock.mock.calls).toHaveLength(3); }); + it('should fail to set version', () => { - execMock.mockReturnValueOnce({code: 1}); + execMock + .mockReturnValueOnce({stdout: '0.81.0-rc.1\n', code: 0}) + .mockReturnValueOnce({code: 1}); + const expectedVersion = '0.82.0-nightly-20230420-currentco'; publishNpm('nightly'); - const expectedVersion = '0.0.0-20230420-2352-currentco'; expect(publishAndroidArtifactsToMavenMock).not.toBeCalled(); expect(execMock.mock.calls[0][0]).toBe( + `npm view react-native dist-tags.next`, + ); + expect(execMock.mock.calls[1][0]).toBe( `node scripts/set-rn-version.js --to-version ${expectedVersion} --build-type nightly`, ); expect(echoMock).toHaveBeenCalledWith( `Failed to set version number to ${expectedVersion}`, ); expect(exitMock).toHaveBeenCalledWith(1); - expect(execMock.mock.calls).toHaveLength(1); + expect(execMock.mock.calls).toHaveLength(2); }); }); describe('release', () => { it('should fail with invalid release version', () => { process.env.CIRCLE_TAG = '1.0.1'; - publishNpm('release'); - expect(echoMock).toHaveBeenCalledWith( - 'Version 1.0.1 is not valid for Release', - ); + expect(() => { + publishNpm('release'); + }).toThrow('Version 1.0.1 is not valid for Release'); expect(publishAndroidArtifactsToMavenMock).not.toBeCalled(); - expect(exitMock).toHaveBeenCalledWith(1); - expect(execMock).not.toBeCalled(); }); it('should publish non-latest', () => { diff --git a/scripts/__tests__/set-rn-version-test.js b/scripts/__tests__/set-rn-version-test.js new file mode 100644 index 00000000000000..b913e4638b9a3f --- /dev/null +++ b/scripts/__tests__/set-rn-version-test.js @@ -0,0 +1,182 @@ +/** + * 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 + */ + +const execMock = jest.fn(); +const echoMock = jest.fn(); +const exitMock = jest.fn(); +const catMock = jest.fn(); +const sedMock = jest.fn(); +const writeFileSyncMock = jest.fn(); + +jest + .mock('shelljs', () => ({ + exec: execMock, + echo: echoMock, + exit: exitMock, + cat: catMock, + sed: sedMock, + })) + .mock('./../scm-utils', () => ({ + saveFiles: jest.fn(), + })) + .mock('path', () => ({ + join: () => '../packages/react-native', + })) + .mock('fs', () => ({ + writeFileSync: writeFileSyncMock, + mkdtempSync: () => './rn-set-version/', + })) + .mock('os'); + +const setReactNativeVersion = require('../set-rn-version'); + +describe('set-rn-version', () => { + afterEach(() => { + jest.resetModules(); + jest.resetAllMocks(); + }); + + it('should set nightly version', () => { + catMock.mockImplementation(path => { + if (path === 'packages/react-native/package.json') { + return '{"name": "myPackage", "version": 2}'; + } else if ( + path === 'scripts/versiontemplates/ReactNativeVersion.java.template' || + path === 'scripts/versiontemplates/RCTVersion.m.template' || + path === 'scripts/versiontemplates/ReactNativeVersion.h.template' || + path === 'scripts/versiontemplates/ReactNativeVersion.js.template' + ) { + return '{major: ${major}, minor: ${minor}, patch: ${patch}, prerelease: ${prerelease}}'; + } else { + throw new Error(`Invalid path passed for package dir. Path: ${path}`); + } + }); + + execMock + .mockReturnValueOnce({code: 0}) + .mockReturnValueOnce({stdout: 'line1\nline2\nline3\n'}); + sedMock.mockReturnValueOnce({code: 0}); + + const version = '0.81.0-nightly-29282302-abcd1234'; + setReactNativeVersion(version, 'nightly'); + + expect(sedMock).toHaveBeenCalledWith( + '-i', + /^VERSION_NAME=.*/, + `VERSION_NAME=${version}`, + 'packages/react-native/ReactAndroid/gradle.properties', + ); + expect(writeFileSyncMock.mock.calls.length).toBe(5); + expect(writeFileSyncMock.mock.calls[0][0]).toBe( + 'packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java', + ); + expect(writeFileSyncMock.mock.calls[0][1]).toBe( + '{major: 0, minor: 81, patch: 0, prerelease: "nightly-29282302-abcd1234"}', + ); + expect(writeFileSyncMock.mock.calls[1][0]).toBe( + 'packages/react-native/React/Base/RCTVersion.m', + ); + expect(writeFileSyncMock.mock.calls[2][0]).toBe( + 'packages/react-native/ReactCommon/cxxreact/ReactNativeVersion.h', + ); + expect(writeFileSyncMock.mock.calls[3][0]).toBe( + 'packages/react-native/Libraries/Core/ReactNativeVersion.js', + ); + expect(writeFileSyncMock.mock.calls[4][0]).toBe( + 'packages/react-native/package.json', + ); + expect(writeFileSyncMock.mock.calls[4][1]).toBe( + `{\n "name": "myPackage",\n "version": "${version}"\n}`, + ); + + expect(exitMock.mock.calls[0][0]).toBe(0); + expect(execMock.mock.calls[0][0]).toBe( + `node scripts/set-rn-template-version.js ${version}`, + ); + }); + + it('should set release version', () => { + catMock.mockImplementation(path => { + if (path === 'packages/react-native/package.json') { + return '{"name": "myPackage", "version": 2}'; + } + return 'exports.version = {major: ${major}, minor: ${minor}, patch: ${patch}, prerelease: ${prerelease}}'; + }); + + execMock + .mockReturnValueOnce({code: 0}) + .mockReturnValueOnce({stdout: 'line1\nline2\nline3\n'}); + sedMock.mockReturnValueOnce({code: 0}); + + const version = '0.81.0'; + setReactNativeVersion(version, 'release'); + + expect(sedMock).toHaveBeenCalledWith( + '-i', + /^VERSION_NAME=.*/, + `VERSION_NAME=${version}`, + 'packages/react-native/ReactAndroid/gradle.properties', + ); + expect(writeFileSyncMock.mock.calls.length).toBe(5); + expect(writeFileSyncMock.mock.calls[0][0]).toBe( + 'packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java', + ); + expect(writeFileSyncMock.mock.calls[0][1]).toBe( + 'exports.version = {major: 0, minor: 81, patch: 0, prerelease: null}', + ); + expect(writeFileSyncMock.mock.calls[4][0]).toBe( + 'packages/react-native/package.json', + ); + expect(writeFileSyncMock.mock.calls[4][1]).toBe( + `{\n "name": "myPackage",\n "version": "${version}"\n}`, + ); + + expect(exitMock.mock.calls[0][0]).toBe(0); + expect(execMock.mock.calls[0][0]).toBe( + `node scripts/set-rn-template-version.js ${version}`, + ); + expect(execMock.mock.calls[1][0]).toBe( + `diff -r ./rn-set-version/ . | grep '^[>]' | grep -c ${version} `, + ); + }); + + it('should fail validation', () => { + catMock.mockReturnValue('{}'); + + execMock + .mockReturnValueOnce({code: 0}) + .mockReturnValueOnce({stdout: 'line1\nline2\n'}); + sedMock.mockReturnValueOnce({code: 0}); + const filesToValidate = [ + 'packages/react-native/package.json', + 'packages/react-native/ReactAndroid/gradle.properties', + 'packages/react-native/template/package.json', + ]; + + const version = '0.81.0'; + setReactNativeVersion(version, 'release'); + + expect(exitMock).toHaveBeenCalledWith(0); + expect(echoMock).toHaveBeenNthCalledWith( + 1, + 'The tmp versioning folder is ./rn-set-version/', + ); + + expect(echoMock).toHaveBeenNthCalledWith(2, 'WARNING:'); + + expect(echoMock.mock.calls[2][0]).toBe( + `Failed to update all the files: [${filesToValidate.join( + ', ', + )}] must have versions in them`, + ); + expect(echoMock.mock.calls[3][0]).toBe( + `These files already had version ${version} set.`, + ); + }); +}); diff --git a/scripts/__tests__/version-utils-test.js b/scripts/__tests__/version-utils-test.js index ad6d958ebff313..1294c0d132d777 100644 --- a/scripts/__tests__/version-utils-test.js +++ b/scripts/__tests__/version-utils-test.js @@ -11,6 +11,7 @@ const { parseVersion, isReleaseBranch, validateBuildType, + isNightly, } = require('../version-utils'); let execResult = null; @@ -300,6 +301,32 @@ describe('version-utils', () => { }); }); + describe('isNightly', () => { + it('should match old version of nightlies', () => { + expect( + isNightly({ + version: '0.0.0-20230420-2108-f84256a92', + major: '0', + minor: '0', + patch: '0', + prerelease: '20230420-2108-f84256a92', + }), + ).toBe(true); + }); + + it('should match nightlies', () => { + expect( + isNightly({ + version: '0.81.0-nightly-20230420-f84256a92', + major: '0', + minor: '81', + patch: '0', + prerelease: 'nightly-20230420-f84256a92', + }), + ).toBe(true); + }); + }); + describe('Validate version', () => { it('Throw error if the buildType is unknown', () => { function testInvalidFunction() { diff --git a/scripts/publish-npm.js b/scripts/publish-npm.js index 536a034c561d17..661944fa6c39a1 100755 --- a/scripts/publish-npm.js +++ b/scripts/publish-npm.js @@ -9,6 +9,21 @@ 'use strict'; +const {exec, echo, exit} = require('shelljs'); +const {parseVersion} = require('./version-utils'); +const { + exitIfNotOnGit, + getCurrentCommit, + isTaggedLatest, +} = require('./scm-utils'); +const { + generateAndroidArtifacts, + publishAndroidArtifactsToMaven, +} = require('./release-utils'); +const fs = require('fs'); +const path = require('path'); +const yargs = require('yargs'); + /** * This script prepares a release version of react-native and may publish to NPM. * It is supposed to run in CI environment, not on a developer's machine. @@ -31,22 +46,45 @@ * * or otherwise `{major}.{minor}-stable` */ -const {exec, echo, exit} = require('shelljs'); -const {parseVersion} = require('./version-utils'); -const { - exitIfNotOnGit, - getCurrentCommit, - isTaggedLatest, -} = require('./scm-utils'); -const { - generateAndroidArtifacts, - publishAndroidArtifactsToMaven, -} = require('./release-utils'); -const fs = require('fs'); -const path = require('path'); -const yargs = require('yargs'); +if (require.main === module) { + const argv = yargs + .option('n', { + alias: 'nightly', + type: 'boolean', + default: false, + }) + .option('d', { + alias: 'dry-run', + type: 'boolean', + default: false, + }) + .option('r', { + alias: 'release', + type: 'boolean', + default: false, + }) + .strict().argv; + + const buildType = argv.release + ? 'release' + : argv.nightly + ? 'nightly' + : 'dry-run'; + + publishNpm(buildType); +} -const RN_PACKAGE_DIR = path.join(__dirname, '..', 'packages', 'react-native'); +// Get `next` version from npm and +1 on the minor for `main` version +function getMainVersion() { + const cmd = 'npm view react-native dist-tags.next'; + echo(cmd); + const result = exec(cmd); + if (result.code) { + throw 'Failed to get next version from npm'; + } + const {major, minor} = parseVersion(result.stdout.trim(), 'release'); + return `${major}.${parseInt(minor, 10) + 1}.0`; +} function getNpmInfo(buildType) { const currentCommit = getCurrentCommit(); @@ -60,13 +98,13 @@ function getNpmInfo(buildType) { } if (buildType === 'nightly') { + const mainVersion = getMainVersion(); const dateIdentifier = new Date() .toISOString() - .slice(0, -8) - .replace(/[-:]/g, '') - .replace(/[T]/g, '-'); + .slice(0, -14) + .replace(/[-]/g, ''); return { - version: `0.0.0-${dateIdentifier}-${shortCommit}`, + version: `${mainVersion}-nightly-${dateIdentifier}-${shortCommit}`, tag: 'nightly', }; } @@ -97,14 +135,7 @@ function getNpmInfo(buildType) { } function publishNpm(buildType) { - let version, - tag = null; - try { - ({version, tag} = getNpmInfo(buildType)); - } catch (e) { - echo(e.message); - return exit(1); - } + const {version, tag} = getNpmInfo(buildType); // Set version number in various files (package.json, gradle.properties etc) // For non-nightly, non-dry-run, CircleCI job `prepare_package_for_release` does this @@ -138,7 +169,8 @@ function publishNpm(buildType) { const otp = process.env.NPM_CONFIG_OTP; const otpFlag = otp ? ` --otp ${otp}` : ''; - if (exec(`npm publish ${tagFlag}${otpFlag}`, {cwd: RN_PACKAGE_DIR}).code) { + const packageDirPath = path.join(__dirname, '..', 'packages', 'react-native'); + if (exec(`npm publish ${tagFlag}${otpFlag}`, {cwd: packageDirPath}).code) { echo('Failed to publish package to npm'); return exit(1); } else { @@ -147,32 +179,4 @@ function publishNpm(buildType) { } } -if (require.main === module) { - const argv = yargs - .option('n', { - alias: 'nightly', - type: 'boolean', - default: false, - }) - .option('d', { - alias: 'dry-run', - type: 'boolean', - default: false, - }) - .option('r', { - alias: 'release', - type: 'boolean', - default: false, - }) - .strict().argv; - - const buildType = argv.release - ? 'release' - : argv.nightly - ? 'nightly' - : 'dry-run'; - - publishNpm(buildType); -} - module.exports = publishNpm; diff --git a/scripts/set-rn-version.js b/scripts/set-rn-version.js index 3d525b93e25c91..a5f99213740ab0 100755 --- a/scripts/set-rn-version.js +++ b/scripts/set-rn-version.js @@ -9,13 +9,6 @@ 'use strict'; -/** - * This script updates relevant React Native files with supplied version: - * * Prepares a package.json suitable for package consumption - * * Updates package.json for template project - * * Updates the version in gradle files and makes sure they are consistent between each other - * * Creates a gemfile - */ const fs = require('fs'); const os = require('os'); const path = require('path'); @@ -24,155 +17,160 @@ const yargs = require('yargs'); const {parseVersion, validateBuildType} = require('./version-utils'); const {saveFiles} = require('./scm-utils'); -let argv = yargs - .option('v', { - alias: 'to-version', - type: 'string', - required: true, - }) - .option('b', { - alias: 'build-type', - type: 'string', - required: true, - }).argv; - -const buildType = argv.buildType; -const version = argv.toVersion; - -try { - validateBuildType(buildType); -} catch (e) { - throw e; +/** + * This script updates relevant React Native files with supplied version: + * * Prepares a package.json suitable for package consumption + * * Updates package.json for template project + * * Updates the version in gradle files and makes sure they are consistent between each other + * * Creates a gemfile + */ +if (require.main === module) { + let argv = yargs + .option('v', { + alias: 'to-version', + type: 'string', + required: true, + }) + .option('b', { + alias: 'build-type', + type: 'string', + required: true, + }).argv; + + setReactNativeVersion(argv.toVersion, argv.buildType); } -let major, - minor, - patch, - prerelease = -1; -try { - ({major, minor, patch, prerelease} = parseVersion(version, buildType)); -} catch (e) { - throw e; -} +function setSource({major, minor, patch, prerelease}) { + fs.writeFileSync( + 'packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java', + cat('scripts/versiontemplates/ReactNativeVersion.java.template') + .replace('${major}', major) + .replace('${minor}', minor) + .replace('${patch}', patch) + .replace( + '${prerelease}', + prerelease !== undefined ? `"${prerelease}"` : 'null', + ), + 'utf-8', + ); -const tmpVersioningFolder = fs.mkdtempSync( - path.join(os.tmpdir(), 'rn-set-version'), -); -echo(`The temp versioning folder is ${tmpVersioningFolder}`); + fs.writeFileSync( + 'packages/react-native/React/Base/RCTVersion.m', + cat('scripts/versiontemplates/RCTVersion.m.template') + .replace('${major}', `@(${major})`) + .replace('${minor}', `@(${minor})`) + .replace('${patch}', `@(${patch})`) + .replace( + '${prerelease}', + prerelease !== undefined ? `@"${prerelease}"` : '[NSNull null]', + ), + 'utf-8', + ); -saveFiles( - [ - 'packages/react-native/package.json', - 'packages/react-native/template/package.json', - ], - tmpVersioningFolder, -); - -fs.writeFileSync( - 'packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java', - cat('scripts/versiontemplates/ReactNativeVersion.java.template') - .replace('${major}', major) - .replace('${minor}', minor) - .replace('${patch}', patch) - .replace( - '${prerelease}', - prerelease !== undefined ? `"${prerelease}"` : 'null', - ), - 'utf-8', -); - -fs.writeFileSync( - 'packages/react-native/React/Base/RCTVersion.m', - cat('scripts/versiontemplates/RCTVersion.m.template') - .replace('${major}', `@(${major})`) - .replace('${minor}', `@(${minor})`) - .replace('${patch}', `@(${patch})`) - .replace( - '${prerelease}', - prerelease !== undefined ? `@"${prerelease}"` : '[NSNull null]', - ), - 'utf-8', -); - -fs.writeFileSync( - 'packages/react-native/ReactCommon/cxxreact/ReactNativeVersion.h', - cat('scripts/versiontemplates/ReactNativeVersion.h.template') - .replace('${major}', major) - .replace('${minor}', minor) - .replace('${patch}', patch) - .replace( - '${prerelease}', - prerelease !== undefined ? `"${prerelease}"` : '""', - ), - 'utf-8', -); - -fs.writeFileSync( - 'packages/react-native/Libraries/Core/ReactNativeVersion.js', - cat('scripts/versiontemplates/ReactNativeVersion.js.template') - .replace('${major}', major) - .replace('${minor}', minor) - .replace('${patch}', patch) - .replace( - '${prerelease}', - prerelease !== undefined ? `'${prerelease}'` : 'null', - ), - 'utf-8', -); - -const packageJson = JSON.parse(cat('packages/react-native/package.json')); -packageJson.version = version; - -fs.writeFileSync( - 'packages/react-native/package.json', - JSON.stringify(packageJson, null, 2), - 'utf-8', -); + fs.writeFileSync( + 'packages/react-native/ReactCommon/cxxreact/ReactNativeVersion.h', + cat('scripts/versiontemplates/ReactNativeVersion.h.template') + .replace('${major}', major) + .replace('${minor}', minor) + .replace('${patch}', patch) + .replace( + '${prerelease}', + prerelease !== undefined ? `"${prerelease}"` : '""', + ), + 'utf-8', + ); + + fs.writeFileSync( + 'packages/react-native/Libraries/Core/ReactNativeVersion.js', + cat('scripts/versiontemplates/ReactNativeVersion.js.template') + .replace('${major}', major) + .replace('${minor}', minor) + .replace('${patch}', patch) + .replace( + '${prerelease}', + prerelease !== undefined ? `'${prerelease}'` : 'null', + ), + 'utf-8', + ); +} // Change ReactAndroid/gradle.properties -saveFiles( - ['packages/react-native/ReactAndroid/gradle.properties'], - tmpVersioningFolder, -); -if ( - sed( +function setGradle({version}) { + const result = sed( '-i', /^VERSION_NAME=.*/, `VERSION_NAME=${version}`, 'packages/react-native/ReactAndroid/gradle.properties', - ).code -) { - echo("Couldn't update version for Gradle"); - exit(1); + ); + if (result.code) { + echo("Couldn't update version for Gradle"); + throw result.stderr; + } } -// Change react-native version in the template's package.json -exec(`node scripts/set-rn-template-version.js ${version}`); - -// Verify that files changed, we just do a git diff and check how many times version is added across files -const filesToValidate = [ - 'packages/react-native/package.json', - 'packages/react-native/ReactAndroid/gradle.properties', - 'packages/react-native/template/package.json', -]; - -const numberOfChangedLinesWithNewVersion = exec( - `diff -r ${tmpVersioningFolder} . | grep '^[>]' | grep -c ${version} `, - {silent: true}, -).stdout.trim(); - -if (+numberOfChangedLinesWithNewVersion !== filesToValidate.length) { - // TODO: the logic that checks whether all the changes have been applied - // is missing several files. For example, it is not checking Ruby version nor that - // the Objecive-C files, the codegen and other files are properly updated. - // We are going to work on this in another PR. - echo('WARNING:'); - echo( - `Failed to update all the files: [${filesToValidate.join( - ', ', - )}] must have versions in them`, +function setPackage({version}) { + const packageJson = JSON.parse(cat('packages/react-native/package.json')); + packageJson.version = version; + + fs.writeFileSync( + 'packages/react-native/package.json', + JSON.stringify(packageJson, null, 2), + 'utf-8', + ); +} + +function setTemplatePackage({version}) { + const result = exec(`node scripts/set-rn-template-version.js ${version}`); + if (result.code) { + echo("Failed to update React Native template's version of React Native"); + throw result.stderr; + } +} + +function setReactNativeVersion(argVersion, buildType) { + validateBuildType(buildType); + + const version = parseVersion(argVersion, buildType); + + // Create tmp folder for copies of files to verify files have changed + const filesToValidate = [ + 'packages/react-native/package.json', + 'packages/react-native/ReactAndroid/gradle.properties', + 'packages/react-native/template/package.json', + ]; + const tmpVersioningFolder = fs.mkdtempSync( + path.join(os.tmpdir(), 'rn-set-version'), ); - echo(`These files already had version ${version} set.`); + echo(`The tmp versioning folder is ${tmpVersioningFolder}`); + saveFiles(tmpVersioningFolder); + + setSource(version); + setPackage(version); + setTemplatePackage(version); + setGradle(version); + + // Validate changes + // We just do a git diff and check how many times version is added across files + const numberOfChangedLinesWithNewVersion = exec( + `diff -r ${tmpVersioningFolder} . | grep '^[>]' | grep -c ${version.version} `, + {silent: true}, + ).stdout.trim(); + + if (+numberOfChangedLinesWithNewVersion !== filesToValidate.length) { + // TODO: the logic that checks whether all the changes have been applied + // is missing several files. For example, it is not checking Ruby version nor that + // the Objecive-C files, the codegen and other files are properly updated. + // We are going to work on this in another PR. + echo('WARNING:'); + echo( + `Failed to update all the files: [${filesToValidate.join( + ', ', + )}] must have versions in them`, + ); + echo(`These files already had version ${version.version} set.`); + } + + return exit(0); } -exit(0); +module.exports = setReactNativeVersion; diff --git a/scripts/version-utils.js b/scripts/version-utils.js index 826050ac0d0f4a..427a9b4d71cb30 100644 --- a/scripts/version-utils.js +++ b/scripts/version-utils.js @@ -19,7 +19,7 @@ const VERSION_REGEX = /^v?((\d+)\.(\d+)\.(\d+)(?:-(.+))?)$/; * - stable: 0.68.1 * - stable prerelease: 0.70.0-rc.0 * - e2e-test: X.Y.Z-20221116-2018 - * - nightly: 0.0.0-20221116-2018-0bc4547fc + * - nightly: X.Y.Z-20221116-0bc4547fc * - dryrun: 1000.0.0 * * Parameters: @@ -106,7 +106,7 @@ function validateRelease(version) { function validateDryRun(version) { if ( !isMain(version) && - !isNightlyBuild(version) && + !isNightly(version) && !isStableRelease(version) && !isStablePrerelease(version) ) { @@ -116,7 +116,7 @@ function validateDryRun(version) { function validateNightly(version) { // a valid nightly is a prerelease - if (!isNightlyBuild(version)) { + if (!isNightly(version)) { throw new Error(`Version ${version.version} is not valid for nightlies`); } } @@ -139,10 +139,13 @@ function isStablePrerelease(version) { ); } -function isNightlyBuild(version) { - return ( - version.major === '0' && version.minor === '0' && version.patch === '0' - ); +function isNightly(version) { + // Check if older nightly version + if (version.major === '0' && version.minor === '0' && version.patch === '0') { + return true; + } + + return version.version.includes('nightly'); } function isMain(version) { @@ -158,6 +161,7 @@ function isReleaseBranch(branch) { module.exports = { validateBuildType, parseVersion, + isNightly, isReleaseBranch, isMain, isStableRelease, diff --git a/tools/eslint/rules/valid-flow-typed-signature.js b/tools/eslint/rules/valid-flow-typed-signature.js index c90ed5bbef663f..76ba9d10ed7872 100644 --- a/tools/eslint/rules/valid-flow-typed-signature.js +++ b/tools/eslint/rules/valid-flow-typed-signature.js @@ -34,7 +34,7 @@ module.exports = { const sourceText = context.getSourceCode().getText(); const firstLineEndIndex = sourceText.indexOf('\n'); - const firstLine = sourceText.substr(0, firstLineEndIndex); + const firstLine = sourceText.slice(0, firstLineEndIndex); const match = firstLine.match(HASH_COMMENT_RE); if (match == null) { @@ -43,7 +43,7 @@ module.exports = { } const hash = match[1]; - const versionedCode = sourceText.substr(firstLineEndIndex + 1); + const versionedCode = sourceText.slice(firstLineEndIndex + 1); if (md5(versionedCode) === hash) { return; } diff --git a/yarn.lock b/yarn.lock index d9a01deaaf8894..8b76bfad3e0ea3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10,12 +10,12 @@ "@jridgewell/gen-mapping" "^0.1.0" "@jridgewell/trace-mapping" "^0.3.9" -"@babel/cli@^7.19.0": - version "7.19.3" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.19.3.tgz#55914ed388e658e0b924b3a95da1296267e278e2" - integrity sha512-643/TybmaCAe101m2tSVHi9UKpETXP9c/Ff4mD2tAwkdP6esKIfaauZFc67vGEM6r9fekbEGid+sZhbEnSe3dg== +"@babel/cli@^7.20.0": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.21.5.tgz#a685a5b50b785f2edfbf6e042c1265c653547d9d" + integrity sha512-TOKytQ9uQW9c4np8F+P7ZfPINy5Kv+pizDIUwSVH8X5zHgYHV4AA8HE5LA450xXeu4jEfmUckTYvv1I4S26M/g== dependencies: - "@jridgewell/trace-mapping" "^0.3.8" + "@jridgewell/trace-mapping" "^0.3.17" commander "^4.0.1" convert-source-map "^1.1.0" fs-readdir-recursive "^1.1.0" @@ -85,10 +85,10 @@ json5 "^2.2.1" semver "^6.3.0" -"@babel/eslint-parser@^7.19.0": - version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.19.1.tgz#4f68f6b0825489e00a24b41b6a1ae35414ecd2f4" - integrity sha512-AqNf2QWt1rtu2/1rLswy6CDP7H9Oh3mMhk177Y67Rg8d7RD9WfOLLv8CGn6tisFvS2htm86yIe1yLF6I1UDaGQ== +"@babel/eslint-parser@^7.20.0": + version "7.21.8" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.21.8.tgz#59fb6fc4f3b017ab86987c076226ceef7b2b2ef2" + integrity sha512-HLhI+2q+BP3sf78mFUZNCGc10KEmoUqtUT1OCdMZsN+qr4qFeLUod62/zAnF3jNQstwyasDkZnVXwfK2Bml7MQ== dependencies: "@nicolo-ribaudo/eslint-scope-5-internals" "5.1.1-v1" eslint-visitor-keys "^2.1.0" @@ -302,6 +302,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz#d1b9000752b18d0877cff85a5c376ce5c3121629" integrity sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ== +"@babel/helper-plugin-utils@^7.21.5": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.21.5.tgz#345f2377d05a720a4e5ecfa39cbf4474a4daed56" + integrity sha512-0WDaIlXKOX/3KfBK/dwP1oQGiPh6rjMkT7HIRv7i5RR2VUMwrx5ZL0dwBkKx7+SW1zwNdgjHd34IMk5ZjTeHVg== + "@babel/helper-remap-async-to-generator@^7.18.6", "@babel/helper-remap-async-to-generator@^7.18.9": version "7.18.9" resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz#997458a0e3357080e54e1d79ec347f8a8cd28519" @@ -454,7 +459,7 @@ "@babel/helper-remap-async-to-generator" "^7.18.9" "@babel/plugin-syntax-async-generators" "^7.8.4" -"@babel/plugin-proposal-class-properties@^7.0.0", "@babel/plugin-proposal-class-properties@^7.13.0", "@babel/plugin-proposal-class-properties@^7.18.6": +"@babel/plugin-proposal-class-properties@^7.0.0", "@babel/plugin-proposal-class-properties@^7.13.0", "@babel/plugin-proposal-class-properties@^7.18.0", "@babel/plugin-proposal-class-properties@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== @@ -511,7 +516,7 @@ "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.0.0", "@babel/plugin-proposal-nullish-coalescing-operator@^7.13.8", "@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6": +"@babel/plugin-proposal-nullish-coalescing-operator@^7.0.0", "@babel/plugin-proposal-nullish-coalescing-operator@^7.13.8", "@babel/plugin-proposal-nullish-coalescing-operator@^7.18.0", "@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1" integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA== @@ -538,6 +543,17 @@ "@babel/plugin-syntax-object-rest-spread" "^7.8.3" "@babel/plugin-transform-parameters" "^7.20.1" +"@babel/plugin-proposal-object-rest-spread@^7.20.0": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz#aa662940ef425779c75534a5c41e9d936edc390a" + integrity sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg== + dependencies: + "@babel/compat-data" "^7.20.5" + "@babel/helper-compilation-targets" "^7.20.7" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.20.7" + "@babel/plugin-proposal-optional-catch-binding@^7.0.0", "@babel/plugin-proposal-optional-catch-binding@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz#f9400d0e6a3ea93ba9ef70b09e72dd6da638a2cb" @@ -555,6 +571,15 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" "@babel/plugin-syntax-optional-chaining" "^7.8.3" +"@babel/plugin-proposal-optional-chaining@^7.20.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz#886f5c8978deb7d30f678b2e24346b287234d3ea" + integrity sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-proposal-private-methods@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz#5209de7d213457548a98436fa2882f52f4be6bea" @@ -609,7 +634,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-dynamic-import@^7.0.0", "@babel/plugin-syntax-dynamic-import@^7.8.3": +"@babel/plugin-syntax-dynamic-import@^7.0.0", "@babel/plugin-syntax-dynamic-import@^7.8.0", "@babel/plugin-syntax-dynamic-import@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== @@ -744,6 +769,15 @@ "@babel/helper-plugin-utils" "^7.18.6" "@babel/helper-remap-async-to-generator" "^7.18.6" +"@babel/plugin-transform-async-to-generator@^7.20.0": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.20.7.tgz#dfee18623c8cb31deb796aa3ca84dda9cea94354" + integrity sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q== + dependencies: + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-remap-async-to-generator" "^7.18.9" + "@babel/plugin-transform-block-scoped-functions@^7.0.0", "@babel/plugin-transform-block-scoped-functions@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz#9187bf4ba302635b9d70d986ad70f038726216a8" @@ -787,6 +821,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.20.2" +"@babel/plugin-transform-destructuring@^7.20.0": + version "7.21.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.21.3.tgz#73b46d0fd11cd6ef57dea8a381b1215f4959d401" + integrity sha512-bp6hwMFzuiE4HqYEyoGJ/V2LeIWn+hLVKc4pnj++E5XQptwhtcGmSayM029d/j2X1bPKGTlsyPwAubuU22KhMA== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/plugin-transform-dotall-regex@^7.18.6", "@babel/plugin-transform-dotall-regex@^7.4.4": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz#b286b3e7aae6c7b861e45bed0a2fafd6b1a4fef8" @@ -818,6 +859,14 @@ "@babel/helper-plugin-utils" "^7.19.0" "@babel/plugin-syntax-flow" "^7.18.6" +"@babel/plugin-transform-flow-strip-types@^7.20.0", "@babel/plugin-transform-flow-strip-types@^7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.21.0.tgz#6aeca0adcb81dc627c8986e770bfaa4d9812aff5" + integrity sha512-FlFA2Mj87a6sDkW4gfGrQQqwY/dLlBAyJa2dJEZ+FHXUVHBflO2wyKvg+OOEzXfrKYIa4HWl0mgmbCzt0cMb7w== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/plugin-syntax-flow" "^7.18.6" + "@babel/plugin-transform-for-of@^7.0.0", "@babel/plugin-transform-for-of@^7.18.8": version "7.18.8" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz#6ef8a50b244eb6a0bdbad0c7c61877e4e30097c1" @@ -913,6 +962,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.20.2" +"@babel/plugin-transform-parameters@^7.20.7": + version "7.21.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.21.3.tgz#18fc4e797cf6d6d972cb8c411dbe8a809fa157db" + integrity sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/plugin-transform-property-literals@^7.0.0", "@babel/plugin-transform-property-literals@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz#e22498903a483448e94e032e9bbb9c5ccbfc93a3" @@ -952,7 +1008,7 @@ "@babel/plugin-syntax-jsx" "^7.18.6" "@babel/types" "^7.19.0" -"@babel/plugin-transform-regenerator@^7.0.0", "@babel/plugin-transform-regenerator@^7.18.6": +"@babel/plugin-transform-regenerator@^7.18.6": version "7.20.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.20.5.tgz#57cda588c7ffb7f4f8483cc83bdcea02a907f04d" integrity sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ== @@ -960,6 +1016,14 @@ "@babel/helper-plugin-utils" "^7.20.2" regenerator-transform "^0.15.1" +"@babel/plugin-transform-regenerator@^7.20.0": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.21.5.tgz#576c62f9923f94bcb1c855adc53561fd7913724e" + integrity sha512-ZoYBKDb6LyMi5yCsByQ5jmXsHAQDDYeexT1Szvlmui+lADvfSecr5Dxd/PkrTC3pAD182Fcju1VQkB4oCp9M+w== + dependencies: + "@babel/helper-plugin-utils" "^7.21.5" + regenerator-transform "^0.15.1" + "@babel/plugin-transform-reserved-words@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz#b1abd8ebf8edaa5f7fe6bbb8d2133d23b6a6f76a" @@ -1048,7 +1112,7 @@ "@babel/helper-create-regexp-features-plugin" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" -"@babel/preset-env@^7.14.0", "@babel/preset-env@^7.20.0": +"@babel/preset-env@^7.20.0": version "7.20.2" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.20.2.tgz#9b1642aa47bb9f43a86f9630011780dab7f86506" integrity sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg== @@ -1129,7 +1193,7 @@ core-js-compat "^3.25.1" semver "^6.3.0" -"@babel/preset-flow@^7.13.13", "@babel/preset-flow@^7.18.0": +"@babel/preset-flow@^7.13.13": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.18.6.tgz#83f7602ba566e72a9918beefafef8ef16d2810cb" integrity sha512-E7BDhL64W6OUqpuyHnSroLnqyRTcG6ZdOBl1OKI/QK/HJfplqK/S3sq1Cckx7oTodJ5yOXyfw7rEADJ6UjoQDQ== @@ -1138,6 +1202,15 @@ "@babel/helper-validator-option" "^7.18.6" "@babel/plugin-transform-flow-strip-types" "^7.18.6" +"@babel/preset-flow@^7.20.0": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.21.4.tgz#a5de2a1cafa61f0e0b3af9b30ff0295d38d3608f" + integrity sha512-F24cSq4DIBmhq4OzK3dE63NHagb27OPE3eWR+HLekt4Z3Y5MzIIUGF3LlLgV0gN8vzbDViSY7HnrReNVCJXTeA== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-validator-option" "^7.21.0" + "@babel/plugin-transform-flow-strip-types" "^7.21.0" + "@babel/preset-modules@^0.1.5": version "0.1.5" resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" @@ -1358,6 +1431,18 @@ tar "^6.1.11" tar-stream "^2.1.4" +"@eslint-community/eslint-utils@^4.2.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.4.0": + version "4.5.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.5.1.tgz#cdd35dce4fa1a89a4fd42b1599eb35b3af408884" + integrity sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ== + "@eslint/eslintrc@^1.3.2": version "1.3.2" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.2.tgz#58b69582f3b7271d8fa67fe5251767a5b38ea356" @@ -1373,6 +1458,26 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" +"@eslint/eslintrc@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.0.3.tgz#4910db5505f4d503f27774bf356e3704818a0331" + integrity sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.5.2" + globals "^13.19.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@8.40.0": + version "8.40.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.40.0.tgz#3ba73359e11f5a7bd3e407f70b3528abfae69cec" + integrity sha512-ElyB54bJIhXQYVKjDSvCkPO1iU1tSAeVQJbllWJq1XQSmmA4dgFk8CbiBGpiOPxleE48vDogxCtmMYku4HSVLA== + "@firebase/analytics-compat@0.1.13": version "0.1.13" resolved "https://registry.yarnpkg.com/@firebase/analytics-compat/-/analytics-compat-0.1.13.tgz#61e1d6f9e4d033c3ed9943d91530eb3e0f382f92" @@ -1828,6 +1933,15 @@ debug "^4.1.1" minimatch "^3.0.4" +"@humanwhocodes/config-array@^0.11.8": + version "0.11.8" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9" + integrity sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g== + dependencies: + "@humanwhocodes/object-schema" "^1.2.1" + debug "^4.1.1" + minimatch "^3.0.5" + "@humanwhocodes/gitignore-to-minimatch@^1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz#316b0a63b91c10e53f242efb4ace5c3b34e8728d" @@ -2273,7 +2387,7 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== -"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.15", "@jridgewell/trace-mapping@^0.3.8", "@jridgewell/trace-mapping@^0.3.9": +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.15", "@jridgewell/trace-mapping@^0.3.9": version "0.3.15" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz#aba35c48a38d3fd84b37e66c9c0423f9744f9774" integrity sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g== @@ -2314,7 +2428,7 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== -"@nodelib/fs.walk@^1.2.3": +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": version "1.2.8" resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== @@ -2938,7 +3052,7 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^5.30.0", "@typescript-eslint/eslint-plugin@^5.30.5": +"@typescript-eslint/eslint-plugin@^5.30.0": version "5.37.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.37.0.tgz#5ccdd5d9004120f28fc6e717fb4b5c9bddcfbc04" integrity sha512-Fde6W0IafXktz1UlnhGkrrmnnGpAo1kyX7dnyHHVrmwJOn72Oqm3eYtddrpOwwel2W8PAK9F3pIL5S+lfoM0og== @@ -2953,7 +3067,23 @@ semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/parser@^5.30.0", "@typescript-eslint/parser@^5.30.5": +"@typescript-eslint/eslint-plugin@^5.57.1": + version "5.59.5" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.5.tgz#f156827610a3f8cefc56baeaa93cd4a5f32966b4" + integrity sha512-feA9xbVRWJZor+AnLNAr7A8JRWeZqHUf4T9tlP+TN04b05pFVhO5eN7/O93Y/1OUlLMHKbnJisgDURs/qvtqdg== + dependencies: + "@eslint-community/regexpp" "^4.4.0" + "@typescript-eslint/scope-manager" "5.59.5" + "@typescript-eslint/type-utils" "5.59.5" + "@typescript-eslint/utils" "5.59.5" + debug "^4.3.4" + grapheme-splitter "^1.0.4" + ignore "^5.2.0" + natural-compare-lite "^1.4.0" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/parser@^5.30.0": version "5.37.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.37.0.tgz#c382077973f3a4ede7453fb14cadcad3970cbf3b" integrity sha512-01VzI/ipYKuaG5PkE5+qyJ6m02fVALmMPY3Qq5BHflDx3y4VobbLdHQkSMg9VPRS4KdNt4oYTMaomFoHonBGAw== @@ -2963,6 +3093,16 @@ "@typescript-eslint/typescript-estree" "5.37.0" debug "^4.3.4" +"@typescript-eslint/parser@^5.57.1": + version "5.59.5" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.59.5.tgz#63064f5eafbdbfb5f9dfbf5c4503cdf949852981" + integrity sha512-NJXQC4MRnF9N9yWqQE2/KLRSOLvrrlZb48NGVfBa+RuPMN6B7ZcK5jZOvhuygv4D64fRKnZI4L4p8+M+rfeQuw== + dependencies: + "@typescript-eslint/scope-manager" "5.59.5" + "@typescript-eslint/types" "5.59.5" + "@typescript-eslint/typescript-estree" "5.59.5" + debug "^4.3.4" + "@typescript-eslint/scope-manager@5.37.0": version "5.37.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.37.0.tgz#044980e4f1516a774a418dafe701a483a6c9f9ca" @@ -2979,6 +3119,14 @@ "@typescript-eslint/types" "5.54.0" "@typescript-eslint/visitor-keys" "5.54.0" +"@typescript-eslint/scope-manager@5.59.5": + version "5.59.5" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.59.5.tgz#33ffc7e8663f42cfaac873de65ebf65d2bce674d" + integrity sha512-jVecWwnkX6ZgutF+DovbBJirZcAxgxC0EOHYt/niMROf8p4PwxxG32Qdhj/iIQQIuOflLjNkxoXyArkcIP7C3A== + dependencies: + "@typescript-eslint/types" "5.59.5" + "@typescript-eslint/visitor-keys" "5.59.5" + "@typescript-eslint/type-utils@5.37.0": version "5.37.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.37.0.tgz#43ed2f567ada49d7e33a6e4b6f9babd060445fe5" @@ -2989,6 +3137,16 @@ debug "^4.3.4" tsutils "^3.21.0" +"@typescript-eslint/type-utils@5.59.5": + version "5.59.5" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.59.5.tgz#485b0e2c5b923460bc2ea6b338c595343f06fc9b" + integrity sha512-4eyhS7oGym67/pSxA2mmNq7X164oqDYNnZCUayBwJZIRVvKpBCMBzFnFxjeoDeShjtO6RQBHBuwybuX3POnDqg== + dependencies: + "@typescript-eslint/typescript-estree" "5.59.5" + "@typescript-eslint/utils" "5.59.5" + debug "^4.3.4" + tsutils "^3.21.0" + "@typescript-eslint/types@5.37.0": version "5.37.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.37.0.tgz#09e4870a5f3af7af3f84e08d792644a87d232261" @@ -2999,6 +3157,11 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.54.0.tgz#7d519df01f50739254d89378e0dcac504cab2740" integrity sha512-nExy+fDCBEgqblasfeE3aQ3NuafBUxZxgxXcYfzYRZFHdVvk5q60KhCSkG0noHgHRo/xQ/BOzURLZAafFpTkmQ== +"@typescript-eslint/types@5.59.5": + version "5.59.5" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.59.5.tgz#e63c5952532306d97c6ea432cee0981f6d2258c7" + integrity sha512-xkfRPHbqSH4Ggx4eHRIO/eGL8XL4Ysb4woL8c87YuAo8Md7AUjyWKa9YMwTL519SyDPrfEgKdewjkxNCVeJW7w== + "@typescript-eslint/typescript-estree@5.37.0": version "5.37.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.37.0.tgz#956dcf5c98363bcb97bdd5463a0a86072ff79355" @@ -3025,6 +3188,19 @@ semver "^7.3.7" tsutils "^3.21.0" +"@typescript-eslint/typescript-estree@5.59.5": + version "5.59.5" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.5.tgz#9b252ce55dd765e972a7a2f99233c439c5101e42" + integrity sha512-+XXdLN2CZLZcD/mO7mQtJMvCkzRfmODbeSKuMY/yXbGkzvA9rJyDY5qDYNoiz2kP/dmyAxXquL2BvLQLJFPQIg== + dependencies: + "@typescript-eslint/types" "5.59.5" + "@typescript-eslint/visitor-keys" "5.59.5" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + semver "^7.3.7" + tsutils "^3.21.0" + "@typescript-eslint/utils@5.37.0", "@typescript-eslint/utils@^5.10.0", "@typescript-eslint/utils@^5.30.0": version "5.37.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.37.0.tgz#7784cb8e91390c4f90ccaffd24a0cf9874df81b2" @@ -3037,6 +3213,20 @@ eslint-scope "^5.1.1" eslint-utils "^3.0.0" +"@typescript-eslint/utils@5.59.5": + version "5.59.5" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.59.5.tgz#15b3eb619bb223302e60413adb0accd29c32bcae" + integrity sha512-sCEHOiw+RbyTii9c3/qN74hYDPNORb8yWCoPLmB7BIflhplJ65u2PBpdRla12e3SSTJ2erRkPjz7ngLHhUegxA== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@types/json-schema" "^7.0.9" + "@types/semver" "^7.3.12" + "@typescript-eslint/scope-manager" "5.59.5" + "@typescript-eslint/types" "5.59.5" + "@typescript-eslint/typescript-estree" "5.59.5" + eslint-scope "^5.1.1" + semver "^7.3.7" + "@typescript-eslint/utils@^5.47.1": version "5.54.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.54.0.tgz#3db758aae078be7b54b8ea8ea4537ff6cd3fbc21" @@ -3067,6 +3257,14 @@ "@typescript-eslint/types" "5.54.0" eslint-visitor-keys "^3.3.0" +"@typescript-eslint/visitor-keys@5.59.5": + version "5.59.5" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.5.tgz#ba5b8d6791a13cf9fea6716af1e7626434b29b9b" + integrity sha512-qL+Oz+dbeBRTeyJTIy0eniD3uvqU7x+y1QceBismZ41hd4aBSRh8UAw4pZP0+XzLuPZmx4raNMq/I+59W2lXKA== + dependencies: + "@typescript-eslint/types" "5.59.5" + eslint-visitor-keys "^3.3.0" + abab@^2.0.0: version "2.0.6" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" @@ -3622,7 +3820,7 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= -base64-js@^1.1.2, base64-js@^1.3.1: +base64-js@^1.3.1, base64-js@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -4879,6 +5077,14 @@ eslint-scope@^7.1.1: esrecurse "^4.3.0" estraverse "^5.2.0" +eslint-scope@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.0.tgz#f21ebdafda02352f103634b96dd47d9f81ca117b" + integrity sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + eslint-utils@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" @@ -4896,7 +5102,12 @@ eslint-visitor-keys@^3.3.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== -eslint@^8.17.0, eslint@^8.19.0: +eslint-visitor-keys@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994" + integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA== + +eslint@^8.17.0: version "8.23.1" resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.23.1.tgz#cfd7b3f7fdd07db8d16b4ac0516a29c8d8dca5dc" integrity sha512-w7C1IXCc6fNqjpuYd0yPlcTKKmHlHHktRkzmBPZ+7cvNBQuiNjx0xaMTjAJGCafJhQkrFJooREv0CtrVzmHwqg== @@ -4941,6 +5152,52 @@ eslint@^8.17.0, eslint@^8.19.0: strip-json-comments "^3.1.0" text-table "^0.2.0" +eslint@^8.19.0: + version "8.40.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.40.0.tgz#a564cd0099f38542c4e9a2f630fa45bf33bc42a4" + integrity sha512-bvR+TsP9EHL3TqNtj9sCNJVAFK3fBN8Q7g5waghxyRsPLIMwL73XSKnZFK0hk/O2ANC+iAoq6PWMQ+IfBAJIiQ== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.4.0" + "@eslint/eslintrc" "^2.0.3" + "@eslint/js" "8.40.0" + "@humanwhocodes/config-array" "^0.11.8" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.2.0" + eslint-visitor-keys "^3.4.1" + espree "^9.5.2" + esquery "^1.4.2" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + find-up "^5.0.0" + glob-parent "^6.0.2" + globals "^13.19.0" + grapheme-splitter "^1.0.4" + ignore "^5.2.0" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + is-path-inside "^3.0.3" + js-sdsl "^4.1.4" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.1" + strip-ansi "^6.0.1" + strip-json-comments "^3.1.0" + text-table "^0.2.0" + espree@^9.4.0: version "9.4.0" resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.0.tgz#cd4bc3d6e9336c433265fc0aa016fc1aaf182f8a" @@ -4950,6 +5207,15 @@ espree@^9.4.0: acorn-jsx "^5.3.2" eslint-visitor-keys "^3.3.0" +espree@^9.5.2: + version "9.5.2" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.5.2.tgz#e994e7dc33a082a7a82dceaf12883a829353215b" + integrity sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw== + dependencies: + acorn "^8.8.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" @@ -4962,6 +5228,13 @@ esquery@^1.4.0: dependencies: estraverse "^5.1.0" +esquery@^1.4.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== + dependencies: + estraverse "^5.1.0" + esrecurse@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" @@ -5328,21 +5601,26 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.2.tgz#64bfed5cb68fe3ca78b3eb214ad97b63bedce561" integrity sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA== -flow-bin@^0.204.1: - version "0.204.1" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.204.1.tgz#096c1dc5413edfa3f8284f888449f436a10a68fc" - integrity sha512-gYlDS1cRIV/FnqLc8G0xb/pFdu9eGM+NuxZlihlxRrt3GTfei8IioPSXMpiJz11DPPkiAr9tpIyI+g5RcP1W7Q== +flow-bin@^0.206.0: + version "0.206.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.206.0.tgz#a593304be5440a965ae773efcef55071b6d33178" + integrity sha512-cZTEs/OEWcbxfvb8BP+Fw0Cep5wrEyEzQHGpXyjVpQXrAraRA5wZUXvTf1C5YHufQaAYY9YkKY5WAr461JvmOA== -flow-enums-runtime@^0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/flow-enums-runtime/-/flow-enums-runtime-0.0.5.tgz#95884bfcc82edaf27eef7e1dd09732331cfbafbc" - integrity sha512-PSZF9ZuaZD03sT9YaIs0FrGJ7lSUw7rHZIex+73UYVXg46eL/wxN5PaVcPJFudE2cJu5f0fezitV5aBkLHPUOQ== +flow-enums-runtime@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz#5bb0cd1b0a3e471330f4d109039b7eba5cb3e787" + integrity sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw== -flow-parser@0.*, flow-parser@^0.185.0: +flow-parser@0.*: version "0.185.0" resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.185.0.tgz#56bde60805bad19b2934ebfc50c9485e5c5424f9" integrity sha512-VWpXjEbQbIGQvB6CyWwx56wMioGZ6w2s8qJlFiuE3S7D8O+xE5t988i1u2TGFO5TLSzQPUhfIOzPpLYA93H9Jg== +flow-parser@^0.206.0: + version "0.206.0" + resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.206.0.tgz#f4f794f8026535278393308e01ea72f31000bfef" + integrity sha512-HVzoK3r6Vsg+lKvlIZzaWNBVai+FXTX1wdYhz/wVlH13tb/gOdLXmlTqy6odmTBhT5UoWUbq0k8263Qhr9d88w== + for-each@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" @@ -5590,7 +5868,7 @@ glob-parent@^5.1.2, glob-parent@~5.1.2: dependencies: is-glob "^4.0.1" -glob-parent@^6.0.1: +glob-parent@^6.0.1, glob-parent@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== @@ -5621,6 +5899,13 @@ globals@^13.15.0: dependencies: type-fest "^0.20.2" +globals@^13.19.0: + version "13.20.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82" + integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ== + dependencies: + type-fest "^0.20.2" + globalthis@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" @@ -6261,6 +6546,11 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" @@ -8123,7 +8413,7 @@ mimic-response@^3.1.0: resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== -minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: +minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -8222,6 +8512,11 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" +natural-compare-lite@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" + integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -9004,10 +9299,10 @@ range-parser@~1.2.0: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= -react-devtools-core@^4.27.2: - version "4.27.2" - resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-4.27.2.tgz#d20fc57e258c656eedabafc2c851d38b33583148" - integrity sha512-8SzmIkpO87alD7Xr6gWIEa1jHkMjawOZ+6egjazlnjB4UUcbnzGDf/vBJ4BzGuWWEM+pzrxuzsPpcMqlQkYK2g== +react-devtools-core@^4.27.7: + version "4.27.7" + resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-4.27.7.tgz#458a6541483078d60a036c75bf88f54c478086ec" + integrity sha512-12N0HrhCPbD76Z7SkyJdGdXdPGouUsgV6tlEsbSpAnLDO06tjXZP+irht4wPdYwJAJRQ85DxL48eQoz7UmrSuQ== dependencies: shell-quote "^1.6.1" ws "^7" @@ -9475,6 +9770,13 @@ sax@^1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== +scheduler@0.24.0-canary-efb381bbf-20230505: + version "0.24.0-canary-efb381bbf-20230505" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.24.0-canary-efb381bbf-20230505.tgz#5dddc60e29f91cd7f8b983d7ce4a99c2202d178f" + integrity sha512-ABvovCDe/k9IluqSh4/ISoq8tIJnW8euVAWYt5j/bg6dRnqwQwiGO1F/V4AyK96NGF/FB04FhOUDuWj8IKfABA== + dependencies: + loose-envify "^1.1.0" + scheduler@^0.23.0: version "0.23.0" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" @@ -10386,10 +10688,10 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== -typescript@4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7" - integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg== +typescript@5.0.4: + version "5.0.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b" + integrity sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw== uglify-es@^3.1.9: version "3.3.9"