mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
Auto merge of #25534 - pshaughn:compiledeventscope, r=jdm
Put target element, form owner, and element document on scope chain of compiled events Event listeners that are created from a function object just get whatever closure the function object had, but event listeners created from a string need a special closure that acts like they were defined inside a series of `with` statements. This now happens. The existing WPT test for it, html/webappapis/scripting/events/compile-event-handler-lexical-scopes.html, also relies on other behavior we don't have, so I added an easier version of the test that doesn't involve bubbling or capturing and doesn't check any IDL properties we don't have. This new test will eventually be redundant when we have everything else the upstream test expects. --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #25517 <!-- Either: --> - [X] There are tests for these changes <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
This commit is contained in:
commit
91877875b9
3 changed files with 95 additions and 11 deletions
|
@ -30,6 +30,7 @@ use crate::dom::element::Element;
|
|||
use crate::dom::errorevent::ErrorEvent;
|
||||
use crate::dom::event::{Event, EventBubbles, EventCancelable, EventStatus};
|
||||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::htmlformelement::FormControlElementHelpers;
|
||||
use crate::dom::node::document_from_node;
|
||||
use crate::dom::virtualmethods::VirtualMethods;
|
||||
use crate::dom::window::Window;
|
||||
|
@ -452,35 +453,50 @@ impl EventTarget {
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#getting-the-current-value-of-the-event-handler
|
||||
// step 3
|
||||
#[allow(unsafe_code)]
|
||||
fn get_compiled_event_handler(
|
||||
&self,
|
||||
handler: InternalRawUncompiledHandler,
|
||||
ty: &Atom,
|
||||
) -> Option<CommonEventHandler> {
|
||||
// Step 1.1
|
||||
// Step 3.1
|
||||
let element = self.downcast::<Element>();
|
||||
let document = match element {
|
||||
Some(element) => document_from_node(element),
|
||||
None => self.downcast::<Window>().unwrap().Document(),
|
||||
};
|
||||
|
||||
// Step 1.2
|
||||
// Step 3.2
|
||||
if !document.is_scripting_enabled() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Step 1.3
|
||||
// Step 3.3
|
||||
let body: Vec<u16> = handler.source.encode_utf16().collect();
|
||||
|
||||
// TODO step 1.5 (form owner)
|
||||
// Step 3.4 is handler.line
|
||||
|
||||
// Step 1.6
|
||||
// Step 3.5
|
||||
let form_owner = element
|
||||
.and_then(|e| e.as_maybe_form_control())
|
||||
.and_then(|f| f.form_owner());
|
||||
|
||||
// Step 3.6 TODO: settings objects not implemented
|
||||
|
||||
// Step 3.7 is written as though we call the parser separately
|
||||
// from the compiler; since we just call CompileFunction with
|
||||
// source text, we handle parse errors later
|
||||
|
||||
// Step 3.8 TODO: settings objects not implemented
|
||||
|
||||
// Step 3.9
|
||||
let window = document.window();
|
||||
|
||||
let url_serialized = CString::new(handler.url.to_string()).unwrap();
|
||||
let name = CString::new(&**ty).unwrap();
|
||||
|
||||
// Step 3.9, subsection ParameterList
|
||||
static mut ARG_NAMES: [*const c_char; 1] = [b"event\0" as *const u8 as *const c_char];
|
||||
static mut ERROR_ARG_NAMES: [*const c_char; 5] = [
|
||||
b"event\0" as *const u8 as *const c_char,
|
||||
|
@ -489,7 +505,6 @@ impl EventTarget {
|
|||
b"colno\0" as *const u8 as *const c_char,
|
||||
b"error\0" as *const u8 as *const c_char,
|
||||
];
|
||||
// step 10
|
||||
let is_error = ty == &atom!("error") && self.is::<Window>();
|
||||
let args = unsafe {
|
||||
if is_error {
|
||||
|
@ -501,11 +516,19 @@ impl EventTarget {
|
|||
|
||||
let cx = window.get_cx();
|
||||
let options = CompileOptionsWrapper::new(*cx, url_serialized.as_ptr(), handler.line as u32);
|
||||
// TODO step 1.10.1-3 (document, form owner, element in scope chain)
|
||||
|
||||
// Step 3.9, subsection Scope steps 1-6
|
||||
let scopechain = AutoObjectVectorWrapper::new(*cx);
|
||||
|
||||
let _ac = enter_realm(&*window);
|
||||
if let Some(element) = element {
|
||||
scopechain.append(document.reflector().get_jsobject().get());
|
||||
if let Some(form_owner) = form_owner {
|
||||
scopechain.append(form_owner.reflector().get_jsobject().get());
|
||||
}
|
||||
scopechain.append(element.reflector().get_jsobject().get());
|
||||
}
|
||||
|
||||
let _ac = enter_realm(&*window); // TODO 3.8 should replace this
|
||||
rooted!(in(*cx) let mut handler = ptr::null_mut::<JSFunction>());
|
||||
let rv = unsafe {
|
||||
CompileFunction(
|
||||
|
@ -525,17 +548,20 @@ impl EventTarget {
|
|||
)
|
||||
};
|
||||
if !rv || handler.get().is_null() {
|
||||
// Step 1.8.2
|
||||
// Step 3.7
|
||||
unsafe {
|
||||
let _ac = JSAutoRealm::new(*cx, self.reflector().get_jsobject().get());
|
||||
// FIXME(#13152): dispatch error event.
|
||||
report_pending_exception(*cx, false);
|
||||
}
|
||||
// Step 1.8.1 / 1.8.3
|
||||
return None;
|
||||
}
|
||||
|
||||
// TODO step 1.11-13
|
||||
// Step 3.10 happens when we drop _ac
|
||||
|
||||
// TODO Step 3.11
|
||||
|
||||
// Step 3.12
|
||||
let funobj = unsafe { JS_GetFunctionObject(handler.get()) };
|
||||
assert!(!funobj.is_null());
|
||||
// Step 1.14
|
||||
|
|
|
@ -11453,6 +11453,12 @@
|
|||
{}
|
||||
]
|
||||
],
|
||||
"mozilla/compile-event-handler-lexical-scopes-simple.html": [
|
||||
[
|
||||
"mozilla/compile-event-handler-lexical-scopes-simple.html",
|
||||
{}
|
||||
]
|
||||
],
|
||||
"mozilla/createEvent-storageevent.html": [
|
||||
[
|
||||
"mozilla/createEvent-storageevent.html",
|
||||
|
@ -18589,6 +18595,10 @@
|
|||
"8e06ffcc0933719b4b79ea6656d6635cc121d900",
|
||||
"testharness"
|
||||
],
|
||||
"mozilla/compile-event-handler-lexical-scopes-simple.html": [
|
||||
"7d1e1839390ea16183bffd09eef4e3445d5d8e16",
|
||||
"testharness"
|
||||
],
|
||||
"mozilla/createEvent-storageevent.html": [
|
||||
"f5deb0173b1459a655ecd62d1c1fd1b45c42c35b",
|
||||
"testharness"
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Lexical scopes when compiling an inline event handler (easy mode)</title>
|
||||
<link rel="help" href="https://html.spec.whatwg.org/C/#getting-the-current-value-of-the-event-handler">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<script>
|
||||
setup({allow_uncaught_exception: true});
|
||||
</script>
|
||||
|
||||
<!-- Testing just the core of
|
||||
html/webappapis/scripting/events/compile-event-handler-lexical-scopes.html
|
||||
to have a test for it that works while #25199 is open -->
|
||||
|
||||
<form method="POST">
|
||||
<input value="hello" onclick="
|
||||
window.testResults.value = value;
|
||||
window.testResults.self = this;
|
||||
window.testResults.method = method;
|
||||
window.testResults.contentType = contentType;
|
||||
window.testResults.input_var = input_var;
|
||||
window.testResults.form_var = form_var;
|
||||
window.testResults.doc_var = doc_var;
|
||||
">
|
||||
</form>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
test(() => {
|
||||
window.testResults = {};
|
||||
|
||||
document.querySelector("input").input_var = 1;
|
||||
document.querySelector("form").form_var = 2;
|
||||
document.doc_var = 3;
|
||||
|
||||
document.querySelector("input").click();
|
||||
|
||||
assert_equals(window.testResults.value, "hello");
|
||||
assert_in_array(window.testResults.method, ["POST","post"]);
|
||||
assert_equals(window.testResults.contentType, "text/html");
|
||||
assert_equals(window.testResults.self, document.querySelector("input"));
|
||||
assert_equals(window.testResults.input_var, 1);
|
||||
assert_equals(window.testResults.form_var, 2);
|
||||
assert_equals(window.testResults.doc_var, 3);
|
||||
}, "Element, form owner, and document all expose expandos and IDL properties");
|
||||
</script>
|
Loading…
Add table
Add a link
Reference in a new issue