Fix web-sys Location test

This commit is contained in:
Alex Crichton 2018-09-17 17:39:20 -07:00
parent e66d01f7fb
commit bbc46f92c6
2 changed files with 52 additions and 13 deletions

View File

@ -19,13 +19,48 @@ use js_sys::Object;
#[cfg(feature = "Window")]
pub fn window() -> Option<Window> {
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering::SeqCst};
use wasm_bindgen::{JsValue, JsCast};
js_sys::Function::new_no_args("return this")
// Cached `Box<JsValue>`, if we've already executed this.
//
// 0 = not calculated
// 1 = `None`
// n = Some(n) == Some(Box<JsValue>)
static WINDOW: AtomicUsize = ATOMIC_USIZE_INIT;
match WINDOW.load(SeqCst) {
0 => {}
1 => return None,
n => return unsafe { Some((*(n as *const JsValue)).clone().unchecked_into()) },
}
// Ok we don't have a cached value, let's load one! Manufacture a function
// to get access to the `this` context and see if it's an instance of
// `Window`.
//
// Note that we avoid `unwrap()` on `call0` to avoid code size bloat, we
// just handle the `Err` case as returning `None`.
let window = js_sys::Function::new_no_args("return this")
.call0(&JsValue::undefined())
.ok()?
.dyn_into::<Window>()
.ok()
.and_then(|w| w.dyn_into::<Window>().ok());
match &window {
None => WINDOW.store(1, SeqCst),
Some(window) => {
let window: &JsValue = window.as_ref();
let ptr: *mut JsValue = Box::into_raw(Box::new(window.clone()));
match WINDOW.compare_exchange(0, ptr as usize, SeqCst, SeqCst) {
// We stored out value, relinquishing ownership of `ptr`
Ok(_) => {}
// Another thread one, drop our value
Err(_) => unsafe { drop(Box::from_raw(ptr)) },
}
}
}
window
}
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));

View File

@ -1,56 +1,60 @@
use wasm_bindgen_test::*;
use web_sys::Window;
use web_sys::{self, Location};
fn location() -> Location {
web_sys::window().unwrap().location()
}
#[wasm_bindgen_test]
fn href() {
let loc = Window::location();
let loc = location();
loc.href().unwrap();
}
#[wasm_bindgen_test]
fn origin() {
let loc = Window::location();
let loc = location();
loc.origin().unwrap();
}
#[wasm_bindgen_test]
fn protocol() {
let loc = Window::location();
let loc = location();
loc.protocol().unwrap();
}
#[wasm_bindgen_test]
fn host() {
let loc = Window::location();
let loc = location();
loc.host().unwrap();
}
#[wasm_bindgen_test]
fn hostname() {
let loc = Window::location();
let loc = location();
loc.hostname().unwrap();
}
#[wasm_bindgen_test]
fn port() {
let loc = Window::location();
let loc = location();
loc.port().unwrap();
}
#[wasm_bindgen_test]
fn pathname() {
let loc = Window::location();
let loc = location();
loc.pathname().unwrap();
}
#[wasm_bindgen_test]
fn search() {
let loc = Window::location();
let loc = location();
loc.search().unwrap();
}
#[wasm_bindgen_test]
fn hash() {
let loc = Window::location();
let loc = location();
loc.hash().unwrap();
}