Skip to content

Commit c7e1e00

Browse files
Make C++ struct generator type-safe (#35656)
Summary: Pull Request resolved: #35656 Changelog: [Internal] ## Change: #35265 added a struct generator - but it is not type safe :-( E.g. you can write a TM Spec type as: ``` export type CustomType = { key: string; enabled: boolean; time?: number; } ``` And a C++ type as: ``` using CustomType = NativeSampleModuleBaseCustomType<float, bool, std::optional<int32_t>>; template <> struct Bridging<CustomType> : NativeSampleModuleBaseCustomTypeBridging<float, bool, std::optional<int32_t>> {}; ``` and it will still compile :-( - which should not. The reason is that the generated structs don't validate the members type :-( ``` template <typename P0, typename P1, typename P2> struct NativeSampleModuleBaseCustomType { P0 key; P1 enabled; P2 time; bool operator==(const NativeSampleModuleBaseCustomType &other) const { return key == other.key && enabled == other.enabled && time == other.time; } }; template <typename P0, typename P1, typename P2> struct NativeSampleModuleBaseCustomTypeBridging { static NativeSampleModuleBaseCustomType<P0, P1, P2> fromJs( jsi::Runtime &rt, const jsi::Object &value, const std::shared_ptr<CallInvoker> &jsInvoker) { NativeSampleModuleBaseCustomType<P0, P1, P2> result{ bridging::fromJs<P0>(rt, value.getProperty(rt, "key"), jsInvoker), bridging::fromJs<P1>(rt, value.getProperty(rt, "enabled"), jsInvoker), bridging::fromJs<P2>(rt, value.getProperty(rt, "time"), jsInvoker)}; return result; } static jsi::Object toJs( jsi::Runtime &rt, const NativeSampleModuleBaseCustomType<P0, P1, P2> &value) { auto result = facebook::jsi::Object(rt); result.setProperty(rt, "key", bridging::toJs(rt, value.key)); result.setProperty(rt, "enabled", bridging::toJs(rt, value.enabled)); if (value.time) { result.setProperty(rt, "time", bridging::toJs(rt, value.time.value())); } keyToJs(rt, value.key); return result; } }; ``` This fixes that, by simply emitting conversion functions for each member such as ``` #ifdef DEBUG static bool keyToJs(jsi::Runtime &rt, P0 value) { return bridging::toJs(rt, value); } static double enabledToJs(jsi::Runtime &rt, P1 value) { return bridging::toJs(rt, value); } static jsi::String timeToJs(jsi::Runtime &rt, P2 value) { return bridging::toJs(rt, value); } #endif ``` Reviewed By: cipolleschi Differential Revision: D42082423 fbshipit-source-id: 5133f14e2aa8351e9bbbf614117a3d5894b17fa6
1 parent b2dbfbc commit c7e1e00

File tree

2 files changed

+257
-110
lines changed

2 files changed

+257
-110
lines changed

packages/react-native-codegen/src/generators/modules/GenerateModuleH.js

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,20 @@ function createStructs(
210210
const templateParameter = value.properties
211211
.map((v, i) => 'P' + i)
212212
.join(', ');
213+
const paramemterConversion = value.properties
214+
.map((v, i) => {
215+
const translatedParam = translatePrimitiveJSTypeToCpp(
216+
v.typeAnnotation,
217+
false,
218+
typeName =>
219+
`Unsupported type for param "${v.name}". Found: ${typeName}`,
220+
resolveAlias,
221+
);
222+
return ` static ${translatedParam} ${v.name}ToJs(jsi::Runtime &rt, P${i} value) {
223+
return bridging::toJs(rt, value);
224+
}`;
225+
})
226+
.join('\n');
213227
return `#pragma mark - ${structName}
214228
215229
template <${templateParameterWithTypename}>
@@ -238,25 +252,29 @@ ${value.properties
238252
return result;
239253
}
240254
255+
#ifdef DEBUG
256+
${paramemterConversion}
257+
#endif
258+
241259
static jsi::Object toJs(
242-
jsi::Runtime &rt,
243-
const ${structName}<${templateParameter}> &value,
244-
const std::shared_ptr<CallInvoker> &jsInvoker) {
245-
auto result = facebook::jsi::Object(rt);
246-
${value.properties
247-
.map((v, i) => {
248-
if (v.optional) {
249-
return ` if (value.${v.name}) {
250-
result.setProperty(rt, "${v.name}", bridging::toJs(rt, value.${v.name}.value(), jsInvoker));
251-
}`;
252-
} else {
253-
return ` result.setProperty(rt, "${v.name}", bridging::toJs(rt, value.${v.name}, jsInvoker));`;
254-
}
255-
})
256-
.join('\n')}
257-
return result;
258-
}
259-
};
260+
jsi::Runtime &rt,
261+
const ${structName}<${templateParameter}> &value,
262+
const std::shared_ptr<CallInvoker> &jsInvoker) {
263+
auto result = facebook::jsi::Object(rt);
264+
${value.properties
265+
.map((v, i) => {
266+
if (v.optional) {
267+
return ` if (value.${v.name}) {
268+
result.setProperty(rt, "${v.name}", bridging::toJs(rt, value.${v.name}.value(), jsInvoker));
269+
}`;
270+
} else {
271+
return ` result.setProperty(rt, "${v.name}", bridging::toJs(rt, value.${v.name}, jsInvoker));`;
272+
}
273+
})
274+
.join('\n')}
275+
return result;
276+
}
277+
};
260278
261279
`;
262280
})

0 commit comments

Comments
 (0)