Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement rustwasm/rfcs#5, implement Deref for imports and structural by default #1019

Merged
merged 10 commits into from
Nov 12, 2018
22 changes: 18 additions & 4 deletions crates/backend/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ impl ToTokens for ast::ImportType {
use wasm_bindgen::convert::RefFromWasmAbi;
use wasm_bindgen::describe::WasmDescribe;
use wasm_bindgen::{JsValue, JsCast};
use wasm_bindgen::__rt::core::mem::ManuallyDrop;
use wasm_bindgen::__rt::core;

impl WasmDescribe for #rust_name {
fn describe() {
Expand Down Expand Up @@ -589,13 +589,13 @@ impl ToTokens for ast::ImportType {

impl RefFromWasmAbi for #rust_name {
type Abi = <JsValue as RefFromWasmAbi>::Abi;
type Anchor = ManuallyDrop<#rust_name>;
type Anchor = core::mem::ManuallyDrop<#rust_name>;

#[inline]
unsafe fn ref_from_abi(js: Self::Abi, extra: &mut Stack) -> Self::Anchor {
let tmp = <JsValue as RefFromWasmAbi>::ref_from_abi(js, extra);
ManuallyDrop::new(#rust_name {
obj: ManuallyDrop::into_inner(tmp),
core::mem::ManuallyDrop::new(#rust_name {
obj: core::mem::ManuallyDrop::into_inner(tmp),
})
}
}
Expand Down Expand Up @@ -657,6 +657,20 @@ impl ToTokens for ast::ImportType {
};
}).to_tokens(tokens);

let deref_target = match self.extends.first() {
Some(target) => quote! { #target },
None => quote! { JsValue },
};
(quote! {
impl core::ops::Deref for #rust_name {
type Target = #deref_target;

#[inline]
fn deref(&self) -> &#deref_target {
self.as_ref()
}
}
}).to_tokens(tokens);
for superclass in self.extends.iter() {
(quote! {
impl From<#rust_name> for #superclass {
Expand Down
11 changes: 10 additions & 1 deletion crates/web-sys/tests/wasm/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ extern crate wasm_bindgen_futures;
extern crate wasm_bindgen_test;
extern crate web_sys;

use wasm_bindgen_test::wasm_bindgen_test_configure;
use wasm_bindgen::{JsValue, JsCast};
use wasm_bindgen_test::*;

wasm_bindgen_test_configure!(run_in_browser);

Expand Down Expand Up @@ -56,3 +57,11 @@ pub mod table_element;
pub mod title_element;
pub mod xpath_result;
pub mod indexeddb;

#[wasm_bindgen_test]
fn deref_works() {
let x = JsValue::from(3);
alexcrichton marked this conversation as resolved.
Show resolved Hide resolved
let x = x.unchecked_into::<web_sys::XmlHttpRequestUpload>();
let y: &web_sys::XmlHttpRequestEventTarget = &x;
drop(y);
}
17 changes: 12 additions & 5 deletions crates/webidl/src/first_pass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -735,11 +735,17 @@ impl<'src> FirstPass<'src, ()> for weedle::CallbackInterfaceDefinition<'src> {
impl<'a> FirstPassRecord<'a> {
pub fn all_superclasses<'me>(&'me self, interface: &str) -> impl Iterator<Item = String> + 'me {
let mut set = BTreeSet::new();
self.fill_superclasses(interface, &mut set);
set.into_iter()
let mut list = Vec::new();
self.fill_superclasses(interface, &mut set, &mut list);
list.into_iter()
}

fn fill_superclasses(&self, interface: &str, set: &mut BTreeSet<String>) {
fn fill_superclasses(
&self,
interface: &str,
set: &mut BTreeSet<&'a str>,
list: &mut Vec<String>,
) {
let data = match self.interfaces.get(interface) {
Some(data) => data,
None => return,
Expand All @@ -749,8 +755,9 @@ impl<'a> FirstPassRecord<'a> {
None => return,
};
if self.interfaces.contains_key(superclass) {
if set.insert(camel_case_ident(superclass)) {
self.fill_superclasses(superclass, set);
if set.insert(superclass) {
list.push(camel_case_ident(superclass));
self.fill_superclasses(superclass, set, list);
}
}
}
Expand Down
5 changes: 1 addition & 4 deletions examples/dom/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@ pub fn run() -> Result<(), JsValue> {
let val = document.create_element("p")?;
val.set_inner_html("Hello from Rust!");

// Right now the class inheritance hierarchy of the DOM isn't super
// ergonomic, so we manually cast `val: Element` to `&Node` to call the
// `append_child` method.
AsRef::<web_sys::Node>::as_ref(&body).append_child(val.as_ref())?;
body.append_child(&val)?;

Ok(())
}
47 changes: 21 additions & 26 deletions examples/paint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,19 @@ use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;

#[wasm_bindgen]
pub fn main() {
pub fn main() -> Result<(), JsValue> {
let document = web_sys::window().unwrap().document().unwrap();
let canvas = document
.create_element("canvas")
.unwrap()
.dyn_into::<web_sys::HtmlCanvasElement>()
.map_err(|_| ())
.unwrap();
(document.body().unwrap().as_ref() as &web_sys::Node)
.append_child(canvas.as_ref() as &web_sys::Node)
.unwrap();
.create_element("canvas")?
.dyn_into::<web_sys::HtmlCanvasElement>()?;
document.body().unwrap().append_child(&canvas)?;
canvas.set_width(640);
canvas.set_height(480);
(canvas.as_ref() as &web_sys::HtmlElement)
.style()
.set_property("border", "solid")
.unwrap();
canvas.style().set_property("border", "solid")?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh man this is sooo much nicer

let context = canvas
.get_context("2d")
.unwrap()
.get_context("2d")?
.unwrap()
.dyn_into::<web_sys::CanvasRenderingContext2d>()
.unwrap();
.dyn_into::<web_sys::CanvasRenderingContext2d>()?;
let context = Rc::new(context);
let pressed = Rc::new(Cell::new(false));
{
Expand All @@ -41,9 +31,10 @@ pub fn main() {
context.move_to(event.offset_x() as f64, event.offset_y() as f64);
pressed.set(true);
}) as Box<FnMut(_)>);
(canvas.as_ref() as &web_sys::EventTarget)
.add_event_listener_with_callback("mousedown", closure.as_ref().unchecked_ref())
.unwrap();
canvas.add_event_listener_with_callback(
"mousedown",
closure.as_ref().unchecked_ref(),
)?;
closure.forget();
}
{
Expand All @@ -57,9 +48,10 @@ pub fn main() {
context.move_to(event.offset_x() as f64, event.offset_y() as f64);
}
}) as Box<FnMut(_)>);
(canvas.as_ref() as &web_sys::EventTarget)
.add_event_listener_with_callback("mousemove", closure.as_ref().unchecked_ref())
.unwrap();
canvas.add_event_listener_with_callback(
"mousemove",
closure.as_ref().unchecked_ref(),
)?;
closure.forget();
}
{
Expand All @@ -70,9 +62,12 @@ pub fn main() {
context.line_to(event.offset_x() as f64, event.offset_y() as f64);
context.stroke();
}) as Box<FnMut(_)>);
(canvas.as_ref() as &web_sys::EventTarget)
.add_event_listener_with_callback("mouseup", closure.as_ref().unchecked_ref())
.unwrap();
canvas.add_event_listener_with_callback(
"mouseup",
closure.as_ref().unchecked_ref(),
)?;
closure.forget();
}

Ok(())
}
6 changes: 3 additions & 3 deletions examples/raytrace-parallel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ impl WorkerPool {
// thread?
// * Need to handle the `?` on `post_message` as well.
array.push(&wasm_bindgen::memory());
worker.post_message(array.as_ref())?;
worker.post_message(&array)?;
worker.set_onmessage(Some(callback.as_ref().unchecked_ref()));
worker.set_onerror(Some(callback.as_ref().unchecked_ref()));
workers.push(worker);
Expand Down Expand Up @@ -355,10 +355,10 @@ impl Shared {
self.scene.height as f64,
)?;
let arr = Array::new();
arr.push(data.as_ref());
arr.push(&data);
arr.push(&JsValue::from(done));
arr.push(&JsValue::from(self.id as f64));
global.post_message(arr.as_ref())?;
global.post_message(&arr)?;
Ok(())
}
}
38 changes: 14 additions & 24 deletions examples/webaudio/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ extern crate wasm_bindgen;
extern crate web_sys;

use wasm_bindgen::prelude::*;
use web_sys::{AudioContext, AudioNode, OscillatorType};
use web_sys::{AudioContext, OscillatorType};

/// Converts a midi note to frequency
///
Expand Down Expand Up @@ -60,34 +60,24 @@ impl FmOsc {
fm_osc.set_type(OscillatorType::Sine);
fm_osc.frequency().set_value(0.0);

// Create base class references:
{
let primary_node: &AudioNode = primary.as_ref();
let gain_node: &AudioNode = gain.as_ref();
let fm_osc_node: &AudioNode = fm_osc.as_ref();
let fm_gain_node: &AudioNode = fm_gain.as_ref();
let destination = ctx.destination();
let destination_node: &AudioNode = destination.as_ref();
// Connect the nodes up!

// Connect the nodes up!
// The primary oscillator is routed through the gain node, so that
// it can control the overall output volume.
primary.connect_with_audio_node(&gain)?;

// The primary oscillator is routed through the gain node, so that
// it can control the overall output volume.
primary_node.connect_with_audio_node(gain.as_ref())?;
// Then connect the gain node to the AudioContext destination (aka
// your speakers).
gain.connect_with_audio_node(&ctx.destination())?;

// Then connect the gain node to the AudioContext destination (aka
// your speakers).
gain_node.connect_with_audio_node(destination_node)?;
// The FM oscillator is connected to its own gain node, so it can
// control the amount of modulation.
fm_osc.connect_with_audio_node(&fm_gain)?;

// The FM oscillator is connected to its own gain node, so it can
// control the amount of modulation.
fm_osc_node.connect_with_audio_node(fm_gain.as_ref())?;


// Connect the FM oscillator to the frequency parameter of the main
// oscillator, so that the FM node can modulate its frequency.
fm_gain_node.connect_with_audio_param(&primary.frequency())?;
}
// Connect the FM oscillator to the frequency parameter of the main
// oscillator, so that the FM node can modulate its frequency.
fm_gain.connect_with_audio_param(&primary.frequency())?;

// Start the oscillators!
primary.start()?;
Expand Down
25 changes: 11 additions & 14 deletions examples/webgl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,16 @@ use web_sys::{WebGlProgram, WebGlRenderingContext, WebGlShader};
use js_sys::{WebAssembly};

#[wasm_bindgen]
pub fn draw() {
pub fn draw() -> Result<(), JsValue> {
let document = web_sys::window().unwrap().document().unwrap();
let canvas = document.get_element_by_id("canvas").unwrap();
let canvas: web_sys::HtmlCanvasElement = canvas
.dyn_into::<web_sys::HtmlCanvasElement>()
.map_err(|_| ())
.unwrap();
.dyn_into::<web_sys::HtmlCanvasElement>()?;

let context = canvas
.get_context("webgl")
.get_context("webgl")?
.unwrap()
.unwrap()
.dyn_into::<WebGlRenderingContext>()
.unwrap();
.dyn_into::<WebGlRenderingContext>()?;

let vert_shader = compile_shader(
&context,
Expand All @@ -32,7 +28,7 @@ pub fn draw() {
gl_Position = position;
}
"#,
).unwrap();
)?;
let frag_shader = compile_shader(
&context,
WebGlRenderingContext::FRAGMENT_SHADER,
Expand All @@ -41,23 +37,23 @@ pub fn draw() {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
"#,
).unwrap();
let program = link_program(&context, [vert_shader, frag_shader].iter()).unwrap();
)?;
let program = link_program(&context, [vert_shader, frag_shader].iter())?;
context.use_program(Some(&program));

let vertices: [f32; 9] = [-0.7, -0.7, 0.0, 0.7, -0.7, 0.0, 0.0, 0.7, 0.0];
let memory_buffer = wasm_bindgen::memory().dyn_into::<WebAssembly::Memory>().unwrap().buffer();
let memory_buffer = wasm_bindgen::memory().dyn_into::<WebAssembly::Memory>()?.buffer();
let vertices_location = vertices.as_ptr() as u32 / 4;
let vert_array = js_sys::Float32Array::new(&memory_buffer).subarray(
vertices_location,
vertices_location + vertices.len() as u32,
);

let buffer = context.create_buffer().unwrap();
let buffer = context.create_buffer().ok_or("failed to create buffer")?;
context.bind_buffer(WebGlRenderingContext::ARRAY_BUFFER, Some(&buffer));
context.buffer_data_with_array_buffer_view(
WebGlRenderingContext::ARRAY_BUFFER,
vert_array.as_ref(),
&vert_array,
WebGlRenderingContext::STATIC_DRAW,
);
context.vertex_attrib_pointer_with_i32(0, 3, WebGlRenderingContext::FLOAT, false, 0, 0);
Expand All @@ -71,6 +67,7 @@ pub fn draw() {
0,
(vertices.len() / 3) as i32,
);
Ok(())
}

pub fn compile_shader(
Expand Down
1 change: 1 addition & 0 deletions guide/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
- [Cargo Features](./web-sys/cargo-features.md)
- [Function Overloads](./web-sys/function-overloads.md)
- [Type Translations](./web-sys/type-translations.md)
- [Inheritance](./web-sys/inheritance.md)

--------------------------------------------------------------------------------

Expand Down
Loading