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

Remove Copy/Clone from MutableHandle #559

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions mozjs/examples/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,14 @@
//! and do some setup on both of these. You also need to enter a "realm"
//! (environment within one global object) before you can execute code.

use ::std::ffi::c_char;
use ::std::ptr;
use ::std::ptr::null_mut;

use mozjs::jsapi::*;
use mozjs::jsval::ObjectValue;
use mozjs::jsval::UndefinedValue;
use mozjs::rooted;
use mozjs::rust::jsapi_wrapped::{Construct1, JS_GetProperty, JS_SetProperty};
use mozjs::rust::wrappers::{Construct1, JS_GetProperty, JS_SetProperty};
use mozjs::rust::SIMPLE_GLOBAL_CLASS;
use mozjs::rust::{IntoHandle, JSEngine, RealmOptions, Runtime};
use mozjs_sys::jsgc::ValueArray;
Expand Down Expand Up @@ -64,20 +63,20 @@ fn run(rt: Runtime) {
rt.cx(),
global.handle(),
c"WebAssembly".as_ptr(),
&mut wasm.handle_mut()
wasm.handle_mut()
));
rooted!(in(rt.cx()) let mut wasm_obj = wasm.to_object());
assert!(JS_GetProperty(
rt.cx(),
wasm_obj.handle(),
c"Module".as_ptr(),
&mut wasm_module.handle_mut()
wasm_module.handle_mut()
));
assert!(JS_GetProperty(
rt.cx(),
wasm_obj.handle(),
c"Instance".as_ptr(),
&mut wasm_instance.handle_mut()
wasm_instance.handle_mut()
));

// ptr needs to be aligned to 8
Expand All @@ -100,7 +99,7 @@ fn run(rt: Runtime) {
rt.cx(),
wasm_module.handle(),
&args,
&mut module.handle_mut()
module.handle_mut()
))
}

Expand Down Expand Up @@ -136,7 +135,7 @@ fn run(rt: Runtime) {
rt.cx(),
wasm_instance.handle(),
&HandleValueArray::from(&args),
&mut instance.handle_mut()
instance.handle_mut()
));
}

Expand All @@ -147,7 +146,7 @@ fn run(rt: Runtime) {
rt.cx(),
instance.handle(),
c"exports".as_ptr(),
&mut exports.handle_mut()
exports.handle_mut()
));

rooted!(in(rt.cx()) let mut exports_obj = exports.to_object());
Expand All @@ -156,7 +155,7 @@ fn run(rt: Runtime) {
rt.cx(),
exports_obj.handle(),
c"foo".as_ptr(),
&mut foo.handle_mut()
foo.handle_mut()
));

// call foo and get its result
Expand Down
21 changes: 20 additions & 1 deletion mozjs/src/gc/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ pub struct Handle<'a, T: 'a> {
pub(crate) ptr: &'a T,
}

#[derive(Copy, Clone)]
pub struct MutableHandle<'a, T: 'a> {
pub(crate) ptr: *mut T,
anchor: PhantomData<&'a mut T>,
Expand Down Expand Up @@ -205,6 +204,26 @@ impl<'a, T> MutableHandle<'a, T> {
unsafe { *self.ptr = v }
}

/// Creates a copy of this object, with a shorter lifetime, that holds a
/// mutable borrow on the original object. When you write code that wants
/// to use a `MutableHandle` more than once, you will typically need to
/// call `reborrow` on all but the last usage. The same way that you might
/// naively clone a type to allow it to be passed to multiple functions.
///
/// This is the same thing that happens with regular mutable references,
/// except there the compiler implicitly inserts the reborrow calls. Until
/// rust gains a feature to implicitly reborrow other types, we have to do
/// it by hand.
pub fn reborrow<'b>(&'b mut self) -> MutableHandle<'b, T>
where
'a: 'b,
{
MutableHandle {
ptr: self.ptr,
anchor: PhantomData,
}
}

pub(crate) fn raw(&mut self) -> RawMutableHandle<T> {
unsafe { RawMutableHandle::from_marked_location(self.ptr) }
}
Expand Down
160 changes: 3 additions & 157 deletions mozjs/src/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -893,9 +893,9 @@ pub unsafe fn try_to_outerize_object(mut rval: MutableHandleObject) {
}

#[inline]
pub unsafe fn maybe_wrap_object(cx: *mut JSContext, obj: MutableHandleObject) {
pub unsafe fn maybe_wrap_object(cx: *mut JSContext, mut obj: MutableHandleObject) {
if get_object_realm(*obj) != get_context_realm(cx) {
assert!(JS_WrapObject(cx, obj.into()));
assert!(JS_WrapObject(cx, obj.reborrow().into()));
}
try_to_outerize_object(obj);
}
Expand Down Expand Up @@ -1065,13 +1065,7 @@ macro_rules! capture_stack {
}
}

/** Wrappers for JSAPI methods that should NOT be used.
*
* The wrapped methods are identical except that they accept Handle and MutableHandle arguments
* that include lifetimes instead.
*
* They require MutableHandles to implement Copy. All code should migrate to jsapi_wrapped instead.
* */
/// Wrappers for JSAPI methods that ačept lifetimed Handle and MutableHandle arguments
pub mod wrappers {
macro_rules! wrap {
// The invocation of @inner has the following form:
Expand Down Expand Up @@ -1212,151 +1206,3 @@ pub mod wrappers {
include!("jsapi_wrappers.in.rs");
include!("glue_wrappers.in.rs");
}

/** Wrappers for JSAPI methods that accept lifetimed Handle and MutableHandle arguments.
*
* The wrapped methods are identical except that they accept Handle and MutableHandle arguments
* that include lifetimes instead. Besides, they mutably borrow the mutable handles
* instead of consuming/copying them.
*
* These wrappers are preferred, js::rust::wrappers should NOT be used.
* */
pub mod jsapi_wrapped {
macro_rules! wrap {
// The invocation of @inner has the following form:
// @inner (input args) <> (argument accumulator) <> (invocation accumulator) <> unparsed tokens
// when `unparsed tokens == \eps`, accumulator contains the final result

(@inner $saved:tt <> ($($declargs:tt)*) <> ($($acc:expr,)*) <> $arg:ident: Handle<$gentype:ty>, $($rest:tt)*) => {
wrap!(@inner $saved <> ($($declargs)* $arg: Handle<$gentype> , ) <> ($($acc,)* $arg.into(),) <> $($rest)*);
};
(@inner $saved:tt <> ($($declargs:tt)*) <> ($($acc:expr,)*) <> $arg:ident: MutableHandle<$gentype:ty>, $($rest:tt)*) => {
wrap!(@inner $saved <> ($($declargs)* $arg: &mut MutableHandle<$gentype> , ) <> ($($acc,)* (*$arg).into(),) <> $($rest)*);
};
(@inner $saved:tt <> ($($declargs:tt)*) <> ($($acc:expr,)*) <> $arg:ident: Handle, $($rest:tt)*) => {
wrap!(@inner $saved <> ($($declargs)* $arg: Handle , ) <> ($($acc,)* $arg.into(),) <> $($rest)*);
};
(@inner $saved:tt <> ($($declargs:tt)*) <> ($($acc:expr,)*) <> $arg:ident: MutableHandle, $($rest:tt)*) => {
wrap!(@inner $saved <> ($($declargs)* $arg: &mut MutableHandle , ) <> ($($acc,)* (*$arg).into(),) <> $($rest)*);
};
(@inner $saved:tt <> ($($declargs:tt)*) <> ($($acc:expr,)*) <> $arg:ident: HandleFunction , $($rest:tt)*) => {
wrap!(@inner $saved <> ($($declargs)* $arg: HandleFunction , ) <> ($($acc,)* $arg.into(),) <> $($rest)*);
};
(@inner $saved:tt <> ($($declargs:tt)*) <> ($($acc:expr,)*) <> $arg:ident: HandleId , $($rest:tt)*) => {
wrap!(@inner $saved <> ($($declargs)* $arg: HandleId , ) <> ($($acc,)* $arg.into(),) <> $($rest)*);
};
(@inner $saved:tt <> ($($declargs:tt)*) <> ($($acc:expr,)*) <> $arg:ident: HandleObject , $($rest:tt)*) => {
wrap!(@inner $saved <> ($($declargs)* $arg: HandleObject , ) <> ($($acc,)* $arg.into(),) <> $($rest)*);
};
(@inner $saved:tt <> ($($declargs:tt)*) <> ($($acc:expr,)*) <> $arg:ident: HandleScript , $($rest:tt)*) => {
wrap!(@inner $saved <> ($($declargs)* $arg: HandleScript , ) <> ($($acc,)* $arg.into(),) <> $($rest)*);
};
(@inner $saved:tt <> ($($declargs:tt)*) <> ($($acc:expr,)*) <> $arg:ident: HandleString , $($rest:tt)*) => {
wrap!(@inner $saved <> ($($declargs)* $arg: HandleString , ) <> ($($acc,)* $arg.into(),) <> $($rest)*);
};
(@inner $saved:tt <> ($($declargs:tt)*) <> ($($acc:expr,)*) <> $arg:ident: HandleSymbol , $($rest:tt)*) => {
wrap!(@inner $saved <> ($($declargs)* $arg: HandleSymbol , ) <> ($($acc,)* $arg.into(),) <> $($rest)*);
};
(@inner $saved:tt <> ($($declargs:tt)*) <> ($($acc:expr,)*) <> $arg:ident: HandleValue , $($rest:tt)*) => {
wrap!(@inner $saved <> ($($declargs)* $arg: HandleValue , ) <> ($($acc,)* $arg.into(),) <> $($rest)*);
};
(@inner $saved:tt <> ($($declargs:tt)*) <> ($($acc:expr,)*) <> $arg:ident: MutableHandleFunction , $($rest:tt)*) => {
wrap!(@inner $saved <> ($($declargs)* $arg: &mut MutableHandleFunction , ) <> ($($acc,)* (*$arg).into(),) <> $($rest)*);
};
(@inner $saved:tt <> ($($declargs:tt)*) <> ($($acc:expr,)*) <> $arg:ident: MutableHandleId , $($rest:tt)*) => {
wrap!(@inner $saved <> ($($declargs)* $arg: &mut MutableHandleId , ) <> ($($acc,)* (*$arg).into(),) <> $($rest)*);
};
(@inner $saved:tt <> ($($declargs:tt)*) <> ($($acc:expr,)*) <> $arg:ident: MutableHandleObject , $($rest:tt)*) => {
wrap!(@inner $saved <> ($($declargs)* $arg: &mut MutableHandleObject , ) <> ($($acc,)* (*$arg).into(),) <> $($rest)*);
};
(@inner $saved:tt <> ($($declargs:tt)*) <> ($($acc:expr,)*) <> $arg:ident: MutableHandleScript , $($rest:tt)*) => {
wrap!(@inner $saved <> ($($declargs)* $arg: &mut MutableHandleScript , ) <> ($($acc,)* (*$arg).into(),) <> $($rest)*);
};
(@inner $saved:tt <> ($($declargs:tt)*) <> ($($acc:expr,)*) <> $arg:ident: MutableHandleString , $($rest:tt)*) => {
wrap!(@inner $saved <> ($($declargs)* $arg: &mut MutableHandleString , ) <> ($($acc,)* (*$arg).into(),) <> $($rest)*);
};
(@inner $saved:tt <> ($($declargs:tt)*) <> ($($acc:expr,)*) <> $arg:ident: MutableHandleSymbol , $($rest:tt)*) => {
wrap!(@inner $saved <> ($($declargs)* $arg: &mut MutableHandleSymbol , ) <> ($($acc,)* (*$arg).into(),) <> $($rest)*);
};
(@inner $saved:tt <> ($($declargs:tt)*) <> ($($acc:expr,)*) <> $arg:ident: MutableHandleValue , $($rest:tt)*) => {
wrap!(@inner $saved <> ($($declargs)* $arg: &mut MutableHandleValue , ) <> ($($acc,)* (*$arg).into(),) <> $($rest)*);
};
(@inner $saved:tt <> ($($declargs:tt)*) <> ($($acc:expr,)*) <> $arg:ident: $type:ty, $($rest:tt)*) => {
wrap!(@inner $saved <> ($($declargs)* $arg: $type,) <> ($($acc,)* $arg,) <> $($rest)*);
};
(@inner ($module:tt: $func_name:ident ($($args:tt)*) -> $outtype:ty) <> ($($declargs:tt)*) <> ($($argexprs:expr,)*) <> ) => {
#[inline]
pub unsafe fn $func_name($($declargs)*) -> $outtype {
$module::$func_name($($argexprs),*)
}
};
($module:tt: pub fn $func_name:ident($($args:tt)*) -> $outtype:ty) => {
wrap!(@inner ($module: $func_name ($($args)*) -> $outtype) <> () <> () <> $($args)* ,);
};
($module:tt: pub fn $func_name:ident($($args:tt)*)) => {
wrap!($module: pub fn $func_name($($args)*) -> ());
}
}

use super::*;
use crate::glue;
use crate::glue::EncodedStringCallback;
use crate::jsapi;
use crate::jsapi::mozilla::Utf8Unit;
use crate::jsapi::BigInt;
use crate::jsapi::CallArgs;
use crate::jsapi::CloneDataPolicy;
use crate::jsapi::ColumnNumberOneOrigin;
use crate::jsapi::CompartmentTransplantCallback;
use crate::jsapi::ESClass;
use crate::jsapi::ExceptionStackBehavior;
use crate::jsapi::ForOfIterator;
use crate::jsapi::ForOfIterator_NonIterableBehavior;
use crate::jsapi::HandleObjectVector;
use crate::jsapi::InstantiateOptions;
use crate::jsapi::JSClass;
use crate::jsapi::JSErrorReport;
use crate::jsapi::JSExnType;
use crate::jsapi::JSFunctionSpec;
use crate::jsapi::JSFunctionSpecWithHelp;
use crate::jsapi::JSJitInfo;
use crate::jsapi::JSONParseHandler;
use crate::jsapi::JSONWriteCallback;
use crate::jsapi::JSPrincipals;
use crate::jsapi::JSPropertySpec;
use crate::jsapi::JSPropertySpec_Name;
use crate::jsapi::JSProtoKey;
use crate::jsapi::JSScript;
use crate::jsapi::JSStructuredCloneData;
use crate::jsapi::JSType;
use crate::jsapi::Latin1Char;
use crate::jsapi::ModuleErrorBehaviour;
use crate::jsapi::MutableHandleIdVector;
use crate::jsapi::PromiseState;
use crate::jsapi::PromiseUserInputEventHandlingState;
use crate::jsapi::PropertyKey;
use crate::jsapi::ReadOnlyCompileOptions;
use crate::jsapi::Realm;
use crate::jsapi::RefPtr;
use crate::jsapi::RegExpFlags;
use crate::jsapi::ScriptEnvironmentPreparer_Closure;
use crate::jsapi::SourceText;
use crate::jsapi::StackCapture;
use crate::jsapi::StructuredCloneScope;
use crate::jsapi::Symbol;
use crate::jsapi::SymbolCode;
use crate::jsapi::TaggedColumnNumberOneOrigin;
use crate::jsapi::TwoByteChars;
use crate::jsapi::UniqueChars;
use crate::jsapi::Value;
use crate::jsapi::WasmModule;
use crate::jsapi::{ElementAdder, IsArrayAnswer, PropertyDescriptor};
use crate::jsapi::{JSContext, JSFunction, JSNative, JSObject, JSString};
use crate::jsapi::{
JSStructuredCloneCallbacks, JSStructuredCloneReader, JSStructuredCloneWriter,
};
use crate::jsapi::{MallocSizeOf, ObjectOpResult, ObjectPrivateVisitor, TabSizes};
use crate::jsapi::{SavedFrameResult, SavedFrameSelfHosted};
include!("jsapi_wrappers.in.rs");
include!("glue_wrappers.in.rs");
}