mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 15:27:35 +00:00
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:
parent
78d6de2ec1
commit
afc055c088
19 changed files with 271 additions and 333 deletions
|
@ -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();
|
||||
|
|
|
@ -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&);
|
||||
|
||||
}
|
||||
|
|
387
Userland/Libraries/LibWeb/HTML/Location.cpp
Normal file
387
Userland/Libraries/LibWeb/HTML/Location.cpp
Normal file
|
@ -0,0 +1,387 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2022-2023, Linus Groh <linusg@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/DeprecatedFlyString.h>
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <LibJS/Heap/MarkedVector.h>
|
||||
#include <LibJS/Runtime/Completion.h>
|
||||
#include <LibJS/Runtime/PropertyDescriptor.h>
|
||||
#include <LibJS/Runtime/PropertyKey.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::HTML {
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/history.html#the-location-interface
|
||||
Location::Location(JS::Realm& realm)
|
||||
: PlatformObject(realm)
|
||||
{
|
||||
}
|
||||
|
||||
Location::~Location() = default;
|
||||
|
||||
void Location::visit_edges(Cell::Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
for (auto& property : m_default_properties)
|
||||
visitor.visit(property);
|
||||
}
|
||||
|
||||
void Location::initialize(JS::Realm& realm)
|
||||
{
|
||||
Object::initialize(realm);
|
||||
set_prototype(&Bindings::ensure_web_prototype<Bindings::LocationPrototype>(realm, "Location"));
|
||||
|
||||
// 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]].
|
||||
m_default_properties.extend(MUST(Object::internal_own_property_keys()));
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/history.html#relevant-document
|
||||
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
|
||||
// relevant global object's browsing context is non-null, and null otherwise.
|
||||
auto* browsing_context = verify_cast<HTML::Window>(HTML::relevant_global_object(*this)).browsing_context();
|
||||
return browsing_context ? browsing_context->active_document() : nullptr;
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/history.html#concept-location-url
|
||||
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.
|
||||
auto const* relevant_document = this->relevant_document();
|
||||
return relevant_document ? relevant_document->url() : "about:blank"sv;
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/history.html#dom-location-href
|
||||
DeprecatedString Location::href() 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, serialized.
|
||||
return url().to_deprecated_string();
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/history.html#the-location-interface:dom-location-href-2
|
||||
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 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));
|
||||
|
||||
// 3. Location-object navigate given the resulting URL record.
|
||||
window.did_set_location_href({}, href_url);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-location-origin
|
||||
DeprecatedString Location::origin() 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 serialization of this's url's 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
|
||||
void Location::reload() const
|
||||
{
|
||||
auto& window = verify_cast<HTML::Window>(HTML::current_global_object());
|
||||
window.did_call_location_reload({});
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/history.html#dom-location-replace
|
||||
void Location::replace(DeprecatedString url) const
|
||||
{
|
||||
auto& window = verify_cast<HTML::Window>(HTML::current_global_object());
|
||||
// FIXME: This needs spec compliance work.
|
||||
window.did_call_location_replace({}, move(url));
|
||||
}
|
||||
|
||||
// 7.10.5.1 [[GetPrototypeOf]] ( ), https://html.spec.whatwg.org/multipage/history.html#location-getprototypeof
|
||||
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))
|
||||
return MUST(JS::Object::internal_get_prototype_of());
|
||||
|
||||
// 2. Return null.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// 7.10.5.2 [[SetPrototypeOf]] ( V ), https://html.spec.whatwg.org/multipage/history.html#location-setprototypeof
|
||||
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> 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> 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>> Location::internal_get_own_property(JS::PropertyKey const& property_key) const
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. If IsPlatformObjectSameOrigin(this) is true, then:
|
||||
if (HTML::is_platform_object_same_origin(*this)) {
|
||||
// 1. Let desc be OrdinaryGetOwnProperty(this, P).
|
||||
auto descriptor = MUST(Object::internal_get_own_property(property_key));
|
||||
|
||||
// 2. If the value of the [[DefaultProperties]] internal slot of this contains P, then set desc.[[Configurable]] to true.
|
||||
auto property_key_value = property_key.is_symbol()
|
||||
? JS::Value { property_key.as_symbol() }
|
||||
: JS::PrimitiveString::create(vm, property_key.to_string());
|
||||
if (m_default_properties.contains_slow(property_key_value))
|
||||
descriptor->configurable = true;
|
||||
|
||||
// 3. Return desc.
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
// 2. Let property be CrossOriginGetOwnPropertyHelper(this, P).
|
||||
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())
|
||||
return property;
|
||||
|
||||
// 4. Return ? CrossOriginPropertyFallback(P).
|
||||
return TRY(HTML::cross_origin_property_fallback(vm, property_key));
|
||||
}
|
||||
|
||||
// 7.10.5.6 [[DefineOwnProperty]] ( P, Desc ), https://html.spec.whatwg.org/multipage/history.html#location-defineownproperty
|
||||
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)) {
|
||||
// 1. If the value of the [[DefaultProperties]] internal slot of this contains P, then return false.
|
||||
// 2. Return ? OrdinaryDefineOwnProperty(this, P, Desc).
|
||||
return JS::Object::internal_define_own_property(property_key, descriptor);
|
||||
}
|
||||
|
||||
// 2. Throw a "SecurityError" DOMException.
|
||||
return throw_completion(WebIDL::SecurityError::create(realm(), DeprecatedString::formatted("Can't define property '{}' on cross-origin object", property_key)));
|
||||
}
|
||||
|
||||
// 7.10.5.7 [[Get]] ( P, Receiver ), https://html.spec.whatwg.org/multipage/history.html#location-get
|
||||
JS::ThrowCompletionOr<JS::Value> Location::internal_get(JS::PropertyKey const& property_key, JS::Value receiver) const
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. If IsPlatformObjectSameOrigin(this) is true, then return ? OrdinaryGet(this, P, Receiver).
|
||||
if (HTML::is_platform_object_same_origin(*this))
|
||||
return JS::Object::internal_get(property_key, receiver);
|
||||
|
||||
// 2. Return ? CrossOriginGet(this, P, Receiver).
|
||||
return HTML::cross_origin_get(vm, static_cast<JS::Object const&>(*this), property_key, receiver);
|
||||
}
|
||||
|
||||
// 7.10.5.8 [[Set]] ( P, V, Receiver ), https://html.spec.whatwg.org/multipage/history.html#location-set
|
||||
JS::ThrowCompletionOr<bool> Location::internal_set(JS::PropertyKey const& property_key, JS::Value value, JS::Value receiver)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. If IsPlatformObjectSameOrigin(this) is true, then return ? OrdinarySet(this, P, V, Receiver).
|
||||
if (HTML::is_platform_object_same_origin(*this))
|
||||
return JS::Object::internal_set(property_key, value, receiver);
|
||||
|
||||
// 2. Return ? CrossOriginSet(this, P, V, Receiver).
|
||||
return HTML::cross_origin_set(vm, static_cast<JS::Object&>(*this), property_key, value, receiver);
|
||||
}
|
||||
|
||||
// 7.10.5.9 [[Delete]] ( P ), https://html.spec.whatwg.org/multipage/history.html#location-delete
|
||||
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))
|
||||
return JS::Object::internal_delete(property_key);
|
||||
|
||||
// 2. Throw a "SecurityError" DOMException.
|
||||
return throw_completion(WebIDL::SecurityError::create(realm(), DeprecatedString::formatted("Can't delete property '{}' on cross-origin object", property_key)));
|
||||
}
|
||||
|
||||
// 7.10.5.10 [[OwnPropertyKeys]] ( ), https://html.spec.whatwg.org/multipage/history.html#location-ownpropertykeys
|
||||
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))
|
||||
return JS::Object::internal_own_property_keys();
|
||||
|
||||
// 2. Return CrossOriginOwnPropertyKeys(this).
|
||||
return HTML::cross_origin_own_property_keys(this);
|
||||
}
|
||||
|
||||
}
|
84
Userland/Libraries/LibWeb/HTML/Location.h
Normal file
84
Userland/Libraries/LibWeb/HTML/Location.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2022-2023, Linus Groh <linusg@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/URL.h>
|
||||
#include <LibJS/Forward.h>
|
||||
#include <LibJS/Runtime/Completion.h>
|
||||
#include <LibWeb/Bindings/PlatformObject.h>
|
||||
#include <LibWeb/Forward.h>
|
||||
#include <LibWeb/HTML/CrossOrigin/CrossOriginPropertyDescriptorMap.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
||||
class Location final : public Bindings::PlatformObject {
|
||||
JS_OBJECT(Location, Bindings::PlatformObject);
|
||||
|
||||
public:
|
||||
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;
|
||||
virtual JS::ThrowCompletionOr<bool> internal_is_extensible() const override;
|
||||
virtual JS::ThrowCompletionOr<bool> internal_prevent_extensions() override;
|
||||
virtual JS::ThrowCompletionOr<Optional<JS::PropertyDescriptor>> internal_get_own_property(JS::PropertyKey const&) const override;
|
||||
virtual JS::ThrowCompletionOr<bool> internal_define_own_property(JS::PropertyKey const&, JS::PropertyDescriptor const&) override;
|
||||
virtual JS::ThrowCompletionOr<JS::Value> internal_get(JS::PropertyKey const&, JS::Value receiver) const override;
|
||||
virtual JS::ThrowCompletionOr<bool> internal_set(JS::PropertyKey const&, JS::Value value, JS::Value receiver) override;
|
||||
virtual JS::ThrowCompletionOr<bool> internal_delete(JS::PropertyKey const&) override;
|
||||
virtual JS::ThrowCompletionOr<JS::MarkedVector<JS::Value>> internal_own_property_keys() const override;
|
||||
|
||||
HTML::CrossOriginPropertyDescriptorMap const& cross_origin_property_descriptor_map() const { return m_cross_origin_property_descriptor_map; }
|
||||
HTML::CrossOriginPropertyDescriptorMap& cross_origin_property_descriptor_map() { return m_cross_origin_property_descriptor_map; }
|
||||
|
||||
private:
|
||||
explicit Location(JS::Realm&);
|
||||
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
|
||||
DOM::Document const* relevant_document() const;
|
||||
AK::URL url() const;
|
||||
|
||||
// [[CrossOriginPropertyDescriptorMap]], https://html.spec.whatwg.org/multipage/browsers.html#crossoriginpropertydescriptormap
|
||||
HTML::CrossOriginPropertyDescriptorMap m_cross_origin_property_descriptor_map;
|
||||
|
||||
// [[DefaultProperties]], https://html.spec.whatwg.org/multipage/history.html#defaultproperties
|
||||
Vector<JS::Value> m_default_properties;
|
||||
};
|
||||
|
||||
}
|
19
Userland/Libraries/LibWeb/HTML/Location.idl
Normal file
19
Userland/Libraries/LibWeb/HTML/Location.idl
Normal 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;
|
||||
};
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue