GlobalEventHandlers.cpp 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. /*
  2. * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibJS/Interpreter.h>
  7. #include <LibJS/Parser.h>
  8. #include <LibJS/Runtime/OrdinaryFunctionObject.h>
  9. #include <LibWeb/DOM/Document.h>
  10. #include <LibWeb/DOM/EventListener.h>
  11. #include <LibWeb/HTML/EventHandler.h>
  12. #include <LibWeb/HTML/EventNames.h>
  13. #include <LibWeb/HTML/GlobalEventHandlers.h>
  14. #include <LibWeb/UIEvents/EventNames.h>
  15. namespace Web::HTML {
  16. #undef __ENUMERATE
  17. #define __ENUMERATE(attribute_name, event_name) \
  18. void GlobalEventHandlers::set_##attribute_name(HTML::EventHandler value) \
  19. { \
  20. set_event_handler_attribute(event_name, move(value)); \
  21. } \
  22. HTML::EventHandler GlobalEventHandlers::attribute_name() \
  23. { \
  24. return get_event_handler_attribute(event_name); \
  25. }
  26. ENUMERATE_GLOBAL_EVENT_HANDLERS(__ENUMERATE)
  27. #undef __ENUMERATE
  28. GlobalEventHandlers::~GlobalEventHandlers()
  29. {
  30. }
  31. void GlobalEventHandlers::set_event_handler_attribute(const FlyString& name, HTML::EventHandler value)
  32. {
  33. auto& self = global_event_handlers_to_event_target();
  34. RefPtr<DOM::EventListener> listener;
  35. if (!value.callback.is_null()) {
  36. listener = adopt_ref(*new DOM::EventListener(move(value.callback)));
  37. } else {
  38. StringBuilder builder;
  39. builder.appendff("function {}(event) {{\n{}\n}}", name, value.string);
  40. auto parser = JS::Parser(JS::Lexer(builder.string_view()));
  41. auto program = parser.parse_function_node<JS::FunctionExpression>();
  42. if (parser.has_errors()) {
  43. dbgln("Failed to parse script in event handler attribute '{}'", name);
  44. return;
  45. }
  46. auto* function = JS::OrdinaryFunctionObject::create(self.script_execution_context()->interpreter().global_object(), name, program->body(), program->parameters(), program->function_length(), nullptr, JS::FunctionKind::Regular, false, false);
  47. VERIFY(function);
  48. listener = adopt_ref(*new DOM::EventListener(JS::make_handle(static_cast<JS::FunctionObject*>(function))));
  49. }
  50. if (listener) {
  51. for (auto& registered_listener : self.listeners()) {
  52. if (registered_listener.event_name == name && registered_listener.listener->is_attribute()) {
  53. self.remove_event_listener(name, registered_listener.listener);
  54. break;
  55. }
  56. }
  57. self.add_event_listener(name, listener.release_nonnull());
  58. }
  59. }
  60. HTML::EventHandler GlobalEventHandlers::get_event_handler_attribute(const FlyString& name)
  61. {
  62. auto& self = global_event_handlers_to_event_target();
  63. for (auto& listener : self.listeners()) {
  64. if (listener.event_name == name && listener.listener->is_attribute()) {
  65. return HTML::EventHandler { JS::make_handle(&listener.listener->function()) };
  66. }
  67. }
  68. return {};
  69. }
  70. }