mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Add function properties to C++ TM complex datatyes (#41810)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41810 Changelog: [Internal] Reviewed By: zeyap Differential Revision: D51858746 fbshipit-source-id: e45ee68fc40e8b7ae3388ecdcedfec646d022e19
This commit is contained in:
committed by
Facebook GitHub Bot
parent
616a907798
commit
db609ff0c6
+79
@@ -1706,6 +1706,65 @@ const CXX_ONLY_NATIVE_MODULES: SchemaType = {
|
||||
},
|
||||
],
|
||||
},
|
||||
MenuItem: {
|
||||
type: 'ObjectTypeAnnotation',
|
||||
properties: [
|
||||
{
|
||||
name: 'label',
|
||||
optional: false,
|
||||
typeAnnotation: {
|
||||
type: 'StringTypeAnnotation',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'onPress',
|
||||
optional: false,
|
||||
typeAnnotation: {
|
||||
type: 'FunctionTypeAnnotation',
|
||||
returnTypeAnnotation: {
|
||||
type: 'VoidTypeAnnotation',
|
||||
},
|
||||
params: [
|
||||
{
|
||||
name: 'value',
|
||||
optional: false,
|
||||
typeAnnotation: {
|
||||
type: 'StringTypeAnnotation',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'flag',
|
||||
optional: false,
|
||||
typeAnnotation: {
|
||||
type: 'BooleanTypeAnnotation',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'shortcut',
|
||||
optional: true,
|
||||
typeAnnotation: {
|
||||
type: 'NullableTypeAnnotation',
|
||||
typeAnnotation: {
|
||||
type: 'StringTypeAnnotation',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'items',
|
||||
optional: true,
|
||||
typeAnnotation: {
|
||||
type: 'ArrayTypeAnnotation',
|
||||
elementType: {
|
||||
type: 'TypeAliasTypeAnnotation',
|
||||
name: 'MenuItem',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
enumMap: {
|
||||
EnumInt: {
|
||||
@@ -2236,6 +2295,26 @@ const CXX_ONLY_NATIVE_MODULES: SchemaType = {
|
||||
params: [],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'setMenu',
|
||||
optional: false,
|
||||
typeAnnotation: {
|
||||
type: 'FunctionTypeAnnotation',
|
||||
returnTypeAnnotation: {
|
||||
type: 'VoidTypeAnnotation',
|
||||
},
|
||||
params: [
|
||||
{
|
||||
name: 'menuItem',
|
||||
optional: false,
|
||||
typeAnnotation: {
|
||||
type: 'TypeAliasTypeAnnotation',
|
||||
name: 'MenuItem',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'emitCustomDeviceEvent',
|
||||
optional: false,
|
||||
|
||||
+8
@@ -253,6 +253,13 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFunc(jsi:
|
||||
);
|
||||
return jsi::Value::undefined();
|
||||
}
|
||||
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_setMenu(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
||||
static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->setMenu(
|
||||
rt,
|
||||
args[0].asObject(rt)
|
||||
);
|
||||
return jsi::Value::undefined();
|
||||
}
|
||||
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_emitCustomDeviceEvent(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
||||
static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->emitCustomDeviceEvent(
|
||||
rt,
|
||||
@@ -308,6 +315,7 @@ NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared
|
||||
methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithPromise};
|
||||
methodMap_[\\"getWithWithOptionalArgs\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getWithWithOptionalArgs};
|
||||
methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFunc};
|
||||
methodMap_[\\"setMenu\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_setMenu};
|
||||
methodMap_[\\"emitCustomDeviceEvent\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_emitCustomDeviceEvent};
|
||||
methodMap_[\\"voidFuncThrows\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFuncThrows};
|
||||
methodMap_[\\"getObjectThrows\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getObjectThrows};
|
||||
|
||||
+139
@@ -582,6 +582,70 @@ struct [[deprecated(\\"Use SampleTurboModuleCxxValueStructBridging instead.\\")]
|
||||
};
|
||||
|
||||
|
||||
|
||||
#pragma mark - SampleTurboModuleCxxBaseMenuItem
|
||||
|
||||
template <typename P0, typename P1, typename P2, typename P3>
|
||||
struct [[deprecated(\\"Use SampleTurboModuleCxxMenuItem instead.\\")]] SampleTurboModuleCxxBaseMenuItem {
|
||||
P0 label;
|
||||
P1 onPress;
|
||||
P2 shortcut;
|
||||
P3 items;
|
||||
bool operator==(const SampleTurboModuleCxxBaseMenuItem &other) const {
|
||||
return label == other.label && onPress == other.onPress && shortcut == other.shortcut && items == other.items;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename P0, typename P1, typename P2, typename P3>
|
||||
struct [[deprecated(\\"Use SampleTurboModuleCxxMenuItemBridging instead.\\")]] SampleTurboModuleCxxBaseMenuItemBridging {
|
||||
static SampleTurboModuleCxxBaseMenuItem<P0, P1, P2, P3> fromJs(
|
||||
jsi::Runtime &rt,
|
||||
const jsi::Object &value,
|
||||
const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
SampleTurboModuleCxxBaseMenuItem<P0, P1, P2, P3> result{
|
||||
bridging::fromJs<P0>(rt, value.getProperty(rt, \\"label\\"), jsInvoker),
|
||||
bridging::fromJs<P1>(rt, value.getProperty(rt, \\"onPress\\"), jsInvoker),
|
||||
bridging::fromJs<P2>(rt, value.getProperty(rt, \\"shortcut\\"), jsInvoker),
|
||||
bridging::fromJs<P3>(rt, value.getProperty(rt, \\"items\\"), jsInvoker)};
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static jsi::String labelToJs(jsi::Runtime &rt, P0 value) {
|
||||
return bridging::toJs(rt, value);
|
||||
}
|
||||
|
||||
static jsi::Function onPressToJs(jsi::Runtime &rt, P1 value) {
|
||||
return bridging::toJs(rt, value);
|
||||
}
|
||||
|
||||
static std::optional<jsi::String> shortcutToJs(jsi::Runtime &rt, P2 value) {
|
||||
return bridging::toJs(rt, value);
|
||||
}
|
||||
|
||||
static jsi::Array itemsToJs(jsi::Runtime &rt, P3 value) {
|
||||
return bridging::toJs(rt, value);
|
||||
}
|
||||
#endif
|
||||
|
||||
static jsi::Object toJs(
|
||||
jsi::Runtime &rt,
|
||||
const SampleTurboModuleCxxBaseMenuItem<P0, P1, P2, P3> &value,
|
||||
const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
auto result = facebook::jsi::Object(rt);
|
||||
result.setProperty(rt, \\"label\\", bridging::toJs(rt, value.label, jsInvoker));
|
||||
result.setProperty(rt, \\"onPress\\", bridging::toJs(rt, value.onPress, jsInvoker));
|
||||
if (value.shortcut) {
|
||||
result.setProperty(rt, \\"shortcut\\", bridging::toJs(rt, value.shortcut.value(), jsInvoker));
|
||||
}
|
||||
if (value.items) {
|
||||
result.setProperty(rt, \\"items\\", bridging::toJs(rt, value.items.value(), jsInvoker));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#pragma mark - SampleTurboModuleCxxConstantsStruct
|
||||
|
||||
template <typename P0, typename P1, typename P2>
|
||||
@@ -857,6 +921,72 @@ struct SampleTurboModuleCxxValueStructBridging {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#pragma mark - SampleTurboModuleCxxMenuItem
|
||||
|
||||
template <typename P0, typename P1, typename P2>
|
||||
struct SampleTurboModuleCxxMenuItem {
|
||||
P0 label;
|
||||
P1 onPress;
|
||||
P2 shortcut;
|
||||
std::optional<std::vector<SampleTurboModuleCxxMenuItem<P0, P1, P2>>> items;
|
||||
bool operator==(const SampleTurboModuleCxxMenuItem &other) const {
|
||||
return label == other.label && onPress == other.onPress && shortcut == other.shortcut && items == other.items;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct SampleTurboModuleCxxMenuItemBridging {
|
||||
static T types;
|
||||
|
||||
static T fromJs(
|
||||
jsi::Runtime &rt,
|
||||
const jsi::Object &value,
|
||||
const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
T result{
|
||||
bridging::fromJs<decltype(types.label)>(rt, value.getProperty(rt, \\"label\\"), jsInvoker),
|
||||
bridging::fromJs<decltype(types.onPress)>(rt, value.getProperty(rt, \\"onPress\\"), jsInvoker),
|
||||
bridging::fromJs<decltype(types.shortcut)>(rt, value.getProperty(rt, \\"shortcut\\"), jsInvoker),
|
||||
bridging::fromJs<decltype(types.items)>(rt, value.getProperty(rt, \\"items\\"), jsInvoker)};
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static jsi::String labelToJs(jsi::Runtime &rt, decltype(types.label) value) {
|
||||
return bridging::toJs(rt, value);
|
||||
}
|
||||
|
||||
static jsi::Function onPressToJs(jsi::Runtime &rt, decltype(types.onPress) value) {
|
||||
return bridging::toJs(rt, value);
|
||||
}
|
||||
|
||||
static std::optional<jsi::String> shortcutToJs(jsi::Runtime &rt, decltype(types.shortcut) value) {
|
||||
return bridging::toJs(rt, value);
|
||||
}
|
||||
|
||||
static jsi::Array itemsToJs(jsi::Runtime &rt, decltype(types.items) value) {
|
||||
return bridging::toJs(rt, value);
|
||||
}
|
||||
#endif
|
||||
|
||||
static jsi::Object toJs(
|
||||
jsi::Runtime &rt,
|
||||
const T &value,
|
||||
const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
auto result = facebook::jsi::Object(rt);
|
||||
result.setProperty(rt, \\"label\\", bridging::toJs(rt, value.label, jsInvoker));
|
||||
result.setProperty(rt, \\"onPress\\", bridging::toJs(rt, value.onPress, jsInvoker));
|
||||
if (value.shortcut) {
|
||||
result.setProperty(rt, \\"shortcut\\", bridging::toJs(rt, value.shortcut.value(), jsInvoker));
|
||||
}
|
||||
if (value.items) {
|
||||
result.setProperty(rt, \\"items\\", bridging::toJs(rt, value.items.value(), jsInvoker));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
class JSI_EXPORT NativeSampleTurboModuleCxxSpecJSI : public TurboModule {
|
||||
protected:
|
||||
NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker);
|
||||
@@ -883,6 +1013,7 @@ public:
|
||||
virtual jsi::Value getValueWithPromise(jsi::Runtime &rt, bool error) = 0;
|
||||
virtual std::optional<bool> getWithWithOptionalArgs(jsi::Runtime &rt, std::optional<bool> optionalArg) = 0;
|
||||
virtual void voidFunc(jsi::Runtime &rt) = 0;
|
||||
virtual void setMenu(jsi::Runtime &rt, jsi::Object menuItem) = 0;
|
||||
virtual void emitCustomDeviceEvent(jsi::Runtime &rt, jsi::String eventName) = 0;
|
||||
virtual void voidFuncThrows(jsi::Runtime &rt) = 0;
|
||||
virtual jsi::Object getObjectThrows(jsi::Runtime &rt, jsi::Object arg) = 0;
|
||||
@@ -1079,6 +1210,14 @@ private:
|
||||
return bridging::callFromJs<void>(
|
||||
rt, &T::voidFunc, jsInvoker_, instance_);
|
||||
}
|
||||
void setMenu(jsi::Runtime &rt, jsi::Object menuItem) override {
|
||||
static_assert(
|
||||
bridging::getParameterCount(&T::setMenu) == 2,
|
||||
\\"Expected setMenu(...) to have 2 parameters\\");
|
||||
|
||||
return bridging::callFromJs<void>(
|
||||
rt, &T::setMenu, jsInvoker_, instance_, std::move(menuItem));
|
||||
}
|
||||
void emitCustomDeviceEvent(jsi::Runtime &rt, jsi::String eventName) override {
|
||||
static_assert(
|
||||
bridging::getParameterCount(&T::emitCustomDeviceEvent) == 2,
|
||||
|
||||
@@ -235,7 +235,7 @@ function parseObjectProperty(
|
||||
);
|
||||
|
||||
if (
|
||||
propertyTypeAnnotation.type === 'FunctionTypeAnnotation' ||
|
||||
(propertyTypeAnnotation.type === 'FunctionTypeAnnotation' && !cxxOnly) ||
|
||||
propertyTypeAnnotation.type === 'PromiseTypeAnnotation' ||
|
||||
propertyTypeAnnotation.type === 'VoidTypeAnnotation'
|
||||
) {
|
||||
|
||||
@@ -169,6 +169,15 @@ void NativeCxxModuleExample::voidFunc(jsi::Runtime& rt) {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
void NativeCxxModuleExample::setMenu(jsi::Runtime& rt, MenuItem menuItem) {
|
||||
menuItem.onPress("value", true);
|
||||
if (menuItem.items) {
|
||||
for (auto subMenuItem : *menuItem.items) {
|
||||
subMenuItem.onPress("another value", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NativeCxxModuleExample::emitCustomDeviceEvent(
|
||||
jsi::Runtime& rt,
|
||||
jsi::String eventName) {
|
||||
|
||||
@@ -104,6 +104,17 @@ template <>
|
||||
struct Bridging<GraphNode>
|
||||
: NativeCxxModuleExampleCxxGraphNodeBridging<GraphNode> {};
|
||||
|
||||
#pragma mark - functional object properties
|
||||
|
||||
using MenuItem = NativeCxxModuleExampleCxxMenuItem<
|
||||
std::string,
|
||||
AsyncCallback<std::string, bool>,
|
||||
std::optional<std::string>>;
|
||||
|
||||
template <>
|
||||
struct Bridging<MenuItem>
|
||||
: NativeCxxModuleExampleCxxMenuItemBridging<MenuItem> {};
|
||||
|
||||
#pragma mark - implementation
|
||||
class NativeCxxModuleExample
|
||||
: public NativeCxxModuleExampleCxxSpec<NativeCxxModuleExample> {
|
||||
@@ -171,6 +182,8 @@ class NativeCxxModuleExample
|
||||
|
||||
void voidFunc(jsi::Runtime& rt);
|
||||
|
||||
void setMenu(jsi::Runtime& rt, MenuItem menuItem);
|
||||
|
||||
void emitCustomDeviceEvent(jsi::Runtime& rt, jsi::String eventName);
|
||||
|
||||
void voidFuncThrows(jsi::Runtime& rt);
|
||||
|
||||
@@ -67,6 +67,13 @@ export type GraphNode = {
|
||||
neighbors?: Array<GraphNode>,
|
||||
};
|
||||
|
||||
export type MenuItem = {
|
||||
label: string,
|
||||
onPress: (value: string, flag: boolean) => void,
|
||||
shortcut?: ?string,
|
||||
items?: Array<MenuItem>,
|
||||
};
|
||||
|
||||
export interface Spec extends TurboModule {
|
||||
+getArray: (arg: Array<ObjectStruct | null>) => Array<ObjectStruct | null>;
|
||||
+getBool: (arg: boolean) => boolean;
|
||||
@@ -92,6 +99,7 @@ export interface Spec extends TurboModule {
|
||||
+getValueWithPromise: (error: boolean) => Promise<string>;
|
||||
+getWithWithOptionalArgs: (optionalArg?: boolean) => ?boolean;
|
||||
+voidFunc: () => void;
|
||||
+setMenu: (menuItem: MenuItem) => void;
|
||||
+emitCustomDeviceEvent: (eventName: string) => void;
|
||||
+voidFuncThrows: () => void;
|
||||
+getObjectThrows: (arg: ObjectStruct) => ObjectStruct;
|
||||
|
||||
@@ -57,6 +57,7 @@ type Examples =
|
||||
| 'promise'
|
||||
| 'rejectPromise'
|
||||
| 'voidFunc'
|
||||
| 'setMenuItem'
|
||||
| 'optionalArgs'
|
||||
| 'emitDeviceEvent';
|
||||
|
||||
@@ -135,6 +136,28 @@ class NativeCxxModuleExampleExample extends React.Component<{||}, State> {
|
||||
.then(() => {})
|
||||
.catch(e => this._setResult('rejectPromise', e.message)),
|
||||
voidFunc: () => NativeCxxModuleExample?.voidFunc(),
|
||||
setMenuItem: () => {
|
||||
let curValue = '';
|
||||
NativeCxxModuleExample?.setMenu({
|
||||
label: 'File',
|
||||
onPress: (value: string, flag: boolean) => {
|
||||
curValue = `${value}: ${flag.toString()}`;
|
||||
this._setResult('setMenuItem', curValue);
|
||||
},
|
||||
items: [
|
||||
{
|
||||
label: 'Open',
|
||||
onPress: (value: string, flag: boolean) => {
|
||||
this._setResult(
|
||||
'setMenuItem',
|
||||
`${curValue} - ${value}: ${flag.toString()}`,
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
shortcut: 'ctrl+shift+f',
|
||||
});
|
||||
},
|
||||
optionalArgs: () => NativeCxxModuleExample?.getWithWithOptionalArgs(),
|
||||
emitDeviceEvent: () => {
|
||||
const CUSTOM_EVENT_TYPE = 'myCustomDeviceEvent';
|
||||
|
||||
Reference in New Issue
Block a user