LibWeb: Convert the Location object to IDL

This includes:

- Moving it from Bindings/ to HTML/
- Renaming it from LocationObject to Location
- Removing the manual definitions of the constructor and prototype
- Removing special handling of the Location interface from the bindings
  generator
- Converting the JS_DEFINE_NATIVE_FUNCTIONs to regular functions
  returning DeprecatedString instead of PrimitiveString
- Adding missing (no-op) setters for the various attributes, which are
  expected to exist by the bindings generator
This commit is contained in:
Linus Groh 2023-01-18 17:41:12 +00:00 committed by Tim Flynn
parent 78d6de2ec1
commit afc055c088
19 changed files with 271 additions and 333 deletions

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021-2023, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
* Copyright (c) 2022, Ali Mohammad Pur <mpfard@serenityos.org>
*
@ -2380,7 +2380,6 @@ void generate_prototype_implementation(IDL::Interface const& interface, StringBu
#include <LibJS/Runtime/Value.h>
#include <LibWeb/Bindings/@prototype_class@.h>
#include <LibWeb/Bindings/ExceptionOrUtils.h>
#include <LibWeb/Bindings/LocationObject.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/DOM/Element.h>
#include <LibWeb/DOM/Event.h>

View file

@ -89,11 +89,10 @@ class @legacy_constructor_class@;)~~~");
add_interface(gen, interface.prototype_class, interface.constructor_class, lookup_legacy_constructor(interface));
}
// FIXME: Special case window. We should convert Window and Location to use IDL.
// FIXME: Special case window. We should convert Window to use IDL.
{
auto gen = generator.fork();
add_interface(gen, "WindowPrototype"sv, "WindowConstructor"sv, {});
add_interface(gen, "LocationPrototype"sv, "LocationConstructor"sv, {});
}
// FIXME: Special case WebAssembly. We should convert WASM to use IDL.
@ -143,12 +142,10 @@ static ErrorOr<void> generate_intrinsic_definitions(StringView output_path, Vect
}
}
// FIXME: Special case window. We should convert Window and Location to use IDL.
// FIXME: Special case window. We should convert Window to use IDL.
generator.append(R"~~~(
#include <LibWeb/Bindings/WindowConstructor.h>
#include <LibWeb/Bindings/WindowPrototype.h>
#include <LibWeb/Bindings/LocationConstructor.h>
#include <LibWeb/Bindings/LocationPrototype.h>)~~~");
#include <LibWeb/Bindings/WindowPrototype.h>)~~~");
// FIXME: Special case WebAssembly. We should convert WASM to use IDL.
generator.append(R"~~~(
@ -207,11 +204,10 @@ void Intrinsics::create_web_prototype_and_constructor<@prototype_class@>(JS::Rea
add_interface(gen, interface.name, interface.prototype_class, interface.constructor_class, lookup_legacy_constructor(interface));
}
// FIXME: Special case window. We should convert Window and Location to use IDL
// FIXME: Special case window. We should convert Window to use IDL
{
auto gen = generator.fork();
add_interface(gen, "Window"sv, "WindowPrototype"sv, "WindowConstructor"sv, {});
add_interface(gen, "Location"sv, "LocationPrototype"sv, "LocationConstructor"sv, {});
}
// FIXME: Special case WebAssembly. We should convert WASM to use IDL.
@ -289,12 +285,10 @@ static ErrorOr<void> generate_exposed_interface_implementation(StringView class_
}
}
// FIXME: Special case window. We should convert Window and Location to use IDL
// FIXME: Special case window. We should convert Window to use IDL
if (class_name == "Window"sv) {
generator.append(R"~~~(#include <LibWeb/Bindings/WindowConstructor.h>
#include <LibWeb/Bindings/WindowPrototype.h>
#include <LibWeb/Bindings/LocationConstructor.h>
#include <LibWeb/Bindings/LocationPrototype.h>
)~~~");
}
@ -325,11 +319,10 @@ void add_@global_object_snake_name@_exposed_interfaces(JS::Object& global)
add_interface(gen, interface.name, interface.prototype_class, lookup_legacy_constructor(interface));
}
// FIXME: Special case window. We should convert Window and Location to use IDL
// FIXME: Special case window. We should convert Window to use IDL
if (class_name == "Window"sv) {
auto gen = generator.fork();
add_interface(gen, "Window"sv, "WindowPrototype"sv, {});
add_interface(gen, "Location"sv, "LocationPrototype"sv, {});
}
generator.append(R"~~~(

View file

@ -1,39 +0,0 @@
/*
* Copyright (c) 2022, the SerenityOS developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/Bindings/LocationConstructor.h>
#include <LibWeb/Bindings/LocationPrototype.h>
namespace Web::Bindings {
LocationConstructor::LocationConstructor(JS::Realm& realm)
: NativeFunction(*realm.intrinsics().function_prototype())
{
}
LocationConstructor::~LocationConstructor() = default;
JS::ThrowCompletionOr<JS::Value> LocationConstructor::call()
{
return vm().throw_completion<JS::TypeError>(JS::ErrorType::ConstructorWithoutNew, "Location");
}
JS::ThrowCompletionOr<JS::NonnullGCPtr<JS::Object>> LocationConstructor::construct(FunctionObject&)
{
return vm().throw_completion<JS::TypeError>(JS::ErrorType::NotAConstructor, "Location");
}
void LocationConstructor::initialize(JS::Realm& realm)
{
auto& vm = this->vm();
NativeFunction::initialize(realm);
define_direct_property(vm.names.prototype, &ensure_web_prototype<Bindings::LocationPrototype>(realm, "Location"), 0);
define_direct_property(vm.names.length, JS::Value(0), JS::Attribute::Configurable);
}
}

View file

@ -1,28 +0,0 @@
/*
* Copyright (c) 2022, the SerenityOS developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibJS/Runtime/NativeFunction.h>
namespace Web::Bindings {
class LocationConstructor : public JS::NativeFunction {
JS_OBJECT(LocationConstructor, JS::NativeFunction);
public:
explicit LocationConstructor(JS::Realm&);
virtual void initialize(JS::Realm&) override;
virtual ~LocationConstructor() override;
virtual JS::ThrowCompletionOr<JS::Value> call() override;
virtual JS::ThrowCompletionOr<JS::NonnullGCPtr<JS::Object>> construct(JS::FunctionObject& new_target) override;
private:
virtual bool has_constructor() const override { return true; }
};
}

View file

@ -1,27 +0,0 @@
/*
* Copyright (c) 2022, the SerenityOS developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/Object.h>
#include <LibJS/Runtime/VM.h>
#include <LibWeb/Forward.h>
#include <LibWeb/HTML/Window.h>
namespace Web::Bindings {
class LocationPrototype final : public JS::Object {
JS_OBJECT(LocationPrototype, JS::Object);
public:
explicit LocationPrototype(JS::Realm& realm)
: JS::Object(ConstructWithPrototypeTag::Tag, *realm.intrinsics().object_prototype())
{
}
};
}

View file

@ -2,7 +2,7 @@
* Copyright (c) 2021-2022, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
* Copyright (c) 2022, networkException <networkexception@serenityos.org>
* Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2022-2023, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -16,10 +16,10 @@
#include <LibJS/Runtime/NativeFunction.h>
#include <LibJS/Runtime/VM.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/Bindings/LocationObject.h>
#include <LibWeb/Bindings/MainThreadVM.h>
#include <LibWeb/Bindings/WindowExposedInterfaces.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/HTML/Location.h>
#include <LibWeb/HTML/PromiseRejectionEvent.h>
#include <LibWeb/HTML/Scripting/ClassicScript.h>
#include <LibWeb/HTML/Scripting/Environments.h>
@ -67,7 +67,7 @@ JS::VM& main_thread_vm()
// 8.1.5.1 HostEnsureCanAddPrivateElement(O), https://html.spec.whatwg.org/multipage/webappapis.html#the-hostensurecanaddprivateelement-implementation
vm->host_ensure_can_add_private_element = [](JS::Object const& object) -> JS::ThrowCompletionOr<void> {
// 1. If O is a WindowProxy object, or implements Location, then return Completion { [[Type]]: throw, [[Value]]: a new TypeError }.
if (is<HTML::WindowProxy>(object) || is<LocationObject>(object))
if (is<HTML::WindowProxy>(object) || is<HTML::Location>(object))
return vm->throw_completion<JS::TypeError>("Cannot add private elements to window or location object");
// 2. Return NormalCompletion(unused).

View file

@ -9,7 +9,6 @@ set(SOURCES
Bindings/Intrinsics.cpp
Bindings/LegacyPlatformObject.cpp
Bindings/LocationConstructor.cpp
Bindings/LocationObject.cpp
Bindings/MainThreadVM.cpp
Bindings/OptionConstructor.cpp
Bindings/PlatformObject.cpp
@ -262,6 +261,7 @@ set(SOURCES
HTML/HTMLUnknownElement.cpp
HTML/HTMLVideoElement.cpp
HTML/ImageData.cpp
HTML/Location.cpp
HTML/MessageChannel.cpp
HTML/MessageEvent.cpp
HTML/MessagePort.cpp

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018-2022, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021-2023, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
* Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org>
*
@ -53,6 +53,7 @@
#include <LibWeb/HTML/HTMLLinkElement.h>
#include <LibWeb/HTML/HTMLScriptElement.h>
#include <LibWeb/HTML/HTMLTitleElement.h>
#include <LibWeb/HTML/Location.h>
#include <LibWeb/HTML/MessageEvent.h>
#include <LibWeb/HTML/NavigationParams.h>
#include <LibWeb/HTML/Origin.h>
@ -1667,7 +1668,7 @@ bool Document::is_active() const
}
// https://html.spec.whatwg.org/multipage/history.html#dom-document-location
Bindings::LocationObject* Document::location()
HTML::Location* Document::location()
{
// The Document object's location attribute's getter must return this Document object's relevant global object's Location object,
// if this Document object is fully active, and null otherwise.
@ -1675,7 +1676,7 @@ Bindings::LocationObject* Document::location()
if (!is_fully_active())
return nullptr;
return window().location_object();
return window().location();
}
// https://html.spec.whatwg.org/multipage/interaction.html#dom-document-hidden

View file

@ -339,7 +339,7 @@ public:
JS::NonnullGCPtr<HTML::History> history();
Bindings::LocationObject* location();
HTML::Location* location();
size_t number_of_things_delaying_the_load_event() { return m_number_of_things_delaying_the_load_event; }
void increment_number_of_things_delaying_the_load_event(Badge<DocumentLoadEventDelayer>);

View file

@ -19,6 +19,7 @@
#import <HTML/HTMLElement.idl>
#import <HTML/HTMLHeadElement.idl>
#import <HTML/HTMLScriptElement.idl>
#import <HTML/Location.idl>
#import <Selection/Selection.idl>
// https://dom.spec.whatwg.org/#document
@ -28,7 +29,6 @@ interface Document : Node {
boolean hasFocus();
// FIXME: These attributes currently don't do anything.
[PutForwards=href, LegacyUnforgeable] readonly attribute Location? location;
attribute USVString domain;

View file

@ -319,6 +319,7 @@ class HTMLUListElement;
class HTMLUnknownElement;
class HTMLVideoElement;
class ImageData;
class Location;
class MessageChannel;
class MessageEvent;
class MessagePort;
@ -496,7 +497,6 @@ class URLSearchParamsIterator;
namespace Web::Bindings {
class Intrinsics;
class LocationObject;
class OptionConstructor;
enum class CanPlayTypeResult;
enum class CanvasFillRule;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2022-2023, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -13,9 +13,9 @@
#include <LibJS/Runtime/Object.h>
#include <LibJS/Runtime/PropertyDescriptor.h>
#include <LibJS/Runtime/PropertyKey.h>
#include <LibWeb/Bindings/LocationObject.h>
#include <LibWeb/Bindings/MainThreadVM.h>
#include <LibWeb/HTML/CrossOrigin/AbstractOperations.h>
#include <LibWeb/HTML/Location.h>
#include <LibWeb/HTML/Scripting/Environments.h>
#include <LibWeb/HTML/Window.h>
#include <LibWeb/WebIDL/DOMException.h>
@ -23,13 +23,13 @@
namespace Web::HTML {
// 7.2.3.1 CrossOriginProperties ( O ), https://html.spec.whatwg.org/multipage/browsers.html#crossoriginproperties-(-o-)
Vector<CrossOriginProperty> cross_origin_properties(Variant<Bindings::LocationObject const*, HTML::Window const*> const& object)
Vector<CrossOriginProperty> cross_origin_properties(Variant<HTML::Location const*, HTML::Window const*> const& object)
{
// 1. Assert: O is a Location or Window object.
return object.visit(
// 2. If O is a Location object, then return « { [[Property]]: "href", [[NeedsGet]]: false, [[NeedsSet]]: true }, { [[Property]]: "replace" } ».
[](Bindings::LocationObject const*) -> Vector<CrossOriginProperty> {
[](HTML::Location const*) -> Vector<CrossOriginProperty> {
return {
{ .property = "href"sv, .needs_get = false, .needs_set = true },
{ .property = "replace"sv },
@ -89,11 +89,11 @@ bool is_platform_object_same_origin(JS::Object const& object)
}
// 7.2.3.4 CrossOriginGetOwnPropertyHelper ( O, P ), https://html.spec.whatwg.org/multipage/browsers.html#crossorigingetownpropertyhelper-(-o,-p-)
Optional<JS::PropertyDescriptor> cross_origin_get_own_property_helper(Variant<Bindings::LocationObject*, HTML::Window*> const& object, JS::PropertyKey const& property_key)
Optional<JS::PropertyDescriptor> cross_origin_get_own_property_helper(Variant<HTML::Location*, HTML::Window*> const& object, JS::PropertyKey const& property_key)
{
auto& realm = *Bindings::main_thread_vm().current_realm();
auto const* object_ptr = object.visit([](auto* o) { return static_cast<JS::Object const*>(o); });
auto const object_const_variant = object.visit([](auto* o) { return Variant<Bindings::LocationObject const*, HTML::Window const*> { o }; });
auto const object_const_variant = object.visit([](auto* o) { return Variant<HTML::Location const*, HTML::Window const*> { o }; });
// 1. Let crossOriginKey be a tuple consisting of the current settings object, O's relevant settings object, and P.
auto cross_origin_key = CrossOriginKey {
@ -226,7 +226,7 @@ JS::ThrowCompletionOr<bool> cross_origin_set(JS::VM& vm, JS::Object& object, JS:
}
// 7.2.3.7 CrossOriginOwnPropertyKeys ( O ), https://html.spec.whatwg.org/multipage/browsers.html#crossoriginownpropertykeys-(-o-)
JS::MarkedVector<JS::Value> cross_origin_own_property_keys(Variant<Bindings::LocationObject const*, HTML::Window const*> const& object)
JS::MarkedVector<JS::Value> cross_origin_own_property_keys(Variant<HTML::Location const*, HTML::Window const*> const& object)
{
auto& event_loop = HTML::main_thread_event_loop();
auto& vm = event_loop.vm();

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2022-2023, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -13,13 +13,13 @@
namespace Web::HTML {
Vector<CrossOriginProperty> cross_origin_properties(Variant<Bindings::LocationObject const*, HTML::Window const*> const&);
Vector<CrossOriginProperty> cross_origin_properties(Variant<HTML::Location const*, HTML::Window const*> const&);
bool is_cross_origin_accessible_window_property_name(JS::PropertyKey const&);
JS::ThrowCompletionOr<JS::PropertyDescriptor> cross_origin_property_fallback(JS::VM&, JS::PropertyKey const&);
bool is_platform_object_same_origin(JS::Object const&);
Optional<JS::PropertyDescriptor> cross_origin_get_own_property_helper(Variant<Bindings::LocationObject*, HTML::Window*> const&, JS::PropertyKey const&);
Optional<JS::PropertyDescriptor> cross_origin_get_own_property_helper(Variant<HTML::Location*, HTML::Window*> const&, JS::PropertyKey const&);
JS::ThrowCompletionOr<JS::Value> cross_origin_get(JS::VM&, JS::Object const&, JS::PropertyKey const&, JS::Value receiver);
JS::ThrowCompletionOr<bool> cross_origin_set(JS::VM&, JS::Object&, JS::PropertyKey const&, JS::Value, JS::Value receiver);
JS::MarkedVector<JS::Value> cross_origin_own_property_keys(Variant<Bindings::LocationObject const*, HTML::Window const*> const&);
JS::MarkedVector<JS::Value> cross_origin_own_property_keys(Variant<HTML::Location const*, HTML::Window const*> const&);
}

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2022-2023, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -11,52 +11,36 @@
#include <LibJS/Runtime/Completion.h>
#include <LibJS/Runtime/PropertyDescriptor.h>
#include <LibJS/Runtime/PropertyKey.h>
#include <LibWeb/Bindings/LocationObject.h>
#include <LibWeb/Bindings/LocationPrototype.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/HTML/CrossOrigin/AbstractOperations.h>
#include <LibWeb/HTML/Location.h>
#include <LibWeb/HTML/Window.h>
#include <LibWeb/WebIDL/DOMException.h>
namespace Web::Bindings {
namespace Web::HTML {
// https://html.spec.whatwg.org/multipage/history.html#the-location-interface
LocationObject::LocationObject(JS::Realm& realm)
Location::Location(JS::Realm& realm)
: PlatformObject(realm)
{
}
LocationObject::~LocationObject() = default;
Location::~Location() = default;
void LocationObject::visit_edges(Cell::Visitor& visitor)
void Location::visit_edges(Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
for (auto& property : m_default_properties)
visitor.visit(property);
}
void LocationObject::initialize(JS::Realm& realm)
void Location::initialize(JS::Realm& realm)
{
auto& vm = this->vm();
Object::initialize(realm);
set_prototype(&ensure_web_prototype<LocationPrototype>(realm, "Location"));
set_prototype(&Bindings::ensure_web_prototype<Bindings::LocationPrototype>(realm, "Location"));
u8 attr = JS::Attribute::Writable | JS::Attribute::Enumerable;
define_native_accessor(realm, "href", href_getter, href_setter, attr);
define_native_accessor(realm, "host", host_getter, {}, attr);
define_native_accessor(realm, "hostname", hostname_getter, {}, attr);
define_native_accessor(realm, "pathname", pathname_getter, {}, attr);
define_native_accessor(realm, "hash", hash_getter, {}, attr);
define_native_accessor(realm, "search", search_getter, {}, attr);
define_native_accessor(realm, "protocol", protocol_getter, {}, attr);
define_native_accessor(realm, "port", port_getter, {}, attr);
define_native_accessor(realm, "origin", origin_getter, {}, attr);
define_native_function(realm, "reload", reload, 0, JS::Attribute::Enumerable);
define_native_function(realm, "replace", replace, 1, JS::Attribute::Enumerable);
define_native_function(realm, vm.names.toString, href_getter, 0, JS::Attribute::Enumerable);
// FIXME: Implement steps 2.-4.
// 5. Set the value of the [[DefaultProperties]] internal slot of location to location.[[OwnPropertyKeys]]().
// NOTE: In LibWeb this happens before the ESO is set up, so we must avoid location's custom [[OwnPropertyKeys]].
@ -64,7 +48,7 @@ void LocationObject::initialize(JS::Realm& realm)
}
// https://html.spec.whatwg.org/multipage/history.html#relevant-document
DOM::Document const* LocationObject::relevant_document() const
DOM::Document const* Location::relevant_document() const
{
// A Location object has an associated relevant Document, which is this Location object's
// relevant global object's browsing context's active document, if this Location object's
@ -74,7 +58,7 @@ DOM::Document const* LocationObject::relevant_document() const
}
// https://html.spec.whatwg.org/multipage/history.html#concept-location-url
AK::URL LocationObject::url() const
AK::URL Location::url() const
{
// A Location object has an associated url, which is this Location object's relevant Document's URL,
// if this Location object's relevant Document is non-null, and about:blank otherwise.
@ -82,34 +66,24 @@ AK::URL LocationObject::url() const
return relevant_document ? relevant_document->url() : "about:blank"sv;
}
static JS::ThrowCompletionOr<LocationObject*> typed_this_value(JS::VM& vm)
{
auto this_value = vm.this_value();
if (!this_value.is_object() || !is<LocationObject>(this_value.as_object()))
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "Location");
return static_cast<LocationObject*>(&this_value.as_object());
}
// https://html.spec.whatwg.org/multipage/history.html#dom-location-href
JS_DEFINE_NATIVE_FUNCTION(LocationObject::href_getter)
DeprecatedString Location::href() const
{
auto* location_object = TRY(typed_this_value(vm));
// FIXME: 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException.
// 2. Return this's url, serialized.
return JS::PrimitiveString::create(vm, location_object->url().to_deprecated_string());
return url().to_deprecated_string();
}
// https://html.spec.whatwg.org/multipage/history.html#the-location-interface:dom-location-href-2
JS_DEFINE_NATIVE_FUNCTION(LocationObject::href_setter)
JS::ThrowCompletionOr<void> Location::set_href(DeprecatedString const& new_href)
{
auto& vm = this->vm();
auto& window = verify_cast<HTML::Window>(HTML::current_global_object());
// FIXME: 1. If this's relevant Document is null, then return.
// 2. Parse the given value relative to the entry settings object. If that failed, throw a TypeError exception.
auto new_href = TRY(vm.argument(0).to_deprecated_string(vm));
auto href_url = window.associated_document().parse_url(new_href);
if (!href_url.is_valid())
return vm.throw_completion<JS::URIError>(DeprecatedString::formatted("Invalid URL '{}'", new_href));
@ -117,144 +91,175 @@ JS_DEFINE_NATIVE_FUNCTION(LocationObject::href_setter)
// 3. Location-object navigate given the resulting URL record.
window.did_set_location_href({}, href_url);
return JS::js_undefined();
}
// https://html.spec.whatwg.org/multipage/history.html#dom-location-pathname
JS_DEFINE_NATIVE_FUNCTION(LocationObject::pathname_getter)
{
auto* location_object = TRY(typed_this_value(vm));
// FIXME: 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException.
// 2. Return the result of URL path serializing this Location object's url.
return JS::PrimitiveString::create(vm, location_object->url().path());
}
// https://html.spec.whatwg.org/multipage/history.html#dom-location-hostname
JS_DEFINE_NATIVE_FUNCTION(LocationObject::hostname_getter)
{
auto* location_object = TRY(typed_this_value(vm));
// FIXME: 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException.
// 2. If this's url's host is null, return the empty string.
if (location_object->url().host().is_null())
return JS::PrimitiveString::create(vm, DeprecatedString::empty());
// 3. Return this's url's host, serialized.
return JS::PrimitiveString::create(vm, location_object->url().host());
}
// https://html.spec.whatwg.org/multipage/history.html#dom-location-host
JS_DEFINE_NATIVE_FUNCTION(LocationObject::host_getter)
{
auto* location_object = TRY(typed_this_value(vm));
// FIXME: 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException.
// 2. Let url be this's url.
auto url = location_object->url();
// 3. If url's host is null, return the empty string.
if (url.host().is_null())
return JS::PrimitiveString::create(vm, DeprecatedString::empty());
// 4. If url's port is null, return url's host, serialized.
if (!url.port().has_value())
return JS::PrimitiveString::create(vm, url.host());
// 5. Return url's host, serialized, followed by ":" and url's port, serialized.
return JS::PrimitiveString::create(vm, DeprecatedString::formatted("{}:{}", url.host(), *url.port()));
}
// https://html.spec.whatwg.org/multipage/history.html#dom-location-hash
JS_DEFINE_NATIVE_FUNCTION(LocationObject::hash_getter)
{
auto* location_object = TRY(typed_this_value(vm));
// FIXME: 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException.
// 2. If this's url's fragment is either null or the empty string, return the empty string.
if (location_object->url().fragment().is_empty())
return JS::PrimitiveString::create(vm, DeprecatedString::empty());
// 3. Return "#", followed by this's url's fragment.
return JS::PrimitiveString::create(vm, DeprecatedString::formatted("#{}", location_object->url().fragment()));
}
// https://html.spec.whatwg.org/multipage/history.html#dom-location-search
JS_DEFINE_NATIVE_FUNCTION(LocationObject::search_getter)
{
auto* location_object = TRY(typed_this_value(vm));
// FIXME: 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException.
// 2. If this's url's query is either null or the empty string, return the empty string.
if (location_object->url().query().is_empty())
return JS::PrimitiveString::create(vm, DeprecatedString::empty());
// 3. Return "?", followed by this's url's query.
return JS::PrimitiveString::create(vm, DeprecatedString::formatted("?{}", location_object->url().query()));
}
// https://html.spec.whatwg.org/multipage/history.html#dom-location-protocol
JS_DEFINE_NATIVE_FUNCTION(LocationObject::protocol_getter)
{
auto* location_object = TRY(typed_this_value(vm));
// FIXME: 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException.
// 2. Return this's url's scheme, followed by ":".
return JS::PrimitiveString::create(vm, DeprecatedString::formatted("{}:", location_object->url().scheme()));
}
// https://html.spec.whatwg.org/multipage/history.html#dom-location-port
JS_DEFINE_NATIVE_FUNCTION(LocationObject::port_getter)
{
auto* location_object = TRY(typed_this_value(vm));
// FIXME: 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException.
// 2. If this's url's port is null, return the empty string.
if (!location_object->url().port().has_value())
return JS::PrimitiveString::create(vm, DeprecatedString::empty());
// 3. Return this's url's port, serialized.
return JS::PrimitiveString::create(vm, DeprecatedString::number(*location_object->url().port()));
return {};
}
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-location-origin
JS_DEFINE_NATIVE_FUNCTION(LocationObject::origin_getter)
DeprecatedString Location::origin() const
{
auto* location_object = TRY(typed_this_value(vm));
// FIXME: 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException.
// 2. Return the serialization of this's url's origin.
return JS::PrimitiveString::create(vm, location_object->url().serialize_origin());
return url().serialize_origin();
}
// https://html.spec.whatwg.org/multipage/history.html#dom-location-protocol
DeprecatedString Location::protocol() const
{
// FIXME: 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException.
// 2. Return this's url's scheme, followed by ":".
return DeprecatedString::formatted("{}:", url().scheme());
}
JS::ThrowCompletionOr<void> Location::set_protocol(DeprecatedString const&)
{
auto& vm = this->vm();
return vm.throw_completion<JS::InternalError>(JS::ErrorType::NotImplemented, "Location.protocol setter");
}
// https://html.spec.whatwg.org/multipage/history.html#dom-location-host
DeprecatedString Location::host() const
{
// FIXME: 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException.
// 2. Let url be this's url.
auto url = this->url();
// 3. If url's host is null, return the empty string.
if (url.host().is_null())
return DeprecatedString::empty();
// 4. If url's port is null, return url's host, serialized.
if (!url.port().has_value())
return url.host();
// 5. Return url's host, serialized, followed by ":" and url's port, serialized.
return DeprecatedString::formatted("{}:{}", url.host(), *url.port());
}
JS::ThrowCompletionOr<void> Location::set_host(DeprecatedString const&)
{
auto& vm = this->vm();
return vm.throw_completion<JS::InternalError>(JS::ErrorType::NotImplemented, "Location.host setter");
}
// https://html.spec.whatwg.org/multipage/history.html#dom-location-hostname
DeprecatedString Location::hostname() const
{
// FIXME: 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException.
auto url = this->url();
// 2. If this's url's host is null, return the empty string.
if (url.host().is_null())
return DeprecatedString::empty();
// 3. Return this's url's host, serialized.
return url.host();
}
JS::ThrowCompletionOr<void> Location::set_hostname(DeprecatedString const&)
{
auto& vm = this->vm();
return vm.throw_completion<JS::InternalError>(JS::ErrorType::NotImplemented, "Location.hostname setter");
}
// https://html.spec.whatwg.org/multipage/history.html#dom-location-port
DeprecatedString Location::port() const
{
// FIXME: 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException.
auto url = this->url();
// 2. If this's url's port is null, return the empty string.
if (!url.port().has_value())
return DeprecatedString::empty();
// 3. Return this's url's port, serialized.
return DeprecatedString::number(*url.port());
}
JS::ThrowCompletionOr<void> Location::set_port(DeprecatedString const&)
{
auto& vm = this->vm();
return vm.throw_completion<JS::InternalError>(JS::ErrorType::NotImplemented, "Location.port setter");
}
// https://html.spec.whatwg.org/multipage/history.html#dom-location-pathname
DeprecatedString Location::pathname() const
{
// FIXME: 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException.
// 2. Return the result of URL path serializing this Location object's url.
return url().path();
}
JS::ThrowCompletionOr<void> Location::set_pathname(DeprecatedString const&)
{
auto& vm = this->vm();
return vm.throw_completion<JS::InternalError>(JS::ErrorType::NotImplemented, "Location.pathname setter");
}
// https://html.spec.whatwg.org/multipage/history.html#dom-location-search
DeprecatedString Location::search() const
{
// FIXME: 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException.
auto url = this->url();
// 2. If this's url's query is either null or the empty string, return the empty string.
if (url.query().is_empty())
return DeprecatedString::empty();
// 3. Return "?", followed by this's url's query.
return DeprecatedString::formatted("?{}", url.query());
}
JS::ThrowCompletionOr<void> Location::set_search(DeprecatedString const&)
{
auto& vm = this->vm();
return vm.throw_completion<JS::InternalError>(JS::ErrorType::NotImplemented, "Location.search setter");
}
// https://html.spec.whatwg.org/multipage/history.html#dom-location-hash
DeprecatedString Location::hash() const
{
// FIXME: 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException.
auto url = this->url();
// 2. If this's url's fragment is either null or the empty string, return the empty string.
if (url.fragment().is_empty())
return DeprecatedString::empty();
// 3. Return "#", followed by this's url's fragment.
return DeprecatedString::formatted("#{}", url.fragment());
}
JS::ThrowCompletionOr<void> Location::set_hash(DeprecatedString const&)
{
auto& vm = this->vm();
return vm.throw_completion<JS::InternalError>(JS::ErrorType::NotImplemented, "Location.hash setter");
}
// https://html.spec.whatwg.org/multipage/history.html#dom-location-reload
JS_DEFINE_NATIVE_FUNCTION(LocationObject::reload)
void Location::reload() const
{
auto& window = verify_cast<HTML::Window>(HTML::current_global_object());
window.did_call_location_reload({});
return JS::js_undefined();
}
// https://html.spec.whatwg.org/multipage/history.html#dom-location-replace
JS_DEFINE_NATIVE_FUNCTION(LocationObject::replace)
void Location::replace(DeprecatedString url) const
{
auto& window = verify_cast<HTML::Window>(HTML::current_global_object());
auto url = TRY(vm.argument(0).to_deprecated_string(vm));
// FIXME: This needs spec compliance work.
window.did_call_location_replace({}, move(url));
return JS::js_undefined();
}
// 7.10.5.1 [[GetPrototypeOf]] ( ), https://html.spec.whatwg.org/multipage/history.html#location-getprototypeof
JS::ThrowCompletionOr<JS::Object*> LocationObject::internal_get_prototype_of() const
JS::ThrowCompletionOr<JS::Object*> Location::internal_get_prototype_of() const
{
// 1. If IsPlatformObjectSameOrigin(this) is true, then return ! OrdinaryGetPrototypeOf(this).
if (HTML::is_platform_object_same_origin(*this))
@ -265,28 +270,28 @@ JS::ThrowCompletionOr<JS::Object*> LocationObject::internal_get_prototype_of() c
}
// 7.10.5.2 [[SetPrototypeOf]] ( V ), https://html.spec.whatwg.org/multipage/history.html#location-setprototypeof
JS::ThrowCompletionOr<bool> LocationObject::internal_set_prototype_of(Object* prototype)
JS::ThrowCompletionOr<bool> Location::internal_set_prototype_of(Object* prototype)
{
// 1. Return ! SetImmutablePrototype(this, V).
return MUST(set_immutable_prototype(prototype));
}
// 7.10.5.3 [[IsExtensible]] ( ), https://html.spec.whatwg.org/multipage/history.html#location-isextensible
JS::ThrowCompletionOr<bool> LocationObject::internal_is_extensible() const
JS::ThrowCompletionOr<bool> Location::internal_is_extensible() const
{
// 1. Return true.
return true;
}
// 7.10.5.4 [[PreventExtensions]] ( ), https://html.spec.whatwg.org/multipage/history.html#location-preventextensions
JS::ThrowCompletionOr<bool> LocationObject::internal_prevent_extensions()
JS::ThrowCompletionOr<bool> Location::internal_prevent_extensions()
{
// 1. Return false.
return false;
}
// 7.10.5.5 [[GetOwnProperty]] ( P ), https://html.spec.whatwg.org/multipage/history.html#location-getownproperty
JS::ThrowCompletionOr<Optional<JS::PropertyDescriptor>> LocationObject::internal_get_own_property(JS::PropertyKey const& property_key) const
JS::ThrowCompletionOr<Optional<JS::PropertyDescriptor>> Location::internal_get_own_property(JS::PropertyKey const& property_key) const
{
auto& vm = this->vm();
@ -307,7 +312,7 @@ JS::ThrowCompletionOr<Optional<JS::PropertyDescriptor>> LocationObject::internal
}
// 2. Let property be CrossOriginGetOwnPropertyHelper(this, P).
auto property = HTML::cross_origin_get_own_property_helper(const_cast<LocationObject*>(this), property_key);
auto property = HTML::cross_origin_get_own_property_helper(const_cast<Location*>(this), property_key);
// 3. If property is not undefined, then return property.
if (property.has_value())
@ -318,7 +323,7 @@ JS::ThrowCompletionOr<Optional<JS::PropertyDescriptor>> LocationObject::internal
}
// 7.10.5.6 [[DefineOwnProperty]] ( P, Desc ), https://html.spec.whatwg.org/multipage/history.html#location-defineownproperty
JS::ThrowCompletionOr<bool> LocationObject::internal_define_own_property(JS::PropertyKey const& property_key, JS::PropertyDescriptor const& descriptor)
JS::ThrowCompletionOr<bool> Location::internal_define_own_property(JS::PropertyKey const& property_key, JS::PropertyDescriptor const& descriptor)
{
// 1. If IsPlatformObjectSameOrigin(this) is true, then:
if (HTML::is_platform_object_same_origin(*this)) {
@ -332,7 +337,7 @@ JS::ThrowCompletionOr<bool> LocationObject::internal_define_own_property(JS::Pro
}
// 7.10.5.7 [[Get]] ( P, Receiver ), https://html.spec.whatwg.org/multipage/history.html#location-get
JS::ThrowCompletionOr<JS::Value> LocationObject::internal_get(JS::PropertyKey const& property_key, JS::Value receiver) const
JS::ThrowCompletionOr<JS::Value> Location::internal_get(JS::PropertyKey const& property_key, JS::Value receiver) const
{
auto& vm = this->vm();
@ -345,7 +350,7 @@ JS::ThrowCompletionOr<JS::Value> LocationObject::internal_get(JS::PropertyKey co
}
// 7.10.5.8 [[Set]] ( P, V, Receiver ), https://html.spec.whatwg.org/multipage/history.html#location-set
JS::ThrowCompletionOr<bool> LocationObject::internal_set(JS::PropertyKey const& property_key, JS::Value value, JS::Value receiver)
JS::ThrowCompletionOr<bool> Location::internal_set(JS::PropertyKey const& property_key, JS::Value value, JS::Value receiver)
{
auto& vm = this->vm();
@ -358,7 +363,7 @@ JS::ThrowCompletionOr<bool> LocationObject::internal_set(JS::PropertyKey const&
}
// 7.10.5.9 [[Delete]] ( P ), https://html.spec.whatwg.org/multipage/history.html#location-delete
JS::ThrowCompletionOr<bool> LocationObject::internal_delete(JS::PropertyKey const& property_key)
JS::ThrowCompletionOr<bool> Location::internal_delete(JS::PropertyKey const& property_key)
{
// 1. If IsPlatformObjectSameOrigin(this) is true, then return ? OrdinaryDelete(this, P).
if (HTML::is_platform_object_same_origin(*this))
@ -369,7 +374,7 @@ JS::ThrowCompletionOr<bool> LocationObject::internal_delete(JS::PropertyKey cons
}
// 7.10.5.10 [[OwnPropertyKeys]] ( ), https://html.spec.whatwg.org/multipage/history.html#location-ownpropertykeys
JS::ThrowCompletionOr<JS::MarkedVector<JS::Value>> LocationObject::internal_own_property_keys() const
JS::ThrowCompletionOr<JS::MarkedVector<JS::Value>> Location::internal_own_property_keys() const
{
// 1. If IsPlatformObjectSameOrigin(this) is true, then return OrdinaryOwnPropertyKeys(this).
if (HTML::is_platform_object_same_origin(*this))

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2022-2023, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -14,14 +14,42 @@
#include <LibWeb/Forward.h>
#include <LibWeb/HTML/CrossOrigin/CrossOriginPropertyDescriptorMap.h>
namespace Web {
namespace Bindings {
namespace Web::HTML {
class LocationObject final : public Bindings::PlatformObject {
JS_OBJECT(LocationObject, Bindings::PlatformObject);
class Location final : public Bindings::PlatformObject {
JS_OBJECT(Location, Bindings::PlatformObject);
public:
virtual ~LocationObject() override;
virtual ~Location() override;
DeprecatedString href() const;
JS::ThrowCompletionOr<void> set_href(DeprecatedString const&);
DeprecatedString origin() const;
DeprecatedString protocol() const;
JS::ThrowCompletionOr<void> set_protocol(DeprecatedString const&);
DeprecatedString host() const;
JS::ThrowCompletionOr<void> set_host(DeprecatedString const&);
DeprecatedString hostname() const;
JS::ThrowCompletionOr<void> set_hostname(DeprecatedString const&);
DeprecatedString port() const;
JS::ThrowCompletionOr<void> set_port(DeprecatedString const&);
DeprecatedString pathname() const;
JS::ThrowCompletionOr<void> set_pathname(DeprecatedString const&);
DeprecatedString search() const;
JS::ThrowCompletionOr<void> set_search(DeprecatedString const&);
DeprecatedString hash() const;
JS::ThrowCompletionOr<void> set_hash(DeprecatedString const&);
void replace(DeprecatedString url) const;
void reload() const;
virtual JS::ThrowCompletionOr<JS::Object*> internal_get_prototype_of() const override;
virtual JS::ThrowCompletionOr<bool> internal_set_prototype_of(Object* prototype) override;
@ -38,7 +66,7 @@ public:
HTML::CrossOriginPropertyDescriptorMap& cross_origin_property_descriptor_map() { return m_cross_origin_property_descriptor_map; }
private:
explicit LocationObject(JS::Realm&);
explicit Location(JS::Realm&);
virtual void initialize(JS::Realm&) override;
virtual void visit_edges(Cell::Visitor&) override;
@ -46,21 +74,6 @@ private:
DOM::Document const* relevant_document() const;
AK::URL url() const;
JS_DECLARE_NATIVE_FUNCTION(reload);
JS_DECLARE_NATIVE_FUNCTION(replace);
JS_DECLARE_NATIVE_FUNCTION(href_getter);
JS_DECLARE_NATIVE_FUNCTION(href_setter);
JS_DECLARE_NATIVE_FUNCTION(host_getter);
JS_DECLARE_NATIVE_FUNCTION(hostname_getter);
JS_DECLARE_NATIVE_FUNCTION(pathname_getter);
JS_DECLARE_NATIVE_FUNCTION(hash_getter);
JS_DECLARE_NATIVE_FUNCTION(search_getter);
JS_DECLARE_NATIVE_FUNCTION(protocol_getter);
JS_DECLARE_NATIVE_FUNCTION(port_getter);
JS_DECLARE_NATIVE_FUNCTION(origin_getter);
// [[CrossOriginPropertyDescriptorMap]], https://html.spec.whatwg.org/multipage/browsers.html#crossoriginpropertydescriptormap
HTML::CrossOriginPropertyDescriptorMap m_cross_origin_property_descriptor_map;
@ -69,4 +82,3 @@ private:
};
}
}

View file

@ -0,0 +1,19 @@
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#location
[Exposed=Window]
interface Location { // but see also additional creation steps and overridden internal methods
[LegacyUnforgeable] stringifier attribute USVString href;
[LegacyUnforgeable] readonly attribute USVString origin;
[LegacyUnforgeable] attribute USVString protocol;
[LegacyUnforgeable] attribute USVString host;
[LegacyUnforgeable] attribute USVString hostname;
[LegacyUnforgeable] attribute USVString port;
[LegacyUnforgeable] attribute USVString pathname;
[LegacyUnforgeable] attribute USVString search;
[LegacyUnforgeable] attribute USVString hash;
// TODO: [LegacyUnforgeable] undefined assign(USVString url);
[LegacyUnforgeable] undefined replace(USVString url);
[LegacyUnforgeable] undefined reload();
// TODO: [LegacyUnforgeable, SameObject] readonly attribute DOMStringList ancestorOrigins;
};

View file

@ -1,6 +1,7 @@
/*
* Copyright (c) 2020-2022, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021-2022, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2021-2023, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -19,7 +20,6 @@
#include <LibWeb/Bindings/CSSNamespace.h>
#include <LibWeb/Bindings/ExceptionOrUtils.h>
#include <LibWeb/Bindings/FetchMethod.h>
#include <LibWeb/Bindings/LocationObject.h>
#include <LibWeb/Bindings/Replaceable.h>
#include <LibWeb/Bindings/WindowExposedInterfaces.h>
#include <LibWeb/Bindings/WindowPrototype.h>
@ -36,6 +36,7 @@
#include <LibWeb/HTML/EventHandler.h>
#include <LibWeb/HTML/EventLoop/EventLoop.h>
#include <LibWeb/HTML/Focus.h>
#include <LibWeb/HTML/Location.h>
#include <LibWeb/HTML/MessageEvent.h>
#include <LibWeb/HTML/Navigator.h>
#include <LibWeb/HTML/Origin.h>
@ -102,7 +103,7 @@ void Window::visit_edges(JS::Cell::Visitor& visitor)
visitor.visit(m_current_event.ptr());
visitor.visit(m_performance.ptr());
visitor.visit(m_screen.ptr());
visitor.visit(m_location_object);
visitor.visit(m_location);
visitor.visit(m_crypto);
visitor.visit(m_navigator);
for (auto& it : m_timers)
@ -581,7 +582,7 @@ void Window::cancel_animation_frame_impl(i32 id)
m_animation_frame_callback_driver.remove(id);
}
void Window::did_set_location_href(Badge<Bindings::LocationObject>, AK::URL const& new_href)
void Window::did_set_location_href(Badge<HTML::Location>, AK::URL const& new_href)
{
auto* browsing_context = associated_document().browsing_context();
if (!browsing_context)
@ -589,7 +590,7 @@ void Window::did_set_location_href(Badge<Bindings::LocationObject>, AK::URL cons
browsing_context->loader().load(new_href, FrameLoader::Type::Navigation);
}
void Window::did_call_location_reload(Badge<Bindings::LocationObject>)
void Window::did_call_location_reload(Badge<HTML::Location>)
{
auto* browsing_context = associated_document().browsing_context();
if (!browsing_context)
@ -597,7 +598,7 @@ void Window::did_call_location_reload(Badge<Bindings::LocationObject>)
browsing_context->loader().load(associated_document().url(), FrameLoader::Type::Reload);
}
void Window::did_call_location_replace(Badge<Bindings::LocationObject>, DeprecatedString url)
void Window::did_call_location_replace(Badge<HTML::Location>, DeprecatedString url)
{
auto* browsing_context = associated_document().browsing_context();
if (!browsing_context)
@ -1142,7 +1143,7 @@ void Window::initialize_web_interfaces(Badge<WindowEnvironmentSettingsObject>)
// Legacy
define_native_accessor(realm, "event", event_getter, event_setter, JS::Attribute::Enumerable);
m_location_object = heap().allocate<Bindings::LocationObject>(realm, realm);
m_location = heap().allocate<HTML::Location>(realm, realm);
m_navigator = heap().allocate<HTML::Navigator>(realm, realm);
define_direct_property("navigator", m_navigator, JS::Attribute::Enumerable | JS::Attribute::Configurable);
@ -1611,13 +1612,13 @@ JS_DEFINE_NATIVE_FUNCTION(Window::event_setter)
JS_DEFINE_NATIVE_FUNCTION(Window::location_getter)
{
auto* impl = TRY(impl_from(vm));
return impl->m_location_object;
return impl->m_location;
}
JS_DEFINE_NATIVE_FUNCTION(Window::location_setter)
{
auto* impl = TRY(impl_from(vm));
TRY(impl->m_location_object->set(JS::PropertyKey("href"), vm.argument(0), JS::Object::ShouldThrowExceptions::Yes));
TRY(impl->m_location->set(JS::PropertyKey("href"), vm.argument(0), JS::Object::ShouldThrowExceptions::Yes));
return JS::js_undefined();
}

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2020-2022, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021-2023, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -79,9 +80,9 @@ public:
int inner_width() const;
int inner_height() const;
void did_set_location_href(Badge<Bindings::LocationObject>, AK::URL const& new_href);
void did_call_location_reload(Badge<Bindings::LocationObject>);
void did_call_location_replace(Badge<Bindings::LocationObject>, DeprecatedString url);
void did_set_location_href(Badge<HTML::Location>, AK::URL const& new_href);
void did_call_location_reload(Badge<HTML::Location>);
void did_call_location_replace(Badge<HTML::Location>, DeprecatedString url);
void deallocate_timer_id(Badge<Timer>, i32);
@ -186,8 +187,8 @@ private:
public:
HTML::Origin origin() const;
Bindings::LocationObject* location_object() { return m_location_object; }
Bindings::LocationObject const* location_object() const { return m_location_object; }
HTML::Location* location() { return m_location; }
HTML::Location const* location() const { return m_location; }
virtual JS::ThrowCompletionOr<bool> internal_set_prototype_of(JS::Object* prototype) override;
@ -281,7 +282,7 @@ private:
ENUMERATE_WINDOW_EVENT_HANDLERS(__ENUMERATE);
#undef __ENUMERATE
Bindings::LocationObject* m_location_object { nullptr };
HTML::Location* m_location { nullptr };
// [[CrossOriginPropertyDescriptorMap]], https://html.spec.whatwg.org/multipage/browsers.html#crossoriginpropertydescriptormap
CrossOriginPropertyDescriptorMap m_cross_origin_property_descriptor_map;

View file

@ -144,6 +144,7 @@ libweb_js_bindings(HTML/HTMLUListElement)
libweb_js_bindings(HTML/HTMLUnknownElement)
libweb_js_bindings(HTML/HTMLVideoElement)
libweb_js_bindings(HTML/ImageData)
libweb_js_bindings(HTML/Location)
libweb_js_bindings(HTML/MessageChannel)
libweb_js_bindings(HTML/MessageEvent)
libweb_js_bindings(HTML/MessagePort)