Skip to content

Commit 5f288bd

Browse files
Fix handling of JS keyword when causing invalid code gen (#4329)
1 parent c60e807 commit 5f288bd

File tree

10 files changed

+536
-52
lines changed

10 files changed

+536
-52
lines changed

CHANGELOG.md

+12
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,18 @@
1313
* Optional parameters are now typed as `T | undefined | null` to reflect the actual JS behavior.
1414
[#4188](https://github.com/rustwasm/wasm-bindgen/pull/4188)
1515

16+
### Fixed
17+
18+
- Fixed using [JavaScript keyword](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#keywords) as identifiers not being handled correctly.
19+
[#4329](https://github.com/rustwasm/wasm-bindgen/pull/4329)
20+
21+
- Using JS keywords as `struct` and `enum` names will now error at compile time, instead of causing invalid JS code gen.
22+
- Using JS keywords that are not valid to call or access properties on will now error at compile time, instead of causing invalid JS code gen if used as:
23+
1. The first part of a `js_namespace` on imports.
24+
2. The name of an imported type or constant if the type or constant does not have a `js_namespace` or `module` attribute.
25+
3. The name of an imported function if the function is not a method and does not have a `js_namespace` or `module` attribute.
26+
- Using JS keywords on imports in places other than the above will no longer cause the keywords to be escaped as `_{keyword}`.
27+
1628
--------------------------------------------------------------------------------
1729

1830
## [0.2.99](https://github.com/rustwasm/wasm-bindgen/compare/0.2.98...0.2.99)

crates/cli/tests/reference/import.js

+21
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { default as default1 } from 'tests/wasm/import_class.js';
2+
13
let wasm;
24
export function __wbg_set_wasm(val) {
35
wasm = val;
@@ -65,6 +67,20 @@ export function __wbg_catchme_f7d87ea824a61e87() { return handleError(function (
6567
catch_me();
6668
}, arguments) };
6769

70+
export function __wbg_get_56ba567010fb9959(arg0) {
71+
const ret = arg0.get();
72+
return ret;
73+
};
74+
75+
export function __wbg_myfunction_8c7b624429f78550() {
76+
b.my_function();
77+
};
78+
79+
export function __wbg_new_d21827b66c7fd25d(arg0) {
80+
const ret = new default1(arg0);
81+
return ret;
82+
};
83+
6884
export function __wbg_nocatch_be850a8dddd9599d() {
6985
no_catch();
7086
};
@@ -73,6 +89,11 @@ export function __wbg_reload_84c12f152ad689f0() {
7389
window.location.reload();
7490
};
7591

92+
export function __wbg_static_accessor_CONST_9e9d5ae758197645() {
93+
const ret = a.CONST;
94+
return ret;
95+
};
96+
7697
export function __wbg_write_c2ce0ce33a6087d5(arg0, arg1) {
7798
window.document.write(getStringFromWasm0(arg0, arg1));
7899
};

crates/cli/tests/reference/import.rs

+25-1
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,36 @@ extern "C" {
2323
fn add(a: f64, b: f64) -> f64;
2424
}
2525

26+
#[wasm_bindgen(js_namespace = ["a"])]
27+
extern "C" {
28+
// test that namespaces are overwritten and not inherited/concatenated
29+
#[wasm_bindgen(js_namespace = ["b"])]
30+
fn my_function();
31+
#[wasm_bindgen(thread_local_v2)]
32+
static CONST: f64;
33+
}
34+
35+
#[wasm_bindgen(module = "tests/wasm/import_class.js")]
36+
extern "C" {
37+
#[wasm_bindgen(js_name = default)]
38+
type RenamedTypes;
39+
#[wasm_bindgen(constructor, js_class = default)]
40+
fn new(arg: i32) -> RenamedTypes;
41+
#[wasm_bindgen(method, js_class = default)]
42+
fn get(this: &RenamedTypes) -> i32;
43+
}
44+
2645
#[wasm_bindgen]
2746
pub fn exported() -> Result<(), JsValue> {
2847
bar_from_foo();
29-
let _ = add(1.0, 2.0);
48+
let _ = add(CONST.with(Clone::clone), 2.0);
3049
reload();
3150
write("");
3251
no_catch();
52+
my_function();
53+
54+
let f = RenamedTypes::new(1);
55+
assert_eq!(f.get(), 2);
56+
3357
catch_me()
3458
}
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/* tslint:disable */
2+
/* eslint-disable */
3+
export function exported(): void;
4+
export function _function(): void;
5+
export function _var(): void;
6+
export function weird_arguments(_new: number, _var: number, _switch: number, _default: number, _arguments: number): void;

crates/cli/tests/reference/keyword.js

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
let wasm;
2+
export function __wbg_set_wasm(val) {
3+
wasm = val;
4+
}
5+
6+
7+
const lTextDecoder = typeof TextDecoder === 'undefined' ? (0, module.require)('util').TextDecoder : TextDecoder;
8+
9+
let cachedTextDecoder = new lTextDecoder('utf-8', { ignoreBOM: true, fatal: true });
10+
11+
cachedTextDecoder.decode();
12+
13+
let cachedUint8ArrayMemory0 = null;
14+
15+
function getUint8ArrayMemory0() {
16+
if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
17+
cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
18+
}
19+
return cachedUint8ArrayMemory0;
20+
}
21+
22+
function getStringFromWasm0(ptr, len) {
23+
ptr = ptr >>> 0;
24+
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
25+
}
26+
27+
export function exported() {
28+
wasm.exported();
29+
}
30+
31+
export function _function() {
32+
wasm._function();
33+
}
34+
35+
export function _var() {
36+
wasm._var();
37+
}
38+
39+
/**
40+
* @param {number} _new
41+
* @param {number} _var
42+
* @param {number} _switch
43+
* @param {number} _default
44+
* @param {number} _arguments
45+
*/
46+
export function weird_arguments(_new, _var, _switch, _default, _arguments) {
47+
wasm.weird_arguments(_new, _var, _switch, _default, _arguments);
48+
}
49+
50+
export function __wbg_await_e0a0e75be8b6fef6() {
51+
await();
52+
};
53+
54+
export function __wbg_let_8d461e9e0592bd8c(arg0) {
55+
arg0.let();
56+
};
57+
58+
export function __wbg_new_4b026aaf1c1e4438() {
59+
const ret = A.new();
60+
return ret;
61+
};
62+
63+
export function __wbg_new_d4bfd9add722b492() {
64+
const ret = window.__TAURI__.menu.Menu.new();
65+
return ret;
66+
};
67+
68+
export function __wbg_new_e17dd7c5a1cd57d8() {
69+
B.new();
70+
};
71+
72+
export function __wbg_static_accessor_TRUE_c6b68bf8545d99a3() {
73+
const ret = true;
74+
return ret;
75+
};
76+
77+
export function __wbindgen_init_externref_table() {
78+
const table = wasm.__wbindgen_export_0;
79+
const offset = table.grow(4);
80+
table.set(0, undefined);
81+
table.set(offset + 0, undefined);
82+
table.set(offset + 1, null);
83+
table.set(offset + 2, true);
84+
table.set(offset + 3, false);
85+
;
86+
};
87+
88+
export function __wbindgen_throw(arg0, arg1) {
89+
throw new Error(getStringFromWasm0(arg0, arg1));
90+
};
91+

crates/cli/tests/reference/keyword.rs

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
use wasm_bindgen::prelude::*;
2+
3+
// Imports with keywords
4+
5+
#[wasm_bindgen]
6+
extern "C" {
7+
#[wasm_bindgen]
8+
pub type A;
9+
10+
#[wasm_bindgen(static_method_of = A, js_name = "new")]
11+
pub fn static_new() -> A;
12+
#[wasm_bindgen(js_namespace = ["B"], js_name = "new")]
13+
pub fn namespace_new();
14+
15+
#[wasm_bindgen(method, js_name = "let")]
16+
pub fn keyword_let(ptr: &A);
17+
18+
// await is not a reserved keyword in JS
19+
pub fn r#await();
20+
21+
// true & false are reserved keywords in JS, but we allow them anyway
22+
#[wasm_bindgen(thread_local_v2, js_name = "true")]
23+
static TRUE: JsValue;
24+
}
25+
26+
// https://github.com/rustwasm/wasm-bindgen/issues/4317
27+
#[wasm_bindgen(js_namespace = ["window", "__TAURI__", "menu"])]
28+
extern "C" {
29+
#[wasm_bindgen]
30+
pub type Menu;
31+
32+
#[wasm_bindgen(static_method_of = Menu)]
33+
pub fn new() -> Menu;
34+
}
35+
36+
// This function ensures the imported stuff isn't optimized out
37+
#[wasm_bindgen]
38+
pub fn exported() {
39+
let a = A::static_new();
40+
let _ = a.keyword_let();
41+
let _ = namespace_new();
42+
let _ = r#await();
43+
std::hint::black_box(&TRUE);
44+
45+
let _ = Menu::new();
46+
}
47+
48+
// Exports with keywords that we allow and are renamed automatically.
49+
50+
#[wasm_bindgen]
51+
pub fn function() {}
52+
53+
#[wasm_bindgen(js_name = "var")]
54+
pub fn sane_name() {}
55+
56+
#[wasm_bindgen]
57+
pub fn weird_arguments(new: u32, var: u32, r#switch: u32, default: u32, arguments: u32) {}
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
(module $reference_test.wasm
2+
(type (;0;) (func))
3+
(type (;1;) (func (param i32 i32 i32 i32 i32)))
4+
(import "./reference_test_bg.js" "__wbindgen_init_externref_table" (func (;0;) (type 0)))
5+
(func $weird_arguments (;1;) (type 1) (param i32 i32 i32 i32 i32))
6+
(func $exported (;2;) (type 0))
7+
(func $_function (;3;) (type 0))
8+
(func $_var (;4;) (type 0))
9+
(table (;0;) 128 externref)
10+
(memory (;0;) 17)
11+
(export "memory" (memory 0))
12+
(export "exported" (func $exported))
13+
(export "_function" (func $_function))
14+
(export "_var" (func $_var))
15+
(export "weird_arguments" (func $weird_arguments))
16+
(export "__wbindgen_export_0" (table 0))
17+
(export "__wbindgen_start" (func 0))
18+
(@custom "target_features" (after code) "\04+\0amultivalue+\0fmutable-globals+\0freference-types+\08sign-ext")
19+
)
20+

0 commit comments

Comments
 (0)