Skip to content

Commit 0b08bba

Browse files
committed
Use static accessors if possible to get global object
Previously we always used `Function('return this')` but this triggers CSP errors since it's basically `eval`. Instead this adds a few preflight checks to look for objects like `globalThis`, `self`, etc. Currently we don't have a `#[wasm_bindgen]` function annotation to import a bare global field like `self`, but we test accesses with `self.self` and `globalThis.globalThis`, catching errors to handle any issues. Closes #1641
1 parent 16fc059 commit 0b08bba

File tree

3 files changed

+52
-6
lines changed

3 files changed

+52
-6
lines changed

crates/js-sys/src/lib.rs

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4449,7 +4449,55 @@ extern "C" {
44494449
/// This allows access to the global properties and global names by accessing
44504450
/// the `Object` returned.
44514451
pub fn global() -> Object {
4452-
thread_local!(static GLOBAL: Object = {
4452+
thread_local!(static GLOBAL: Object = get_global_object());
4453+
4454+
return GLOBAL.with(|g| g.clone());
4455+
4456+
fn get_global_object() -> Object {
4457+
// This is a bit wonky, but we're basically using `#[wasm_bindgen]`
4458+
// attributes to synthesize imports so we can access properties of the
4459+
// form:
4460+
//
4461+
// * `globalThis.globalThis`
4462+
// * `self.self`
4463+
// * ... (etc)
4464+
//
4465+
// Accessing the global object is not an easy thing to do, and what we
4466+
// basically want is `globalThis` but we can't rely on that existing
4467+
// everywhere. In the meantime we've got the fallbacks mentioned in:
4468+
//
4469+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis
4470+
//
4471+
// Note that this is pretty heavy code-size wise but it at least gets
4472+
// the job largely done for now and avoids the `Function` constructor at
4473+
// the end which triggers CSP errors.
4474+
#[wasm_bindgen]
4475+
extern "C" {
4476+
type Global;
4477+
4478+
#[wasm_bindgen(getter, catch, static_method_of = Global, js_class = globalThis, js_name = globalThis)]
4479+
fn get_global_this() -> Result<Object, JsValue>;
4480+
4481+
#[wasm_bindgen(getter, catch, static_method_of = Global, js_class = self, js_name = self)]
4482+
fn get_self() -> Result<Object, JsValue>;
4483+
4484+
#[wasm_bindgen(getter, catch, static_method_of = Global, js_class = window, js_name = window)]
4485+
fn get_window() -> Result<Object, JsValue>;
4486+
4487+
#[wasm_bindgen(getter, catch, static_method_of = Global, js_class = global, js_name = global)]
4488+
fn get_global() -> Result<Object, JsValue>;
4489+
}
4490+
4491+
let static_object = Global::get_global_this()
4492+
.or_else(|_| Global::get_self())
4493+
.or_else(|_| Global::get_window())
4494+
.or_else(|_| Global::get_global());
4495+
if let Ok(obj) = static_object {
4496+
if !obj.is_undefined() {
4497+
return obj;
4498+
}
4499+
}
4500+
44534501
// According to StackOverflow you can access the global object via:
44544502
//
44554503
// const global = Function('return this')();
@@ -4472,9 +4520,7 @@ pub fn global() -> Object {
44724520
Some(this) => this.unchecked_into(),
44734521
None => JsValue::undefined().unchecked_into(),
44744522
}
4475-
});
4476-
4477-
GLOBAL.with(|g| g.clone())
4523+
}
44784524
}
44794525

44804526
macro_rules! arrays {

tests/wasm/imports.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ exports.return_three = function() { return 3; };
6969

7070
exports.underscore = function(x) {};
7171

72-
exports.self = function() { return 2; };
72+
exports.pub = function() { return 2; };
7373

7474
exports.bar = { foo: 3 };
7575

tests/wasm/imports.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ extern "C" {
3030

3131
fn underscore(_: u8);
3232

33-
#[wasm_bindgen(js_name = self)]
33+
#[wasm_bindgen(js_name = pub)]
3434
fn js_function_named_rust_keyword() -> u32;
3535

3636
type bar;

0 commit comments

Comments
 (0)