2020-05-18 21:42:40 +02:00
/*
2023-02-11 12:19:28 +01:00
* Copyright ( c ) 2020 - 2023 , Andreas Kling < kling @ serenityos . org >
2023-01-18 17:41:12 +00:00
* Copyright ( c ) 2022 - 2023 , Linus Groh < linusg @ serenityos . org >
2020-05-18 21:42:40 +02:00
*
2021-04-22 01:24:48 -07:00
* SPDX - License - Identifier : BSD - 2 - Clause
2020-05-18 21:42:40 +02:00
*/
2023-03-04 22:16:07 +00:00
# include <AK/String.h>
2020-05-18 21:59:16 +02:00
# include <AK/StringBuilder.h>
2023-02-11 12:19:28 +01:00
# include <AK/URLParser.h>
2022-03-06 00:24:18 +01:00
# include <LibJS/Heap/MarkedVector.h>
2021-09-28 23:54:42 +01:00
# include <LibJS/Runtime/Completion.h>
2022-03-06 00:24:18 +01:00
# include <LibJS/Runtime/PropertyDescriptor.h>
# include <LibJS/Runtime/PropertyKey.h>
2022-04-05 17:54:04 -03:00
# include <LibWeb/Bindings/LocationPrototype.h>
2020-05-18 21:42:40 +02:00
# include <LibWeb/DOM/Document.h>
2022-09-24 14:02:47 +01:00
# include <LibWeb/HTML/CrossOrigin/AbstractOperations.h>
2023-01-18 17:41:12 +00:00
# include <LibWeb/HTML/Location.h>
2023-08-28 18:06:10 +02:00
# include <LibWeb/HTML/Navigation.h>
2022-03-07 23:08:26 +01:00
# include <LibWeb/HTML/Window.h>
2022-09-25 17:28:46 +01:00
# include <LibWeb/WebIDL/DOMException.h>
2020-05-18 21:42:40 +02:00
2023-01-18 17:41:12 +00:00
namespace Web : : HTML {
2020-05-18 21:42:40 +02:00
2022-03-04 23:35:34 +01:00
// https://html.spec.whatwg.org/multipage/history.html#the-location-interface
2023-01-18 17:41:12 +00:00
Location : : Location ( JS : : Realm & realm )
2022-09-04 16:55:50 +02:00
: PlatformObject ( realm )
2020-06-20 17:28:13 +02:00
{
2022-09-04 16:55:50 +02:00
}
2023-01-18 17:41:12 +00:00
Location : : ~ Location ( ) = default ;
2022-09-04 16:55:50 +02:00
2023-01-18 17:41:12 +00:00
void Location : : visit_edges ( Cell : : Visitor & visitor )
2022-09-04 16:55:50 +02:00
{
Base : : visit_edges ( visitor ) ;
for ( auto & property : m_default_properties )
visitor . visit ( property ) ;
2020-06-20 17:28:13 +02:00
}
2023-08-07 08:41:28 +02:00
void Location : : initialize ( JS : : Realm & realm )
2020-05-18 21:42:40 +02:00
{
2023-08-07 08:41:28 +02:00
Base : : initialize ( realm ) ;
2023-01-18 17:41:12 +00:00
set_prototype ( & Bindings : : ensure_web_prototype < Bindings : : LocationPrototype > ( realm , " Location " ) ) ;
2022-08-22 21:47:35 +01:00
2023-01-18 17:41:12 +00:00
// FIXME: Implement steps 2.-4.
2022-03-06 00:24:18 +01:00
// 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 ( ) ) ) ;
2020-05-18 21:42:40 +02:00
}
2022-03-05 00:15:36 +01:00
// https://html.spec.whatwg.org/multipage/history.html#relevant-document
2023-03-04 22:37:12 +00:00
JS : : GCPtr < DOM : : Document > Location : : relevant_document ( ) const
2022-03-05 00:15:36 +01:00
{
// 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.
2022-08-28 13:42:07 +02:00
auto * browsing_context = verify_cast < HTML : : Window > ( HTML : : relevant_global_object ( * this ) ) . browsing_context ( ) ;
2022-03-05 00:15:36 +01:00
return browsing_context ? browsing_context - > active_document ( ) : nullptr ;
}
2023-08-28 18:06:10 +02:00
static Bindings : : NavigationHistoryBehavior to_navigation_history_behavior ( HistoryHandlingBehavior b )
{
switch ( b ) {
case HistoryHandlingBehavior : : Push :
return Bindings : : NavigationHistoryBehavior : : Push ;
case HistoryHandlingBehavior : : Replace :
return Bindings : : NavigationHistoryBehavior : : Replace ;
default :
return Bindings : : NavigationHistoryBehavior : : Auto ;
}
}
2023-08-22 18:12:10 +02:00
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#location-object-navigate
WebIDL : : ExceptionOr < void > Location : : navigate ( AK : : URL url , HistoryHandlingBehavior history_handling )
{
// 1. Let navigable be location's relevant global object's navigable.
auto navigable = verify_cast < HTML : : Window > ( HTML : : relevant_global_object ( * this ) ) . navigable ( ) ;
// 2. Let sourceDocument be the incumbent global object's associated Document.
auto & source_document = verify_cast < HTML : : Window > ( incumbent_global_object ( ) ) . associated_document ( ) ;
// 3. If location's relevant Document is not yet completely loaded, and the incumbent global object does not have transient activation, then set historyHandling to "replace".
if ( ! relevant_document ( ) - > is_completely_loaded ( ) & & ! verify_cast < HTML : : Window > ( incumbent_global_object ( ) ) . has_transient_activation ( ) ) {
history_handling = HistoryHandlingBehavior : : Replace ;
}
// 4. Navigate navigable to url using sourceDocument, with exceptionsEnabled set to true and historyHandling set to historyHandling.
2023-08-28 18:06:10 +02:00
TRY ( navigable - > navigate ( url , source_document , { } , nullptr , true , to_navigation_history_behavior ( history_handling ) ) ) ;
2023-08-22 18:12:10 +02:00
return { } ;
}
2022-03-05 00:17:47 +01:00
// https://html.spec.whatwg.org/multipage/history.html#concept-location-url
2023-01-18 17:41:12 +00:00
AK : : URL Location : : url ( ) const
2022-03-05 00:17:47 +01:00
{
// 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.
2023-03-04 22:37:12 +00:00
auto const relevant_document = this - > relevant_document ( ) ;
2022-03-05 00:17:47 +01:00
return relevant_document ? relevant_document - > url ( ) : " about:blank " sv ;
}
2022-03-04 23:35:34 +01:00
// https://html.spec.whatwg.org/multipage/history.html#dom-location-href
2023-03-04 22:16:07 +00:00
WebIDL : : ExceptionOr < String > Location : : href ( ) const
2020-05-18 21:42:40 +02:00
{
2023-03-04 22:16:07 +00:00
auto & vm = this - > vm ( ) ;
2023-03-04 22:37:12 +00:00
// 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 const relevant_document = this - > relevant_document ( ) ;
if ( relevant_document & & ! relevant_document - > origin ( ) . is_same_origin_domain ( entry_settings_object ( ) . origin ( ) ) )
2023-09-06 16:03:01 +12:00
return WebIDL : : SecurityError : : create ( realm ( ) , " Location's relevant document is not same origin-domain with the entry settings object's origin " _fly_string ) ;
2022-03-04 23:35:34 +01:00
// 2. Return this's url, serialized.
2023-03-04 22:16:07 +00:00
return TRY_OR_THROW_OOM ( vm , String : : from_deprecated_string ( url ( ) . serialize ( ) ) ) ;
2020-05-18 21:42:40 +02:00
}
2022-03-04 23:35:34 +01:00
// https://html.spec.whatwg.org/multipage/history.html#the-location-interface:dom-location-href-2
2023-03-04 22:19:14 +00:00
WebIDL : : ExceptionOr < void > Location : : set_href ( String const & new_href )
2020-05-18 21:42:40 +02:00
{
2023-01-18 17:41:12 +00:00
auto & vm = this - > vm ( ) ;
2022-08-28 13:42:07 +02:00
auto & window = verify_cast < HTML : : Window > ( HTML : : current_global_object ( ) ) ;
2022-03-04 23:35:34 +01:00
2023-03-04 22:37:12 +00:00
// 1. If this's relevant Document is null, then return.
auto const relevant_document = this - > relevant_document ( ) ;
if ( ! relevant_document )
return { } ;
2022-03-04 23:35:34 +01:00
// 2. Parse the given value relative to the entry settings object. If that failed, throw a TypeError exception.
2023-03-04 22:16:07 +00:00
auto href_url = window . associated_document ( ) . parse_url ( new_href . to_deprecated_string ( ) ) ;
2021-10-31 08:21:02 -04:00
if ( ! href_url . is_valid ( ) )
2023-02-16 14:09:11 -05:00
return vm . throw_completion < JS : : URIError > ( TRY_OR_THROW_OOM ( vm , String : : formatted ( " Invalid URL '{}' " , new_href ) ) ) ;
2022-03-04 23:35:34 +01:00
// 3. Location-object navigate given the resulting URL record.
2023-08-22 18:33:20 +02:00
TRY ( navigate ( href_url ) ) ;
2022-03-04 23:35:34 +01:00
2023-01-18 17:41:12 +00:00
return { } ;
2020-05-18 21:42:40 +02:00
}
2023-01-18 17:41:12 +00:00
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-location-origin
2023-03-04 22:16:07 +00:00
WebIDL : : ExceptionOr < String > Location : : origin ( ) const
2020-05-18 21:42:40 +02:00
{
2023-03-04 22:16:07 +00:00
auto & vm = this - > vm ( ) ;
2023-03-04 22:37:12 +00:00
// 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 const relevant_document = this - > relevant_document ( ) ;
if ( relevant_document & & ! relevant_document - > origin ( ) . is_same_origin_domain ( entry_settings_object ( ) . origin ( ) ) )
2023-09-06 16:03:01 +12:00
return WebIDL : : SecurityError : : create ( realm ( ) , " Location's relevant document is not same origin-domain with the entry settings object's origin " _fly_string ) ;
2022-03-04 23:35:34 +01:00
2023-01-18 17:41:12 +00:00
// 2. Return the serialization of this's url's origin.
2023-03-04 22:16:07 +00:00
return TRY_OR_THROW_OOM ( vm , String : : from_deprecated_string ( url ( ) . serialize_origin ( ) ) ) ;
2020-05-18 21:42:40 +02:00
}
2023-01-18 17:41:12 +00:00
// https://html.spec.whatwg.org/multipage/history.html#dom-location-protocol
2023-03-04 22:16:07 +00:00
WebIDL : : ExceptionOr < String > Location : : protocol ( ) const
2020-05-18 21:42:40 +02:00
{
2023-03-04 22:16:07 +00:00
auto & vm = this - > vm ( ) ;
2023-03-04 22:37:12 +00:00
// 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 const relevant_document = this - > relevant_document ( ) ;
if ( relevant_document & & ! relevant_document - > origin ( ) . is_same_origin_domain ( entry_settings_object ( ) . origin ( ) ) )
2023-09-06 16:03:01 +12:00
return WebIDL : : SecurityError : : create ( realm ( ) , " Location's relevant document is not same origin-domain with the entry settings object's origin " _fly_string ) ;
2022-03-04 23:35:34 +01:00
2023-01-18 17:41:12 +00:00
// 2. Return this's url's scheme, followed by ":".
2023-03-04 22:16:07 +00:00
return TRY_OR_THROW_OOM ( vm , String : : formatted ( " {}: " , url ( ) . scheme ( ) ) ) ;
2023-01-18 17:41:12 +00:00
}
2022-03-05 00:22:48 +01:00
2023-03-04 22:19:14 +00:00
WebIDL : : ExceptionOr < void > Location : : set_protocol ( String const & )
2023-01-18 17:41:12 +00:00
{
auto & vm = this - > vm ( ) ;
return vm . throw_completion < JS : : InternalError > ( JS : : ErrorType : : NotImplemented , " Location.protocol setter " ) ;
2020-05-18 21:42:40 +02:00
}
2022-03-04 23:35:34 +01:00
// https://html.spec.whatwg.org/multipage/history.html#dom-location-host
2023-03-04 22:16:07 +00:00
WebIDL : : ExceptionOr < String > Location : : host ( ) const
2020-05-18 21:59:16 +02:00
{
2023-03-04 22:16:07 +00:00
auto & vm = this - > vm ( ) ;
2023-03-04 22:37:12 +00:00
// 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 const relevant_document = this - > relevant_document ( ) ;
if ( relevant_document & & ! relevant_document - > origin ( ) . is_same_origin_domain ( entry_settings_object ( ) . origin ( ) ) )
2023-09-06 16:03:01 +12:00
return WebIDL : : SecurityError : : create ( realm ( ) , " Location's relevant document is not same origin-domain with the entry settings object's origin " _fly_string ) ;
2022-03-04 23:35:34 +01:00
// 2. Let url be this's url.
2023-01-18 17:41:12 +00:00
auto url = this - > url ( ) ;
2022-03-04 23:35:34 +01:00
2022-03-05 00:22:48 +01:00
// 3. If url's host is null, return the empty string.
2023-07-27 21:40:41 +12:00
if ( url . host ( ) . has < Empty > ( ) )
2023-03-04 22:16:07 +00:00
return String { } ;
2022-03-05 00:22:48 +01:00
// 4. If url's port is null, return url's host, serialized.
if ( ! url . port ( ) . has_value ( ) )
2023-07-27 21:40:41 +12:00
return TRY_OR_THROW_OOM ( vm , url . serialized_host ( ) ) ;
2022-03-04 23:35:34 +01:00
// 5. Return url's host, serialized, followed by ":" and url's port, serialized.
2023-07-27 21:40:41 +12:00
return TRY_OR_THROW_OOM ( vm , String : : formatted ( " {}:{} " , TRY_OR_THROW_OOM ( vm , url . serialized_host ( ) ) , * url . port ( ) ) ) ;
2020-05-18 21:59:16 +02:00
}
2023-03-04 22:19:14 +00:00
WebIDL : : ExceptionOr < void > Location : : set_host ( String const & )
2020-05-18 21:42:40 +02:00
{
2023-01-18 17:41:12 +00:00
auto & vm = this - > vm ( ) ;
return vm . throw_completion < JS : : InternalError > ( JS : : ErrorType : : NotImplemented , " Location.host setter " ) ;
}
2022-03-04 23:35:34 +01:00
2023-01-18 17:41:12 +00:00
// https://html.spec.whatwg.org/multipage/history.html#dom-location-hostname
2023-03-04 22:16:07 +00:00
WebIDL : : ExceptionOr < String > Location : : hostname ( ) const
2023-01-18 17:41:12 +00:00
{
2023-03-04 22:16:07 +00:00
auto & vm = this - > vm ( ) ;
2023-03-04 22:37:12 +00:00
// 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 const relevant_document = this - > relevant_document ( ) ;
if ( relevant_document & & ! relevant_document - > origin ( ) . is_same_origin_domain ( entry_settings_object ( ) . origin ( ) ) )
2023-09-06 16:03:01 +12:00
return WebIDL : : SecurityError : : create ( realm ( ) , " Location's relevant document is not same origin-domain with the entry settings object's origin " _fly_string ) ;
2022-03-04 23:35:34 +01:00
2023-01-18 17:41:12 +00:00
auto url = this - > url ( ) ;
2022-03-04 23:35:34 +01:00
2023-01-18 17:41:12 +00:00
// 2. If this's url's host is null, return the empty string.
2023-07-27 21:40:41 +12:00
if ( url . host ( ) . has < Empty > ( ) )
2023-03-04 22:16:07 +00:00
return String { } ;
2023-01-18 17:41:12 +00:00
// 3. Return this's url's host, serialized.
2023-07-27 21:40:41 +12:00
return TRY_OR_THROW_OOM ( vm , url . serialized_host ( ) ) ;
2020-05-18 21:42:40 +02:00
}
2023-03-04 22:19:14 +00:00
WebIDL : : ExceptionOr < void > Location : : set_hostname ( String const & )
2020-05-18 21:42:40 +02:00
{
2023-01-18 17:41:12 +00:00
auto & vm = this - > vm ( ) ;
return vm . throw_completion < JS : : InternalError > ( JS : : ErrorType : : NotImplemented , " Location.hostname setter " ) ;
}
2022-03-04 23:35:34 +01:00
2023-01-18 17:41:12 +00:00
// https://html.spec.whatwg.org/multipage/history.html#dom-location-port
2023-03-04 22:16:07 +00:00
WebIDL : : ExceptionOr < String > Location : : port ( ) const
2023-01-18 17:41:12 +00:00
{
2023-03-04 22:16:07 +00:00
auto & vm = this - > vm ( ) ;
2023-03-04 22:37:12 +00:00
// 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 const relevant_document = this - > relevant_document ( ) ;
if ( relevant_document & & ! relevant_document - > origin ( ) . is_same_origin_domain ( entry_settings_object ( ) . origin ( ) ) )
2023-09-06 16:03:01 +12:00
return WebIDL : : SecurityError : : create ( realm ( ) , " Location's relevant document is not same origin-domain with the entry settings object's origin " _fly_string ) ;
2022-03-04 23:35:34 +01:00
2023-01-18 17:41:12 +00:00
auto url = this - > url ( ) ;
2022-03-04 23:35:34 +01:00
2023-01-18 17:41:12 +00:00
// 2. If this's url's port is null, return the empty string.
if ( ! url . port ( ) . has_value ( ) )
2023-03-04 22:16:07 +00:00
return String { } ;
2023-01-18 17:41:12 +00:00
// 3. Return this's url's port, serialized.
2023-03-04 22:16:07 +00:00
return TRY_OR_THROW_OOM ( vm , String : : number ( * url . port ( ) ) ) ;
2020-05-18 21:42:40 +02:00
}
2023-03-04 22:19:14 +00:00
WebIDL : : ExceptionOr < void > Location : : set_port ( String const & )
2020-05-18 21:59:16 +02:00
{
2023-01-18 17:41:12 +00:00
auto & vm = this - > vm ( ) ;
return vm . throw_completion < JS : : InternalError > ( JS : : ErrorType : : NotImplemented , " Location.port setter " ) ;
}
2022-03-04 23:35:34 +01:00
2023-01-18 17:41:12 +00:00
// https://html.spec.whatwg.org/multipage/history.html#dom-location-pathname
2023-03-04 22:16:07 +00:00
WebIDL : : ExceptionOr < String > Location : : pathname ( ) const
2023-01-18 17:41:12 +00:00
{
2023-03-04 22:16:07 +00:00
auto & vm = this - > vm ( ) ;
2023-03-04 22:37:12 +00:00
// 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 const relevant_document = this - > relevant_document ( ) ;
if ( relevant_document & & ! relevant_document - > origin ( ) . is_same_origin_domain ( entry_settings_object ( ) . origin ( ) ) )
2023-09-06 16:03:01 +12:00
return WebIDL : : SecurityError : : create ( realm ( ) , " Location's relevant document is not same origin-domain with the entry settings object's origin " _fly_string ) ;
2022-03-04 23:35:34 +01:00
2023-01-18 17:41:12 +00:00
// 2. Return the result of URL path serializing this Location object's url.
2023-04-14 20:12:03 +01:00
return TRY_OR_THROW_OOM ( vm , String : : from_deprecated_string ( url ( ) . serialize_path ( ) ) ) ;
2020-05-18 21:59:16 +02:00
}
2023-03-04 22:19:14 +00:00
WebIDL : : ExceptionOr < void > Location : : set_pathname ( String const & )
2021-09-18 21:44:45 +02:00
{
2023-01-18 17:41:12 +00:00
auto & vm = this - > vm ( ) ;
return vm . throw_completion < JS : : InternalError > ( JS : : ErrorType : : NotImplemented , " Location.pathname setter " ) ;
}
2022-03-04 23:35:34 +01:00
2023-01-18 17:41:12 +00:00
// https://html.spec.whatwg.org/multipage/history.html#dom-location-search
2023-03-04 22:16:07 +00:00
WebIDL : : ExceptionOr < String > Location : : search ( ) const
2023-01-18 17:41:12 +00:00
{
2023-03-04 22:16:07 +00:00
auto & vm = this - > vm ( ) ;
2023-03-04 22:37:12 +00:00
// 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 const relevant_document = this - > relevant_document ( ) ;
if ( relevant_document & & ! relevant_document - > origin ( ) . is_same_origin_domain ( entry_settings_object ( ) . origin ( ) ) )
2023-09-06 16:03:01 +12:00
return WebIDL : : SecurityError : : create ( realm ( ) , " Location's relevant document is not same origin-domain with the entry settings object's origin " _fly_string ) ;
2022-03-04 23:35:34 +01:00
2023-01-18 17:41:12 +00:00
auto url = this - > url ( ) ;
2022-03-04 23:35:34 +01:00
2023-01-18 17:41:12 +00:00
// 2. If this's url's query is either null or the empty string, return the empty string.
2023-08-12 19:28:19 +12:00
if ( ! url . query ( ) . has_value ( ) | | url . query ( ) - > is_empty ( ) )
2023-03-04 22:16:07 +00:00
return String { } ;
2023-01-18 17:41:12 +00:00
// 3. Return "?", followed by this's url's query.
2023-03-04 22:16:07 +00:00
return TRY_OR_THROW_OOM ( vm , String : : formatted ( " ?{} " , url . query ( ) ) ) ;
2021-09-18 21:44:45 +02:00
}
2023-03-04 22:19:14 +00:00
WebIDL : : ExceptionOr < void > Location : : set_search ( String const & )
2022-11-04 22:48:42 -03:00
{
2023-01-18 17:41:12 +00:00
auto & vm = this - > vm ( ) ;
return vm . throw_completion < JS : : InternalError > ( JS : : ErrorType : : NotImplemented , " Location.search setter " ) ;
}
2022-11-04 22:48:42 -03:00
2023-01-18 17:41:12 +00:00
// https://html.spec.whatwg.org/multipage/history.html#dom-location-hash
2023-03-04 22:16:07 +00:00
WebIDL : : ExceptionOr < String > Location : : hash ( ) const
2023-01-18 17:41:12 +00:00
{
2023-03-04 22:16:07 +00:00
auto & vm = this - > vm ( ) ;
2023-03-04 22:37:12 +00:00
// 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 const relevant_document = this - > relevant_document ( ) ;
if ( relevant_document & & ! relevant_document - > origin ( ) . is_same_origin_domain ( entry_settings_object ( ) . origin ( ) ) )
2023-09-06 16:03:01 +12:00
return WebIDL : : SecurityError : : create ( realm ( ) , " Location's relevant document is not same origin-domain with the entry settings object's origin " _fly_string ) ;
2022-11-04 22:48:42 -03:00
2023-01-18 17:41:12 +00:00
auto url = this - > url ( ) ;
// 2. If this's url's fragment is either null or the empty string, return the empty string.
2023-08-12 16:52:42 +12:00
if ( ! url . fragment ( ) . has_value ( ) | | url . fragment ( ) - > is_empty ( ) )
2023-03-04 22:16:07 +00:00
return String { } ;
2023-01-18 17:41:12 +00:00
// 3. Return "#", followed by this's url's fragment.
2023-08-12 16:52:42 +12:00
return TRY_OR_THROW_OOM ( vm , String : : formatted ( " #{} " , * url . fragment ( ) ) ) ;
2023-01-18 17:41:12 +00:00
}
2023-02-11 12:19:28 +01:00
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-location-hash
2023-03-04 22:19:14 +00:00
WebIDL : : ExceptionOr < void > Location : : set_hash ( String const & value )
2023-01-18 17:41:12 +00:00
{
2023-02-11 12:19:28 +01:00
// The hash setter steps are:
2023-03-04 22:37:12 +00:00
auto const relevant_document = this - > relevant_document ( ) ;
2023-02-11 12:19:28 +01:00
// 1. If this's relevant Document is null, then return.
2023-03-04 22:37:12 +00:00
if ( ! relevant_document )
2023-02-11 12:19:28 +01:00
return { } ;
2023-03-04 22:37:12 +00:00
// 2. If this's relevant Document's origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException.
if ( ! relevant_document - > origin ( ) . is_same_origin_domain ( entry_settings_object ( ) . origin ( ) ) )
2023-09-06 16:03:01 +12:00
return WebIDL : : SecurityError : : create ( realm ( ) , " Location's relevant document is not same origin-domain with the entry settings object's origin " _fly_string ) ;
2023-02-11 12:19:28 +01:00
// 3. Let copyURL be a copy of this's url.
auto copy_url = this - > url ( ) ;
// 4. Let input be the given value with a single leading "#" removed, if any.
2023-03-04 22:16:07 +00:00
auto input = value . bytes_as_string_view ( ) . trim ( " # " sv , TrimMode : : Left ) ;
2023-02-11 12:19:28 +01:00
// 5. Set copyURL's fragment to the empty string.
2023-08-12 16:52:42 +12:00
copy_url . set_fragment ( String { } ) ;
2023-02-11 12:19:28 +01:00
// 6. Basic URL parse input, with copyURL as url and fragment state as state override.
2023-07-15 14:29:20 +12:00
auto result_url = URLParser : : basic_parse ( input , { } , copy_url , URLParser : : State : : Fragment ) ;
2023-02-11 12:19:28 +01:00
// 7. If copyURL's fragment is this's url's fragment, then return.
if ( copy_url . fragment ( ) = = this - > url ( ) . fragment ( ) )
return { } ;
// 8. Location-object navigate this to copyURL.
2023-08-22 18:33:20 +02:00
TRY ( navigate ( copy_url ) ) ;
2023-02-11 12:19:28 +01:00
return { } ;
2022-11-04 22:48:42 -03:00
}
2022-03-04 23:35:34 +01:00
// https://html.spec.whatwg.org/multipage/history.html#dom-location-reload
2023-01-18 17:41:12 +00:00
void Location : : reload ( ) const
2020-05-18 22:05:13 +02:00
{
2023-08-22 18:21:00 +02:00
// 1. Let document be this's relevant Document.
auto document = relevant_document ( ) ;
// 2. If document is null, then return.
if ( ! document )
return ;
2023-08-22 18:33:20 +02:00
2023-08-22 18:21:00 +02:00
// FIXME: 3. If document's origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException.
// 4. Reload document's node navigable.
document - > navigable ( ) - > reload ( ) ;
2020-05-18 22:05:13 +02:00
}
2022-03-04 23:35:34 +01:00
// https://html.spec.whatwg.org/multipage/history.html#dom-location-replace
2023-08-22 18:49:28 +02:00
WebIDL : : ExceptionOr < void > Location : : replace ( String const & url )
2021-10-03 23:31:52 +02:00
{
2023-08-22 18:49:28 +02:00
// 1. If this's relevant Document is null, then return.
if ( ! relevant_document ( ) )
return { } ;
// 2. Parse url relative to the entry settings object. If that failed, throw a "SyntaxError" DOMException.
auto replace_url = entry_settings_object ( ) . parse_url ( url ) ;
if ( ! replace_url . is_valid ( ) )
return WebIDL : : SyntaxError : : create ( realm ( ) , MUST ( String : : formatted ( " Invalid URL '{}' " , url ) ) ) ;
// 3. Location-object navigate this to the resulting URL record given "replace".
TRY ( navigate ( replace_url , HistoryHandlingBehavior : : Replace ) ) ;
return { } ;
2021-10-03 23:31:52 +02:00
}
2023-05-15 20:11:38 +01:00
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-location-assign
2023-08-22 18:33:20 +02:00
WebIDL : : ExceptionOr < void > Location : : assign ( String const & url )
2023-05-15 20:11:38 +01:00
{
// 1. If this's relevant Document is null, then return.
auto const relevant_document = this - > relevant_document ( ) ;
if ( ! relevant_document )
return { } ;
// 2. If this's relevant Document's origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException.
if ( ! relevant_document - > origin ( ) . is_same_origin_domain ( entry_settings_object ( ) . origin ( ) ) )
2023-09-06 16:03:01 +12:00
return WebIDL : : SecurityError : : create ( realm ( ) , " Location's relevant document is not same origin-domain with the entry settings object's origin " _fly_string ) ;
2023-05-15 20:11:38 +01:00
// 3. Parse url relative to the entry settings object. If that failed, throw a "SyntaxError" DOMException.
auto assign_url = entry_settings_object ( ) . parse_url ( url ) ;
if ( ! assign_url . is_valid ( ) )
2023-09-06 16:03:01 +12:00
return WebIDL : : SyntaxError : : create ( realm ( ) , MUST ( String : : formatted ( " Invalid URL '{}' " , url ) ) ) ;
2023-05-15 20:11:38 +01:00
// 4. Location-object navigate this to the resulting URL record.
2023-08-22 18:33:20 +02:00
TRY ( navigate ( assign_url ) ) ;
2023-05-15 20:11:38 +01:00
return { } ;
}
2022-03-06 00:24:18 +01:00
// 7.10.5.1 [[GetPrototypeOf]] ( ), https://html.spec.whatwg.org/multipage/history.html#location-getprototypeof
2023-01-18 17:41:12 +00:00
JS : : ThrowCompletionOr < JS : : Object * > Location : : internal_get_prototype_of ( ) const
2022-03-06 00:24:18 +01:00
{
// 1. If IsPlatformObjectSameOrigin(this) is true, then return ! OrdinaryGetPrototypeOf(this).
2022-09-24 14:02:47 +01:00
if ( HTML : : is_platform_object_same_origin ( * this ) )
2022-03-06 00:24:18 +01:00
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
2023-01-18 17:41:12 +00:00
JS : : ThrowCompletionOr < bool > Location : : internal_set_prototype_of ( Object * prototype )
2021-09-12 14:54:17 +01:00
{
// 1. Return ! SetImmutablePrototype(this, V).
2021-10-03 19:52:13 +01:00
return MUST ( set_immutable_prototype ( prototype ) ) ;
2021-09-12 14:54:17 +01:00
}
2022-03-06 00:24:18 +01:00
// 7.10.5.3 [[IsExtensible]] ( ), https://html.spec.whatwg.org/multipage/history.html#location-isextensible
2023-01-18 17:41:12 +00:00
JS : : ThrowCompletionOr < bool > Location : : internal_is_extensible ( ) const
2021-09-12 14:54:17 +01:00
{
// 1. Return true.
return true ;
}
2022-03-06 00:24:18 +01:00
// 7.10.5.4 [[PreventExtensions]] ( ), https://html.spec.whatwg.org/multipage/history.html#location-preventextensions
2023-01-18 17:41:12 +00:00
JS : : ThrowCompletionOr < bool > Location : : internal_prevent_extensions ( )
2021-09-12 14:54:17 +01:00
{
// 1. Return false.
return false ;
2020-05-18 21:42:40 +02:00
}
2022-03-06 00:24:18 +01:00
// 7.10.5.5 [[GetOwnProperty]] ( P ), https://html.spec.whatwg.org/multipage/history.html#location-getownproperty
2023-01-18 17:41:12 +00:00
JS : : ThrowCompletionOr < Optional < JS : : PropertyDescriptor > > Location : : internal_get_own_property ( JS : : PropertyKey const & property_key ) const
2022-03-06 00:24:18 +01:00
{
2022-08-21 21:21:52 +01:00
auto & vm = this - > vm ( ) ;
2022-03-06 00:24:18 +01:00
// 1. If IsPlatformObjectSameOrigin(this) is true, then:
2022-09-24 14:02:47 +01:00
if ( HTML : : is_platform_object_same_origin ( * this ) ) {
2022-03-06 00:24:18 +01:00
// 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 ( ) }
2022-12-06 22:17:27 +00:00
: JS : : PrimitiveString : : create ( vm , property_key . to_string ( ) ) ;
2022-03-06 00:24:18 +01:00
if ( m_default_properties . contains_slow ( property_key_value ) )
descriptor - > configurable = true ;
// 3. Return desc.
return descriptor ;
}
// 2. Let property be CrossOriginGetOwnPropertyHelper(this, P).
2023-01-18 17:41:12 +00:00
auto property = HTML : : cross_origin_get_own_property_helper ( const_cast < Location * > ( this ) , property_key ) ;
2022-03-06 00:24:18 +01:00
// 3. If property is not undefined, then return property.
if ( property . has_value ( ) )
return property ;
// 4. Return ? CrossOriginPropertyFallback(P).
2022-09-24 14:02:47 +01:00
return TRY ( HTML : : cross_origin_property_fallback ( vm , property_key ) ) ;
2022-03-06 00:24:18 +01:00
}
// 7.10.5.6 [[DefineOwnProperty]] ( P, Desc ), https://html.spec.whatwg.org/multipage/history.html#location-defineownproperty
2023-01-18 17:41:12 +00:00
JS : : ThrowCompletionOr < bool > Location : : internal_define_own_property ( JS : : PropertyKey const & property_key , JS : : PropertyDescriptor const & descriptor )
2022-03-06 00:24:18 +01:00
{
// 1. If IsPlatformObjectSameOrigin(this) is true, then:
2022-09-24 14:02:47 +01:00
if ( HTML : : is_platform_object_same_origin ( * this ) ) {
2022-03-06 00:24:18 +01:00
// 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.
2023-09-06 16:03:01 +12:00
return throw_completion ( WebIDL : : SecurityError : : create ( realm ( ) , MUST ( String : : formatted ( " Can't define property ' { } ' on cross - origin object " , property_key))));
2022-03-06 00:24:18 +01:00
}
// 7.10.5.7 [[Get]] ( P, Receiver ), https://html.spec.whatwg.org/multipage/history.html#location-get
2023-07-08 17:39:18 +02:00
JS : : ThrowCompletionOr < JS : : Value > Location : : internal_get ( JS : : PropertyKey const & property_key , JS : : Value receiver , JS : : CacheablePropertyMetadata * cacheable_metadata ) const
2022-03-06 00:24:18 +01:00
{
2022-08-21 21:21:52 +01:00
auto & vm = this - > vm ( ) ;
2022-03-06 00:24:18 +01:00
// 1. If IsPlatformObjectSameOrigin(this) is true, then return ? OrdinaryGet(this, P, Receiver).
2022-09-24 14:02:47 +01:00
if ( HTML : : is_platform_object_same_origin ( * this ) )
2023-07-08 17:39:18 +02:00
return JS : : Object : : internal_get ( property_key , receiver , cacheable_metadata ) ;
2022-03-06 00:24:18 +01:00
// 2. Return ? CrossOriginGet(this, P, Receiver).
2022-09-24 14:02:47 +01:00
return HTML : : cross_origin_get ( vm , static_cast < JS : : Object const & > ( * this ) , property_key , receiver ) ;
2022-03-06 00:24:18 +01:00
}
// 7.10.5.8 [[Set]] ( P, V, Receiver ), https://html.spec.whatwg.org/multipage/history.html#location-set
2023-01-18 17:41:12 +00:00
JS : : ThrowCompletionOr < bool > Location : : internal_set ( JS : : PropertyKey const & property_key , JS : : Value value , JS : : Value receiver )
2022-03-06 00:24:18 +01:00
{
2022-08-21 21:21:52 +01:00
auto & vm = this - > vm ( ) ;
2022-03-06 00:24:18 +01:00
// 1. If IsPlatformObjectSameOrigin(this) is true, then return ? OrdinarySet(this, P, V, Receiver).
2022-09-24 14:02:47 +01:00
if ( HTML : : is_platform_object_same_origin ( * this ) )
2022-03-06 00:24:18 +01:00
return JS : : Object : : internal_set ( property_key , value , receiver ) ;
// 2. Return ? CrossOriginSet(this, P, V, Receiver).
2022-09-24 14:02:47 +01:00
return HTML : : cross_origin_set ( vm , static_cast < JS : : Object & > ( * this ) , property_key , value , receiver ) ;
2022-03-06 00:24:18 +01:00
}
// 7.10.5.9 [[Delete]] ( P ), https://html.spec.whatwg.org/multipage/history.html#location-delete
2023-01-18 17:41:12 +00:00
JS : : ThrowCompletionOr < bool > Location : : internal_delete ( JS : : PropertyKey const & property_key )
2022-03-06 00:24:18 +01:00
{
// 1. If IsPlatformObjectSameOrigin(this) is true, then return ? OrdinaryDelete(this, P).
2022-09-24 14:02:47 +01:00
if ( HTML : : is_platform_object_same_origin ( * this ) )
2022-03-06 00:24:18 +01:00
return JS : : Object : : internal_delete ( property_key ) ;
// 2. Throw a "SecurityError" DOMException.
2023-09-06 16:03:01 +12:00
return throw_completion ( WebIDL : : SecurityError : : create ( realm ( ) , MUST ( String : : formatted ( " Can't delete property ' { } ' on cross - origin object " , property_key))));
2022-03-06 00:24:18 +01:00
}
// 7.10.5.10 [[OwnPropertyKeys]] ( ), https://html.spec.whatwg.org/multipage/history.html#location-ownpropertykeys
2023-01-18 17:41:12 +00:00
JS : : ThrowCompletionOr < JS : : MarkedVector < JS : : Value > > Location : : internal_own_property_keys ( ) const
2022-03-06 00:24:18 +01:00
{
// 1. If IsPlatformObjectSameOrigin(this) is true, then return OrdinaryOwnPropertyKeys(this).
2022-09-24 14:02:47 +01:00
if ( HTML : : is_platform_object_same_origin ( * this ) )
2022-03-06 00:24:18 +01:00
return JS : : Object : : internal_own_property_keys ( ) ;
// 2. Return CrossOriginOwnPropertyKeys(this).
2022-09-24 14:02:47 +01:00
return HTML : : cross_origin_own_property_keys ( this ) ;
2022-03-06 00:24:18 +01:00
}
2020-05-18 21:42:40 +02:00
}