mirror of
https://github.com/RGBCube/serenity
synced 2025-05-30 23:48:11 +00:00
LibWeb: Implement the [PutForwards] IDL extended attribute
For example, consider the attribute: interface Element { [PutForwards=value] readonly attribute DOMTokenList classList; } When `classList` is set, we should instead set the attribute `value` on the `classList` attribute of the Element interface.
This commit is contained in:
parent
3bd1d8bf6c
commit
9c569e8a0f
3 changed files with 18 additions and 39 deletions
|
@ -2178,7 +2178,7 @@ static void generate_prototype_or_global_mixin_declarations(IDL::Interface const
|
||||||
JS_DECLARE_NATIVE_FUNCTION(@attribute.name:snakecase@_getter);
|
JS_DECLARE_NATIVE_FUNCTION(@attribute.name:snakecase@_getter);
|
||||||
)~~~");
|
)~~~");
|
||||||
|
|
||||||
if (!attribute.readonly || attribute.extended_attributes.contains("Replaceable"sv)) {
|
if (!attribute.readonly || attribute.extended_attributes.contains("Replaceable"sv) || attribute.extended_attributes.contains("PutForwards"sv)) {
|
||||||
attribute_generator.append(R"~~~(
|
attribute_generator.append(R"~~~(
|
||||||
JS_DECLARE_NATIVE_FUNCTION(@attribute.name:snakecase@_setter);
|
JS_DECLARE_NATIVE_FUNCTION(@attribute.name:snakecase@_setter);
|
||||||
)~~~");
|
)~~~");
|
||||||
|
@ -2300,7 +2300,7 @@ JS::ThrowCompletionOr<void> @class_name@::initialize(JS::Realm& realm)
|
||||||
attribute_generator.set("attribute.name", attribute.name);
|
attribute_generator.set("attribute.name", attribute.name);
|
||||||
attribute_generator.set("attribute.getter_callback", attribute.getter_callback_name);
|
attribute_generator.set("attribute.getter_callback", attribute.getter_callback_name);
|
||||||
|
|
||||||
if (!attribute.readonly || attribute.extended_attributes.contains("Replaceable"sv))
|
if (!attribute.readonly || attribute.extended_attributes.contains("Replaceable"sv) || attribute.extended_attributes.contains("PutForwards"sv))
|
||||||
attribute_generator.set("attribute.setter_callback", attribute.setter_callback_name);
|
attribute_generator.set("attribute.setter_callback", attribute.setter_callback_name);
|
||||||
else
|
else
|
||||||
attribute_generator.set("attribute.setter_callback", "nullptr");
|
attribute_generator.set("attribute.setter_callback", "nullptr");
|
||||||
|
@ -2540,6 +2540,22 @@ JS_DEFINE_NATIVE_FUNCTION(@class_name@::@attribute.setter_callback@)
|
||||||
TRY(this_value.as_object().internal_define_own_property("@attribute.name@", JS::PropertyDescriptor { .value = vm.argument(0), .writable = true }));
|
TRY(this_value.as_object().internal_define_own_property("@attribute.name@", JS::PropertyDescriptor { .value = vm.argument(0), .writable = true }));
|
||||||
return JS::js_undefined();
|
return JS::js_undefined();
|
||||||
}
|
}
|
||||||
|
)~~~");
|
||||||
|
} else if (auto put_forwards_identifier = attribute.extended_attributes.get("PutForwards"sv); put_forwards_identifier.has_value()) {
|
||||||
|
attribute_generator.set("attribute.name", attribute.name.to_snakecase());
|
||||||
|
attribute_generator.set("put_forwards_identifier"sv, *put_forwards_identifier);
|
||||||
|
|
||||||
|
attribute_generator.append(R"~~~(
|
||||||
|
JS_DEFINE_NATIVE_FUNCTION(@class_name@::@attribute.setter_callback@)
|
||||||
|
{
|
||||||
|
auto* impl = TRY(impl_from(vm));
|
||||||
|
auto value = vm.argument(0);
|
||||||
|
|
||||||
|
auto receiver = TRY(throw_dom_exception_if_needed(vm, [&]() { return impl->@attribute.name@(); }));
|
||||||
|
TRY(receiver->set(JS::PropertyKey { "@put_forwards_identifier@" }, value, JS::Object::ShouldThrowExceptions::Yes));
|
||||||
|
|
||||||
|
return JS::js_undefined();
|
||||||
|
}
|
||||||
)~~~");
|
)~~~");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -756,10 +756,6 @@ WebIDL::ExceptionOr<void> Window::initialize_web_interfaces(Badge<WindowEnvironm
|
||||||
create_method_property("CSS", MUST_OR_THROW_OOM(heap().allocate<Bindings::CSSNamespace>(realm, realm)));
|
create_method_property("CSS", MUST_OR_THROW_OOM(heap().allocate<Bindings::CSSNamespace>(realm, realm)));
|
||||||
create_method_property("WebAssembly", MUST_OR_THROW_OOM(heap().allocate<Bindings::WebAssemblyObject>(realm, realm)));
|
create_method_property("WebAssembly", MUST_OR_THROW_OOM(heap().allocate<Bindings::WebAssemblyObject>(realm, realm)));
|
||||||
|
|
||||||
// FIXME: Implement codegen for readonly properties with [PutForwards]
|
|
||||||
auto& location_accessor = storage_get("location")->value.as_accessor();
|
|
||||||
location_accessor.set_setter(JS::NativeFunction::create(realm, location_setter, 1, "location", &realm, {}, "set"sv));
|
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -770,29 +766,6 @@ JS::ThrowCompletionOr<bool> Window::internal_set_prototype_of(JS::Object* protot
|
||||||
return set_immutable_prototype(prototype);
|
return set_immutable_prototype(prototype);
|
||||||
}
|
}
|
||||||
|
|
||||||
static JS::ThrowCompletionOr<Window*> impl_from(JS::VM& vm)
|
|
||||||
{
|
|
||||||
// Since this is a non built-in function we must treat it as non-strict mode
|
|
||||||
// this means that a nullish this_value should be converted to the
|
|
||||||
// global_object. Generally this does not matter as we try to convert the
|
|
||||||
// this_value to a specific object type in the bindings. But since window is
|
|
||||||
// the global object we make an exception here.
|
|
||||||
// This allows calls like `setTimeout(f, 10)` to work.
|
|
||||||
auto this_value = vm.this_value();
|
|
||||||
if (this_value.is_nullish())
|
|
||||||
this_value = &vm.current_realm()->global_object();
|
|
||||||
|
|
||||||
auto* this_object = MUST(this_value.to_object(vm));
|
|
||||||
|
|
||||||
if (is<WindowProxy>(*this_object))
|
|
||||||
return static_cast<WindowProxy*>(this_object)->window().ptr();
|
|
||||||
|
|
||||||
if (is<Window>(*this_object))
|
|
||||||
return static_cast<Window*>(this_object);
|
|
||||||
|
|
||||||
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "Window");
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/window-object.html#dom-window
|
// https://html.spec.whatwg.org/multipage/window-object.html#dom-window
|
||||||
JS::NonnullGCPtr<WindowProxy> Window::window() const
|
JS::NonnullGCPtr<WindowProxy> Window::window() const
|
||||||
{
|
{
|
||||||
|
@ -1371,12 +1344,4 @@ size_t Window::document_tree_child_browsing_context_count() const
|
||||||
return this_browsing_context->document_tree_child_browsing_context_count();
|
return this_browsing_context->document_tree_child_browsing_context_count();
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_DEFINE_NATIVE_FUNCTION(Window::location_setter)
|
|
||||||
{
|
|
||||||
auto* impl = TRY(impl_from(vm));
|
|
||||||
auto location = TRY(Bindings::throw_dom_exception_if_needed(vm, [&] { return impl->location(); }));
|
|
||||||
TRY(location->set(JS::PropertyKey("href"), vm.argument(0), JS::Object::ShouldThrowExceptions::Yes));
|
|
||||||
return JS::js_undefined();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -233,8 +233,6 @@ private:
|
||||||
|
|
||||||
// [[CrossOriginPropertyDescriptorMap]], https://html.spec.whatwg.org/multipage/browsers.html#crossoriginpropertydescriptormap
|
// [[CrossOriginPropertyDescriptorMap]], https://html.spec.whatwg.org/multipage/browsers.html#crossoriginpropertydescriptormap
|
||||||
CrossOriginPropertyDescriptorMap m_cross_origin_property_descriptor_map;
|
CrossOriginPropertyDescriptorMap m_cross_origin_property_descriptor_map;
|
||||||
|
|
||||||
JS_DECLARE_NATIVE_FUNCTION(location_setter);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void run_animation_frame_callbacks(DOM::Document&, double now);
|
void run_animation_frame_callbacks(DOM::Document&, double now);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue