mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Summary: ## New Functionality - Detect if the JS file represents a NativeModule spec. - **Note:** A JS file is a NativeModule spec if it contains a flow `interface` that extends `TurboModule`. This logic is copied over from the OSS Codegen, here: https://github.com/facebook/react-native/blob/7ccb67a49c087e7ee536c2ffb71717e68a79324b/packages/react-native-codegen/src/parsers/flow/index.js#L60-L75 - For all NativeModule specs, generate the spec's schema using the OSS Codegen for Modules, and conditionally inline it into every `TurboModuleRegistry.get(Enforcing)?` call in the spec, like so: **Before:** ``` /** * flow */ import type {TurboModule} from 'RCTExport'; export interface Spec extends TurboModule { //... } export default TurboModuleRegistry.get<Spec>('FooModule'); ``` **After:** ``` /** * flow */ import type {TurboModule} from 'RCTExport'; export interface Spec extends TurboModule { //... } export default TurboModuleRegistry.get<Spec>('FooModule', __getModuleShape()); function __getModuleShape() { if (!(global.RN$EnableTurboModuleJSCodegen === true)) { return undefined; } return {...}; } ``` Changelog: [General][Added] Extend react-native/babel-plugin-codegen to generate TurboModule JS codegen Reviewed By: TheSavior Differential Revision: D22803845 fbshipit-source-id: 18c157a1dbfcc575012184de31c38908acd53c36
245 lines
6.9 KiB
JavaScript
245 lines
6.9 KiB
JavaScript
/**
|
|
* 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.
|
|
*
|
|
* @flow strict-local
|
|
* @format
|
|
*/
|
|
|
|
'use strict';
|
|
const NOT_A_NATIVE_COMPONENT = `
|
|
const requireNativeComponent = require('requireNativeComponent');
|
|
|
|
export default 'Not a view config'
|
|
`;
|
|
|
|
const FULL_NATIVE_COMPONENT = `
|
|
// @flow
|
|
|
|
const codegenNativeCommands = require('codegenNativeCommands');
|
|
const codegenNativeComponent = require('codegenNativeComponent');
|
|
|
|
import type {
|
|
Int32,
|
|
BubblingEventHandler,
|
|
DirectEventHandler,
|
|
WithDefault,
|
|
} from 'CodegenFlowtypes';
|
|
import type {NativeComponentType} from 'codegenNativeComponent';
|
|
|
|
import type {ViewProps} from 'ViewPropTypes';
|
|
|
|
type ModuleProps = $ReadOnly<{|
|
|
...ViewProps,
|
|
|
|
// Props
|
|
boolean_default_true_optional_both?: WithDefault<boolean, true>,
|
|
|
|
// Events
|
|
onDirectEventDefinedInlineNull: DirectEventHandler<null>,
|
|
onBubblingEventDefinedInlineNull: BubblingEventHandler<null>,
|
|
|}>;
|
|
|
|
type NativeType = NativeComponentType<ModuleProps>;
|
|
|
|
interface NativeCommands {
|
|
+hotspotUpdate: (viewRef: React.ElementRef<NativeType>, x: Int32, y: Int32) => void;
|
|
+scrollTo: (viewRef: React.ElementRef<NativeType>, y: Int32, animated: boolean) => void;
|
|
}
|
|
|
|
export const Commands = codegenNativeCommands<NativeCommands>({
|
|
supportedCommands: ['hotspotUpdate', 'scrollTo'],
|
|
});
|
|
|
|
export default codegenNativeComponent<ModuleProps>('Module', {
|
|
interfaceOnly: true,
|
|
paperComponentName: 'RCTModule',
|
|
});
|
|
`;
|
|
|
|
const FULL_NATIVE_COMPONENT_WITH_TYPE_EXPORT = `
|
|
// @flow
|
|
|
|
const codegenNativeCommands = require('codegenNativeCommands');
|
|
const codegenNativeComponent = require('codegenNativeComponent');
|
|
import type {NativeComponentType} from 'codegenNativeComponent';
|
|
|
|
import type {
|
|
Int32,
|
|
BubblingEventHandler,
|
|
DirectEventHandler,
|
|
WithDefault,
|
|
} from 'CodegenFlowtypes';
|
|
|
|
import type {ViewProps} from 'ViewPropTypes';
|
|
|
|
type ModuleProps = $ReadOnly<{|
|
|
...ViewProps,
|
|
|
|
// Props
|
|
boolean_default_true_optional_both?: WithDefault<boolean, true>,
|
|
|
|
// Events
|
|
onDirectEventDefinedInlineNull: DirectEventHandler<null>,
|
|
onBubblingEventDefinedInlineNull: BubblingEventHandler<null>,
|
|
|}>;
|
|
|
|
type NativeType = NativeComponentType<ModuleProps>;
|
|
|
|
interface NativeCommands {
|
|
+hotspotUpdate: (viewRef: React.ElementRef<NativeType>, x: Int32, y: Int32) => void;
|
|
+scrollTo: (viewRef: React.ElementRef<NativeType>, y: Int32, animated: boolean) => void;
|
|
}
|
|
|
|
export const Commands = codegenNativeCommands<NativeCommands>({
|
|
supportedCommands: ['hotspotUpdate', 'scrollTo'],
|
|
});
|
|
|
|
export default (codegenNativeComponent<ModuleProps>('Module', {
|
|
interfaceOnly: true,
|
|
paperComponentName: 'RCTModule',
|
|
}): NativeType);
|
|
`;
|
|
|
|
const SAMPLE_TURBO_MODULE_SINGLE_DEFAULT_EXPORT = `
|
|
// @flow
|
|
|
|
import type {RootTag, TurboModule} from '../RCTExport';
|
|
import * as TurboModuleRegistry from '../TurboModuleRegistry';
|
|
|
|
export interface Spec extends TurboModule {
|
|
// Exported methods.
|
|
+getConstants: () => {|
|
|
const1: boolean,
|
|
const2: number,
|
|
const3: string,
|
|
|};
|
|
+voidFunc: () => void;
|
|
+getBool: (arg: boolean) => boolean;
|
|
+getNumber: (arg: number) => number;
|
|
+getString: (arg: string) => string;
|
|
+getArray: (arg: Array<any>) => Array<any>;
|
|
+getObject: (arg: Object) => Object;
|
|
+getRootTag: (arg: RootTag) => RootTag;
|
|
+getValue: (x: number, y: string, z: Object) => Object;
|
|
+getValueWithCallback: (callback: (value: string) => void) => void;
|
|
+getValueWithPromise: (error: boolean) => Promise<string>;
|
|
}
|
|
|
|
export default (TurboModuleRegistry.getEnforcing<Spec>(
|
|
'SampleTurboModule',
|
|
): Spec);
|
|
`;
|
|
|
|
const SAMPLE_TURBO_MODULE_VARIABLE_ASSIGNMENT = `
|
|
// @flow
|
|
|
|
import type {RootTag, TurboModule} from '../RCTExport';
|
|
import * as TurboModuleRegistry from '../TurboModuleRegistry';
|
|
|
|
export interface Spec extends TurboModule {
|
|
// Exported methods.
|
|
+getConstants: () => {|
|
|
const1: boolean,
|
|
const2: number,
|
|
const3: string,
|
|
|};
|
|
+voidFunc: () => void;
|
|
+getBool: (arg: boolean) => boolean;
|
|
+getNumber: (arg: number) => number;
|
|
+getString: (arg: string) => string;
|
|
+getArray: (arg: Array<any>) => Array<any>;
|
|
+getObject: (arg: Object) => Object;
|
|
+getRootTag: (arg: RootTag) => RootTag;
|
|
+getValue: (x: number, y: string, z: Object) => Object;
|
|
+getValueWithCallback: (callback: (value: string) => void) => void;
|
|
+getValueWithPromise: (error: boolean) => Promise<string>;
|
|
}
|
|
|
|
const module = TurboModuleRegistry.getEnforcing<Spec>(
|
|
'SampleTurboModule',
|
|
);
|
|
|
|
export default (module: Spec);
|
|
`;
|
|
|
|
const SAMPLE_TURBO_MODULE_MANY_MODULES_DEFAULT_EXPORT = `
|
|
// @flow
|
|
|
|
import type {RootTag, TurboModule} from '../RCTExport';
|
|
import * as TurboModuleRegistry from '../TurboModuleRegistry';
|
|
|
|
export interface Spec extends TurboModule {
|
|
// Exported methods.
|
|
+getConstants: () => {|
|
|
const1: boolean,
|
|
const2: number,
|
|
const3: string,
|
|
|};
|
|
+voidFunc: () => void;
|
|
+getBool: (arg: boolean) => boolean;
|
|
+getNumber: (arg: number) => number;
|
|
+getString: (arg: string) => string;
|
|
+getArray: (arg: Array<any>) => Array<any>;
|
|
+getObject: (arg: Object) => Object;
|
|
+getRootTag: (arg: RootTag) => RootTag;
|
|
+getValue: (x: number, y: string, z: Object) => Object;
|
|
+getValueWithCallback: (callback: (value: string) => void) => void;
|
|
+getValueWithPromise: (error: boolean) => Promise<string>;
|
|
}
|
|
|
|
export default (
|
|
(
|
|
TurboModuleRegistry.getEnforcing<Spec>('SampleTurboModule') ||
|
|
TurboModuleRegistry.getEnforcing<Spec>('SampleTurboModule2')
|
|
): Spec);
|
|
`;
|
|
|
|
const SAMPLE_TURBO_MODULE_MANY_MODULES_VARIABLE_ASSIGNMENT = `
|
|
// @flow
|
|
|
|
import type {RootTag, TurboModule} from '../RCTExport';
|
|
import * as TurboModuleRegistry from '../TurboModuleRegistry';
|
|
|
|
export interface Spec extends TurboModule {
|
|
// Exported methods.
|
|
+getConstants: () => {|
|
|
const1: boolean,
|
|
const2: number,
|
|
const3: string,
|
|
|};
|
|
+voidFunc: () => void;
|
|
+getBool: (arg: boolean) => boolean;
|
|
+getNumber: (arg: number) => number;
|
|
+getString: (arg: string) => string;
|
|
+getArray: (arg: Array<any>) => Array<any>;
|
|
+getObject: (arg: Object) => Object;
|
|
+getRootTag: (arg: RootTag) => RootTag;
|
|
+getValue: (x: number, y: string, z: Object) => Object;
|
|
+getValueWithCallback: (callback: (value: string) => void) => void;
|
|
+getValueWithPromise: (error: boolean) => Promise<string>;
|
|
}
|
|
|
|
const module1 = TurboModuleRegistry.getEnforcing<Spec>(
|
|
'SampleTurboModule',
|
|
);
|
|
|
|
const module2 = TurboModuleRegistry.getEnforcing<Spec>(
|
|
'SampleTurboModule2',
|
|
);
|
|
|
|
export default ((module1 || module2): Spec);
|
|
`;
|
|
|
|
module.exports = {
|
|
'NotANativeComponent.js': NOT_A_NATIVE_COMPONENT,
|
|
'FullNativeComponent.js': FULL_NATIVE_COMPONENT,
|
|
'FullTypedNativeComponent.js': FULL_NATIVE_COMPONENT_WITH_TYPE_EXPORT,
|
|
'NativeSampleTurboModule0.js': SAMPLE_TURBO_MODULE_SINGLE_DEFAULT_EXPORT,
|
|
'NativeSampleTurboModule1.js': SAMPLE_TURBO_MODULE_VARIABLE_ASSIGNMENT,
|
|
'NativeSampleTurboModule2.js': SAMPLE_TURBO_MODULE_MANY_MODULES_DEFAULT_EXPORT,
|
|
'NativeSampleTurboModule3.js': SAMPLE_TURBO_MODULE_MANY_MODULES_VARIABLE_ASSIGNMENT,
|
|
};
|