Created
January 16, 2017 18:31
-
-
Save jdm/e9ddf21af8c3151a859d63e6035fa21b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit 2b82584c108cf3a8f6f071f8459bc3b216972c68 | |
Author: Josh Matthews <[email protected]> | |
Date: Fri Jan 13 19:17:40 2017 -0500 | |
Set the proper filename and line number for inline compiled event handlers. | |
diff --git a/components/script/dom/bindings/utils.rs b/components/script/dom/bindings/utils.rs | |
index de1ac8f..8384aaf 100644 | |
--- a/components/script/dom/bindings/utils.rs | |
+++ b/components/script/dom/bindings/utils.rs | |
@@ -22,8 +22,8 @@ use js::glue::{RUST_FUNCTION_VALUE_TO_JITINFO, RUST_JSID_IS_INT, RUST_JSID_IS_ST | |
use js::glue::{RUST_JSID_TO_INT, RUST_JSID_TO_STRING, UnwrapObject}; | |
use js::jsapi::{CallArgs, DOMCallbacks, GetGlobalForObjectCrossCompartment}; | |
use js::jsapi::{HandleId, HandleObject, HandleValue, Heap, JSAutoCompartment, JSContext}; | |
-use js::jsapi::{JSJitInfo, JSObject, JSTracer, JSWrapObjectCallbacks}; | |
-use js::jsapi::{JS_DeletePropertyById, JS_EnumerateStandardClasses}; | |
+use js::jsapi::{JSJitInfo, JSObject, JSTracer, JSWrapObjectCallbacks, AutoFilename}; | |
+use js::jsapi::{JS_DeletePropertyById, JS_EnumerateStandardClasses, DescribeScriptedCaller}; | |
use js::jsapi::{JS_ForwardGetPropertyTo, JS_GetLatin1StringCharsAndLength}; | |
use js::jsapi::{JS_GetProperty, JS_GetPrototype, JS_GetReservedSlot, JS_HasProperty}; | |
use js::jsapi::{JS_HasPropertyById, JS_IsExceptionPending, JS_IsGlobalObject}; | |
@@ -32,7 +32,7 @@ use js::jsapi::{JS_StringHasLatin1Chars, MutableHandleValue, ObjectOpResult}; | |
use js::jsval::{JSVal, UndefinedValue}; | |
use js::rust::{GCMethods, ToString, get_object_class, is_dom_class}; | |
use libc; | |
-use std::ffi::CString; | |
+use std::ffi::{CString, CStr}; | |
use std::os::raw::c_void; | |
use std::ptr; | |
use std::slice; | |
@@ -513,3 +513,32 @@ unsafe extern "C" fn instance_class_has_proto_at_depth(clasp: *const js::jsapi:: | |
pub const DOM_CALLBACKS: DOMCallbacks = DOMCallbacks { | |
instanceClassMatchesProto: Some(instance_class_has_proto_at_depth), | |
}; | |
+ | |
+pub struct ScriptedCaller { | |
+ pub filename: String, | |
+ pub line: usize, | |
+ pub column: usize, | |
+} | |
+ | |
+pub fn describe_scripted_caller() -> Option<ScriptedCaller> { | |
+ let cx = Runtime::get(); | |
+ let mut fname = AutoFilename { | |
+ ss_: ptr::null_mut(), | |
+ filename_: [0, 0], | |
+ }; | |
+ let mut lineno = 0; | |
+ let mut column = 0; | |
+ let ok = unsafe { | |
+ DescribeScriptedCaller(cx, &mut fname, &mut lineno, &mut column) | |
+ }; | |
+ if ok { | |
+ Some(ScriptedCaller { | |
+ filename: unsafe { CStr::from_ptr(fname.get()).to_string_lossy().into() }, | |
+ line: lineno as usize, | |
+ column: column as usize, | |
+ }) | |
+ } else { | |
+ //TODO: get the entry global? how to figure out line/column, in that case? | |
+ None | |
+ } | |
+} | |
diff --git a/components/script/dom/eventtarget.rs b/components/script/dom/eventtarget.rs | |
index 09cafb6..81262e6 100644 | |
--- a/components/script/dom/eventtarget.rs | |
+++ b/components/script/dom/eventtarget.rs | |
@@ -71,8 +71,9 @@ pub enum ListenerPhase { | |
#[derive(JSTraceable, Clone, PartialEq)] | |
struct InternalRawUncompiledHandler { | |
source: DOMString, | |
- url: ServoUrl, | |
+ filename: String, | |
line: usize, | |
+ column: usize, | |
} | |
/// A representation of an event handler, either compiled or uncompiled raw source, or null. | |
@@ -348,14 +349,16 @@ impl EventTarget { | |
/// Store the raw uncompiled event handler for on-demand compilation later. | |
/// https://html.spec.whatwg.org/multipage/#event-handler-attributes:event-handler-content-attributes-3 | |
pub fn set_event_handler_uncompiled(&self, | |
- url: ServoUrl, | |
+ filename: String, | |
line: usize, | |
+ column: usize, | |
ty: &str, | |
source: DOMString) { | |
let handler = InternalRawUncompiledHandler { | |
source: source, | |
line: line, | |
- url: url, | |
+ column: column, | |
+ filename: filename, | |
}; | |
self.set_inline_event_listener(Atom::from(ty), | |
Some(InlineEventListener::Uncompiled(handler))); | |
@@ -387,7 +390,7 @@ impl EventTarget { | |
// Step 1.6 | |
let window = document.window(); | |
- let url_serialized = CString::new(handler.url.to_string()).unwrap(); | |
+ let url_serialized = CString::new(handler.filename).unwrap(); | |
let name = CString::new(&**ty).unwrap(); | |
static mut ARG_NAMES: [*const c_char; 1] = [b"event\0" as *const u8 as *const c_char]; | |
diff --git a/components/script/dom/htmlbodyelement.rs b/components/script/dom/htmlbodyelement.rs | |
index ea9b177..02becb3 100644 | |
--- a/components/script/dom/htmlbodyelement.rs | |
+++ b/components/script/dom/htmlbodyelement.rs | |
@@ -9,7 +9,9 @@ use dom::bindings::codegen::Bindings::HTMLBodyElementBinding::{self, HTMLBodyEle | |
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; | |
use dom::bindings::inheritance::Castable; | |
use dom::bindings::js::{LayoutJS, Root}; | |
+use dom::bindings::reflector::DomObject; | |
use dom::bindings::str::DOMString; | |
+use dom::bindings::utils::describe_scripted_caller; | |
use dom::document::Document; | |
use dom::element::{AttributeMutation, Element, RawLayoutElementHelpers}; | |
use dom::eventtarget::EventTarget; | |
@@ -169,9 +171,14 @@ impl VirtualMethods for HTMLBodyElement { | |
&local_name!("onresize") | &local_name!("onunload") | &local_name!("onerror") | |
=> { | |
let evtarget = window.upcast::<EventTarget>(); // forwarded event | |
- let source_line = 1; //TODO(#9604) obtain current JS execution line | |
- evtarget.set_event_handler_uncompiled(window.get_url(), | |
- source_line, | |
+ let caller = describe_scripted_caller(); | |
+ let (filename, line, column) = match caller { | |
+ Some(c) => (c.filename, c.line, c.column), | |
+ None => (window.get_url().to_string(), 1, 0), | |
+ }; | |
+ evtarget.set_event_handler_uncompiled(filename, | |
+ line, | |
+ column, | |
&name[2..], | |
DOMString::from((**attr.value()).to_owned())); | |
false | |
diff --git a/components/script/dom/htmlelement.rs b/components/script/dom/htmlelement.rs | |
index 6725fdb..f351818 100644 | |
--- a/components/script/dom/htmlelement.rs | |
+++ b/components/script/dom/htmlelement.rs | |
@@ -14,7 +14,9 @@ use dom::bindings::error::{Error, ErrorResult}; | |
use dom::bindings::inheritance::{ElementTypeId, HTMLElementTypeId, NodeTypeId}; | |
use dom::bindings::inheritance::Castable; | |
use dom::bindings::js::{JS, MutNullableJS, Root, RootedReference}; | |
+use dom::bindings::reflector::DomObject; | |
use dom::bindings::str::DOMString; | |
+use dom::bindings::utils::describe_scripted_caller; | |
use dom::cssstyledeclaration::{CSSModificationAccess, CSSStyleDeclaration, CSSStyleOwner}; | |
use dom::document::{Document, FocusType}; | |
use dom::domstringmap::DOMStringMap; | |
@@ -511,9 +513,14 @@ impl VirtualMethods for HTMLElement { | |
match (attr.local_name(), mutation) { | |
(name, AttributeMutation::Set(_)) if name.starts_with("on") => { | |
let evtarget = self.upcast::<EventTarget>(); | |
- let source_line = 1; //TODO(#9604) get current JS execution line | |
- evtarget.set_event_handler_uncompiled(window_from_node(self).get_url(), | |
- source_line, | |
+ let caller = describe_scripted_caller(); | |
+ let (filename, line, column) = match caller { | |
+ Some(c) => (c.filename, c.line, c.column), | |
+ None => (window_from_node(self).get_url().to_string(), 1, 0), | |
+ }; | |
+ evtarget.set_event_handler_uncompiled(filename, | |
+ line, | |
+ column, | |
&name[2..], | |
// FIXME(ajeffrey): Convert directly from AttrValue to DOMString | |
DOMString::from(&**attr.value())); | |
diff --git a/tests/wpt/mozilla/tests/mozilla/track_line.html b/tests/wpt/mozilla/tests/mozilla/track_line.html | |
index b181b70..3e037bd 100644 | |
--- a/tests/wpt/mozilla/tests/mozilla/track_line.html | |
+++ b/tests/wpt/mozilla/tests/mozilla/track_line.html | |
@@ -7,16 +7,26 @@ | |
setup({allow_uncaught_exception:true}); | |
var t = async_test("error event has proper line number"); | |
var errors = 0; | |
-var expected_lines = [21, 4]; | |
+var expected_lines = [[location.href, 27], | |
+ [location.href, 31], | |
+ [location.href.replace('track_line.html', 'resources/external.js'), 4]]; | |
window.addEventListener('error', t.step_func(function(e) { | |
assert_true(e instanceof ErrorEvent); | |
- assert_equals(e.lineno, expected_lines[errors]); | |
+ var expected = expected_lines[errors]; | |
+ assert_equals(e.filename, expected[0]); | |
+ assert_equals(e.lineno, expected[1]); | |
errors++; | |
- if (errors == 2) { | |
+ if (errors == expected_lines.length) { | |
t.done(); | |
} | |
}), true); | |
</script> | |
+<div id="testdiv"></div> | |
+<script> | |
+ var div = document.querySelector('#testdiv'); | |
+ div.setAttribute('onclick', 'this_is_a_js_error'); | |
+ div.dispatchEvent(new Event('click')); | |
+</script> | |
<script> | |
this_is_a_js_error | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment