mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
Format script component
This commit is contained in:
parent
2ca7a13473
commit
c37a345dc9
357 changed files with 25485 additions and 18076 deletions
|
@ -53,7 +53,7 @@ pub struct CallbackObject {
|
|||
///
|
||||
/// ["callback context"]: https://heycam.github.io/webidl/#dfn-callback-context
|
||||
/// [sometimes]: https://github.com/whatwg/html/issues/2248
|
||||
incumbent: Option<Dom<GlobalScope>>
|
||||
incumbent: Option<Dom<GlobalScope>>,
|
||||
}
|
||||
|
||||
impl Default for CallbackObject {
|
||||
|
@ -81,8 +81,11 @@ impl CallbackObject {
|
|||
unsafe fn init(&mut self, cx: *mut JSContext, callback: *mut JSObject) {
|
||||
self.callback.set(callback);
|
||||
self.permanent_js_root.set(ObjectValue(callback));
|
||||
assert!(AddRawValueRoot(cx, self.permanent_js_root.get_unsafe(),
|
||||
b"CallbackObject::root\n".as_c_char_ptr()));
|
||||
assert!(AddRawValueRoot(
|
||||
cx,
|
||||
self.permanent_js_root.get_unsafe(),
|
||||
b"CallbackObject::root\n".as_c_char_ptr()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,7 +97,6 @@ impl Drop for CallbackObject {
|
|||
RemoveRawValueRoot(cx, self.permanent_js_root.get_unsafe());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl PartialEq for CallbackObject {
|
||||
|
@ -103,7 +105,6 @@ impl PartialEq for CallbackObject {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// A trait to be implemented by concrete IDL callback function and
|
||||
/// callback interface types.
|
||||
pub trait CallbackContainer {
|
||||
|
@ -124,7 +125,6 @@ pub trait CallbackContainer {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// A common base class for representing IDL callback function types.
|
||||
#[derive(JSTraceable, PartialEq)]
|
||||
#[must_root]
|
||||
|
@ -153,9 +153,6 @@ impl CallbackFunction {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// A common base class for representing IDL callback interface types.
|
||||
#[derive(JSTraceable, PartialEq)]
|
||||
#[must_root]
|
||||
|
@ -194,19 +191,22 @@ impl CallbackInterface {
|
|||
}
|
||||
|
||||
if !callable.is_object() || !IsCallable(callable.to_object()) {
|
||||
return Err(Error::Type(format!("The value of the {} property is not callable",
|
||||
name)));
|
||||
return Err(Error::Type(format!(
|
||||
"The value of the {} property is not callable",
|
||||
name
|
||||
)));
|
||||
}
|
||||
}
|
||||
Ok(callable.get())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Wraps the reflector for `p` into the compartment of `cx`.
|
||||
pub fn wrap_call_this_object<T: DomObject>(cx: *mut JSContext,
|
||||
p: &T,
|
||||
mut rval: MutableHandleObject) {
|
||||
pub fn wrap_call_this_object<T: DomObject>(
|
||||
cx: *mut JSContext,
|
||||
p: &T,
|
||||
mut rval: MutableHandleObject,
|
||||
) {
|
||||
rval.set(p.reflector().get_jsobject().get());
|
||||
assert!(!rval.get().is_null());
|
||||
|
||||
|
@ -217,7 +217,6 @@ pub fn wrap_call_this_object<T: DomObject>(cx: *mut JSContext,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// A class that performs whatever setup we need to safely make a call while
|
||||
/// this class is on the stack. After `new` returns, the call is safe to make.
|
||||
pub struct CallSetup {
|
||||
|
@ -241,9 +240,7 @@ pub struct CallSetup {
|
|||
impl CallSetup {
|
||||
/// Performs the setup needed to make a call.
|
||||
#[allow(unrooted_must_root)]
|
||||
pub fn new<T: CallbackContainer>(callback: &T,
|
||||
handling: ExceptionHandling)
|
||||
-> CallSetup {
|
||||
pub fn new<T: CallbackContainer>(callback: &T, handling: ExceptionHandling) -> CallSetup {
|
||||
let global = unsafe { GlobalScope::from_object(callback.callback()) };
|
||||
let cx = global.get_cx();
|
||||
|
||||
|
@ -270,8 +267,10 @@ impl Drop for CallSetup {
|
|||
unsafe {
|
||||
JS_LeaveCompartment(self.cx, self.old_compartment);
|
||||
if self.handling == ExceptionHandling::Report {
|
||||
let _ac = JSAutoCompartment::new(self.cx,
|
||||
self.exception_global.reflector().get_jsobject().get());
|
||||
let _ac = JSAutoCompartment::new(
|
||||
self.cx,
|
||||
self.exception_global.reflector().get_jsobject().get(),
|
||||
);
|
||||
report_pending_exception(self.cx, true);
|
||||
}
|
||||
drop(self.incumbent_script.take());
|
||||
|
|
|
@ -55,7 +55,6 @@ impl<T> DomRefCell<T> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// Immutably borrows the wrapped value.
|
||||
///
|
||||
/// The borrow lasts until the returned `Ref` exits scope. Multiple
|
||||
|
@ -67,7 +66,8 @@ impl<T> DomRefCell<T> {
|
|||
///
|
||||
/// Panics if the value is currently mutably borrowed.
|
||||
pub fn borrow(&self) -> Ref<T> {
|
||||
self.try_borrow().expect("DomRefCell<T> already mutably borrowed")
|
||||
self.try_borrow()
|
||||
.expect("DomRefCell<T> already mutably borrowed")
|
||||
}
|
||||
|
||||
/// Mutably borrows the wrapped value.
|
||||
|
@ -81,7 +81,8 @@ impl<T> DomRefCell<T> {
|
|||
///
|
||||
/// Panics if the value is currently borrowed.
|
||||
pub fn borrow_mut(&self) -> RefMut<T> {
|
||||
self.try_borrow_mut().expect("DomRefCell<T> already borrowed")
|
||||
self.try_borrow_mut()
|
||||
.expect("DomRefCell<T> already borrowed")
|
||||
}
|
||||
|
||||
/// Attempts to immutably borrow the wrapped value.
|
||||
|
|
|
@ -51,16 +51,15 @@ impl ConstantSpec {
|
|||
|
||||
/// Defines constants on `obj`.
|
||||
/// Fails on JSAPI failure.
|
||||
pub unsafe fn define_constants(
|
||||
cx: *mut JSContext,
|
||||
obj: HandleObject,
|
||||
constants: &[ConstantSpec]) {
|
||||
pub unsafe fn define_constants(cx: *mut JSContext, obj: HandleObject, constants: &[ConstantSpec]) {
|
||||
for spec in constants {
|
||||
rooted!(in(cx) let value = spec.get_value());
|
||||
assert!(JS_DefineProperty(cx,
|
||||
obj,
|
||||
spec.name.as_ptr() as *const libc::c_char,
|
||||
value.handle(),
|
||||
(JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT) as u32));
|
||||
assert!(JS_DefineProperty(
|
||||
cx,
|
||||
obj,
|
||||
spec.name.as_ptr() as *const libc::c_char,
|
||||
value.handle(),
|
||||
(JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT) as u32
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,8 +69,10 @@ pub trait IDLInterface {
|
|||
}
|
||||
|
||||
/// A trait to mark an IDL interface as deriving from another one.
|
||||
#[cfg_attr(feature = "unstable",
|
||||
rustc_on_unimplemented = "The IDL interface `{Self}` is not derived from `{T}`.")]
|
||||
#[cfg_attr(
|
||||
feature = "unstable",
|
||||
rustc_on_unimplemented = "The IDL interface `{Self}` is not derived from `{T}`."
|
||||
)]
|
||||
pub trait DerivedFrom<T: Castable>: Castable {}
|
||||
|
||||
impl<T: Float + ToJSValConvertible> ToJSValConvertible for Finite<T> {
|
||||
|
@ -81,20 +83,21 @@ impl<T: Float + ToJSValConvertible> ToJSValConvertible for Finite<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Float + FromJSValConvertible<Config=()>> FromJSValConvertible for Finite<T> {
|
||||
impl<T: Float + FromJSValConvertible<Config = ()>> FromJSValConvertible for Finite<T> {
|
||||
type Config = ();
|
||||
|
||||
unsafe fn from_jsval(cx: *mut JSContext,
|
||||
value: HandleValue,
|
||||
option: ())
|
||||
-> Result<ConversionResult<Finite<T>>, ()> {
|
||||
unsafe fn from_jsval(
|
||||
cx: *mut JSContext,
|
||||
value: HandleValue,
|
||||
option: (),
|
||||
) -> Result<ConversionResult<Finite<T>>, ()> {
|
||||
let result = match FromJSValConvertible::from_jsval(cx, value, option)? {
|
||||
ConversionResult::Success(v) => v,
|
||||
ConversionResult::Failure(error) => {
|
||||
// FIXME(emilio): Why throwing instead of propagating the error?
|
||||
throw_type_error(cx, &error);
|
||||
return Err(());
|
||||
}
|
||||
},
|
||||
};
|
||||
match Finite::new(result) {
|
||||
Some(v) => Ok(ConversionResult::Success(v)),
|
||||
|
@ -106,13 +109,14 @@ impl<T: Float + FromJSValConvertible<Config=()>> FromJSValConvertible for Finite
|
|||
}
|
||||
}
|
||||
|
||||
impl <T: DomObject + IDLInterface> FromJSValConvertible for DomRoot<T> {
|
||||
impl<T: DomObject + IDLInterface> FromJSValConvertible for DomRoot<T> {
|
||||
type Config = ();
|
||||
|
||||
unsafe fn from_jsval(_cx: *mut JSContext,
|
||||
value: HandleValue,
|
||||
_config: Self::Config)
|
||||
-> Result<ConversionResult<DomRoot<T>>, ()> {
|
||||
unsafe fn from_jsval(
|
||||
_cx: *mut JSContext,
|
||||
value: HandleValue,
|
||||
_config: Self::Config,
|
||||
) -> Result<ConversionResult<DomRoot<T>>, ()> {
|
||||
Ok(match root_from_handlevalue(value) {
|
||||
Ok(result) => ConversionResult::Success(result),
|
||||
Err(()) => ConversionResult::Failure("value is not an object".into()),
|
||||
|
@ -129,19 +133,21 @@ impl<T: ToJSValConvertible + JSTraceable> ToJSValConvertible for RootedTraceable
|
|||
}
|
||||
|
||||
impl<T> FromJSValConvertible for RootedTraceableBox<Heap<T>>
|
||||
where
|
||||
T: FromJSValConvertible + js::rust::GCMethods + Copy,
|
||||
Heap<T>: JSTraceable + Default
|
||||
where
|
||||
T: FromJSValConvertible + js::rust::GCMethods + Copy,
|
||||
Heap<T>: JSTraceable + Default,
|
||||
{
|
||||
type Config = T::Config;
|
||||
|
||||
unsafe fn from_jsval(cx: *mut JSContext,
|
||||
value: HandleValue,
|
||||
config: Self::Config)
|
||||
-> Result<ConversionResult<Self>, ()> {
|
||||
unsafe fn from_jsval(
|
||||
cx: *mut JSContext,
|
||||
value: HandleValue,
|
||||
config: Self::Config,
|
||||
) -> Result<ConversionResult<Self>, ()> {
|
||||
T::from_jsval(cx, value, config).map(|result| match result {
|
||||
ConversionResult::Success(inner) =>
|
||||
ConversionResult::Success(RootedTraceableBox::from_box(Heap::boxed(inner))),
|
||||
ConversionResult::Success(inner) => {
|
||||
ConversionResult::Success(RootedTraceableBox::from_box(Heap::boxed(inner)))
|
||||
},
|
||||
ConversionResult::Failure(msg) => ConversionResult::Failure(msg),
|
||||
})
|
||||
}
|
||||
|
@ -190,12 +196,12 @@ impl ToJSValConvertible for DOMString {
|
|||
// https://heycam.github.io/webidl/#es-DOMString
|
||||
impl FromJSValConvertible for DOMString {
|
||||
type Config = StringificationBehavior;
|
||||
unsafe fn from_jsval(cx: *mut JSContext,
|
||||
value: HandleValue,
|
||||
null_behavior: StringificationBehavior)
|
||||
-> Result<ConversionResult<DOMString>, ()> {
|
||||
if null_behavior == StringificationBehavior::Empty &&
|
||||
value.get().is_null() {
|
||||
unsafe fn from_jsval(
|
||||
cx: *mut JSContext,
|
||||
value: HandleValue,
|
||||
null_behavior: StringificationBehavior,
|
||||
) -> Result<ConversionResult<DOMString>, ()> {
|
||||
if null_behavior == StringificationBehavior::Empty && value.get().is_null() {
|
||||
Ok(ConversionResult::Success(DOMString::new()))
|
||||
} else {
|
||||
let jsstr = ToString(cx, value);
|
||||
|
@ -231,16 +237,19 @@ pub unsafe fn jsstring_to_str(cx: *mut JSContext, s: *mut JSString) -> DOMString
|
|||
"Found an unpaired surrogate in a DOM string. \
|
||||
If you see this in real web content, \
|
||||
please comment on https://github.com/servo/servo/issues/6564"
|
||||
}
|
||||
};
|
||||
}
|
||||
if opts::get().replace_surrogates {
|
||||
error!(message!());
|
||||
s.push('\u{FFFD}');
|
||||
} else {
|
||||
panic!(concat!(message!(), " Use `-Z replace-surrogates` \
|
||||
on the command line to make this non-fatal."));
|
||||
panic!(concat!(
|
||||
message!(),
|
||||
" Use `-Z replace-surrogates` \
|
||||
on the command line to make this non-fatal."
|
||||
));
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
s
|
||||
|
@ -250,8 +259,11 @@ pub unsafe fn jsstring_to_str(cx: *mut JSContext, s: *mut JSString) -> DOMString
|
|||
// http://heycam.github.io/webidl/#es-USVString
|
||||
impl FromJSValConvertible for USVString {
|
||||
type Config = ();
|
||||
unsafe fn from_jsval(cx: *mut JSContext, value: HandleValue, _: ())
|
||||
-> Result<ConversionResult<USVString>, ()> {
|
||||
unsafe fn from_jsval(
|
||||
cx: *mut JSContext,
|
||||
value: HandleValue,
|
||||
_: (),
|
||||
) -> Result<ConversionResult<USVString>, ()> {
|
||||
let jsstr = ToString(cx, value);
|
||||
if jsstr.is_null() {
|
||||
debug!("ToString failed");
|
||||
|
@ -260,23 +272,28 @@ impl FromJSValConvertible for USVString {
|
|||
let latin1 = JS_StringHasLatin1Chars(jsstr);
|
||||
if latin1 {
|
||||
// FIXME(ajeffrey): Convert directly from DOMString to USVString
|
||||
return Ok(ConversionResult::Success(
|
||||
USVString(String::from(jsstring_to_str(cx, jsstr)))));
|
||||
return Ok(ConversionResult::Success(USVString(String::from(
|
||||
jsstring_to_str(cx, jsstr),
|
||||
))));
|
||||
}
|
||||
let mut length = 0;
|
||||
let chars = JS_GetTwoByteStringCharsAndLength(cx, ptr::null(), jsstr, &mut length);
|
||||
assert!(!chars.is_null());
|
||||
let char_vec = slice::from_raw_parts(chars as *const u16, length as usize);
|
||||
Ok(ConversionResult::Success(USVString(String::from_utf16_lossy(char_vec))))
|
||||
Ok(ConversionResult::Success(USVString(
|
||||
String::from_utf16_lossy(char_vec),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
// http://heycam.github.io/webidl/#es-ByteString
|
||||
impl ToJSValConvertible for ByteString {
|
||||
unsafe fn to_jsval(&self, cx: *mut JSContext, mut rval: MutableHandleValue) {
|
||||
let jsstr = JS_NewStringCopyN(cx,
|
||||
self.as_ptr() as *const libc::c_char,
|
||||
self.len() as libc::size_t);
|
||||
let jsstr = JS_NewStringCopyN(
|
||||
cx,
|
||||
self.as_ptr() as *const libc::c_char,
|
||||
self.len() as libc::size_t,
|
||||
);
|
||||
if jsstr.is_null() {
|
||||
panic!("JS_NewStringCopyN failed");
|
||||
}
|
||||
|
@ -287,10 +304,11 @@ impl ToJSValConvertible for ByteString {
|
|||
// http://heycam.github.io/webidl/#es-ByteString
|
||||
impl FromJSValConvertible for ByteString {
|
||||
type Config = ();
|
||||
unsafe fn from_jsval(cx: *mut JSContext,
|
||||
value: HandleValue,
|
||||
_option: ())
|
||||
-> Result<ConversionResult<ByteString>, ()> {
|
||||
unsafe fn from_jsval(
|
||||
cx: *mut JSContext,
|
||||
value: HandleValue,
|
||||
_option: (),
|
||||
) -> Result<ConversionResult<ByteString>, ()> {
|
||||
let string = ToString(cx, value);
|
||||
if string.is_null() {
|
||||
debug!("ToString failed");
|
||||
|
@ -304,7 +322,9 @@ impl FromJSValConvertible for ByteString {
|
|||
assert!(!chars.is_null());
|
||||
|
||||
let char_slice = slice::from_raw_parts(chars as *mut u8, length as usize);
|
||||
return Ok(ConversionResult::Success(ByteString::new(char_slice.to_vec())));
|
||||
return Ok(ConversionResult::Success(ByteString::new(
|
||||
char_slice.to_vec(),
|
||||
)));
|
||||
}
|
||||
|
||||
let mut length = 0;
|
||||
|
@ -315,13 +335,13 @@ impl FromJSValConvertible for ByteString {
|
|||
throw_type_error(cx, "Invalid ByteString");
|
||||
Err(())
|
||||
} else {
|
||||
Ok(ConversionResult::Success(
|
||||
ByteString::new(char_vec.iter().map(|&c| c as u8).collect())))
|
||||
Ok(ConversionResult::Success(ByteString::new(
|
||||
char_vec.iter().map(|&c| c as u8).collect(),
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl ToJSValConvertible for Reflector {
|
||||
unsafe fn to_jsval(&self, cx: *mut JSContext, mut rval: MutableHandleValue) {
|
||||
let obj = self.get_jsobject().get();
|
||||
|
@ -389,10 +409,12 @@ pub unsafe fn get_dom_class(obj: *mut JSObject) -> Result<&'static DOMClass, ()>
|
|||
/// not an object for a DOM object of the given type (as defined by the
|
||||
/// proto_id and proto_depth).
|
||||
#[inline]
|
||||
pub unsafe fn private_from_proto_check<F>(mut obj: *mut JSObject,
|
||||
proto_check: F)
|
||||
-> Result<*const libc::c_void, ()>
|
||||
where F: Fn(&'static DOMClass) -> bool
|
||||
pub unsafe fn private_from_proto_check<F>(
|
||||
mut obj: *mut JSObject,
|
||||
proto_check: F,
|
||||
) -> Result<*const libc::c_void, ()>
|
||||
where
|
||||
F: Fn(&'static DOMClass) -> bool,
|
||||
{
|
||||
let dom_class = get_dom_class(obj).or_else(|_| {
|
||||
if IsWrapper(obj) {
|
||||
|
@ -423,11 +445,10 @@ pub unsafe fn private_from_proto_check<F>(mut obj: *mut JSObject,
|
|||
|
||||
/// Get a `*const T` for a DOM object accessible from a `JSObject`.
|
||||
pub fn native_from_object<T>(obj: *mut JSObject) -> Result<*const T, ()>
|
||||
where T: DomObject + IDLInterface
|
||||
where
|
||||
T: DomObject + IDLInterface,
|
||||
{
|
||||
unsafe {
|
||||
private_from_proto_check(obj, T::derives).map(|ptr| ptr as *const T)
|
||||
}
|
||||
unsafe { private_from_proto_check(obj, T::derives).map(|ptr| ptr as *const T) }
|
||||
}
|
||||
|
||||
/// Get a `DomRoot<T>` for the given DOM object, unwrapping any wrapper
|
||||
|
@ -437,7 +458,8 @@ pub fn native_from_object<T>(obj: *mut JSObject) -> Result<*const T, ()>
|
|||
/// not a reflector for a DOM object of the given type (as defined by the
|
||||
/// proto_id and proto_depth).
|
||||
pub fn root_from_object<T>(obj: *mut JSObject) -> Result<DomRoot<T>, ()>
|
||||
where T: DomObject + IDLInterface
|
||||
where
|
||||
T: DomObject + IDLInterface,
|
||||
{
|
||||
native_from_object(obj).map(|ptr| unsafe { DomRoot::from_ref(&*ptr) })
|
||||
}
|
||||
|
@ -445,7 +467,8 @@ pub fn root_from_object<T>(obj: *mut JSObject) -> Result<DomRoot<T>, ()>
|
|||
/// Get a `*const T` for a DOM object accessible from a `HandleValue`.
|
||||
/// Caller is responsible for throwing a JS exception if needed in case of error.
|
||||
pub fn native_from_handlevalue<T>(v: HandleValue) -> Result<*const T, ()>
|
||||
where T: DomObject + IDLInterface
|
||||
where
|
||||
T: DomObject + IDLInterface,
|
||||
{
|
||||
if !v.get().is_object() {
|
||||
return Err(());
|
||||
|
@ -456,7 +479,8 @@ pub fn native_from_handlevalue<T>(v: HandleValue) -> Result<*const T, ()>
|
|||
/// Get a `DomRoot<T>` for a DOM object accessible from a `HandleValue`.
|
||||
/// Caller is responsible for throwing a JS exception if needed in case of error.
|
||||
pub fn root_from_handlevalue<T>(v: HandleValue) -> Result<DomRoot<T>, ()>
|
||||
where T: DomObject + IDLInterface
|
||||
where
|
||||
T: DomObject + IDLInterface,
|
||||
{
|
||||
if !v.get().is_object() {
|
||||
return Err(());
|
||||
|
@ -466,7 +490,8 @@ pub fn root_from_handlevalue<T>(v: HandleValue) -> Result<DomRoot<T>, ()>
|
|||
|
||||
/// Get a `DomRoot<T>` for a DOM object accessible from a `HandleObject`.
|
||||
pub fn root_from_handleobject<T>(obj: HandleObject) -> Result<DomRoot<T>, ()>
|
||||
where T: DomObject + IDLInterface
|
||||
where
|
||||
T: DomObject + IDLInterface,
|
||||
{
|
||||
root_from_object(obj.get())
|
||||
}
|
||||
|
@ -487,12 +512,12 @@ pub unsafe fn is_array_like(cx: *mut JSContext, value: HandleValue) -> bool {
|
|||
}
|
||||
|
||||
/// Get a property from a JS object.
|
||||
pub unsafe fn get_property_jsval(cx: *mut JSContext,
|
||||
object: HandleObject,
|
||||
name: &str,
|
||||
mut rval: MutableHandleValue)
|
||||
-> Fallible<()>
|
||||
{
|
||||
pub unsafe fn get_property_jsval(
|
||||
cx: *mut JSContext,
|
||||
object: HandleObject,
|
||||
name: &str,
|
||||
mut rval: MutableHandleValue,
|
||||
) -> Fallible<()> {
|
||||
rval.set(UndefinedValue());
|
||||
let cname = match ffi::CString::new(name) {
|
||||
Ok(cname) => cname,
|
||||
|
@ -506,12 +531,14 @@ pub unsafe fn get_property_jsval(cx: *mut JSContext,
|
|||
}
|
||||
|
||||
/// Get a property from a JS object, and convert it to a Rust value.
|
||||
pub unsafe fn get_property<T>(cx: *mut JSContext,
|
||||
object: HandleObject,
|
||||
name: &str,
|
||||
option: T::Config)
|
||||
-> Fallible<Option<T>> where
|
||||
T: FromJSValConvertible
|
||||
pub unsafe fn get_property<T>(
|
||||
cx: *mut JSContext,
|
||||
object: HandleObject,
|
||||
name: &str,
|
||||
option: T::Config,
|
||||
) -> Fallible<Option<T>>
|
||||
where
|
||||
T: FromJSValConvertible,
|
||||
{
|
||||
debug!("Getting property {}.", name);
|
||||
rooted!(in(cx) let mut result = UndefinedValue());
|
||||
|
|
|
@ -126,7 +126,7 @@ pub unsafe fn throw_dom_exception(cx: *mut JSContext, global: &GlobalScope, resu
|
|||
Error::JSFailed => {
|
||||
assert!(JS_IsExceptionPending(cx));
|
||||
return;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
assert!(!JS_IsExceptionPending(cx));
|
||||
|
@ -149,8 +149,7 @@ pub struct ErrorInfo {
|
|||
}
|
||||
|
||||
impl ErrorInfo {
|
||||
unsafe fn from_native_error(cx: *mut JSContext, object: HandleObject)
|
||||
-> Option<ErrorInfo> {
|
||||
unsafe fn from_native_error(cx: *mut JSContext, object: HandleObject) -> Option<ErrorInfo> {
|
||||
let report = JS_ErrorFromException(cx, object);
|
||||
if report.is_null() {
|
||||
return None;
|
||||
|
@ -205,7 +204,9 @@ impl ErrorInfo {
|
|||
/// The `dispatch_event` argument is temporary and non-standard; passing false
|
||||
/// prevents dispatching the `error` event.
|
||||
pub unsafe fn report_pending_exception(cx: *mut JSContext, dispatch_event: bool) {
|
||||
if !JS_IsExceptionPending(cx) { return; }
|
||||
if !JS_IsExceptionPending(cx) {
|
||||
return;
|
||||
}
|
||||
|
||||
rooted!(in(cx) let mut value = UndefinedValue());
|
||||
if !JS_GetPendingException(cx, value.handle_mut()) {
|
||||
|
@ -219,23 +220,19 @@ pub unsafe fn report_pending_exception(cx: *mut JSContext, dispatch_event: bool)
|
|||
rooted!(in(cx) let object = value.to_object());
|
||||
ErrorInfo::from_native_error(cx, object.handle())
|
||||
.or_else(|| ErrorInfo::from_dom_exception(object.handle()))
|
||||
.unwrap_or_else(|| {
|
||||
ErrorInfo {
|
||||
message: format!("uncaught exception: unknown (can't convert to string)"),
|
||||
filename: String::new(),
|
||||
lineno: 0,
|
||||
column: 0,
|
||||
}
|
||||
.unwrap_or_else(|| ErrorInfo {
|
||||
message: format!("uncaught exception: unknown (can't convert to string)"),
|
||||
filename: String::new(),
|
||||
lineno: 0,
|
||||
column: 0,
|
||||
})
|
||||
} else {
|
||||
match USVString::from_jsval(cx, value.handle(), ()) {
|
||||
Ok(ConversionResult::Success(USVString(string))) => {
|
||||
ErrorInfo {
|
||||
message: format!("uncaught exception: {}", string),
|
||||
filename: String::new(),
|
||||
lineno: 0,
|
||||
column: 0,
|
||||
}
|
||||
Ok(ConversionResult::Success(USVString(string))) => ErrorInfo {
|
||||
message: format!("uncaught exception: {}", string),
|
||||
filename: String::new(),
|
||||
lineno: 0,
|
||||
column: 0,
|
||||
},
|
||||
_ => {
|
||||
panic!("Uncaught exception: failed to stringify primitive");
|
||||
|
@ -243,15 +240,13 @@ pub unsafe fn report_pending_exception(cx: *mut JSContext, dispatch_event: bool)
|
|||
}
|
||||
};
|
||||
|
||||
error!("Error at {}:{}:{} {}",
|
||||
error_info.filename,
|
||||
error_info.lineno,
|
||||
error_info.column,
|
||||
error_info.message);
|
||||
error!(
|
||||
"Error at {}:{}:{} {}",
|
||||
error_info.filename, error_info.lineno, error_info.column, error_info.message
|
||||
);
|
||||
|
||||
if dispatch_event {
|
||||
GlobalScope::from_context(cx)
|
||||
.report_an_error(error_info, value.handle());
|
||||
GlobalScope::from_context(cx).report_an_error(error_info, value.handle());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -259,14 +254,21 @@ pub unsafe fn report_pending_exception(cx: *mut JSContext, dispatch_event: bool)
|
|||
/// given DOM type.
|
||||
pub unsafe fn throw_invalid_this(cx: *mut JSContext, proto_id: u16) {
|
||||
debug_assert!(!JS_IsExceptionPending(cx));
|
||||
let error = format!("\"this\" object does not implement interface {}.",
|
||||
proto_id_to_name(proto_id));
|
||||
let error = format!(
|
||||
"\"this\" object does not implement interface {}.",
|
||||
proto_id_to_name(proto_id)
|
||||
);
|
||||
throw_type_error(cx, &error);
|
||||
}
|
||||
|
||||
impl Error {
|
||||
/// Convert this error value to a JS value, consuming it in the process.
|
||||
pub unsafe fn to_jsval(self, cx: *mut JSContext, global: &GlobalScope, rval: MutableHandleValue) {
|
||||
pub unsafe fn to_jsval(
|
||||
self,
|
||||
cx: *mut JSContext,
|
||||
global: &GlobalScope,
|
||||
rval: MutableHandleValue,
|
||||
) {
|
||||
assert!(!JS_IsExceptionPending(cx));
|
||||
throw_dom_exception(cx, global, self);
|
||||
assert!(JS_IsExceptionPending(cx));
|
||||
|
|
|
@ -89,7 +89,9 @@ use std::ptr;
|
|||
|
||||
// https://html.spec.whatwg.org/multipage/#htmlconstructor
|
||||
pub unsafe fn html_constructor<T>(window: &Window, call_args: &CallArgs) -> Fallible<DomRoot<T>>
|
||||
where T: DerivedFrom<Element> {
|
||||
where
|
||||
T: DerivedFrom<Element>,
|
||||
{
|
||||
let document = window.Document();
|
||||
|
||||
// Step 1
|
||||
|
@ -101,7 +103,11 @@ pub unsafe fn html_constructor<T>(window: &Window, call_args: &CallArgs) -> Fall
|
|||
rooted!(in(window.get_cx()) let new_target = call_args.new_target().to_object());
|
||||
let definition = match registry.lookup_definition_by_constructor(new_target.handle()) {
|
||||
Some(definition) => definition,
|
||||
None => return Err(Error::Type("No custom element definition found for new.target".to_owned())),
|
||||
None => {
|
||||
return Err(Error::Type(
|
||||
"No custom element definition found for new.target".to_owned(),
|
||||
))
|
||||
},
|
||||
};
|
||||
|
||||
rooted!(in(window.get_cx()) let callee = UnwrapObject(call_args.callee(), 1));
|
||||
|
@ -119,18 +125,25 @@ pub unsafe fn html_constructor<T>(window: &Window, call_args: &CallArgs) -> Fall
|
|||
// Since this element is autonomous, its active function object must be the HTMLElement
|
||||
|
||||
// Retrieve the constructor object for HTMLElement
|
||||
HTMLElementBinding::GetConstructorObject(window.get_cx(), global_object.handle(), constructor.handle_mut());
|
||||
|
||||
HTMLElementBinding::GetConstructorObject(
|
||||
window.get_cx(),
|
||||
global_object.handle(),
|
||||
constructor.handle_mut(),
|
||||
);
|
||||
} else {
|
||||
// Step 5
|
||||
get_constructor_object_from_local_name(definition.local_name.clone(),
|
||||
window.get_cx(),
|
||||
global_object.handle(),
|
||||
constructor.handle_mut());
|
||||
get_constructor_object_from_local_name(
|
||||
definition.local_name.clone(),
|
||||
window.get_cx(),
|
||||
global_object.handle(),
|
||||
constructor.handle_mut(),
|
||||
);
|
||||
}
|
||||
// Callee must be the same as the element interface's constructor object.
|
||||
if constructor.get() != callee.get() {
|
||||
return Err(Error::Type("Custom element does not extend the proper interface".to_owned()));
|
||||
return Err(Error::Type(
|
||||
"Custom element does not extend the proper interface".to_owned(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,11 +189,12 @@ pub unsafe fn html_constructor<T>(window: &Window, call_args: &CallArgs) -> Fall
|
|||
|
||||
/// Returns the constructor object for the element associated with the given local name.
|
||||
/// This list should only include elements marked with the [HTMLConstructor] extended attribute.
|
||||
pub fn get_constructor_object_from_local_name(name: LocalName,
|
||||
cx: *mut JSContext,
|
||||
global: HandleObject,
|
||||
rval: MutableHandleObject)
|
||||
-> bool {
|
||||
pub fn get_constructor_object_from_local_name(
|
||||
name: LocalName,
|
||||
cx: *mut JSContext,
|
||||
global: HandleObject,
|
||||
rval: MutableHandleObject,
|
||||
) -> bool {
|
||||
macro_rules! get_constructor(
|
||||
($binding:ident) => ({
|
||||
unsafe { $binding::GetConstructorObject(cx, global, rval); }
|
||||
|
@ -189,131 +203,131 @@ pub fn get_constructor_object_from_local_name(name: LocalName,
|
|||
);
|
||||
|
||||
match name {
|
||||
local_name!("a") => get_constructor!(HTMLAnchorElementBinding),
|
||||
local_name!("abbr") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("acronym") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("address") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("area") => get_constructor!(HTMLAreaElementBinding),
|
||||
local_name!("article") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("aside") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("audio") => get_constructor!(HTMLAudioElementBinding),
|
||||
local_name!("b") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("base") => get_constructor!(HTMLBaseElementBinding),
|
||||
local_name!("bdi") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("bdo") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("big") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("a") => get_constructor!(HTMLAnchorElementBinding),
|
||||
local_name!("abbr") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("acronym") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("address") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("area") => get_constructor!(HTMLAreaElementBinding),
|
||||
local_name!("article") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("aside") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("audio") => get_constructor!(HTMLAudioElementBinding),
|
||||
local_name!("b") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("base") => get_constructor!(HTMLBaseElementBinding),
|
||||
local_name!("bdi") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("bdo") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("big") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("blockquote") => get_constructor!(HTMLQuoteElementBinding),
|
||||
local_name!("body") => get_constructor!(HTMLBodyElementBinding),
|
||||
local_name!("br") => get_constructor!(HTMLBRElementBinding),
|
||||
local_name!("button") => get_constructor!(HTMLButtonElementBinding),
|
||||
local_name!("canvas") => get_constructor!(HTMLCanvasElementBinding),
|
||||
local_name!("caption") => get_constructor!(HTMLTableCaptionElementBinding),
|
||||
local_name!("center") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("cite") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("code") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("col") => get_constructor!(HTMLTableColElementBinding),
|
||||
local_name!("colgroup") => get_constructor!(HTMLTableColElementBinding),
|
||||
local_name!("data") => get_constructor!(HTMLDataElementBinding),
|
||||
local_name!("datalist") => get_constructor!(HTMLDataListElementBinding),
|
||||
local_name!("dd") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("del") => get_constructor!(HTMLModElementBinding),
|
||||
local_name!("details") => get_constructor!(HTMLDetailsElementBinding),
|
||||
local_name!("dfn") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("dialog") => get_constructor!(HTMLDialogElementBinding),
|
||||
local_name!("dir") => get_constructor!(HTMLDirectoryElementBinding),
|
||||
local_name!("div") => get_constructor!(HTMLDivElementBinding),
|
||||
local_name!("dl") => get_constructor!(HTMLDListElementBinding),
|
||||
local_name!("dt") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("em") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("embed") => get_constructor!(HTMLEmbedElementBinding),
|
||||
local_name!("fieldset") => get_constructor!(HTMLFieldSetElementBinding),
|
||||
local_name!("body") => get_constructor!(HTMLBodyElementBinding),
|
||||
local_name!("br") => get_constructor!(HTMLBRElementBinding),
|
||||
local_name!("button") => get_constructor!(HTMLButtonElementBinding),
|
||||
local_name!("canvas") => get_constructor!(HTMLCanvasElementBinding),
|
||||
local_name!("caption") => get_constructor!(HTMLTableCaptionElementBinding),
|
||||
local_name!("center") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("cite") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("code") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("col") => get_constructor!(HTMLTableColElementBinding),
|
||||
local_name!("colgroup") => get_constructor!(HTMLTableColElementBinding),
|
||||
local_name!("data") => get_constructor!(HTMLDataElementBinding),
|
||||
local_name!("datalist") => get_constructor!(HTMLDataListElementBinding),
|
||||
local_name!("dd") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("del") => get_constructor!(HTMLModElementBinding),
|
||||
local_name!("details") => get_constructor!(HTMLDetailsElementBinding),
|
||||
local_name!("dfn") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("dialog") => get_constructor!(HTMLDialogElementBinding),
|
||||
local_name!("dir") => get_constructor!(HTMLDirectoryElementBinding),
|
||||
local_name!("div") => get_constructor!(HTMLDivElementBinding),
|
||||
local_name!("dl") => get_constructor!(HTMLDListElementBinding),
|
||||
local_name!("dt") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("em") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("embed") => get_constructor!(HTMLEmbedElementBinding),
|
||||
local_name!("fieldset") => get_constructor!(HTMLFieldSetElementBinding),
|
||||
local_name!("figcaption") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("figure") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("font") => get_constructor!(HTMLFontElementBinding),
|
||||
local_name!("footer") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("form") => get_constructor!(HTMLFormElementBinding),
|
||||
local_name!("frame") => get_constructor!(HTMLFrameElementBinding),
|
||||
local_name!("frameset") => get_constructor!(HTMLFrameSetElementBinding),
|
||||
local_name!("h1") => get_constructor!(HTMLHeadingElementBinding),
|
||||
local_name!("h2") => get_constructor!(HTMLHeadingElementBinding),
|
||||
local_name!("h3") => get_constructor!(HTMLHeadingElementBinding),
|
||||
local_name!("h4") => get_constructor!(HTMLHeadingElementBinding),
|
||||
local_name!("h5") => get_constructor!(HTMLHeadingElementBinding),
|
||||
local_name!("h6") => get_constructor!(HTMLHeadingElementBinding),
|
||||
local_name!("head") => get_constructor!(HTMLHeadElementBinding),
|
||||
local_name!("header") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("hgroup") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("hr") => get_constructor!(HTMLHRElementBinding),
|
||||
local_name!("html") => get_constructor!(HTMLHtmlElementBinding),
|
||||
local_name!("i") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("iframe") => get_constructor!(HTMLIFrameElementBinding),
|
||||
local_name!("img") => get_constructor!(HTMLImageElementBinding),
|
||||
local_name!("input") => get_constructor!(HTMLInputElementBinding),
|
||||
local_name!("ins") => get_constructor!(HTMLModElementBinding),
|
||||
local_name!("kbd") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("label") => get_constructor!(HTMLLabelElementBinding),
|
||||
local_name!("legend") => get_constructor!(HTMLLegendElementBinding),
|
||||
local_name!("li") => get_constructor!(HTMLLIElementBinding),
|
||||
local_name!("link") => get_constructor!(HTMLLinkElementBinding),
|
||||
local_name!("listing") => get_constructor!(HTMLPreElementBinding),
|
||||
local_name!("main") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("map") => get_constructor!(HTMLMapElementBinding),
|
||||
local_name!("mark") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("marquee") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("meta") => get_constructor!(HTMLMetaElementBinding),
|
||||
local_name!("meter") => get_constructor!(HTMLMeterElementBinding),
|
||||
local_name!("nav") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("nobr") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("noframes") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("noscript") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("object") => get_constructor!(HTMLObjectElementBinding),
|
||||
local_name!("ol") => get_constructor!(HTMLOListElementBinding),
|
||||
local_name!("optgroup") => get_constructor!(HTMLOptGroupElementBinding),
|
||||
local_name!("option") => get_constructor!(HTMLOptionElementBinding),
|
||||
local_name!("output") => get_constructor!(HTMLOutputElementBinding),
|
||||
local_name!("p") => get_constructor!(HTMLParagraphElementBinding),
|
||||
local_name!("param") => get_constructor!(HTMLParamElementBinding),
|
||||
local_name!("plaintext") => get_constructor!(HTMLPreElementBinding),
|
||||
local_name!("pre") => get_constructor!(HTMLPreElementBinding),
|
||||
local_name!("progress") => get_constructor!(HTMLProgressElementBinding),
|
||||
local_name!("q") => get_constructor!(HTMLQuoteElementBinding),
|
||||
local_name!("rp") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("rt") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("ruby") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("s") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("samp") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("script") => get_constructor!(HTMLScriptElementBinding),
|
||||
local_name!("section") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("select") => get_constructor!(HTMLSelectElementBinding),
|
||||
local_name!("small") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("source") => get_constructor!(HTMLSourceElementBinding),
|
||||
local_name!("span") => get_constructor!(HTMLSpanElementBinding),
|
||||
local_name!("strike") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("strong") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("style") => get_constructor!(HTMLStyleElementBinding),
|
||||
local_name!("sub") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("summary") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("sup") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("table") => get_constructor!(HTMLTableElementBinding),
|
||||
local_name!("tbody") => get_constructor!(HTMLTableSectionElementBinding),
|
||||
local_name!("td") => get_constructor!(HTMLTableDataCellElementBinding),
|
||||
local_name!("template") => get_constructor!(HTMLTemplateElementBinding),
|
||||
local_name!("textarea") => get_constructor!(HTMLTextAreaElementBinding),
|
||||
local_name!("tfoot") => get_constructor!(HTMLTableSectionElementBinding),
|
||||
local_name!("th") => get_constructor!(HTMLTableHeaderCellElementBinding),
|
||||
local_name!("thead") => get_constructor!(HTMLTableSectionElementBinding),
|
||||
local_name!("time") => get_constructor!(HTMLTimeElementBinding),
|
||||
local_name!("title") => get_constructor!(HTMLTitleElementBinding),
|
||||
local_name!("tr") => get_constructor!(HTMLTableRowElementBinding),
|
||||
local_name!("tt") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("track") => get_constructor!(HTMLTrackElementBinding),
|
||||
local_name!("u") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("ul") => get_constructor!(HTMLUListElementBinding),
|
||||
local_name!("var") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("video") => get_constructor!(HTMLVideoElementBinding),
|
||||
local_name!("wbr") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("xmp") => get_constructor!(HTMLPreElementBinding),
|
||||
_ => false,
|
||||
local_name!("figure") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("font") => get_constructor!(HTMLFontElementBinding),
|
||||
local_name!("footer") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("form") => get_constructor!(HTMLFormElementBinding),
|
||||
local_name!("frame") => get_constructor!(HTMLFrameElementBinding),
|
||||
local_name!("frameset") => get_constructor!(HTMLFrameSetElementBinding),
|
||||
local_name!("h1") => get_constructor!(HTMLHeadingElementBinding),
|
||||
local_name!("h2") => get_constructor!(HTMLHeadingElementBinding),
|
||||
local_name!("h3") => get_constructor!(HTMLHeadingElementBinding),
|
||||
local_name!("h4") => get_constructor!(HTMLHeadingElementBinding),
|
||||
local_name!("h5") => get_constructor!(HTMLHeadingElementBinding),
|
||||
local_name!("h6") => get_constructor!(HTMLHeadingElementBinding),
|
||||
local_name!("head") => get_constructor!(HTMLHeadElementBinding),
|
||||
local_name!("header") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("hgroup") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("hr") => get_constructor!(HTMLHRElementBinding),
|
||||
local_name!("html") => get_constructor!(HTMLHtmlElementBinding),
|
||||
local_name!("i") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("iframe") => get_constructor!(HTMLIFrameElementBinding),
|
||||
local_name!("img") => get_constructor!(HTMLImageElementBinding),
|
||||
local_name!("input") => get_constructor!(HTMLInputElementBinding),
|
||||
local_name!("ins") => get_constructor!(HTMLModElementBinding),
|
||||
local_name!("kbd") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("label") => get_constructor!(HTMLLabelElementBinding),
|
||||
local_name!("legend") => get_constructor!(HTMLLegendElementBinding),
|
||||
local_name!("li") => get_constructor!(HTMLLIElementBinding),
|
||||
local_name!("link") => get_constructor!(HTMLLinkElementBinding),
|
||||
local_name!("listing") => get_constructor!(HTMLPreElementBinding),
|
||||
local_name!("main") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("map") => get_constructor!(HTMLMapElementBinding),
|
||||
local_name!("mark") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("marquee") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("meta") => get_constructor!(HTMLMetaElementBinding),
|
||||
local_name!("meter") => get_constructor!(HTMLMeterElementBinding),
|
||||
local_name!("nav") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("nobr") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("noframes") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("noscript") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("object") => get_constructor!(HTMLObjectElementBinding),
|
||||
local_name!("ol") => get_constructor!(HTMLOListElementBinding),
|
||||
local_name!("optgroup") => get_constructor!(HTMLOptGroupElementBinding),
|
||||
local_name!("option") => get_constructor!(HTMLOptionElementBinding),
|
||||
local_name!("output") => get_constructor!(HTMLOutputElementBinding),
|
||||
local_name!("p") => get_constructor!(HTMLParagraphElementBinding),
|
||||
local_name!("param") => get_constructor!(HTMLParamElementBinding),
|
||||
local_name!("plaintext") => get_constructor!(HTMLPreElementBinding),
|
||||
local_name!("pre") => get_constructor!(HTMLPreElementBinding),
|
||||
local_name!("progress") => get_constructor!(HTMLProgressElementBinding),
|
||||
local_name!("q") => get_constructor!(HTMLQuoteElementBinding),
|
||||
local_name!("rp") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("rt") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("ruby") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("s") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("samp") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("script") => get_constructor!(HTMLScriptElementBinding),
|
||||
local_name!("section") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("select") => get_constructor!(HTMLSelectElementBinding),
|
||||
local_name!("small") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("source") => get_constructor!(HTMLSourceElementBinding),
|
||||
local_name!("span") => get_constructor!(HTMLSpanElementBinding),
|
||||
local_name!("strike") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("strong") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("style") => get_constructor!(HTMLStyleElementBinding),
|
||||
local_name!("sub") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("summary") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("sup") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("table") => get_constructor!(HTMLTableElementBinding),
|
||||
local_name!("tbody") => get_constructor!(HTMLTableSectionElementBinding),
|
||||
local_name!("td") => get_constructor!(HTMLTableDataCellElementBinding),
|
||||
local_name!("template") => get_constructor!(HTMLTemplateElementBinding),
|
||||
local_name!("textarea") => get_constructor!(HTMLTextAreaElementBinding),
|
||||
local_name!("tfoot") => get_constructor!(HTMLTableSectionElementBinding),
|
||||
local_name!("th") => get_constructor!(HTMLTableHeaderCellElementBinding),
|
||||
local_name!("thead") => get_constructor!(HTMLTableSectionElementBinding),
|
||||
local_name!("time") => get_constructor!(HTMLTimeElementBinding),
|
||||
local_name!("title") => get_constructor!(HTMLTitleElementBinding),
|
||||
local_name!("tr") => get_constructor!(HTMLTableRowElementBinding),
|
||||
local_name!("tt") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("track") => get_constructor!(HTMLTrackElementBinding),
|
||||
local_name!("u") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("ul") => get_constructor!(HTMLUListElementBinding),
|
||||
local_name!("var") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("video") => get_constructor!(HTMLVideoElementBinding),
|
||||
local_name!("wbr") => get_constructor!(HTMLElementBinding),
|
||||
local_name!("xmp") => get_constructor!(HTMLPreElementBinding),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,8 @@ use std::mem;
|
|||
pub trait Castable: IDLInterface + DomObject + Sized {
|
||||
/// Check whether a DOM object implements one of its deriving interfaces.
|
||||
fn is<T>(&self) -> bool
|
||||
where T: DerivedFrom<Self>
|
||||
where
|
||||
T: DerivedFrom<Self>,
|
||||
{
|
||||
let class = unsafe { get_dom_class(self.reflector().get_jsobject().get()).unwrap() };
|
||||
T::derives(class)
|
||||
|
@ -24,15 +25,17 @@ pub trait Castable: IDLInterface + DomObject + Sized {
|
|||
|
||||
/// Cast a DOM object upwards to one of the interfaces it derives from.
|
||||
fn upcast<T>(&self) -> &T
|
||||
where T: Castable,
|
||||
Self: DerivedFrom<T>
|
||||
where
|
||||
T: Castable,
|
||||
Self: DerivedFrom<T>,
|
||||
{
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
|
||||
/// Cast a DOM object downwards to one of the interfaces it might implement.
|
||||
fn downcast<T>(&self) -> Option<&T>
|
||||
where T: DerivedFrom<Self>
|
||||
where
|
||||
T: DerivedFrom<Self>,
|
||||
{
|
||||
if self.is::<T>() {
|
||||
Some(unsafe { mem::transmute(self) })
|
||||
|
|
|
@ -52,11 +52,12 @@ unsafe impl Sync for NonCallbackInterfaceObjectClass {}
|
|||
|
||||
impl NonCallbackInterfaceObjectClass {
|
||||
/// Create a new `NonCallbackInterfaceObjectClass` structure.
|
||||
pub const fn new(constructor_behavior: &'static InterfaceConstructorBehavior,
|
||||
string_rep: &'static [u8],
|
||||
proto_id: PrototypeList::ID,
|
||||
proto_depth: u16)
|
||||
-> NonCallbackInterfaceObjectClass {
|
||||
pub const fn new(
|
||||
constructor_behavior: &'static InterfaceConstructorBehavior,
|
||||
string_rep: &'static [u8],
|
||||
proto_id: PrototypeList::ID,
|
||||
proto_depth: u16,
|
||||
) -> NonCallbackInterfaceObjectClass {
|
||||
NonCallbackInterfaceObjectClass {
|
||||
class: Class {
|
||||
name: b"Function\0" as *const _ as *const libc::c_char,
|
||||
|
@ -74,9 +75,7 @@ impl NonCallbackInterfaceObjectClass {
|
|||
|
||||
/// cast own reference to `JSClass` reference
|
||||
pub fn as_jsclass(&self) -> &JSClass {
|
||||
unsafe {
|
||||
&*(self as *const _ as *const JSClass)
|
||||
}
|
||||
unsafe { &*(self as *const _ as *const JSClass) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,27 +123,29 @@ impl InterfaceConstructorBehavior {
|
|||
}
|
||||
|
||||
/// A trace hook.
|
||||
pub type TraceHook =
|
||||
unsafe extern "C" fn(trc: *mut JSTracer, obj: *mut JSObject);
|
||||
pub type TraceHook = unsafe extern "C" fn(trc: *mut JSTracer, obj: *mut JSObject);
|
||||
|
||||
/// Create a global object with the given class.
|
||||
pub unsafe fn create_global_object(
|
||||
cx: *mut JSContext,
|
||||
class: &'static JSClass,
|
||||
private: *const libc::c_void,
|
||||
trace: TraceHook,
|
||||
mut rval: MutableHandleObject) {
|
||||
cx: *mut JSContext,
|
||||
class: &'static JSClass,
|
||||
private: *const libc::c_void,
|
||||
trace: TraceHook,
|
||||
mut rval: MutableHandleObject,
|
||||
) {
|
||||
assert!(rval.is_null());
|
||||
|
||||
let mut options = CompartmentOptions::default();
|
||||
options.creationOptions_.traceGlobal_ = Some(trace);
|
||||
options.creationOptions_.sharedMemoryAndAtomics_ = true;
|
||||
|
||||
rval.set(JS_NewGlobalObject(cx,
|
||||
class,
|
||||
ptr::null_mut(),
|
||||
OnNewGlobalHookOption::DontFireOnNewGlobalHook,
|
||||
&options));
|
||||
rval.set(JS_NewGlobalObject(
|
||||
cx,
|
||||
class,
|
||||
ptr::null_mut(),
|
||||
OnNewGlobalHookOption::DontFireOnNewGlobalHook,
|
||||
&options,
|
||||
));
|
||||
assert!(!rval.is_null());
|
||||
|
||||
// Initialize the reserved slots before doing anything that can GC, to
|
||||
|
@ -162,11 +163,12 @@ pub unsafe fn create_global_object(
|
|||
|
||||
/// Create and define the interface object of a callback interface.
|
||||
pub unsafe fn create_callback_interface_object(
|
||||
cx: *mut JSContext,
|
||||
global: HandleObject,
|
||||
constants: &[Guard<&[ConstantSpec]>],
|
||||
name: &[u8],
|
||||
mut rval: MutableHandleObject) {
|
||||
cx: *mut JSContext,
|
||||
global: HandleObject,
|
||||
constants: &[Guard<&[ConstantSpec]>],
|
||||
name: &[u8],
|
||||
mut rval: MutableHandleObject,
|
||||
) {
|
||||
assert!(!constants.is_empty());
|
||||
rval.set(JS_NewObject(cx, ptr::null()));
|
||||
assert!(!rval.is_null());
|
||||
|
@ -177,15 +179,24 @@ pub unsafe fn create_callback_interface_object(
|
|||
|
||||
/// Create the interface prototype object of a non-callback interface.
|
||||
pub unsafe fn create_interface_prototype_object(
|
||||
cx: *mut JSContext,
|
||||
proto: HandleObject,
|
||||
class: &'static JSClass,
|
||||
regular_methods: &[Guard<&'static [JSFunctionSpec]>],
|
||||
regular_properties: &[Guard<&'static [JSPropertySpec]>],
|
||||
constants: &[Guard<&[ConstantSpec]>],
|
||||
unscopable_names: &[&[u8]],
|
||||
rval: MutableHandleObject) {
|
||||
create_object(cx, proto, class, regular_methods, regular_properties, constants, rval);
|
||||
cx: *mut JSContext,
|
||||
proto: HandleObject,
|
||||
class: &'static JSClass,
|
||||
regular_methods: &[Guard<&'static [JSFunctionSpec]>],
|
||||
regular_properties: &[Guard<&'static [JSPropertySpec]>],
|
||||
constants: &[Guard<&[ConstantSpec]>],
|
||||
unscopable_names: &[&[u8]],
|
||||
rval: MutableHandleObject,
|
||||
) {
|
||||
create_object(
|
||||
cx,
|
||||
proto,
|
||||
class,
|
||||
regular_methods,
|
||||
regular_properties,
|
||||
constants,
|
||||
rval,
|
||||
);
|
||||
|
||||
if !unscopable_names.is_empty() {
|
||||
rooted!(in(cx) let mut unscopable_obj = ptr::null_mut::<JSObject>());
|
||||
|
@ -196,32 +207,43 @@ pub unsafe fn create_interface_prototype_object(
|
|||
|
||||
rooted!(in(cx) let unscopable_id = RUST_SYMBOL_TO_JSID(unscopable_symbol));
|
||||
assert!(JS_DefinePropertyById4(
|
||||
cx, rval.handle(), unscopable_id.handle(), unscopable_obj.handle(),
|
||||
JSPROP_READONLY as u32))
|
||||
cx,
|
||||
rval.handle(),
|
||||
unscopable_id.handle(),
|
||||
unscopable_obj.handle(),
|
||||
JSPROP_READONLY as u32
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// Create and define the interface object of a non-callback interface.
|
||||
pub unsafe fn create_noncallback_interface_object(
|
||||
cx: *mut JSContext,
|
||||
global: HandleObject,
|
||||
proto: HandleObject,
|
||||
class: &'static NonCallbackInterfaceObjectClass,
|
||||
static_methods: &[Guard<&'static [JSFunctionSpec]>],
|
||||
static_properties: &[Guard<&'static [JSPropertySpec]>],
|
||||
constants: &[Guard<&[ConstantSpec]>],
|
||||
interface_prototype_object: HandleObject,
|
||||
name: &[u8],
|
||||
length: u32,
|
||||
rval: MutableHandleObject) {
|
||||
create_object(cx,
|
||||
proto,
|
||||
class.as_jsclass(),
|
||||
static_methods,
|
||||
static_properties,
|
||||
constants,
|
||||
rval);
|
||||
assert!(JS_LinkConstructorAndPrototype(cx, rval.handle(), interface_prototype_object));
|
||||
cx: *mut JSContext,
|
||||
global: HandleObject,
|
||||
proto: HandleObject,
|
||||
class: &'static NonCallbackInterfaceObjectClass,
|
||||
static_methods: &[Guard<&'static [JSFunctionSpec]>],
|
||||
static_properties: &[Guard<&'static [JSPropertySpec]>],
|
||||
constants: &[Guard<&[ConstantSpec]>],
|
||||
interface_prototype_object: HandleObject,
|
||||
name: &[u8],
|
||||
length: u32,
|
||||
rval: MutableHandleObject,
|
||||
) {
|
||||
create_object(
|
||||
cx,
|
||||
proto,
|
||||
class.as_jsclass(),
|
||||
static_methods,
|
||||
static_properties,
|
||||
constants,
|
||||
rval,
|
||||
);
|
||||
assert!(JS_LinkConstructorAndPrototype(
|
||||
cx,
|
||||
rval.handle(),
|
||||
interface_prototype_object
|
||||
));
|
||||
define_name(cx, rval.handle(), name);
|
||||
define_length(cx, rval.handle(), i32::try_from(length).expect("overflow"));
|
||||
define_on_global_object(cx, global, name, rval.handle());
|
||||
|
@ -229,29 +251,34 @@ pub unsafe fn create_noncallback_interface_object(
|
|||
|
||||
/// Create and define the named constructors of a non-callback interface.
|
||||
pub unsafe fn create_named_constructors(
|
||||
cx: *mut JSContext,
|
||||
global: HandleObject,
|
||||
named_constructors: &[(ConstructorClassHook, &[u8], u32)],
|
||||
interface_prototype_object: HandleObject) {
|
||||
cx: *mut JSContext,
|
||||
global: HandleObject,
|
||||
named_constructors: &[(ConstructorClassHook, &[u8], u32)],
|
||||
interface_prototype_object: HandleObject,
|
||||
) {
|
||||
rooted!(in(cx) let mut constructor = ptr::null_mut::<JSObject>());
|
||||
|
||||
for &(native, name, arity) in named_constructors {
|
||||
assert_eq!(*name.last().unwrap(), b'\0');
|
||||
|
||||
let fun = JS_NewFunction(cx,
|
||||
Some(native),
|
||||
arity,
|
||||
JSFUN_CONSTRUCTOR,
|
||||
name.as_ptr() as *const libc::c_char);
|
||||
let fun = JS_NewFunction(
|
||||
cx,
|
||||
Some(native),
|
||||
arity,
|
||||
JSFUN_CONSTRUCTOR,
|
||||
name.as_ptr() as *const libc::c_char,
|
||||
);
|
||||
assert!(!fun.is_null());
|
||||
constructor.set(JS_GetFunctionObject(fun));
|
||||
assert!(!constructor.is_null());
|
||||
|
||||
assert!(JS_DefineProperty2(cx,
|
||||
constructor.handle(),
|
||||
b"prototype\0".as_ptr() as *const libc::c_char,
|
||||
interface_prototype_object,
|
||||
(JSPROP_PERMANENT | JSPROP_READONLY) as u32));
|
||||
assert!(JS_DefineProperty2(
|
||||
cx,
|
||||
constructor.handle(),
|
||||
b"prototype\0".as_ptr() as *const libc::c_char,
|
||||
interface_prototype_object,
|
||||
(JSPROP_PERMANENT | JSPROP_READONLY) as u32
|
||||
));
|
||||
|
||||
define_on_global_object(cx, global, name, constructor.handle());
|
||||
}
|
||||
|
@ -259,13 +286,14 @@ pub unsafe fn create_named_constructors(
|
|||
|
||||
/// Create a new object with a unique type.
|
||||
pub unsafe fn create_object(
|
||||
cx: *mut JSContext,
|
||||
proto: HandleObject,
|
||||
class: &'static JSClass,
|
||||
methods: &[Guard<&'static [JSFunctionSpec]>],
|
||||
properties: &[Guard<&'static [JSPropertySpec]>],
|
||||
constants: &[Guard<&[ConstantSpec]>],
|
||||
mut rval: MutableHandleObject) {
|
||||
cx: *mut JSContext,
|
||||
proto: HandleObject,
|
||||
class: &'static JSClass,
|
||||
methods: &[Guard<&'static [JSFunctionSpec]>],
|
||||
properties: &[Guard<&'static [JSPropertySpec]>],
|
||||
constants: &[Guard<&[ConstantSpec]>],
|
||||
mut rval: MutableHandleObject,
|
||||
) {
|
||||
rval.set(JS_NewObjectWithUniqueType(cx, class, proto));
|
||||
assert!(!rval.is_null());
|
||||
define_guarded_methods(cx, rval.handle(), methods);
|
||||
|
@ -275,9 +303,10 @@ pub unsafe fn create_object(
|
|||
|
||||
/// Conditionally define constants on an object.
|
||||
pub unsafe fn define_guarded_constants(
|
||||
cx: *mut JSContext,
|
||||
obj: HandleObject,
|
||||
constants: &[Guard<&[ConstantSpec]>]) {
|
||||
cx: *mut JSContext,
|
||||
obj: HandleObject,
|
||||
constants: &[Guard<&[ConstantSpec]>],
|
||||
) {
|
||||
for guard in constants {
|
||||
if let Some(specs) = guard.expose(cx, obj) {
|
||||
define_constants(cx, obj, specs);
|
||||
|
@ -287,9 +316,10 @@ pub unsafe fn define_guarded_constants(
|
|||
|
||||
/// Conditionally define methods on an object.
|
||||
pub unsafe fn define_guarded_methods(
|
||||
cx: *mut JSContext,
|
||||
obj: HandleObject,
|
||||
methods: &[Guard<&'static [JSFunctionSpec]>]) {
|
||||
cx: *mut JSContext,
|
||||
obj: HandleObject,
|
||||
methods: &[Guard<&'static [JSFunctionSpec]>],
|
||||
) {
|
||||
for guard in methods {
|
||||
if let Some(specs) = guard.expose(cx, obj) {
|
||||
define_methods(cx, obj, specs).unwrap();
|
||||
|
@ -299,9 +329,10 @@ pub unsafe fn define_guarded_methods(
|
|||
|
||||
/// Conditionally define properties on an object.
|
||||
pub unsafe fn define_guarded_properties(
|
||||
cx: *mut JSContext,
|
||||
obj: HandleObject,
|
||||
properties: &[Guard<&'static [JSPropertySpec]>]) {
|
||||
cx: *mut JSContext,
|
||||
obj: HandleObject,
|
||||
properties: &[Guard<&'static [JSPropertySpec]>],
|
||||
) {
|
||||
for guard in properties {
|
||||
if let Some(specs) = guard.expose(cx, obj) {
|
||||
define_properties(cx, obj, specs).unwrap();
|
||||
|
@ -320,16 +351,19 @@ pub unsafe fn is_exposed_in(object: HandleObject, globals: Globals) -> bool {
|
|||
/// Define a property with a given name on the global object. Should be called
|
||||
/// through the resolve hook.
|
||||
pub unsafe fn define_on_global_object(
|
||||
cx: *mut JSContext,
|
||||
global: HandleObject,
|
||||
name: &[u8],
|
||||
obj: HandleObject) {
|
||||
cx: *mut JSContext,
|
||||
global: HandleObject,
|
||||
name: &[u8],
|
||||
obj: HandleObject,
|
||||
) {
|
||||
assert_eq!(*name.last().unwrap(), b'\0');
|
||||
assert!(JS_DefineProperty2(cx,
|
||||
global,
|
||||
name.as_ptr() as *const libc::c_char,
|
||||
obj,
|
||||
JSPROP_RESOLVING));
|
||||
assert!(JS_DefineProperty2(
|
||||
cx,
|
||||
global,
|
||||
name.as_ptr() as *const libc::c_char,
|
||||
obj,
|
||||
JSPROP_RESOLVING
|
||||
));
|
||||
}
|
||||
|
||||
const OBJECT_OPS: ObjectOps = ObjectOps {
|
||||
|
@ -344,10 +378,11 @@ const OBJECT_OPS: ObjectOps = ObjectOps {
|
|||
funToString: Some(fun_to_string_hook),
|
||||
};
|
||||
|
||||
unsafe extern "C" fn fun_to_string_hook(cx: *mut JSContext,
|
||||
obj: RawHandleObject,
|
||||
_is_to_source: bool)
|
||||
-> *mut JSString {
|
||||
unsafe extern "C" fn fun_to_string_hook(
|
||||
cx: *mut JSContext,
|
||||
obj: RawHandleObject,
|
||||
_is_to_source: bool,
|
||||
) -> *mut JSString {
|
||||
let js_class = get_object_class(obj.get());
|
||||
assert!(!js_class.is_null());
|
||||
let repr = (*(js_class as *const NonCallbackInterfaceObjectClass)).representation;
|
||||
|
@ -358,17 +393,19 @@ unsafe extern "C" fn fun_to_string_hook(cx: *mut JSContext,
|
|||
}
|
||||
|
||||
/// Hook for instanceof on interface objects.
|
||||
unsafe extern "C" fn has_instance_hook(cx: *mut JSContext,
|
||||
obj: RawHandleObject,
|
||||
value: RawMutableHandleValue,
|
||||
rval: *mut bool) -> bool {
|
||||
unsafe extern "C" fn has_instance_hook(
|
||||
cx: *mut JSContext,
|
||||
obj: RawHandleObject,
|
||||
value: RawMutableHandleValue,
|
||||
rval: *mut bool,
|
||||
) -> bool {
|
||||
let obj_raw = HandleObject::from_raw(obj);
|
||||
let val_raw = HandleValue::from_raw(value.handle());
|
||||
match has_instance(cx, obj_raw, val_raw) {
|
||||
Ok(result) => {
|
||||
*rval = result;
|
||||
true
|
||||
}
|
||||
},
|
||||
Err(()) => false,
|
||||
}
|
||||
}
|
||||
|
@ -376,10 +413,10 @@ unsafe extern "C" fn has_instance_hook(cx: *mut JSContext,
|
|||
/// Return whether a value is an instance of a given prototype.
|
||||
/// <http://heycam.github.io/webidl/#es-interface-hasinstance>
|
||||
unsafe fn has_instance(
|
||||
cx: *mut JSContext,
|
||||
interface_object: HandleObject,
|
||||
value: HandleValue)
|
||||
-> Result<bool, ()> {
|
||||
cx: *mut JSContext,
|
||||
interface_object: HandleObject,
|
||||
value: HandleValue,
|
||||
) -> Result<bool, ()> {
|
||||
if !value.is_object() {
|
||||
// Step 1.
|
||||
return Ok(false);
|
||||
|
@ -391,8 +428,10 @@ unsafe fn has_instance(
|
|||
let js_class = get_object_class(interface_object.get());
|
||||
let object_class = &*(js_class as *const NonCallbackInterfaceObjectClass);
|
||||
|
||||
if let Ok(dom_class) = get_dom_class(UncheckedUnwrapObject(value.get(),
|
||||
/* stopAtWindowProxy = */ 0)) {
|
||||
if let Ok(dom_class) = get_dom_class(UncheckedUnwrapObject(
|
||||
value.get(),
|
||||
/* stopAtWindowProxy = */ 0,
|
||||
)) {
|
||||
if dom_class.interface_chain[object_class.proto_depth as usize] == object_class.proto_id {
|
||||
// Step 4.
|
||||
return Ok(true);
|
||||
|
@ -422,9 +461,10 @@ unsafe fn has_instance(
|
|||
}
|
||||
|
||||
unsafe fn create_unscopable_object(
|
||||
cx: *mut JSContext,
|
||||
names: &[&[u8]],
|
||||
mut rval: MutableHandleObject) {
|
||||
cx: *mut JSContext,
|
||||
names: &[&[u8]],
|
||||
mut rval: MutableHandleObject,
|
||||
) {
|
||||
assert!(!names.is_empty());
|
||||
assert!(rval.is_null());
|
||||
rval.set(JS_NewPlainObject(cx));
|
||||
|
@ -445,35 +485,39 @@ unsafe fn define_name(cx: *mut JSContext, obj: HandleObject, name: &[u8]) {
|
|||
assert_eq!(*name.last().unwrap(), b'\0');
|
||||
rooted!(in(cx) let name = JS_AtomizeAndPinString(cx, name.as_ptr() as *const libc::c_char));
|
||||
assert!(!name.is_null());
|
||||
assert!(JS_DefineProperty3(cx,
|
||||
obj,
|
||||
b"name\0".as_ptr() as *const libc::c_char,
|
||||
name.handle().into(),
|
||||
JSPROP_READONLY as u32));
|
||||
assert!(JS_DefineProperty3(
|
||||
cx,
|
||||
obj,
|
||||
b"name\0".as_ptr() as *const libc::c_char,
|
||||
name.handle().into(),
|
||||
JSPROP_READONLY as u32
|
||||
));
|
||||
}
|
||||
|
||||
unsafe fn define_length(cx: *mut JSContext, obj: HandleObject, length: i32) {
|
||||
assert!(JS_DefineProperty4(cx,
|
||||
obj,
|
||||
b"length\0".as_ptr() as *const libc::c_char,
|
||||
length,
|
||||
JSPROP_READONLY as u32));
|
||||
assert!(JS_DefineProperty4(
|
||||
cx,
|
||||
obj,
|
||||
b"length\0".as_ptr() as *const libc::c_char,
|
||||
length,
|
||||
JSPROP_READONLY as u32
|
||||
));
|
||||
}
|
||||
|
||||
unsafe extern "C" fn invalid_constructor(
|
||||
cx: *mut JSContext,
|
||||
_argc: libc::c_uint,
|
||||
_vp: *mut JSVal)
|
||||
-> bool {
|
||||
cx: *mut JSContext,
|
||||
_argc: libc::c_uint,
|
||||
_vp: *mut JSVal,
|
||||
) -> bool {
|
||||
throw_type_error(cx, "Illegal constructor.");
|
||||
false
|
||||
}
|
||||
|
||||
unsafe extern "C" fn non_new_constructor(
|
||||
cx: *mut JSContext,
|
||||
_argc: libc::c_uint,
|
||||
_vp: *mut JSVal)
|
||||
-> bool {
|
||||
cx: *mut JSContext,
|
||||
_argc: libc::c_uint,
|
||||
_vp: *mut JSVal,
|
||||
) -> bool {
|
||||
throw_type_error(cx, "This constructor needs to be called with `new`.");
|
||||
false
|
||||
}
|
||||
|
|
|
@ -59,10 +59,11 @@ pub struct IterableIterator<T: DomObject + JSTraceable + Iterable> {
|
|||
|
||||
impl<T: DomObject + JSTraceable + Iterable> IterableIterator<T> {
|
||||
/// Create a new iterator instance for the provided iterable DOM interface.
|
||||
pub fn new(iterable: &T,
|
||||
type_: IteratorType,
|
||||
wrap: unsafe fn(*mut JSContext, &GlobalScope, Box<IterableIterator<T>>)
|
||||
-> DomRoot<Self>) -> DomRoot<Self> {
|
||||
pub fn new(
|
||||
iterable: &T,
|
||||
type_: IteratorType,
|
||||
wrap: unsafe fn(*mut JSContext, &GlobalScope, Box<IterableIterator<T>>) -> DomRoot<Self>,
|
||||
) -> DomRoot<Self> {
|
||||
let iterator = Box::new(IterableIterator {
|
||||
reflector: Reflector::new(),
|
||||
type_: type_,
|
||||
|
@ -84,37 +85,45 @@ impl<T: DomObject + JSTraceable + Iterable> IterableIterator<T> {
|
|||
match self.type_ {
|
||||
IteratorType::Keys => {
|
||||
unsafe {
|
||||
self.iterable.get_key_at_index(index).to_jsval(cx, value.handle_mut());
|
||||
self.iterable
|
||||
.get_key_at_index(index)
|
||||
.to_jsval(cx, value.handle_mut());
|
||||
}
|
||||
dict_return(cx, rval.handle_mut(), false, value.handle())
|
||||
}
|
||||
},
|
||||
IteratorType::Values => {
|
||||
unsafe {
|
||||
self.iterable.get_value_at_index(index).to_jsval(cx, value.handle_mut());
|
||||
self.iterable
|
||||
.get_value_at_index(index)
|
||||
.to_jsval(cx, value.handle_mut());
|
||||
}
|
||||
dict_return(cx, rval.handle_mut(), false, value.handle())
|
||||
}
|
||||
},
|
||||
IteratorType::Entries => {
|
||||
rooted!(in(cx) let mut key = UndefinedValue());
|
||||
unsafe {
|
||||
self.iterable.get_key_at_index(index).to_jsval(cx, key.handle_mut());
|
||||
self.iterable.get_value_at_index(index).to_jsval(cx, value.handle_mut());
|
||||
self.iterable
|
||||
.get_key_at_index(index)
|
||||
.to_jsval(cx, key.handle_mut());
|
||||
self.iterable
|
||||
.get_value_at_index(index)
|
||||
.to_jsval(cx, value.handle_mut());
|
||||
}
|
||||
key_and_value_return(cx, rval.handle_mut(), key.handle(), value.handle())
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
self.index.set(index + 1);
|
||||
result.map(|_| {
|
||||
NonNull::new(rval.get()).expect("got a null pointer")
|
||||
})
|
||||
result.map(|_| NonNull::new(rval.get()).expect("got a null pointer"))
|
||||
}
|
||||
}
|
||||
|
||||
fn dict_return(cx: *mut JSContext,
|
||||
mut result: MutableHandleObject,
|
||||
done: bool,
|
||||
value: HandleValue) -> Fallible<()> {
|
||||
fn dict_return(
|
||||
cx: *mut JSContext,
|
||||
mut result: MutableHandleObject,
|
||||
done: bool,
|
||||
value: HandleValue,
|
||||
) -> Fallible<()> {
|
||||
let mut dict = IterableKeyOrValueResult::empty();
|
||||
dict.done = done;
|
||||
dict.value.set(value.get());
|
||||
|
@ -126,16 +135,20 @@ fn dict_return(cx: *mut JSContext,
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn key_and_value_return(cx: *mut JSContext,
|
||||
mut result: MutableHandleObject,
|
||||
key: HandleValue,
|
||||
value: HandleValue) -> Fallible<()> {
|
||||
fn key_and_value_return(
|
||||
cx: *mut JSContext,
|
||||
mut result: MutableHandleObject,
|
||||
key: HandleValue,
|
||||
value: HandleValue,
|
||||
) -> Fallible<()> {
|
||||
let mut dict = IterableKeyAndValueResult::empty();
|
||||
dict.done = false;
|
||||
dict.value = Some(vec![key, value]
|
||||
.into_iter()
|
||||
.map(|handle| RootedTraceableBox::from_box(Heap::boxed(handle.get())))
|
||||
.collect());
|
||||
dict.value = Some(
|
||||
vec![key, value]
|
||||
.into_iter()
|
||||
.map(|handle| RootedTraceableBox::from_box(Heap::boxed(handle.get())))
|
||||
.collect(),
|
||||
);
|
||||
rooted!(in(cx) let mut dict_value = UndefinedValue());
|
||||
unsafe {
|
||||
dict.to_jsval(cx, dict_value.handle_mut());
|
||||
|
|
|
@ -49,24 +49,37 @@ impl<T> Deref for MozMap<T> {
|
|||
}
|
||||
|
||||
impl<T, C> FromJSValConvertible for MozMap<T>
|
||||
where T: FromJSValConvertible<Config=C>,
|
||||
C: Clone,
|
||||
where
|
||||
T: FromJSValConvertible<Config = C>,
|
||||
C: Clone,
|
||||
{
|
||||
type Config = C;
|
||||
unsafe fn from_jsval(cx: *mut JSContext, value: HandleValue, config: C)
|
||||
-> Result<ConversionResult<Self>, ()> {
|
||||
unsafe fn from_jsval(
|
||||
cx: *mut JSContext,
|
||||
value: HandleValue,
|
||||
config: C,
|
||||
) -> Result<ConversionResult<Self>, ()> {
|
||||
if !value.is_object() {
|
||||
return Ok(ConversionResult::Failure("MozMap value was not an object".into()));
|
||||
return Ok(ConversionResult::Failure(
|
||||
"MozMap value was not an object".into(),
|
||||
));
|
||||
}
|
||||
|
||||
rooted!(in(cx) let object = value.to_object());
|
||||
let ids = IdVector::new(cx);
|
||||
if !GetPropertyKeys(cx, object.handle(), JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS, ids.get()) {
|
||||
if !GetPropertyKeys(
|
||||
cx,
|
||||
object.handle(),
|
||||
JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS,
|
||||
ids.get(),
|
||||
) {
|
||||
// TODO: can GetPropertyKeys fail?
|
||||
// (it does so if the object has duplicate keys)
|
||||
// https://github.com/servo/servo/issues/21462
|
||||
report_pending_exception(cx, false);
|
||||
return Ok(ConversionResult::Failure("Getting MozMap value property keys failed".into()));
|
||||
return Ok(ConversionResult::Failure(
|
||||
"Getting MozMap value property keys failed".into(),
|
||||
));
|
||||
}
|
||||
|
||||
let mut map = HashMap::new();
|
||||
|
@ -90,9 +103,7 @@ impl<T, C> FromJSValConvertible for MozMap<T>
|
|||
}
|
||||
}
|
||||
|
||||
Ok(ConversionResult::Success(MozMap {
|
||||
map: map,
|
||||
}))
|
||||
Ok(ConversionResult::Success(MozMap { map: map }))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,12 +118,14 @@ impl<T: ToJSValConvertible> ToJSValConvertible for MozMap<T> {
|
|||
let key = key.encode_utf16().collect::<Vec<_>>();
|
||||
value.to_jsval(cx, js_value.handle_mut());
|
||||
|
||||
assert!(JS_DefineUCProperty2(cx,
|
||||
js_object.handle(),
|
||||
key.as_ptr(),
|
||||
key.len(),
|
||||
js_value.handle(),
|
||||
JSPROP_ENUMERATE as u32));
|
||||
assert!(JS_DefineUCProperty2(
|
||||
cx,
|
||||
js_object.handle(),
|
||||
key.as_ptr(),
|
||||
key.len(),
|
||||
js_value.handle(),
|
||||
JSPROP_ENUMERATE as u32
|
||||
));
|
||||
}
|
||||
|
||||
rval.set(ObjectValue(js_object.handle().get()));
|
||||
|
|
|
@ -30,13 +30,14 @@ impl NamespaceObjectClass {
|
|||
|
||||
/// Create a new namespace object.
|
||||
pub unsafe fn create_namespace_object(
|
||||
cx: *mut JSContext,
|
||||
global: HandleObject,
|
||||
proto: HandleObject,
|
||||
class: &'static NamespaceObjectClass,
|
||||
methods: &[Guard<&'static [JSFunctionSpec]>],
|
||||
name: &[u8],
|
||||
rval: MutableHandleObject) {
|
||||
cx: *mut JSContext,
|
||||
global: HandleObject,
|
||||
proto: HandleObject,
|
||||
class: &'static NamespaceObjectClass,
|
||||
methods: &[Guard<&'static [JSFunctionSpec]>],
|
||||
name: &[u8],
|
||||
rval: MutableHandleObject,
|
||||
) {
|
||||
create_object(cx, proto, &class.0, methods, &[], &[], rval);
|
||||
define_on_global_object(cx, global, name, rval.handle());
|
||||
}
|
||||
|
|
|
@ -26,8 +26,10 @@ impl<T: Float> Finite<T> {
|
|||
/// Create a new `Finite<T: Float>`.
|
||||
#[inline]
|
||||
pub fn wrap(value: T) -> Finite<T> {
|
||||
assert!(value.is_finite(),
|
||||
"Finite<T> doesn't encapsulate unrestricted value.");
|
||||
assert!(
|
||||
value.is_finite(),
|
||||
"Finite<T> doesn't encapsulate unrestricted value."
|
||||
);
|
||||
Finite(value)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,12 +30,12 @@ use js::rust::wrappers::JS_AlreadyHasOwnPropertyById;
|
|||
use js::rust::wrappers::JS_NewObjectWithGivenProto;
|
||||
use std::ptr;
|
||||
|
||||
|
||||
/// Determine if this id shadows any existing properties for this proxy.
|
||||
pub unsafe extern "C" fn shadow_check_callback(cx: *mut JSContext,
|
||||
object: RawHandleObject,
|
||||
id: RawHandleId)
|
||||
-> DOMProxyShadowsResult {
|
||||
pub unsafe extern "C" fn shadow_check_callback(
|
||||
cx: *mut JSContext,
|
||||
object: RawHandleObject,
|
||||
id: RawHandleId,
|
||||
) -> DOMProxyShadowsResult {
|
||||
// TODO: support OverrideBuiltins when #12978 is fixed.
|
||||
|
||||
rooted!(in(cx) let mut expando = ptr::null_mut::<JSObject>());
|
||||
|
@ -59,19 +59,19 @@ pub unsafe extern "C" fn shadow_check_callback(cx: *mut JSContext,
|
|||
|
||||
/// Initialize the infrastructure for DOM proxy objects.
|
||||
pub unsafe fn init() {
|
||||
SetDOMProxyInformation(GetProxyHandlerFamily(),
|
||||
Some(shadow_check_callback));
|
||||
SetDOMProxyInformation(GetProxyHandlerFamily(), Some(shadow_check_callback));
|
||||
}
|
||||
|
||||
/// Invoke the [[GetOwnProperty]] trap (`getOwnPropertyDescriptor`) on `proxy`,
|
||||
/// with argument `id` and return the result, if it is not `undefined`.
|
||||
/// Otherwise, walk along the prototype chain to find a property with that
|
||||
/// name.
|
||||
pub unsafe extern "C" fn get_property_descriptor(cx: *mut JSContext,
|
||||
proxy: RawHandleObject,
|
||||
id: RawHandleId,
|
||||
desc: RawMutableHandle<PropertyDescriptor>)
|
||||
-> bool {
|
||||
pub unsafe extern "C" fn get_property_descriptor(
|
||||
cx: *mut JSContext,
|
||||
proxy: RawHandleObject,
|
||||
id: RawHandleId,
|
||||
desc: RawMutableHandle<PropertyDescriptor>,
|
||||
) -> bool {
|
||||
let handler = GetProxyHandler(proxy.get());
|
||||
if !InvokeGetOwnPropertyDescriptor(handler, cx, proxy, id, desc) {
|
||||
return false;
|
||||
|
@ -91,23 +91,25 @@ pub unsafe extern "C" fn get_property_descriptor(cx: *mut JSContext,
|
|||
}
|
||||
|
||||
/// Defines an expando on the given `proxy`.
|
||||
pub unsafe extern "C" fn define_property(cx: *mut JSContext,
|
||||
proxy: RawHandleObject,
|
||||
id: RawHandleId,
|
||||
desc: RawHandle<PropertyDescriptor>,
|
||||
result: *mut ObjectOpResult)
|
||||
-> bool {
|
||||
pub unsafe extern "C" fn define_property(
|
||||
cx: *mut JSContext,
|
||||
proxy: RawHandleObject,
|
||||
id: RawHandleId,
|
||||
desc: RawHandle<PropertyDescriptor>,
|
||||
result: *mut ObjectOpResult,
|
||||
) -> bool {
|
||||
rooted!(in(cx) let mut expando = ptr::null_mut::<JSObject>());
|
||||
ensure_expando_object(cx, proxy, expando.handle_mut());
|
||||
JS_DefinePropertyById(cx, expando.handle().into(), id, desc, result)
|
||||
}
|
||||
|
||||
/// Deletes an expando off the given `proxy`.
|
||||
pub unsafe extern "C" fn delete(cx: *mut JSContext,
|
||||
proxy: RawHandleObject,
|
||||
id: RawHandleId,
|
||||
bp: *mut ObjectOpResult)
|
||||
-> bool {
|
||||
pub unsafe extern "C" fn delete(
|
||||
cx: *mut JSContext,
|
||||
proxy: RawHandleObject,
|
||||
id: RawHandleId,
|
||||
bp: *mut ObjectOpResult,
|
||||
) -> bool {
|
||||
rooted!(in(cx) let mut expando = ptr::null_mut::<JSObject>());
|
||||
get_expando_object(proxy, expando.handle_mut());
|
||||
if expando.is_null() {
|
||||
|
@ -119,19 +121,21 @@ pub unsafe extern "C" fn delete(cx: *mut JSContext,
|
|||
}
|
||||
|
||||
/// Controls whether the Extensible bit can be changed
|
||||
pub unsafe extern "C" fn prevent_extensions(_cx: *mut JSContext,
|
||||
_proxy: RawHandleObject,
|
||||
result: *mut ObjectOpResult)
|
||||
-> bool {
|
||||
pub unsafe extern "C" fn prevent_extensions(
|
||||
_cx: *mut JSContext,
|
||||
_proxy: RawHandleObject,
|
||||
result: *mut ObjectOpResult,
|
||||
) -> bool {
|
||||
(*result).code_ = JSErrNum::JSMSG_CANT_PREVENT_EXTENSIONS as ::libc::uintptr_t;
|
||||
true
|
||||
}
|
||||
|
||||
/// Reports whether the object is Extensible
|
||||
pub unsafe extern "C" fn is_extensible(_cx: *mut JSContext,
|
||||
_proxy: RawHandleObject,
|
||||
succeeded: *mut bool)
|
||||
-> bool {
|
||||
pub unsafe extern "C" fn is_extensible(
|
||||
_cx: *mut JSContext,
|
||||
_proxy: RawHandleObject,
|
||||
succeeded: *mut bool,
|
||||
) -> bool {
|
||||
*succeeded = true;
|
||||
true
|
||||
}
|
||||
|
@ -145,11 +149,12 @@ pub unsafe extern "C" fn is_extensible(_cx: *mut JSContext,
|
|||
/// This implementation always handles the case of the ordinary
|
||||
/// `[[GetPrototypeOf]]` behavior. An alternative implementation will be
|
||||
/// necessary for the Location object.
|
||||
pub unsafe extern "C" fn get_prototype_if_ordinary(_: *mut JSContext,
|
||||
proxy: RawHandleObject,
|
||||
is_ordinary: *mut bool,
|
||||
proto: RawMutableHandleObject)
|
||||
-> bool {
|
||||
pub unsafe extern "C" fn get_prototype_if_ordinary(
|
||||
_: *mut JSContext,
|
||||
proxy: RawHandleObject,
|
||||
is_ordinary: *mut bool,
|
||||
proto: RawMutableHandleObject,
|
||||
) -> bool {
|
||||
*is_ordinary = true;
|
||||
proto.set(GetStaticPrototype(proxy.get()));
|
||||
true
|
||||
|
@ -169,11 +174,19 @@ pub unsafe fn get_expando_object(obj: RawHandleObject, mut expando: MutableHandl
|
|||
|
||||
/// Get the expando object, or create it if it doesn't exist yet.
|
||||
/// Fails on JSAPI failure.
|
||||
pub unsafe fn ensure_expando_object(cx: *mut JSContext, obj: RawHandleObject, mut expando: MutableHandleObject) {
|
||||
pub unsafe fn ensure_expando_object(
|
||||
cx: *mut JSContext,
|
||||
obj: RawHandleObject,
|
||||
mut expando: MutableHandleObject,
|
||||
) {
|
||||
assert!(is_dom_proxy(obj.get()));
|
||||
get_expando_object(obj, expando);
|
||||
if expando.is_null() {
|
||||
expando.set(JS_NewObjectWithGivenProto(cx, ptr::null_mut(), HandleObject::null()));
|
||||
expando.set(JS_NewObjectWithGivenProto(
|
||||
cx,
|
||||
ptr::null_mut(),
|
||||
HandleObject::null(),
|
||||
));
|
||||
assert!(!expando.is_null());
|
||||
|
||||
SetProxyPrivate(obj.get(), &ObjectValue(expando.get()));
|
||||
|
@ -182,9 +195,11 @@ pub unsafe fn ensure_expando_object(cx: *mut JSContext, obj: RawHandleObject, mu
|
|||
|
||||
/// Set the property descriptor's object to `obj` and set it to enumerable,
|
||||
/// and writable if `readonly` is true.
|
||||
pub fn fill_property_descriptor(mut desc: MutableHandle<PropertyDescriptor>,
|
||||
obj: *mut JSObject,
|
||||
attrs: u32) {
|
||||
pub fn fill_property_descriptor(
|
||||
mut desc: MutableHandle<PropertyDescriptor>,
|
||||
obj: *mut JSObject,
|
||||
attrs: u32,
|
||||
) {
|
||||
desc.obj = obj;
|
||||
desc.attrs = attrs;
|
||||
desc.getter = None;
|
||||
|
|
|
@ -39,9 +39,9 @@ use std::rc::Rc;
|
|||
use std::sync::{Arc, Weak};
|
||||
use task::TaskOnce;
|
||||
|
||||
|
||||
#[allow(missing_docs)] // FIXME
|
||||
mod dummy { // Attributes don’t apply through the macro.
|
||||
#[allow(missing_docs)] // FIXME
|
||||
mod dummy {
|
||||
// Attributes don’t apply through the macro.
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use super::LiveDOMReferences;
|
||||
|
@ -50,7 +50,6 @@ mod dummy { // Attributes don’t apply through the macro.
|
|||
}
|
||||
pub use self::dummy::LIVE_REFERENCES;
|
||||
|
||||
|
||||
/// A pointer to a Rust DOM object that needs to be destroyed.
|
||||
pub struct TrustedReference(*const libc::c_void);
|
||||
unsafe impl Send for TrustedReference {}
|
||||
|
@ -98,19 +97,28 @@ impl TrustedPromise {
|
|||
LIVE_REFERENCES.with(|ref r| {
|
||||
let r = r.borrow();
|
||||
let live_references = r.as_ref().unwrap();
|
||||
assert_eq!(self.owner_thread, (&*live_references) as *const _ as *const libc::c_void);
|
||||
assert_eq!(
|
||||
self.owner_thread,
|
||||
(&*live_references) as *const _ as *const libc::c_void
|
||||
);
|
||||
// Borrow-check error requires the redundant `let promise = ...; promise` here.
|
||||
let promise = match live_references.promise_table.borrow_mut().entry(self.dom_object) {
|
||||
let promise = match live_references
|
||||
.promise_table
|
||||
.borrow_mut()
|
||||
.entry(self.dom_object)
|
||||
{
|
||||
Occupied(mut entry) => {
|
||||
let promise = {
|
||||
let promises = entry.get_mut();
|
||||
promises.pop().expect("rooted promise list unexpectedly empty")
|
||||
promises
|
||||
.pop()
|
||||
.expect("rooted promise list unexpectedly empty")
|
||||
};
|
||||
if entry.get().is_empty() {
|
||||
entry.remove();
|
||||
}
|
||||
promise
|
||||
}
|
||||
},
|
||||
Vacant(_) => unreachable!(),
|
||||
};
|
||||
promise
|
||||
|
@ -182,9 +190,7 @@ impl<T: DomObject> Trusted<T> {
|
|||
let live_references = r.as_ref().unwrap();
|
||||
self.owner_thread == (&*live_references) as *const _ as *const libc::c_void
|
||||
}));
|
||||
unsafe {
|
||||
DomRoot::from_ref(&*(self.refcount.0 as *const T))
|
||||
}
|
||||
unsafe { DomRoot::from_ref(&*(self.refcount.0 as *const T)) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -246,15 +252,15 @@ impl LiveDOMReferences {
|
|||
let refcount = Arc::new(TrustedReference::new(ptr));
|
||||
entry.insert(Arc::downgrade(&refcount));
|
||||
refcount
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove null entries from the live references table
|
||||
fn remove_nulls<K: Eq + Hash + Clone, V> (table: &mut HashMap<K, Weak<V>>) {
|
||||
let to_remove: Vec<K> =
|
||||
table.iter()
|
||||
fn remove_nulls<K: Eq + Hash + Clone, V>(table: &mut HashMap<K, Weak<V>>) {
|
||||
let to_remove: Vec<K> = table
|
||||
.iter()
|
||||
.filter(|&(_, value)| Weak::upgrade(value).is_none())
|
||||
.map(|(key, _)| key.clone())
|
||||
.collect();
|
||||
|
|
|
@ -14,16 +14,16 @@ use std::default::Default;
|
|||
/// Create the reflector for a new DOM object and yield ownership to the
|
||||
/// reflector.
|
||||
pub fn reflect_dom_object<T, U>(
|
||||
obj: Box<T>,
|
||||
global: &U,
|
||||
wrap_fn: unsafe fn(*mut JSContext, &GlobalScope, Box<T>) -> DomRoot<T>)
|
||||
-> DomRoot<T>
|
||||
where T: DomObject, U: DerivedFrom<GlobalScope>
|
||||
obj: Box<T>,
|
||||
global: &U,
|
||||
wrap_fn: unsafe fn(*mut JSContext, &GlobalScope, Box<T>) -> DomRoot<T>,
|
||||
) -> DomRoot<T>
|
||||
where
|
||||
T: DomObject,
|
||||
U: DerivedFrom<GlobalScope>,
|
||||
{
|
||||
let global_scope = global.upcast();
|
||||
unsafe {
|
||||
wrap_fn(global_scope.get_cx(), global_scope, obj)
|
||||
}
|
||||
unsafe { wrap_fn(global_scope.get_cx(), global_scope, obj) }
|
||||
}
|
||||
|
||||
/// A struct to store a reference to the reflector of a DOM object.
|
||||
|
@ -79,7 +79,10 @@ pub trait DomObject: 'static {
|
|||
fn reflector(&self) -> &Reflector;
|
||||
|
||||
/// Returns the global scope of the realm that the DomObject was created in.
|
||||
fn global(&self) -> DomRoot<GlobalScope> where Self: Sized {
|
||||
fn global(&self) -> DomRoot<GlobalScope>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
GlobalScope::from_reflector(self)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,9 +96,7 @@ where
|
|||
trace_reflector(tracer, "on stack", &self.0);
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
&*(self.reflector() as *const Reflector as *const ReflectorStackRoot)
|
||||
}
|
||||
unsafe { &*(self.reflector() as *const Reflector as *const ReflectorStackRoot) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,15 +129,17 @@ pub type DomRoot<T> = Root<Dom<T>>;
|
|||
impl<T: Castable> DomRoot<T> {
|
||||
/// Cast a DOM object root upwards to one of the interfaces it derives from.
|
||||
pub fn upcast<U>(root: DomRoot<T>) -> DomRoot<U>
|
||||
where U: Castable,
|
||||
T: DerivedFrom<U>
|
||||
where
|
||||
U: Castable,
|
||||
T: DerivedFrom<U>,
|
||||
{
|
||||
unsafe { mem::transmute(root) }
|
||||
}
|
||||
|
||||
/// Cast a DOM object root downwards to one of the interfaces it might implement.
|
||||
pub fn downcast<U>(root: DomRoot<T>) -> Option<DomRoot<U>>
|
||||
where U: DerivedFrom<T>
|
||||
where
|
||||
U: DerivedFrom<T>,
|
||||
{
|
||||
if root.is::<U>() {
|
||||
Some(unsafe { mem::transmute(root) })
|
||||
|
@ -207,9 +207,7 @@ pub struct ThreadLocalStackRoots<'a>(PhantomData<&'a u32>);
|
|||
|
||||
impl<'a> ThreadLocalStackRoots<'a> {
|
||||
pub fn new(roots: &'a RootCollection) -> Self {
|
||||
STACK_ROOTS.with(|ref r| {
|
||||
r.set(Some(roots))
|
||||
});
|
||||
STACK_ROOTS.with(|ref r| r.set(Some(roots)));
|
||||
ThreadLocalStackRoots(PhantomData)
|
||||
}
|
||||
}
|
||||
|
@ -363,9 +361,7 @@ unsafe impl<T: DomObject> JSTraceable for Dom<T> {
|
|||
#[cfg(not(all(feature = "unstable", debug_assertions)))]
|
||||
let trace_info = "for DOM object on heap";
|
||||
|
||||
trace_reflector(trc,
|
||||
trace_info,
|
||||
(*self.ptr.as_ptr()).reflector());
|
||||
trace_reflector(trc, trace_info, (*self.ptr.as_ptr()).reflector());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -379,8 +375,9 @@ pub struct LayoutDom<T> {
|
|||
impl<T: Castable> LayoutDom<T> {
|
||||
/// Cast a DOM object root upwards to one of the interfaces it derives from.
|
||||
pub fn upcast<U>(&self) -> LayoutDom<U>
|
||||
where U: Castable,
|
||||
T: DerivedFrom<U>
|
||||
where
|
||||
U: Castable,
|
||||
T: DerivedFrom<U>,
|
||||
{
|
||||
debug_assert!(thread_state::get().is_layout());
|
||||
let ptr: *mut T = self.ptr.as_ptr();
|
||||
|
@ -391,7 +388,8 @@ impl<T: Castable> LayoutDom<T> {
|
|||
|
||||
/// Cast a DOM object downwards to one of the interfaces it might implement.
|
||||
pub fn downcast<U>(&self) -> Option<LayoutDom<U>>
|
||||
where U: DerivedFrom<T>
|
||||
where
|
||||
U: DerivedFrom<T>,
|
||||
{
|
||||
debug_assert!(thread_state::get().is_layout());
|
||||
unsafe {
|
||||
|
@ -429,7 +427,6 @@ impl<'a, T: DomObject> PartialEq<&'a T> for Dom<T> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
impl<T> Eq for Dom<T> {}
|
||||
|
||||
impl<T> PartialEq for LayoutDom<T> {
|
||||
|
@ -452,7 +449,7 @@ impl<T> Hash for LayoutDom<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl <T> Clone for Dom<T> {
|
||||
impl<T> Clone for Dom<T> {
|
||||
#[inline]
|
||||
#[allow(unrooted_must_root)]
|
||||
fn clone(&self) -> Dom<T> {
|
||||
|
@ -463,7 +460,7 @@ impl <T> Clone for Dom<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl <T> Clone for LayoutDom<T> {
|
||||
impl<T> Clone for LayoutDom<T> {
|
||||
#[inline]
|
||||
fn clone(&self) -> LayoutDom<T> {
|
||||
debug_assert!(thread_state::get().is_layout());
|
||||
|
@ -516,9 +513,7 @@ impl<T: DomObject> MutDom<T> {
|
|||
/// Get the value in this `MutDom`.
|
||||
pub fn get(&self) -> DomRoot<T> {
|
||||
debug_assert!(thread_state::get().is_script());
|
||||
unsafe {
|
||||
DomRoot::from_ref(&*ptr::read(self.val.get()))
|
||||
}
|
||||
unsafe { DomRoot::from_ref(&*ptr::read(self.val.get())) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -530,18 +525,14 @@ impl<T: DomObject> MallocSizeOf for MutDom<T> {
|
|||
}
|
||||
|
||||
impl<T: DomObject> PartialEq for MutDom<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
unsafe {
|
||||
*self.val.get() == *other.val.get()
|
||||
}
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
unsafe { *self.val.get() == *other.val.get() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: DomObject + PartialEq> PartialEq<T> for MutDom<T> {
|
||||
fn eq(&self, other: &T) -> bool {
|
||||
unsafe {
|
||||
**self.val.get() == *other
|
||||
}
|
||||
unsafe { **self.val.get() == *other }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -569,7 +560,8 @@ impl<T: DomObject> MutNullableDom<T> {
|
|||
/// Retrieve a copy of the current inner value. If it is `None`, it is
|
||||
/// initialized with the result of `cb` first.
|
||||
pub fn or_init<F>(&self, cb: F) -> DomRoot<T>
|
||||
where F: FnOnce() -> DomRoot<T>
|
||||
where
|
||||
F: FnOnce() -> DomRoot<T>,
|
||||
{
|
||||
debug_assert!(thread_state::get().is_script());
|
||||
match self.get() {
|
||||
|
@ -594,9 +586,7 @@ impl<T: DomObject> MutNullableDom<T> {
|
|||
#[allow(unrooted_must_root)]
|
||||
pub fn get(&self) -> Option<DomRoot<T>> {
|
||||
debug_assert!(thread_state::get().is_script());
|
||||
unsafe {
|
||||
ptr::read(self.ptr.get()).map(|o| DomRoot::from_ref(&*o))
|
||||
}
|
||||
unsafe { ptr::read(self.ptr.get()).map(|o| DomRoot::from_ref(&*o)) }
|
||||
}
|
||||
|
||||
/// Set this `MutNullableDom` to the given value.
|
||||
|
@ -617,17 +607,13 @@ impl<T: DomObject> MutNullableDom<T> {
|
|||
|
||||
impl<T: DomObject> PartialEq for MutNullableDom<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
unsafe {
|
||||
*self.ptr.get() == *other.ptr.get()
|
||||
}
|
||||
unsafe { *self.ptr.get() == *other.ptr.get() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: DomObject> PartialEq<Option<&'a T>> for MutNullableDom<T> {
|
||||
fn eq(&self, other: &Option<&T>) -> bool {
|
||||
unsafe {
|
||||
*self.ptr.get() == other.map(Dom::from_ref)
|
||||
}
|
||||
unsafe { *self.ptr.get() == other.map(Dom::from_ref) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -661,13 +647,14 @@ pub struct DomOnceCell<T: DomObject> {
|
|||
|
||||
impl<T> DomOnceCell<T>
|
||||
where
|
||||
T: DomObject
|
||||
T: DomObject,
|
||||
{
|
||||
/// Retrieve a copy of the current inner value. If it is `None`, it is
|
||||
/// initialized with the result of `cb` first.
|
||||
#[allow(unrooted_must_root)]
|
||||
pub fn init_once<F>(&self, cb: F) -> &T
|
||||
where F: FnOnce() -> DomRoot<T>
|
||||
where
|
||||
F: FnOnce() -> DomRoot<T>,
|
||||
{
|
||||
debug_assert!(thread_state::get().is_script());
|
||||
&self.ptr.init_once(|| Dom::from_ref(&cb()))
|
||||
|
@ -725,14 +712,17 @@ pub trait OptionalHeapSetter {
|
|||
fn set(&mut self, v: Option<Self::Value>);
|
||||
}
|
||||
|
||||
impl<T: GCMethods + Copy> OptionalHeapSetter for Option<Heap<T>> where Heap<T>: Default {
|
||||
impl<T: GCMethods + Copy> OptionalHeapSetter for Option<Heap<T>>
|
||||
where
|
||||
Heap<T>: Default,
|
||||
{
|
||||
type Value = T;
|
||||
fn set(&mut self, v: Option<T>) {
|
||||
let v = match v {
|
||||
None => {
|
||||
*self = None;
|
||||
return;
|
||||
}
|
||||
},
|
||||
Some(v) => v,
|
||||
};
|
||||
|
||||
|
|
|
@ -36,9 +36,7 @@ pub unsafe fn trace(tracer: *mut JSTracer) {
|
|||
}
|
||||
|
||||
pub fn is_execution_stack_empty() -> bool {
|
||||
STACK.with(|stack| {
|
||||
stack.borrow().is_empty()
|
||||
})
|
||||
STACK.with(|stack| stack.borrow().is_empty())
|
||||
}
|
||||
|
||||
/// RAII struct that pushes and pops entries from the script settings stack.
|
||||
|
@ -69,9 +67,10 @@ impl Drop for AutoEntryScript {
|
|||
STACK.with(|stack| {
|
||||
let mut stack = stack.borrow_mut();
|
||||
let entry = stack.pop().unwrap();
|
||||
assert_eq!(&*entry.global as *const GlobalScope,
|
||||
&*self.global as *const GlobalScope,
|
||||
"Dropped AutoEntryScript out of order.");
|
||||
assert_eq!(
|
||||
&*entry.global as *const GlobalScope, &*self.global as *const GlobalScope,
|
||||
"Dropped AutoEntryScript out of order."
|
||||
);
|
||||
assert_eq!(entry.kind, StackEntryKind::Entry);
|
||||
trace!("Clean up after running script with {:p}", &*entry.global);
|
||||
});
|
||||
|
@ -87,13 +86,15 @@ impl Drop for AutoEntryScript {
|
|||
///
|
||||
/// ["entry"]: https://html.spec.whatwg.org/multipage/#entry
|
||||
pub fn entry_global() -> DomRoot<GlobalScope> {
|
||||
STACK.with(|stack| {
|
||||
stack.borrow()
|
||||
.iter()
|
||||
.rev()
|
||||
.find(|entry| entry.kind == StackEntryKind::Entry)
|
||||
.map(|entry| DomRoot::from_ref(&*entry.global))
|
||||
}).unwrap()
|
||||
STACK
|
||||
.with(|stack| {
|
||||
stack
|
||||
.borrow()
|
||||
.iter()
|
||||
.rev()
|
||||
.find(|entry| entry.kind == StackEntryKind::Entry)
|
||||
.map(|entry| DomRoot::from_ref(&*entry.global))
|
||||
}).unwrap()
|
||||
}
|
||||
|
||||
/// RAII struct that pushes and pops entries from the script settings stack.
|
||||
|
@ -133,11 +134,15 @@ impl Drop for AutoIncumbentScript {
|
|||
let mut stack = stack.borrow_mut();
|
||||
let entry = stack.pop().unwrap();
|
||||
// Step 3.
|
||||
assert_eq!(&*entry.global as *const GlobalScope as usize,
|
||||
self.global,
|
||||
"Dropped AutoIncumbentScript out of order.");
|
||||
assert_eq!(
|
||||
&*entry.global as *const GlobalScope as usize, self.global,
|
||||
"Dropped AutoIncumbentScript out of order."
|
||||
);
|
||||
assert_eq!(entry.kind, StackEntryKind::Incumbent);
|
||||
trace!("Clean up after running a callback with {:p}", &*entry.global);
|
||||
trace!(
|
||||
"Clean up after running a callback with {:p}",
|
||||
&*entry.global
|
||||
);
|
||||
});
|
||||
unsafe {
|
||||
// Step 1-2.
|
||||
|
@ -169,8 +174,9 @@ pub fn incumbent_global() -> Option<DomRoot<GlobalScope>> {
|
|||
|
||||
// Step 2: nothing from the JS engine. Let's use whatever's on the explicit stack.
|
||||
STACK.with(|stack| {
|
||||
stack.borrow()
|
||||
.last()
|
||||
.map(|entry| DomRoot::from_ref(&*entry.global))
|
||||
stack
|
||||
.borrow()
|
||||
.last()
|
||||
.map(|entry| DomRoot::from_ref(&*entry.global))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -82,7 +82,6 @@ impl ops::Deref for ByteString {
|
|||
#[derive(Clone, Default, MallocSizeOf)]
|
||||
pub struct USVString(pub String);
|
||||
|
||||
|
||||
/// Returns whether `s` is a `token`, as defined by
|
||||
/// [RFC 2616](http://tools.ietf.org/html/rfc2616#page-17).
|
||||
pub fn is_token(s: &[u8]) -> bool {
|
||||
|
@ -93,31 +92,14 @@ pub fn is_token(s: &[u8]) -> bool {
|
|||
// http://tools.ietf.org/html/rfc2616#section-2.2
|
||||
match x {
|
||||
0...31 | 127 => false, // CTLs
|
||||
40 |
|
||||
41 |
|
||||
60 |
|
||||
62 |
|
||||
64 |
|
||||
44 |
|
||||
59 |
|
||||
58 |
|
||||
92 |
|
||||
34 |
|
||||
47 |
|
||||
91 |
|
||||
93 |
|
||||
63 |
|
||||
61 |
|
||||
123 |
|
||||
125 |
|
||||
32 => false, // separators
|
||||
40 | 41 | 60 | 62 | 64 | 44 | 59 | 58 | 92 | 34 | 47 | 91 | 93 | 63 | 61 | 123 |
|
||||
125 | 32 => false, // separators
|
||||
x if x > 127 => false, // non-CHARs
|
||||
_ => true,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/// A DOMString.
|
||||
///
|
||||
/// This type corresponds to the [`DOMString`](idl) type in WebIDL.
|
||||
|
@ -196,14 +178,16 @@ impl DOMString {
|
|||
/// Removes leading and trailing ASCII whitespaces according to
|
||||
/// <https://infra.spec.whatwg.org/#strip-leading-and-trailing-ascii-whitespace>.
|
||||
pub fn strip_leading_and_trailing_ascii_whitespace(&mut self) {
|
||||
if self.0.len() == 0 { return; }
|
||||
if self.0.len() == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
let last_non_whitespace = match self.0.rfind(|ref c| !char::is_ascii_whitespace(c)) {
|
||||
Some(idx) => idx + 1,
|
||||
None => {
|
||||
self.0.clear();
|
||||
return;
|
||||
}
|
||||
},
|
||||
};
|
||||
let first_non_whitespace = self.0.find(|ref c| !char::is_ascii_whitespace(c)).unwrap();
|
||||
|
||||
|
@ -231,17 +215,21 @@ impl DOMString {
|
|||
Done,
|
||||
Error,
|
||||
}
|
||||
let next_state = |valid: bool, next: State| -> State { if valid { next } else { State::Error } };
|
||||
let next_state = |valid: bool, next: State| -> State {
|
||||
if valid {
|
||||
next
|
||||
} else {
|
||||
State::Error
|
||||
}
|
||||
};
|
||||
|
||||
let state = self.chars().fold(State::HourHigh, |state, c| {
|
||||
match state {
|
||||
// Step 1 "HH"
|
||||
State::HourHigh => {
|
||||
match c {
|
||||
'0' | '1' => State::HourLow09,
|
||||
'2' => State::HourLow03,
|
||||
_ => State::Error,
|
||||
}
|
||||
State::HourHigh => match c {
|
||||
'0' | '1' => State::HourLow09,
|
||||
'2' => State::HourLow03,
|
||||
_ => State::Error,
|
||||
},
|
||||
State::HourLow09 => next_state(c.is_digit(10), State::MinuteColon),
|
||||
State::HourLow03 => next_state(c.is_digit(4), State::MinuteColon),
|
||||
|
@ -323,15 +311,21 @@ impl DOMString {
|
|||
/// where date and time are both valid, and the time string must be as short as possible
|
||||
/// https://html.spec.whatwg.org/multipage/#valid-normalised-local-date-and-time-string
|
||||
pub fn convert_valid_normalized_local_date_and_time_string(&mut self) -> Result<(), ()> {
|
||||
let ((year, month, day), (hour, minute, second)) = parse_local_date_and_time_string(&*self.0)?;
|
||||
let ((year, month, day), (hour, minute, second)) =
|
||||
parse_local_date_and_time_string(&*self.0)?;
|
||||
if second == 0.0 {
|
||||
self.0 = format!("{:04}-{:02}-{:02}T{:02}:{:02}", year, month, day, hour, minute);
|
||||
self.0 = format!(
|
||||
"{:04}-{:02}-{:02}T{:02}:{:02}",
|
||||
year, month, day, hour, minute
|
||||
);
|
||||
} else {
|
||||
self.0 = format!("{:04}-{:02}-{:02}T{:02}:{:02}:{}", year, month, day, hour, minute, second);
|
||||
self.0 = format!(
|
||||
"{:04}-{:02}-{:02}T{:02}:{:02}:{}",
|
||||
year, month, day, hour, minute, second
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl Borrow<str> for DOMString {
|
||||
|
@ -452,7 +446,10 @@ impl<'a> Into<CowRcStr<'a>> for DOMString {
|
|||
}
|
||||
|
||||
impl Extend<char> for DOMString {
|
||||
fn extend<I>(&mut self, iterable: I) where I: IntoIterator<Item=char> {
|
||||
fn extend<I>(&mut self, iterable: I)
|
||||
where
|
||||
I: IntoIterator<Item = char>,
|
||||
{
|
||||
self.0.extend(iterable)
|
||||
}
|
||||
}
|
||||
|
@ -541,7 +538,7 @@ fn parse_month_component(value: &str) -> Result<(u32, u32), ()> {
|
|||
|
||||
// Step 4, 5
|
||||
let month_int = month.parse::<u32>().map_err(|_| ())?;
|
||||
if month.len() != 2 || month_int > 12 || month_int < 1 {
|
||||
if month.len() != 2 || month_int > 12 || month_int < 1 {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
|
@ -611,12 +608,12 @@ fn parse_time_component(value: &str) -> Result<(u32, u32, f32), ()> {
|
|||
return Err(());
|
||||
}
|
||||
},
|
||||
None => {}
|
||||
None => {},
|
||||
}
|
||||
|
||||
second.parse::<f32>().map_err(|_| ())?
|
||||
},
|
||||
None => 0.0
|
||||
None => 0.0,
|
||||
};
|
||||
|
||||
// Step 8
|
||||
|
@ -624,7 +621,7 @@ fn parse_time_component(value: &str) -> Result<(u32, u32, f32), ()> {
|
|||
}
|
||||
|
||||
/// https://html.spec.whatwg.org/multipage/#parse-a-local-date-and-time-string
|
||||
fn parse_local_date_and_time_string(value: &str) -> Result<((u32, u32, u32), (u32, u32, f32)), ()> {
|
||||
fn parse_local_date_and_time_string(value: &str) -> Result<((u32, u32, u32), (u32, u32, f32)), ()> {
|
||||
// Step 1, 2, 4
|
||||
let mut iterator = if value.contains('T') {
|
||||
value.split('T')
|
||||
|
@ -651,8 +648,8 @@ fn parse_local_date_and_time_string(value: &str) -> Result<((u32, u32, u32), (u
|
|||
|
||||
fn max_day_in_month(year_num: u32, month_num: u32) -> Result<u32, ()> {
|
||||
match month_num {
|
||||
1|3|5|7|8|10|12 => Ok(31),
|
||||
4|6|9|11 => Ok(30),
|
||||
1 | 3 | 5 | 7 | 8 | 10 | 12 => Ok(31),
|
||||
4 | 6 | 9 | 11 => Ok(30),
|
||||
2 => {
|
||||
if is_leap_year(year_num) {
|
||||
Ok(29)
|
||||
|
@ -660,7 +657,7 @@ fn max_day_in_month(year_num: u32, month_num: u32) -> Result<u32, ()> {
|
|||
Ok(28)
|
||||
}
|
||||
},
|
||||
_ => Err(())
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -669,7 +666,7 @@ fn max_week_in_year(year: u32) -> u32 {
|
|||
match Utc.ymd(year as i32, 1, 1).weekday() {
|
||||
Weekday::Thu => 53,
|
||||
Weekday::Wed if is_leap_year(year) => 53,
|
||||
_ => 52
|
||||
_ => 52,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -681,14 +678,16 @@ fn is_leap_year(year: u32) -> bool {
|
|||
/// https://html.spec.whatwg.org/multipage/#rules-for-parsing-floating-point-number-values
|
||||
fn parse_floating_point_number(input: &str) -> Result<f64, ()> {
|
||||
match input.trim().parse::<f64>() {
|
||||
Ok(val) if !(
|
||||
Ok(val)
|
||||
if !(
|
||||
// A valid number is the same as what rust considers to be valid,
|
||||
// except for +1., NaN, and Infinity.
|
||||
val.is_infinite() || val.is_nan() || input.ends_with(".") || input.starts_with("+")
|
||||
) => {
|
||||
) =>
|
||||
{
|
||||
// TODO(#19773): need consider `min`, `max`, `step`, when they are implemented
|
||||
Ok(val.round())
|
||||
},
|
||||
_ => Err(())
|
||||
}
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,35 +47,39 @@ enum StructuredCloneTags {
|
|||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
unsafe fn write_length(w: *mut JSStructuredCloneWriter,
|
||||
length: usize) {
|
||||
let high: u32 = (length >> 32) as u32;
|
||||
let low: u32 = length as u32;
|
||||
assert!(JS_WriteUint32Pair(w, high, low));
|
||||
unsafe fn write_length(w: *mut JSStructuredCloneWriter, length: usize) {
|
||||
let high: u32 = (length >> 32) as u32;
|
||||
let low: u32 = length as u32;
|
||||
assert!(JS_WriteUint32Pair(w, high, low));
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
unsafe fn write_length(w: *mut JSStructuredCloneWriter,
|
||||
length: usize) {
|
||||
assert!(JS_WriteUint32Pair(w, length as u32, 0));
|
||||
unsafe fn write_length(w: *mut JSStructuredCloneWriter, length: usize) {
|
||||
assert!(JS_WriteUint32Pair(w, length as u32, 0));
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
unsafe fn read_length(r: *mut JSStructuredCloneReader)
|
||||
-> usize {
|
||||
let mut high: u32 = 0;
|
||||
let mut low: u32 = 0;
|
||||
assert!(JS_ReadUint32Pair(r, &mut high as *mut u32, &mut low as *mut u32));
|
||||
return (low << high) as usize;
|
||||
unsafe fn read_length(r: *mut JSStructuredCloneReader) -> usize {
|
||||
let mut high: u32 = 0;
|
||||
let mut low: u32 = 0;
|
||||
assert!(JS_ReadUint32Pair(
|
||||
r,
|
||||
&mut high as *mut u32,
|
||||
&mut low as *mut u32
|
||||
));
|
||||
return (low << high) as usize;
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
unsafe fn read_length(r: *mut JSStructuredCloneReader)
|
||||
-> usize {
|
||||
let mut length: u32 = 0;
|
||||
let mut zero: u32 = 0;
|
||||
assert!(JS_ReadUint32Pair(r, &mut length as *mut u32, &mut zero as *mut u32));
|
||||
return length as usize;
|
||||
unsafe fn read_length(r: *mut JSStructuredCloneReader) -> usize {
|
||||
let mut length: u32 = 0;
|
||||
let mut zero: u32 = 0;
|
||||
assert!(JS_ReadUint32Pair(
|
||||
r,
|
||||
&mut length as *mut u32,
|
||||
&mut zero as *mut u32
|
||||
));
|
||||
return length as usize;
|
||||
}
|
||||
|
||||
struct StructuredCloneWriter {
|
||||
|
@ -86,7 +90,11 @@ impl StructuredCloneWriter {
|
|||
unsafe fn write_slice(&self, v: &[u8]) {
|
||||
let type_length = v.len();
|
||||
write_length(self.w, type_length);
|
||||
assert!(JS_WriteBytes(self.w, v.as_ptr() as *const raw::c_void, type_length));
|
||||
assert!(JS_WriteBytes(
|
||||
self.w,
|
||||
v.as_ptr() as *const raw::c_void,
|
||||
type_length
|
||||
));
|
||||
}
|
||||
unsafe fn write_str(&self, s: &str) {
|
||||
self.write_slice(s.as_bytes());
|
||||
|
@ -101,7 +109,11 @@ impl StructuredCloneReader {
|
|||
unsafe fn read_bytes(&self) -> Vec<u8> {
|
||||
let mut bytes = vec![0u8; read_length(self.r)];
|
||||
let blob_length = bytes.len();
|
||||
assert!(JS_ReadBytes(self.r, bytes.as_mut_ptr() as *mut raw::c_void, blob_length));
|
||||
assert!(JS_ReadBytes(
|
||||
self.r,
|
||||
bytes.as_mut_ptr() as *mut raw::c_void,
|
||||
blob_length
|
||||
));
|
||||
return bytes;
|
||||
}
|
||||
unsafe fn read_str(&self) -> String {
|
||||
|
@ -110,87 +122,105 @@ impl StructuredCloneReader {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe fn read_blob(cx: *mut JSContext,
|
||||
r: *mut JSStructuredCloneReader,
|
||||
sc_holder: &mut StructuredCloneHolder)
|
||||
-> *mut JSObject {
|
||||
unsafe fn read_blob(
|
||||
cx: *mut JSContext,
|
||||
r: *mut JSStructuredCloneReader,
|
||||
sc_holder: &mut StructuredCloneHolder,
|
||||
) -> *mut JSObject {
|
||||
let structured_reader = StructuredCloneReader { r: r };
|
||||
let blob_buffer = structured_reader.read_bytes();
|
||||
let type_str = structured_reader.read_str();
|
||||
let target_global = GlobalScope::from_context(cx);
|
||||
let blob = Blob::new(&target_global, BlobImpl::new_from_bytes(blob_buffer), type_str);
|
||||
let blob = Blob::new(
|
||||
&target_global,
|
||||
BlobImpl::new_from_bytes(blob_buffer),
|
||||
type_str,
|
||||
);
|
||||
let js_object = blob.reflector().get_jsobject().get();
|
||||
sc_holder.blob = Some(blob);
|
||||
js_object
|
||||
}
|
||||
|
||||
unsafe fn write_blob(blob: DomRoot<Blob>,
|
||||
w: *mut JSStructuredCloneWriter)
|
||||
-> Result<(), ()> {
|
||||
unsafe fn write_blob(blob: DomRoot<Blob>, w: *mut JSStructuredCloneWriter) -> Result<(), ()> {
|
||||
let structured_writer = StructuredCloneWriter { w: w };
|
||||
let blob_vec = blob.get_bytes()?;
|
||||
assert!(JS_WriteUint32Pair(w, StructuredCloneTags::DomBlob as u32, 0));
|
||||
assert!(JS_WriteUint32Pair(
|
||||
w,
|
||||
StructuredCloneTags::DomBlob as u32,
|
||||
0
|
||||
));
|
||||
structured_writer.write_slice(&blob_vec);
|
||||
structured_writer.write_str(&blob.type_string());
|
||||
return Ok(())
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
unsafe extern "C" fn read_callback(cx: *mut JSContext,
|
||||
r: *mut JSStructuredCloneReader,
|
||||
tag: u32,
|
||||
_data: u32,
|
||||
closure: *mut raw::c_void)
|
||||
-> *mut JSObject {
|
||||
assert!(tag < StructuredCloneTags::Max as u32, "tag should be lower than StructuredCloneTags::Max");
|
||||
assert!(tag > StructuredCloneTags::Min as u32, "tag should be higher than StructuredCloneTags::Min");
|
||||
unsafe extern "C" fn read_callback(
|
||||
cx: *mut JSContext,
|
||||
r: *mut JSStructuredCloneReader,
|
||||
tag: u32,
|
||||
_data: u32,
|
||||
closure: *mut raw::c_void,
|
||||
) -> *mut JSObject {
|
||||
assert!(
|
||||
tag < StructuredCloneTags::Max as u32,
|
||||
"tag should be lower than StructuredCloneTags::Max"
|
||||
);
|
||||
assert!(
|
||||
tag > StructuredCloneTags::Min as u32,
|
||||
"tag should be higher than StructuredCloneTags::Min"
|
||||
);
|
||||
if tag == StructuredCloneTags::DomBlob as u32 {
|
||||
return read_blob(cx, r, &mut *(closure as *mut StructuredCloneHolder))
|
||||
return read_blob(cx, r, &mut *(closure as *mut StructuredCloneHolder));
|
||||
}
|
||||
return ptr::null_mut()
|
||||
return ptr::null_mut();
|
||||
}
|
||||
|
||||
unsafe extern "C" fn write_callback(_cx: *mut JSContext,
|
||||
w: *mut JSStructuredCloneWriter,
|
||||
obj: RawHandleObject,
|
||||
_closure: *mut raw::c_void)
|
||||
-> bool {
|
||||
unsafe extern "C" fn write_callback(
|
||||
_cx: *mut JSContext,
|
||||
w: *mut JSStructuredCloneWriter,
|
||||
obj: RawHandleObject,
|
||||
_closure: *mut raw::c_void,
|
||||
) -> bool {
|
||||
if let Ok(blob) = root_from_handleobject::<Blob>(Handle::from_raw(obj)) {
|
||||
return write_blob(blob, w).is_ok()
|
||||
return write_blob(blob, w).is_ok();
|
||||
}
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
|
||||
unsafe extern "C" fn read_transfer_callback(_cx: *mut JSContext,
|
||||
_r: *mut JSStructuredCloneReader,
|
||||
_tag: u32,
|
||||
_content: *mut raw::c_void,
|
||||
_extra_data: u64,
|
||||
_closure: *mut raw::c_void,
|
||||
_return_object: RawMutableHandleObject)
|
||||
-> bool {
|
||||
unsafe extern "C" fn read_transfer_callback(
|
||||
_cx: *mut JSContext,
|
||||
_r: *mut JSStructuredCloneReader,
|
||||
_tag: u32,
|
||||
_content: *mut raw::c_void,
|
||||
_extra_data: u64,
|
||||
_closure: *mut raw::c_void,
|
||||
_return_object: RawMutableHandleObject,
|
||||
) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
unsafe extern "C" fn write_transfer_callback(_cx: *mut JSContext,
|
||||
_obj: RawHandleObject,
|
||||
_closure: *mut raw::c_void,
|
||||
_tag: *mut u32,
|
||||
_ownership: *mut TransferableOwnership,
|
||||
_content: *mut *mut raw::c_void,
|
||||
_extra_data: *mut u64)
|
||||
-> bool {
|
||||
unsafe extern "C" fn write_transfer_callback(
|
||||
_cx: *mut JSContext,
|
||||
_obj: RawHandleObject,
|
||||
_closure: *mut raw::c_void,
|
||||
_tag: *mut u32,
|
||||
_ownership: *mut TransferableOwnership,
|
||||
_content: *mut *mut raw::c_void,
|
||||
_extra_data: *mut u64,
|
||||
) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
unsafe extern "C" fn free_transfer_callback(_tag: u32,
|
||||
_ownership: TransferableOwnership,
|
||||
_content: *mut raw::c_void,
|
||||
_extra_data: u64,
|
||||
_closure: *mut raw::c_void) {
|
||||
unsafe extern "C" fn free_transfer_callback(
|
||||
_tag: u32,
|
||||
_ownership: TransferableOwnership,
|
||||
_content: *mut raw::c_void,
|
||||
_extra_data: u64,
|
||||
_closure: *mut raw::c_void,
|
||||
) {
|
||||
}
|
||||
|
||||
unsafe extern "C" fn report_error_callback(_cx: *mut JSContext, _errorid: u32) {
|
||||
}
|
||||
unsafe extern "C" fn report_error_callback(_cx: *mut JSContext, _errorid: u32) {}
|
||||
|
||||
static STRUCTURED_CLONE_CALLBACKS: JSStructuredCloneCallbacks = JSStructuredCloneCallbacks {
|
||||
read: Some(read_callback),
|
||||
|
@ -202,7 +232,7 @@ static STRUCTURED_CLONE_CALLBACKS: JSStructuredCloneCallbacks = JSStructuredClon
|
|||
};
|
||||
|
||||
struct StructuredCloneHolder {
|
||||
blob: Option<DomRoot<Blob>>
|
||||
blob: Option<DomRoot<Blob>>,
|
||||
}
|
||||
|
||||
/// A buffer for a structured clone.
|
||||
|
@ -210,7 +240,7 @@ pub enum StructuredCloneData {
|
|||
/// A non-serializable (default) variant
|
||||
Struct(*mut u64, size_t),
|
||||
/// A variant that can be serialized
|
||||
Vector(Vec<u8>)
|
||||
Vector(Vec<u8>),
|
||||
}
|
||||
|
||||
impl StructuredCloneData {
|
||||
|
@ -218,21 +248,25 @@ impl StructuredCloneData {
|
|||
/// Writes a structured clone. Returns a `DataClone` error if that fails.
|
||||
pub fn write(cx: *mut JSContext, message: HandleValue) -> Fallible<StructuredCloneData> {
|
||||
unsafe {
|
||||
let scbuf = NewJSAutoStructuredCloneBuffer(StructuredCloneScope::DifferentProcess,
|
||||
&STRUCTURED_CLONE_CALLBACKS);
|
||||
let scbuf = NewJSAutoStructuredCloneBuffer(
|
||||
StructuredCloneScope::DifferentProcess,
|
||||
&STRUCTURED_CLONE_CALLBACKS,
|
||||
);
|
||||
let scdata = &mut ((*scbuf).data_);
|
||||
let policy = CloneDataPolicy {
|
||||
// TODO: SAB?
|
||||
sharedArrayBuffer_: false,
|
||||
};
|
||||
let result = JS_WriteStructuredClone(cx,
|
||||
message,
|
||||
scdata,
|
||||
StructuredCloneScope::DifferentProcess,
|
||||
policy,
|
||||
&STRUCTURED_CLONE_CALLBACKS,
|
||||
ptr::null_mut(),
|
||||
HandleValue::undefined());
|
||||
let result = JS_WriteStructuredClone(
|
||||
cx,
|
||||
message,
|
||||
scdata,
|
||||
StructuredCloneScope::DifferentProcess,
|
||||
policy,
|
||||
&STRUCTURED_CLONE_CALLBACKS,
|
||||
ptr::null_mut(),
|
||||
HandleValue::undefined(),
|
||||
);
|
||||
if !result {
|
||||
JS_ClearPendingException(cx);
|
||||
return Err(Error::DataClone);
|
||||
|
@ -252,41 +286,40 @@ impl StructuredCloneData {
|
|||
/// Converts a StructuredCloneData to Vec<u8> for inter-thread sharing
|
||||
pub fn move_to_arraybuffer(self) -> Vec<u8> {
|
||||
match self {
|
||||
StructuredCloneData::Struct(data, nbytes) => {
|
||||
unsafe {
|
||||
slice::from_raw_parts(data as *mut u8, nbytes).to_vec()
|
||||
}
|
||||
}
|
||||
StructuredCloneData::Vector(msg) => msg
|
||||
StructuredCloneData::Struct(data, nbytes) => unsafe {
|
||||
slice::from_raw_parts(data as *mut u8, nbytes).to_vec()
|
||||
},
|
||||
StructuredCloneData::Vector(msg) => msg,
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads a structured clone.
|
||||
///
|
||||
/// Panics if `JS_ReadStructuredClone` fails.
|
||||
fn read_clone(global: &GlobalScope,
|
||||
data: *mut u64,
|
||||
nbytes: size_t,
|
||||
rval: MutableHandleValue) {
|
||||
fn read_clone(global: &GlobalScope, data: *mut u64, nbytes: size_t, rval: MutableHandleValue) {
|
||||
let cx = global.get_cx();
|
||||
let globalhandle = global.reflector().get_jsobject();
|
||||
let _ac = JSAutoCompartment::new(cx, globalhandle.get());
|
||||
let mut sc_holder = StructuredCloneHolder { blob: None };
|
||||
let sc_holder_ptr = &mut sc_holder as *mut _;
|
||||
unsafe {
|
||||
let scbuf = NewJSAutoStructuredCloneBuffer(StructuredCloneScope::DifferentProcess,
|
||||
&STRUCTURED_CLONE_CALLBACKS);
|
||||
let scbuf = NewJSAutoStructuredCloneBuffer(
|
||||
StructuredCloneScope::DifferentProcess,
|
||||
&STRUCTURED_CLONE_CALLBACKS,
|
||||
);
|
||||
let scdata = &mut ((*scbuf).data_);
|
||||
|
||||
WriteBytesToJSStructuredCloneData(data as *const u8, nbytes, scdata);
|
||||
|
||||
assert!(JS_ReadStructuredClone(cx,
|
||||
scdata,
|
||||
JS_STRUCTURED_CLONE_VERSION,
|
||||
StructuredCloneScope::DifferentProcess,
|
||||
rval,
|
||||
&STRUCTURED_CLONE_CALLBACKS,
|
||||
sc_holder_ptr as *mut raw::c_void));
|
||||
assert!(JS_ReadStructuredClone(
|
||||
cx,
|
||||
scdata,
|
||||
JS_STRUCTURED_CLONE_VERSION,
|
||||
StructuredCloneScope::DifferentProcess,
|
||||
rval,
|
||||
&STRUCTURED_CLONE_CALLBACKS,
|
||||
sc_holder_ptr as *mut raw::c_void
|
||||
));
|
||||
|
||||
DeleteJSAutoStructuredCloneBuffer(scbuf);
|
||||
}
|
||||
|
@ -299,8 +332,10 @@ impl StructuredCloneData {
|
|||
let nbytes = vec_msg.len();
|
||||
let data = vec_msg.as_mut_ptr() as *mut u64;
|
||||
StructuredCloneData::read_clone(global, data, nbytes, rval);
|
||||
}
|
||||
StructuredCloneData::Struct(data, nbytes) => StructuredCloneData::read_clone(global, data, nbytes, rval)
|
||||
},
|
||||
StructuredCloneData::Struct(data, nbytes) => {
|
||||
StructuredCloneData::read_clone(global, data, nbytes, rval)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -149,9 +149,11 @@ pub fn trace_jsval(tracer: *mut JSTracer, description: &str, val: &Heap<JSVal>)
|
|||
}
|
||||
|
||||
trace!("tracing value {}", description);
|
||||
CallValueTracer(tracer,
|
||||
val.ptr.get() as *mut _,
|
||||
GCTraceKindToAscii(val.get().trace_kind()));
|
||||
CallValueTracer(
|
||||
tracer,
|
||||
val.ptr.get() as *mut _,
|
||||
GCTraceKindToAscii(val.get().trace_kind()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,9 +168,11 @@ pub fn trace_reflector(tracer: *mut JSTracer, description: &str, reflector: &Ref
|
|||
pub fn trace_object(tracer: *mut JSTracer, description: &str, obj: &Heap<*mut JSObject>) {
|
||||
unsafe {
|
||||
trace!("tracing {}", description);
|
||||
CallObjectTracer(tracer,
|
||||
obj.ptr.get() as *mut _,
|
||||
GCTraceKindToAscii(TraceKind::Object));
|
||||
CallObjectTracer(
|
||||
tracer,
|
||||
obj.ptr.get() as *mut _,
|
||||
GCTraceKindToAscii(TraceKind::Object),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -295,9 +299,10 @@ unsafe impl<T: JSTraceable, U: JSTraceable> JSTraceable for Result<T, U> {
|
|||
}
|
||||
|
||||
unsafe impl<K, V, S> JSTraceable for HashMap<K, V, S>
|
||||
where K: Hash + Eq + JSTraceable,
|
||||
V: JSTraceable,
|
||||
S: BuildHasher,
|
||||
where
|
||||
K: Hash + Eq + JSTraceable,
|
||||
V: JSTraceable,
|
||||
S: BuildHasher,
|
||||
{
|
||||
#[inline]
|
||||
unsafe fn trace(&self, trc: *mut JSTracer) {
|
||||
|
@ -309,8 +314,9 @@ unsafe impl<K, V, S> JSTraceable for HashMap<K, V, S>
|
|||
}
|
||||
|
||||
unsafe impl<T, S> JSTraceable for HashSet<T, S>
|
||||
where T: Hash + Eq + JSTraceable,
|
||||
S: BuildHasher,
|
||||
where
|
||||
T: Hash + Eq + JSTraceable,
|
||||
S: BuildHasher,
|
||||
{
|
||||
#[inline]
|
||||
unsafe fn trace(&self, trc: *mut JSTracer) {
|
||||
|
@ -365,7 +371,12 @@ unsafe_no_jsmanaged_fields!(PropertyDeclarationBlock);
|
|||
// These three are interdependent, if you plan to put jsmanaged data
|
||||
// in one of these make sure it is propagated properly to containing structs
|
||||
unsafe_no_jsmanaged_fields!(DocumentActivity, WindowSizeData, WindowSizeType);
|
||||
unsafe_no_jsmanaged_fields!(BrowsingContextId, HistoryStateId, PipelineId, TopLevelBrowsingContextId);
|
||||
unsafe_no_jsmanaged_fields!(
|
||||
BrowsingContextId,
|
||||
HistoryStateId,
|
||||
PipelineId,
|
||||
TopLevelBrowsingContextId
|
||||
);
|
||||
unsafe_no_jsmanaged_fields!(TimerEventId, TimerSource);
|
||||
unsafe_no_jsmanaged_fields!(TimelineMarkerType);
|
||||
unsafe_no_jsmanaged_fields!(WorkerId);
|
||||
|
@ -459,7 +470,10 @@ unsafe impl<'a, A, B> JSTraceable for fn(&A) -> B {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<T> JSTraceable for IpcSender<T> where T: for<'de> Deserialize<'de> + Serialize {
|
||||
unsafe impl<T> JSTraceable for IpcSender<T>
|
||||
where
|
||||
T: for<'de> Deserialize<'de> + Serialize,
|
||||
{
|
||||
#[inline]
|
||||
unsafe fn trace(&self, _: *mut JSTracer) {
|
||||
// Do nothing
|
||||
|
@ -481,7 +495,10 @@ unsafe impl JSTraceable for () {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<T> JSTraceable for IpcReceiver<T> where T: for<'de> Deserialize<'de> + Serialize {
|
||||
unsafe impl<T> JSTraceable for IpcReceiver<T>
|
||||
where
|
||||
T: for<'de> Deserialize<'de> + Serialize,
|
||||
{
|
||||
#[inline]
|
||||
unsafe fn trace(&self, _: *mut JSTracer) {
|
||||
// Do nothing
|
||||
|
@ -509,14 +526,20 @@ unsafe impl<T: Send> JSTraceable for Sender<T> {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: Send> JSTraceable for WebGLReceiver<T> where T: for<'de> Deserialize<'de> + Serialize {
|
||||
unsafe impl<T: Send> JSTraceable for WebGLReceiver<T>
|
||||
where
|
||||
T: for<'de> Deserialize<'de> + Serialize,
|
||||
{
|
||||
#[inline]
|
||||
unsafe fn trace(&self, _: *mut JSTracer) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: Send> JSTraceable for WebGLSender<T> where T: for<'de> Deserialize<'de> + Serialize {
|
||||
unsafe impl<T: Send> JSTraceable for WebGLSender<T>
|
||||
where
|
||||
T: for<'de> Deserialize<'de> + Serialize,
|
||||
{
|
||||
#[inline]
|
||||
unsafe fn trace(&self, _: *mut JSTracer) {
|
||||
// Do nothing
|
||||
|
@ -665,7 +688,10 @@ unsafe impl JSTraceable for StyleLocked<MediaList> {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<T> JSTraceable for TypedArray<T, Box<Heap<*mut JSObject>>> where T: TypedArrayElement {
|
||||
unsafe impl<T> JSTraceable for TypedArray<T, Box<Heap<*mut JSObject>>>
|
||||
where
|
||||
T: TypedArrayElement,
|
||||
{
|
||||
unsafe fn trace(&self, trc: *mut JSTracer) {
|
||||
self.underlying_object().trace(trc);
|
||||
}
|
||||
|
@ -682,34 +708,26 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// Holds a set of JSTraceables that need to be rooted
|
||||
struct RootedTraceableSet {
|
||||
set: Vec<*const JSTraceable>,
|
||||
}
|
||||
|
||||
thread_local!(
|
||||
/// TLV Holds a set of JSTraceables that need to be rooted
|
||||
static ROOTED_TRACEABLES: RefCell<RootedTraceableSet> =
|
||||
RefCell::new(RootedTraceableSet::new());
|
||||
);
|
||||
thread_local!(/// TLV Holds a set of JSTraceables that need to be rooted
|
||||
static ROOTED_TRACEABLES: RefCell<RootedTraceableSet> = RefCell::new(RootedTraceableSet::new()););
|
||||
|
||||
impl RootedTraceableSet {
|
||||
fn new() -> RootedTraceableSet {
|
||||
RootedTraceableSet {
|
||||
set: vec![],
|
||||
}
|
||||
RootedTraceableSet { set: vec![] }
|
||||
}
|
||||
|
||||
unsafe fn remove(traceable: *const JSTraceable) {
|
||||
ROOTED_TRACEABLES.with(|ref traceables| {
|
||||
let mut traceables = traceables.borrow_mut();
|
||||
let idx =
|
||||
match traceables.set.iter()
|
||||
.rposition(|x| *x == traceable) {
|
||||
Some(idx) => idx,
|
||||
None => unreachable!(),
|
||||
};
|
||||
let idx = match traceables.set.iter().rposition(|x| *x == traceable) {
|
||||
Some(idx) => idx,
|
||||
None => unreachable!(),
|
||||
};
|
||||
traceables.set.remove(idx);
|
||||
});
|
||||
}
|
||||
|
@ -744,9 +762,7 @@ impl<'a, T: JSTraceable + 'static> RootedTraceable<'a, T> {
|
|||
unsafe {
|
||||
RootedTraceableSet::add(traceable);
|
||||
}
|
||||
RootedTraceable {
|
||||
ptr: traceable,
|
||||
}
|
||||
RootedTraceable { ptr: traceable }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -787,16 +803,14 @@ impl<T: JSTraceable + 'static> RootedTraceableBox<T> {
|
|||
unsafe {
|
||||
RootedTraceableSet::add(traceable);
|
||||
}
|
||||
RootedTraceableBox {
|
||||
ptr: traceable,
|
||||
}
|
||||
RootedTraceableBox { ptr: traceable }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> RootedTraceableBox<Heap<T>>
|
||||
where
|
||||
Heap<T>: JSTraceable + 'static,
|
||||
T: GCMethods + Copy,
|
||||
where
|
||||
Heap<T>: JSTraceable + 'static,
|
||||
T: GCMethods + Copy,
|
||||
{
|
||||
pub fn handle(&self) -> Handle<T> {
|
||||
unsafe { Handle::from_raw((*self.ptr).handle()) }
|
||||
|
@ -812,17 +826,13 @@ impl<T: JSTraceable + Default> Default for RootedTraceableBox<T> {
|
|||
impl<T: JSTraceable> Deref for RootedTraceableBox<T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &T {
|
||||
unsafe {
|
||||
&*self.ptr
|
||||
}
|
||||
unsafe { &*self.ptr }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: JSTraceable> DerefMut for RootedTraceableBox<T> {
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
unsafe {
|
||||
&mut *self.ptr
|
||||
}
|
||||
unsafe { &mut *self.ptr }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -849,9 +859,7 @@ pub struct RootableVec<T: JSTraceable> {
|
|||
impl<T: JSTraceable> RootableVec<T> {
|
||||
/// Create a vector of items of type T that can be rooted later.
|
||||
pub fn new_unrooted() -> RootableVec<T> {
|
||||
RootableVec {
|
||||
v: vec![],
|
||||
}
|
||||
RootableVec { v: vec![] }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -868,9 +876,7 @@ impl<'a, T: 'static + JSTraceable> RootedVec<'a, T> {
|
|||
unsafe {
|
||||
RootedTraceableSet::add(root);
|
||||
}
|
||||
RootedVec {
|
||||
root: root,
|
||||
}
|
||||
RootedVec { root: root }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -878,15 +884,14 @@ impl<'a, T: 'static + JSTraceable + DomObject> RootedVec<'a, Dom<T>> {
|
|||
/// Create a vector of items of type Dom<T> that is rooted for
|
||||
/// the lifetime of this struct
|
||||
pub fn from_iter<I>(root: &'a mut RootableVec<Dom<T>>, iter: I) -> Self
|
||||
where I: Iterator<Item = DomRoot<T>>
|
||||
where
|
||||
I: Iterator<Item = DomRoot<T>>,
|
||||
{
|
||||
unsafe {
|
||||
RootedTraceableSet::add(root);
|
||||
}
|
||||
root.v.extend(iter.map(|item| Dom::from_ref(&*item)));
|
||||
RootedVec {
|
||||
root: root,
|
||||
}
|
||||
RootedVec { root: root }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -85,7 +85,6 @@ pub const DOM_PROTOTYPE_SLOT: u32 = js::JSCLASS_GLOBAL_SLOT_COUNT;
|
|||
// changes.
|
||||
pub const JSCLASS_DOM_GLOBAL: u32 = js::JSCLASS_USERBIT1;
|
||||
|
||||
|
||||
/// The struct that holds inheritance information for DOM object reflectors.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct DOMClass {
|
||||
|
@ -137,13 +136,14 @@ pub type ProtoOrIfaceArray = [*mut JSObject; PROTO_OR_IFACE_LENGTH];
|
|||
/// set to true and `*vp` to the value, otherwise `*found` is set to false.
|
||||
///
|
||||
/// Returns false on JSAPI failure.
|
||||
pub unsafe fn get_property_on_prototype(cx: *mut JSContext,
|
||||
proxy: HandleObject,
|
||||
receiver: HandleValue,
|
||||
id: HandleId,
|
||||
found: *mut bool,
|
||||
vp: MutableHandleValue)
|
||||
-> bool {
|
||||
pub unsafe fn get_property_on_prototype(
|
||||
cx: *mut JSContext,
|
||||
proxy: HandleObject,
|
||||
receiver: HandleValue,
|
||||
id: HandleId,
|
||||
found: *mut bool,
|
||||
vp: MutableHandleValue,
|
||||
) -> bool {
|
||||
rooted!(in(cx) let mut proto = ptr::null_mut::<JSObject>());
|
||||
if !JS_GetPrototype(cx, proxy, proto.handle_mut()) || proto.is_null() {
|
||||
*found = false;
|
||||
|
@ -184,23 +184,29 @@ pub fn get_array_index_from_id(_cx: *mut JSContext, id: HandleId) -> Option<u32>
|
|||
return if StringIsArray(str, &mut i) != 0 { i } else { -1 }
|
||||
} else {
|
||||
IdToInt32(cx, id);
|
||||
}*/
|
||||
}
|
||||
}*/}
|
||||
|
||||
/// Find the enum equivelent of a string given by `v` in `pairs`.
|
||||
/// Returns `Err(())` on JSAPI failure (there is a pending exception), and
|
||||
/// `Ok((None, value))` if there was no matching string.
|
||||
pub unsafe fn find_enum_value<'a, T>(cx: *mut JSContext,
|
||||
v: HandleValue,
|
||||
pairs: &'a [(&'static str, T)])
|
||||
-> Result<(Option<&'a T>, DOMString), ()> {
|
||||
pub unsafe fn find_enum_value<'a, T>(
|
||||
cx: *mut JSContext,
|
||||
v: HandleValue,
|
||||
pairs: &'a [(&'static str, T)],
|
||||
) -> Result<(Option<&'a T>, DOMString), ()> {
|
||||
let jsstr = ToString(cx, v);
|
||||
if jsstr.is_null() {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
let search = jsstring_to_str(cx, jsstr);
|
||||
Ok((pairs.iter().find(|&&(key, _)| search == *key).map(|&(_, ref ev)| ev), search))
|
||||
Ok((
|
||||
pairs
|
||||
.iter()
|
||||
.find(|&&(key, _)| search == *key)
|
||||
.map(|&(_, ref ev)| ev),
|
||||
search,
|
||||
))
|
||||
}
|
||||
|
||||
/// Returns wether `obj` is a platform object
|
||||
|
@ -228,23 +234,26 @@ pub fn is_platform_object(obj: *mut JSObject) -> bool {
|
|||
/// Get the property with name `property` from `object`.
|
||||
/// Returns `Err(())` on JSAPI failure (there is a pending exception), and
|
||||
/// `Ok(false)` if there was no property with the given name.
|
||||
pub fn get_dictionary_property(cx: *mut JSContext,
|
||||
object: HandleObject,
|
||||
property: &str,
|
||||
rval: MutableHandleValue)
|
||||
-> Result<bool, ()> {
|
||||
fn has_property(cx: *mut JSContext,
|
||||
object: HandleObject,
|
||||
property: &CString,
|
||||
found: &mut bool)
|
||||
-> bool {
|
||||
pub fn get_dictionary_property(
|
||||
cx: *mut JSContext,
|
||||
object: HandleObject,
|
||||
property: &str,
|
||||
rval: MutableHandleValue,
|
||||
) -> Result<bool, ()> {
|
||||
fn has_property(
|
||||
cx: *mut JSContext,
|
||||
object: HandleObject,
|
||||
property: &CString,
|
||||
found: &mut bool,
|
||||
) -> bool {
|
||||
unsafe { JS_HasProperty(cx, object, property.as_ptr(), found) }
|
||||
}
|
||||
fn get_property(cx: *mut JSContext,
|
||||
object: HandleObject,
|
||||
property: &CString,
|
||||
value: MutableHandleValue)
|
||||
-> bool {
|
||||
fn get_property(
|
||||
cx: *mut JSContext,
|
||||
object: HandleObject,
|
||||
property: &CString,
|
||||
value: MutableHandleValue,
|
||||
) -> bool {
|
||||
unsafe { JS_GetProperty(cx, object, property.as_ptr(), value) }
|
||||
}
|
||||
|
||||
|
@ -272,11 +281,12 @@ pub fn get_dictionary_property(cx: *mut JSContext,
|
|||
/// Set the property with name `property` from `object`.
|
||||
/// Returns `Err(())` on JSAPI failure, or null object,
|
||||
/// and Ok(()) otherwise
|
||||
pub fn set_dictionary_property(cx: *mut JSContext,
|
||||
object: HandleObject,
|
||||
property: &str,
|
||||
value: HandleValue)
|
||||
-> Result<(), ()> {
|
||||
pub fn set_dictionary_property(
|
||||
cx: *mut JSContext,
|
||||
object: HandleObject,
|
||||
property: &str,
|
||||
value: HandleValue,
|
||||
) -> Result<(), ()> {
|
||||
if object.get().is_null() {
|
||||
return Err(());
|
||||
}
|
||||
|
@ -292,11 +302,12 @@ pub fn set_dictionary_property(cx: *mut JSContext,
|
|||
}
|
||||
|
||||
/// Returns whether `proxy` has a property `id` on its prototype.
|
||||
pub unsafe fn has_property_on_prototype(cx: *mut JSContext,
|
||||
proxy: HandleObject,
|
||||
id: HandleId,
|
||||
found: &mut bool)
|
||||
-> bool {
|
||||
pub unsafe fn has_property_on_prototype(
|
||||
cx: *mut JSContext,
|
||||
proxy: HandleObject,
|
||||
id: HandleId,
|
||||
found: &mut bool,
|
||||
) -> bool {
|
||||
rooted!(in(cx) let mut proto = ptr::null_mut::<JSObject>());
|
||||
if !JS_GetPrototype(cx, proxy, proto.handle_mut()) {
|
||||
return false;
|
||||
|
@ -322,9 +333,11 @@ pub unsafe fn trace_global(tracer: *mut JSTracer, obj: *mut JSObject) {
|
|||
let array = get_proto_or_iface_array(obj);
|
||||
for proto in (*array).iter() {
|
||||
if !proto.is_null() {
|
||||
trace_object(tracer,
|
||||
"prototype",
|
||||
&*(proto as *const *mut JSObject as *const Heap<*mut JSObject>));
|
||||
trace_object(
|
||||
tracer,
|
||||
"prototype",
|
||||
&*(proto as *const *mut JSObject as *const Heap<*mut JSObject>),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -343,11 +356,11 @@ pub unsafe extern "C" fn enumerate_global(cx: *mut JSContext, obj: RawHandleObje
|
|||
|
||||
/// Resolve a lazy global property, for interface objects and named constructors.
|
||||
pub unsafe extern "C" fn resolve_global(
|
||||
cx: *mut JSContext,
|
||||
obj: RawHandleObject,
|
||||
id: RawHandleId,
|
||||
rval: *mut bool)
|
||||
-> bool {
|
||||
cx: *mut JSContext,
|
||||
obj: RawHandleObject,
|
||||
id: RawHandleId,
|
||||
rval: *mut bool,
|
||||
) -> bool {
|
||||
assert!(JS_IsGlobalObject(obj.get()));
|
||||
if !JS_ResolveStandardClass(cx, obj, id, rval) {
|
||||
return false;
|
||||
|
@ -379,20 +392,23 @@ pub unsafe extern "C" fn resolve_global(
|
|||
true
|
||||
}
|
||||
|
||||
unsafe extern "C" fn wrap(cx: *mut JSContext,
|
||||
_existing: RawHandleObject,
|
||||
obj: RawHandleObject)
|
||||
-> *mut JSObject {
|
||||
unsafe extern "C" fn wrap(
|
||||
cx: *mut JSContext,
|
||||
_existing: RawHandleObject,
|
||||
obj: RawHandleObject,
|
||||
) -> *mut JSObject {
|
||||
// FIXME terrible idea. need security wrappers
|
||||
// https://github.com/servo/servo/issues/2382
|
||||
WrapperNew(cx, obj, GetCrossCompartmentWrapper(), ptr::null(), false)
|
||||
}
|
||||
|
||||
unsafe extern "C" fn pre_wrap(cx: *mut JSContext,
|
||||
_scope: RawHandleObject,
|
||||
obj: RawHandleObject,
|
||||
_object_passed_to_wrap: RawHandleObject,
|
||||
rval: RawMutableHandleObject) {
|
||||
unsafe extern "C" fn pre_wrap(
|
||||
cx: *mut JSContext,
|
||||
_scope: RawHandleObject,
|
||||
obj: RawHandleObject,
|
||||
_object_passed_to_wrap: RawHandleObject,
|
||||
rval: RawMutableHandleObject,
|
||||
) {
|
||||
let _ac = JSAutoCompartment::new(cx, obj.get());
|
||||
let obj = ToWindowProxyIfWindow(obj.get());
|
||||
assert!(!obj.is_null());
|
||||
|
@ -406,23 +422,29 @@ pub static WRAP_CALLBACKS: JSWrapObjectCallbacks = JSWrapObjectCallbacks {
|
|||
};
|
||||
|
||||
/// Deletes the property `id` from `object`.
|
||||
pub unsafe fn delete_property_by_id(cx: *mut JSContext,
|
||||
object: HandleObject,
|
||||
id: HandleId,
|
||||
bp: *mut ObjectOpResult)
|
||||
-> bool {
|
||||
pub unsafe fn delete_property_by_id(
|
||||
cx: *mut JSContext,
|
||||
object: HandleObject,
|
||||
id: HandleId,
|
||||
bp: *mut ObjectOpResult,
|
||||
) -> bool {
|
||||
JS_DeletePropertyById(cx, object, id, bp)
|
||||
}
|
||||
|
||||
unsafe fn generic_call(cx: *mut JSContext,
|
||||
argc: libc::c_uint,
|
||||
vp: *mut JSVal,
|
||||
is_lenient: bool,
|
||||
call: unsafe extern fn(*const JSJitInfo, *mut JSContext,
|
||||
RawHandleObject, *mut libc::c_void, u32,
|
||||
*mut JSVal)
|
||||
-> bool)
|
||||
-> bool {
|
||||
unsafe fn generic_call(
|
||||
cx: *mut JSContext,
|
||||
argc: libc::c_uint,
|
||||
vp: *mut JSVal,
|
||||
is_lenient: bool,
|
||||
call: unsafe extern "C" fn(
|
||||
*const JSJitInfo,
|
||||
*mut JSContext,
|
||||
RawHandleObject,
|
||||
*mut libc::c_void,
|
||||
u32,
|
||||
*mut JSVal,
|
||||
) -> bool,
|
||||
) -> bool {
|
||||
let args = CallArgs::from_vp(vp, argc);
|
||||
|
||||
let info = RUST_FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));
|
||||
|
@ -441,9 +463,8 @@ unsafe fn generic_call(cx: *mut JSContext,
|
|||
};
|
||||
rooted!(in(cx) let obj = obj);
|
||||
let depth = (*info).depth;
|
||||
let proto_check = |class: &'static DOMClass| {
|
||||
class.interface_chain[depth as usize] as u16 == proto_id
|
||||
};
|
||||
let proto_check =
|
||||
|class: &'static DOMClass| class.interface_chain[depth as usize] as u16 == proto_id;
|
||||
let this = match private_from_proto_check(obj.get(), proto_check) {
|
||||
Ok(val) => val,
|
||||
Err(()) => {
|
||||
|
@ -455,42 +476,53 @@ unsafe fn generic_call(cx: *mut JSContext,
|
|||
throw_invalid_this(cx, proto_id);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
call(info, cx, obj.handle().into(), this as *mut libc::c_void, argc, vp)
|
||||
call(
|
||||
info,
|
||||
cx,
|
||||
obj.handle().into(),
|
||||
this as *mut libc::c_void,
|
||||
argc,
|
||||
vp,
|
||||
)
|
||||
}
|
||||
|
||||
/// Generic method of IDL interface.
|
||||
pub unsafe extern "C" fn generic_method(cx: *mut JSContext,
|
||||
argc: libc::c_uint,
|
||||
vp: *mut JSVal)
|
||||
-> bool {
|
||||
pub unsafe extern "C" fn generic_method(
|
||||
cx: *mut JSContext,
|
||||
argc: libc::c_uint,
|
||||
vp: *mut JSVal,
|
||||
) -> bool {
|
||||
generic_call(cx, argc, vp, false, CallJitMethodOp)
|
||||
}
|
||||
|
||||
/// Generic getter of IDL interface.
|
||||
pub unsafe extern "C" fn generic_getter(cx: *mut JSContext,
|
||||
argc: libc::c_uint,
|
||||
vp: *mut JSVal)
|
||||
-> bool {
|
||||
pub unsafe extern "C" fn generic_getter(
|
||||
cx: *mut JSContext,
|
||||
argc: libc::c_uint,
|
||||
vp: *mut JSVal,
|
||||
) -> bool {
|
||||
generic_call(cx, argc, vp, false, CallJitGetterOp)
|
||||
}
|
||||
|
||||
/// Generic lenient getter of IDL interface.
|
||||
pub unsafe extern "C" fn generic_lenient_getter(cx: *mut JSContext,
|
||||
argc: libc::c_uint,
|
||||
vp: *mut JSVal)
|
||||
-> bool {
|
||||
pub unsafe extern "C" fn generic_lenient_getter(
|
||||
cx: *mut JSContext,
|
||||
argc: libc::c_uint,
|
||||
vp: *mut JSVal,
|
||||
) -> bool {
|
||||
generic_call(cx, argc, vp, true, CallJitGetterOp)
|
||||
}
|
||||
|
||||
unsafe extern "C" fn call_setter(info: *const JSJitInfo,
|
||||
cx: *mut JSContext,
|
||||
handle: RawHandleObject,
|
||||
this: *mut libc::c_void,
|
||||
argc: u32,
|
||||
vp: *mut JSVal)
|
||||
-> bool {
|
||||
unsafe extern "C" fn call_setter(
|
||||
info: *const JSJitInfo,
|
||||
cx: *mut JSContext,
|
||||
handle: RawHandleObject,
|
||||
this: *mut libc::c_void,
|
||||
argc: u32,
|
||||
vp: *mut JSVal,
|
||||
) -> bool {
|
||||
if !CallJitSetterOp(info, cx, handle, this, argc, vp) {
|
||||
return false;
|
||||
}
|
||||
|
@ -499,31 +531,34 @@ unsafe extern "C" fn call_setter(info: *const JSJitInfo,
|
|||
}
|
||||
|
||||
/// Generic setter of IDL interface.
|
||||
pub unsafe extern "C" fn generic_setter(cx: *mut JSContext,
|
||||
argc: libc::c_uint,
|
||||
vp: *mut JSVal)
|
||||
-> bool {
|
||||
pub unsafe extern "C" fn generic_setter(
|
||||
cx: *mut JSContext,
|
||||
argc: libc::c_uint,
|
||||
vp: *mut JSVal,
|
||||
) -> bool {
|
||||
generic_call(cx, argc, vp, false, call_setter)
|
||||
}
|
||||
|
||||
/// Generic lenient setter of IDL interface.
|
||||
pub unsafe extern "C" fn generic_lenient_setter(cx: *mut JSContext,
|
||||
argc: libc::c_uint,
|
||||
vp: *mut JSVal)
|
||||
-> bool {
|
||||
pub unsafe extern "C" fn generic_lenient_setter(
|
||||
cx: *mut JSContext,
|
||||
argc: libc::c_uint,
|
||||
vp: *mut JSVal,
|
||||
) -> bool {
|
||||
generic_call(cx, argc, vp, true, call_setter)
|
||||
}
|
||||
|
||||
unsafe extern "C" fn instance_class_has_proto_at_depth(clasp: *const js::jsapi::Class,
|
||||
proto_id: u32,
|
||||
depth: u32)
|
||||
-> bool {
|
||||
unsafe extern "C" fn instance_class_has_proto_at_depth(
|
||||
clasp: *const js::jsapi::Class,
|
||||
proto_id: u32,
|
||||
depth: u32,
|
||||
) -> bool {
|
||||
let domclass: *const DOMJSClass = clasp as *const _;
|
||||
let domclass = &*domclass;
|
||||
domclass.dom_class.interface_chain[depth as usize] as u32 == proto_id
|
||||
}
|
||||
|
||||
#[allow(missing_docs)] // FIXME
|
||||
#[allow(missing_docs)] // FIXME
|
||||
pub const DOM_CALLBACKS: DOMCallbacks = DOMCallbacks {
|
||||
instanceClassMatchesProto: Some(instance_class_has_proto_at_depth),
|
||||
};
|
||||
|
|
|
@ -70,9 +70,11 @@ pub trait WeakReferenceable: DomObject + Sized {
|
|||
let box_ = &*ptr;
|
||||
assert!(box_.value.get().is_some());
|
||||
let new_count = box_.count.get() + 1;
|
||||
trace!("Incrementing WeakBox refcount for {:p} to {}.",
|
||||
self,
|
||||
new_count);
|
||||
trace!(
|
||||
"Incrementing WeakBox refcount for {:p} to {}.",
|
||||
self,
|
||||
new_count
|
||||
);
|
||||
box_.count.set(new_count);
|
||||
WeakRef {
|
||||
ptr: ptr::NonNull::new_unchecked(ptr),
|
||||
|
@ -91,9 +93,10 @@ impl<T: WeakReferenceable> WeakRef<T> {
|
|||
|
||||
/// DomRoot a weak reference. Returns `None` if the object was already collected.
|
||||
pub fn root(&self) -> Option<DomRoot<T>> {
|
||||
unsafe { &*self.ptr.as_ptr() }.value.get().map(|ptr| unsafe {
|
||||
DomRoot::from_ref(&*ptr.as_ptr())
|
||||
})
|
||||
unsafe { &*self.ptr.as_ptr() }
|
||||
.value
|
||||
.get()
|
||||
.map(|ptr| unsafe { DomRoot::from_ref(&*ptr.as_ptr()) })
|
||||
}
|
||||
|
||||
/// Return whether the weakly-referenced object is still alive.
|
||||
|
@ -108,9 +111,7 @@ impl<T: WeakReferenceable> Clone for WeakRef<T> {
|
|||
let box_ = &*self.ptr.as_ptr();
|
||||
let new_count = box_.count.get() + 1;
|
||||
box_.count.set(new_count);
|
||||
WeakRef {
|
||||
ptr: self.ptr,
|
||||
}
|
||||
WeakRef { ptr: self.ptr }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -122,10 +123,10 @@ impl<T: WeakReferenceable> MallocSizeOf for WeakRef<T> {
|
|||
}
|
||||
|
||||
impl<T: WeakReferenceable> PartialEq for WeakRef<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
unsafe {
|
||||
(*self.ptr.as_ptr()).value.get().map(ptr::NonNull::as_ptr) ==
|
||||
(*other.ptr.as_ptr()).value.get().map(ptr::NonNull::as_ptr)
|
||||
(*other.ptr.as_ptr()).value.get().map(ptr::NonNull::as_ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -190,7 +191,9 @@ impl<T: WeakReferenceable> MutableWeakRef<T> {
|
|||
/// DomRoot a mutable weak reference. Returns `None` if the object
|
||||
/// was already collected.
|
||||
pub fn root(&self) -> Option<DomRoot<T>> {
|
||||
unsafe { &*self.cell.get() }.as_ref().and_then(WeakRef::root)
|
||||
unsafe { &*self.cell.get() }
|
||||
.as_ref()
|
||||
.and_then(WeakRef::root)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -233,7 +236,10 @@ impl<T: WeakReferenceable> WeakRefVec<T> {
|
|||
let mut i = 0;
|
||||
while i < self.vec.len() {
|
||||
if self.vec[i].is_alive() {
|
||||
f(WeakRefEntry { vec: self, index: &mut i });
|
||||
f(WeakRefEntry {
|
||||
vec: self,
|
||||
index: &mut i,
|
||||
});
|
||||
} else {
|
||||
self.vec.swap_remove(i);
|
||||
}
|
||||
|
@ -293,13 +299,13 @@ impl<'a, T: WeakReferenceable + 'a> Drop for WeakRefEntry<'a, T> {
|
|||
|
||||
#[derive(MallocSizeOf)]
|
||||
pub struct DOMTracker<T: WeakReferenceable> {
|
||||
dom_objects: DomRefCell<WeakRefVec<T>>
|
||||
dom_objects: DomRefCell<WeakRefVec<T>>,
|
||||
}
|
||||
|
||||
impl<T: WeakReferenceable> DOMTracker<T> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
dom_objects: DomRefCell::new(WeakRefVec::new())
|
||||
dom_objects: DomRefCell::new(WeakRefVec::new()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,9 +25,10 @@ pub fn validate_qualified_name(qualified_name: &str) -> ErrorResult {
|
|||
|
||||
/// Validate a namespace and qualified name and extract their parts.
|
||||
/// See https://dom.spec.whatwg.org/#validate-and-extract for details.
|
||||
pub fn validate_and_extract(namespace: Option<DOMString>,
|
||||
qualified_name: &str)
|
||||
-> Fallible<(Namespace, Option<Prefix>, LocalName)> {
|
||||
pub fn validate_and_extract(
|
||||
namespace: Option<DOMString>,
|
||||
qualified_name: &str,
|
||||
) -> Fallible<(Namespace, Option<Prefix>, LocalName)> {
|
||||
// Step 1.
|
||||
let namespace = namespace_from_domstring(namespace);
|
||||
|
||||
|
@ -76,7 +77,7 @@ pub fn validate_and_extract(namespace: Option<DOMString>,
|
|||
(ns, p) => {
|
||||
// Step 10.
|
||||
Ok((ns, p.map(Prefix::from), LocalName::from(local_name)))
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,14 +116,10 @@ pub fn xml_name_type(name: &str) -> XMLName {
|
|||
}
|
||||
|
||||
fn is_valid_continuation(c: char) -> bool {
|
||||
is_valid_start(c) ||
|
||||
match c {
|
||||
'-' |
|
||||
'.' |
|
||||
'0'...'9' |
|
||||
'\u{B7}' |
|
||||
'\u{300}'...'\u{36F}' |
|
||||
'\u{203F}'...'\u{2040}' => true,
|
||||
is_valid_start(c) || match c {
|
||||
'-' | '.' | '0'...'9' | '\u{B7}' | '\u{300}'...'\u{36F}' | '\u{203F}'...'\u{2040}' => {
|
||||
true
|
||||
},
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -140,7 +137,7 @@ pub fn xml_name_type(name: &str) -> XMLName {
|
|||
non_qname_colons = true;
|
||||
}
|
||||
c
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
for c in iter {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue