diff --git a/crates/js-sys/src/lib.rs b/crates/js-sys/src/lib.rs index 8a78d4c8..009148c2 100644 --- a/crates/js-sys/src/lib.rs +++ b/crates/js-sys/src/lib.rs @@ -4449,7 +4449,55 @@ extern "C" { /// This allows access to the global properties and global names by accessing /// the `Object` returned. pub fn global() -> Object { - thread_local!(static GLOBAL: Object = { + thread_local!(static GLOBAL: Object = get_global_object()); + + return GLOBAL.with(|g| g.clone()); + + fn get_global_object() -> Object { + // This is a bit wonky, but we're basically using `#[wasm_bindgen]` + // attributes to synthesize imports so we can access properties of the + // form: + // + // * `globalThis.globalThis` + // * `self.self` + // * ... (etc) + // + // Accessing the global object is not an easy thing to do, and what we + // basically want is `globalThis` but we can't rely on that existing + // everywhere. In the meantime we've got the fallbacks mentioned in: + // + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis + // + // Note that this is pretty heavy code-size wise but it at least gets + // the job largely done for now and avoids the `Function` constructor at + // the end which triggers CSP errors. + #[wasm_bindgen] + extern "C" { + type Global; + + #[wasm_bindgen(getter, catch, static_method_of = Global, js_class = globalThis, js_name = globalThis)] + fn get_global_this() -> Result; + + #[wasm_bindgen(getter, catch, static_method_of = Global, js_class = self, js_name = self)] + fn get_self() -> Result; + + #[wasm_bindgen(getter, catch, static_method_of = Global, js_class = window, js_name = window)] + fn get_window() -> Result; + + #[wasm_bindgen(getter, catch, static_method_of = Global, js_class = global, js_name = global)] + fn get_global() -> Result; + } + + let static_object = Global::get_global_this() + .or_else(|_| Global::get_self()) + .or_else(|_| Global::get_window()) + .or_else(|_| Global::get_global()); + if let Ok(obj) = static_object { + if !obj.is_undefined() { + return obj; + } + } + // According to StackOverflow you can access the global object via: // // const global = Function('return this')(); @@ -4472,9 +4520,7 @@ pub fn global() -> Object { Some(this) => this.unchecked_into(), None => JsValue::undefined().unchecked_into(), } - }); - - GLOBAL.with(|g| g.clone()) + } } macro_rules! arrays { diff --git a/tests/wasm/imports.js b/tests/wasm/imports.js index f464a651..9163a6ee 100644 --- a/tests/wasm/imports.js +++ b/tests/wasm/imports.js @@ -69,7 +69,7 @@ exports.return_three = function() { return 3; }; exports.underscore = function(x) {}; -exports.self = function() { return 2; }; +exports.pub = function() { return 2; }; exports.bar = { foo: 3 }; diff --git a/tests/wasm/imports.rs b/tests/wasm/imports.rs index 5c5d35b5..eb7a5fa9 100644 --- a/tests/wasm/imports.rs +++ b/tests/wasm/imports.rs @@ -30,7 +30,7 @@ extern "C" { fn underscore(_: u8); - #[wasm_bindgen(js_name = self)] + #[wasm_bindgen(js_name = pub)] fn js_function_named_rust_keyword() -> u32; type bar;