LibWeb: Delete LegacyPlatformObject and move behavior to PlatformObject
We have two known PlatformObjects that need to implement some of the behavior of LegacyPlatformObjects to date: Window, and HTMLFormElement. To make this not require double (or virtual) inheritance of PlatformObject, move the behavior of LegacyPlatformObject into PlatformObject. The selection of LegacyPlatformObject behavior is done with a new bitfield of feature flags instead of a dozen virtual functions that return bool. This change simplifies every class involved in the diff with the notable exception of Window, which now needs some ugly const casts to implement named property access.
This commit is contained in:
parent
6047f1adcb
commit
521ed0e911
Notes:
sideshowbarker
2024-07-17 01:28:15 +09:00
Author: https://github.com/ADKaster Commit: https://github.com/SerenityOS/serenity/commit/521ed0e911 Pull-request: https://github.com/SerenityOS/serenity/pull/22675 Reviewed-by: https://github.com/shannonbooth ✅
41 changed files with 684 additions and 801 deletions
|
@ -2647,7 +2647,7 @@ JS::ThrowCompletionOr<Optional<JS::PropertyDescriptor>> @named_properties_class@
|
|||
auto& object = verify_cast<A>(realm.global_object());
|
||||
|
||||
// 4. If the result of running the named property visibility algorithm with property name P and object object is true, then:
|
||||
if (TRY(is_named_property_exposed_on_object({ &object }, property_name))) {
|
||||
if (TRY(object.is_named_property_exposed_on_object(property_name))) {
|
||||
auto property_name_string = MUST(FlyString::from_deprecated_fly_string(property_name.to_string()));
|
||||
|
||||
// 1. Let operation be the operation used to declare the named property getter.
|
||||
|
|
|
@ -11,8 +11,6 @@ source_set("Bindings") {
|
|||
"ImageConstructor.h",
|
||||
"Intrinsics.cpp",
|
||||
"Intrinsics.h",
|
||||
"LegacyPlatformObject.cpp",
|
||||
"LegacyPlatformObject.h",
|
||||
"MainThreadVM.cpp",
|
||||
"MainThreadVM.h",
|
||||
"OptionConstructor.cpp",
|
||||
|
|
|
@ -1,394 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
#include <LibWeb/Bindings/ExceptionOrUtils.h>
|
||||
#include <LibWeb/Bindings/LegacyPlatformObject.h>
|
||||
|
||||
namespace Web::Bindings {
|
||||
|
||||
LegacyPlatformObject::LegacyPlatformObject(JS::Realm& realm)
|
||||
: PlatformObject(realm, MayInterfereWithIndexedPropertyAccess::Yes)
|
||||
{
|
||||
}
|
||||
|
||||
LegacyPlatformObject::~LegacyPlatformObject() = default;
|
||||
|
||||
// https://webidl.spec.whatwg.org/#LegacyPlatformObjectGetOwnProperty
|
||||
JS::ThrowCompletionOr<Optional<JS::PropertyDescriptor>> LegacyPlatformObject::legacy_platform_object_get_own_property(JS::PropertyKey const& property_name, IgnoreNamedProps ignore_named_props) const
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. If O supports indexed properties and P is an array index, then:
|
||||
if (supports_indexed_properties() && property_name.is_number()) {
|
||||
// 1. Let index be the result of calling ToUint32(P).
|
||||
u32 index = property_name.as_number();
|
||||
|
||||
// 2. If index is a supported property index, then:
|
||||
if (is_supported_property_index(index)) {
|
||||
// 1. Let operation be the operation used to declare the indexed property getter.
|
||||
// 2. Let value be an uninitialized variable.
|
||||
// 3. If operation was defined without an identifier, then set value to the result of performing the steps listed in the interface description to determine the value of an indexed property with index as the index.
|
||||
// 4. Otherwise, operation was defined with an identifier. Set value to the result of performing the method steps of operation with O as this and « index » as the argument values.
|
||||
auto value = TRY(throw_dom_exception_if_needed(vm, [&] { return item_value(index); }));
|
||||
|
||||
// 5. Let desc be a newly created Property Descriptor with no fields.
|
||||
JS::PropertyDescriptor descriptor;
|
||||
|
||||
// 6. Set desc.[[Value]] to the result of converting value to an ECMAScript value.
|
||||
descriptor.value = value;
|
||||
|
||||
// 7. If O implements an interface with an indexed property setter, then set desc.[[Writable]] to true, otherwise set it to false.
|
||||
descriptor.writable = has_indexed_property_setter();
|
||||
|
||||
// 8. Set desc.[[Enumerable]] and desc.[[Configurable]] to true.
|
||||
descriptor.enumerable = true;
|
||||
descriptor.configurable = true;
|
||||
|
||||
// 9. Return desc.
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
// 3. Set ignoreNamedProps to true.
|
||||
ignore_named_props = IgnoreNamedProps::Yes;
|
||||
}
|
||||
|
||||
// 2. If O supports named properties and ignoreNamedProps is false, then:
|
||||
if (supports_named_properties() && ignore_named_props == IgnoreNamedProps::No) {
|
||||
// 1. If the result of running the named property visibility algorithm with property name P and object O is true, then:
|
||||
if (TRY(WebIDL::is_named_property_exposed_on_object({ this }, property_name))) {
|
||||
// FIXME: It's unfortunate that this is done twice, once in is_named_property_exposed_on_object and here.
|
||||
auto property_name_string = MUST(FlyString::from_deprecated_fly_string(property_name.to_string()));
|
||||
|
||||
// 1. Let operation be the operation used to declare the named property getter.
|
||||
// 2. Let value be an uninitialized variable.
|
||||
// 3. If operation was defined without an identifier, then set value to the result of performing the steps listed in the interface description to determine the value of a named property with P as the name.
|
||||
// 4. Otherwise, operation was defined with an identifier. Set value to the result of performing the method steps of operation with O as this and « P » as the argument values.
|
||||
auto value = TRY(throw_dom_exception_if_needed(vm, [&] { return named_item_value(property_name_string); }));
|
||||
|
||||
// 5. Let desc be a newly created Property Descriptor with no fields.
|
||||
JS::PropertyDescriptor descriptor;
|
||||
|
||||
// 6. Set desc.[[Value]] to the result of converting value to an ECMAScript value.
|
||||
descriptor.value = value;
|
||||
|
||||
// 7. If O implements an interface with a named property setter, then set desc.[[Writable]] to true, otherwise set it to false.
|
||||
descriptor.writable = has_named_property_setter();
|
||||
|
||||
// 8. If O implements an interface with the [LegacyUnenumerableNamedProperties] extended attribute, then set desc.[[Enumerable]] to false, otherwise set it to true.
|
||||
descriptor.enumerable = !has_legacy_unenumerable_named_properties_interface_extended_attribute();
|
||||
|
||||
// 9. Set desc.[[Configurable]] to true.
|
||||
descriptor.configurable = true;
|
||||
|
||||
// 10. Return desc.
|
||||
return descriptor;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Return OrdinaryGetOwnProperty(O, P).
|
||||
return TRY(Object::internal_get_own_property(property_name));
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#invoke-indexed-setter
|
||||
WebIDL::ExceptionOr<void> LegacyPlatformObject::invoke_indexed_property_setter(JS::PropertyKey const& property_name, JS::Value value)
|
||||
{
|
||||
// 1. Let index be the result of calling ? ToUint32(P).
|
||||
auto index = property_name.as_number();
|
||||
|
||||
// 2. Let creating be true if index is not a supported property index, and false otherwise.
|
||||
bool creating = !is_supported_property_index(index);
|
||||
|
||||
// FIXME: We do not have this information at this point, so converting the value is left as an exercise to the inheritor of LegacyPlatformObject.
|
||||
// 3. Let operation be the operation used to declare the indexed property setter.
|
||||
// 4. Let T be the type of the second argument of operation.
|
||||
// 5. Let value be the result of converting V to an IDL value of type T.
|
||||
|
||||
// 6. If operation was defined without an identifier, then:
|
||||
if (!indexed_property_setter_has_identifier()) {
|
||||
// 1. If creating is true, then perform the steps listed in the interface description to set the value of a new indexed property with index as the index and value as the value.
|
||||
if (creating)
|
||||
return set_value_of_new_indexed_property(index, value);
|
||||
|
||||
// 2. Otherwise, creating is false. Perform the steps listed in the interface description to set the value of an existing indexed property with index as the index and value as the value.
|
||||
return set_value_of_existing_indexed_property(index, value);
|
||||
}
|
||||
|
||||
// 7. Otherwise, operation was defined with an identifier. Perform the method steps of operation with O as this and « index, value » as the argument values.
|
||||
return set_value_of_indexed_property(index, value);
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#invoke-named-setter
|
||||
WebIDL::ExceptionOr<void> LegacyPlatformObject::invoke_named_property_setter(String const& property_name, JS::Value value)
|
||||
{
|
||||
// 1. Let creating be true if P is not a supported property name, and false otherwise.
|
||||
auto supported_property_names = this->supported_property_names();
|
||||
bool creating = !supported_property_names.contains_slow(property_name);
|
||||
|
||||
// FIXME: We do not have this information at this point, so converting the value is left as an exercise to the inheritor of LegacyPlatformObject.
|
||||
// 2. Let operation be the operation used to declare the indexed property setter.
|
||||
// 3. Let T be the type of the second argument of operation.
|
||||
// 4. Let value be the result of converting V to an IDL value of type T.
|
||||
|
||||
// 5. If operation was defined without an identifier, then:
|
||||
if (!named_property_setter_has_identifier()) {
|
||||
// 1. If creating is true, then perform the steps listed in the interface description to set the value of a new named property with P as the name and value as the value.
|
||||
if (creating)
|
||||
return set_value_of_new_named_property(property_name, value);
|
||||
|
||||
// 2. Otherwise, creating is false. Perform the steps listed in the interface description to set the value of an existing named property with P as the name and value as the value.
|
||||
return set_value_of_existing_named_property(property_name, value);
|
||||
}
|
||||
|
||||
// 6. Otherwise, operation was defined with an identifier. Perform the method steps of operation with O as this and « P, value » as the argument values.
|
||||
return set_value_of_named_property(property_name, value);
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#legacy-platform-object-getownproperty
|
||||
JS::ThrowCompletionOr<Optional<JS::PropertyDescriptor>> LegacyPlatformObject::internal_get_own_property(JS::PropertyKey const& property_name) const
|
||||
{
|
||||
// 1. Return ? LegacyPlatformObjectGetOwnProperty(O, P, false).
|
||||
return TRY(legacy_platform_object_get_own_property(property_name, IgnoreNamedProps::No));
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#legacy-platform-object-set
|
||||
JS::ThrowCompletionOr<bool> LegacyPlatformObject::internal_set(JS::PropertyKey const& property_name, JS::Value value, JS::Value receiver, JS::CacheablePropertyMetadata*)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. If O and Receiver are the same object, then:
|
||||
if (receiver.is_object() && &receiver.as_object() == this) {
|
||||
// 1. If O implements an interface with an indexed property setter and P is an array index, then:
|
||||
if (has_indexed_property_setter() && property_name.is_number()) {
|
||||
// 1. Invoke the indexed property setter on O with P and V.
|
||||
TRY(throw_dom_exception_if_needed(vm, [&] { return invoke_indexed_property_setter(property_name, value); }));
|
||||
|
||||
// 2. Return true.
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2. If O implements an interface with a named property setter and Type(P) is String, then:
|
||||
if (has_named_property_setter() && property_name.is_string()) {
|
||||
// 1. Invoke the named property setter on O with P and V.
|
||||
TRY(throw_dom_exception_if_needed(vm, [&] { return invoke_named_property_setter(MUST(String::from_byte_string(property_name.as_string())), value); }));
|
||||
|
||||
// 2. Return true.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Let ownDesc be ? LegacyPlatformObjectGetOwnProperty(O, P, true).
|
||||
auto own_descriptor = TRY(legacy_platform_object_get_own_property(property_name, IgnoreNamedProps::Yes));
|
||||
|
||||
// 3. Perform ? OrdinarySetWithOwnDescriptor(O, P, V, Receiver, ownDesc).
|
||||
// NOTE: The spec says "perform" instead of "return", meaning nothing will be returned on this path according to the spec, which isn't possible to do.
|
||||
// Let's treat it as though it says "return" instead of "perform".
|
||||
return ordinary_set_with_own_descriptor(property_name, value, receiver, own_descriptor);
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#legacy-platform-object-defineownproperty
|
||||
JS::ThrowCompletionOr<bool> LegacyPlatformObject::internal_define_own_property(JS::PropertyKey const& property_name, JS::PropertyDescriptor const& property_descriptor)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. If O supports indexed properties and P is an array index, then:
|
||||
if (supports_indexed_properties() && property_name.is_number()) {
|
||||
// 1. If the result of calling IsDataDescriptor(Desc) is false, then return false.
|
||||
if (!property_descriptor.is_data_descriptor())
|
||||
return false;
|
||||
|
||||
// 2. If O does not implement an interface with an indexed property setter, then return false.
|
||||
if (!has_indexed_property_setter())
|
||||
return false;
|
||||
|
||||
// 3. Invoke the indexed property setter on O with P and Desc.[[Value]].
|
||||
TRY(throw_dom_exception_if_needed(vm, [&] { return invoke_indexed_property_setter(property_name, property_descriptor.value.value()); }));
|
||||
|
||||
// 4. Return true.
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2. If O supports named properties, O does not implement an interface with the [Global] extended attribute, Type(P) is String, and P is not an unforgeable property name of O, then:
|
||||
// FIXME: Check if P is not an unforgeable property name of O
|
||||
if (supports_named_properties() && !has_global_interface_extended_attribute() && property_name.is_string()) {
|
||||
auto const& property_name_as_string = property_name.as_string();
|
||||
|
||||
// 1. Let creating be true if P is not a supported property name, and false otherwise.
|
||||
// NOTE: This is in it's own variable to enforce the type.
|
||||
auto supported_property_names = this->supported_property_names();
|
||||
bool creating = !supported_property_names.contains_slow(MUST(FlyString::from_deprecated_fly_string(property_name_as_string)));
|
||||
|
||||
// 2. If O implements an interface with the [LegacyOverrideBuiltIns] extended attribute or O does not have an own property named P, then:
|
||||
// NOTE: Own property lookup has to be done manually instead of using Object::has_own_property, as that would use the overridden internal_get_own_property.
|
||||
if (has_legacy_override_built_ins_interface_extended_attribute() || !TRY(Object::internal_get_own_property(property_name)).has_value()) {
|
||||
// 1. If creating is false and O does not implement an interface with a named property setter, then return false.
|
||||
if (!creating && !has_named_property_setter())
|
||||
return false;
|
||||
|
||||
// 2. If O implements an interface with a named property setter, then:
|
||||
if (has_named_property_setter()) {
|
||||
// 1. If the result of calling IsDataDescriptor(Desc) is false, then return false.
|
||||
if (!property_descriptor.is_data_descriptor())
|
||||
return false;
|
||||
|
||||
// 2. Invoke the named property setter on O with P and Desc.[[Value]].
|
||||
TRY(throw_dom_exception_if_needed(vm, [&] { return invoke_named_property_setter(MUST(String::from_byte_string(property_name_as_string)), property_descriptor.value.value()); }));
|
||||
|
||||
// 3. Return true.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. If O does not implement an interface with the [Global] extended attribute, then set Desc.[[Configurable]] to true.
|
||||
// 4. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
|
||||
if (!has_global_interface_extended_attribute()) {
|
||||
// property_descriptor is a const&, thus we need to create a copy here to set [[Configurable]]
|
||||
JS::PropertyDescriptor descriptor_copy(property_descriptor);
|
||||
descriptor_copy.configurable = true;
|
||||
return Object::internal_define_own_property(property_name, descriptor_copy);
|
||||
}
|
||||
|
||||
return Object::internal_define_own_property(property_name, property_descriptor);
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#legacy-platform-object-delete
|
||||
JS::ThrowCompletionOr<bool> LegacyPlatformObject::internal_delete(JS::PropertyKey const& property_name)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. If O supports indexed properties and P is an array index, then:
|
||||
if (supports_indexed_properties() && property_name.is_number()) {
|
||||
// 1. Let index be the result of calling ! ToUint32(P).
|
||||
u32 index = property_name.as_number();
|
||||
|
||||
// 2. If index is not a supported property index, then return true.
|
||||
if (!is_supported_property_index(index))
|
||||
return true;
|
||||
|
||||
// 3. Return false.
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. If O supports named properties, O does not implement an interface with the [Global] extended attribute and
|
||||
// the result of calling the named property visibility algorithm with property name P and object O is true, then:
|
||||
if (supports_named_properties() && !has_global_interface_extended_attribute() && TRY(WebIDL::is_named_property_exposed_on_object({ this }, property_name))) {
|
||||
// 1. If O does not implement an interface with a named property deleter, then return false.
|
||||
if (!has_named_property_deleter())
|
||||
return false;
|
||||
|
||||
// FIXME: It's unfortunate that this is done twice, once in is_named_property_exposed_on_object and here.
|
||||
auto property_name_string = property_name.to_string();
|
||||
|
||||
// 2. Let operation be the operation used to declare the named property deleter.
|
||||
// 3. If operation was defined without an identifier, then:
|
||||
// 1. Perform the steps listed in the interface description to delete an existing named property with P as the name.
|
||||
// 2. If the steps indicated that the deletion failed, then return false.
|
||||
// 4. Otherwise, operation was defined with an identifier:
|
||||
// 1. Perform method steps of operation with O as this and « P » as the argument values.
|
||||
// 2. If operation was declared with a return type of boolean and the steps returned false, then return false.
|
||||
auto did_deletion_fail = TRY(throw_dom_exception_if_needed(vm, [&] { return delete_value(MUST(String::from_byte_string(property_name_string))); }));
|
||||
if (!named_property_deleter_has_identifier())
|
||||
VERIFY(did_deletion_fail != DidDeletionFail::NotRelevant);
|
||||
|
||||
if (did_deletion_fail == DidDeletionFail::Yes)
|
||||
return false;
|
||||
|
||||
// 5. Return true.
|
||||
return true;
|
||||
}
|
||||
|
||||
// 3. If O has an own property with name P, then:
|
||||
// NOTE: This has to be done manually instead of using Object::has_own_property, as that would use the overridden internal_get_own_property.
|
||||
auto own_property_named_p_descriptor = TRY(Object::internal_get_own_property(property_name));
|
||||
|
||||
if (own_property_named_p_descriptor.has_value()) {
|
||||
// 1. If the property is not configurable, then return false.
|
||||
if (!own_property_named_p_descriptor->configurable.value())
|
||||
return false;
|
||||
|
||||
// 2. Otherwise, remove the property from O.
|
||||
storage_delete(property_name);
|
||||
}
|
||||
|
||||
// 4. Return true.
|
||||
return true;
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#legacy-platform-object-preventextensions
|
||||
JS::ThrowCompletionOr<bool> LegacyPlatformObject::internal_prevent_extensions()
|
||||
{
|
||||
// 1. Return false.
|
||||
// Spec Note: Note: this keeps legacy platform objects extensible by making [[PreventExtensions]] fail for them.
|
||||
return false;
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#legacy-platform-object-ownpropertykeys
|
||||
JS::ThrowCompletionOr<JS::MarkedVector<JS::Value>> LegacyPlatformObject::internal_own_property_keys() const
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. Let keys be a new empty list of ECMAScript String and Symbol values.
|
||||
JS::MarkedVector<JS::Value> keys { heap() };
|
||||
|
||||
// 2. If O supports indexed properties, then for each index of O’s supported property indices, in ascending numerical order, append ! ToString(index) to keys.
|
||||
if (supports_indexed_properties()) {
|
||||
for (u64 index = 0; index <= NumericLimits<u32>::max(); ++index) {
|
||||
if (is_supported_property_index(index))
|
||||
keys.append(JS::PrimitiveString::create(vm, MUST(String::number(index))));
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. If O supports named properties, then for each P of O’s supported property names that is visible according to the named property visibility algorithm, append P to keys.
|
||||
if (supports_named_properties()) {
|
||||
for (auto& named_property : supported_property_names()) {
|
||||
if (TRY(WebIDL::is_named_property_exposed_on_object({ this }, named_property.to_deprecated_fly_string())))
|
||||
keys.append(JS::PrimitiveString::create(vm, named_property));
|
||||
}
|
||||
}
|
||||
|
||||
// 4. For each P of O’s own property keys that is a String, in ascending chronological order of property creation, append P to keys.
|
||||
for (auto& it : shape().property_table()) {
|
||||
if (it.key.is_string())
|
||||
keys.append(it.key.to_value(vm));
|
||||
}
|
||||
|
||||
// 5. For each P of O’s own property keys that is a Symbol, in ascending chronological order of property creation, append P to keys.
|
||||
for (auto& it : shape().property_table()) {
|
||||
if (it.key.is_symbol())
|
||||
keys.append(it.key.to_value(vm));
|
||||
}
|
||||
|
||||
// FIXME: 6. Assert: keys has no duplicate items.
|
||||
|
||||
// 7. Return keys.
|
||||
return { move(keys) };
|
||||
}
|
||||
|
||||
WebIDL::ExceptionOr<JS::Value> LegacyPlatformObject::item_value(size_t) const
|
||||
{
|
||||
return JS::js_undefined();
|
||||
}
|
||||
|
||||
WebIDL::ExceptionOr<JS::Value> LegacyPlatformObject::named_item_value(FlyString const&) const
|
||||
{
|
||||
return JS::js_undefined();
|
||||
}
|
||||
|
||||
Vector<FlyString> LegacyPlatformObject::supported_property_names() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
bool LegacyPlatformObject::is_supported_property_index(u32) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,96 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/Bindings/PlatformObject.h>
|
||||
#include <LibWeb/WebIDL/AbstractOperations.h>
|
||||
#include <LibWeb/WebIDL/ExceptionOr.h>
|
||||
|
||||
namespace Web::Bindings {
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-legacy-platform-object
|
||||
class LegacyPlatformObject : public PlatformObject {
|
||||
WEB_PLATFORM_OBJECT(LegacyPlatformObject, PlatformObject);
|
||||
|
||||
virtual bool has_legacy_override_built_ins_interface_extended_attribute() const = 0;
|
||||
|
||||
public:
|
||||
virtual ~LegacyPlatformObject() override;
|
||||
|
||||
virtual JS::ThrowCompletionOr<Optional<JS::PropertyDescriptor>> internal_get_own_property(JS::PropertyKey const&) const override;
|
||||
virtual JS::ThrowCompletionOr<bool> internal_set(JS::PropertyKey const&, JS::Value, JS::Value, JS::CacheablePropertyMetadata*) override;
|
||||
virtual JS::ThrowCompletionOr<bool> internal_define_own_property(JS::PropertyKey const&, JS::PropertyDescriptor const&) override;
|
||||
virtual JS::ThrowCompletionOr<bool> internal_delete(JS::PropertyKey const&) override;
|
||||
virtual JS::ThrowCompletionOr<bool> internal_prevent_extensions() override;
|
||||
virtual JS::ThrowCompletionOr<JS::MarkedVector<JS::Value>> internal_own_property_keys() const override;
|
||||
|
||||
enum class IgnoreNamedProps {
|
||||
No,
|
||||
Yes,
|
||||
};
|
||||
JS::ThrowCompletionOr<Optional<JS::PropertyDescriptor>> legacy_platform_object_get_own_property(JS::PropertyKey const&, IgnoreNamedProps ignore_named_props) const;
|
||||
|
||||
virtual WebIDL::ExceptionOr<JS::Value> item_value(size_t index) const;
|
||||
virtual WebIDL::ExceptionOr<JS::Value> named_item_value(FlyString const& name) const;
|
||||
virtual Vector<FlyString> supported_property_names() const;
|
||||
virtual bool is_supported_property_index(u32) const;
|
||||
|
||||
// NOTE: These will crash if you make has_named_property_setter return true but do not override these methods.
|
||||
// NOTE: This is only used if named_property_setter_has_identifier returns false, otherwise set_value_of_named_property is used instead.
|
||||
virtual WebIDL::ExceptionOr<void> set_value_of_new_named_property(String const&, JS::Value) { VERIFY_NOT_REACHED(); }
|
||||
virtual WebIDL::ExceptionOr<void> set_value_of_existing_named_property(String const&, JS::Value) { VERIFY_NOT_REACHED(); }
|
||||
|
||||
// NOTE: These will crash if you make has_named_property_setter return true but do not override these methods.
|
||||
// NOTE: This is only used if you make named_property_setter_has_identifier return true, otherwise set_value_of_{new,existing}_named_property is used instead.
|
||||
virtual WebIDL::ExceptionOr<void> set_value_of_named_property(String const&, JS::Value) { VERIFY_NOT_REACHED(); }
|
||||
|
||||
// NOTE: These will crash if you make has_indexed_property_setter return true but do not override these methods.
|
||||
// NOTE: This is only used if indexed_property_setter_has_identifier returns false, otherwise set_value_of_indexed_property is used instead.
|
||||
virtual WebIDL::ExceptionOr<void> set_value_of_new_indexed_property(u32, JS::Value) { VERIFY_NOT_REACHED(); }
|
||||
virtual WebIDL::ExceptionOr<void> set_value_of_existing_indexed_property(u32, JS::Value) { VERIFY_NOT_REACHED(); }
|
||||
|
||||
// NOTE: These will crash if you make has_named_property_setter return true but do not override these methods.
|
||||
// NOTE: This is only used if indexed_property_setter_has_identifier returns true, otherwise set_value_of_{new,existing}_indexed_property is used instead.
|
||||
virtual WebIDL::ExceptionOr<void> set_value_of_indexed_property(u32, JS::Value) { VERIFY_NOT_REACHED(); }
|
||||
|
||||
enum class DidDeletionFail {
|
||||
// If the named property deleter has an identifier, but does not return a boolean.
|
||||
// This is done because we don't know the return type of the deleter outside of the IDL generator.
|
||||
NotRelevant,
|
||||
No,
|
||||
Yes,
|
||||
};
|
||||
|
||||
// NOTE: This will crash if you make has_named_property_deleter return true but do not override this method.
|
||||
virtual WebIDL::ExceptionOr<DidDeletionFail> delete_value(String const&) { VERIFY_NOT_REACHED(); }
|
||||
|
||||
protected:
|
||||
explicit LegacyPlatformObject(JS::Realm& realm);
|
||||
|
||||
// NOTE: These two can also be seen as "has x property getter"
|
||||
virtual bool supports_indexed_properties() const = 0;
|
||||
virtual bool supports_named_properties() const = 0;
|
||||
|
||||
virtual bool has_indexed_property_setter() const = 0;
|
||||
virtual bool has_named_property_setter() const = 0;
|
||||
|
||||
virtual bool has_named_property_deleter() const = 0;
|
||||
|
||||
virtual bool has_legacy_unenumerable_named_properties_interface_extended_attribute() const = 0;
|
||||
virtual bool has_global_interface_extended_attribute() const = 0;
|
||||
|
||||
virtual bool indexed_property_setter_has_identifier() const = 0;
|
||||
virtual bool named_property_setter_has_identifier() const = 0;
|
||||
virtual bool named_property_deleter_has_identifier() const = 0;
|
||||
|
||||
private:
|
||||
WebIDL::ExceptionOr<void> invoke_indexed_property_setter(JS::PropertyKey const&, JS::Value);
|
||||
WebIDL::ExceptionOr<void> invoke_named_property_setter(String const&, JS::Value);
|
||||
};
|
||||
|
||||
}
|
|
@ -6,7 +6,9 @@
|
|||
|
||||
#include <AK/TypeCasts.h>
|
||||
#include <LibJS/Runtime/Realm.h>
|
||||
#include <LibWeb/Bindings/ExceptionOrUtils.h>
|
||||
#include <LibWeb/Bindings/PlatformObject.h>
|
||||
#include <LibWeb/Bindings/WindowPrototype.h>
|
||||
#include <LibWeb/HTML/Window.h>
|
||||
|
||||
namespace Web::Bindings {
|
||||
|
@ -28,9 +30,487 @@ JS::Realm& PlatformObject::realm() const
|
|||
return shape().realm();
|
||||
}
|
||||
|
||||
// FIXME: remove this
|
||||
HTML::Window& PlatformObject::global_object() const
|
||||
{
|
||||
return verify_cast<HTML::Window>(realm().global_object());
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-named-property-visibility
|
||||
JS::ThrowCompletionOr<bool> PlatformObject::is_named_property_exposed_on_object(JS::PropertyKey const& property_key) const
|
||||
{
|
||||
// The spec doesn't say anything about the type of the property name here.
|
||||
// Numbers can be converted to a string, which is fine and what other engines do.
|
||||
// However, since a symbol cannot be converted to a string, it cannot be a supported property name. Return early if it's a symbol.
|
||||
if (property_key.is_symbol())
|
||||
return false;
|
||||
|
||||
// 1. If P is not a supported property name of O, then return false.
|
||||
// NOTE: This is in it's own variable to enforce the type.
|
||||
auto supported_property_names = this->supported_property_names();
|
||||
auto property_key_string = MUST(String::from_byte_string(property_key.to_string()));
|
||||
if (!supported_property_names.contains_slow(property_key_string))
|
||||
return false;
|
||||
|
||||
// 2. If O has an own property named P, then return false.
|
||||
// NOTE: This has to be done manually instead of using Object::has_own_property, as that would use the overridden internal_get_own_property.
|
||||
auto own_property_named_p = MUST(Object::internal_get_own_property(property_key));
|
||||
|
||||
if (own_property_named_p.has_value())
|
||||
return false;
|
||||
|
||||
// 3. If O implements an interface that has the [LegacyOverrideBuiltIns] extended attribute, then return true.
|
||||
if (m_legacy_platform_object_flags->has_legacy_override_built_ins_interface_extended_attribute)
|
||||
return true;
|
||||
|
||||
// 4. Let prototype be O.[[GetPrototypeOf]]().
|
||||
auto* prototype = TRY(internal_get_prototype_of());
|
||||
|
||||
// 5. While prototype is not null:
|
||||
while (prototype) {
|
||||
// 1. If prototype is not a named properties object, and prototype has an own property named P, then return false.
|
||||
// FIXME: Are there other named properties objects?
|
||||
if (!is<Bindings::WindowProperties>(prototype)) {
|
||||
bool prototype_has_own_property_named_p = TRY(prototype->has_own_property(property_key));
|
||||
if (prototype_has_own_property_named_p)
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. Set prototype to prototype.[[GetPrototypeOf]]().
|
||||
prototype = TRY(prototype->internal_get_prototype_of());
|
||||
}
|
||||
|
||||
// 6. Return true.
|
||||
return true;
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#PlatformObjectGetOwnProperty
|
||||
JS::ThrowCompletionOr<Optional<JS::PropertyDescriptor>> PlatformObject::legacy_platform_object_get_own_property(JS::PropertyKey const& property_name, IgnoreNamedProps ignore_named_props) const
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. If O supports indexed properties and P is an array index, then:
|
||||
if (m_legacy_platform_object_flags->supports_indexed_properties && property_name.is_number()) {
|
||||
// 1. Let index be the result of calling ToUint32(P).
|
||||
u32 index = property_name.as_number();
|
||||
|
||||
// 2. If index is a supported property index, then:
|
||||
if (is_supported_property_index(index)) {
|
||||
// 1. Let operation be the operation used to declare the indexed property getter.
|
||||
// 2. Let value be an uninitialized variable.
|
||||
// 3. If operation was defined without an identifier, then set value to the result of performing the steps listed in the interface description to determine the value of an indexed property with index as the index.
|
||||
// 4. Otherwise, operation was defined with an identifier. Set value to the result of performing the method steps of operation with O as this and « index » as the argument values.
|
||||
auto value = TRY(throw_dom_exception_if_needed(vm, [&] { return item_value(index); }));
|
||||
|
||||
// 5. Let desc be a newly created Property Descriptor with no fields.
|
||||
JS::PropertyDescriptor descriptor;
|
||||
|
||||
// 6. Set desc.[[Value]] to the result of converting value to an ECMAScript value.
|
||||
descriptor.value = value;
|
||||
|
||||
// 7. If O implements an interface with an indexed property setter, then set desc.[[Writable]] to true, otherwise set it to false.
|
||||
descriptor.writable = m_legacy_platform_object_flags->has_indexed_property_setter;
|
||||
|
||||
// 8. Set desc.[[Enumerable]] and desc.[[Configurable]] to true.
|
||||
descriptor.enumerable = true;
|
||||
descriptor.configurable = true;
|
||||
|
||||
// 9. Return desc.
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
// 3. Set ignoreNamedProps to true.
|
||||
ignore_named_props = IgnoreNamedProps::Yes;
|
||||
}
|
||||
|
||||
// 2. If O supports named properties and ignoreNamedProps is false, then:
|
||||
if (m_legacy_platform_object_flags->supports_named_properties && ignore_named_props == IgnoreNamedProps::No) {
|
||||
// 1. If the result of running the named property visibility algorithm with property name P and object O is true, then:
|
||||
if (TRY(is_named_property_exposed_on_object(property_name))) {
|
||||
// FIXME: It's unfortunate that this is done twice, once in is_named_property_exposed_on_object and here.
|
||||
auto property_name_string = MUST(FlyString::from_deprecated_fly_string(property_name.to_string()));
|
||||
|
||||
// 1. Let operation be the operation used to declare the named property getter.
|
||||
// 2. Let value be an uninitialized variable.
|
||||
// 3. If operation was defined without an identifier, then set value to the result of performing the steps listed in the interface description to determine the value of a named property with P as the name.
|
||||
// 4. Otherwise, operation was defined with an identifier. Set value to the result of performing the method steps of operation with O as this and « P » as the argument values.
|
||||
auto value = TRY(throw_dom_exception_if_needed(vm, [&] { return named_item_value(property_name_string); }));
|
||||
|
||||
// 5. Let desc be a newly created Property Descriptor with no fields.
|
||||
JS::PropertyDescriptor descriptor;
|
||||
|
||||
// 6. Set desc.[[Value]] to the result of converting value to an ECMAScript value.
|
||||
descriptor.value = value;
|
||||
|
||||
// 7. If O implements an interface with a named property setter, then set desc.[[Writable]] to true, otherwise set it to false.
|
||||
descriptor.writable = m_legacy_platform_object_flags->has_named_property_setter;
|
||||
|
||||
// 8. If O implements an interface with the [LegacyUnenumerableNamedProperties] extended attribute, then set desc.[[Enumerable]] to false, otherwise set it to true.
|
||||
descriptor.enumerable = !m_legacy_platform_object_flags->has_legacy_unenumerable_named_properties_interface_extended_attribute;
|
||||
|
||||
// 9. Set desc.[[Configurable]] to true.
|
||||
descriptor.configurable = true;
|
||||
|
||||
// 10. Return desc.
|
||||
return descriptor;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Return OrdinaryGetOwnProperty(O, P).
|
||||
return TRY(Object::internal_get_own_property(property_name));
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#invoke-indexed-setter
|
||||
WebIDL::ExceptionOr<void> PlatformObject::invoke_indexed_property_setter(JS::PropertyKey const& property_name, JS::Value value)
|
||||
{
|
||||
// 1. Let index be the result of calling ? ToUint32(P).
|
||||
auto index = property_name.as_number();
|
||||
|
||||
// 2. Let creating be true if index is not a supported property index, and false otherwise.
|
||||
bool creating = !is_supported_property_index(index);
|
||||
|
||||
// FIXME: We do not have this information at this point, so converting the value is left as an exercise to the inheritor of PlatformObject.
|
||||
// 3. Let operation be the operation used to declare the indexed property setter.
|
||||
// 4. Let T be the type of the second argument of operation.
|
||||
// 5. Let value be the result of converting V to an IDL value of type T.
|
||||
|
||||
// 6. If operation was defined without an identifier, then:
|
||||
if (!m_legacy_platform_object_flags->indexed_property_setter_has_identifier) {
|
||||
// 1. If creating is true, then perform the steps listed in the interface description to set the value of a new indexed property with index as the index and value as the value.
|
||||
if (creating)
|
||||
return set_value_of_new_indexed_property(index, value);
|
||||
|
||||
// 2. Otherwise, creating is false. Perform the steps listed in the interface description to set the value of an existing indexed property with index as the index and value as the value.
|
||||
return set_value_of_existing_indexed_property(index, value);
|
||||
}
|
||||
|
||||
// 7. Otherwise, operation was defined with an identifier. Perform the method steps of operation with O as this and « index, value » as the argument values.
|
||||
return set_value_of_indexed_property(index, value);
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#invoke-named-setter
|
||||
WebIDL::ExceptionOr<void> PlatformObject::invoke_named_property_setter(String const& property_name, JS::Value value)
|
||||
{
|
||||
// 1. Let creating be true if P is not a supported property name, and false otherwise.
|
||||
auto supported_property_names = this->supported_property_names();
|
||||
bool creating = !supported_property_names.contains_slow(property_name);
|
||||
|
||||
// FIXME: We do not have this information at this point, so converting the value is left as an exercise to the inheritor of PlatformObject.
|
||||
// 2. Let operation be the operation used to declare the indexed property setter.
|
||||
// 3. Let T be the type of the second argument of operation.
|
||||
// 4. Let value be the result of converting V to an IDL value of type T.
|
||||
|
||||
// 5. If operation was defined without an identifier, then:
|
||||
if (!m_legacy_platform_object_flags->named_property_setter_has_identifier) {
|
||||
// 1. If creating is true, then perform the steps listed in the interface description to set the value of a new named property with P as the name and value as the value.
|
||||
if (creating)
|
||||
return set_value_of_new_named_property(property_name, value);
|
||||
|
||||
// 2. Otherwise, creating is false. Perform the steps listed in the interface description to set the value of an existing named property with P as the name and value as the value.
|
||||
return set_value_of_existing_named_property(property_name, value);
|
||||
}
|
||||
|
||||
// 6. Otherwise, operation was defined with an identifier. Perform the method steps of operation with O as this and « P, value » as the argument values.
|
||||
return set_value_of_named_property(property_name, value);
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#legacy-platform-object-getownproperty
|
||||
JS::ThrowCompletionOr<Optional<JS::PropertyDescriptor>> PlatformObject::internal_get_own_property(JS::PropertyKey const& property_name) const
|
||||
{
|
||||
if (m_legacy_platform_object_flags.has_value()) {
|
||||
// 1. Return ? PlatformObjectGetOwnProperty(O, P, false).
|
||||
return TRY(legacy_platform_object_get_own_property(property_name, IgnoreNamedProps::No));
|
||||
} else {
|
||||
return Base::internal_get_own_property(property_name);
|
||||
}
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#legacy-platform-object-set
|
||||
JS::ThrowCompletionOr<bool> PlatformObject::internal_set(JS::PropertyKey const& property_name, JS::Value value, JS::Value receiver, JS::CacheablePropertyMetadata* metadata)
|
||||
{
|
||||
if (!m_legacy_platform_object_flags.has_value())
|
||||
return Base::internal_set(property_name, value, receiver, metadata);
|
||||
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. If O and Receiver are the same object, then:
|
||||
if (receiver.is_object() && &receiver.as_object() == this) {
|
||||
// 1. If O implements an interface with an indexed property setter and P is an array index, then:
|
||||
if (m_legacy_platform_object_flags->has_indexed_property_setter && property_name.is_number()) {
|
||||
// 1. Invoke the indexed property setter on O with P and V.
|
||||
TRY(throw_dom_exception_if_needed(vm, [&] { return invoke_indexed_property_setter(property_name, value); }));
|
||||
|
||||
// 2. Return true.
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2. If O implements an interface with a named property setter and Type(P) is String, then:
|
||||
if (m_legacy_platform_object_flags->has_named_property_setter && property_name.is_string()) {
|
||||
// 1. Invoke the named property setter on O with P and V.
|
||||
TRY(throw_dom_exception_if_needed(vm, [&] { return invoke_named_property_setter(MUST(String::from_byte_string(property_name.as_string())), value); }));
|
||||
|
||||
// 2. Return true.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Let ownDesc be ? PlatformObjectGetOwnProperty(O, P, true).
|
||||
auto own_descriptor = TRY(legacy_platform_object_get_own_property(property_name, IgnoreNamedProps::Yes));
|
||||
|
||||
// 3. Perform ? OrdinarySetWithOwnDescriptor(O, P, V, Receiver, ownDesc).
|
||||
// NOTE: The spec says "perform" instead of "return", meaning nothing will be returned on this path according to the spec, which isn't possible to do.
|
||||
// Let's treat it as though it says "return" instead of "perform".
|
||||
return ordinary_set_with_own_descriptor(property_name, value, receiver, own_descriptor);
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#legacy-platform-object-defineownproperty
|
||||
JS::ThrowCompletionOr<bool> PlatformObject::internal_define_own_property(JS::PropertyKey const& property_name, JS::PropertyDescriptor const& property_descriptor)
|
||||
{
|
||||
if (!m_legacy_platform_object_flags.has_value())
|
||||
return Base::internal_define_own_property(property_name, property_descriptor);
|
||||
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. If O supports indexed properties and P is an array index, then:
|
||||
if (m_legacy_platform_object_flags->supports_indexed_properties && property_name.is_number()) {
|
||||
// 1. If the result of calling IsDataDescriptor(Desc) is false, then return false.
|
||||
if (!property_descriptor.is_data_descriptor())
|
||||
return false;
|
||||
|
||||
// 2. If O does not implement an interface with an indexed property setter, then return false.
|
||||
if (!m_legacy_platform_object_flags->has_indexed_property_setter)
|
||||
return false;
|
||||
|
||||
// 3. Invoke the indexed property setter on O with P and Desc.[[Value]].
|
||||
TRY(throw_dom_exception_if_needed(vm, [&] { return invoke_indexed_property_setter(property_name, property_descriptor.value.value()); }));
|
||||
|
||||
// 4. Return true.
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2. If O supports named properties, O does not implement an interface with the [Global] extended attribute, Type(P) is String, and P is not an unforgeable property name of O, then:
|
||||
// FIXME: Check if P is not an unforgeable property name of O
|
||||
if (m_legacy_platform_object_flags->supports_named_properties && !m_legacy_platform_object_flags->has_global_interface_extended_attribute && property_name.is_string()) {
|
||||
auto const& property_name_as_string = property_name.as_string();
|
||||
|
||||
// 1. Let creating be true if P is not a supported property name, and false otherwise.
|
||||
// NOTE: This is in it's own variable to enforce the type.
|
||||
auto supported_property_names = this->supported_property_names();
|
||||
bool creating = !supported_property_names.contains_slow(MUST(FlyString::from_deprecated_fly_string(property_name_as_string)));
|
||||
|
||||
// 2. If O implements an interface with the [LegacyOverrideBuiltIns] extended attribute or O does not have an own property named P, then:
|
||||
// NOTE: Own property lookup has to be done manually instead of using Object::has_own_property, as that would use the overridden internal_get_own_property.
|
||||
if (m_legacy_platform_object_flags->has_legacy_override_built_ins_interface_extended_attribute || !TRY(Object::internal_get_own_property(property_name)).has_value()) {
|
||||
// 1. If creating is false and O does not implement an interface with a named property setter, then return false.
|
||||
if (!creating && !m_legacy_platform_object_flags->has_named_property_setter)
|
||||
return false;
|
||||
|
||||
// 2. If O implements an interface with a named property setter, then:
|
||||
if (m_legacy_platform_object_flags->has_named_property_setter) {
|
||||
// 1. If the result of calling IsDataDescriptor(Desc) is false, then return false.
|
||||
if (!property_descriptor.is_data_descriptor())
|
||||
return false;
|
||||
|
||||
// 2. Invoke the named property setter on O with P and Desc.[[Value]].
|
||||
TRY(throw_dom_exception_if_needed(vm, [&] { return invoke_named_property_setter(MUST(String::from_byte_string(property_name_as_string)), property_descriptor.value.value()); }));
|
||||
|
||||
// 3. Return true.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. If O does not implement an interface with the [Global] extended attribute, then set Desc.[[Configurable]] to true.
|
||||
// 4. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
|
||||
if (!m_legacy_platform_object_flags->has_global_interface_extended_attribute) {
|
||||
// property_descriptor is a const&, thus we need to create a copy here to set [[Configurable]]
|
||||
JS::PropertyDescriptor descriptor_copy(property_descriptor);
|
||||
descriptor_copy.configurable = true;
|
||||
return Object::internal_define_own_property(property_name, descriptor_copy);
|
||||
}
|
||||
|
||||
return Object::internal_define_own_property(property_name, property_descriptor);
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#legacy-platform-object-delete
|
||||
JS::ThrowCompletionOr<bool> PlatformObject::internal_delete(JS::PropertyKey const& property_name)
|
||||
{
|
||||
if (!m_legacy_platform_object_flags.has_value())
|
||||
return Base::internal_delete(property_name);
|
||||
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. If O supports indexed properties and P is an array index, then:
|
||||
if (m_legacy_platform_object_flags->supports_indexed_properties && property_name.is_number()) {
|
||||
// 1. Let index be the result of calling ! ToUint32(P).
|
||||
u32 index = property_name.as_number();
|
||||
|
||||
// 2. If index is not a supported property index, then return true.
|
||||
if (!is_supported_property_index(index))
|
||||
return true;
|
||||
|
||||
// 3. Return false.
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. If O supports named properties, O does not implement an interface with the [Global] extended attribute and
|
||||
// the result of calling the named property visibility algorithm with property name P and object O is true, then:
|
||||
if (m_legacy_platform_object_flags->supports_named_properties
|
||||
&& !m_legacy_platform_object_flags->has_global_interface_extended_attribute
|
||||
&& TRY(is_named_property_exposed_on_object(property_name))) {
|
||||
// 1. If O does not implement an interface with a named property deleter, then return false.
|
||||
if (!m_legacy_platform_object_flags->has_named_property_deleter)
|
||||
return false;
|
||||
|
||||
// FIXME: It's unfortunate that this is done twice, once in is_named_property_exposed_on_object and here.
|
||||
auto property_name_string = property_name.to_string();
|
||||
|
||||
// 2. Let operation be the operation used to declare the named property deleter.
|
||||
// 3. If operation was defined without an identifier, then:
|
||||
// 1. Perform the steps listed in the interface description to delete an existing named property with P as the name.
|
||||
// 2. If the steps indicated that the deletion failed, then return false.
|
||||
// 4. Otherwise, operation was defined with an identifier:
|
||||
// 1. Perform method steps of operation with O as this and « P » as the argument values.
|
||||
// 2. If operation was declared with a return type of boolean and the steps returned false, then return false.
|
||||
auto did_deletion_fail = TRY(throw_dom_exception_if_needed(vm, [&] { return delete_value(MUST(String::from_byte_string(property_name_string))); }));
|
||||
if (!m_legacy_platform_object_flags->named_property_deleter_has_identifier)
|
||||
VERIFY(did_deletion_fail != DidDeletionFail::NotRelevant);
|
||||
|
||||
if (did_deletion_fail == DidDeletionFail::Yes)
|
||||
return false;
|
||||
|
||||
// 5. Return true.
|
||||
return true;
|
||||
}
|
||||
|
||||
// 3. If O has an own property with name P, then:
|
||||
// NOTE: This has to be done manually instead of using Object::has_own_property, as that would use the overridden internal_get_own_property.
|
||||
auto own_property_named_p_descriptor = TRY(Object::internal_get_own_property(property_name));
|
||||
|
||||
if (own_property_named_p_descriptor.has_value()) {
|
||||
// 1. If the property is not configurable, then return false.
|
||||
if (!own_property_named_p_descriptor->configurable.value())
|
||||
return false;
|
||||
|
||||
// 2. Otherwise, remove the property from O.
|
||||
storage_delete(property_name);
|
||||
}
|
||||
|
||||
// 4. Return true.
|
||||
return true;
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#legacy-platform-object-preventextensions
|
||||
JS::ThrowCompletionOr<bool> PlatformObject::internal_prevent_extensions()
|
||||
{
|
||||
if (!m_legacy_platform_object_flags.has_value())
|
||||
return Base::internal_prevent_extensions();
|
||||
|
||||
// 1. Return false.
|
||||
// Spec Note: Note: this keeps legacy platform objects extensible by making [[PreventExtensions]] fail for them.
|
||||
return false;
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#legacy-platform-object-ownpropertykeys
|
||||
JS::ThrowCompletionOr<JS::MarkedVector<JS::Value>> PlatformObject::internal_own_property_keys() const
|
||||
{
|
||||
if (!m_legacy_platform_object_flags.has_value())
|
||||
return Base::internal_own_property_keys();
|
||||
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. Let keys be a new empty list of ECMAScript String and Symbol values.
|
||||
JS::MarkedVector<JS::Value> keys { heap() };
|
||||
|
||||
// 2. If O supports indexed properties, then for each index of O’s supported property indices, in ascending numerical order, append ! ToString(index) to keys.
|
||||
if (m_legacy_platform_object_flags->supports_indexed_properties) {
|
||||
for (u64 index = 0; index <= NumericLimits<u32>::max(); ++index) {
|
||||
if (is_supported_property_index(index))
|
||||
keys.append(JS::PrimitiveString::create(vm, MUST(String::number(index))));
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. If O supports named properties, then for each P of O’s supported property names that is visible according to the named property visibility algorithm, append P to keys.
|
||||
if (m_legacy_platform_object_flags->supports_named_properties) {
|
||||
for (auto& named_property : supported_property_names()) {
|
||||
if (TRY(is_named_property_exposed_on_object(named_property.to_deprecated_fly_string())))
|
||||
keys.append(JS::PrimitiveString::create(vm, named_property));
|
||||
}
|
||||
}
|
||||
|
||||
// 4. For each P of O’s own property keys that is a String, in ascending chronological order of property creation, append P to keys.
|
||||
for (auto& it : shape().property_table()) {
|
||||
if (it.key.is_string())
|
||||
keys.append(it.key.to_value(vm));
|
||||
}
|
||||
|
||||
// 5. For each P of O’s own property keys that is a Symbol, in ascending chronological order of property creation, append P to keys.
|
||||
for (auto& it : shape().property_table()) {
|
||||
if (it.key.is_symbol())
|
||||
keys.append(it.key.to_value(vm));
|
||||
}
|
||||
|
||||
// FIXME: 6. Assert: keys has no duplicate items.
|
||||
|
||||
// 7. Return keys.
|
||||
return { move(keys) };
|
||||
}
|
||||
|
||||
WebIDL::ExceptionOr<void> PlatformObject::set_value_of_new_named_property(String const&, JS::Value)
|
||||
{
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
WebIDL::ExceptionOr<void> PlatformObject::set_value_of_existing_named_property(String const&, JS::Value)
|
||||
{
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
WebIDL::ExceptionOr<void> PlatformObject::set_value_of_named_property(String const&, JS::Value)
|
||||
{
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
WebIDL::ExceptionOr<void> PlatformObject::set_value_of_new_indexed_property(u32, JS::Value)
|
||||
{
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
WebIDL::ExceptionOr<void> PlatformObject::set_value_of_existing_indexed_property(u32, JS::Value)
|
||||
{
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
WebIDL::ExceptionOr<void> PlatformObject::set_value_of_indexed_property(u32, JS::Value)
|
||||
{
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
WebIDL::ExceptionOr<PlatformObject::DidDeletionFail> PlatformObject::delete_value(String const&)
|
||||
{
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
WebIDL::ExceptionOr<JS::Value> PlatformObject::item_value(size_t) const
|
||||
{
|
||||
return JS::js_undefined();
|
||||
}
|
||||
|
||||
WebIDL::ExceptionOr<JS::Value> PlatformObject::named_item_value(FlyString const&) const
|
||||
{
|
||||
return JS::js_undefined();
|
||||
}
|
||||
|
||||
Vector<FlyString> PlatformObject::supported_property_names() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
bool PlatformObject::is_supported_property_index(u32) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -39,9 +39,78 @@ public:
|
|||
// This is implemented by overrides that get generated by the WEB_PLATFORM_OBJECT macro.
|
||||
[[nodiscard]] virtual bool implements_interface(String const&) const { return false; }
|
||||
|
||||
// ^JS::Object
|
||||
virtual JS::ThrowCompletionOr<Optional<JS::PropertyDescriptor>> internal_get_own_property(JS::PropertyKey const&) const override;
|
||||
virtual JS::ThrowCompletionOr<bool> internal_set(JS::PropertyKey const&, JS::Value, JS::Value, JS::CacheablePropertyMetadata* = nullptr) override;
|
||||
virtual JS::ThrowCompletionOr<bool> internal_define_own_property(JS::PropertyKey const&, JS::PropertyDescriptor const&) override;
|
||||
virtual JS::ThrowCompletionOr<bool> internal_delete(JS::PropertyKey const&) override;
|
||||
virtual JS::ThrowCompletionOr<bool> internal_prevent_extensions() override;
|
||||
virtual JS::ThrowCompletionOr<JS::MarkedVector<JS::Value>> internal_own_property_keys() const override;
|
||||
|
||||
JS::ThrowCompletionOr<bool> is_named_property_exposed_on_object(JS::PropertyKey const&) const;
|
||||
|
||||
protected:
|
||||
explicit PlatformObject(JS::Realm&, MayInterfereWithIndexedPropertyAccess = MayInterfereWithIndexedPropertyAccess::No);
|
||||
explicit PlatformObject(JS::Object& prototype, MayInterfereWithIndexedPropertyAccess = MayInterfereWithIndexedPropertyAccess::No);
|
||||
|
||||
struct LegacyPlatformObjectFlags {
|
||||
u16 supports_indexed_properties : 1 = false;
|
||||
u16 supports_named_properties : 1 = false;
|
||||
u16 has_indexed_property_setter : 1 = false;
|
||||
u16 has_named_property_setter : 1 = false;
|
||||
u16 has_named_property_deleter : 1 = false;
|
||||
u16 has_legacy_unenumerable_named_properties_interface_extended_attribute : 1 = false;
|
||||
u16 has_legacy_override_built_ins_interface_extended_attribute : 1 = false;
|
||||
u16 has_global_interface_extended_attribute : 1 = false;
|
||||
u16 indexed_property_setter_has_identifier : 1 = false;
|
||||
u16 named_property_setter_has_identifier : 1 = false;
|
||||
u16 named_property_deleter_has_identifier : 1 = false;
|
||||
};
|
||||
Optional<LegacyPlatformObjectFlags> m_legacy_platform_object_flags = {};
|
||||
|
||||
enum class IgnoreNamedProps {
|
||||
No,
|
||||
Yes,
|
||||
};
|
||||
JS::ThrowCompletionOr<Optional<JS::PropertyDescriptor>> legacy_platform_object_get_own_property(JS::PropertyKey const&, IgnoreNamedProps ignore_named_props) const;
|
||||
|
||||
virtual WebIDL::ExceptionOr<JS::Value> item_value(size_t index) const;
|
||||
virtual WebIDL::ExceptionOr<JS::Value> named_item_value(FlyString const& name) const;
|
||||
virtual Vector<FlyString> supported_property_names() const;
|
||||
virtual bool is_supported_property_index(u32) const;
|
||||
|
||||
// NOTE: These will crash if you make has_named_property_setter return true but do not override these methods.
|
||||
// NOTE: This is only used if named_property_setter_has_identifier returns false, otherwise set_value_of_named_property is used instead.
|
||||
virtual WebIDL::ExceptionOr<void> set_value_of_new_named_property(String const&, JS::Value);
|
||||
virtual WebIDL::ExceptionOr<void> set_value_of_existing_named_property(String const&, JS::Value);
|
||||
|
||||
// NOTE: These will crash if you make has_named_property_setter return true but do not override these methods.
|
||||
// NOTE: This is only used if you make named_property_setter_has_identifier return true, otherwise set_value_of_{new,existing}_named_property is used instead.
|
||||
virtual WebIDL::ExceptionOr<void> set_value_of_named_property(String const&, JS::Value);
|
||||
|
||||
// NOTE: These will crash if you make has_indexed_property_setter return true but do not override these methods.
|
||||
// NOTE: This is only used if indexed_property_setter_has_identifier returns false, otherwise set_value_of_indexed_property is used instead.
|
||||
virtual WebIDL::ExceptionOr<void> set_value_of_new_indexed_property(u32, JS::Value);
|
||||
virtual WebIDL::ExceptionOr<void> set_value_of_existing_indexed_property(u32, JS::Value);
|
||||
|
||||
// NOTE: These will crash if you make has_named_property_setter return true but do not override these methods.
|
||||
// NOTE: This is only used if indexed_property_setter_has_identifier returns true, otherwise set_value_of_{new,existing}_indexed_property is used instead.
|
||||
virtual WebIDL::ExceptionOr<void> set_value_of_indexed_property(u32, JS::Value);
|
||||
|
||||
enum class DidDeletionFail {
|
||||
// If the named property deleter has an identifier, but does not return a boolean.
|
||||
// This is done because we don't know the return type of the deleter outside of the IDL generator.
|
||||
NotRelevant,
|
||||
No,
|
||||
Yes,
|
||||
};
|
||||
|
||||
// NOTE: This will crash if you make has_named_property_deleter return true but do not override this method.
|
||||
virtual WebIDL::ExceptionOr<DidDeletionFail> delete_value(String const&);
|
||||
|
||||
private:
|
||||
WebIDL::ExceptionOr<void> invoke_indexed_property_setter(JS::PropertyKey const&, JS::Value);
|
||||
WebIDL::ExceptionOr<void> invoke_named_property_setter(String const&, JS::Value);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ set(SOURCES
|
|||
Bindings/HostDefined.cpp
|
||||
Bindings/ImageConstructor.cpp
|
||||
Bindings/Intrinsics.cpp
|
||||
Bindings/LegacyPlatformObject.cpp
|
||||
Bindings/LocationConstructor.cpp
|
||||
Bindings/MainThreadVM.cpp
|
||||
Bindings/OptionConstructor.cpp
|
||||
|
|
|
@ -29,8 +29,9 @@ JS::NonnullGCPtr<CSSRuleList> CSSRuleList::create(JS::Realm& realm, JS::MarkedVe
|
|||
}
|
||||
|
||||
CSSRuleList::CSSRuleList(JS::Realm& realm)
|
||||
: Bindings::LegacyPlatformObject(realm)
|
||||
: Bindings::PlatformObject(realm)
|
||||
{
|
||||
m_legacy_platform_object_flags = LegacyPlatformObjectFlags { .supports_indexed_properties = 1 };
|
||||
}
|
||||
|
||||
JS::NonnullGCPtr<CSSRuleList> CSSRuleList::create_empty(JS::Realm& realm)
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include <AK/Function.h>
|
||||
#include <AK/Iterator.h>
|
||||
#include <AK/RefPtr.h>
|
||||
#include <LibWeb/Bindings/LegacyPlatformObject.h>
|
||||
#include <LibWeb/Bindings/PlatformObject.h>
|
||||
#include <LibWeb/CSS/CSSRule.h>
|
||||
#include <LibWeb/Forward.h>
|
||||
#include <LibWeb/WebIDL/ExceptionOr.h>
|
||||
|
@ -19,8 +19,8 @@
|
|||
namespace Web::CSS {
|
||||
|
||||
// https://www.w3.org/TR/cssom/#the-cssrulelist-interface
|
||||
class CSSRuleList : public Bindings::LegacyPlatformObject {
|
||||
WEB_PLATFORM_OBJECT(CSSRuleList, Bindings::LegacyPlatformObject);
|
||||
class CSSRuleList : public Bindings::PlatformObject {
|
||||
WEB_PLATFORM_OBJECT(CSSRuleList, Bindings::PlatformObject);
|
||||
JS_DECLARE_ALLOCATOR(CSSRuleList);
|
||||
|
||||
public:
|
||||
|
@ -70,19 +70,6 @@ private:
|
|||
virtual void initialize(JS::Realm&) override;
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
|
||||
// ^Bindings::LegacyPlatformObject
|
||||
virtual bool supports_indexed_properties() const override { return true; }
|
||||
virtual bool supports_named_properties() const override { return false; }
|
||||
virtual bool has_indexed_property_setter() const override { return false; }
|
||||
virtual bool has_named_property_setter() const override { return false; }
|
||||
virtual bool has_named_property_deleter() const override { return false; }
|
||||
virtual bool has_legacy_override_built_ins_interface_extended_attribute() const override { return false; }
|
||||
virtual bool has_legacy_unenumerable_named_properties_interface_extended_attribute() const override { return false; }
|
||||
virtual bool has_global_interface_extended_attribute() const override { return false; }
|
||||
virtual bool indexed_property_setter_has_identifier() const override { return false; }
|
||||
virtual bool named_property_setter_has_identifier() const override { return false; }
|
||||
virtual bool named_property_deleter_has_identifier() const override { return false; }
|
||||
|
||||
Vector<JS::NonnullGCPtr<CSSRule>> m_rules;
|
||||
};
|
||||
|
||||
|
|
|
@ -21,9 +21,10 @@ JS::NonnullGCPtr<MediaList> MediaList::create(JS::Realm& realm, Vector<NonnullRe
|
|||
}
|
||||
|
||||
MediaList::MediaList(JS::Realm& realm, Vector<NonnullRefPtr<MediaQuery>>&& media)
|
||||
: Bindings::LegacyPlatformObject(realm)
|
||||
: Bindings::PlatformObject(realm)
|
||||
, m_media(move(media))
|
||||
{
|
||||
m_legacy_platform_object_flags = LegacyPlatformObjectFlags { .supports_indexed_properties = true };
|
||||
}
|
||||
|
||||
void MediaList::initialize(JS::Realm& realm)
|
||||
|
|
|
@ -10,14 +10,14 @@
|
|||
|
||||
#include <AK/Optional.h>
|
||||
#include <LibJS/Runtime/Object.h>
|
||||
#include <LibWeb/Bindings/LegacyPlatformObject.h>
|
||||
#include <LibWeb/Bindings/PlatformObject.h>
|
||||
#include <LibWeb/CSS/MediaQuery.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
||||
// https://www.w3.org/TR/cssom-1/#the-medialist-interface
|
||||
class MediaList final : public Bindings::LegacyPlatformObject {
|
||||
WEB_PLATFORM_OBJECT(MediaList, Bindings::LegacyPlatformObject);
|
||||
class MediaList final : public Bindings::PlatformObject {
|
||||
WEB_PLATFORM_OBJECT(MediaList, Bindings::PlatformObject);
|
||||
JS_DECLARE_ALLOCATOR(MediaList);
|
||||
|
||||
public:
|
||||
|
@ -42,19 +42,6 @@ private:
|
|||
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
|
||||
// ^Bindings::LegacyPlatformObject
|
||||
virtual bool supports_indexed_properties() const override { return true; }
|
||||
virtual bool supports_named_properties() const override { return false; }
|
||||
virtual bool has_indexed_property_setter() const override { return false; }
|
||||
virtual bool has_named_property_setter() const override { return false; }
|
||||
virtual bool has_named_property_deleter() const override { return false; }
|
||||
virtual bool has_legacy_override_built_ins_interface_extended_attribute() const override { return false; }
|
||||
virtual bool has_legacy_unenumerable_named_properties_interface_extended_attribute() const override { return false; }
|
||||
virtual bool has_global_interface_extended_attribute() const override { return false; }
|
||||
virtual bool indexed_property_setter_has_identifier() const override { return false; }
|
||||
virtual bool named_property_setter_has_identifier() const override { return false; }
|
||||
virtual bool named_property_deleter_has_identifier() const override { return false; }
|
||||
|
||||
Vector<NonnullRefPtr<MediaQuery>> m_media;
|
||||
};
|
||||
|
||||
|
|
|
@ -71,9 +71,10 @@ JS::NonnullGCPtr<StyleSheetList> StyleSheetList::create(DOM::Document& document)
|
|||
}
|
||||
|
||||
StyleSheetList::StyleSheetList(DOM::Document& document)
|
||||
: Bindings::LegacyPlatformObject(document.realm())
|
||||
: Bindings::PlatformObject(document.realm())
|
||||
, m_document(document)
|
||||
{
|
||||
m_legacy_platform_object_flags = LegacyPlatformObjectFlags { .supports_indexed_properties = true };
|
||||
}
|
||||
|
||||
void StyleSheetList::initialize(JS::Realm& realm)
|
||||
|
|
|
@ -7,13 +7,13 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/Bindings/LegacyPlatformObject.h>
|
||||
#include <LibWeb/Bindings/PlatformObject.h>
|
||||
#include <LibWeb/CSS/CSSStyleSheet.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
||||
class StyleSheetList final : public Bindings::LegacyPlatformObject {
|
||||
WEB_PLATFORM_OBJECT(StyleSheetList, Bindings::LegacyPlatformObject);
|
||||
class StyleSheetList final : public Bindings::PlatformObject {
|
||||
WEB_PLATFORM_OBJECT(StyleSheetList, Bindings::PlatformObject);
|
||||
JS_DECLARE_ALLOCATOR(StyleSheetList);
|
||||
|
||||
public:
|
||||
|
@ -46,19 +46,6 @@ private:
|
|||
virtual void initialize(JS::Realm&) override;
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
|
||||
// ^Bindings::LegacyPlatformObject
|
||||
virtual bool supports_indexed_properties() const override { return true; }
|
||||
virtual bool supports_named_properties() const override { return false; }
|
||||
virtual bool has_indexed_property_setter() const override { return false; }
|
||||
virtual bool has_named_property_setter() const override { return false; }
|
||||
virtual bool has_named_property_deleter() const override { return false; }
|
||||
virtual bool has_legacy_override_built_ins_interface_extended_attribute() const override { return false; }
|
||||
virtual bool has_legacy_unenumerable_named_properties_interface_extended_attribute() const override { return false; }
|
||||
virtual bool has_global_interface_extended_attribute() const override { return false; }
|
||||
virtual bool indexed_property_setter_has_identifier() const override { return false; }
|
||||
virtual bool named_property_setter_has_identifier() const override { return false; }
|
||||
virtual bool named_property_deleter_has_identifier() const override { return false; }
|
||||
|
||||
void sort_sheets();
|
||||
|
||||
JS::NonnullGCPtr<DOM::Document> m_document;
|
||||
|
|
|
@ -62,10 +62,12 @@ JS::NonnullGCPtr<DOMTokenList> DOMTokenList::create(Element& associated_element,
|
|||
|
||||
// https://dom.spec.whatwg.org/#ref-for-domtokenlist%E2%91%A0%E2%91%A2
|
||||
DOMTokenList::DOMTokenList(Element& associated_element, FlyString associated_attribute)
|
||||
: Bindings::LegacyPlatformObject(associated_element.realm())
|
||||
: Bindings::PlatformObject(associated_element.realm())
|
||||
, m_associated_element(associated_element)
|
||||
, m_associated_attribute(move(associated_attribute))
|
||||
{
|
||||
m_legacy_platform_object_flags = LegacyPlatformObjectFlags { .supports_indexed_properties = 1 };
|
||||
|
||||
auto value = associated_element.deprecated_get_attribute(m_associated_attribute);
|
||||
associated_attribute_changed(value);
|
||||
}
|
||||
|
|
|
@ -13,15 +13,15 @@
|
|||
#include <AK/String.h>
|
||||
#include <AK/StringView.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <LibWeb/Bindings/LegacyPlatformObject.h>
|
||||
#include <LibWeb/Bindings/PlatformObject.h>
|
||||
#include <LibWeb/Forward.h>
|
||||
#include <LibWeb/WebIDL/ExceptionOr.h>
|
||||
|
||||
namespace Web::DOM {
|
||||
|
||||
// https://dom.spec.whatwg.org/#domtokenlist
|
||||
class DOMTokenList final : public Bindings::LegacyPlatformObject {
|
||||
WEB_PLATFORM_OBJECT(DOMTokenList, Bindings::LegacyPlatformObject);
|
||||
class DOMTokenList final : public Bindings::PlatformObject {
|
||||
WEB_PLATFORM_OBJECT(DOMTokenList, Bindings::PlatformObject);
|
||||
JS_DECLARE_ALLOCATOR(DOMTokenList);
|
||||
|
||||
public:
|
||||
|
@ -50,19 +50,6 @@ private:
|
|||
virtual void initialize(JS::Realm&) override;
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
|
||||
// ^Bindings::LegacyPlatformObject
|
||||
virtual bool supports_indexed_properties() const override { return true; }
|
||||
virtual bool supports_named_properties() const override { return false; }
|
||||
virtual bool has_indexed_property_setter() const override { return false; }
|
||||
virtual bool has_named_property_setter() const override { return false; }
|
||||
virtual bool has_named_property_deleter() const override { return false; }
|
||||
virtual bool has_legacy_override_built_ins_interface_extended_attribute() const override { return false; }
|
||||
virtual bool has_legacy_unenumerable_named_properties_interface_extended_attribute() const override { return false; }
|
||||
virtual bool has_global_interface_extended_attribute() const override { return false; }
|
||||
virtual bool indexed_property_setter_has_identifier() const override { return false; }
|
||||
virtual bool named_property_setter_has_identifier() const override { return false; }
|
||||
virtual bool named_property_deleter_has_identifier() const override { return false; }
|
||||
|
||||
WebIDL::ExceptionOr<void> validate_token(StringView token) const;
|
||||
void run_update_steps();
|
||||
|
||||
|
|
|
@ -21,11 +21,16 @@ JS::NonnullGCPtr<HTMLCollection> HTMLCollection::create(ParentNode& root, Scope
|
|||
}
|
||||
|
||||
HTMLCollection::HTMLCollection(ParentNode& root, Scope scope, Function<bool(Element const&)> filter)
|
||||
: LegacyPlatformObject(root.realm())
|
||||
: PlatformObject(root.realm())
|
||||
, m_root(root)
|
||||
, m_filter(move(filter))
|
||||
, m_scope(scope)
|
||||
{
|
||||
m_legacy_platform_object_flags = LegacyPlatformObjectFlags {
|
||||
.supports_indexed_properties = true,
|
||||
.supports_named_properties = true,
|
||||
.has_legacy_unenumerable_named_properties_interface_extended_attribute = true,
|
||||
};
|
||||
}
|
||||
|
||||
HTMLCollection::~HTMLCollection() = default;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
#include <AK/Function.h>
|
||||
#include <LibJS/Heap/GCPtr.h>
|
||||
#include <LibWeb/Bindings/LegacyPlatformObject.h>
|
||||
#include <LibWeb/Bindings/PlatformObject.h>
|
||||
#include <LibWeb/Forward.h>
|
||||
|
||||
namespace Web::DOM {
|
||||
|
@ -25,8 +25,8 @@ namespace Web::DOM {
|
|||
// We should teach it how to cache results. The main challenge is invalidating
|
||||
// these caches, since this needs to happen on various kinds of DOM mutation.
|
||||
|
||||
class HTMLCollection : public Bindings::LegacyPlatformObject {
|
||||
WEB_PLATFORM_OBJECT(HTMLCollection, Bindings::LegacyPlatformObject);
|
||||
class HTMLCollection : public Bindings::PlatformObject {
|
||||
WEB_PLATFORM_OBJECT(HTMLCollection, Bindings::PlatformObject);
|
||||
JS_DECLARE_ALLOCATOR(HTMLCollection);
|
||||
|
||||
public:
|
||||
|
@ -60,19 +60,6 @@ protected:
|
|||
private:
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
|
||||
// ^Bindings::LegacyPlatformObject
|
||||
virtual bool supports_indexed_properties() const override { return true; }
|
||||
virtual bool supports_named_properties() const override { return true; }
|
||||
virtual bool has_indexed_property_setter() const override { return false; }
|
||||
virtual bool has_named_property_setter() const override { return false; }
|
||||
virtual bool has_named_property_deleter() const override { return false; }
|
||||
virtual bool has_legacy_override_built_ins_interface_extended_attribute() const override { return false; }
|
||||
virtual bool has_legacy_unenumerable_named_properties_interface_extended_attribute() const override { return true; }
|
||||
virtual bool has_global_interface_extended_attribute() const override { return false; }
|
||||
virtual bool indexed_property_setter_has_identifier() const override { return false; }
|
||||
virtual bool named_property_setter_has_identifier() const override { return false; }
|
||||
virtual bool named_property_deleter_has_identifier() const override { return false; }
|
||||
|
||||
JS::NonnullGCPtr<ParentNode> m_root;
|
||||
Function<bool(Element const&)> m_filter;
|
||||
|
||||
|
|
|
@ -23,9 +23,14 @@ JS::NonnullGCPtr<NamedNodeMap> NamedNodeMap::create(Element& element)
|
|||
}
|
||||
|
||||
NamedNodeMap::NamedNodeMap(Element& element)
|
||||
: Bindings::LegacyPlatformObject(element.realm())
|
||||
: Bindings::PlatformObject(element.realm())
|
||||
, m_element(element)
|
||||
{
|
||||
m_legacy_platform_object_flags = LegacyPlatformObjectFlags {
|
||||
.supports_indexed_properties = true,
|
||||
.supports_named_properties = true,
|
||||
.has_legacy_unenumerable_named_properties_interface_extended_attribute = true,
|
||||
};
|
||||
}
|
||||
|
||||
void NamedNodeMap::initialize(JS::Realm& realm)
|
||||
|
|
|
@ -9,15 +9,15 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/Bindings/LegacyPlatformObject.h>
|
||||
#include <LibWeb/Bindings/PlatformObject.h>
|
||||
#include <LibWeb/Forward.h>
|
||||
#include <LibWeb/WebIDL/ExceptionOr.h>
|
||||
|
||||
namespace Web::DOM {
|
||||
|
||||
// https://dom.spec.whatwg.org/#interface-namednodemap
|
||||
class NamedNodeMap : public Bindings::LegacyPlatformObject {
|
||||
WEB_PLATFORM_OBJECT(NamedNodeMap, Bindings::LegacyPlatformObject);
|
||||
class NamedNodeMap : public Bindings::PlatformObject {
|
||||
WEB_PLATFORM_OBJECT(NamedNodeMap, Bindings::PlatformObject);
|
||||
JS_DECLARE_ALLOCATOR(NamedNodeMap);
|
||||
|
||||
public:
|
||||
|
@ -60,19 +60,6 @@ private:
|
|||
virtual void initialize(JS::Realm&) override;
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
|
||||
// ^Bindings::LegacyPlatformObject
|
||||
virtual bool supports_indexed_properties() const override { return true; }
|
||||
virtual bool supports_named_properties() const override { return true; }
|
||||
virtual bool has_indexed_property_setter() const override { return false; }
|
||||
virtual bool has_named_property_setter() const override { return false; }
|
||||
virtual bool has_named_property_deleter() const override { return false; }
|
||||
virtual bool has_legacy_override_built_ins_interface_extended_attribute() const override { return false; }
|
||||
virtual bool has_legacy_unenumerable_named_properties_interface_extended_attribute() const override { return true; }
|
||||
virtual bool has_global_interface_extended_attribute() const override { return false; }
|
||||
virtual bool indexed_property_setter_has_identifier() const override { return false; }
|
||||
virtual bool named_property_setter_has_identifier() const override { return false; }
|
||||
virtual bool named_property_deleter_has_identifier() const override { return false; }
|
||||
|
||||
Element& associated_element() { return *m_element; }
|
||||
Element const& associated_element() const { return *m_element; }
|
||||
|
||||
|
|
|
@ -11,8 +11,9 @@
|
|||
namespace Web::DOM {
|
||||
|
||||
NodeList::NodeList(JS::Realm& realm)
|
||||
: LegacyPlatformObject(realm)
|
||||
: PlatformObject(realm)
|
||||
{
|
||||
m_legacy_platform_object_flags = LegacyPlatformObjectFlags { .supports_indexed_properties = true };
|
||||
}
|
||||
|
||||
NodeList::~NodeList() = default;
|
||||
|
|
|
@ -7,13 +7,13 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/Bindings/LegacyPlatformObject.h>
|
||||
#include <LibWeb/Bindings/PlatformObject.h>
|
||||
|
||||
namespace Web::DOM {
|
||||
|
||||
// https://dom.spec.whatwg.org/#nodelist
|
||||
class NodeList : public Bindings::LegacyPlatformObject {
|
||||
WEB_PLATFORM_OBJECT(NodeList, Bindings::LegacyPlatformObject);
|
||||
class NodeList : public Bindings::PlatformObject {
|
||||
WEB_PLATFORM_OBJECT(NodeList, Bindings::PlatformObject);
|
||||
|
||||
public:
|
||||
virtual ~NodeList() override;
|
||||
|
@ -28,19 +28,6 @@ protected:
|
|||
explicit NodeList(JS::Realm&);
|
||||
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
|
||||
// ^Bindings::LegacyPlatformObject
|
||||
virtual bool supports_indexed_properties() const final override { return true; }
|
||||
virtual bool supports_named_properties() const final override { return false; }
|
||||
virtual bool has_indexed_property_setter() const final override { return false; }
|
||||
virtual bool has_named_property_setter() const final override { return false; }
|
||||
virtual bool has_named_property_deleter() const final override { return false; }
|
||||
virtual bool has_legacy_override_built_ins_interface_extended_attribute() const final override { return false; }
|
||||
virtual bool has_legacy_unenumerable_named_properties_interface_extended_attribute() const final override { return false; }
|
||||
virtual bool has_global_interface_extended_attribute() const final override { return false; }
|
||||
virtual bool indexed_property_setter_has_identifier() const final override { return false; }
|
||||
virtual bool named_property_setter_has_identifier() const final override { return false; }
|
||||
virtual bool named_property_deleter_has_identifier() const final override { return false; }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include <LibJS/Runtime/Realm.h>
|
||||
#include <LibWeb/Bindings/Intrinsics.h>
|
||||
#include <LibWeb/Bindings/LegacyPlatformObject.h>
|
||||
#include <LibWeb/Bindings/PlatformObject.h>
|
||||
#include <LibWeb/FileAPI/FileList.h>
|
||||
|
||||
namespace Web::FileAPI {
|
||||
|
@ -19,9 +19,10 @@ JS::NonnullGCPtr<FileList> FileList::create(JS::Realm& realm, Vector<JS::Nonnull
|
|||
}
|
||||
|
||||
FileList::FileList(JS::Realm& realm, Vector<JS::NonnullGCPtr<File>>&& files)
|
||||
: Bindings::LegacyPlatformObject(realm)
|
||||
: Bindings::PlatformObject(realm)
|
||||
, m_files(move(files))
|
||||
{
|
||||
m_legacy_platform_object_flags = LegacyPlatformObjectFlags { .supports_indexed_properties = 1 };
|
||||
}
|
||||
|
||||
FileList::~FileList() = default;
|
||||
|
|
|
@ -9,13 +9,13 @@
|
|||
|
||||
#include <AK/Vector.h>
|
||||
#include <LibJS/Heap/GCPtr.h>
|
||||
#include <LibWeb/Bindings/LegacyPlatformObject.h>
|
||||
#include <LibWeb/Bindings/PlatformObject.h>
|
||||
#include <LibWeb/FileAPI/File.h>
|
||||
|
||||
namespace Web::FileAPI {
|
||||
|
||||
class FileList : public Bindings::LegacyPlatformObject {
|
||||
WEB_PLATFORM_OBJECT(FileList, Bindings::LegacyPlatformObject);
|
||||
class FileList : public Bindings::PlatformObject {
|
||||
WEB_PLATFORM_OBJECT(FileList, Bindings::PlatformObject);
|
||||
JS_DECLARE_ALLOCATOR(FileList);
|
||||
|
||||
public:
|
||||
|
@ -46,19 +46,6 @@ private:
|
|||
virtual void initialize(JS::Realm&) override;
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
|
||||
// ^Bindings::LegacyPlatformObject
|
||||
virtual bool supports_indexed_properties() const override { return true; }
|
||||
virtual bool supports_named_properties() const override { return false; }
|
||||
virtual bool has_indexed_property_setter() const override { return false; }
|
||||
virtual bool has_named_property_setter() const override { return false; }
|
||||
virtual bool has_named_property_deleter() const override { return false; }
|
||||
virtual bool has_legacy_override_built_ins_interface_extended_attribute() const override { return false; }
|
||||
virtual bool has_legacy_unenumerable_named_properties_interface_extended_attribute() const override { return false; }
|
||||
virtual bool has_global_interface_extended_attribute() const override { return false; }
|
||||
virtual bool indexed_property_setter_has_identifier() const override { return false; }
|
||||
virtual bool named_property_setter_has_identifier() const override { return false; }
|
||||
virtual bool named_property_deleter_has_identifier() const override { return false; }
|
||||
|
||||
Vector<JS::NonnullGCPtr<File>> m_files;
|
||||
};
|
||||
|
||||
|
|
|
@ -43,7 +43,6 @@ enum class StateAndProperties;
|
|||
|
||||
namespace Web::Bindings {
|
||||
class Intrinsics;
|
||||
class LegacyPlatformObject;
|
||||
class OptionConstructor;
|
||||
|
||||
enum class AudioContextLatencyCategory;
|
||||
|
|
|
@ -23,9 +23,10 @@ JS::NonnullGCPtr<DOMRectList> DOMRectList::create(JS::Realm& realm, Vector<JS::H
|
|||
}
|
||||
|
||||
DOMRectList::DOMRectList(JS::Realm& realm, Vector<JS::NonnullGCPtr<DOMRect>> rects)
|
||||
: Bindings::LegacyPlatformObject(realm)
|
||||
: Bindings::PlatformObject(realm)
|
||||
, m_rects(move(rects))
|
||||
{
|
||||
m_legacy_platform_object_flags = LegacyPlatformObjectFlags { .supports_indexed_properties = 1 };
|
||||
}
|
||||
|
||||
DOMRectList::~DOMRectList() = default;
|
||||
|
|
|
@ -8,14 +8,14 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/Vector.h>
|
||||
#include <LibWeb/Bindings/LegacyPlatformObject.h>
|
||||
#include <LibWeb/Bindings/PlatformObject.h>
|
||||
#include <LibWeb/Geometry/DOMRect.h>
|
||||
|
||||
namespace Web::Geometry {
|
||||
|
||||
// https://drafts.fxtf.org/geometry-1/#DOMRectList
|
||||
class DOMRectList final : public Bindings::LegacyPlatformObject {
|
||||
WEB_PLATFORM_OBJECT(DOMRectList, Bindings::LegacyPlatformObject);
|
||||
class DOMRectList final : public Bindings::PlatformObject {
|
||||
WEB_PLATFORM_OBJECT(DOMRectList, Bindings::PlatformObject);
|
||||
JS_DECLARE_ALLOCATOR(DOMRectList);
|
||||
|
||||
public:
|
||||
|
@ -35,19 +35,6 @@ private:
|
|||
virtual void initialize(JS::Realm&) override;
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
|
||||
// ^Bindings::LegacyPlatformObject
|
||||
virtual bool supports_indexed_properties() const override { return true; }
|
||||
virtual bool supports_named_properties() const override { return false; }
|
||||
virtual bool has_indexed_property_setter() const override { return false; }
|
||||
virtual bool has_named_property_setter() const override { return false; }
|
||||
virtual bool has_named_property_deleter() const override { return false; }
|
||||
virtual bool has_legacy_override_built_ins_interface_extended_attribute() const override { return false; }
|
||||
virtual bool has_legacy_unenumerable_named_properties_interface_extended_attribute() const override { return false; }
|
||||
virtual bool has_global_interface_extended_attribute() const override { return false; }
|
||||
virtual bool indexed_property_setter_has_identifier() const override { return false; }
|
||||
virtual bool named_property_setter_has_identifier() const override { return false; }
|
||||
virtual bool named_property_deleter_has_identifier() const override { return false; }
|
||||
|
||||
Vector<JS::NonnullGCPtr<DOMRect>> m_rects;
|
||||
};
|
||||
|
||||
|
|
|
@ -21,9 +21,15 @@ JS::NonnullGCPtr<DOMStringMap> DOMStringMap::create(DOM::Element& element)
|
|||
}
|
||||
|
||||
DOMStringMap::DOMStringMap(DOM::Element& element)
|
||||
: LegacyPlatformObject(element.realm())
|
||||
: PlatformObject(element.realm())
|
||||
, m_associated_element(element)
|
||||
{
|
||||
m_legacy_platform_object_flags = LegacyPlatformObjectFlags {
|
||||
.supports_named_properties = true,
|
||||
.has_named_property_setter = true,
|
||||
.has_named_property_deleter = true,
|
||||
.has_legacy_override_built_ins_interface_extended_attribute = true,
|
||||
};
|
||||
}
|
||||
|
||||
DOMStringMap::~DOMStringMap() = default;
|
||||
|
@ -121,7 +127,7 @@ String DOMStringMap::determine_value_of_named_property(FlyString const& name) co
|
|||
// https://html.spec.whatwg.org/multipage/dom.html#dom-domstringmap-setitem
|
||||
WebIDL::ExceptionOr<void> DOMStringMap::set_value_of_new_named_property(String const& name, JS::Value unconverted_value)
|
||||
{
|
||||
// NOTE: Since LegacyPlatformObject does not know the type of value, we must convert it ourselves.
|
||||
// NOTE: Since PlatformObject does not know the type of value, we must convert it ourselves.
|
||||
// The type of `value` is `DOMString`.
|
||||
auto value = TRY(unconverted_value.to_string(vm()));
|
||||
|
||||
|
@ -170,7 +176,7 @@ WebIDL::ExceptionOr<void> DOMStringMap::set_value_of_existing_named_property(Str
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/dom.html#dom-domstringmap-removeitem
|
||||
WebIDL::ExceptionOr<Bindings::LegacyPlatformObject::DidDeletionFail> DOMStringMap::delete_value(String const& name)
|
||||
WebIDL::ExceptionOr<Bindings::PlatformObject::DidDeletionFail> DOMStringMap::delete_value(String const& name)
|
||||
{
|
||||
StringBuilder builder;
|
||||
|
||||
|
|
|
@ -7,14 +7,14 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/Bindings/LegacyPlatformObject.h>
|
||||
#include <LibWeb/Bindings/PlatformObject.h>
|
||||
#include <LibWeb/Forward.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/dom.html#domstringmap
|
||||
class DOMStringMap final : public Bindings::LegacyPlatformObject {
|
||||
WEB_PLATFORM_OBJECT(DOMStringMap, Bindings::LegacyPlatformObject);
|
||||
class DOMStringMap final : public Bindings::PlatformObject {
|
||||
WEB_PLATFORM_OBJECT(DOMStringMap, Bindings::PlatformObject);
|
||||
JS_DECLARE_ALLOCATOR(DOMStringMap);
|
||||
|
||||
public:
|
||||
|
@ -35,22 +35,10 @@ private:
|
|||
virtual void initialize(JS::Realm&) override;
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
|
||||
// ^LegacyPlatformObject
|
||||
// ^PlatformObject
|
||||
virtual WebIDL::ExceptionOr<JS::Value> named_item_value(FlyString const&) const override;
|
||||
virtual Vector<FlyString> supported_property_names() const override;
|
||||
|
||||
virtual bool supports_indexed_properties() const override { return false; }
|
||||
virtual bool supports_named_properties() const override { return true; }
|
||||
virtual bool has_indexed_property_setter() const override { return false; }
|
||||
virtual bool has_named_property_setter() const override { return true; }
|
||||
virtual bool has_named_property_deleter() const override { return true; }
|
||||
virtual bool has_legacy_override_built_ins_interface_extended_attribute() const override { return true; }
|
||||
virtual bool has_legacy_unenumerable_named_properties_interface_extended_attribute() const override { return false; }
|
||||
virtual bool has_global_interface_extended_attribute() const override { return false; }
|
||||
virtual bool indexed_property_setter_has_identifier() const override { return false; }
|
||||
virtual bool named_property_setter_has_identifier() const override { return false; }
|
||||
virtual bool named_property_deleter_has_identifier() const override { return false; }
|
||||
|
||||
struct NameValuePair {
|
||||
FlyString name;
|
||||
String value;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/Bindings/LegacyPlatformObject.h>
|
||||
#include <LibWeb/Bindings/PlatformObject.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
||||
|
|
|
@ -15,8 +15,13 @@ namespace Web::HTML {
|
|||
JS_DEFINE_ALLOCATOR(MimeTypeArray);
|
||||
|
||||
MimeTypeArray::MimeTypeArray(JS::Realm& realm)
|
||||
: Bindings::LegacyPlatformObject(realm)
|
||||
: Bindings::PlatformObject(realm)
|
||||
{
|
||||
m_legacy_platform_object_flags = LegacyPlatformObjectFlags {
|
||||
.supports_indexed_properties = true,
|
||||
.supports_named_properties = true,
|
||||
.has_legacy_unenumerable_named_properties_interface_extended_attribute = true,
|
||||
};
|
||||
}
|
||||
|
||||
MimeTypeArray::~MimeTypeArray() = default;
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/Bindings/LegacyPlatformObject.h>
|
||||
#include <LibWeb/Bindings/PlatformObject.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/system-state.html#mimetypearray
|
||||
class MimeTypeArray : public Bindings::LegacyPlatformObject {
|
||||
WEB_PLATFORM_OBJECT(MimeTypeArray, Bindings::LegacyPlatformObject);
|
||||
class MimeTypeArray : public Bindings::PlatformObject {
|
||||
WEB_PLATFORM_OBJECT(MimeTypeArray, Bindings::PlatformObject);
|
||||
JS_DECLARE_ALLOCATOR(MimeTypeArray);
|
||||
|
||||
public:
|
||||
|
@ -27,23 +27,11 @@ private:
|
|||
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
|
||||
// ^Bindings::LegacyPlatformObject
|
||||
// ^Bindings::PlatformObject
|
||||
virtual Vector<FlyString> supported_property_names() const override;
|
||||
virtual WebIDL::ExceptionOr<JS::Value> item_value(size_t index) const override;
|
||||
virtual WebIDL::ExceptionOr<JS::Value> named_item_value(FlyString const& name) const override;
|
||||
virtual bool is_supported_property_index(u32) const override;
|
||||
|
||||
virtual bool supports_indexed_properties() const override { return true; }
|
||||
virtual bool supports_named_properties() const override { return true; }
|
||||
virtual bool has_indexed_property_setter() const override { return false; }
|
||||
virtual bool has_named_property_setter() const override { return false; }
|
||||
virtual bool has_named_property_deleter() const override { return false; }
|
||||
virtual bool has_legacy_override_built_ins_interface_extended_attribute() const override { return false; }
|
||||
virtual bool has_legacy_unenumerable_named_properties_interface_extended_attribute() const override { return true; }
|
||||
virtual bool has_global_interface_extended_attribute() const override { return false; }
|
||||
virtual bool indexed_property_setter_has_identifier() const override { return false; }
|
||||
virtual bool named_property_setter_has_identifier() const override { return false; }
|
||||
virtual bool named_property_deleter_has_identifier() const override { return false; }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -15,9 +15,14 @@ namespace Web::HTML {
|
|||
JS_DEFINE_ALLOCATOR(Plugin);
|
||||
|
||||
Plugin::Plugin(JS::Realm& realm, String name)
|
||||
: Bindings::LegacyPlatformObject(realm)
|
||||
: Bindings::PlatformObject(realm)
|
||||
, m_name(move(name))
|
||||
{
|
||||
m_legacy_platform_object_flags = LegacyPlatformObjectFlags {
|
||||
.supports_indexed_properties = true,
|
||||
.supports_named_properties = true,
|
||||
.has_legacy_unenumerable_named_properties_interface_extended_attribute = true,
|
||||
};
|
||||
}
|
||||
|
||||
Plugin::~Plugin() = default;
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/Bindings/LegacyPlatformObject.h>
|
||||
#include <LibWeb/Bindings/PlatformObject.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/system-state.html#dom-plugin
|
||||
class Plugin : public Bindings::LegacyPlatformObject {
|
||||
WEB_PLATFORM_OBJECT(Plugin, Bindings::LegacyPlatformObject);
|
||||
class Plugin : public Bindings::PlatformObject {
|
||||
WEB_PLATFORM_OBJECT(Plugin, Bindings::PlatformObject);
|
||||
JS_DECLARE_ALLOCATOR(Plugin);
|
||||
|
||||
public:
|
||||
|
@ -33,23 +33,11 @@ private:
|
|||
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
|
||||
// ^Bindings::LegacyPlatformObject
|
||||
// ^Bindings::PlatformObject
|
||||
virtual Vector<FlyString> supported_property_names() const override;
|
||||
virtual WebIDL::ExceptionOr<JS::Value> item_value(size_t index) const override;
|
||||
virtual WebIDL::ExceptionOr<JS::Value> named_item_value(FlyString const& name) const override;
|
||||
virtual bool is_supported_property_index(u32) const override;
|
||||
|
||||
virtual bool supports_indexed_properties() const override { return true; }
|
||||
virtual bool supports_named_properties() const override { return true; }
|
||||
virtual bool has_indexed_property_setter() const override { return false; }
|
||||
virtual bool has_named_property_setter() const override { return false; }
|
||||
virtual bool has_named_property_deleter() const override { return false; }
|
||||
virtual bool has_legacy_override_built_ins_interface_extended_attribute() const override { return false; }
|
||||
virtual bool has_legacy_unenumerable_named_properties_interface_extended_attribute() const override { return true; }
|
||||
virtual bool has_global_interface_extended_attribute() const override { return false; }
|
||||
virtual bool indexed_property_setter_has_identifier() const override { return false; }
|
||||
virtual bool named_property_setter_has_identifier() const override { return false; }
|
||||
virtual bool named_property_deleter_has_identifier() const override { return false; }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -15,8 +15,13 @@ namespace Web::HTML {
|
|||
JS_DEFINE_ALLOCATOR(PluginArray);
|
||||
|
||||
PluginArray::PluginArray(JS::Realm& realm)
|
||||
: Bindings::LegacyPlatformObject(realm)
|
||||
: Bindings::PlatformObject(realm)
|
||||
{
|
||||
m_legacy_platform_object_flags = LegacyPlatformObjectFlags {
|
||||
.supports_indexed_properties = true,
|
||||
.supports_named_properties = true,
|
||||
.has_legacy_unenumerable_named_properties_interface_extended_attribute = true,
|
||||
};
|
||||
}
|
||||
|
||||
PluginArray::~PluginArray() = default;
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/Bindings/LegacyPlatformObject.h>
|
||||
#include <LibWeb/Bindings/PlatformObject.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/system-state.html#pluginarray
|
||||
class PluginArray : public Bindings::LegacyPlatformObject {
|
||||
WEB_PLATFORM_OBJECT(PluginArray, Bindings::LegacyPlatformObject);
|
||||
class PluginArray : public Bindings::PlatformObject {
|
||||
WEB_PLATFORM_OBJECT(PluginArray, Bindings::PlatformObject);
|
||||
JS_DECLARE_ALLOCATOR(PluginArray);
|
||||
|
||||
public:
|
||||
|
@ -28,23 +28,11 @@ private:
|
|||
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
|
||||
// ^Bindings::LegacyPlatformObject
|
||||
// ^Bindings::PlatformObject
|
||||
virtual Vector<FlyString> supported_property_names() const override;
|
||||
virtual WebIDL::ExceptionOr<JS::Value> item_value(size_t index) const override;
|
||||
virtual WebIDL::ExceptionOr<JS::Value> named_item_value(FlyString const& name) const override;
|
||||
virtual bool is_supported_property_index(u32) const override;
|
||||
|
||||
virtual bool supports_indexed_properties() const override { return true; }
|
||||
virtual bool supports_named_properties() const override { return true; }
|
||||
virtual bool has_indexed_property_setter() const override { return false; }
|
||||
virtual bool has_named_property_setter() const override { return false; }
|
||||
virtual bool has_named_property_deleter() const override { return false; }
|
||||
virtual bool has_legacy_override_built_ins_interface_extended_attribute() const override { return false; }
|
||||
virtual bool has_legacy_unenumerable_named_properties_interface_extended_attribute() const override { return true; }
|
||||
virtual bool has_global_interface_extended_attribute() const override { return false; }
|
||||
virtual bool indexed_property_setter_has_identifier() const override { return false; }
|
||||
virtual bool named_property_setter_has_identifier() const override { return false; }
|
||||
virtual bool named_property_deleter_has_identifier() const override { return false; }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -19,8 +19,16 @@ JS::NonnullGCPtr<Storage> Storage::create(JS::Realm& realm)
|
|||
}
|
||||
|
||||
Storage::Storage(JS::Realm& realm)
|
||||
: Bindings::LegacyPlatformObject(realm)
|
||||
: Bindings::PlatformObject(realm)
|
||||
{
|
||||
m_legacy_platform_object_flags = LegacyPlatformObjectFlags {
|
||||
.supports_named_properties = true,
|
||||
.has_named_property_setter = true,
|
||||
.has_named_property_deleter = true,
|
||||
.has_legacy_override_built_ins_interface_extended_attribute = true,
|
||||
.named_property_setter_has_identifier = true,
|
||||
.named_property_deleter_has_identifier = true,
|
||||
};
|
||||
}
|
||||
|
||||
Storage::~Storage() = default;
|
||||
|
@ -167,7 +175,7 @@ WebIDL::ExceptionOr<JS::Value> Storage::named_item_value(FlyString const& name)
|
|||
return JS::PrimitiveString::create(vm(), value.release_value());
|
||||
}
|
||||
|
||||
WebIDL::ExceptionOr<Bindings::LegacyPlatformObject::DidDeletionFail> Storage::delete_value(String const& name)
|
||||
WebIDL::ExceptionOr<Bindings::PlatformObject::DidDeletionFail> Storage::delete_value(String const& name)
|
||||
{
|
||||
remove_item(name);
|
||||
return DidDeletionFail::NotRelevant;
|
||||
|
@ -175,7 +183,7 @@ WebIDL::ExceptionOr<Bindings::LegacyPlatformObject::DidDeletionFail> Storage::de
|
|||
|
||||
WebIDL::ExceptionOr<void> Storage::set_value_of_named_property(String const& key, JS::Value unconverted_value)
|
||||
{
|
||||
// NOTE: Since LegacyPlatformObject does not know the type of value, we must convert it ourselves.
|
||||
// NOTE: Since PlatformObject does not know the type of value, we must convert it ourselves.
|
||||
// The type of `value` is `DOMString`.
|
||||
auto value = TRY(unconverted_value.to_string(vm()));
|
||||
return set_item(key, value);
|
||||
|
|
|
@ -8,13 +8,13 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/HashMap.h>
|
||||
#include <LibWeb/Bindings/LegacyPlatformObject.h>
|
||||
#include <LibWeb/Bindings/PlatformObject.h>
|
||||
#include <LibWeb/WebIDL/ExceptionOr.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
||||
class Storage : public Bindings::LegacyPlatformObject {
|
||||
WEB_PLATFORM_OBJECT(Storage, Bindings::LegacyPlatformObject);
|
||||
class Storage : public Bindings::PlatformObject {
|
||||
WEB_PLATFORM_OBJECT(Storage, Bindings::PlatformObject);
|
||||
JS_DECLARE_ALLOCATOR(Storage);
|
||||
|
||||
public:
|
||||
|
@ -37,24 +37,12 @@ private:
|
|||
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
|
||||
// ^LegacyPlatformObject
|
||||
// ^PlatformObject
|
||||
virtual WebIDL::ExceptionOr<JS::Value> named_item_value(FlyString const&) const override;
|
||||
virtual WebIDL::ExceptionOr<DidDeletionFail> delete_value(String const&) override;
|
||||
virtual Vector<FlyString> supported_property_names() const override;
|
||||
virtual WebIDL::ExceptionOr<void> set_value_of_named_property(String const& key, JS::Value value) override;
|
||||
|
||||
virtual bool supports_indexed_properties() const override { return false; }
|
||||
virtual bool supports_named_properties() const override { return true; }
|
||||
virtual bool has_indexed_property_setter() const override { return false; }
|
||||
virtual bool has_named_property_setter() const override { return true; }
|
||||
virtual bool has_named_property_deleter() const override { return true; }
|
||||
virtual bool has_legacy_override_built_ins_interface_extended_attribute() const override { return true; }
|
||||
virtual bool has_legacy_unenumerable_named_properties_interface_extended_attribute() const override { return false; }
|
||||
virtual bool has_global_interface_extended_attribute() const override { return false; }
|
||||
virtual bool indexed_property_setter_has_identifier() const override { return false; }
|
||||
virtual bool named_property_setter_has_identifier() const override { return true; }
|
||||
virtual bool named_property_deleter_has_identifier() const override { return true; }
|
||||
|
||||
void reorder();
|
||||
void broadcast(StringView key, StringView old_value, StringView new_value);
|
||||
|
||||
|
|
|
@ -106,6 +106,11 @@ JS::NonnullGCPtr<Window> Window::create(JS::Realm& realm)
|
|||
Window::Window(JS::Realm& realm)
|
||||
: DOM::EventTarget(realm)
|
||||
{
|
||||
m_legacy_platform_object_flags = LegacyPlatformObjectFlags {
|
||||
.supports_named_properties = true,
|
||||
.has_legacy_unenumerable_named_properties_interface_extended_attribute = true,
|
||||
.has_global_interface_extended_attribute = true,
|
||||
};
|
||||
}
|
||||
|
||||
void Window::visit_edges(JS::Cell::Visitor& visitor)
|
||||
|
@ -1560,8 +1565,11 @@ OrderedHashMap<FlyString, JS::NonnullGCPtr<Navigable>> Window::document_tree_chi
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/#named-access-on-the-window-object
|
||||
Vector<FlyString> Window::supported_property_names()
|
||||
Vector<FlyString> Window::supported_property_names() const
|
||||
{
|
||||
// FIXME: Make the const-correctness of the methods this method calls less cowboy.
|
||||
auto& mutable_this = const_cast<Window&>(*this);
|
||||
|
||||
// The Window object supports named properties.
|
||||
// The supported property names of a Window object window at any moment consist of the following,
|
||||
// in tree order according to the element that contributed them, ignoring later duplicates:
|
||||
|
@ -1569,7 +1577,7 @@ Vector<FlyString> Window::supported_property_names()
|
|||
HashTable<FlyString> property_names;
|
||||
|
||||
// - window's document-tree child navigable target name property set;
|
||||
auto child_navigable_property_set = document_tree_child_navigable_target_name_property_set();
|
||||
auto child_navigable_property_set = mutable_this.document_tree_child_navigable_target_name_property_set();
|
||||
for (auto& entry : child_navigable_property_set)
|
||||
property_names.set(entry.key, AK::HashSetExistingEntryBehavior::Keep);
|
||||
|
||||
|
@ -1591,19 +1599,22 @@ Vector<FlyString> Window::supported_property_names()
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/#named-access-on-the-window-object
|
||||
WebIDL::ExceptionOr<JS::Value> Window::named_item_value(FlyString const& name)
|
||||
WebIDL::ExceptionOr<JS::Value> Window::named_item_value(FlyString const& name) const
|
||||
{
|
||||
// FIXME: Make the const-correctness of the methods this method calls less cowboy.
|
||||
auto& mutable_this = const_cast<Window&>(*this);
|
||||
|
||||
// To determine the value of a named property name in a Window object window, the user agent must return the value obtained using the following steps:
|
||||
|
||||
// 1. Let objects be the list of named objects of window with the name name.
|
||||
// NOTE: There will be at least one such object, since the algorithm would otherwise not have been invoked by Web IDL.
|
||||
auto objects = named_objects(name);
|
||||
auto objects = mutable_this.named_objects(name);
|
||||
|
||||
// 2. If objects contains a navigable, then:
|
||||
if (!objects.navigables.is_empty()) {
|
||||
// 1. Let container be the first navigable container in window's associated Document's descendants whose content navigable is in objects.
|
||||
JS::GCPtr<NavigableContainer> container = nullptr;
|
||||
associated_document().for_each_in_subtree_of_type<HTML::NavigableContainer>([&](HTML::NavigableContainer& navigable_container) {
|
||||
mutable_this.associated_document().for_each_in_subtree_of_type<HTML::NavigableContainer>([&](HTML::NavigableContainer& navigable_container) {
|
||||
if (!navigable_container.content_navigable())
|
||||
return IterationDecision::Continue;
|
||||
if (objects.navigables.contains_slow(JS::NonnullGCPtr { *navigable_container.content_navigable() })) {
|
||||
|
@ -1623,7 +1634,7 @@ WebIDL::ExceptionOr<JS::Value> Window::named_item_value(FlyString const& name)
|
|||
|
||||
// 4. Otherwise return an HTMLCollection rooted at window's associated Document,
|
||||
// whose filter matches only named objects of window with the name name. (By definition, these will all be elements.)
|
||||
return DOM::HTMLCollection::create(associated_document(), DOM::HTMLCollection::Scope::Descendants, [name](auto& element) -> bool {
|
||||
return DOM::HTMLCollection::create(mutable_this.associated_document(), DOM::HTMLCollection::Scope::Descendants, [name](auto& element) -> bool {
|
||||
if ((is<HTMLEmbedElement>(element) || is<HTMLFormElement>(element) || is<HTMLImageElement>(element) || is<HTMLObjectElement>(element))
|
||||
&& (element.attribute(AttributeNames::name) == name))
|
||||
return true;
|
||||
|
|
|
@ -203,8 +203,8 @@ public:
|
|||
|
||||
[[nodiscard]] OrderedHashMap<FlyString, JS::NonnullGCPtr<Navigable>> document_tree_child_navigable_target_name_property_set();
|
||||
|
||||
[[nodiscard]] Vector<FlyString> supported_property_names();
|
||||
[[nodiscard]] WebIDL::ExceptionOr<JS::Value> named_item_value(FlyString const&);
|
||||
[[nodiscard]] Vector<FlyString> supported_property_names() const override;
|
||||
[[nodiscard]] WebIDL::ExceptionOr<JS::Value> named_item_value(FlyString const&) const override;
|
||||
|
||||
private:
|
||||
explicit Window(JS::Realm&);
|
||||
|
|
|
@ -15,8 +15,7 @@
|
|||
#include <LibJS/Runtime/PropertyKey.h>
|
||||
#include <LibJS/Runtime/TypedArray.h>
|
||||
#include <LibJS/Runtime/ValueInlines.h>
|
||||
#include <LibWeb/Bindings/LegacyPlatformObject.h>
|
||||
#include <LibWeb/Bindings/WindowPrototype.h>
|
||||
#include <LibWeb/Bindings/PlatformObject.h>
|
||||
#include <LibWeb/HTML/Window.h>
|
||||
#include <LibWeb/WebIDL/AbstractOperations.h>
|
||||
#include <LibWeb/WebIDL/Promise.h>
|
||||
|
@ -320,56 +319,6 @@ JS::Completion construct(WebIDL::CallbackType& callback, JS::MarkedVector<JS::Va
|
|||
return completion;
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-named-property-visibility
|
||||
JS::ThrowCompletionOr<bool> is_named_property_exposed_on_object(Variant<Bindings::LegacyPlatformObject const*, HTML::Window*> const& variant, JS::PropertyKey const& property_key)
|
||||
{
|
||||
auto const& object = *variant.visit([](auto& o) { return static_cast<JS::Object const*>(o); });
|
||||
|
||||
// The spec doesn't say anything about the type of the property name here.
|
||||
// Numbers can be converted to a string, which is fine and what other engines do.
|
||||
// However, since a symbol cannot be converted to a string, it cannot be a supported property name. Return early if it's a symbol.
|
||||
if (property_key.is_symbol())
|
||||
return false;
|
||||
|
||||
// 1. If P is not a supported property name of O, then return false.
|
||||
// NOTE: This is in it's own variable to enforce the type.
|
||||
auto supported_property_names = variant.visit([](auto* o) { return o->supported_property_names(); });
|
||||
auto property_key_string = MUST(String::from_byte_string(property_key.to_string()));
|
||||
if (!supported_property_names.contains_slow(property_key_string))
|
||||
return false;
|
||||
|
||||
// 2. If O has an own property named P, then return false.
|
||||
// NOTE: This has to be done manually instead of using Object::has_own_property, as that would use the overridden internal_get_own_property.
|
||||
auto own_property_named_p = MUST(object.JS::Object::internal_get_own_property(property_key));
|
||||
|
||||
if (own_property_named_p.has_value())
|
||||
return false;
|
||||
|
||||
// 3. If O implements an interface that has the [LegacyOverrideBuiltIns] extended attribute, then return true.
|
||||
if (variant.has<Bindings::LegacyPlatformObject const*>() && variant.get<Bindings::LegacyPlatformObject const*>()->has_legacy_override_built_ins_interface_extended_attribute())
|
||||
return true;
|
||||
|
||||
// 4. Let prototype be O.[[GetPrototypeOf]]().
|
||||
auto* prototype = TRY(object.internal_get_prototype_of());
|
||||
|
||||
// 5. While prototype is not null:
|
||||
while (prototype) {
|
||||
// 1. If prototype is not a named properties object, and prototype has an own property named P, then return false.
|
||||
// FIXME: Are there other named properties objects?
|
||||
if (!is<Bindings::WindowProperties>(prototype)) {
|
||||
bool prototype_has_own_property_named_p = TRY(prototype->has_own_property(property_key));
|
||||
if (prototype_has_own_property_named_p)
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. Set prototype to prototype.[[GetPrototypeOf]]().
|
||||
prototype = TRY(prototype->internal_get_prototype_of());
|
||||
}
|
||||
|
||||
// 6. Return true.
|
||||
return true;
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#abstract-opdef-integerpart
|
||||
double integer_part(double n)
|
||||
{
|
||||
|
|
|
@ -62,8 +62,6 @@ JS::Completion construct(WebIDL::CallbackType& callback, Args&&... args)
|
|||
return construct(callback, move(arguments_list));
|
||||
}
|
||||
|
||||
JS::ThrowCompletionOr<bool> is_named_property_exposed_on_object(Variant<Bindings::LegacyPlatformObject const*, HTML::Window*> const& variant, JS::PropertyKey const& property_key);
|
||||
|
||||
// https://webidl.spec.whatwg.org/#abstract-opdef-integerpart
|
||||
double integer_part(double n);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue