Skip to content

Commit

Permalink
embind: Support overloaded constructors for TS generation. (#20714)
Browse files Browse the repository at this point in the history
This also removes the default constructor which was producing an inaccurate
TS definition for classes, since a class binding that doesn't have `constructor<>()`
won't have a JS constructor.

Thanks to @walkingeyerobot for finding this solution.
  • Loading branch information
brendandahl authored Nov 28, 2023
1 parent cd5f6ed commit 9d830e2
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 15 deletions.
27 changes: 16 additions & 11 deletions src/embind/embind_ts.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,7 @@ var LibraryEmbind = {
this.methods = [];
this.staticMethods = [];
this.staticProperties = [];
this.constructors = [
new FunctionDefinition('default', this, [])
];
this.constructors = [];
this.base = base;
this.properties = [];
}
Expand All @@ -96,18 +94,25 @@ var LibraryEmbind = {
}

printModuleEntry(nameMap, out) {
out.push(` ${this.name}: {new`);
// TODO Handle constructor overloading
const constructor = this.constructors[this.constructors.length > 1 ? 1 : 0];
constructor.printSignature(nameMap, out);
out.push(` ${this.name}: {`);
const entries = [];
for(const construct of this.constructors) {
const entry = [];
entry.push('new');
construct.printSignature(nameMap, entry);
entries.push(entry.join(''));
}
for (const method of this.staticMethods) {
out.push('; ');
method.printFunction(nameMap, out);
const entry = [];
method.printFunction(nameMap, entry);
entries.push(entry.join(''));
}
for (const prop of this.staticProperties) {
out.push('; ');
prop.print(nameMap, out);
const entry = [];
prop.print(nameMap, entry);
entries.push(entry.join(''));
}
out.push(entries.join('; '));
out.push('};\n');
}
},
Expand Down
11 changes: 11 additions & 0 deletions test/other/embind_tsgen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ class ClassWithConstructor {
int fn(int x) { return 0; }
};

class ClassWithTwoConstructors {
public:
ClassWithTwoConstructors() {}
ClassWithTwoConstructors(int) {}
};

class ClassWithSmartPtrConstructor {
public:
ClassWithSmartPtrConstructor(int, const ValArr&) {}
Expand Down Expand Up @@ -154,6 +160,11 @@ EMSCRIPTEN_BINDINGS(Test) {
.constructor<int, const ValArr&>()
.function("fn", &ClassWithConstructor::fn);

// The last defined constructor should be used in the definition.
class_<ClassWithTwoConstructors>("ClassWithTwoConstructors")
.constructor<>()
.constructor<int>();

class_<ClassWithSmartPtrConstructor>("ClassWithSmartPtrConstructor")
.smart_ptr_constructor(
"ClassWithSmartPtrConstructor",
Expand Down
13 changes: 9 additions & 4 deletions test/other/embind_tsgen.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ export interface ClassWithConstructor {
delete(): void;
}

export interface ClassWithTwoConstructors {
delete(): void;
}

export interface ClassWithSmartPtrConstructor {
fn(_0: number): number;
delete(): void;
Expand All @@ -66,7 +70,7 @@ export interface DerivedClass extends BaseClass {
export type ValArr = [ number, number, number ];

export interface MainModule {
Test: {new(): Test; staticFunction(_0: number): number; staticFunctionWithParam(x: number): number; staticProperty: number};
Test: {staticFunction(_0: number): number; staticFunctionWithParam(x: number): number; staticProperty: number};
class_returning_fn(): Test;
class_unique_ptr_returning_fn(): Test;
a_class_instance: Test;
Expand All @@ -75,11 +79,12 @@ export interface MainModule {
EmptyEnum: {};
enum_returning_fn(): Bar;
IntVec: {new(): IntVec};
Foo: {new(): Foo};
Foo: {};
ClassWithConstructor: {new(_0: number, _1: ValArr): ClassWithConstructor};
ClassWithTwoConstructors: {new(): ClassWithTwoConstructors; new(_0: number): ClassWithTwoConstructors};
ClassWithSmartPtrConstructor: {new(_0: number, _1: ValArr): ClassWithSmartPtrConstructor};
BaseClass: {new(): BaseClass};
DerivedClass: {new(): DerivedClass};
BaseClass: {};
DerivedClass: {};
a_bool: boolean;
an_int: number;
global_fn(_0: number, _1: number): number;
Expand Down

0 comments on commit 9d830e2

Please sign in to comment.