diff options
-rw-r--r-- | src/components/script/dom/bindings/error.rs | 20 | ||||
-rw-r--r-- | src/components/script/dom/eventtarget.rs | 32 | ||||
-rw-r--r-- | src/test/content/test_event_handler_syntax_error.html | 23 |
3 files changed, 60 insertions, 15 deletions
diff --git a/src/components/script/dom/bindings/error.rs b/src/components/script/dom/bindings/error.rs index f204dc5859a..cef1de163fd 100644 --- a/src/components/script/dom/bindings/error.rs +++ b/src/components/script/dom/bindings/error.rs @@ -6,10 +6,12 @@ use dom::bindings::conversions::ToJSValConvertible; use dom::bindings::global::GlobalRef; use dom::domexception::DOMException; -use js::jsapi::{JSContext, JSBool}; -use js::jsapi::{JS_IsExceptionPending, JS_SetPendingException}; +use js::jsapi::{JSContext, JSBool, JSObject}; +use js::jsapi::{JS_IsExceptionPending, JS_SetPendingException, JS_ReportPendingException}; use js::jsapi::{JS_ReportErrorNumber, JSErrorFormatString, JSEXN_TYPEERR}; +use js::jsapi::{JS_SaveFrameChain, JS_RestoreFrameChain}; use js::glue::{ReportError}; +use js::rust::with_compartment; use libc; use std::ptr; @@ -46,6 +48,20 @@ pub fn throw_dom_exception(cx: *mut JSContext, global: &GlobalRef, } } +pub fn report_pending_exception(cx: *mut JSContext, obj: *mut JSObject) { + unsafe { + if JS_IsExceptionPending(cx) != 0 { + let saved = JS_SaveFrameChain(cx); + with_compartment(cx, obj, || { + JS_ReportPendingException(cx); + }); + if saved != 0 { + JS_RestoreFrameChain(cx); + } + } + } +} + pub fn throw_not_in_union(cx: *mut JSContext, names: &'static str) -> JSBool { assert!(unsafe { JS_IsExceptionPending(cx) } == 0); let message = format!("argument could not be converted to any of: {}", names); diff --git a/src/components/script/dom/eventtarget.rs b/src/components/script/dom/eventtarget.rs index 1683f280100..75a7319ee23 100644 --- a/src/components/script/dom/eventtarget.rs +++ b/src/components/script/dom/eventtarget.rs @@ -5,7 +5,7 @@ use dom::bindings::callback::CallbackContainer; use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; use dom::bindings::codegen::Bindings::EventListenerBinding::EventListener; -use dom::bindings::error::{Fallible, InvalidState}; +use dom::bindings::error::{Fallible, InvalidState, report_pending_exception}; use dom::bindings::js::JSRef; use dom::bindings::trace::Traceable; use dom::bindings::utils::{Reflectable, Reflector}; @@ -181,19 +181,25 @@ impl<'a> EventTargetHelpers for JSRef<'a, EventTarget> { static arg_names: [*c_char, ..1] = [&arg_name as *c_char]; let source = source.to_utf16(); - let handler = - name.with_ref(|name| { - url.with_ref(|url| { unsafe { - let fun = JS_CompileUCFunction(cx, ptr::mut_null(), name, - nargs, &arg_names as **i8 as *mut *i8, source.as_ptr(), - source.len() as size_t, - url, lineno); - assert!(fun.is_not_null()); - JS_GetFunctionObject(fun) - }})}); - let funobj = unsafe { JS_CloneFunctionObject(cx, handler, scope) }; + let handler = name.with_ref(|name| { + url.with_ref(|url| { + unsafe { + JS_CompileUCFunction(cx, ptr::mut_null(), name, + nargs, &arg_names as **i8 as *mut *i8, + source.as_ptr(), source.len() as size_t, url, lineno) + } + }) + }); + if handler.is_null() { + report_pending_exception(cx, self.reflector().get_jsobject()); + return; + } + + let funobj = unsafe { + JS_CloneFunctionObject(cx, JS_GetFunctionObject(handler), scope) + }; assert!(funobj.is_not_null()); - self.set_event_handler_common(ty, Some(EventHandlerNonNull::new(funobj))) + self.set_event_handler_common(ty, Some(EventHandlerNonNull::new(funobj))); } fn set_event_handler_common<T: CallbackContainer>( diff --git a/src/test/content/test_event_handler_syntax_error.html b/src/test/content/test_event_handler_syntax_error.html new file mode 100644 index 00000000000..f6c8cdffcff --- /dev/null +++ b/src/test/content/test_event_handler_syntax_error.html @@ -0,0 +1,23 @@ +<!DOCTYPE html> +<html> +<head> + <title></title> + <meta charset="UTF-8"> + <script src="harness.js"></script> +</head> +<body> + <a id="a" onclick="{">link</a> + <script> + var a = document.getElementById("a"); + is(a.onclick, null, "invalid onclick attribute"); + + document.body.setAttribute("onx", "{"); + document.body.setAttribute("ony", "}"); + + is(document.body.getAttribute("onx"), "{"); + is(document.body.getAttribute("ony"), "}"); + + finish(); + </script> +</body> +</html> |