Skip to content

Commit bfe3a91

Browse files
authored
[tsgen] Quote non-identifier enum value names in module entry. (#26814)
`enum_value_type::string` (added in #25257) accepts arbitrary JS-facing names via `.value("name", ...)`. The type union path quotes these correctly as string literals, but `printModuleEntry` emits them as bare object keys, producing invalid TypeScript when the name is not a valid JS identifier. ```cpp enum_<Foo>("Foo", enum_value_type::string).value("a-b", Foo::A); ``` Before: ```ts Foo: { a-b: 'a-b' }; // bare hyphenated key — TS parser rejects ``` After: ```ts Foo: { 'a-b': 'a-b' }; ``` The same bare-key shape exists in all three `valueType` branches of `printModuleEntry`. The convention in `object`/`number` modes is to use C++ identifiers so the bug isn't reachable there in practice, but the fix applies to all three for symmetry with `print`, which already handles non-identifier names via string-literal quoting.
1 parent 6d16622 commit bfe3a91

8 files changed

Lines changed: 27 additions & 3 deletions

src/lib/libembind_gen.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -337,15 +337,17 @@ var LibraryEmbind = {
337337
out.push(` ${this.name}: {`);
338338
const outItems = [];
339339
for (const [name, value] of this.items) {
340+
// Quote keys that aren't valid JS identifiers.
341+
const key = /^[a-zA-Z_$][\w$]*$/.test(name) ? name : `'${name}'`;
340342
switch (this.valueType) {
341343
case 'object':
342-
outItems.push(`${name}: ${this.name}Value<${value}>`);
344+
outItems.push(`${key}: ${this.name}Value<${value}>`);
343345
break;
344346
case 'number':
345-
outItems.push(`${name}: ${value}`);
347+
outItems.push(`${key}: ${value}`);
346348
break;
347349
case 'string':
348-
outItems.push(`${name}: '${name}'`);
350+
outItems.push(`${key}: '${name}'`);
349351
break;
350352
}
351353
}

test/other/embind_tsgen.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ std::unique_ptr<Test> class_unique_ptr_returning_fn() {
5858
enum FirstEnum { kValueOne, kValueTwo, kValueThree };
5959
enum SecondEnum { kValueA, kValueB, kValueC };
6060
enum ThirdEnum { kValueAlpha, kValueBeta, kValueGamma };
61+
enum HyphenatedEnum { kHyphenA, kHyphenB };
6162
enum EmptyEnum {};
6263

6364
FirstEnum enum_returning_fn() { return kValueOne; }
@@ -215,6 +216,9 @@ EMSCRIPTEN_BINDINGS(Test) {
215216
.value("kValueAlpha", ThirdEnum::kValueAlpha)
216217
.value("kValueBeta", ThirdEnum::kValueBeta)
217218
.value("kValueGamma", ThirdEnum::kValueGamma);
219+
enum_<HyphenatedEnum>("HyphenatedEnum", enum_value_type::string)
220+
.value("k-hyphen-a", HyphenatedEnum::kHyphenA)
221+
.value("k-hyphen-b", HyphenatedEnum::kHyphenB);
218222
enum_<EmptyEnum>("EmptyEnum");
219223

220224
function("enum_returning_fn", &enum_returning_fn);

test/other/embind_tsgen.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ export type SecondEnum = 0|1|2;
4040

4141
export type ThirdEnum = 'kValueAlpha'|'kValueBeta'|'kValueGamma';
4242

43+
export type HyphenatedEnum = 'k-hyphen-a'|'k-hyphen-b';
44+
4345
export interface EmptyEnumValue<T extends number> {
4446
value: T;
4547
}
@@ -129,6 +131,7 @@ interface EmbindModule {
129131
FirstEnum: {kValueOne: FirstEnumValue<0>, kValueTwo: FirstEnumValue<1>, kValueThree: FirstEnumValue<2>};
130132
SecondEnum: {kValueA: 0, kValueB: 1, kValueC: 2};
131133
ThirdEnum: {kValueAlpha: 'kValueAlpha', kValueBeta: 'kValueBeta', kValueGamma: 'kValueGamma'};
134+
HyphenatedEnum: {'k-hyphen-a': 'k-hyphen-a', 'k-hyphen-b': 'k-hyphen-b'};
132135
EmptyEnum: {};
133136
enum_returning_fn(): FirstEnum;
134137
num_enum_returning_fn(): SecondEnum;

test/other/embind_tsgen_ignore_1.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ export type SecondEnum = 0|1|2;
5151

5252
export type ThirdEnum = 'kValueAlpha'|'kValueBeta'|'kValueGamma';
5353

54+
export type HyphenatedEnum = 'k-hyphen-a'|'k-hyphen-b';
55+
5456
export interface EmptyEnumValue<T extends number> {
5557
value: T;
5658
}
@@ -140,6 +142,7 @@ interface EmbindModule {
140142
FirstEnum: {kValueOne: FirstEnumValue<0>, kValueTwo: FirstEnumValue<1>, kValueThree: FirstEnumValue<2>};
141143
SecondEnum: {kValueA: 0, kValueB: 1, kValueC: 2};
142144
ThirdEnum: {kValueAlpha: 'kValueAlpha', kValueBeta: 'kValueBeta', kValueGamma: 'kValueGamma'};
145+
HyphenatedEnum: {'k-hyphen-a': 'k-hyphen-a', 'k-hyphen-b': 'k-hyphen-b'};
143146
EmptyEnum: {};
144147
enum_returning_fn(): FirstEnum;
145148
num_enum_returning_fn(): SecondEnum;

test/other/embind_tsgen_ignore_2.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ export type SecondEnum = 0|1|2;
3939

4040
export type ThirdEnum = 'kValueAlpha'|'kValueBeta'|'kValueGamma';
4141

42+
export type HyphenatedEnum = 'k-hyphen-a'|'k-hyphen-b';
43+
4244
export interface EmptyEnumValue<T extends number> {
4345
value: T;
4446
}
@@ -128,6 +130,7 @@ interface EmbindModule {
128130
FirstEnum: {kValueOne: FirstEnumValue<0>, kValueTwo: FirstEnumValue<1>, kValueThree: FirstEnumValue<2>};
129131
SecondEnum: {kValueA: 0, kValueB: 1, kValueC: 2};
130132
ThirdEnum: {kValueAlpha: 'kValueAlpha', kValueBeta: 'kValueBeta', kValueGamma: 'kValueGamma'};
133+
HyphenatedEnum: {'k-hyphen-a': 'k-hyphen-a', 'k-hyphen-b': 'k-hyphen-b'};
131134
EmptyEnum: {};
132135
enum_returning_fn(): FirstEnum;
133136
num_enum_returning_fn(): SecondEnum;

test/other/embind_tsgen_ignore_3.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ export type SecondEnum = 0|1|2;
4040

4141
export type ThirdEnum = 'kValueAlpha'|'kValueBeta'|'kValueGamma';
4242

43+
export type HyphenatedEnum = 'k-hyphen-a'|'k-hyphen-b';
44+
4345
export interface EmptyEnumValue<T extends number> {
4446
value: T;
4547
}
@@ -129,6 +131,7 @@ interface EmbindModule {
129131
FirstEnum: {kValueOne: FirstEnumValue<0>, kValueTwo: FirstEnumValue<1>, kValueThree: FirstEnumValue<2>};
130132
SecondEnum: {kValueA: 0, kValueB: 1, kValueC: 2};
131133
ThirdEnum: {kValueAlpha: 'kValueAlpha', kValueBeta: 'kValueBeta', kValueGamma: 'kValueGamma'};
134+
HyphenatedEnum: {'k-hyphen-a': 'k-hyphen-a', 'k-hyphen-b': 'k-hyphen-b'};
132135
EmptyEnum: {};
133136
enum_returning_fn(): FirstEnum;
134137
num_enum_returning_fn(): SecondEnum;

test/other/embind_tsgen_ignore_7.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ export type SecondEnum = 0|1|2;
4040

4141
export type ThirdEnum = 'kValueAlpha'|'kValueBeta'|'kValueGamma';
4242

43+
export type HyphenatedEnum = 'k-hyphen-a'|'k-hyphen-b';
44+
4345
export interface EmptyEnumValue<T extends number> {
4446
value: T;
4547
}
@@ -129,6 +131,7 @@ interface EmbindModule {
129131
FirstEnum: {kValueOne: FirstEnumValue<0>, kValueTwo: FirstEnumValue<1>, kValueThree: FirstEnumValue<2>};
130132
SecondEnum: {kValueA: 0, kValueB: 1, kValueC: 2};
131133
ThirdEnum: {kValueAlpha: 'kValueAlpha', kValueBeta: 'kValueBeta', kValueGamma: 'kValueGamma'};
134+
HyphenatedEnum: {'k-hyphen-a': 'k-hyphen-a', 'k-hyphen-b': 'k-hyphen-b'};
132135
EmptyEnum: {};
133136
enum_returning_fn(): FirstEnum;
134137
num_enum_returning_fn(): SecondEnum;

test/other/embind_tsgen_module.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ export type SecondEnum = 0|1|2;
4040

4141
export type ThirdEnum = 'kValueAlpha'|'kValueBeta'|'kValueGamma';
4242

43+
export type HyphenatedEnum = 'k-hyphen-a'|'k-hyphen-b';
44+
4345
export interface EmptyEnumValue<T extends number> {
4446
value: T;
4547
}
@@ -129,6 +131,7 @@ interface EmbindModule {
129131
FirstEnum: {kValueOne: FirstEnumValue<0>, kValueTwo: FirstEnumValue<1>, kValueThree: FirstEnumValue<2>};
130132
SecondEnum: {kValueA: 0, kValueB: 1, kValueC: 2};
131133
ThirdEnum: {kValueAlpha: 'kValueAlpha', kValueBeta: 'kValueBeta', kValueGamma: 'kValueGamma'};
134+
HyphenatedEnum: {'k-hyphen-a': 'k-hyphen-a', 'k-hyphen-b': 'k-hyphen-b'};
132135
EmptyEnum: {};
133136
enum_returning_fn(): FirstEnum;
134137
num_enum_returning_fn(): SecondEnum;

0 commit comments

Comments
 (0)