LocationObject.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /*
  2. * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/FlyString.h>
  7. #include <AK/StringBuilder.h>
  8. #include <LibJS/Runtime/Completion.h>
  9. #include <LibWeb/Bindings/LocationObject.h>
  10. #include <LibWeb/Bindings/WindowObject.h>
  11. #include <LibWeb/DOM/Document.h>
  12. #include <LibWeb/DOM/Window.h>
  13. namespace Web::Bindings {
  14. LocationObject::LocationObject(JS::GlobalObject& global_object)
  15. : Object(*global_object.object_prototype())
  16. {
  17. }
  18. void LocationObject::initialize(JS::GlobalObject& global_object)
  19. {
  20. auto& vm = global_object.vm();
  21. Object::initialize(global_object);
  22. u8 attr = JS::Attribute::Writable | JS::Attribute::Enumerable;
  23. define_old_native_accessor("href", href_getter, href_setter, attr);
  24. define_old_native_accessor("host", host_getter, {}, attr);
  25. define_old_native_accessor("hostname", hostname_getter, {}, attr);
  26. define_old_native_accessor("pathname", pathname_getter, {}, attr);
  27. define_old_native_accessor("hash", hash_getter, {}, attr);
  28. define_old_native_accessor("search", search_getter, {}, attr);
  29. define_old_native_accessor("protocol", protocol_getter, {}, attr);
  30. define_old_native_accessor("port", port_getter, {}, attr);
  31. define_old_native_function("reload", reload, 0, JS::Attribute::Enumerable);
  32. define_old_native_function("replace", replace, 1, JS::Attribute::Enumerable);
  33. define_old_native_function(vm.names.toString, href_getter, 0, JS::Attribute::Enumerable);
  34. }
  35. LocationObject::~LocationObject()
  36. {
  37. }
  38. JS_DEFINE_OLD_NATIVE_FUNCTION(LocationObject::href_getter)
  39. {
  40. auto& window = static_cast<WindowObject&>(global_object);
  41. return JS::js_string(vm, window.impl().associated_document().url().to_string());
  42. }
  43. JS_DEFINE_OLD_NATIVE_FUNCTION(LocationObject::href_setter)
  44. {
  45. auto& window = static_cast<WindowObject&>(global_object);
  46. auto new_href = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
  47. auto href_url = window.impl().associated_document().parse_url(new_href);
  48. if (!href_url.is_valid()) {
  49. vm.throw_exception<JS::URIError>(global_object, String::formatted("Invalid URL '{}'", new_href));
  50. return {};
  51. }
  52. window.impl().did_set_location_href({}, href_url);
  53. return JS::js_undefined();
  54. }
  55. JS_DEFINE_OLD_NATIVE_FUNCTION(LocationObject::pathname_getter)
  56. {
  57. auto& window = static_cast<WindowObject&>(global_object);
  58. return JS::js_string(vm, window.impl().associated_document().url().path());
  59. }
  60. JS_DEFINE_OLD_NATIVE_FUNCTION(LocationObject::hostname_getter)
  61. {
  62. auto& window = static_cast<WindowObject&>(global_object);
  63. return JS::js_string(vm, window.impl().associated_document().url().host());
  64. }
  65. JS_DEFINE_OLD_NATIVE_FUNCTION(LocationObject::host_getter)
  66. {
  67. auto& window = static_cast<WindowObject&>(global_object);
  68. auto url = window.impl().associated_document().url();
  69. return JS::js_string(vm, String::formatted("{}:{}", url.host(), url.port_or_default()));
  70. }
  71. JS_DEFINE_OLD_NATIVE_FUNCTION(LocationObject::hash_getter)
  72. {
  73. auto& window = static_cast<WindowObject&>(global_object);
  74. auto fragment = window.impl().associated_document().url().fragment();
  75. if (!fragment.length())
  76. return JS::js_string(vm, "");
  77. StringBuilder builder;
  78. builder.append('#');
  79. builder.append(fragment);
  80. return JS::js_string(vm, builder.to_string());
  81. }
  82. JS_DEFINE_OLD_NATIVE_FUNCTION(LocationObject::search_getter)
  83. {
  84. auto& window = static_cast<WindowObject&>(global_object);
  85. auto query = window.impl().associated_document().url().query();
  86. if (!query.length())
  87. return JS::js_string(vm, "");
  88. StringBuilder builder;
  89. builder.append('?');
  90. builder.append(query);
  91. return JS::js_string(vm, builder.to_string());
  92. }
  93. JS_DEFINE_OLD_NATIVE_FUNCTION(LocationObject::protocol_getter)
  94. {
  95. auto& window = static_cast<WindowObject&>(global_object);
  96. StringBuilder builder;
  97. builder.append(window.impl().associated_document().url().protocol());
  98. builder.append(':');
  99. return JS::js_string(vm, builder.to_string());
  100. }
  101. JS_DEFINE_OLD_NATIVE_FUNCTION(LocationObject::port_getter)
  102. {
  103. auto& window = static_cast<WindowObject&>(global_object);
  104. return JS::Value(window.impl().associated_document().url().port_or_default());
  105. }
  106. JS_DEFINE_OLD_NATIVE_FUNCTION(LocationObject::reload)
  107. {
  108. auto& window = static_cast<WindowObject&>(global_object);
  109. window.impl().did_call_location_reload({});
  110. return JS::js_undefined();
  111. }
  112. JS_DEFINE_OLD_NATIVE_FUNCTION(LocationObject::replace)
  113. {
  114. auto& window = static_cast<WindowObject&>(global_object);
  115. auto url = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
  116. // FIXME: This needs spec compliance work.
  117. window.impl().did_call_location_replace({}, move(url));
  118. return JS::js_undefined();
  119. }
  120. // https://html.spec.whatwg.org/multipage/history.html#location-setprototypeof
  121. JS::ThrowCompletionOr<bool> LocationObject::internal_set_prototype_of(Object* prototype)
  122. {
  123. // 1. Return ! SetImmutablePrototype(this, V).
  124. return MUST(set_immutable_prototype(prototype));
  125. }
  126. // https://html.spec.whatwg.org/multipage/history.html#location-isextensible
  127. JS::ThrowCompletionOr<bool> LocationObject::internal_is_extensible() const
  128. {
  129. // 1. Return true.
  130. return true;
  131. }
  132. // https://html.spec.whatwg.org/multipage/history.html#location-preventextensions
  133. JS::ThrowCompletionOr<bool> LocationObject::internal_prevent_extensions()
  134. {
  135. // 1. Return false.
  136. return false;
  137. }
  138. }