Make callbacks' new methods unsafe

They take raw pointers to contexts and objects.
This commit is contained in:
Anthony Ramine 2018-01-25 11:25:23 +01:00
parent 9c13073075
commit f903da0a7b
3 changed files with 58 additions and 30 deletions

View file

@ -4549,7 +4549,7 @@ class ClassConstructor(ClassItem):
"});\n" "});\n"
"// Note: callback cannot be moved after calling init.\n" "// Note: callback cannot be moved after calling init.\n"
"match Rc::get_mut(&mut ret) {\n" "match Rc::get_mut(&mut ret) {\n"
" Some(ref mut callback) => unsafe { callback.parent.init(%s, %s) },\n" " Some(ref mut callback) => callback.parent.init(%s, %s),\n"
" None => unreachable!(),\n" " None => unreachable!(),\n"
"};\n" "};\n"
"ret") % (cgClass.name, '\n'.join(initializers), "ret") % (cgClass.name, '\n'.join(initializers),
@ -4564,7 +4564,7 @@ class ClassConstructor(ClassItem):
body = ' {\n' + body + '}' body = ' {\n' + body + '}'
return string.Template("""\ return string.Template("""\
pub fn ${decorators}new(${args}) -> Rc<${className}>${body} pub unsafe fn ${decorators}new(${args}) -> Rc<${className}>${body}
""").substitute({'decorators': self.getDecorators(True), """).substitute({'decorators': self.getDecorators(True),
'className': cgClass.getNameString(), 'className': cgClass.getNameString(),
'args': args, 'args': args,

View file

@ -121,7 +121,8 @@ impl CustomElementRegistry {
/// <https://html.spec.whatwg.org/multipage/#dom-customelementregistry-define> /// <https://html.spec.whatwg.org/multipage/#dom-customelementregistry-define>
/// Steps 10.3, 10.4 /// Steps 10.3, 10.4
fn get_callbacks(&self, prototype: HandleObject) -> Fallible<LifecycleCallbacks> { #[allow(unsafe_code)]
unsafe fn get_callbacks(&self, prototype: HandleObject) -> Fallible<LifecycleCallbacks> {
let cx = self.window.get_cx(); let cx = self.window.get_cx();
// Step 4 // Step 4
@ -164,20 +165,21 @@ impl CustomElementRegistry {
/// <https://html.spec.whatwg.org/multipage/#dom-customelementregistry-define> /// <https://html.spec.whatwg.org/multipage/#dom-customelementregistry-define>
/// Step 10.4 /// Step 10.4
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn get_callback(cx: *mut JSContext, prototype: HandleObject, name: &[u8]) -> Fallible<Option<Rc<Function>>> { unsafe fn get_callback(
cx: *mut JSContext,
prototype: HandleObject,
name: &[u8],
) -> Fallible<Option<Rc<Function>>> {
rooted!(in(cx) let mut callback = UndefinedValue()); rooted!(in(cx) let mut callback = UndefinedValue());
// Step 10.4.1 // Step 10.4.1
if unsafe { !JS_GetProperty(cx, if !JS_GetProperty(cx, prototype, name.as_ptr() as *const _, callback.handle_mut()) {
prototype,
name.as_ptr() as *const _,
callback.handle_mut()) } {
return Err(Error::JSFailed); return Err(Error::JSFailed);
} }
// Step 10.4.2 // Step 10.4.2
if !callback.is_undefined() { if !callback.is_undefined() {
if !callback.is_object() || unsafe { !IsCallable(callback.to_object()) } { if !callback.is_object() || !IsCallable(callback.to_object()) {
return Err(Error::Type("Lifecycle callback is not callable".to_owned())); return Err(Error::Type("Lifecycle callback is not callable".to_owned()));
} }
Ok(Some(Function::new(cx, callback.to_object()))) Ok(Some(Function::new(cx, callback.to_object())))
@ -265,7 +267,7 @@ impl CustomElementRegistryMethods for CustomElementRegistry {
rooted!(in(cx) let proto_object = prototype.to_object()); rooted!(in(cx) let proto_object = prototype.to_object());
let callbacks = { let callbacks = {
let _ac = JSAutoCompartment::new(cx, proto_object.get()); let _ac = JSAutoCompartment::new(cx, proto_object.get());
match self.get_callbacks(proto_object.handle()) { match unsafe { self.get_callbacks(proto_object.handle()) } {
Ok(callbacks) => callbacks, Ok(callbacks) => callbacks,
Err(error) => { Err(error) => {
self.element_definition_is_running.set(false); self.element_definition_is_running.set(false);

View file

@ -471,50 +471,76 @@ impl EventTarget {
assert!(!funobj.is_null()); assert!(!funobj.is_null());
// Step 1.14 // Step 1.14
if is_error { if is_error {
Some(CommonEventHandler::ErrorEventHandler(OnErrorEventHandlerNonNull::new(cx, funobj))) Some(CommonEventHandler::ErrorEventHandler(
unsafe { OnErrorEventHandlerNonNull::new(cx, funobj) },
))
} else { } else {
if ty == &atom!("beforeunload") { if ty == &atom!("beforeunload") {
Some(CommonEventHandler::BeforeUnloadEventHandler( Some(CommonEventHandler::BeforeUnloadEventHandler(
OnBeforeUnloadEventHandlerNonNull::new(cx, funobj))) unsafe { OnBeforeUnloadEventHandlerNonNull::new(cx, funobj) },
))
} else { } else {
Some(CommonEventHandler::EventHandler(EventHandlerNonNull::new(cx, funobj))) Some(CommonEventHandler::EventHandler(
unsafe { EventHandlerNonNull::new(cx, funobj) },
))
} }
} }
} }
#[allow(unsafe_code)]
pub fn set_event_handler_common<T: CallbackContainer>( pub fn set_event_handler_common<T: CallbackContainer>(
&self, ty: &str, listener: Option<Rc<T>>) &self,
ty: &str,
listener: Option<Rc<T>>,
)
where
T: CallbackContainer,
{ {
let cx = self.global().get_cx(); let cx = self.global().get_cx();
let event_listener = listener.map(|listener| let event_listener = listener.map(|listener| {
InlineEventListener::Compiled( InlineEventListener::Compiled(CommonEventHandler::EventHandler(
CommonEventHandler::EventHandler( unsafe { EventHandlerNonNull::new(cx, listener.callback()) },
EventHandlerNonNull::new(cx, listener.callback())))); ))
});
self.set_inline_event_listener(Atom::from(ty), event_listener); self.set_inline_event_listener(Atom::from(ty), event_listener);
} }
#[allow(unsafe_code)]
pub fn set_error_event_handler<T: CallbackContainer>( pub fn set_error_event_handler<T: CallbackContainer>(
&self, ty: &str, listener: Option<Rc<T>>) &self,
ty: &str,
listener: Option<Rc<T>>,
)
where
T: CallbackContainer,
{ {
let cx = self.global().get_cx(); let cx = self.global().get_cx();
let event_listener = listener.map(|listener| let event_listener = listener.map(|listener| {
InlineEventListener::Compiled( InlineEventListener::Compiled(CommonEventHandler::ErrorEventHandler(
CommonEventHandler::ErrorEventHandler( unsafe { OnErrorEventHandlerNonNull::new(cx, listener.callback()) }
OnErrorEventHandlerNonNull::new(cx, listener.callback())))); ))
});
self.set_inline_event_listener(Atom::from(ty), event_listener); self.set_inline_event_listener(Atom::from(ty), event_listener);
} }
pub fn set_beforeunload_event_handler<T: CallbackContainer>(&self, ty: &str, #[allow(unsafe_code)]
listener: Option<Rc<T>>) { pub fn set_beforeunload_event_handler<T: CallbackContainer>(
&self,
ty: &str,
listener: Option<Rc<T>>,
)
where
T: CallbackContainer,
{
let cx = self.global().get_cx(); let cx = self.global().get_cx();
let event_listener = listener.map(|listener| let event_listener = listener.map(|listener| {
InlineEventListener::Compiled( InlineEventListener::Compiled(CommonEventHandler::BeforeUnloadEventHandler(
CommonEventHandler::BeforeUnloadEventHandler( unsafe { OnBeforeUnloadEventHandlerNonNull::new(cx, listener.callback()) }
OnBeforeUnloadEventHandlerNonNull::new(cx, listener.callback()))) ))
); });
self.set_inline_event_listener(Atom::from(ty), event_listener); self.set_inline_event_listener(Atom::from(ty), event_listener);
} }