Skip to content

Commit d6f18ae

Browse files
authored
[embind] Generate better TS def for pointers. (#22184)
Pointers should be allowed to be null in the TS definitions. Fixes #22182
1 parent 782231d commit d6f18ae

6 files changed

+60
-23
lines changed

src/embind/embind_gen.js

+18-10
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,13 @@ var LibraryEmbind = {
4444
},
4545
$FunctionDefinition__deps: ['$createJsInvoker', '$createJsInvokerSignature', '$emittedFunctions'],
4646
$FunctionDefinition: class {
47-
constructor(name, returnType, argumentTypes, functionIndex, thisType = null, isAsync = false) {
47+
constructor(name, returnType, argumentTypes, functionIndex, thisType = null, isConstructor = false, isAsync = false) {
4848
this.name = name;
4949
this.returnType = returnType;
5050
this.argumentTypes = argumentTypes;
5151
this.functionIndex = functionIndex;
5252
this.thisType = thisType;
53+
this.isConstructor = isConstructor;
5354
this.isAsync = isAsync;
5455
}
5556

@@ -75,7 +76,14 @@ var LibraryEmbind = {
7576
}
7677

7778
out.push(argOut.join(', '));
78-
out.push(`): ${nameMap(this.returnType, true)}`);
79+
let returnType = this.returnType;
80+
// Constructors can return a pointer, but it will be a non-null pointer.
81+
// Change the return type to the class type so the TS output doesn't
82+
// have `| null`.
83+
if (this.isConstructor && this.returnType instanceof PointerDefinition) {
84+
returnType = this.returnType.classType;
85+
}
86+
out.push(`): ${nameMap(returnType, true)}`);
7987
}
8088

8189
printFunction(nameMap, out) {
@@ -183,7 +191,7 @@ var LibraryEmbind = {
183191
printModuleEntry(nameMap, out) {
184192
out.push(` ${this.name}: {`);
185193
const entries = [];
186-
for(const construct of this.constructors) {
194+
for (const construct of this.constructors) {
187195
const entry = [];
188196
entry.push('new');
189197
construct.printSignature(nameMap, entry);
@@ -368,7 +376,7 @@ var LibraryEmbind = {
368376
return tsName;
369377
}
370378
if (type instanceof PointerDefinition) {
371-
return this.typeToJsName(type.classType);
379+
return `${this.typeToJsName(type.classType)} | null`;
372380
}
373381
if (type instanceof OptionalType) {
374382
return `${this.typeToJsName(type.type)} | undefined`;
@@ -432,7 +440,7 @@ var LibraryEmbind = {
432440
registerType(id, new IntegerType(id));
433441
},
434442
$createFunctionDefinition__deps: ['$FunctionDefinition', '$heap32VectorToArray', '$readLatin1String', '$Argument', '$whenDependentTypesAreResolved', '$getFunctionName', '$getFunctionArgsName', '$PointerDefinition', '$ClassDefinition'],
435-
$createFunctionDefinition: (name, argCount, rawArgTypesAddr, functionIndex, hasThis, isAsync, cb) => {
443+
$createFunctionDefinition: (name, argCount, rawArgTypesAddr, functionIndex, hasThis, isConstructor, isAsync, cb) => {
436444
const argTypes = heap32VectorToArray(argCount, rawArgTypesAddr);
437445
name = typeof name === 'string' ? name : readLatin1String(name);
438446

@@ -462,7 +470,7 @@ var LibraryEmbind = {
462470
args.push(new Argument(`_${i - argStart}`, argTypes[i]));
463471
}
464472
}
465-
const funcDef = new FunctionDefinition(name, returnType, args, functionIndex, thisType, isAsync);
473+
const funcDef = new FunctionDefinition(name, returnType, args, functionIndex, thisType, isConstructor, isAsync);
466474
cb(funcDef);
467475
return [];
468476
});
@@ -514,7 +522,7 @@ var LibraryEmbind = {
514522
},
515523
_embind_register_function__deps: ['$moduleDefinitions', '$createFunctionDefinition'],
516524
_embind_register_function: (name, argCount, rawArgTypesAddr, signature, rawInvoker, fn, isAsync) => {
517-
createFunctionDefinition(name, argCount, rawArgTypesAddr, fn, false, isAsync, (funcDef) => {
525+
createFunctionDefinition(name, argCount, rawArgTypesAddr, fn, false, false, isAsync, (funcDef) => {
518526
moduleDefinitions.push(funcDef);
519527
});
520528
},
@@ -559,7 +567,7 @@ var LibraryEmbind = {
559567
) {
560568
whenDependentTypesAreResolved([], [rawClassType], function(classType) {
561569
classType = classType[0];
562-
createFunctionDefinition(`constructor ${classType.name}`, argCount, rawArgTypesAddr, rawConstructor, false, false, (funcDef) => {
570+
createFunctionDefinition(`constructor ${classType.name}`, argCount, rawArgTypesAddr, rawConstructor, false, true, false, (funcDef) => {
563571
classType.constructors.push(funcDef);
564572
});
565573
return [];
@@ -575,7 +583,7 @@ var LibraryEmbind = {
575583
context,
576584
isPureVirtual,
577585
isAsync) {
578-
createFunctionDefinition(methodName, argCount, rawArgTypesAddr, context, true, isAsync, (funcDef) => {
586+
createFunctionDefinition(methodName, argCount, rawArgTypesAddr, context, true, false, isAsync, (funcDef) => {
579587
const classDef = funcDef.thisType;
580588
classDef.methods.push(funcDef);
581589
});
@@ -616,7 +624,7 @@ var LibraryEmbind = {
616624
isAsync) {
617625
whenDependentTypesAreResolved([], [rawClassType], function(classType) {
618626
classType = classType[0];
619-
createFunctionDefinition(methodName, argCount, rawArgTypesAddr, fn, false, isAsync, (funcDef) => {
627+
createFunctionDefinition(methodName, argCount, rawArgTypesAddr, fn, false, false, isAsync, (funcDef) => {
620628
classType.staticMethods.push(funcDef);
621629
});
622630
return [];

test/other/embind_tsgen.cpp

+10-5
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,17 @@ class Test {
3131
int y;
3232
};
3333

34+
class Foo {
35+
public:
36+
void process(const Test& input) {}
37+
};
38+
3439
Test class_returning_fn() { return Test(); }
3540

3641
std::unique_ptr<Test> class_unique_ptr_returning_fn() {
3742
return std::make_unique<Test>();
3843
}
3944

40-
class Foo {
41-
public:
42-
void process(const Test& input) {}
43-
};
44-
4545
enum Bar { kValueOne, kValueTwo, kValueThree };
4646

4747
enum EmptyEnum {};
@@ -85,6 +85,9 @@ int smart_ptr_function(std::shared_ptr<ClassWithSmartPtrConstructor>) {
8585
return 0;
8686
}
8787

88+
struct Obj {};
89+
Obj* get_pointer(Obj* ptr) { return ptr; }
90+
8891
int function_with_callback_param(CallbackType ct) {
8992
ct(val("hello"));
9093
return 0;
@@ -140,6 +143,8 @@ EMSCRIPTEN_BINDINGS(Test) {
140143
function("class_returning_fn", &class_returning_fn);
141144
function("class_unique_ptr_returning_fn",
142145
&class_unique_ptr_returning_fn);
146+
class_<Obj>("Obj");
147+
function("getPointer", &get_pointer, allow_raw_pointers());
143148

144149
constant("an_int", 5);
145150
constant("a_bool", false);

test/other/embind_tsgen.d.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ export interface Test {
3131
delete(): void;
3232
}
3333

34+
export interface Obj {
35+
delete(): void;
36+
}
37+
3438
export interface BarValue<T extends number> {
3539
value: T;
3640
}
@@ -101,6 +105,8 @@ interface EmbindModule {
101105
Test: {staticFunction(_0: number): number; staticFunctionWithParam(x: number): number; staticProperty: number};
102106
class_returning_fn(): Test;
103107
class_unique_ptr_returning_fn(): Test;
108+
Obj: {};
109+
getPointer(_0: Obj | null): Obj | null;
104110
a_class_instance: Test;
105111
an_enum: Bar;
106112
Bar: {valueOne: BarValue<0>, valueTwo: BarValue<1>, valueThree: BarValue<2>};
@@ -119,8 +125,8 @@ interface EmbindModule {
119125
optional_test(_0?: Foo): number | undefined;
120126
global_fn(_0: number, _1: number): number;
121127
optional_and_nonoptional_test(_0: Foo | undefined, _1: number): number | undefined;
122-
smart_ptr_function(_0: ClassWithSmartPtrConstructor): number;
123-
smart_ptr_function_with_params(foo: ClassWithSmartPtrConstructor): number;
128+
smart_ptr_function(_0: ClassWithSmartPtrConstructor | null): number;
129+
smart_ptr_function_with_params(foo: ClassWithSmartPtrConstructor | null): number;
124130
function_with_callback_param(_0: (message: string) => void): number;
125131
string_test(_0: EmbindString): string;
126132
wstring_test(_0: string): string;

test/other/embind_tsgen_ignore_1.d.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ export interface Test {
4040
delete(): void;
4141
}
4242

43+
export interface Obj {
44+
delete(): void;
45+
}
46+
4347
export interface BarValue<T extends number> {
4448
value: T;
4549
}
@@ -110,6 +114,8 @@ interface EmbindModule {
110114
Test: {staticFunction(_0: number): number; staticFunctionWithParam(x: number): number; staticProperty: number};
111115
class_returning_fn(): Test;
112116
class_unique_ptr_returning_fn(): Test;
117+
Obj: {};
118+
getPointer(_0: Obj | null): Obj | null;
113119
a_class_instance: Test;
114120
an_enum: Bar;
115121
Bar: {valueOne: BarValue<0>, valueTwo: BarValue<1>, valueThree: BarValue<2>};
@@ -128,8 +134,8 @@ interface EmbindModule {
128134
optional_test(_0?: Foo): number | undefined;
129135
global_fn(_0: number, _1: number): number;
130136
optional_and_nonoptional_test(_0: Foo | undefined, _1: number): number | undefined;
131-
smart_ptr_function(_0: ClassWithSmartPtrConstructor): number;
132-
smart_ptr_function_with_params(foo: ClassWithSmartPtrConstructor): number;
137+
smart_ptr_function(_0: ClassWithSmartPtrConstructor | null): number;
138+
smart_ptr_function_with_params(foo: ClassWithSmartPtrConstructor | null): number;
133139
function_with_callback_param(_0: (message: string) => void): number;
134140
string_test(_0: EmbindString): string;
135141
wstring_test(_0: string): string;

test/other/embind_tsgen_ignore_2.d.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ export interface Test {
1717
delete(): void;
1818
}
1919

20+
export interface Obj {
21+
delete(): void;
22+
}
23+
2024
export interface BarValue<T extends number> {
2125
value: T;
2226
}
@@ -87,6 +91,8 @@ interface EmbindModule {
8791
Test: {staticFunction(_0: number): number; staticFunctionWithParam(x: number): number; staticProperty: number};
8892
class_returning_fn(): Test;
8993
class_unique_ptr_returning_fn(): Test;
94+
Obj: {};
95+
getPointer(_0: Obj | null): Obj | null;
9096
a_class_instance: Test;
9197
an_enum: Bar;
9298
Bar: {valueOne: BarValue<0>, valueTwo: BarValue<1>, valueThree: BarValue<2>};
@@ -105,8 +111,8 @@ interface EmbindModule {
105111
optional_test(_0?: Foo): number | undefined;
106112
global_fn(_0: number, _1: number): number;
107113
optional_and_nonoptional_test(_0: Foo | undefined, _1: number): number | undefined;
108-
smart_ptr_function(_0: ClassWithSmartPtrConstructor): number;
109-
smart_ptr_function_with_params(foo: ClassWithSmartPtrConstructor): number;
114+
smart_ptr_function(_0: ClassWithSmartPtrConstructor | null): number;
115+
smart_ptr_function_with_params(foo: ClassWithSmartPtrConstructor | null): number;
110116
function_with_callback_param(_0: (message: string) => void): number;
111117
string_test(_0: EmbindString): string;
112118
wstring_test(_0: string): string;

test/other/embind_tsgen_ignore_3.d.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ export interface Test {
3131
delete(): void;
3232
}
3333

34+
export interface Obj {
35+
delete(): void;
36+
}
37+
3438
export interface BarValue<T extends number> {
3539
value: T;
3640
}
@@ -101,6 +105,8 @@ interface EmbindModule {
101105
Test: {staticFunction(_0: number): number; staticFunctionWithParam(x: number): number; staticProperty: number};
102106
class_returning_fn(): Test;
103107
class_unique_ptr_returning_fn(): Test;
108+
Obj: {};
109+
getPointer(_0: Obj | null): Obj | null;
104110
a_class_instance: Test;
105111
an_enum: Bar;
106112
Bar: {valueOne: BarValue<0>, valueTwo: BarValue<1>, valueThree: BarValue<2>};
@@ -119,8 +125,8 @@ interface EmbindModule {
119125
optional_test(_0?: Foo): number | undefined;
120126
global_fn(_0: number, _1: number): number;
121127
optional_and_nonoptional_test(_0: Foo | undefined, _1: number): number | undefined;
122-
smart_ptr_function(_0: ClassWithSmartPtrConstructor): number;
123-
smart_ptr_function_with_params(foo: ClassWithSmartPtrConstructor): number;
128+
smart_ptr_function(_0: ClassWithSmartPtrConstructor | null): number;
129+
smart_ptr_function_with_params(foo: ClassWithSmartPtrConstructor | null): number;
124130
function_with_callback_param(_0: (message: string) => void): number;
125131
string_test(_0: EmbindString): string;
126132
wstring_test(_0: string): string;

0 commit comments

Comments
 (0)