mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 03:47:35 +00:00
LibWeb: Ignore window-forwarded document.body.onfoo in detached DOM
Normally, assigning to e.g document.body.onload will forward to window.onload. However, in a detached DOM tree, there is no associated window, so we have nowhere to forward to, making this a no-op. The bulk of this change is making Document::window() return a nullable pointer, as documents created by DOMParser or DOMImplementation do not have an associated window object, and so must be able to return null from here.
This commit is contained in:
parent
7139d5945f
commit
b98a2be96b
28 changed files with 92 additions and 61 deletions
|
@ -55,7 +55,7 @@ static void run_focus_update_steps(Vector<JS::Handle<DOM::Node>> old_chain, Vect
|
|||
blur_event_target = entry.ptr();
|
||||
} else if (is<DOM::Document>(*entry)) {
|
||||
// If entry is a Document object, let blur event target be that Document object's relevant global object.
|
||||
blur_event_target = &static_cast<DOM::Document&>(*entry).window();
|
||||
blur_event_target = static_cast<DOM::Document&>(*entry).window();
|
||||
}
|
||||
|
||||
// 3. If entry is the last entry in old chain, and entry is an Element,
|
||||
|
@ -105,7 +105,7 @@ static void run_focus_update_steps(Vector<JS::Handle<DOM::Node>> old_chain, Vect
|
|||
focus_event_target = entry.ptr();
|
||||
} else if (is<DOM::Document>(*entry)) {
|
||||
// If entry is a Document object, let focus event target be that Document object's relevant global object.
|
||||
focus_event_target = &static_cast<DOM::Document&>(*entry).window();
|
||||
focus_event_target = static_cast<DOM::Document&>(*entry).window();
|
||||
}
|
||||
|
||||
// 3. If entry is the last entry in new chain, and entry is an Element,
|
||||
|
|
|
@ -12,14 +12,17 @@
|
|||
namespace Web::HTML {
|
||||
|
||||
#undef __ENUMERATE
|
||||
#define __ENUMERATE(attribute_name, event_name) \
|
||||
void GlobalEventHandlers::set_##attribute_name(WebIDL::CallbackType* value) \
|
||||
{ \
|
||||
global_event_handlers_to_event_target(event_name).set_event_handler_attribute(event_name, value); \
|
||||
} \
|
||||
WebIDL::CallbackType* GlobalEventHandlers::attribute_name() \
|
||||
{ \
|
||||
return global_event_handlers_to_event_target(event_name).event_handler_attribute(event_name); \
|
||||
#define __ENUMERATE(attribute_name, event_name) \
|
||||
void GlobalEventHandlers::set_##attribute_name(WebIDL::CallbackType* value) \
|
||||
{ \
|
||||
if (auto event_target = global_event_handlers_to_event_target(event_name)) \
|
||||
event_target->set_event_handler_attribute(event_name, value); \
|
||||
} \
|
||||
WebIDL::CallbackType* GlobalEventHandlers::attribute_name() \
|
||||
{ \
|
||||
if (auto event_target = global_event_handlers_to_event_target(event_name)) \
|
||||
return event_target->event_handler_attribute(event_name); \
|
||||
return nullptr; \
|
||||
}
|
||||
ENUMERATE_GLOBAL_EVENT_HANDLERS(__ENUMERATE)
|
||||
#undef __ENUMERATE
|
||||
|
|
|
@ -94,7 +94,7 @@ public:
|
|||
#undef __ENUMERATE
|
||||
|
||||
protected:
|
||||
virtual DOM::EventTarget& global_event_handlers_to_event_target(FlyString const& event_name) = 0;
|
||||
virtual JS::GCPtr<DOM::EventTarget> global_event_handlers_to_event_target(FlyString const& event_name) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ void HTMLBodyElement::attribute_changed(FlyString const& name, Optional<String>
|
|||
#undef __ENUMERATE
|
||||
}
|
||||
|
||||
DOM::EventTarget& HTMLBodyElement::global_event_handlers_to_event_target(FlyString const& event_name)
|
||||
JS::GCPtr<DOM::EventTarget> HTMLBodyElement::global_event_handlers_to_event_target(FlyString const& event_name)
|
||||
{
|
||||
// NOTE: This is a little weird, but IIUC document.body.onload actually refers to window.onload
|
||||
// NOTE: document.body can return either a HTMLBodyElement or HTMLFrameSetElement, so both these elements must support this mapping.
|
||||
|
@ -104,7 +104,7 @@ DOM::EventTarget& HTMLBodyElement::global_event_handlers_to_event_target(FlyStri
|
|||
return *this;
|
||||
}
|
||||
|
||||
DOM::EventTarget& HTMLBodyElement::window_event_handlers_to_event_target()
|
||||
JS::GCPtr<DOM::EventTarget> HTMLBodyElement::window_event_handlers_to_event_target()
|
||||
{
|
||||
// All WindowEventHandlers on HTMLFrameSetElement (e.g. document.body.onrejectionhandled) are mapped to window.on{event}.
|
||||
// NOTE: document.body can return either a HTMLBodyElement or HTMLFrameSetElement, so both these elements must support this mapping.
|
||||
|
|
|
@ -38,10 +38,10 @@ private:
|
|||
virtual void initialize(JS::Realm&) override;
|
||||
|
||||
// ^HTML::GlobalEventHandlers
|
||||
virtual EventTarget& global_event_handlers_to_event_target(FlyString const& event_name) override;
|
||||
virtual JS::GCPtr<DOM::EventTarget> global_event_handlers_to_event_target(FlyString const& event_name) override;
|
||||
|
||||
// ^HTML::WindowEventHandlers
|
||||
virtual EventTarget& window_event_handlers_to_event_target() override;
|
||||
virtual JS::GCPtr<DOM::EventTarget> window_event_handlers_to_event_target() override;
|
||||
|
||||
RefPtr<CSS::ImageStyleValue> m_background_style_value;
|
||||
};
|
||||
|
|
|
@ -82,7 +82,7 @@ private:
|
|||
virtual bool is_html_element() const final { return true; }
|
||||
|
||||
// ^HTML::GlobalEventHandlers
|
||||
virtual DOM::EventTarget& global_event_handlers_to_event_target(FlyString const&) override { return *this; }
|
||||
virtual JS::GCPtr<DOM::EventTarget> global_event_handlers_to_event_target(FlyString const&) override { return *this; }
|
||||
virtual void did_receive_focus() override;
|
||||
|
||||
JS::GCPtr<DOMStringMap> m_dataset;
|
||||
|
|
|
@ -38,7 +38,7 @@ void HTMLFrameSetElement::attribute_changed(FlyString const& name, Optional<Stri
|
|||
#undef __ENUMERATE
|
||||
}
|
||||
|
||||
DOM::EventTarget& HTMLFrameSetElement::global_event_handlers_to_event_target(FlyString const& event_name)
|
||||
JS::GCPtr<DOM::EventTarget> HTMLFrameSetElement::global_event_handlers_to_event_target(FlyString const& event_name)
|
||||
{
|
||||
// NOTE: This is a little weird, but IIUC document.body.onload actually refers to window.onload
|
||||
// NOTE: document.body can return either a HTMLBodyElement or HTMLFrameSetElement, so both these elements must support this mapping.
|
||||
|
@ -48,7 +48,7 @@ DOM::EventTarget& HTMLFrameSetElement::global_event_handlers_to_event_target(Fly
|
|||
return *this;
|
||||
}
|
||||
|
||||
DOM::EventTarget& HTMLFrameSetElement::window_event_handlers_to_event_target()
|
||||
JS::GCPtr<DOM::EventTarget> HTMLFrameSetElement::window_event_handlers_to_event_target()
|
||||
{
|
||||
// All WindowEventHandlers on HTMLFrameSetElement (e.g. document.body.onrejectionhandled) are mapped to window.on{event}.
|
||||
// NOTE: document.body can return either a HTMLBodyElement or HTMLFrameSetElement, so both these elements must support this mapping.
|
||||
|
|
|
@ -28,10 +28,10 @@ private:
|
|||
virtual void attribute_changed(FlyString const&, Optional<String> const&) override;
|
||||
|
||||
// ^HTML::GlobalEventHandlers
|
||||
virtual EventTarget& global_event_handlers_to_event_target(FlyString const& event_name) override;
|
||||
virtual JS::GCPtr<EventTarget> global_event_handlers_to_event_target(FlyString const& event_name) override;
|
||||
|
||||
// ^HTML::WindowEventHandlers
|
||||
virtual EventTarget& window_event_handlers_to_event_target() override;
|
||||
virtual JS::GCPtr<EventTarget> window_event_handlers_to_event_target() override;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -941,7 +941,7 @@ static void update_the_source_set(DOM::Element& element)
|
|||
if (child->has_attribute(HTML::AttributeNames::media)) {
|
||||
auto media_query = parse_media_query(CSS::Parser::ParsingContext { element.document() },
|
||||
child->get_attribute_value(HTML::AttributeNames::media));
|
||||
if (!media_query || !media_query->evaluate(element.document().window())) {
|
||||
if (!media_query || !element.document().window() || !media_query->evaluate(*element.document().window())) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ void HTMLMetaElement::inserted()
|
|||
auto media = attribute(AttributeNames::media);
|
||||
if (media.has_value()) {
|
||||
auto query = parse_media_query(context, media.value());
|
||||
if (!query->evaluate(document().window()))
|
||||
if (document().window() && !query->evaluate(*document().window()))
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -328,7 +328,7 @@ void HTMLParser::the_end(JS::NonnullGCPtr<DOM::Document> document, JS::GCPtr<HTM
|
|||
return;
|
||||
|
||||
// 3. Let window be the Document's relevant global object.
|
||||
JS::NonnullGCPtr<Window> window = document->window();
|
||||
auto& window = verify_cast<Window>(relevant_global_object(*document));
|
||||
|
||||
// 4. Set the Document's load timing info's load event start time to the current high resolution time given window.
|
||||
document->load_timing_info().load_event_start_time = HighResolutionTime::unsafe_shared_current_time();
|
||||
|
@ -336,7 +336,7 @@ void HTMLParser::the_end(JS::NonnullGCPtr<DOM::Document> document, JS::GCPtr<HTM
|
|||
// 5. Fire an event named load at window, with legacy target override flag set.
|
||||
// FIXME: The legacy target override flag is currently set by a virtual override of dispatch_event()
|
||||
// We should reorganize this so that the flag appears explicitly here instead.
|
||||
window->dispatch_event(DOM::Event::create(document->realm(), HTML::EventNames::load));
|
||||
window.dispatch_event(DOM::Event::create(document->realm(), HTML::EventNames::load));
|
||||
|
||||
// FIXME: 6. Invoke WebDriver BiDi load complete with the Document's browsing context, and a new WebDriver BiDi navigation status whose id is the Document object's navigation id, status is "complete", and url is the Document object's URL.
|
||||
|
||||
|
@ -352,7 +352,7 @@ void HTMLParser::the_end(JS::NonnullGCPtr<DOM::Document> document, JS::GCPtr<HTM
|
|||
document->set_page_showing(true);
|
||||
|
||||
// 11. Fire a page transition event named pageshow at window with false.
|
||||
window->fire_a_page_transition_event(HTML::EventNames::pageshow, false);
|
||||
window.fire_a_page_transition_event(HTML::EventNames::pageshow, false);
|
||||
|
||||
// 12. Completely finish loading the Document.
|
||||
document->completely_finish_loading();
|
||||
|
|
|
@ -79,7 +79,7 @@ JS_DEFINE_ALLOCATOR(Window);
|
|||
void run_animation_frame_callbacks(DOM::Document& document, double now)
|
||||
{
|
||||
// FIXME: Bring this closer to the spec.
|
||||
document.window().animation_frame_callback_driver().run(now);
|
||||
document.window()->animation_frame_callback_driver().run(now);
|
||||
}
|
||||
|
||||
class IdleCallback : public RefCounted<IdleCallback> {
|
||||
|
|
|
@ -218,10 +218,10 @@ private:
|
|||
virtual void finalize() override;
|
||||
|
||||
// ^HTML::GlobalEventHandlers
|
||||
virtual DOM::EventTarget& global_event_handlers_to_event_target(FlyString const&) override { return *this; }
|
||||
virtual JS::GCPtr<DOM::EventTarget> global_event_handlers_to_event_target(FlyString const&) override { return *this; }
|
||||
|
||||
// ^HTML::WindowEventHandlers
|
||||
virtual DOM::EventTarget& window_event_handlers_to_event_target() override { return *this; }
|
||||
virtual JS::GCPtr<DOM::EventTarget> window_event_handlers_to_event_target() override { return *this; }
|
||||
|
||||
void invoke_idle_callbacks();
|
||||
|
||||
|
|
|
@ -11,14 +11,17 @@
|
|||
namespace Web::HTML {
|
||||
|
||||
#undef __ENUMERATE
|
||||
#define __ENUMERATE(attribute_name, event_name) \
|
||||
void WindowEventHandlers::set_##attribute_name(WebIDL::CallbackType* value) \
|
||||
{ \
|
||||
window_event_handlers_to_event_target().set_event_handler_attribute(event_name, value); \
|
||||
} \
|
||||
WebIDL::CallbackType* WindowEventHandlers::attribute_name() \
|
||||
{ \
|
||||
return window_event_handlers_to_event_target().event_handler_attribute(event_name); \
|
||||
#define __ENUMERATE(attribute_name, event_name) \
|
||||
void WindowEventHandlers::set_##attribute_name(WebIDL::CallbackType* value) \
|
||||
{ \
|
||||
if (auto event_target = window_event_handlers_to_event_target()) \
|
||||
event_target->set_event_handler_attribute(event_name, value); \
|
||||
} \
|
||||
WebIDL::CallbackType* WindowEventHandlers::attribute_name() \
|
||||
{ \
|
||||
if (auto event_target = window_event_handlers_to_event_target()) \
|
||||
return event_target->event_handler_attribute(event_name); \
|
||||
return nullptr; \
|
||||
}
|
||||
ENUMERATE_WINDOW_EVENT_HANDLERS(__ENUMERATE)
|
||||
#undef __ENUMERATE
|
||||
|
|
|
@ -41,7 +41,7 @@ public:
|
|||
#undef __ENUMERATE
|
||||
|
||||
protected:
|
||||
virtual DOM::EventTarget& window_event_handlers_to_event_target() = 0;
|
||||
virtual JS::GCPtr<DOM::EventTarget> window_event_handlers_to_event_target() = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue