Skip to content

Commit 19614c2

Browse files
committed
[embind] Add register_type<T>(name, definition) to emit a stable TS alias
Introduce a second overload of register_type that creates a named TypeScript alias for val-based types declared with EMSCRIPTEN_DECLARE_VAL_TYPE. See changes in tests for examples.
1 parent 0743e64 commit 19614c2

File tree

11 files changed

+72
-0
lines changed

11 files changed

+72
-0
lines changed

site/source/docs/porting/connecting_cpp_and_javascript/embind.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,6 +1214,13 @@ produce `val` types. To give better type information, custom `val` types can be
12141214
registered using :cpp:func:`EMSCRIPTEN_DECLARE_VAL_TYPE` in combination with
12151215
:cpp:class:`emscripten::register_type`. An example below:
12161216

1217+
Two registration forms are supported:
1218+
1219+
* Single parameter: ``register_type<T>(definition)`` — the provided string is inlined
1220+
everywhere the type appears.
1221+
* Two parameters: ``register_type<T>(name, definition)`` — creates a named TypeScript
1222+
type alias (``type name = definition;``) and uses ``name`` at call sites.
1223+
12171224
.. code:: cpp
12181225
12191226
EMSCRIPTEN_DECLARE_VAL_TYPE(CallbackType);
@@ -1226,6 +1233,9 @@ registered using :cpp:func:`EMSCRIPTEN_DECLARE_VAL_TYPE` in combination with
12261233
EMSCRIPTEN_BINDINGS(custom_val) {
12271234
function("function_with_callback_param", &function_with_callback_param);
12281235
register_type<CallbackType>("(message: string) => void");
1236+
1237+
// Named alias form (emits: type Callback = (message: string) => void;)
1238+
// register_type<CallbackType>("Callback", "(message: string) => void");
12291239
}
12301240
12311241

src/lib/libembind.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,11 @@ var LibraryEmbind = {
568568
__embind_register_emval(rawType);
569569
},
570570

571+
_embind_register_user_type_definition__deps: ['_embind_register_emval'],
572+
_embind_register_user_type_definition: (rawType, name, definition) => {
573+
__embind_register_emval(rawType);
574+
},
575+
571576
_embind_register_optional__deps: ['$registerType', '$EmValOptionalType'],
572577
_embind_register_optional: (rawOptionalType, rawType) => {
573578
registerType(rawOptionalType, EmValOptionalType);

src/lib/libembind_gen.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,18 @@ var LibraryEmbind = {
3636
this.destructorType = 'none'; // Same as emval.
3737
}
3838
},
39+
$UserTypeDefinition: class {
40+
constructor(typeId, name, definition) {
41+
this.typeId = typeId;
42+
this.name = name;
43+
this.definition = definition;
44+
this.destructorType = 'none'; // Same as emval.
45+
}
46+
47+
print(nameMap, out) {
48+
out.push(`type ${this.name} = ${this.definition};\n\n`);
49+
}
50+
},
3951
$OptionalType: class {
4052
constructor(type) {
4153
this.type = type;
@@ -563,6 +575,14 @@ var LibraryEmbind = {
563575
name = AsciiToString(name);
564576
registerType(rawType, new UserType(rawType, name));
565577
},
578+
_embind_register_user_type_definition__deps: ['$registerType', '$AsciiToString', '$UserTypeDefinition'],
579+
_embind_register_user_type_definition: (rawType, name, definition) => {
580+
name = AsciiToString(name);
581+
definition = AsciiToString(definition);
582+
const userTypeDef = new UserTypeDefinition(rawType, name, definition);
583+
registerType(rawType, userTypeDef);
584+
moduleDefinitions.push(userTypeDef);
585+
},
566586
_embind_register_optional__deps: ['$OptionalType'],
567587
_embind_register_optional: (rawOptionalType, rawType) => {
568588
whenDependentTypesAreResolved([rawOptionalType], [rawType], function(type) {

src/lib/libsigs.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ sigs = {
307307
_embind_register_std_string__sig: 'vpp',
308308
_embind_register_std_wstring__sig: 'vppp',
309309
_embind_register_user_type__sig: 'vpp',
310+
_embind_register_user_type_definition__sig: 'vppp',
310311
_embind_register_value_array__sig: 'vpppppp',
311312
_embind_register_value_array_element__sig: 'vppppppppp',
312313
_embind_register_value_object__sig: 'vpppppp',

system/include/emscripten/bind.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,11 @@ void _embind_register_user_type(
262262
TYPEID type,
263263
const char* typeName);
264264

265+
void _embind_register_user_type_definition(
266+
TYPEID type,
267+
const char* typeName,
268+
const char* typeDefinition);
269+
265270
// Register an InitFunc in the global linked list of init functions.
266271
void _embind_register_bindings(struct InitFunc* f);
267272

@@ -2223,6 +2228,12 @@ inline void register_type(const char* name) {
22232228
_embind_register_user_type(TypeID<T>::get(), name);
22242229
}
22252230

2231+
template <typename T>
2232+
inline void register_type(const char* name, const char* definition) {
2233+
using namespace internal;
2234+
_embind_register_user_type_definition(TypeID<T>::get(), name, definition);
2235+
}
2236+
22262237
// EMSCRIPTEN_BINDINGS creates a static struct to initialize the binding which
22272238
// will get included in the program if the translation unit in which it is
22282239
// defined gets linked into the program. Using a C++ constructor here ensures it

test/other/embind_tsgen.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ struct ValObj {
6464
ValObj() : callback(val::undefined()) {}
6565
};
6666

67+
EMSCRIPTEN_DECLARE_VAL_TYPE(AliasedVal);
68+
69+
6770
ValObj getValObj() {
6871
ValObj o;
6972
return o;
@@ -104,6 +107,9 @@ int function_with_callback_param(CallbackType ct) {
104107
return 0;
105108
}
106109

110+
void function_consuming_aliased_val(AliasedVal) {
111+
}
112+
107113
int global_fn(int, int) { return 0; }
108114

109115
std::string string_test(std::string arg) {
@@ -240,7 +246,11 @@ EMSCRIPTEN_BINDINGS(Test) {
240246
function("function_with_callback_param",
241247
&function_with_callback_param);
242248

249+
function("function_consuming_aliased_val",
250+
&function_consuming_aliased_val);
251+
243252
register_type<CallbackType>("(message: string) => void");
253+
register_type<AliasedVal>("AliasedVal", "number");
244254

245255
class_<BaseClass>("BaseClass").function("fn", &BaseClass::fn);
246256

test/other/embind_tsgen.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ export interface ClassWithSmartPtrConstructor extends ClassHandle {
7373
fn(_0: number): number;
7474
}
7575

76+
type AliasedVal = number;
77+
7678
export interface BaseClass extends ClassHandle {
7779
fn(_0: number): number;
7880
}
@@ -139,6 +141,7 @@ interface EmbindModule {
139141
extend(_0: EmbindString, _1: any): any;
140142
};
141143
InterfaceWrapper: {};
144+
function_consuming_aliased_val(_0: AliasedVal): void;
142145
a_bool: boolean;
143146
an_int: number;
144147
optional_test(_0?: Foo): number | undefined;

test/other/embind_tsgen_ignore_1.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ export interface ClassWithSmartPtrConstructor extends ClassHandle {
8484
fn(_0: number): number;
8585
}
8686

87+
type AliasedVal = number;
88+
8789
export interface BaseClass extends ClassHandle {
8890
fn(_0: number): number;
8991
}
@@ -150,6 +152,7 @@ interface EmbindModule {
150152
extend(_0: EmbindString, _1: any): any;
151153
};
152154
InterfaceWrapper: {};
155+
function_consuming_aliased_val(_0: AliasedVal): void;
153156
a_bool: boolean;
154157
an_int: number;
155158
optional_test(_0?: Foo): number | undefined;

test/other/embind_tsgen_ignore_2.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ export interface ClassWithSmartPtrConstructor extends ClassHandle {
7272
fn(_0: number): number;
7373
}
7474

75+
type AliasedVal = number;
76+
7577
export interface BaseClass extends ClassHandle {
7678
fn(_0: number): number;
7779
}
@@ -138,6 +140,7 @@ interface EmbindModule {
138140
extend(_0: EmbindString, _1: any): any;
139141
};
140142
InterfaceWrapper: {};
143+
function_consuming_aliased_val(_0: AliasedVal): void;
141144
a_bool: boolean;
142145
an_int: number;
143146
optional_test(_0?: Foo): number | undefined;

test/other/embind_tsgen_ignore_3.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ export interface ClassWithSmartPtrConstructor extends ClassHandle {
7373
fn(_0: number): number;
7474
}
7575

76+
type AliasedVal = number;
77+
7678
export interface BaseClass extends ClassHandle {
7779
fn(_0: number): number;
7880
}
@@ -139,6 +141,7 @@ interface EmbindModule {
139141
extend(_0: EmbindString, _1: any): any;
140142
};
141143
InterfaceWrapper: {};
144+
function_consuming_aliased_val(_0: AliasedVal): void;
142145
a_bool: boolean;
143146
an_int: number;
144147
optional_test(_0?: Foo): number | undefined;

0 commit comments

Comments
 (0)