Rename JsObject to JsValue

Let's reserve `JsObject` for something we actually know is an object
This commit is contained in:
Alex Crichton 2018-02-06 15:04:46 -08:00
parent 9de4f1106b
commit e60aa6a990
9 changed files with 116 additions and 116 deletions

View File

@ -53,13 +53,13 @@ Let's take a look at an example.
```rust
// foo.rs
wasm_bindgen! {
pub fn foo(a: &JsObject) {
pub fn foo(a: &JsValue) {
// ...
}
}
```
Here we're using the special `JsObject` type from the `wasm-bindgen` library
Here we're using the special `JsValue` type from the `wasm-bindgen` library
itself. Our exported function, `foo`, takes a *reference* to an object. This
notably means that it can't persist the object past the lifetime of this
function call.
@ -112,14 +112,14 @@ there! Let's take a look at the code that `wasm_bindgen!` generates in Rust:
```rust
// what the user wrote
pub fn foo(a: &JsObject) {
pub fn foo(a: &JsValue) {
// ...
}
#[export_name = "foo"]
pub extern fn __wasm_bindgen_generated_foo(arg0: u32) {
let arg0 = unsafe {
ManuallyDrop::new(JsObject::__from_idx(arg0))
ManuallyDrop::new(JsValue::__from_idx(arg0))
};
let arg0 = &*arg0;
foo(arg0);
@ -132,7 +132,7 @@ And as with the JS, the notable points here are:
* A generated function here (with a unique name) is the one that's actually
exported from the wasm module
* Our generated function takes an integer argument (our index) and then wraps it
in a `JsObject`. There's some trickery here that's not worth going into just
in a `JsValue`. There's some trickery here that's not worth going into just
yet, but we'll see in a bit what's happening under the hood.
### Long-lived JS objects in a slab
@ -153,13 +153,13 @@ example.
```rust
// foo.rs
wasm_bindgen! {
pub fn foo(a: JsObject) {
pub fn foo(a: JsValue) {
// ...
}
}
```
Note that the `&` is missing in front of the `JsObject` we had before, and in
Note that the `&` is missing in front of the `JsValue` we had before, and in
Rust parlance this means it's taking ownership of the JS value. The exported ES
module interface is the same as before, but the ownership mechanics are slightly
different. Let's see the generated JS's slab in action:
@ -208,7 +208,7 @@ using `Rc`, but it's overall not too important to worry about here.
Another curious aspect of this generated module is the
`__wbindgen_object_drop_ref` function. This is one that's actually imported from
wasm rather than used in this module! This function is used to signal the end of
the lifetime of a `JsObject` in Rust, or in other words when it goes out of
the lifetime of a `JsValue` in Rust, or in other words when it goes out of
scope. Otherwise though this function is largely just a general "slab free"
implementation.
@ -216,14 +216,14 @@ And finally, let's take a look at the Rust generated again too:
```rust
// what the user wrote
pub fn foo(a: JsObject) {
pub fn foo(a: JsValue) {
// ...
}
#[export_name = "foo"]
pub extern fn __wasm_bindgen_generated_foo(arg0: u32) {
let arg0 = unsafe {
JsObject::__from_idx(arg0)
JsValue::__from_idx(arg0)
};
foo(arg0);
}
@ -232,18 +232,18 @@ pub extern fn __wasm_bindgen_generated_foo(arg0: u32) {
Ah that looks much more familiar! Not much interesting is happening here, so
let's move on to...
### Anatomy of `JsObject`
### Anatomy of `JsValue`
Currently the `JsObject` struct is actually quite simple in Rust, it's:
Currently the `JsValue` struct is actually quite simple in Rust, it's:
```rust
pub struct JsObject {
pub struct JsValue {
idx: u32,
}
// "private" constructors
impl Drop for JsObject {
impl Drop for JsValue {
fn drop(&mut self) {
unsafe {
__wbindgen_object_drop_ref(self.idx);
@ -257,7 +257,7 @@ passed from wasm. The destructor here is where the `__wbindgen_object_drop_ref`
function is called to relinquish our reference count of the JS object, freeing
up our slot in the `slab` that we saw above.
If you'll recall as well, when we took `&JsObject` above we generated a wrapper
If you'll recall as well, when we took `&JsValue` above we generated a wrapper
of `ManuallyDrop` around the local binding, and that's because we wanted to
avoid invoking this destructor when the object comes from the stack.
@ -673,7 +673,7 @@ take a look:
```rust
pub struct Bar {
obj: JsObject,
obj: JsValue,
}
impl Bar {
@ -683,7 +683,7 @@ impl Bar {
}
unsafe {
let ret = __wbg_s_Bar_new();
Bar { obj: JsObject::__from_idx(ret) }
Bar { obj: JsValue::__from_idx(ret) }
}
}
@ -711,7 +711,7 @@ impl Bar {
```
In Rust we're seeing that a new type, `Bar`, is generated for this import of a
class. The type `Bar` internally contains a `JsObject` as an instance of `Bar`
class. The type `Bar` internally contains a `JsValue` as an instance of `Bar`
is meant to represent a JS object stored in our module's stack/slab. This then
works mostly the same way that we saw JS objects work in the beginning.

View File

@ -264,16 +264,16 @@ wasm_bindgen! {
pub struct Bar {
contents: u32,
opaque: JsObject, // defined in `wasm_bindgen`, imported via prelude
opaque: JsValue, // defined in `wasm_bindgen`, imported via prelude
}
#[wasm_module = "./index"] // what ES6 module to import this functionality from
extern "JS" {
fn bar_on_reset(to: &str, opaque: &JsObject);
fn bar_on_reset(to: &str, opaque: &JsValue);
}
impl Bar {
pub fn from_str(s: &str, opaque: JsObject) -> Bar {
pub fn from_str(s: &str, opaque: JsValue) -> Bar {
Bar { contents: s.parse().unwrap_or(0), opaque }
}
@ -362,7 +362,7 @@ macro itself. Arguments allowed are:
* Owned strings (`String`)
* Owned structs (`Foo`) defined in the same bindgen macro
* Borrowed structs (`&Foo` or `&mut Bar`) defined in the same bindgen macro
* The `JsObject` type and `&JsObject` (not mutable references)
* The `JsValue` type and `&JsValue` (not mutable references)
All of the above can also be returned except borrowed references. Strings are
implemented with shim functions to copy data in/out of the Rust heap. That is, a

View File

@ -377,7 +377,7 @@ fn bindgen_imported_struct(import: &ast::ImportStruct, tokens: &mut Tokens) {
(my_quote! {
pub struct #name {
obj: ::wasm_bindgen::JsObject,
obj: ::wasm_bindgen::JsValue,
}
impl #name {
@ -385,9 +385,9 @@ fn bindgen_imported_struct(import: &ast::ImportStruct, tokens: &mut Tokens) {
}
impl ::wasm_bindgen::convert::WasmBoundary for #name {
type Js = <::wasm_bindgen::JsObject as
type Js = <::wasm_bindgen::JsValue as
::wasm_bindgen::convert::WasmBoundary>::Js;
const DESCRIPTOR: char = <::wasm_bindgen::JsObject as
const DESCRIPTOR: char = <::wasm_bindgen::JsValue as
::wasm_bindgen::convert::WasmBoundary>::DESCRIPTOR;
fn into_js(self) -> Self::Js {
@ -395,7 +395,7 @@ fn bindgen_imported_struct(import: &ast::ImportStruct, tokens: &mut Tokens) {
}
unsafe fn from_js(js: Self::Js) -> Self {
#name { obj: ::wasm_bindgen::JsObject::from_js(js) }
#name { obj: ::wasm_bindgen::JsValue::from_js(js) }
}
}
}).to_tokens(tokens);

View File

@ -1,7 +1,7 @@
use std::mem::{self, ManuallyDrop};
use std::ops::{Deref, DerefMut};
use super::JsObject;
use super::JsValue;
// keep in sync with shared/src/lib.rs TYPE constants
pub const DESCRIPTOR_CUSTOM_REF_FLAG: u32 = 0x1;
@ -92,7 +92,7 @@ impl<T> WasmBoundary for *mut T {
unsafe fn from_js(js: u32) -> *mut T { js as *mut T }
}
impl WasmBoundary for JsObject {
impl WasmBoundary for JsValue {
type Js = u32;
const DESCRIPTOR: char = DESCRIPTOR_JS_OWNED;
@ -102,21 +102,21 @@ impl WasmBoundary for JsObject {
return ret
}
unsafe fn from_js(js: u32) -> JsObject {
JsObject { idx: js }
unsafe fn from_js(js: u32) -> JsValue {
JsValue { idx: js }
}
}
impl ToRefWasmBoundary for JsObject {
impl ToRefWasmBoundary for JsValue {
fn to_js_ref(&self) -> u32 {
self.idx
}
}
impl FromRefWasmBoundary for JsObject {
type RefAnchor = ManuallyDrop<JsObject>;
impl FromRefWasmBoundary for JsValue {
type RefAnchor = ManuallyDrop<JsValue>;
unsafe fn from_js_ref(js: u32) -> ManuallyDrop<JsObject> {
ManuallyDrop::new(JsObject { idx: js })
unsafe fn from_js_ref(js: u32) -> ManuallyDrop<JsValue> {
ManuallyDrop::new(JsValue { idx: js })
}
}

View File

@ -2,7 +2,7 @@
//!
//! This crate contains the runtime support necessary for `wasm-bindgen` the
//! macro and tool. Crates pull in the `wasm_bindgen!` macro through this crate
//! and this crate also provides JS bindings through the `JsObject` interface.
//! and this crate also provides JS bindings through the `JsValue` interface.
#![feature(use_extern_macros)]
@ -17,29 +17,29 @@ use std::ptr;
/// ```
pub mod prelude {
pub use wasm_bindgen_macro::wasm_bindgen;
pub use JsObject;
pub use JsValue;
}
pub mod convert;
/// Representation of an object owned by JS.
///
/// A `JsObject` doesn't actually live in Rust right now but actually in a table
/// A `JsValue` doesn't actually live in Rust right now but actually in a table
/// owned by the `wasm-bindgen` generated JS glue code. Eventually the ownership
/// will transfer into wasm directly and this will likely become more efficient,
/// but for now it may be slightly slow.
pub struct JsObject {
pub struct JsValue {
idx: u32,
}
impl JsObject {
impl JsValue {
/// Creates a new JS value which is a string.
///
/// The utf-8 string provided is copied to the JS heap and the string will
/// be owned by the JS garbage collector.
pub fn from_str(s: &str) -> JsObject {
pub fn from_str(s: &str) -> JsValue {
unsafe {
JsObject { idx: __wbindgen_string_new(s.as_ptr(), s.len()) }
JsValue { idx: __wbindgen_string_new(s.as_ptr(), s.len()) }
}
}
@ -47,9 +47,9 @@ impl JsObject {
///
/// This function creates a JS value representing a number (a heap
/// allocated number) and returns a handle to the JS version of it.
pub fn from_f64(n: f64) -> JsObject {
pub fn from_f64(n: f64) -> JsValue {
unsafe {
JsObject { idx: __wbindgen_number_new(n) }
JsValue { idx: __wbindgen_number_new(n) }
}
}
@ -57,23 +57,23 @@ impl JsObject {
///
/// This function creates a JS object representing a boolean (a heap
/// allocated boolean) and returns a handle to the JS version of it.
pub fn from_bool(b: bool) -> JsObject {
pub fn from_bool(b: bool) -> JsValue {
unsafe {
JsObject { idx: __wbindgen_boolean_new(b as u32) }
JsValue { idx: __wbindgen_boolean_new(b as u32) }
}
}
/// Creates a new JS value representing `undefined`.
pub fn undefined() -> JsObject {
pub fn undefined() -> JsValue {
unsafe {
JsObject { idx: __wbindgen_undefined_new() }
JsValue { idx: __wbindgen_undefined_new() }
}
}
/// Creates a new JS value representing `null`.
pub fn null() -> JsObject {
pub fn null() -> JsValue {
unsafe {
JsObject { idx: __wbindgen_null_new() }
JsValue { idx: __wbindgen_null_new() }
}
}
@ -81,17 +81,17 @@ impl JsObject {
///
/// This function will invoke the `Symbol` constructor in JS and return the
/// JS object corresponding to the symbol created.
pub fn symbol(description: Option<&str>) -> JsObject {
pub fn symbol(description: Option<&str>) -> JsValue {
unsafe {
let ptr = description.map(|s| s.as_ptr()).unwrap_or(ptr::null());
let len = description.map(|s| s.len()).unwrap_or(0);
JsObject { idx: __wbindgen_symbol_new(ptr, len) }
JsValue { idx: __wbindgen_symbol_new(ptr, len) }
}
}
// #[doc(hidden)]
// pub fn __from_idx(idx: u32) -> JsObject {
// JsObject { idx }
// pub fn __from_idx(idx: u32) -> JsValue {
// JsValue { idx }
// }
//
// #[doc(hidden)]
@ -178,29 +178,29 @@ impl JsObject {
}
}
impl<'a> From<&'a str> for JsObject {
fn from(s: &'a str) -> JsObject {
JsObject::from_str(s)
impl<'a> From<&'a str> for JsValue {
fn from(s: &'a str) -> JsValue {
JsValue::from_str(s)
}
}
impl<'a> From<&'a String> for JsObject {
fn from(s: &'a String) -> JsObject {
JsObject::from_str(s)
impl<'a> From<&'a String> for JsValue {
fn from(s: &'a String) -> JsValue {
JsValue::from_str(s)
}
}
impl From<bool> for JsObject {
fn from(s: bool) -> JsObject {
JsObject::from_bool(s)
impl From<bool> for JsValue {
fn from(s: bool) -> JsValue {
JsValue::from_bool(s)
}
}
macro_rules! numbers {
($($n:ident)*) => ($(
impl From<$n> for JsObject {
fn from(n: $n) -> JsObject {
JsObject::from_f64(n.into())
impl From<$n> for JsValue {
fn from(n: $n) -> JsValue {
JsValue::from_f64(n.into())
}
}
)*)
@ -225,16 +225,16 @@ extern {
fn __wbindgen_string_get(idx: u32, len: *mut usize) -> *mut u8;
}
impl Clone for JsObject {
fn clone(&self) -> JsObject {
impl Clone for JsValue {
fn clone(&self) -> JsValue {
unsafe {
let idx = __wbindgen_object_clone_ref(self.idx);
JsObject { idx }
JsValue { idx }
}
}
}
impl Drop for JsObject {
impl Drop for JsValue {
fn drop(&mut self) {
unsafe {
__wbindgen_object_drop_ref(self.idx);

View File

@ -11,35 +11,35 @@ fn works() {
use wasm_bindgen::prelude::*;
wasm_bindgen! {
pub fn foo() -> JsObject {
JsObject::from("foo")
pub fn foo() -> JsValue {
JsValue::from("foo")
}
pub fn bar(s: &str) -> JsObject {
JsObject::from(s)
pub fn bar(s: &str) -> JsValue {
JsValue::from(s)
}
pub fn baz() -> JsObject {
JsObject::from(1.0)
pub fn baz() -> JsValue {
JsValue::from(1.0)
}
pub fn baz2(a: &JsObject, b: &JsObject) {
pub fn baz2(a: &JsValue, b: &JsValue) {
assert_eq!(a.as_f64(), Some(2.0));
assert_eq!(b.as_f64(), None);
}
pub fn js_null() -> JsObject {
JsObject::null()
pub fn js_null() -> JsValue {
JsValue::null()
}
pub fn js_undefined() -> JsObject {
JsObject::undefined()
pub fn js_undefined() -> JsValue {
JsValue::undefined()
}
pub fn test_is_null_undefined(
a: &JsObject,
b: &JsObject,
c: &JsObject,
a: &JsValue,
b: &JsValue,
c: &JsValue,
) {
assert!(a.is_null());
assert!(!a.is_undefined());
@ -51,47 +51,47 @@ fn works() {
assert!(!c.is_undefined());
}
pub fn get_true() -> JsObject {
JsObject::from(true)
pub fn get_true() -> JsValue {
JsValue::from(true)
}
pub fn get_false() -> JsObject {
JsObject::from(false)
pub fn get_false() -> JsValue {
JsValue::from(false)
}
pub fn test_bool(
a: &JsObject,
b: &JsObject,
c: &JsObject,
a: &JsValue,
b: &JsValue,
c: &JsValue,
) {
assert_eq!(a.as_bool(), Some(true));
assert_eq!(b.as_bool(), Some(false));
assert_eq!(c.as_bool(), None);
}
pub fn mk_symbol() -> JsObject {
let a = JsObject::symbol(None);
pub fn mk_symbol() -> JsValue {
let a = JsValue::symbol(None);
assert!(a.is_symbol());
return a
}
pub fn mk_symbol2(s: &str) -> JsObject {
let a = JsObject::symbol(Some(s));
pub fn mk_symbol2(s: &str) -> JsValue {
let a = JsValue::symbol(Some(s));
assert!(a.is_symbol());
return a
}
pub fn assert_symbols(a: &JsObject, b: &JsObject) {
pub fn assert_symbols(a: &JsValue, b: &JsValue) {
assert!(a.is_symbol());
assert!(!b.is_symbol());
}
pub fn acquire_string(a: &JsObject, b: &JsObject) {
pub fn acquire_string(a: &JsValue, b: &JsValue) {
assert_eq!(a.as_string().unwrap(), "foo");
assert_eq!(b.as_string(), None);
}
pub fn acquire_string2(a: &JsObject) -> String {
pub fn acquire_string2(a: &JsValue) -> String {
a.as_string().unwrap_or("wrong".to_string())
}
}

View File

@ -16,7 +16,7 @@ fn simple() {
fn foo(s: &str);
fn another(a: u32) -> i32;
fn take_and_return_bool(a: bool) -> bool;
fn return_object() -> JsObject;
fn return_object() -> JsValue;
}
pub fn bar(s: &str) {
foo(s);
@ -28,7 +28,7 @@ fn simple() {
take_and_return_bool(a)
}
pub fn get_the_object() -> JsObject {
pub fn get_the_object() -> JsValue {
return_object()
}
}

View File

@ -13,9 +13,9 @@ fn simple() {
wasm_bindgen! {
#[wasm_module = "./test"]
extern "JS" {
fn foo(s: &JsObject);
fn foo(s: &JsValue);
}
pub fn bar(s: &JsObject) {
pub fn bar(s: &JsValue) {
foo(s);
}
}
@ -54,9 +54,9 @@ fn owned() {
wasm_bindgen! {
#[wasm_module = "./test"]
extern "JS" {
fn foo(s: JsObject);
fn foo(s: JsValue);
}
pub fn bar(s: JsObject) {
pub fn bar(s: JsValue) {
foo(s);
}
}
@ -95,14 +95,14 @@ fn clone() {
wasm_bindgen! {
#[wasm_module = "./test"]
extern "JS" {
fn foo1(s: JsObject);
fn foo2(s: &JsObject);
fn foo3(s: JsObject);
fn foo4(s: &JsObject);
fn foo5(s: JsObject);
fn foo1(s: JsValue);
fn foo2(s: &JsValue);
fn foo3(s: JsValue);
fn foo4(s: &JsValue);
fn foo5(s: JsValue);
}
pub fn bar(s: JsObject) {
pub fn bar(s: JsValue) {
foo1(s.clone());
foo2(&s);
foo3(s.clone());
@ -143,13 +143,13 @@ fn promote() {
wasm_bindgen! {
#[wasm_module = "./test"]
extern "JS" {
fn foo1(s: &JsObject);
fn foo2(s: JsObject);
fn foo3(s: &JsObject);
fn foo4(s: JsObject);
fn foo1(s: &JsValue);
fn foo2(s: JsValue);
fn foo3(s: &JsValue);
fn foo4(s: JsValue);
}
pub fn bar(s: &JsObject) {
pub fn bar(s: &JsValue) {
foo1(s);
foo2(s.clone());
foo3(s);

View File

@ -19,7 +19,7 @@ fn works() {
A {}
}
}
pub fn clone(a: &JsObject) -> JsObject {
pub fn clone(a: &JsValue) -> JsValue {
drop(a.clone());
a.clone()
}