LibWeb: Unify WebIDL C++ type generation

Represent WebIDL C++ types with a single CppType model that tracks
nullability, optional presence, and contained storage.

GC-like values now use GC::Ref/GC::Ptr directly, while containers choose
"plain", "Root", or "Conservative" container types depending on what
they contain. For example, sequence<Element> becomes a RootVector of
GC::Ref values, while sequence<SomeDictionary> becomes a
ConservativeVector only when the dictionary contains GC-like values.
This moves the generated bindings away from wrapping GC values in
GC::Root by default.

This has broad fallout as the types passed to interfaces for GC
objects changes almost fully across the board.
This commit is contained in:
Shannon Booth 2026-05-20 20:58:46 +02:00 committed by Shannon Booth
parent aa0eb13a89
commit 637fd51595
207 changed files with 1126 additions and 1255 deletions

View file

@ -30,16 +30,6 @@ static size_t get_function_shortest_length(FunctionType& function)
return length;
}
enum class SequenceStorageType {
Vector, // Used to safely store non-JS values
RootVector, // Used to safely store JS::Value and anything that inherits JS::Cell, e.g. JS::Object
};
struct CppType {
ByteString name;
SequenceStorageType sequence_storage_type;
};
class Context;
class ParameterizedType;
class UnionType;

View file

@ -26,7 +26,7 @@ struct Animatable::Transition {
Animatable::Impl::~Impl() = default;
// https://www.w3.org/TR/web-animations-1/#dom-animatable-animate
WebIDL::ExceptionOr<GC::Ref<Animation>> Animatable::animate(Optional<GC::Root<JS::Object>> keyframes, Variant<Empty, double, Bindings::KeyframeAnimationOptions> const& options)
WebIDL::ExceptionOr<GC::Ref<Animation>> Animatable::animate(GC::Ptr<JS::Object> keyframes, Variant<Empty, double, Bindings::KeyframeAnimationOptions> const& options)
{
// 1. Let target be the object on which this method was called.
GC::Ref target { *static_cast<DOM::Element*>(this) };
@ -46,7 +46,7 @@ WebIDL::ExceptionOr<GC::Ref<Animation>> Animatable::animate(Optional<GC::Root<JS
// on which this method was called.
Optional<GC::Ptr<AnimationTimeline>> timeline;
if (options.has<Bindings::KeyframeAnimationOptions>() && options.get<Bindings::KeyframeAnimationOptions>().timeline.has_value())
timeline = options.get<Bindings::KeyframeAnimationOptions>().timeline->ptr();
timeline = options.get<Bindings::KeyframeAnimationOptions>().timeline.value();
if (!timeline.has_value())
timeline = target->document().timeline();

View file

@ -39,7 +39,7 @@ public:
Yes
};
WebIDL::ExceptionOr<GC::Ref<Animation>> animate(Optional<GC::Root<JS::Object>> keyframes, Variant<Empty, double, Bindings::KeyframeAnimationOptions> const& options = {});
WebIDL::ExceptionOr<GC::Ref<Animation>> animate(GC::Ptr<JS::Object> keyframes, Variant<Empty, double, Bindings::KeyframeAnimationOptions> const& options = {});
WebIDL::ExceptionOr<Vector<GC::Ref<Animation>>> get_animations(Optional<Bindings::GetAnimationsOptions> const& options = {});
WebIDL::ExceptionOr<Vector<GC::Ref<Animation>>> get_animations_internal(GetAnimationsSorted sorted, Optional<Bindings::GetAnimationsOptions> const& options = {});

View file

@ -225,7 +225,7 @@ WebIDL::ExceptionOr<Optional<TimeValue>> Animation::validate_a_css_numberish_tim
m_timeline && m_timeline->is_progress_based() &&
// time is not a CSSNumeric value with percent units:
(!time.has<GC::Root<CSS::CSSNumericValue>>() || !time.get<GC::Root<CSS::CSSNumericValue>>()->type().matches_percentage())) {
(!time.has<GC::Ref<CSS::CSSNumericValue>>() || !time.get<GC::Ref<CSS::CSSNumericValue>>()->type().matches_percentage())) {
// throw a TypeError.
// return false;
return WebIDL::SimpleException {
@ -240,14 +240,14 @@ WebIDL::ExceptionOr<Optional<TimeValue>> Animation::validate_a_css_numberish_tim
(!m_timeline || !m_timeline->is_progress_based()) &&
// time is a CSSNumericValue, and
time.has<GC::Root<CSS::CSSNumericValue>>() &&
time.has<GC::Ref<CSS::CSSNumericValue>>() &&
// the units of time are not duration units:
!time.get<GC::Root<CSS::CSSNumericValue>>()->type().matches_time({}) &&
!time.get<GC::Ref<CSS::CSSNumericValue>>()->type().matches_time({}) &&
// AD-HOC: While it's not mentioned in the spec WPT also expects us to support CSSNumericValue number value, see
// https://github.com/w3c/csswg-drafts/issues/13196
!time.get<GC::Root<CSS::CSSNumericValue>>()->type().matches_number({})) {
!time.get<GC::Ref<CSS::CSSNumericValue>>()->type().matches_number({})) {
// throw a TypeError.
// return false.
return WebIDL::SimpleException {
@ -266,7 +266,7 @@ WebIDL::ExceptionOr<Optional<TimeValue>> Animation::validate_a_css_numberish_tim
// FIXME: Figure out which element we should use for this, for now we just use the document element of the current
// window
return TimeValue::from_css_numberish(time.downcast<double, GC::Root<CSS::CSSNumericValue>>(), DOM::AbstractElement { *as<HTML::Window>(realm().global_object()).associated_document().document_element() });
return TimeValue::from_css_numberish(time.downcast<double, GC::Ref<CSS::CSSNumericValue>>(), DOM::AbstractElement { *as<HTML::Window>(realm().global_object()).associated_document().document_element() });
VERIFY_NOT_REACHED();
}

View file

@ -72,7 +72,7 @@ Bindings::OptionalEffectTiming to_optional_effect_timing(Bindings::EffectTiming
[](double const& value) -> Variant<double, String> { return value; },
[](String const& value) -> Variant<double, String> { return value; },
// NB: We check that this isn't the case in the caller
[](GC::Root<CSS::CSSNumericValue> const&) -> Variant<double, String> { VERIFY_NOT_REACHED(); }),
[](GC::Ref<CSS::CSSNumericValue>) -> Variant<double, String> { VERIFY_NOT_REACHED(); }),
.easing = effect_timing.easing,
.end_delay = effect_timing.end_delay,
.fill = effect_timing.fill,

View file

@ -25,18 +25,10 @@ WebIDL::ExceptionOr<GC::Ref<AnimationPlaybackEvent>> AnimationPlaybackEvent::con
return create(realm, type, event_init);
}
AnimationPlaybackEvent::CSSNumberishInternal AnimationPlaybackEvent::to_numberish_internal(NullableCSSNumberish const& numberish_root)
{
return numberish_root.visit(
[](Empty) -> CSSNumberishInternal { return Empty {}; },
[](GC::Root<CSS::CSSNumericValue> const& root) -> CSSNumberishInternal { return GC::Ref { *root }; },
[](auto const& other) -> CSSNumberishInternal { return other; });
}
AnimationPlaybackEvent::AnimationPlaybackEvent(JS::Realm& realm, FlyString const& type, Bindings::AnimationPlaybackEventInit const& event_init)
: DOM::Event(realm, type, event_init)
, m_current_time(to_numberish_internal(event_init.current_time))
, m_timeline_time(to_numberish_internal(event_init.timeline_time))
, m_current_time(event_init.current_time)
, m_timeline_time(event_init.timeline_time)
{
}
@ -53,21 +45,14 @@ void AnimationPlaybackEvent::visit_edges(Visitor& visitor)
visitor.visit(m_timeline_time);
}
NullableCSSNumberish AnimationPlaybackEvent::to_nullable_numberish(CSSNumberishInternal const& numberish)
{
return numberish.visit(
[](GC::Ref<CSS::CSSNumericValue> const& ref) -> NullableCSSNumberish { return GC::Root { *ref }; },
[](auto const& other) -> NullableCSSNumberish { return other; });
}
NullableCSSNumberish AnimationPlaybackEvent::current_time() const
{
return to_nullable_numberish(m_current_time);
return m_current_time;
}
NullableCSSNumberish AnimationPlaybackEvent::timeline_time() const
{
return to_nullable_numberish(m_timeline_time);
return m_timeline_time;
}
}

View file

@ -34,15 +34,11 @@ private:
virtual void initialize(JS::Realm&) override;
virtual void visit_edges(Visitor&) override;
using CSSNumberishInternal = Variant<Empty, double, GC::Ref<CSS::CSSNumericValue>>;
static CSSNumberishInternal to_numberish_internal(NullableCSSNumberish const&);
static NullableCSSNumberish to_nullable_numberish(CSSNumberishInternal const&);
// https://drafts.csswg.org/web-animations-2/#dom-animationplaybackevent-currenttime
CSSNumberishInternal m_current_time;
NullableCSSNumberish m_current_time;
// https://drafts.csswg.org/web-animations-2/#dom-animationplaybackevent-timelinetime
CSSNumberishInternal m_timeline_time;
NullableCSSNumberish m_timeline_time;
};
}

View file

@ -664,8 +664,8 @@ GC::Ref<KeyframeEffect> KeyframeEffect::create(JS::Realm& realm)
// https://www.w3.org/TR/web-animations-1/#dom-keyframeeffect-keyframeeffect
WebIDL::ExceptionOr<GC::Ref<KeyframeEffect>> KeyframeEffect::construct_impl(
JS::Realm& realm,
GC::Root<DOM::Element> const& target,
Optional<GC::Root<JS::Object>> const& keyframes,
GC::Ptr<DOM::Element> target,
GC::Ptr<JS::Object> keyframes,
Variant<double, Bindings::KeyframeEffectOptions> options)
{
// 1. Create a new KeyframeEffect object, effect.
@ -711,7 +711,7 @@ WebIDL::ExceptionOr<GC::Ref<KeyframeEffect>> KeyframeEffect::construct_impl(
// returned as a CSSNumericValue when resolving the duration in getComputedTiming(). Future versions of
// the spec may enable setting the duration as a CSSNumeric value, where the unit is a valid time unit or
// percent.
if (timing_input.duration.has<GC::Root<CSS::CSSNumericValue>>())
if (timing_input.duration.has<GC::Ref<CSS::CSSNumericValue>>())
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Setting duration as a CSSNumericValue is not supported"sv };
// 5. Call the procedure to update the timing properties of an animation effect of effect from timing input.
@ -894,10 +894,10 @@ WebIDL::ExceptionOr<GC::RootVector<JS::Object*>> KeyframeEffect::get_keyframes()
}
// https://www.w3.org/TR/web-animations-1/#dom-keyframeeffect-setkeyframes
WebIDL::ExceptionOr<void> KeyframeEffect::set_keyframes(Optional<GC::Root<JS::Object>> const& keyframe_object)
WebIDL::ExceptionOr<void> KeyframeEffect::set_keyframes(GC::Ptr<JS::Object> keyframe_object)
{
m_keyframe_objects.clear();
m_keyframes = TRY(process_a_keyframes_argument(realm(), keyframe_object.has_value() ? GC::Ptr { keyframe_object->ptr() } : GC::Ptr<Object> {}));
m_keyframes = TRY(process_a_keyframes_argument(realm(), keyframe_object));
// FIXME: After processing the keyframe argument, we need to turn the set of keyframes into a set of computed
// keyframes using the procedure outlined in the second half of
// https://www.w3.org/TR/web-animations-1/#calculating-computed-keyframes. For now, just compute the

View file

@ -76,8 +76,8 @@ public:
static WebIDL::ExceptionOr<GC::Ref<KeyframeEffect>> construct_impl(
JS::Realm&,
GC::Root<DOM::Element> const& target,
Optional<GC::Root<JS::Object>> const& keyframes,
GC::Ptr<DOM::Element> target,
GC::Ptr<JS::Object> keyframes,
Variant<double, Bindings::KeyframeEffectOptions> options = Bindings::KeyframeEffectOptions {});
static WebIDL::ExceptionOr<GC::Ref<KeyframeEffect>> construct_impl(JS::Realm&, GC::Ref<KeyframeEffect> source);
@ -99,7 +99,7 @@ public:
void set_composite(Bindings::CompositeOperation value);
WebIDL::ExceptionOr<GC::RootVector<JS::Object*>> get_keyframes();
WebIDL::ExceptionOr<void> set_keyframes(Optional<GC::Root<JS::Object>> const&);
WebIDL::ExceptionOr<void> set_keyframes(GC::Ptr<JS::Object>);
KeyFrameSet const* key_frame_set() { return m_key_frame_set; }
void set_key_frame_set(RefPtr<KeyFrameSet const> key_frame_set) { m_key_frame_set = key_frame_set; }

View file

@ -36,7 +36,7 @@ GC::Ref<ScrollTimeline> ScrollTimeline::construct_impl(JS::Realm& realm, Binding
// If the source member of options is present,
// The source member of options.
if (options.source.has_value())
return options.source.value().ptr();
return options.source.value();
// Otherwise,
// The scrollingElement of the Document associated with the Window that is the current global object.

View file

@ -16,7 +16,7 @@ TimeValue TimeValue::from_css_numberish(CSS::CSSNumberish const& time, DOM::Abst
if (time.has<double>())
return { Type::Milliseconds, time.get<double>() };
auto const& numeric_value = time.get<GC::Root<CSS::CSSNumericValue>>();
auto const& numeric_value = time.get<GC::Ref<CSS::CSSNumericValue>>();
// NB: Skip creating a calculation node for simple unit values
if (auto const* unit_value = as_if<CSS::CSSUnitValue>(*numeric_value)) {
@ -70,7 +70,7 @@ CSS::CSSNumberish TimeValue::as_css_numberish(JS::Realm& realm) const
return value;
case Type::Percentage:
GC::Ref<CSS::CSSNumericValue> numeric_value = CSS::CSSUnitValue::create(realm, value, "percent"_fly_string);
return GC::Root { numeric_value };
return numeric_value;
}
VERIFY_NOT_REACHED();

View file

@ -21,6 +21,7 @@
#include <LibWeb/Bindings/ExceptionOrUtils.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/Bindings/MainThreadVM.h>
#include <LibWeb/Bindings/PromiseRejectionEvent.h>
#include <LibWeb/Bindings/WindowExposedInterfaces.h>
#include <LibWeb/ContentSecurityPolicy/BlockingAlgorithms.h>
#include <LibWeb/ContentSecurityPolicy/Directives/KeywordSources.h>

View file

@ -124,8 +124,8 @@ GC::Ref<CSSKeywordValue> rectify_a_keywordish_value(JS::Realm& realm, CSSKeyword
// To rectify a keywordish value val, perform the following steps:
return keywordish.visit(
// 1. If val is a CSSKeywordValue, return val.
[](GC::Root<CSSKeywordValue> const& value) -> GC::Ref<CSSKeywordValue> {
return *value;
[](GC::Ref<CSSKeywordValue> const& value) -> GC::Ref<CSSKeywordValue> {
return value;
},
// 2. If val is a DOMString, return a new CSSKeywordValue with its value internal slot set to val.

View file

@ -12,7 +12,7 @@
namespace Web::CSS {
// https://drafts.css-houdini.org/css-typed-om-1/#typedefdef-csskeywordish
using CSSKeywordish = Variant<String, GC::Root<CSSKeywordValue>>;
using CSSKeywordish = Variant<String, GC::Ref<CSSKeywordValue>>;
// https://drafts.css-houdini.org/css-typed-om-1/#csskeywordvalue
class CSSKeywordValue final : public CSSStyleValue {

View file

@ -44,7 +44,7 @@ WebIDL::ExceptionOr<GC::Ref<CSSMathMin>> CSSMathMin::add_all_types_into_math_min
}
// https://drafts.css-houdini.org/css-typed-om-1/#dom-cssmathmin-cssmathmin
WebIDL::ExceptionOr<GC::Ref<CSSMathMin>> CSSMathMin::construct_impl(JS::Realm& realm, Vector<CSSNumberish> values)
WebIDL::ExceptionOr<GC::Ref<CSSMathMin>> CSSMathMin::construct_impl(JS::Realm& realm, ReadonlySpan<CSSNumberish> values)
{
// The CSSMathMin(...args) and CSSMathMax(...args) constructors are defined identically to the above, except that
// in the last step they return a new CSSMathMin or CSSMathMax object, respectively.

View file

@ -17,7 +17,7 @@ class CSSMathMin final : public CSSMathValue {
public:
[[nodiscard]] static GC::Ref<CSSMathMin> create(JS::Realm&, NumericType, GC::Ref<CSSNumericArray>);
static WebIDL::ExceptionOr<GC::Ref<CSSMathMin>> construct_impl(JS::Realm&, Vector<CSSNumberish>);
static WebIDL::ExceptionOr<GC::Ref<CSSMathMin>> construct_impl(JS::Realm&, ReadonlySpan<CSSNumberish>);
static WebIDL::ExceptionOr<GC::Ref<CSSMathMin>> add_all_types_into_math_min(JS::Realm&, GC::RootVector<GC::Ref<CSSNumericValue>> const&);
virtual ~CSSMathMin() override;

View file

@ -43,7 +43,7 @@ WebIDL::ExceptionOr<GC::Ref<CSSMathProduct>> CSSMathProduct::multiply_all_types_
}
// https://drafts.css-houdini.org/css-typed-om-1/#dom-cssmathproduct-cssmathproduct
WebIDL::ExceptionOr<GC::Ref<CSSMathProduct>> CSSMathProduct::construct_impl(JS::Realm& realm, Vector<CSSNumberish> values)
WebIDL::ExceptionOr<GC::Ref<CSSMathProduct>> CSSMathProduct::construct_impl(JS::Realm& realm, ReadonlySpan<CSSNumberish> values)
{
// The CSSMathProduct(...args) constructor is defined identically to the above, except that in step 3 it multiplies
// the types instead of adding, and in the last step it returns a CSSMathProduct.

View file

@ -17,7 +17,7 @@ class CSSMathProduct final : public CSSMathValue {
public:
[[nodiscard]] static GC::Ref<CSSMathProduct> create(JS::Realm&, NumericType, GC::Ref<CSSNumericArray>);
static WebIDL::ExceptionOr<GC::Ref<CSSMathProduct>> construct_impl(JS::Realm&, Vector<CSSNumberish>);
static WebIDL::ExceptionOr<GC::Ref<CSSMathProduct>> construct_impl(JS::Realm&, ReadonlySpan<CSSNumberish>);
static WebIDL::ExceptionOr<GC::Ref<CSSMathProduct>> multiply_all_types_into_math_product(JS::Realm&, GC::RootVector<GC::Ref<CSSNumericValue>> const&);
virtual ~CSSMathProduct() override;

View file

@ -43,7 +43,7 @@ WebIDL::ExceptionOr<GC::Ref<CSSMathSum>> CSSMathSum::add_all_types_into_math_sum
}
// https://drafts.css-houdini.org/css-typed-om-1/#dom-cssmathsum-cssmathsum
WebIDL::ExceptionOr<GC::Ref<CSSMathSum>> CSSMathSum::construct_impl(JS::Realm& realm, Vector<CSSNumberish> values)
WebIDL::ExceptionOr<GC::Ref<CSSMathSum>> CSSMathSum::construct_impl(JS::Realm& realm, ReadonlySpan<CSSNumberish> values)
{
// The CSSMathSum(...args) constructor must, when called, perform the following steps:

View file

@ -17,7 +17,7 @@ class CSSMathSum final : public CSSMathValue {
public:
[[nodiscard]] static GC::Ref<CSSMathSum> create(JS::Realm&, NumericType, GC::Ref<CSSNumericArray>);
static WebIDL::ExceptionOr<GC::Ref<CSSMathSum>> construct_impl(JS::Realm&, Vector<CSSNumberish>);
static WebIDL::ExceptionOr<GC::Ref<CSSMathSum>> construct_impl(JS::Realm&, ReadonlySpan<CSSNumberish>);
static WebIDL::ExceptionOr<GC::Ref<CSSMathSum>> add_all_types_into_math_sum(JS::Realm&, GC::RootVector<GC::Ref<CSSNumericValue>> const&);
virtual ~CSSMathSum() override;

View file

@ -63,7 +63,7 @@ void CSSNumericValue::initialize(JS::Realm& realm)
Base::initialize(realm);
}
static bool all_values_are_css_unit_values_with_the_same_unit(GC::RootVector<GC::Ref<CSSNumericValue>> const& values)
static bool all_values_are_css_unit_values_with_the_same_unit(ReadonlySpan<GC::Ref<CSSNumericValue>> const& values)
{
VERIFY(!values.is_empty());
return all_of(values, [&](auto& value) {
@ -74,7 +74,7 @@ static bool all_values_are_css_unit_values_with_the_same_unit(GC::RootVector<GC:
}
template<typename Operation>
static GC::Ref<CSSNumericValue> apply_math_operation_on_css_unit_values(JS::Realm& realm, GC::RootVector<GC::Ref<CSSNumericValue>> const& values, Operation&& operation)
static GC::Ref<CSSNumericValue> apply_math_operation_on_css_unit_values(JS::Realm& realm, ReadonlySpan<GC::Ref<CSSNumericValue>> values, Operation&& operation)
{
auto& first_unit_value = as<CSSUnitValue>(*values[0]);
auto& unit = first_unit_value.unit();
@ -86,7 +86,7 @@ static GC::Ref<CSSNumericValue> apply_math_operation_on_css_unit_values(JS::Real
}
// https://drafts.css-houdini.org/css-typed-om-1/#dom-cssnumericvalue-add
WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> CSSNumericValue::add(Vector<CSSNumberish> const& initial_values)
WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> CSSNumericValue::add(ReadonlySpan<CSSNumberish> initial_values)
{
auto& realm = this->realm();
@ -118,7 +118,7 @@ WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> CSSNumericValue::add(Vector<CSSNum
}
// https://drafts.css-houdini.org/css-typed-om-1/#dom-cssnumericvalue-sub
WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> CSSNumericValue::sub(Vector<CSSNumberish> const& initial_values)
WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> CSSNumericValue::sub(ReadonlySpan<CSSNumberish> initial_values)
{
auto& realm = this->realm();
@ -136,19 +136,19 @@ CSSNumberish CSSNumericValue::negate()
{
// 1. If this is a CSSMathNegate object, return thiss value internal slot.
if (auto* negate = as_if<CSSMathNegate>(*this))
return GC::Root<CSSNumericValue> { negate->value().ptr() };
return GC::Ref<CSSNumericValue> { negate->value() };
// 2. If this is a CSSUnitValue object, return a new CSSUnitValue with the same unit internal slot as this, and a
// value internal slot set to the negation of thiss.
if (auto* unit_value = as_if<CSSUnitValue>(*this))
return GC::Root<CSSNumericValue> { CSSUnitValue::create(realm(), -unit_value->value(), unit_value->unit()).ptr() };
return GC::Ref<CSSNumericValue> { CSSUnitValue::create(realm(), -unit_value->value(), unit_value->unit()) };
// 3. Otherwise, return a new CSSMathNegate object whose value internal slot is set to this.
return GC::Root<CSSNumericValue> { CSSMathNegate::construct_impl(realm(), GC::Root<CSSNumericValue> { this }).ptr() };
return GC::Ref<CSSNumericValue> { CSSMathNegate::construct_impl(realm(), GC::Ref<CSSNumericValue> { *this }) };
}
// https://drafts.css-houdini.org/css-typed-om-1/#dom-cssnumericvalue-mul
WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> CSSNumericValue::mul(Vector<CSSNumberish> const& initial_values)
WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> CSSNumericValue::mul(ReadonlySpan<CSSNumberish> initial_values)
{
auto& realm = this->realm();
// 1. Replace each item of values with the result of rectifying a numberish value for the item.
@ -209,7 +209,7 @@ WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> CSSNumericValue::mul(Vector<CSSNum
}
// https://drafts.css-houdini.org/css-typed-om-1/#dom-cssnumericvalue-div
WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> CSSNumericValue::div(Vector<CSSNumberish> const& initial_values)
WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> CSSNumericValue::div(ReadonlySpan<CSSNumberish> initial_values)
{
auto& realm = this->realm();
@ -227,7 +227,7 @@ WebIDL::ExceptionOr<CSSNumberish> CSSNumericValue::invert()
{
// 1. If this is a CSSMathInvert object, return thiss value internal slot.
if (auto* invert = as_if<CSSMathInvert>(*this))
return GC::Root<CSSNumericValue> { invert->value().ptr() };
return CSSNumberish { GC::Ref<CSSNumericValue> { invert->value() } };
// 2. If this is a CSSUnitValue object with unit internal slot set to "number":
if (auto* unit_value = as_if<CSSUnitValue>(*this); unit_value && unit_value->unit() == "number"sv) {
@ -237,15 +237,15 @@ WebIDL::ExceptionOr<CSSNumberish> CSSNumericValue::invert()
// 2. Else return a new CSSUnitValue with the unit internal slot set to "number", and a value internal slot set
// to 1 divided by thiss {CSSUnitValue/value}} internal slot.
return GC::Root<CSSNumericValue> { CSSUnitValue::create(realm(), 1.0 / unit_value->value(), "number"_fly_string).ptr() };
return CSSNumberish { GC::Ref<CSSNumericValue> { CSSUnitValue::create(realm(), 1.0 / unit_value->value(), "number"_fly_string) } };
}
// 3. Otherwise, return a new CSSMathInvert object whose value internal slot is set to this.
return GC::Root<CSSNumericValue> { CSSMathInvert::construct_impl(realm(), GC::Root<CSSNumericValue> { this }).ptr() };
return CSSNumberish { GC::Ref<CSSNumericValue> { CSSMathInvert::construct_impl(realm(), GC::Ref<CSSNumericValue> { *this }) } };
}
// https://drafts.css-houdini.org/css-typed-om-1/#dom-cssnumericvalue-min
WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> CSSNumericValue::min(Vector<CSSNumberish> const& initial_values)
WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> CSSNumericValue::min(ReadonlySpan<CSSNumberish> initial_values)
{
auto& realm = this->realm();
@ -275,7 +275,7 @@ WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> CSSNumericValue::min(Vector<CSSNum
}
// https://drafts.css-houdini.org/css-typed-om-1/#dom-cssnumericvalue-max
WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> CSSNumericValue::max(Vector<CSSNumberish> const& initial_values)
WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> CSSNumericValue::max(ReadonlySpan<CSSNumberish> initial_values)
{
auto& realm = this->realm();
@ -305,7 +305,7 @@ WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> CSSNumericValue::max(Vector<CSSNum
}
// https://drafts.css-houdini.org/css-typed-om-1/#dom-cssnumericvalue-equals
bool CSSNumericValue::equals_for_bindings(Vector<CSSNumberish> values) const
bool CSSNumericValue::equals_for_bindings(ReadonlySpan<CSSNumberish> values) const
{
// The equals(...values) method, when called on a CSSNumericValue this, must perform the following steps:
@ -432,8 +432,8 @@ GC::Ref<CSSNumericValue> rectify_a_numberish_value(JS::Realm& realm, CSSNumberis
// To rectify a numberish value num, optionally to a given unit unit (defaulting to "number"), perform the following steps:
return numberish.visit(
// 1. If num is a CSSNumericValue, return num.
[](GC::Root<CSSNumericValue> const& num) -> GC::Ref<CSSNumericValue> {
return GC::Ref { *num };
[](GC::Ref<CSSNumericValue> num) -> GC::Ref<CSSNumericValue> {
return num;
},
// 2. If num is a double, return a new CSSUnitValue with its value internal slot set to num and its unit
// internal slot set to unit.

View file

@ -36,14 +36,14 @@ public:
};
virtual ~CSSNumericValue() override = default;
WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> add(Vector<CSSNumberish> const&);
WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> sub(Vector<CSSNumberish> const&);
WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> mul(Vector<CSSNumberish> const&);
WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> div(Vector<CSSNumberish> const&);
WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> min(Vector<CSSNumberish> const&);
WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> max(Vector<CSSNumberish> const&);
WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> add(ReadonlySpan<CSSNumberish>);
WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> sub(ReadonlySpan<CSSNumberish>);
WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> mul(ReadonlySpan<CSSNumberish>);
WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> div(ReadonlySpan<CSSNumberish>);
WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> min(ReadonlySpan<CSSNumberish>);
WebIDL::ExceptionOr<GC::Ref<CSSNumericValue>> max(ReadonlySpan<CSSNumberish>);
bool equals_for_bindings(Vector<CSSNumberish>) const;
bool equals_for_bindings(ReadonlySpan<CSSNumberish>) const;
virtual bool is_equal_numeric_value(GC::Ref<CSSNumericValue> other) const = 0;
WebIDL::ExceptionOr<GC::Ref<CSSUnitValue>> to(FlyString const& unit) const;

View file

@ -24,7 +24,7 @@ static WebIDL::ExceptionOr<CSSPerspectiveValueInternal> to_internal(JS::Realm& r
// https://drafts.css-houdini.org/css-typed-om-1/#dom-cssperspective-cssperspective
return value.visit(
// 1. If length is a CSSNumericValue:
[](GC::Root<CSSNumericValue> const& numeric_value) -> WebIDL::ExceptionOr<CSSPerspectiveValueInternal> {
[](GC::Ref<CSSNumericValue> const& numeric_value) -> WebIDL::ExceptionOr<CSSPerspectiveValueInternal> {
// 1. If length does not match <length>, throw a TypeError.
if (!numeric_value->type().matches_length({})) {
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "CSSPerspective length component doesn't match <length>"sv };
@ -135,13 +135,7 @@ WebIDL::ExceptionOr<GC::Ref<Geometry::DOMMatrix>> CSSPerspective::to_matrix() co
CSSPerspectiveValue CSSPerspective::length() const
{
return m_length.visit(
[](GC::Ref<CSSNumericValue> const& numeric_value) -> CSSPerspectiveValue {
return GC::Root { numeric_value };
},
[](GC::Ref<CSSKeywordValue> const& keyword_value) -> CSSPerspectiveValue {
return CSSKeywordish { keyword_value };
});
return m_length;
}
WebIDL::ExceptionOr<void> CSSPerspective::set_length(CSSPerspectiveValue value)

View file

@ -14,7 +14,7 @@ namespace Web::CSS {
// https://drafts.css-houdini.org/css-typed-om-1/#typedefdef-cssperspectivevalue
// NB: CSSKeywordish is flattened here, because our bindings generator flattens nested variants.
using CSSPerspectiveValue = Variant<GC::Root<CSSNumericValue>, String, GC::Root<CSSKeywordValue>>;
using CSSPerspectiveValue = Variant<GC::Ref<CSSNumericValue>, String, GC::Ref<CSSKeywordValue>>;
using CSSPerspectiveValueInternal = Variant<GC::Ref<CSSNumericValue>, GC::Ref<CSSKeywordValue>>;
// https://drafts.css-houdini.org/css-typed-om-1/#cssperspective

View file

@ -27,9 +27,9 @@ public:
virtual WebIDL::ExceptionOr<GC::Ref<Geometry::DOMMatrix>> to_matrix() const override;
CSSNumberish x() const { return GC::Root { m_x }; }
CSSNumberish y() const { return GC::Root { m_y }; }
CSSNumberish z() const { return GC::Root { m_z }; }
CSSNumberish x() const { return m_x; }
CSSNumberish y() const { return m_y; }
CSSNumberish z() const { return m_z; }
GC::Ref<CSSNumericValue> angle() const { return m_angle; }
WebIDL::ExceptionOr<void> set_x(CSSNumberish value);
WebIDL::ExceptionOr<void> set_y(CSSNumberish value);

View file

@ -26,9 +26,9 @@ public:
virtual WebIDL::ExceptionOr<GC::Ref<Geometry::DOMMatrix>> to_matrix() const override;
CSSNumberish x() const { return GC::Root { m_x }; }
CSSNumberish y() const { return GC::Root { m_y }; }
CSSNumberish z() const { return GC::Root { m_z }; }
CSSNumberish x() const { return m_x; }
CSSNumberish y() const { return m_y; }
CSSNumberish z() const { return m_z; }
WebIDL::ExceptionOr<void> set_x(CSSNumberish value);
WebIDL::ExceptionOr<void> set_y(CSSNumberish value);
WebIDL::ExceptionOr<void> set_z(CSSNumberish value);

View file

@ -92,7 +92,7 @@ WebIDL::ExceptionOr<GC::Ref<CSSStyleSheet>> CSSStyleSheet::construct_impl(JS::Re
if (options->media.has<String>()) {
sheet->set_media(options->media.get<String>());
} else {
sheet->m_media = *options->media.get<GC::Root<MediaList>>();
sheet->m_media = *options->media.get<GC::Ref<MediaList>>();
}
}

View file

@ -18,13 +18,17 @@ namespace Web::CSS {
GC_DEFINE_ALLOCATOR(CSSTransformValue);
GC::Ref<CSSTransformValue> CSSTransformValue::create(JS::Realm& realm, Vector<GC::Ref<CSSTransformComponent>> transforms)
GC::Ref<CSSTransformValue> CSSTransformValue::create(JS::Realm& realm, ReadonlySpan<GC::Ref<CSSTransformComponent>> transforms)
{
return realm.create<CSSTransformValue>(realm, move(transforms));
Vector<GC::Ref<CSSTransformComponent>> converted_transforms;
converted_transforms.ensure_capacity(transforms.size());
for (auto const& transform : transforms)
converted_transforms.append(transform);
return realm.create<CSSTransformValue>(realm, move(converted_transforms));
}
// https://drafts.css-houdini.org/css-typed-om-1/#dom-csstransformvalue-csstransformvalue
WebIDL::ExceptionOr<GC::Ref<CSSTransformValue>> CSSTransformValue::construct_impl(JS::Realm& realm, Vector<GC::Root<CSSTransformComponent>> const& transforms)
WebIDL::ExceptionOr<GC::Ref<CSSTransformValue>> CSSTransformValue::construct_impl(JS::Realm& realm, ReadonlySpan<GC::Ref<CSSTransformComponent>> const& transforms)
{
// The CSSTransformValue(transforms) constructor must, when called, perform the following steps:
@ -33,11 +37,7 @@ WebIDL::ExceptionOr<GC::Ref<CSSTransformValue>> CSSTransformValue::construct_imp
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "CSSTransformValue's transforms list cannot be empty."sv };
// 2. Return a new CSSTransformValue whose values to iterate over is transforms.
Vector<GC::Ref<CSSTransformComponent>> converted_transforms;
converted_transforms.ensure_capacity(transforms.size());
for (auto const& transform : transforms)
converted_transforms.append(*transform);
return CSSTransformValue::create(realm, move(converted_transforms));
return CSSTransformValue::create(realm, transforms);
}
CSSTransformValue::CSSTransformValue(JS::Realm& realm, Vector<GC::Ref<CSSTransformComponent>> transforms)

View file

@ -17,8 +17,8 @@ class CSSTransformValue final : public CSSStyleValue {
GC_DECLARE_ALLOCATOR(CSSTransformValue);
public:
[[nodiscard]] static GC::Ref<CSSTransformValue> create(JS::Realm&, Vector<GC::Ref<CSSTransformComponent>>);
static WebIDL::ExceptionOr<GC::Ref<CSSTransformValue>> construct_impl(JS::Realm&, Vector<GC::Root<CSSTransformComponent>> const&);
[[nodiscard]] static GC::Ref<CSSTransformValue> create(JS::Realm&, ReadonlySpan<GC::Ref<CSSTransformComponent>>);
static WebIDL::ExceptionOr<GC::Ref<CSSTransformValue>> construct_impl(JS::Realm&, ReadonlySpan<GC::Ref<CSSTransformComponent>> const&);
virtual ~CSSTransformValue() override;

View file

@ -16,13 +16,13 @@ namespace Web::CSS {
GC_DEFINE_ALLOCATOR(CSSUnparsedValue);
GC::Ref<CSSUnparsedValue> CSSUnparsedValue::create(JS::Realm& realm, Vector<GCRootCSSUnparsedSegment> value)
GC::Ref<CSSUnparsedValue> CSSUnparsedValue::create(JS::Realm& realm, ReadonlySpan<CSSUnparsedSegment> value)
{
// NB: Convert our GC::Roots into GC::Refs.
// NB: Convert our Span into a Vector of Refs.
Vector<CSSUnparsedSegment> converted_value;
for (auto const& variant : value) {
variant.visit(
[&](GC::Root<CSSVariableReferenceValue> const& it) { converted_value.append(GC::Ref { *it }); },
[&](GC::Ref<CSSVariableReferenceValue> it) { converted_value.append(it); },
[&](String const& it) { converted_value.append(it); });
}
@ -30,14 +30,14 @@ GC::Ref<CSSUnparsedValue> CSSUnparsedValue::create(JS::Realm& realm, Vector<GCRo
}
// https://drafts.css-houdini.org/css-typed-om-1/#dom-cssunparsedvalue-cssunparsedvalue
WebIDL::ExceptionOr<GC::Ref<CSSUnparsedValue>> CSSUnparsedValue::construct_impl(JS::Realm& realm, Vector<GCRootCSSUnparsedSegment> value)
WebIDL::ExceptionOr<GC::Ref<CSSUnparsedValue>> CSSUnparsedValue::construct_impl(JS::Realm& realm, ReadonlySpan<CSSUnparsedSegment> value)
{
// AD-HOC: There is no spec for this, see https://github.com/w3c/css-houdini-drafts/issues/1146
return CSSUnparsedValue::create(realm, move(value));
}
CSSUnparsedValue::CSSUnparsedValue(JS::Realm& realm, Vector<CSSUnparsedSegment> value)
CSSUnparsedValue::CSSUnparsedValue(JS::Realm& realm, ReadonlySpan<CSSUnparsedSegment> value)
: CSSStyleValue(realm)
, m_tokens(move(value))
{

View file

@ -12,7 +12,6 @@
namespace Web::CSS {
using CSSUnparsedSegment = Variant<String, GC::Ref<CSSVariableReferenceValue>>;
using GCRootCSSUnparsedSegment = Variant<String, GC::Root<CSSVariableReferenceValue>>;
// https://drafts.css-houdini.org/css-typed-om-1/#cssunparsedvalue
class CSSUnparsedValue final : public CSSStyleValue {
@ -20,8 +19,8 @@ class CSSUnparsedValue final : public CSSStyleValue {
GC_DECLARE_ALLOCATOR(CSSUnparsedValue);
public:
[[nodiscard]] static GC::Ref<CSSUnparsedValue> create(JS::Realm&, Vector<GCRootCSSUnparsedSegment>);
static WebIDL::ExceptionOr<GC::Ref<CSSUnparsedValue>> construct_impl(JS::Realm&, Vector<GCRootCSSUnparsedSegment>);
[[nodiscard]] static GC::Ref<CSSUnparsedValue> create(JS::Realm&, ReadonlySpan<CSSUnparsedSegment>);
static WebIDL::ExceptionOr<GC::Ref<CSSUnparsedValue>> construct_impl(JS::Realm&, ReadonlySpan<CSSUnparsedSegment>);
virtual ~CSSUnparsedValue() override;
@ -34,7 +33,7 @@ public:
virtual WebIDL::ExceptionOr<NonnullRefPtr<StyleValue const>> create_an_internal_representation(PropertyNameAndID const&, PerformTypeCheck) const override;
private:
explicit CSSUnparsedValue(JS::Realm&, Vector<CSSUnparsedSegment>);
explicit CSSUnparsedValue(JS::Realm&, ReadonlySpan<CSSUnparsedSegment>);
virtual void initialize(JS::Realm&) override;
virtual void visit_edges(Visitor&) override;

View file

@ -177,7 +177,7 @@ GC::Ref<FontFace> FontFace::construct_impl(JS::Realm& realm, String family, Font
font_face->m_urls = ParsedFontFace::sources_from_style_value(*parsed_source);
font_face->m_urls.remove_all_matching(is_unsupported_source);
} else {
auto buffer_source = source.get<GC::Root<WebIDL::BufferSource>>();
auto buffer_source = source.get<GC::Ref<WebIDL::BufferSource>>();
auto maybe_buffer = WebIDL::get_buffer_source_copy(buffer_source->raw_object());
if (maybe_buffer.is_error()) {
VERIFY(maybe_buffer.error().code() == ENOMEM);

View file

@ -23,7 +23,7 @@ class FontFace final : public Bindings::PlatformObject {
GC_DECLARE_ALLOCATOR(FontFace);
public:
using FontFaceSource = Variant<String, GC::Root<WebIDL::BufferSource>>;
using FontFaceSource = Variant<String, GC::Ref<WebIDL::BufferSource>>;
[[nodiscard]] static GC::Ref<FontFace> construct_impl(JS::Realm&, String family, FontFaceSource source, Bindings::FontFaceDescriptors const& descriptors);
[[nodiscard]] static GC::Ref<FontFace> create_css_connected(JS::Realm&, CSSFontFaceRule&);

View file

@ -11,6 +11,7 @@
#include <LibJS/Runtime/Set.h>
#include <LibWeb/Bindings/ExceptionOrUtils.h>
#include <LibWeb/Bindings/FontFaceSet.h>
#include <LibWeb/Bindings/FontFaceSetLoadEvent.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/CSS/FontComputer.h>
#include <LibWeb/CSS/FontFace.h>
@ -375,7 +376,7 @@ void FontFaceSet::fire_a_font_load_event(FlyString name, Vector<GC::Ref<FontFace
// event named e using the FontFaceSetLoadEvent interface that also meets these conditions:
// 1. The fontfaces attribute is initialized to the result of filtering font faces to only contain FontFace
// objects contained in target.
Bindings::FontFaceSetLoadEventInit load_event_init {};
Bindings::FontFaceSetLoadEventInit load_event_init;
for (auto const& font_face : font_faces) {
if (set_entries()->set_has(font_face))
load_event_init.fontfaces.append(font_face);

View file

@ -29,8 +29,7 @@ FontFaceSetLoadEvent::FontFaceSetLoadEvent(JS::Realm& realm, FlyString const& ev
{
m_fontfaces.ensure_capacity(event_init.fontfaces.size());
for (auto const& font_face : event_init.fontfaces) {
VERIFY(font_face);
m_fontfaces.unchecked_append(*font_face);
m_fontfaces.unchecked_append(font_face);
}
}

View file

@ -6,7 +6,6 @@
#pragma once
#include <LibWeb/Bindings/FontFaceSetLoadEvent.h>
#include <LibWeb/Bindings/PlatformObject.h>
#include <LibWeb/DOM/Event.h>
@ -17,15 +16,15 @@ class FontFaceSetLoadEvent : public DOM::Event {
GC_DECLARE_ALLOCATOR(FontFaceSetLoadEvent);
public:
[[nodiscard]] static GC::Ref<FontFaceSetLoadEvent> create(JS::Realm&, FlyString const& type, Bindings::FontFaceSetLoadEventInit const& event_init = {});
static WebIDL::ExceptionOr<GC::Ref<FontFaceSetLoadEvent>> construct_impl(JS::Realm&, FlyString const& type, Bindings::FontFaceSetLoadEventInit const& event_init = {});
[[nodiscard]] static GC::Ref<FontFaceSetLoadEvent> create(JS::Realm&, FlyString const& type, Bindings::FontFaceSetLoadEventInit const&);
static WebIDL::ExceptionOr<GC::Ref<FontFaceSetLoadEvent>> construct_impl(JS::Realm&, FlyString const& type, Bindings::FontFaceSetLoadEventInit const&);
virtual ~FontFaceSetLoadEvent() override = default;
Vector<GC::Ref<FontFace>> const& fontfaces() const { return m_fontfaces; }
private:
FontFaceSetLoadEvent(JS::Realm&, FlyString const& type, Bindings::FontFaceSetLoadEventInit const& event_init = {});
FontFaceSetLoadEvent(JS::Realm&, FlyString const& type, Bindings::FontFaceSetLoadEventInit const&);
virtual void initialize(JS::Realm&) override;
virtual void visit_edges(Visitor&) override;

View file

@ -47,10 +47,10 @@ void StylePropertyMap::initialize(JS::Realm& realm)
Base::initialize(realm);
}
static bool any_have_non_matching_associated_property(FlyString const& property, Vector<Variant<GC::Root<CSSStyleValue>, String>> values)
static bool any_have_non_matching_associated_property(FlyString const& property, ReadonlySpan<Variant<GC::Ref<CSSStyleValue>, String>> values)
{
return any_of(values, [&property](Variant<GC::Root<CSSStyleValue>, String> const& value) {
if (auto* style_value = value.get_pointer<GC::Root<CSSStyleValue>>()) {
return any_of(values, [&property](Variant<GC::Ref<CSSStyleValue>, String> const& value) {
if (auto* style_value = value.get_pointer<GC::Ref<CSSStyleValue>>()) {
if (auto associated_property = (*style_value)->associated_property();
associated_property.has_value() && associated_property != property)
return true;
@ -60,11 +60,11 @@ static bool any_have_non_matching_associated_property(FlyString const& property,
}
// https://drafts.css-houdini.org/css-typed-om-1/#create-an-internal-representation
static WebIDL::ExceptionOr<NonnullRefPtr<StyleValue const>> create_an_internal_representation(JS::VM& vm, PropertyNameAndID const& property, Variant<GC::Root<CSSStyleValue>, String> const& value)
static WebIDL::ExceptionOr<NonnullRefPtr<StyleValue const>> create_an_internal_representation(JS::VM& vm, PropertyNameAndID const& property, Variant<GC::Ref<CSSStyleValue>, String> const& value)
{
// To create an internal representation, given a string property and a string or CSSStyleValue value:
return value.visit(
[&property](GC::Root<CSSStyleValue> const& css_style_value) {
[&property](GC::Ref<CSSStyleValue> const& css_style_value) {
return css_style_value->create_an_internal_representation(property, CSSStyleValue::PerformTypeCheck::Yes);
},
[&](String const& css_text) -> WebIDL::ExceptionOr<NonnullRefPtr<StyleValue const>> {
@ -116,7 +116,7 @@ static WebIDL::ExceptionOr<NonnullRefPtr<StyleValue const>> normalize_overflow_c
}
// https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-set
WebIDL::ExceptionOr<void> StylePropertyMap::set(FlyString property_name, Vector<Variant<GC::Root<CSSStyleValue>, String>> values)
WebIDL::ExceptionOr<void> StylePropertyMap::set(FlyString property_name, ReadonlySpan<Variant<GC::Ref<CSSStyleValue>, String>> values)
{
// The set(property, ...values) method, when called on a StylePropertyMap this, must perform the following steps:
@ -221,7 +221,7 @@ WebIDL::ExceptionOr<void> StylePropertyMap::set(FlyString property_name, Vector<
}
// https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-append
WebIDL::ExceptionOr<void> StylePropertyMap::append(FlyString property_name, Vector<Variant<GC::Root<CSSStyleValue>, String>> values)
WebIDL::ExceptionOr<void> StylePropertyMap::append(FlyString property_name, ReadonlySpan<Variant<GC::Ref<CSSStyleValue>, String>> values)
{
// The append(property, ...values) method, when called on a StylePropertyMap this, must perform the following steps:

View file

@ -20,8 +20,8 @@ public:
virtual ~StylePropertyMap() override;
WebIDL::ExceptionOr<void> set(FlyString property, Vector<Variant<GC::Root<CSSStyleValue>, String>> values);
WebIDL::ExceptionOr<void> append(FlyString property, Vector<Variant<GC::Root<CSSStyleValue>, String>> values);
WebIDL::ExceptionOr<void> set(FlyString property, ReadonlySpan<Variant<GC::Ref<CSSStyleValue>, String>> values);
WebIDL::ExceptionOr<void> append(FlyString property, ReadonlySpan<Variant<GC::Ref<CSSStyleValue>, String>> values);
WebIDL::ExceptionOr<void> delete_(FlyString property);
WebIDL::ExceptionOr<void> clear();

View file

@ -52,7 +52,7 @@ bool UnresolvedStyleValue::equals(StyleValue const& other) const
static GC::Ref<CSSUnparsedValue> reify_a_list_of_component_values(JS::Realm&, Vector<Parser::ComponentValue>);
// https://drafts.css-houdini.org/css-typed-om-1/#reify-var
static GC::Root<CSSVariableReferenceValue> reify_a_var_reference(JS::Realm& realm, Parser::Function function)
static GC::Ptr<CSSVariableReferenceValue> reify_a_var_reference(JS::Realm& realm, Parser::Function function)
{
// NB: A var() might not be representable as a CSSVariableReferenceValue, for example if it has invalid syntax or
// it contains an ASF in its variable-name slot. In those cases, we return null here, so it's treated like a
@ -90,7 +90,7 @@ static GC::Root<CSSVariableReferenceValue> reify_a_var_reference(JS::Realm& real
class Reifier {
public:
static Vector<GCRootCSSUnparsedSegment> reify(JS::Realm& realm, Vector<Parser::ComponentValue> const& source_values)
static Vector<CSSUnparsedSegment> reify(JS::Realm& realm, Vector<Parser::ComponentValue> const& source_values)
{
Reifier reifier;
reifier.process_values(realm, source_values);
@ -112,7 +112,7 @@ private:
// serializing it like a regular function.
if (auto var_reference = reify_a_var_reference(realm, component_value.function())) {
serialize_unserialized_values();
m_reified_values.append(move(var_reference));
m_reified_values.append(GC::Ref { *var_reference });
continue;
}
}
@ -143,7 +143,7 @@ private:
m_unserialized_values.clear_with_capacity();
}
Vector<GCRootCSSUnparsedSegment> m_reified_values {};
Vector<CSSUnparsedSegment> m_reified_values {};
Vector<Parser::ComponentValue> m_unserialized_values {};
};

View file

@ -398,7 +398,7 @@ GC::Ref<WebIDL::Promise> Clipboard::read_text()
}
// https://w3c.github.io/clipboard-apis/#dom-clipboard-write
GC::Ref<WebIDL::Promise> Clipboard::write(Vector<GC::Root<ClipboardItem>> const& data)
GC::Ref<WebIDL::Promise> Clipboard::write(GC::RootVector<GC::Ref<ClipboardItem>> const& data)
{
// 1. Let realm be this's relevant realm.
auto& realm = HTML::relevant_realm(*this);

View file

@ -27,7 +27,7 @@ public:
GC::Ref<WebIDL::Promise> read(Bindings::ClipboardUnsanitizedFormats formats = {});
GC::Ref<WebIDL::Promise> read_text();
GC::Ref<WebIDL::Promise> write(Vector<GC::Root<ClipboardItem>> const&);
GC::Ref<WebIDL::Promise> write(GC::RootVector<GC::Ref<ClipboardItem>> const&);
GC::Ref<WebIDL::Promise> write_text(String);
private:

View file

@ -16,7 +16,7 @@ namespace Web::Clipboard {
GC_DEFINE_ALLOCATOR(ClipboardItem);
// https://w3c.github.io/clipboard-apis/#dom-clipboarditem-clipboarditem
WebIDL::ExceptionOr<GC::Ref<ClipboardItem>> ClipboardItem::construct_impl(JS::Realm& realm, OrderedHashMap<String, GC::Root<WebIDL::Promise>> const& items, Bindings::ClipboardItemOptions const& options)
WebIDL::ExceptionOr<GC::Ref<ClipboardItem>> ClipboardItem::construct_impl(JS::Realm& realm, GC::OrderedRootHashMap<String, GC::Ref<WebIDL::Promise>> const& items, Bindings::ClipboardItemOptions const& options)
{
// 1. If items is empty, then throw a TypeError.
if (items.is_empty())

View file

@ -35,7 +35,7 @@ public:
GC::Ref<WebIDL::Promise> data; // The actual data for this representation.
};
static WebIDL::ExceptionOr<GC::Ref<ClipboardItem>> construct_impl(JS::Realm&, OrderedHashMap<String, GC::Root<WebIDL::Promise>> const& items, Bindings::ClipboardItemOptions const& options = {});
static WebIDL::ExceptionOr<GC::Ref<ClipboardItem>> construct_impl(JS::Realm&, GC::OrderedRootHashMap<String, GC::Ref<WebIDL::Promise>> const& items, Bindings::ClipboardItemOptions const& options = {});
virtual ~ClipboardItem() override;

View file

@ -56,8 +56,7 @@ static JS::ThrowCompletionOr<HashAlgorithmIdentifier> hash_algorithm_identifier_
}
if (hash_value.is_object()) {
auto const hash_object = TRY(hash_value.to_object(vm));
auto const hash_object_root = GC::make_root(hash_object);
return normalize_an_algorithm(*realm, hash_object_root, "digest"_string);
return normalize_an_algorithm(*realm, hash_object, "digest"_string);
}
VERIFY_NOT_REACHED();
}();

View file

@ -22,9 +22,9 @@
namespace Web::Crypto {
using AlgorithmIdentifier = Variant<GC::Root<JS::Object>, String>;
using AlgorithmIdentifier = Variant<GC::Ref<JS::Object>, String>;
using NamedCurve = String;
using KeyDataType = Variant<GC::Root<WebIDL::BufferSource>, JsonWebKey>;
using KeyDataType = Variant<GC::Ref<WebIDL::BufferSource>, JsonWebKey>;
// https://wicg.github.io/webcrypto-modern-algos/#encapsulation
struct EncapsulatedKey {

View file

@ -109,9 +109,8 @@ WebIDL::ExceptionOr<NormalizedAlgorithmAndParameter> normalize_an_algorithm(JS::
if (algorithm.has<String>()) {
// Return the result of running the normalize an algorithm algorithm,
// with the alg set to a new Algorithm dictionary whose name attribute is alg, and with the op set to op.
auto dictionary = GC::make_root(JS::Object::create(realm, realm.intrinsics().object_prototype()));
auto dictionary = JS::Object::create(realm, realm.intrinsics().object_prototype());
TRY(dictionary->create_data_property("name"_utf16_fly_string, JS::PrimitiveString::create(vm, algorithm.get<String>())));
return normalize_an_algorithm(realm, dictionary, operation);
}
@ -127,7 +126,7 @@ WebIDL::ExceptionOr<NormalizedAlgorithmAndParameter> normalize_an_algorithm(JS::
// 3. If an error occurred, return the error and terminate this algorithm.
// Note: We're not going to bother creating an Algorithm object, all we want is the name attribute so that we can
// fetch the actual algorithm factory from the registeredAlgorithms map.
auto initial_algorithm = TRY(algorithm.get<GC::Root<JS::Object>>()->get("name"_utf16_fly_string));
auto initial_algorithm = TRY(algorithm.get<GC::Ref<JS::Object>>()->get("name"_utf16_fly_string));
if (initial_algorithm.is_undefined()) {
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "Algorithm");
@ -159,7 +158,7 @@ WebIDL::ExceptionOr<NormalizedAlgorithmAndParameter> normalize_an_algorithm(JS::
// 12. For each dictionary dictionary in dictionaries:
// Note: All of these steps are handled by the create_methods and parameter_from_value methods.
auto methods = desired_type.create_methods(realm);
auto parameter = TRY(desired_type.parameter_from_value(vm, algorithm.get<GC::Root<JS::Object>>()));
auto parameter = TRY(desired_type.parameter_from_value(vm, algorithm.get<GC::Ref<JS::Object>>()));
// 9. Set the name attribute of normalizedAlgorithm to algName.
VERIFY(parameter->name.is_empty());
@ -447,7 +446,7 @@ GC::Ref<WebIDL::Promise> SubtleCrypto::generate_key(AlgorithmIdentifier algorith
}
// https://w3c.github.io/webcrypto/#SubtleCrypto-method-importKey
JS::ThrowCompletionOr<GC::Ref<WebIDL::Promise>> SubtleCrypto::import_key(Bindings::KeyFormat format, Variant<GC::Root<WebIDL::BufferSource>, Bindings::JsonWebKey> key_data, AlgorithmIdentifier algorithm, bool extractable, Vector<Bindings::KeyUsage> key_usages)
JS::ThrowCompletionOr<GC::Ref<WebIDL::Promise>> SubtleCrypto::import_key(Bindings::KeyFormat format, Variant<GC::Ref<WebIDL::BufferSource>, Bindings::JsonWebKey> key_data, AlgorithmIdentifier algorithm, bool extractable, Vector<Bindings::KeyUsage> key_usages)
{
auto& realm = this->realm();
@ -469,7 +468,7 @@ JS::ThrowCompletionOr<GC::Ref<WebIDL::Promise>> SubtleCrypto::import_key(Binding
}
// 2. Let keyData be the result of getting a copy of the bytes held by the keyData parameter passed to the importKey() method.
real_key_data = MUST(WebIDL::get_buffer_source_copy(*key_data.get<GC::Root<WebIDL::BufferSource>>()->raw_object()));
real_key_data = MUST(WebIDL::get_buffer_source_copy(*key_data.get<GC::Ref<WebIDL::BufferSource>>()->raw_object()));
}
if (format == Bindings::KeyFormat::Jwk) {
@ -1079,7 +1078,7 @@ GC::Ref<WebIDL::Promise> SubtleCrypto::unwrap_key(Bindings::KeyFormat format, Ke
auto normalized_key_algorithm = normalized_key_algorithm_or_error.release_value();
// 7. Let wrappedKey be the result of getting a copy of the bytes held by the wrappedKey parameter passed to the unwrapKey() method.
auto real_wrapped_key = MUST(WebIDL::get_buffer_source_copy(*wrapped_key.get<GC::Root<WebIDL::BufferSource>>()->raw_object()));
auto real_wrapped_key = MUST(WebIDL::get_buffer_source_copy(*wrapped_key.get<GC::Ref<WebIDL::BufferSource>>()->raw_object()));
// 9. Let promise be a new Promise.
auto promise = WebIDL::create_promise(realm);

View file

@ -37,7 +37,7 @@ public:
GC::Ref<WebIDL::Promise> derive_bits(AlgorithmIdentifier algorithm, GC::Ref<CryptoKey> base_key, Optional<u32> length_optional);
GC::Ref<WebIDL::Promise> derive_key(AlgorithmIdentifier algorithm, GC::Ref<CryptoKey> base_key, AlgorithmIdentifier derived_key_type, bool extractable, Vector<Bindings::KeyUsage> key_usages);
JS::ThrowCompletionOr<GC::Ref<WebIDL::Promise>> import_key(Bindings::KeyFormat format, Variant<GC::Root<WebIDL::BufferSource>, Bindings::JsonWebKey> key_data, AlgorithmIdentifier algorithm, bool extractable, Vector<Bindings::KeyUsage> key_usages);
JS::ThrowCompletionOr<GC::Ref<WebIDL::Promise>> import_key(Bindings::KeyFormat format, Variant<GC::Ref<WebIDL::BufferSource>, Bindings::JsonWebKey> key_data, AlgorithmIdentifier algorithm, bool extractable, Vector<Bindings::KeyUsage> key_usages);
GC::Ref<WebIDL::Promise> export_key(Bindings::KeyFormat format, GC::Ref<CryptoKey> key);
GC::Ref<WebIDL::Promise> wrap_key(Bindings::KeyFormat format, GC::Ref<CryptoKey> key, GC::Ref<CryptoKey> wrapping_key, AlgorithmIdentifier wrap_algorithm);

View file

@ -41,10 +41,10 @@ void AbortController::visit_edges(Cell::Visitor& visitor)
}
// https://dom.spec.whatwg.org/#dom-abortcontroller-abort
void AbortController::abort(JS::Value reason)
void AbortController::abort(Optional<JS::Value> reason)
{
// The abort(reason) method steps are to signal abort on thiss signal with reason if it is given.
m_signal->signal_abort(reason);
m_signal->signal_abort(reason.value_or(JS::js_undefined()));
}
}

View file

@ -24,7 +24,7 @@ public:
// https://dom.spec.whatwg.org/#dom-abortcontroller-signal
GC::Ref<AbortSignal> signal() const { return *m_signal; }
void abort(JS::Value reason);
void abort(Optional<JS::Value> reason);
private:
AbortController(JS::Realm&, GC::Ref<AbortSignal>);

View file

@ -144,12 +144,13 @@ size_t AbortSignal::external_memory_size() const
}
// https://dom.spec.whatwg.org/#dom-abortsignal-abort
WebIDL::ExceptionOr<GC::Ref<AbortSignal>> AbortSignal::abort(JS::VM& vm, JS::Value reason)
WebIDL::ExceptionOr<GC::Ref<AbortSignal>> AbortSignal::abort(JS::VM& vm, Optional<JS::Value> maybe_reason)
{
// 1. Let signal be a new AbortSignal object.
auto signal = TRY(construct_impl(*vm.current_realm()));
// 2. Set signals abort reason to reason if it is given; otherwise to a new "AbortError" DOMException.
auto reason = maybe_reason.value_or(JS::js_undefined());
if (reason.is_undefined())
reason = WebIDL::AbortError::create(*vm.current_realm(), "Aborted without reason"_utf16).ptr();
@ -185,14 +186,14 @@ WebIDL::ExceptionOr<GC::Ref<AbortSignal>> AbortSignal::timeout(JS::VM& vm, WebID
}
// https://dom.spec.whatwg.org/#dom-abortsignal-any
WebIDL::ExceptionOr<GC::Ref<AbortSignal>> AbortSignal::any(JS::VM& vm, Vector<GC::Root<AbortSignal>> const& signals)
WebIDL::ExceptionOr<GC::Ref<AbortSignal>> AbortSignal::any(JS::VM& vm, ReadonlySpan<GC::Ref<AbortSignal>> signals)
{
// The static any(signals) method steps are to return the result of creating a dependent abort signal from signals using AbortSignal and the current realm.
return create_dependent_abort_signal(*vm.current_realm(), signals);
}
// https://dom.spec.whatwg.org/#create-a-dependent-abort-signal
WebIDL::ExceptionOr<GC::Ref<AbortSignal>> AbortSignal::create_dependent_abort_signal(JS::Realm& realm, Vector<GC::Root<AbortSignal>> const& signals)
WebIDL::ExceptionOr<GC::Ref<AbortSignal>> AbortSignal::create_dependent_abort_signal(JS::Realm& realm, ReadonlySpan<GC::Ref<AbortSignal>> signals)
{
// 1. Let resultSignal be a new object implementing signalInterface using realm.
auto result_signal = TRY(construct_impl(realm));

View file

@ -46,11 +46,11 @@ public:
JS::ThrowCompletionOr<void> throw_if_aborted() const;
static WebIDL::ExceptionOr<GC::Ref<AbortSignal>> abort(JS::VM&, JS::Value reason);
static WebIDL::ExceptionOr<GC::Ref<AbortSignal>> abort(JS::VM&, Optional<JS::Value> reason);
static WebIDL::ExceptionOr<GC::Ref<AbortSignal>> timeout(JS::VM&, Web::WebIDL::UnsignedLongLong milliseconds);
static WebIDL::ExceptionOr<GC::Ref<AbortSignal>> any(JS::VM&, Vector<GC::Root<AbortSignal>> const&);
static WebIDL::ExceptionOr<GC::Ref<AbortSignal>> any(JS::VM&, ReadonlySpan<GC::Ref<AbortSignal>>);
static WebIDL::ExceptionOr<GC::Ref<AbortSignal>> create_dependent_abort_signal(JS::Realm&, Vector<GC::Root<AbortSignal>> const&);
static WebIDL::ExceptionOr<GC::Ref<AbortSignal>> create_dependent_abort_signal(JS::Realm&, ReadonlySpan<GC::Ref<AbortSignal>>);
private:
explicit AbortSignal(JS::Realm&);

View file

@ -16,7 +16,7 @@ template<typename NodeType>
class ChildNode {
public:
// https://dom.spec.whatwg.org/#dom-childnode-before
WebIDL::ExceptionOr<void> before(Vector<Variant<GC::Root<Node>, Utf16String>> const& nodes)
WebIDL::ExceptionOr<void> before(ReadonlySpan<Variant<GC::Ref<Node>, Utf16String>> nodes)
{
auto* node = static_cast<NodeType*>(this);
@ -46,7 +46,7 @@ public:
}
// https://dom.spec.whatwg.org/#dom-childnode-after
WebIDL::ExceptionOr<void> after(Vector<Variant<GC::Root<Node>, Utf16String>> const& nodes)
WebIDL::ExceptionOr<void> after(ReadonlySpan<Variant<GC::Ref<Node>, Utf16String>> nodes)
{
auto* node = static_cast<NodeType*>(this);
@ -70,7 +70,7 @@ public:
}
// https://dom.spec.whatwg.org/#dom-childnode-replacewith
WebIDL::ExceptionOr<void> replace_with(Vector<Variant<GC::Root<Node>, Utf16String>> const& nodes)
WebIDL::ExceptionOr<void> replace_with(ReadonlySpan<Variant<GC::Ref<Node>, Utf16String>> nodes)
{
auto* node = static_cast<NodeType*>(this);
@ -117,7 +117,7 @@ protected:
ChildNode() = default;
private:
GC::Ptr<Node> viable_previous_sibling_for_insertion(Vector<Variant<GC::Root<Node>, Utf16String>> const& nodes)
GC::Ptr<Node> viable_previous_sibling_for_insertion(ReadonlySpan<Variant<GC::Ref<Node>, Utf16String>> const& nodes)
{
auto* node = static_cast<NodeType*>(this);
@ -125,11 +125,11 @@ private:
bool contained_in_nodes = false;
for (auto const& node_or_string : nodes) {
if (!node_or_string.template has<GC::Root<Node>>())
if (!node_or_string.template has<GC::Ref<Node>>())
continue;
auto const& node_in_vector = node_or_string.template get<GC::Root<Node>>();
if (node_in_vector.cell() == sibling) {
auto const& node_in_vector = node_or_string.template get<GC::Ref<Node>>();
if (node_in_vector == sibling) {
contained_in_nodes = true;
break;
}
@ -142,7 +142,7 @@ private:
return nullptr;
}
GC::Ptr<Node> viable_next_sibling_for_insertion(Vector<Variant<GC::Root<Node>, Utf16String>> const& nodes)
GC::Ptr<Node> viable_next_sibling_for_insertion(ReadonlySpan<Variant<GC::Ref<Node>, Utf16String>> const& nodes)
{
auto* node = static_cast<NodeType*>(this);
@ -150,11 +150,11 @@ private:
bool contained_in_nodes = false;
for (auto const& node_or_string : nodes) {
if (!node_or_string.template has<GC::Root<Node>>())
if (!node_or_string.template has<GC::Ref<Node>>())
continue;
auto const& node_in_vector = node_or_string.template get<GC::Root<Node>>();
if (node_in_vector.cell() == sibling) {
auto const& node_in_vector = node_or_string.template get<GC::Ref<Node>>();
if (node_in_vector == sibling) {
contained_in_nodes = true;
break;
}

View file

@ -42,6 +42,8 @@
#include <LibWeb/Bindings/Document.h>
#include <LibWeb/Bindings/IntersectionObserver.h>
#include <LibWeb/Bindings/MainThreadVM.h>
#include <LibWeb/Bindings/MessageEvent.h>
#include <LibWeb/Bindings/PointerEvent.h>
#include <LibWeb/Bindings/PrincipalHostDefined.h>
#include <LibWeb/CSS/AnimationEvent.h>
#include <LibWeb/CSS/CSSAnimation.h>
@ -2678,11 +2680,11 @@ void Document::set_hovered_node(GC::Ptr<Node> node, Optional<HoverEventData> hov
// https://w3c.github.io/pointerevents/#the-pointerout-event
if (old_hovered_node && old_hovered_node != m_hovered_node) {
Bindings::PointerEventInit pointer_event_init {};
Bindings::PointerEventInit pointer_event_init;
pointer_event_init.bubbles = true;
pointer_event_init.cancelable = true;
pointer_event_init.composed = true;
pointer_event_init.related_target = GC::Root<DOM::EventTarget> { m_hovered_node.ptr() };
pointer_event_init.related_target = m_hovered_node;
pointer_event_init.is_primary = true;
pointer_event_init.pointer_type = UIEvents::PointerTypes::Mouse;
pointer_event_init.view = window_proxy;
@ -2700,7 +2702,7 @@ void Document::set_hovered_node(GC::Ptr<Node> node, Optional<HoverEventData> hov
mouse_event_init.bubbles = true;
mouse_event_init.cancelable = true;
mouse_event_init.composed = true;
mouse_event_init.related_target = GC::Root<DOM::EventTarget> { m_hovered_node.ptr() };
mouse_event_init.related_target = m_hovered_node;
mouse_event_init.view = window_proxy;
if (hover_event_data.has_value())
populate_mouse_event_init_from_hover_event_data(mouse_event_init, *hover_event_data, window_proxy);
@ -2713,8 +2715,8 @@ void Document::set_hovered_node(GC::Ptr<Node> node, Optional<HoverEventData> hov
// https://w3c.github.io/pointerevents/#the-pointerleave-event
if (!pointer_leave_targets.is_empty()) {
for (auto const& target : pointer_leave_targets) {
Bindings::PointerEventInit pointer_event_init {};
pointer_event_init.related_target = GC::Root<DOM::EventTarget> { m_hovered_node.ptr() };
Bindings::PointerEventInit pointer_event_init;
pointer_event_init.related_target = m_hovered_node;
pointer_event_init.is_primary = true;
pointer_event_init.pointer_type = UIEvents::PointerTypes::Mouse;
pointer_event_init.view = window_proxy;
@ -2731,7 +2733,7 @@ void Document::set_hovered_node(GC::Ptr<Node> node, Optional<HoverEventData> hov
if (!mouse_leave_targets.is_empty()) {
for (auto const& target : mouse_leave_targets) {
Bindings::MouseEventInit mouse_event_init {};
mouse_event_init.related_target = GC::Root<DOM::EventTarget> { m_hovered_node.ptr() };
mouse_event_init.related_target = m_hovered_node;
if (hover_event_data.has_value())
populate_mouse_event_init_from_hover_event_data(mouse_event_init, *hover_event_data, window_proxy);
auto offset = target.offset;
@ -2743,11 +2745,11 @@ void Document::set_hovered_node(GC::Ptr<Node> node, Optional<HoverEventData> hov
// https://w3c.github.io/pointerevents/#the-pointerover-event
if (m_hovered_node && m_hovered_node != old_hovered_node) {
Bindings::PointerEventInit pointer_event_init {};
Bindings::PointerEventInit pointer_event_init;
pointer_event_init.bubbles = true;
pointer_event_init.cancelable = true;
pointer_event_init.composed = true;
pointer_event_init.related_target = GC::Root<DOM::EventTarget> { old_hovered_node.ptr() };
pointer_event_init.related_target = old_hovered_node;
pointer_event_init.is_primary = true;
pointer_event_init.pointer_type = UIEvents::PointerTypes::Mouse;
pointer_event_init.view = window_proxy;
@ -2765,7 +2767,7 @@ void Document::set_hovered_node(GC::Ptr<Node> node, Optional<HoverEventData> hov
mouse_event_init.bubbles = true;
mouse_event_init.cancelable = true;
mouse_event_init.composed = true;
mouse_event_init.related_target = GC::Root<DOM::EventTarget> { old_hovered_node.ptr() };
mouse_event_init.related_target = old_hovered_node;
mouse_event_init.view = window_proxy;
if (hover_event_data.has_value())
populate_mouse_event_init_from_hover_event_data(mouse_event_init, *hover_event_data, window_proxy);
@ -2781,8 +2783,8 @@ void Document::set_hovered_node(GC::Ptr<Node> node, Optional<HoverEventData> hov
// Leave events are dispatched in the opposite order.
if (!entered_ancestors.is_empty()) {
for (auto target : entered_ancestors.in_reverse()) {
Bindings::PointerEventInit pointer_event_init {};
pointer_event_init.related_target = GC::Root<DOM::EventTarget> { old_hovered_node.ptr() };
Bindings::PointerEventInit pointer_event_init;
pointer_event_init.related_target = old_hovered_node;
pointer_event_init.is_primary = true;
pointer_event_init.pointer_type = UIEvents::PointerTypes::Mouse;
pointer_event_init.view = window_proxy;
@ -2793,7 +2795,7 @@ void Document::set_hovered_node(GC::Ptr<Node> node, Optional<HoverEventData> hov
mark_mouse_transition_event_as_trusted_if_needed(pointer_event, hover_event_data);
target.node->dispatch_event(pointer_event);
Bindings::MouseEventInit mouse_event_init {};
mouse_event_init.related_target = GC::Root<DOM::EventTarget> { old_hovered_node.ptr() };
mouse_event_init.related_target = old_hovered_node;
if (hover_event_data.has_value())
populate_mouse_event_init_from_hover_event_data(mouse_event_init, *hover_event_data, window_proxy);
auto mouse_event = UIEvents::MouseEvent::create(realm(), UIEvents::EventNames::mouseenter, mouse_event_init, page_offset.x().to_double(), page_offset.y().to_double(), offset.x().to_double(), offset.y().to_double());
@ -3076,7 +3078,7 @@ WebIDL::ExceptionOr<GC::Ref<Event>> Document::create_event(StringView interface)
} else if (interface.equals_ignoring_ascii_case("keyboardevent"sv)) {
event = UIEvents::KeyboardEvent::create(realm, String {});
} else if (interface.equals_ignoring_ascii_case("messageevent"sv)) {
event = HTML::MessageEvent::create(realm, String {});
event = HTML::MessageEvent::create(realm, FlyString {}, Bindings::MessageEventInit {});
} else if (interface.equals_ignoring_ascii_case("mouseevent"sv)
|| interface.equals_ignoring_ascii_case("mouseevents"sv)) {
event = UIEvents::MouseEvent::create(realm, FlyString {});
@ -3209,8 +3211,8 @@ WebIDL::ExceptionOr<GC::Ref<Node>> Document::import_node(GC::Ref<Node> node, Var
subtree = !options.self_only;
// 2. If options["customElementRegistry"] exists, then set registry to it.
if (options.custom_element_registry.has_value())
registry = options.custom_element_registry->ptr();
if (options.custom_element_registry)
registry = options.custom_element_registry;
// 3. If registrys is scoped is false and registry is not thiss custom element registry, then throw a
// "NotSupportedError" DOMException.

View file

@ -386,7 +386,7 @@ GC::Ptr<Attr> Element::get_attribute_node_ns(Optional<FlyString> const& namespac
}
// https://dom.spec.whatwg.org/#dom-element-setattribute
WebIDL::ExceptionOr<void> Element::set_attribute_for_bindings(FlyString qualified_name, Variant<GC::Root<TrustedTypes::TrustedHTML>, GC::Root<TrustedTypes::TrustedScript>, GC::Root<TrustedTypes::TrustedScriptURL>, Utf16String> const& value)
WebIDL::ExceptionOr<void> Element::set_attribute_for_bindings(FlyString qualified_name, Variant<GC::Ref<TrustedTypes::TrustedHTML>, GC::Ref<TrustedTypes::TrustedScript>, GC::Ref<TrustedTypes::TrustedScriptURL>, Utf16String> const& value)
{
// 1. If qualifiedName is not a valid attribute local name, then throw an "InvalidCharacterError" DOMException.
if (!is_valid_attribute_local_name(qualified_name))
@ -421,12 +421,12 @@ WebIDL::ExceptionOr<void> Element::set_attribute_for_bindings(FlyString qualifie
}
// https://dom.spec.whatwg.org/#dom-element-setattribute
WebIDL::ExceptionOr<void> Element::set_attribute_for_bindings(FlyString qualified_name, Variant<GC::Root<TrustedTypes::TrustedHTML>, GC::Root<TrustedTypes::TrustedScript>, GC::Root<TrustedTypes::TrustedScriptURL>, String> const& value)
WebIDL::ExceptionOr<void> Element::set_attribute_for_bindings(FlyString qualified_name, Variant<GC::Ref<TrustedTypes::TrustedHTML>, GC::Ref<TrustedTypes::TrustedScript>, GC::Ref<TrustedTypes::TrustedScriptURL>, String> const& value)
{
return set_attribute_for_bindings(move(qualified_name),
value.visit(
[](auto const& trusted_type) -> Variant<GC::Root<TrustedTypes::TrustedHTML>, GC::Root<TrustedTypes::TrustedScript>, GC::Root<TrustedTypes::TrustedScriptURL>, Utf16String> { return trusted_type; },
[](String const& string) -> Variant<GC::Root<TrustedTypes::TrustedHTML>, GC::Root<TrustedTypes::TrustedScript>, GC::Root<TrustedTypes::TrustedScriptURL>, Utf16String> { return Utf16String::from_utf8(string); }));
[](auto const& trusted_type) -> Variant<GC::Ref<TrustedTypes::TrustedHTML>, GC::Ref<TrustedTypes::TrustedScript>, GC::Ref<TrustedTypes::TrustedScriptURL>, Utf16String> { return trusted_type; },
[](String const& string) -> Variant<GC::Ref<TrustedTypes::TrustedHTML>, GC::Ref<TrustedTypes::TrustedScript>, GC::Ref<TrustedTypes::TrustedScriptURL>, Utf16String> { return Utf16String::from_utf8(string); }));
}
// https://dom.spec.whatwg.org/#valid-namespace-prefix
@ -540,7 +540,7 @@ WebIDL::ExceptionOr<QualifiedName> validate_and_extract(JS::Realm& realm, Option
}
// https://dom.spec.whatwg.org/#dom-element-setattributens
WebIDL::ExceptionOr<void> Element::set_attribute_ns_for_bindings(Optional<FlyString> const& namespace_, FlyString const& qualified_name, Variant<GC::Root<TrustedTypes::TrustedHTML>, GC::Root<TrustedTypes::TrustedScript>, GC::Root<TrustedTypes::TrustedScriptURL>, Utf16String> const& value)
WebIDL::ExceptionOr<void> Element::set_attribute_ns_for_bindings(Optional<FlyString> const& namespace_, FlyString const& qualified_name, Variant<GC::Ref<TrustedTypes::TrustedHTML>, GC::Ref<TrustedTypes::TrustedScript>, GC::Ref<TrustedTypes::TrustedScriptURL>, Utf16String> const& value)
{
// 1. Let (namespace, prefix, localName) be the result of validating and extracting namespace and qualifiedName given "attribute".
auto extracted_qualified_name = TRY(validate_and_extract(realm(), namespace_, qualified_name, ValidationContext::Attribute));

View file

@ -129,10 +129,10 @@ public:
Optional<String> lang() const;
void invalidate_lang_value();
WebIDL::ExceptionOr<void> set_attribute_for_bindings(FlyString qualified_name, Variant<GC::Root<TrustedTypes::TrustedHTML>, GC::Root<TrustedTypes::TrustedScript>, GC::Root<TrustedTypes::TrustedScriptURL>, Utf16String> const& value);
WebIDL::ExceptionOr<void> set_attribute_for_bindings(FlyString qualified_name, Variant<GC::Root<TrustedTypes::TrustedHTML>, GC::Root<TrustedTypes::TrustedScript>, GC::Root<TrustedTypes::TrustedScriptURL>, String> const& value);
WebIDL::ExceptionOr<void> set_attribute_for_bindings(FlyString qualified_name, Variant<GC::Ref<TrustedTypes::TrustedHTML>, GC::Ref<TrustedTypes::TrustedScript>, GC::Ref<TrustedTypes::TrustedScriptURL>, Utf16String> const& value);
WebIDL::ExceptionOr<void> set_attribute_for_bindings(FlyString qualified_name, Variant<GC::Ref<TrustedTypes::TrustedHTML>, GC::Ref<TrustedTypes::TrustedScript>, GC::Ref<TrustedTypes::TrustedScriptURL>, String> const& value);
WebIDL::ExceptionOr<void> set_attribute_ns_for_bindings(Optional<FlyString> const& namespace_, FlyString const& qualified_name, Variant<GC::Root<TrustedTypes::TrustedHTML>, GC::Root<TrustedTypes::TrustedScript>, GC::Root<TrustedTypes::TrustedScriptURL>, Utf16String> const& value);
WebIDL::ExceptionOr<void> set_attribute_ns_for_bindings(Optional<FlyString> const& namespace_, FlyString const& qualified_name, Variant<GC::Ref<TrustedTypes::TrustedHTML>, GC::Ref<TrustedTypes::TrustedScript>, GC::Ref<TrustedTypes::TrustedScriptURL>, Utf16String> const& value);
void set_attribute_value(FlyString const& local_name, String const& value, Optional<FlyString> const& prefix = {}, Optional<FlyString> const& namespace_ = {});
WebIDL::ExceptionOr<GC::Ptr<Attr>> set_attribute_node_for_bindings(Attr&);
WebIDL::ExceptionOr<GC::Ptr<Attr>> set_attribute_node_ns_for_bindings(Attr&);

View file

@ -158,8 +158,8 @@ static FlattenedAddEventListenerOptions flatten_add_event_listener_options(Varia
passive = add_event_listener_options.passive;
// 3. If options["signal"] exists, then set signal to options["signal"].
if (add_event_listener_options.signal.has_value())
signal = add_event_listener_options.signal->ptr();
if (add_event_listener_options.signal)
signal = add_event_listener_options.signal;
}
// 5. Return capture, passive, once, and signal.

View file

@ -16,12 +16,12 @@
namespace Web::DOM {
// https://dom.spec.whatwg.org/#convert-nodes-into-a-node
WebIDL::ExceptionOr<GC::Ref<Node>> convert_nodes_to_single_node(Vector<Variant<GC::Root<Node>, Utf16String>> const& nodes, Document& document)
WebIDL::ExceptionOr<GC::Ref<Node>> convert_nodes_to_single_node(ReadonlySpan<Variant<GC::Ref<Node>, Utf16String>> nodes, Document& document)
{
// 1. Replace each string of nodes with a new Text node whose data is the string and node document is document.
auto potentially_convert_string_to_text_node = [&document](Variant<GC::Root<Node>, Utf16String> const& node) -> GC::Ref<Node> {
if (node.has<GC::Root<Node>>())
return *node.get<GC::Root<Node>>();
auto potentially_convert_string_to_text_node = [&document](Variant<GC::Ref<Node>, Utf16String> const& node) -> GC::Ref<Node> {
if (node.has<GC::Ref<Node>>())
return node.get<GC::Ref<Node>>();
return document.realm().create<Text>(document, node.get<Utf16String>());
};

View file

@ -13,6 +13,6 @@
namespace Web::DOM {
WebIDL::ExceptionOr<GC::Ref<Node>> convert_nodes_to_single_node(Vector<Variant<GC::Root<Node>, Utf16String>> const& nodes, DOM::Document& document);
WebIDL::ExceptionOr<GC::Ref<Node>> convert_nodes_to_single_node(ReadonlySpan<Variant<GC::Ref<Node>, Utf16String>> nodes, DOM::Document& document);
}

View file

@ -187,7 +187,7 @@ GC::Ref<HTMLCollection> ParentNode::get_elements_by_tag_name_ns(Optional<FlyStri
}
// https://dom.spec.whatwg.org/#dom-parentnode-prepend
WebIDL::ExceptionOr<void> ParentNode::prepend(Vector<Variant<GC::Root<Node>, Utf16String>> const& nodes)
WebIDL::ExceptionOr<void> ParentNode::prepend(ReadonlySpan<Variant<GC::Ref<Node>, Utf16String>> const& nodes)
{
// 1. Let node be the result of converting nodes into a node given nodes and thiss node document.
auto node = TRY(convert_nodes_to_single_node(nodes, document()));
@ -198,7 +198,7 @@ WebIDL::ExceptionOr<void> ParentNode::prepend(Vector<Variant<GC::Root<Node>, Utf
return {};
}
WebIDL::ExceptionOr<void> ParentNode::append(Vector<Variant<GC::Root<Node>, Utf16String>> const& nodes)
WebIDL::ExceptionOr<void> ParentNode::append(ReadonlySpan<Variant<GC::Ref<Node>, Utf16String>> const& nodes)
{
// 1. Let node be the result of converting nodes into a node given nodes and thiss node document.
auto node = TRY(convert_nodes_to_single_node(nodes, document()));
@ -209,7 +209,7 @@ WebIDL::ExceptionOr<void> ParentNode::append(Vector<Variant<GC::Root<Node>, Utf1
return {};
}
WebIDL::ExceptionOr<void> ParentNode::replace_children(Vector<Variant<GC::Root<Node>, Utf16String>> const& nodes)
WebIDL::ExceptionOr<void> ParentNode::replace_children(ReadonlySpan<Variant<GC::Ref<Node>, Utf16String>> const& nodes)
{
// 1. Let node be the result of converting nodes into a node given nodes and thiss node document.
auto node = TRY(convert_nodes_to_single_node(nodes, document()));

View file

@ -33,9 +33,9 @@ public:
GC::Ref<HTMLCollection> get_elements_by_tag_name(FlyString const&);
GC::Ref<HTMLCollection> get_elements_by_tag_name_ns(Optional<FlyString>, FlyString const&);
WebIDL::ExceptionOr<void> prepend(Vector<Variant<GC::Root<Node>, Utf16String>> const& nodes);
WebIDL::ExceptionOr<void> append(Vector<Variant<GC::Root<Node>, Utf16String>> const& nodes);
WebIDL::ExceptionOr<void> replace_children(Vector<Variant<GC::Root<Node>, Utf16String>> const& nodes);
WebIDL::ExceptionOr<void> prepend(ReadonlySpan<Variant<GC::Ref<Node>, Utf16String>> const& nodes);
WebIDL::ExceptionOr<void> append(ReadonlySpan<Variant<GC::Ref<Node>, Utf16String>> const& nodes);
WebIDL::ExceptionOr<void> replace_children(ReadonlySpan<Variant<GC::Ref<Node>, Utf16String>> const& nodes);
WebIDL::ExceptionOr<void> move_before(GC::Ref<Node> node, GC::Ptr<Node> child);
GC::Ref<HTMLCollection> get_elements_by_class_name(StringView);

View file

@ -467,13 +467,13 @@ Optional<URL::URL> parse(StringView input, Optional<URL::URL const&> base_url, O
if (blob_url_entry.has_value()) {
url->set_blob_url_entry(URL::BlobURLEntry {
.object = blob_url_entry->object.visit(
[](GC::Root<FileAPI::Blob> const& blob) -> URL::BlobURLEntry::Object {
[](GC::Ref<FileAPI::Blob> const& blob) -> URL::BlobURLEntry::Object {
return URL::BlobURLEntry::Blob {
.type = blob->type(),
.data = MUST(ByteBuffer::copy(blob->raw_bytes())),
};
},
[](GC::Root<MediaSourceExtensions::MediaSource> const&) -> URL::BlobURLEntry::Object { return URL::BlobURLEntry::MediaSource {}; }),
[](GC::Ref<MediaSourceExtensions::MediaSource> const&) -> URL::BlobURLEntry::Object { return URL::BlobURLEntry::MediaSource {}; }),
.environment { .origin = blob_url_entry->environment->origin() },
});
}

View file

@ -63,13 +63,13 @@ void TextDecoder::initialize(JS::Realm& realm)
}
// https://encoding.spec.whatwg.org/#dom-textdecoder-decode
WebIDL::ExceptionOr<String> TextDecoder::decode(Optional<GC::Root<WebIDL::BufferSource>> const& input, Optional<Bindings::TextDecodeOptions> const&) const
WebIDL::ExceptionOr<String> TextDecoder::decode(GC::Ptr<WebIDL::BufferSource> input, Optional<Bindings::TextDecodeOptions> const&) const
{
if (!input.has_value())
if (!input)
return TRY_OR_THROW_OOM(vm(), m_decoder.to_utf8({}));
// FIXME: Implement the streaming stuff.
auto data_buffer_or_error = WebIDL::get_buffer_source_copy(*input.value()->raw_object());
auto data_buffer_or_error = WebIDL::get_buffer_source_copy(*input->raw_object());
if (data_buffer_or_error.is_error())
return WebIDL::OperationError::create(realm(), "Failed to copy bytes from ArrayBuffer"_utf16);
auto& data_buffer = data_buffer_or_error.value();

View file

@ -30,7 +30,7 @@ public:
virtual ~TextDecoder() override;
WebIDL::ExceptionOr<String> decode(Optional<GC::Root<WebIDL::BufferSource>> const&, Optional<Bindings::TextDecodeOptions> const& options = {}) const;
WebIDL::ExceptionOr<String> decode(GC::Ptr<WebIDL::BufferSource>, Optional<Bindings::TextDecodeOptions> const& options = {}) const;
private:
TextDecoder(JS::Realm&, TextCodec::Decoder&, FlyString encoding, ErrorMode error_mode, bool ignore_bom);

View file

@ -444,10 +444,11 @@ MultipartParsingErrorOr<GC::ConservativeVector<XHR::FormDataEntry>> parse_multip
}
// 3. Let value be a new File object with name filename, type contentType, and body body.
auto blob = FileAPI::Blob::create(realm, MUST(ByteBuffer::copy(body.bytes())), header.content_type.release_value());
auto content_type = header.content_type.release_value();
auto blob = FileAPI::Blob::create(realm, MUST(ByteBuffer::copy(body.bytes())), content_type);
Bindings::FilePropertyBag options {};
options.type = blob->type();
value = MUST(FileAPI::File::create(realm, { GC::make_root(blob) }, header.filename.release_value(), move(options)));
options.type = move(content_type);
value = MUST(FileAPI::File::create(realm, { { blob } }, header.filename.release_value(), move(options)));
}
// 11. Otherwise:
else {

View file

@ -26,7 +26,7 @@ namespace Web::Fetch {
Infrastructure::BodyWithType safely_extract_body(JS::Realm& realm, BodyInitOrReadableBytes const& object)
{
// 1. If object is a ReadableStream object, then:
if (auto const* stream = object.get_pointer<GC::Root<Streams::ReadableStream>>()) {
if (auto const* stream = object.get_pointer<GC::Ref<Streams::ReadableStream>>()) {
// 1. Assert: object is neither disturbed nor locked.
VERIFY(!((*stream)->is_disturbed() || (*stream)->is_locked()));
}
@ -46,12 +46,12 @@ WebIDL::ExceptionOr<Infrastructure::BodyWithType> extract_body(JS::Realm& realm,
GC::Ptr<Streams::ReadableStream> stream;
// 2. If object is a ReadableStream object, then set stream to object.
if (auto const* stream_handle = object.get_pointer<GC::Root<Streams::ReadableStream>>()) {
stream = const_cast<Streams::ReadableStream*>(stream_handle->cell());
if (auto const* maybe_stream = object.get_pointer<GC::Ref<Streams::ReadableStream>>()) {
stream = *maybe_stream;
}
// 3. Otherwise, if object is a Blob object, set stream to the result of running objects get stream.
else if (auto const* blob_handle = object.get_pointer<GC::Root<FileAPI::Blob>>()) {
stream = blob_handle->cell()->get_stream();
else if (auto* blob = object.get_pointer<GC::Ref<FileAPI::Blob>>()) {
stream = (*blob)->get_stream();
}
// 4. Otherwise, set stream to a new ReadableStream object, and set up stream with byte reading support.
else {
@ -76,7 +76,7 @@ WebIDL::ExceptionOr<Infrastructure::BodyWithType> extract_body(JS::Realm& realm,
// 10. Switch on object.
TRY(object.visit(
[&](GC::Root<FileAPI::Blob> const& blob) -> WebIDL::ExceptionOr<void> {
[&](GC::Ref<FileAPI::Blob> blob) -> WebIDL::ExceptionOr<void> {
// Set source to object.
source = blob;
// Set length to objects size.
@ -96,12 +96,12 @@ WebIDL::ExceptionOr<Infrastructure::BodyWithType> extract_body(JS::Realm& realm,
source = bytes;
return {};
},
[&](GC::Root<WebIDL::BufferSource> const& buffer_source) -> WebIDL::ExceptionOr<void> {
[&](GC::Ref<WebIDL::BufferSource> buffer_source) -> WebIDL::ExceptionOr<void> {
// Set source to a copy of the bytes held by object.
source = MUST(WebIDL::get_buffer_source_copy(*buffer_source->raw_object()));
return {};
},
[&](GC::Root<XHR::FormData> const& form_data) -> WebIDL::ExceptionOr<void> {
[&](GC::Ref<XHR::FormData> form_data) -> WebIDL::ExceptionOr<void> {
// Set action to this step: run the multipart/form-data encoding algorithm, with objects entry list and UTF-8.
auto serialized_form_data = MUST(HTML::serialize_to_multipart_form_data(form_data->entry_list()));
// Set source to object.
@ -111,7 +111,7 @@ WebIDL::ExceptionOr<Infrastructure::BodyWithType> extract_body(JS::Realm& realm,
type = ByteString::formatted("multipart/form-data; boundary={}", serialized_form_data.boundary);
return {};
},
[&](GC::Root<DOMURL::URLSearchParams> const& url_search_params) -> WebIDL::ExceptionOr<void> {
[&](GC::Ref<DOMURL::URLSearchParams> url_search_params) -> WebIDL::ExceptionOr<void> {
// Set source to the result of running the application/x-www-form-urlencoded serializer with objects list.
auto search_params_string = url_search_params->to_string();
source = MUST(ByteBuffer::copy(search_params_string.bytes()));
@ -127,7 +127,7 @@ WebIDL::ExceptionOr<Infrastructure::BodyWithType> extract_body(JS::Realm& realm,
type = "text/plain;charset=UTF-8"sv;
return {};
},
[&](GC::Root<Streams::ReadableStream> const& stream) -> WebIDL::ExceptionOr<void> {
[&](GC::Ref<Streams::ReadableStream> stream) -> WebIDL::ExceptionOr<void> {
// If keepalive is true, then throw a TypeError.
if (keepalive)
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Cannot extract body from stream when keepalive is set"sv };

View file

@ -16,10 +16,10 @@
namespace Web::Fetch {
// https://fetch.spec.whatwg.org/#bodyinit
using BodyInit = Variant<GC::Root<Streams::ReadableStream>, GC::Root<FileAPI::Blob>, GC::Root<WebIDL::BufferSource>, GC::Root<XHR::FormData>, GC::Root<DOMURL::URLSearchParams>, String>;
using NullableBodyInit = Variant<GC::Root<Streams::ReadableStream>, GC::Root<FileAPI::Blob>, GC::Root<WebIDL::BufferSource>, GC::Root<XHR::FormData>, GC::Root<DOMURL::URLSearchParams>, String, Empty>;
using BodyInit = Variant<GC::Ref<Streams::ReadableStream>, GC::Ref<FileAPI::Blob>, GC::Ref<WebIDL::BufferSource>, GC::Ref<XHR::FormData>, GC::Ref<DOMURL::URLSearchParams>, String>;
using NullableBodyInit = Variant<GC::Ref<Streams::ReadableStream>, GC::Ref<FileAPI::Blob>, GC::Ref<WebIDL::BufferSource>, GC::Ref<XHR::FormData>, GC::Ref<DOMURL::URLSearchParams>, String, Empty>;
using BodyInitOrReadableBytes = Variant<GC::Root<Streams::ReadableStream>, GC::Root<FileAPI::Blob>, GC::Root<WebIDL::BufferSource>, GC::Root<XHR::FormData>, GC::Root<DOMURL::URLSearchParams>, String, ReadonlyBytes, Core::ImmutableBytes>;
using BodyInitOrReadableBytes = Variant<GC::Ref<Streams::ReadableStream>, GC::Ref<FileAPI::Blob>, GC::Ref<WebIDL::BufferSource>, GC::Ref<XHR::FormData>, GC::Ref<DOMURL::URLSearchParams>, String, ReadonlyBytes, Core::ImmutableBytes>;
WEB_API Infrastructure::BodyWithType safely_extract_body(JS::Realm&, BodyInitOrReadableBytes const&);
WEB_API WebIDL::ExceptionOr<Infrastructure::BodyWithType> extract_body(JS::Realm&, BodyInitOrReadableBytes const&, bool keepalive = false);

View file

@ -1546,7 +1546,7 @@ GC::Ptr<PendingResponse> http_redirect_fetch(JS::Realm& realm, Infrastructure::F
auto converted_source = source.visit(
[](ByteBuffer const& byte_buffer) -> BodyInitOrReadableBytes { return byte_buffer.bytes(); },
[](Core::ImmutableBytes const& bytes) -> BodyInitOrReadableBytes { return bytes; },
[](GC::Ref<FileAPI::Blob> const& blob) -> BodyInitOrReadableBytes { return GC::make_root(blob); },
[](GC::Ref<FileAPI::Blob> blob) -> BodyInitOrReadableBytes { return blob; },
[](Empty) -> BodyInitOrReadableBytes { VERIFY_NOT_REACHED(); });
auto [body, _] = safely_extract_body(realm, converted_source);
request->set_body(body);
@ -2005,7 +2005,7 @@ GC::Ref<PendingResponse> http_network_or_cache_fetch(JS::Realm& realm, Infrastru
auto converted_source = source.visit(
[](ByteBuffer const& byte_buffer) -> BodyInitOrReadableBytes { return byte_buffer.bytes(); },
[](Core::ImmutableBytes const& bytes) -> BodyInitOrReadableBytes { return bytes; },
[](GC::Ref<FileAPI::Blob> const& blob) -> BodyInitOrReadableBytes { return GC::make_root(blob); },
[](GC::Ref<FileAPI::Blob> blob) -> BodyInitOrReadableBytes { return blob; },
[](Empty) -> BodyInitOrReadableBytes { VERIFY_NOT_REACHED(); });
auto [body, _] = safely_extract_body(realm, converted_source);
request->set_body(body);

View file

@ -19,26 +19,12 @@ namespace Web::Fetch::Infrastructure {
GC_DEFINE_ALLOCATOR(Body);
static Body::SourceTypeInternal to_source_type_internal(Body::SourceType&& source_type)
{
return source_type.visit(
[](Empty) -> Body::SourceTypeInternal { return Empty {}; },
[](ByteBuffer& buffer) -> Body::SourceTypeInternal { return move(buffer); },
[](Core::ImmutableBytes& bytes) -> Body::SourceTypeInternal { return move(bytes); },
[](GC::Root<FileAPI::Blob> const& blob) -> Body::SourceTypeInternal { return GC::Ref { *blob }; });
}
GC::Ref<Body> Body::create(JS::VM& vm, GC::Ref<Streams::ReadableStream> stream)
{
return vm.heap().allocate<Body>(stream);
}
GC::Ref<Body> Body::create(JS::VM& vm, GC::Ref<Streams::ReadableStream> stream, SourceType source, Optional<u64> length)
{
return create(vm, stream, to_source_type_internal(move(source)), length);
}
GC::Ref<Body> Body::create(JS::VM& vm, GC::Ref<Streams::ReadableStream> stream, SourceTypeInternal source, Optional<u64> length)
{
return vm.heap().allocate<Body>(stream, source, length);
}
@ -48,7 +34,7 @@ Body::Body(GC::Ref<Streams::ReadableStream> stream)
{
}
Body::Body(GC::Ref<Streams::ReadableStream> stream, SourceTypeInternal source, Optional<u64> length)
Body::Body(GC::Ref<Streams::ReadableStream> stream, SourceType source, Optional<u64> length)
: m_stream(stream)
, m_source(move(source))
, m_length(move(length))

View file

@ -31,8 +31,7 @@ class WEB_API Body final : public JS::Cell {
GC_DECLARE_ALLOCATOR(Body);
public:
using SourceType = Variant<Empty, ByteBuffer, Core::ImmutableBytes, GC::Root<FileAPI::Blob>>;
using SourceTypeInternal = Variant<Empty, ByteBuffer, Core::ImmutableBytes, GC::Ref<FileAPI::Blob>>;
using SourceType = Variant<Empty, ByteBuffer, Core::ImmutableBytes, GC::Ref<FileAPI::Blob>>;
// processBody must be an algorithm accepting a byte sequence.
using ProcessBodyCallback = GC::Ref<GC::Function<void(ByteBuffer)>>;
// processBodyError must be an algorithm optionally accepting an exception.
@ -44,11 +43,10 @@ public:
[[nodiscard]] static GC::Ref<Body> create(JS::VM&, GC::Ref<Streams::ReadableStream>);
[[nodiscard]] static GC::Ref<Body> create(JS::VM&, GC::Ref<Streams::ReadableStream>, SourceType, Optional<u64>);
[[nodiscard]] static GC::Ref<Body> create(JS::VM&, GC::Ref<Streams::ReadableStream>, SourceTypeInternal, Optional<u64>);
[[nodiscard]] GC::Ref<Streams::ReadableStream> stream() const { return *m_stream; }
void set_stream(GC::Ref<Streams::ReadableStream> value) { m_stream = value; }
[[nodiscard]] SourceTypeInternal const& source() const { return m_source; }
[[nodiscard]] SourceType const& source() const { return m_source; }
void set_source(Core::ImmutableBytes, Optional<u64> length);
[[nodiscard]] Optional<u64> const& length() const { return m_length; }
@ -76,7 +74,7 @@ public:
private:
explicit Body(GC::Ref<Streams::ReadableStream>);
Body(GC::Ref<Streams::ReadableStream>, SourceTypeInternal, Optional<u64>);
Body(GC::Ref<Streams::ReadableStream>, SourceType, Optional<u64>);
// https://fetch.spec.whatwg.org/#concept-body-stream
// A stream (a ReadableStream object).
@ -84,7 +82,7 @@ private:
// https://fetch.spec.whatwg.org/#concept-body-source
// A source (null, a byte sequence, a Blob object, or a FormData object), initially null.
SourceTypeInternal m_source;
SourceType m_source;
// https://fetch.spec.whatwg.org/#concept-body-total-bytes
// A length (null or an integer), initially null.

View file

@ -160,13 +160,13 @@ WebIDL::ExceptionOr<GC::Ref<Request>> Request::construct_impl(JS::Realm& realm,
// 6. Otherwise:
else {
// 1. Assert: input is a Request object.
VERIFY(input.has<GC::Root<Request>>());
VERIFY(input.has<GC::Ref<Request>>());
// 2. Set request to inputs request.
input_request = input.get<GC::Root<Request>>()->request();
input_request = input.get<GC::Ref<Request>>()->request();
// 3. Set signal to inputs signal.
input_signal = input.get<GC::Root<Request>>()->signal();
input_signal = input.get<GC::Ref<Request>>()->signal();
}
// 7. Let origin be thiss relevant settings objects origin.
@ -402,7 +402,7 @@ WebIDL::ExceptionOr<GC::Ref<Request>> Request::construct_impl(JS::Realm& realm,
// 26. If init["signal"] exists, then set signal to it.
if (init.signal.has_value())
input_signal = *init.signal;
input_signal = init.signal->ptr();
// 27. If init["priority"] exists, then:
if (init.priority.has_value())
@ -414,7 +414,7 @@ WebIDL::ExceptionOr<GC::Ref<Request>> Request::construct_impl(JS::Realm& realm,
// 29. Let signals be « signal » if signal is non-null; otherwise « ».
auto& this_relevant_realm = HTML::relevant_realm(*request_object);
Vector<GC::Root<DOM::AbortSignal>> signals;
GC::RootVector<GC::Ref<DOM::AbortSignal>> signals;
if (input_signal != nullptr)
signals.append(*input_signal);
@ -464,8 +464,8 @@ WebIDL::ExceptionOr<GC::Ref<Request>> Request::construct_impl(JS::Realm& realm,
// 34. Let inputBody be inputs requests body if input is a Request object; otherwise null.
Optional<Infrastructure::Request::BodyType const&> input_body;
if (input.has<GC::Root<Request>>())
input_body = input.get<GC::Root<Request>>()->request()->body();
if (input.has<GC::Ref<Request>>())
input_body = input.get<GC::Ref<Request>>()->request()->body();
// 35. If either init["body"] exists and is non-null or inputBody is non-null, and requests method is `GET` or `HEAD`, then throw a TypeError.
if (((init.body.has_value() && !init.body->has<Empty>()) || (input_body.has_value() && !input_body.value().has<Empty>())) && request->method().is_one_of("GET"sv, "HEAD"sv))
@ -477,7 +477,7 @@ WebIDL::ExceptionOr<GC::Ref<Request>> Request::construct_impl(JS::Realm& realm,
// 37. If init["body"] exists and is non-null, then:
if (init.body.has_value() && !init.body->has<Empty>()) {
// 1. Let bodyWithType be the result of extracting init["body"], with keepalive set to request's keepalive.
auto body_with_type = TRY(extract_body(realm, init.body->downcast<GC::Root<Streams::ReadableStream>, GC::Root<FileAPI::Blob>, GC::Root<WebIDL::BufferSource>, GC::Root<XHR::FormData>, GC::Root<DOMURL::URLSearchParams>, String>(), request->keepalive()));
auto body_with_type = TRY(extract_body(realm, init.body->downcast<GC::Ref<Streams::ReadableStream>, GC::Ref<FileAPI::Blob>, GC::Ref<WebIDL::BufferSource>, GC::Ref<XHR::FormData>, GC::Ref<DOMURL::URLSearchParams>, String>(), request->keepalive()));
// 2. Set initBody to bodyWithTypes body.
init_body = body_with_type.body;
@ -514,7 +514,7 @@ WebIDL::ExceptionOr<GC::Ref<Request>> Request::construct_impl(JS::Realm& realm,
// 41. If initBody is null and inputBody is non-null, then:
if (!init_body.has_value() && input_body.has_value()) {
// 2. If input is unusable, then throw a TypeError.
if (input.has<GC::Root<Request>>() && input.get<GC::Root<Request>>()->is_unusable())
if (input.has<GC::Ref<Request>>() && input.get<GC::Ref<Request>>()->is_unusable())
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Request is unusable"sv };
// FIXME: 2. Set finalBody to the result of creating a proxy for inputBody.
@ -671,7 +671,7 @@ WebIDL::ExceptionOr<GC::Ref<Request>> Request::clone() const
// 4. Let clonedSignal be the result of creating a dependent abort signal from « thiss signal », using AbortSignal and thiss relevant realm.
auto& relevant_realm = HTML::relevant_realm(*this);
auto cloned_signal = TRY(DOM::AbortSignal::create_dependent_abort_signal(relevant_realm, { m_signal }));
auto cloned_signal = TRY(DOM::AbortSignal::create_dependent_abort_signal(relevant_realm, { { *m_signal } }));
// 5. Let clonedRequestObject be the result of creating a Request object, given clonedRequest, thiss headerss guard, clonedSignal and thiss relevant realm.
auto cloned_request_object = Request::create(relevant_realm, cloned_request, m_headers->guard(), cloned_signal);

View file

@ -20,7 +20,7 @@
namespace Web::Fetch {
// https://fetch.spec.whatwg.org/#requestinfo
using RequestInfo = Variant<GC::Root<Request>, String>;
using RequestInfo = Variant<GC::Ref<Request>, String>;
// https://fetch.spec.whatwg.org/#request
class Request final

View file

@ -156,7 +156,7 @@ WebIDL::ExceptionOr<GC::Ref<Response>> Response::construct_impl(JS::Realm& realm
// 4. If body is non-null, then set bodyWithType to the result of extracting body.
if (!body.has<Empty>())
body_with_type = TRY(extract_body(realm, body.downcast<GC::Root<Streams::ReadableStream>, GC::Root<FileAPI::Blob>, GC::Root<WebIDL::BufferSource>, GC::Root<XHR::FormData>, GC::Root<DOMURL::URLSearchParams>, String>()));
body_with_type = TRY(extract_body(realm, body.downcast<GC::Ref<Streams::ReadableStream>, GC::Ref<FileAPI::Blob>, GC::Ref<WebIDL::BufferSource>, GC::Ref<XHR::FormData>, GC::Ref<DOMURL::URLSearchParams>, String>()));
// 5. Perform initialize a response given this, init, and bodyWithType.
TRY(response_object->initialize_response(init, body_with_type));

View file

@ -107,12 +107,12 @@ ErrorOr<ByteBuffer> process_blob_parts(BlobParts const& blob_parts, Optional<Bin
return bytes.try_append(s.bytes());
},
// 2. If element is a BufferSource, get a copy of the bytes held by the buffer source, and append those bytes to bytes.
[&](GC::Root<WebIDL::BufferSource> const& buffer_source) -> ErrorOr<void> {
[&](GC::Ref<WebIDL::BufferSource> const& buffer_source) -> ErrorOr<void> {
auto data_buffer = TRY(WebIDL::get_buffer_source_copy(*buffer_source->raw_object()));
return bytes.try_append(data_buffer.bytes());
},
// 3. If element is a Blob, append the bytes it represents to bytes.
[&](GC::Root<Blob> const& blob) -> ErrorOr<void> {
[&](GC::Ref<Blob> const& blob) -> ErrorOr<void> {
return bytes.try_append(blob->raw_bytes());
}));
}
@ -223,7 +223,9 @@ GC::Ref<Blob> Blob::create(JS::Realm& realm, Optional<BlobPartsOrByteBuffer> con
WebIDL::ExceptionOr<GC::Ref<Blob>> Blob::construct_impl(JS::Realm& realm, Optional<BlobParts> const& blob_parts, Optional<Bindings::BlobPropertyBag> const& options)
{
return create(realm, blob_parts.has_value() ? blob_parts.value() : Optional<BlobPartsOrByteBuffer> {}, options);
if (blob_parts.has_value())
return create(realm, BlobPartsOrByteBuffer { blob_parts.value() }, options);
return create(realm, {}, options);
}
// https://w3c.github.io/FileAPI/#dfn-slice

View file

@ -17,8 +17,8 @@
namespace Web::FileAPI {
using BlobPart = Variant<GC::Root<WebIDL::BufferSource>, GC::Root<Blob>, String>;
using BlobParts = Vector<BlobPart>;
using BlobPart = Variant<GC::Ref<WebIDL::BufferSource>, GC::Ref<Blob>, String>;
using BlobParts = GC::ConservativeVector<BlobPart>;
using BlobPartsOrByteBuffer = Variant<BlobParts, ByteBuffer>;
[[nodiscard]] ErrorOr<String> convert_line_endings_to_native(StringView string);

View file

@ -20,7 +20,7 @@ namespace Web::FileAPI {
BlobURLStore& blob_url_store()
{
static HashMap<String, BlobURLEntry> store;
static GC::ConservativeHashMap<String, BlobURLEntry> store;
return store;
}

View file

@ -6,8 +6,8 @@
#pragma once
#include <AK/HashMap.h>
#include <AK/String.h>
#include <LibGC/ConservativeHashMap.h>
#include <LibGC/Ptr.h>
#include <LibGC/Root.h>
#include <LibURL/URL.h>
@ -17,14 +17,14 @@ namespace Web::FileAPI {
// https://w3c.github.io/FileAPI/#blob-url-entry
struct BlobURLEntry {
using Object = Variant<GC::Root<Blob>, GC::Root<MediaSourceExtensions::MediaSource>>;
using Object = Variant<GC::Ref<Blob>, GC::Ref<MediaSourceExtensions::MediaSource>>;
Object object;
GC::Root<HTML::EnvironmentSettingsObject> environment;
GC::Ref<HTML::EnvironmentSettingsObject> environment;
};
// https://w3c.github.io/FileAPI/#BlobURLStore
using BlobURLStore = HashMap<String, BlobURLEntry>;
using BlobURLStore = GC::ConservativeHashMap<String, BlobURLEntry>;
BlobURLStore& blob_url_store();
ErrorOr<Utf16String> generate_new_blob_url();

View file

@ -485,7 +485,7 @@ struct StyleSheetIdentifier;
struct TransitionProperties;
// https://drafts.css-houdini.org/css-typed-om-1/#typedefdef-cssnumberish
using CSSNumberish = Variant<double, GC::Root<CSSNumericValue>>;
using CSSNumberish = Variant<double, GC::Ref<CSSNumericValue>>;
using PaintOrderList = Array<PaintOrder, 3>;
using StyleValueVector = Vector<ValueComparingNonnullRefPtr<StyleValue const>>;
using StyleValueTuple = Vector<ValueComparingRefPtr<StyleValue const>>;

View file

@ -11,12 +11,14 @@
#include <LibWeb/Bindings/BroadcastChannel.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/Bindings/MainThreadVM.h>
#include <LibWeb/Bindings/MessageEvent.h>
#include <LibWeb/Bindings/PrincipalHostDefined.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/HTML/BroadcastChannel.h>
#include <LibWeb/HTML/BroadcastChannelMessage.h>
#include <LibWeb/HTML/EventNames.h>
#include <LibWeb/HTML/MessageEvent.h>
#include <LibWeb/HTML/MessagePort.h>
#include <LibWeb/HTML/StructuredSerialize.h>
#include <LibWeb/HTML/Window.h>
#include <LibWeb/HTML/WorkerGlobalScope.h>
@ -208,7 +210,7 @@ void BroadcastChannel::deliver_message_locally(BroadcastChannelMessage const& me
// origin initialized to sourceOrigin, and then abort these steps.
auto data_or_error = structured_deserialize(vm, message.serialized_message, target_realm);
if (data_or_error.is_exception()) {
Bindings::MessageEventInit event_init {};
Bindings::MessageEventInit event_init;
auto event = MessageEvent::create(target_realm, HTML::EventNames::messageerror, event_init, message.source_origin);
event->set_is_trusted(true);
destination->dispatch_event(event);
@ -217,7 +219,7 @@ void BroadcastChannel::deliver_message_locally(BroadcastChannelMessage const& me
// 4. Fire an event named message at destination, using MessageEvent, with the data attribute initialized to data and
// its origin initialized to sourceOrigin.
Bindings::MessageEventInit event_init {};
Bindings::MessageEventInit event_init;
event_init.data = data_or_error.release_value();
auto event = MessageEvent::create(target_realm, HTML::EventNames::message, event_init, message.source_origin);
event->set_is_trusted(true);

View file

@ -16,36 +16,36 @@ namespace Web::HTML {
Gfx::IntSize canvas_image_source_dimensions(CanvasImageSource const& image)
{
return image.visit(
[](GC::Root<HTMLImageElement> const& source) -> Gfx::IntSize {
[](GC::Ref<HTMLImageElement> source) -> Gfx::IntSize {
if (auto frame = source->current_image_frame(); frame.has_value())
return frame->size();
// FIXME: This is very janky and not correct.
return { source->width(), source->height() };
},
[](GC::Root<SVG::SVGImageElement> const& source) -> Gfx::IntSize {
[](GC::Ref<SVG::SVGImageElement> source) -> Gfx::IntSize {
if (auto decoded_image_frame = source->current_image_frame(); decoded_image_frame.has_value())
return decoded_image_frame->size();
// FIXME: This is very janky and not correct.
return { source->width()->anim_val()->value(), source->height()->anim_val()->value() };
},
[](GC::Root<HTMLCanvasElement> const& source) -> Gfx::IntSize {
[](GC::Ref<HTMLCanvasElement> source) -> Gfx::IntSize {
if (auto painting_surface = source->surface())
return painting_surface->size();
return { source->width(), source->height() };
},
[](GC::Root<ImageBitmap> const& source) -> Gfx::IntSize {
[](GC::Ref<ImageBitmap> source) -> Gfx::IntSize {
if (auto* bitmap = source->bitmap())
return bitmap->size();
return { source->width(), source->height() };
},
[](GC::Root<OffscreenCanvas> const& source) -> Gfx::IntSize {
[](GC::Ref<OffscreenCanvas> source) -> Gfx::IntSize {
if (auto bitmap = source->bitmap())
return bitmap->size();
return {};
},
[](GC::Root<HTMLVideoElement> const& source) -> Gfx::IntSize {
[](GC::Ref<HTMLVideoElement> source) -> Gfx::IntSize {
return { source->video_width(), source->video_height() };
});
}
@ -53,7 +53,7 @@ Gfx::IntSize canvas_image_source_dimensions(CanvasImageSource const& image)
Optional<Gfx::DecodedImageFrame> canvas_image_source_frame(CanvasImageSource const& image)
{
return image.visit(
[](OneOf<GC::Root<HTMLImageElement>, GC::Root<SVG::SVGImageElement>> auto const& element) -> Optional<Gfx::DecodedImageFrame> {
[](OneOf<GC::Ref<HTMLImageElement>, GC::Ref<SVG::SVGImageElement>> auto const& element) -> Optional<Gfx::DecodedImageFrame> {
auto image_data = element->decoded_image_data();
if (!image_data)
return {};
@ -66,20 +66,20 @@ Optional<Gfx::DecodedImageFrame> canvas_image_source_frame(CanvasImageSource con
return image_data->frame(0, size);
},
[](GC::Root<HTMLCanvasElement> const& canvas) -> Optional<Gfx::DecodedImageFrame> {
[](GC::Ref<HTMLCanvasElement> const& canvas) -> Optional<Gfx::DecodedImageFrame> {
canvas->present();
auto surface = canvas->surface();
if (!surface)
return Gfx::DecodedImageFrame { *canvas->get_bitmap_from_surface() };
return Gfx::DecodedImageFrame { *surface->snapshot_bitmap() };
},
[](OneOf<GC::Root<ImageBitmap>, GC::Root<OffscreenCanvas>> auto const& source) -> Optional<Gfx::DecodedImageFrame> {
[](OneOf<GC::Ref<ImageBitmap>, GC::Ref<OffscreenCanvas>> auto const& source) -> Optional<Gfx::DecodedImageFrame> {
auto bitmap = source->bitmap();
if (!bitmap)
return {};
return Gfx::DecodedImageFrame { *bitmap };
},
[](GC::Root<HTMLVideoElement> const& source) -> Optional<Gfx::DecodedImageFrame> {
[](GC::Ref<HTMLVideoElement> const& source) -> Optional<Gfx::DecodedImageFrame> {
return source->current_decoded_image_frame();
});
}

View file

@ -22,7 +22,7 @@ namespace Web::HTML {
// https://html.spec.whatwg.org/multipage/canvas.html#canvasimagesource
// NOTE: This is the Variant created by the IDL wrapper generator, and needs to be updated accordingly.
using CanvasImageSource = Variant<GC::Root<HTMLImageElement>, GC::Root<SVG::SVGImageElement>, GC::Root<HTMLCanvasElement>, GC::Root<ImageBitmap>, GC::Root<OffscreenCanvas>, GC::Root<HTMLVideoElement>>;
using CanvasImageSource = Variant<GC::Ref<HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTMLCanvasElement>, GC::Ref<ImageBitmap>, GC::Ref<OffscreenCanvas>, GC::Ref<HTMLVideoElement>>;
Gfx::IntSize canvas_image_source_dimensions(CanvasImageSource const&);
Optional<Gfx::DecodedImageFrame> canvas_image_source_frame(CanvasImageSource const&);

View file

@ -19,7 +19,7 @@ template<typename IncludingClass>
class CanvasFillStrokeStyles {
public:
~CanvasFillStrokeStyles() = default;
using FillOrStrokeStyleVariant = Variant<String, GC::Root<CanvasGradient>, GC::Root<CanvasPattern>>;
using FillOrStrokeStyleVariant = Variant<String, GC::Ref<CanvasGradient>, GC::Ref<CanvasPattern>>;
void set_fill_style(FillOrStrokeStyleVariant style);
FillOrStrokeStyleVariant fill_style() const;

View file

@ -59,7 +59,7 @@ public:
Optional<Gfx::Color> as_color() const;
Gfx::Color to_color_but_fixme_should_accept_any_paint_style() const;
using JsFillOrStrokeStyle = Variant<String, GC::Root<CanvasGradient>, GC::Root<CanvasPattern>>;
using JsFillOrStrokeStyle = Variant<String, GC::Ref<CanvasGradient>, GC::Ref<CanvasPattern>>;
JsFillOrStrokeStyle to_js_fill_or_stroke_style() const
{
@ -68,7 +68,7 @@ public:
return color.to_string(Gfx::Color::HTMLCompatibleSerialization::Yes);
},
[&](auto handle) -> JsFillOrStrokeStyle {
return GC::make_root(handle);
return handle;
});
}

View file

@ -911,7 +911,7 @@ WebIDL::ExceptionOr<CanvasImageSourceUsability> check_usability_of_image(CanvasI
// 1. Switch on image:
auto usability = TRY(image.visit(
// HTMLOrSVGImageElement
[](GC::Root<HTMLImageElement> const& image_element) -> WebIDL::ExceptionOr<Optional<CanvasImageSourceUsability>> {
[](GC::Ref<HTMLImageElement> image_element) -> WebIDL::ExceptionOr<Optional<CanvasImageSourceUsability>> {
// If image's current request's state is broken, then throw an "InvalidStateError" DOMException.
if (image_element->current_request().state() == HTML::ImageRequest::State::Broken)
return WebIDL::InvalidStateError::create(image_element->realm(), "Image element state is broken"_utf16);
@ -927,7 +927,7 @@ WebIDL::ExceptionOr<CanvasImageSourceUsability> check_usability_of_image(CanvasI
return Optional<CanvasImageSourceUsability> {};
},
// FIXME: Don't duplicate this for HTMLImageElement and SVGImageElement.
[](GC::Root<SVG::SVGImageElement> const& image_element) -> WebIDL::ExceptionOr<Optional<CanvasImageSourceUsability>> {
[](GC::Ref<SVG::SVGImageElement> image_element) -> WebIDL::ExceptionOr<Optional<CanvasImageSourceUsability>> {
// FIXME: If image's current request's state is broken, then throw an "InvalidStateError" DOMException.
// If image is not fully decodable, then return bad.
@ -941,7 +941,7 @@ WebIDL::ExceptionOr<CanvasImageSourceUsability> check_usability_of_image(CanvasI
return Optional<CanvasImageSourceUsability> {};
},
[](GC::Root<HTML::HTMLVideoElement> const& video_element) -> WebIDL::ExceptionOr<Optional<CanvasImageSourceUsability>> {
[](GC::Ref<HTML::HTMLVideoElement> video_element) -> WebIDL::ExceptionOr<Optional<CanvasImageSourceUsability>> {
// If image's readyState attribute is either HAVE_NOTHING or HAVE_METADATA, then return bad.
if (video_element->ready_state() == HTML::HTMLMediaElement::ReadyState::HaveNothing || video_element->ready_state() == HTML::HTMLMediaElement::ReadyState::HaveMetadata) {
return { CanvasImageSourceUsability::Bad };
@ -950,14 +950,14 @@ WebIDL::ExceptionOr<CanvasImageSourceUsability> check_usability_of_image(CanvasI
},
// OffscreenCanvas
[](GC::Root<OffscreenCanvas> const& offscreen_canvas) -> WebIDL::ExceptionOr<Optional<CanvasImageSourceUsability>> {
[](GC::Ref<OffscreenCanvas> offscreen_canvas) -> WebIDL::ExceptionOr<Optional<CanvasImageSourceUsability>> {
// If image has either a horizontal dimension or a vertical dimension equal to zero, then throw an "InvalidStateError" DOMException.
if (offscreen_canvas->width() == 0 || offscreen_canvas->height() == 0)
return WebIDL::InvalidStateError::create(offscreen_canvas->realm(), "OffscreenCanvas width or height is zero"_utf16);
return Optional<CanvasImageSourceUsability> {};
},
// HTMLCanvasElement
[](GC::Root<HTMLCanvasElement> const& canvas_element) -> WebIDL::ExceptionOr<Optional<CanvasImageSourceUsability>> {
[](GC::Ref<HTMLCanvasElement> canvas_element) -> WebIDL::ExceptionOr<Optional<CanvasImageSourceUsability>> {
// If image has either a horizontal dimension or a vertical dimension equal to zero, then throw an "InvalidStateError" DOMException.
if (canvas_element->width() == 0 || canvas_element->height() == 0)
return WebIDL::InvalidStateError::create(canvas_element->realm(), "Canvas width or height is zero"_utf16);
@ -966,7 +966,7 @@ WebIDL::ExceptionOr<CanvasImageSourceUsability> check_usability_of_image(CanvasI
// ImageBitmap
// FIXME: VideoFrame
[](GC::Root<ImageBitmap> const& image_bitmap) -> WebIDL::ExceptionOr<Optional<CanvasImageSourceUsability>> {
[](GC::Ref<ImageBitmap> image_bitmap) -> WebIDL::ExceptionOr<Optional<CanvasImageSourceUsability>> {
if (image_bitmap->is_detached())
return WebIDL::InvalidStateError::create(image_bitmap->realm(), "Image bitmap is detached"_utf16);
return Optional<CanvasImageSourceUsability> {};
@ -984,20 +984,20 @@ bool image_is_not_origin_clean(CanvasImageSource const& image)
// An object image is not origin-clean if, switching on image's type:
return image.visit(
// HTMLOrSVGImageElement
[](GC::Root<HTMLImageElement> const&) {
[](GC::Ref<HTMLImageElement>) {
// FIXME: image's current request's image data is CORS-cross-origin.
return false;
},
[](GC::Root<SVG::SVGImageElement> const&) {
[](GC::Ref<SVG::SVGImageElement>) {
// FIXME: image's current request's image data is CORS-cross-origin.
return false;
},
[](GC::Root<HTML::HTMLVideoElement> const&) {
[](GC::Ref<HTML::HTMLVideoElement>) {
// FIXME: image's media data is CORS-cross-origin.
return false;
},
// HTMLCanvasElement, ImageBitmap or OffscreenCanvas
[](OneOf<GC::Root<HTMLCanvasElement>, GC::Root<ImageBitmap>, GC::Root<OffscreenCanvas>> auto const&) {
[](OneOf<GC::Ref<HTMLCanvasElement>, GC::Ref<ImageBitmap>, GC::Ref<OffscreenCanvas>> auto const&) {
// FIXME: image's bitmap's origin-clean flag is false.
return false;
});

View file

@ -69,9 +69,7 @@ WebIDL::ExceptionOr<GC::Ref<CloseWatcher>> CloseWatcher::construct_impl(JS::Real
auto close_watcher = establish(window, GC::create_function(realm.heap(), [] { return true; }));
// 3. If options["signal"] exists, then:
if (options.signal.has_value()) {
auto signal = options.signal->ptr();
if (auto signal = options.signal) {
// 3.1 If options["signal"]'s aborted, then destroy closeWatcher.
if (signal->aborted()) {
close_watcher->destroy();

View file

@ -330,7 +330,7 @@ JS::ThrowCompletionOr<void> CustomElementRegistry::define(String const& name, We
}
// https://html.spec.whatwg.org/multipage/custom-elements.html#dom-customelementregistry-get
Variant<GC::Root<WebIDL::CallbackType>, Empty> CustomElementRegistry::get(String const& name) const
Variant<GC::Ref<WebIDL::CallbackType>, Empty> CustomElementRegistry::get(String const& name) const
{
// 1. If this's custom element definition set contains an item with name name, then return that item's constructor.
auto existing_definition_iterator = m_custom_element_definitions.find_if([&name](auto const& definition) {
@ -338,18 +338,18 @@ Variant<GC::Root<WebIDL::CallbackType>, Empty> CustomElementRegistry::get(String
});
if (!existing_definition_iterator.is_end())
return GC::make_root((*existing_definition_iterator)->constructor());
return GC::Ref { (*existing_definition_iterator)->constructor() };
// 2. Return undefined.
return Empty {};
}
// https://html.spec.whatwg.org/multipage/custom-elements.html#dom-customelementregistry-getname
Optional<String> CustomElementRegistry::get_name(GC::Root<WebIDL::CallbackType> const& constructor) const
Optional<String> CustomElementRegistry::get_name(GC::Ref<WebIDL::CallbackType> constructor) const
{
// 1. If this's custom element definition set contains an item with constructor constructor, then return that item's name.
auto existing_definition_iterator = m_custom_element_definitions.find_if([&constructor](auto const& definition) {
return definition->constructor().callback == constructor.cell()->callback;
return definition->constructor().callback == constructor->callback;
});
if (!existing_definition_iterator.is_end())

View file

@ -25,8 +25,8 @@ public:
virtual ~CustomElementRegistry() override;
JS::ThrowCompletionOr<void> define(String const& name, WebIDL::CallbackType* constructor, Bindings::ElementDefinitionOptions const&);
Variant<GC::Root<WebIDL::CallbackType>, Empty> get(String const& name) const;
Optional<String> get_name(GC::Root<WebIDL::CallbackType> const& constructor) const;
Variant<GC::Ref<WebIDL::CallbackType>, Empty> get(String const& name) const;
Optional<String> get_name(GC::Ref<WebIDL::CallbackType> constructor) const;
WebIDL::ExceptionOr<GC::Ref<WebIDL::Promise>> when_defined(String const& name);
void upgrade(GC::Ref<DOM::Node> root) const;
WebIDL::ExceptionOr<void> initialize_for_bindings(GC::Ref<DOM::Node> root);

View file

@ -255,7 +255,7 @@ GC::Ref<FileAPI::FileList> DataTransfer::files() const
Bindings::FilePropertyBag options {};
options.type = item.type_string;
auto file = MUST(FileAPI::File::create(realm, { GC::make_root(blob) }, file_name, move(options)));
auto file = MUST(FileAPI::File::create(realm, { { blob } }, file_name, move(options)));
files->add_file(file);
}

View file

@ -146,7 +146,9 @@ GC::Ptr<FileAPI::File> DataTransferItem::get_as_file() const
Bindings::FilePropertyBag options {};
options.type = item.type_string;
return MUST(FileAPI::File::create(realm, { GC::make_root(blob) }, file_name, move(options)));
FileAPI::BlobParts file_bits {};
file_bits.append(blob);
return MUST(FileAPI::File::create(realm, file_bits, file_name, move(options)));
}
// https://wicg.github.io/entries-api/#dom-datatransferitem-webkitgetasentry

View file

@ -58,7 +58,7 @@ WebIDL::ExceptionOr<void> DedicatedWorkerGlobalScope::post_message(JS::Value mes
}
// https://html.spec.whatwg.org/multipage/workers.html#dom-dedicatedworkerglobalscope-postmessage
WebIDL::ExceptionOr<void> DedicatedWorkerGlobalScope::post_message(JS::Value message, Vector<GC::Root<JS::Object>> const& transfer)
WebIDL::ExceptionOr<void> DedicatedWorkerGlobalScope::post_message(JS::Value message, GC::RootVector<GC::Ref<JS::Object>> const& transfer)
{
// The postMessage(message, transfer) and postMessage(message, options) methods on DedicatedWorkerGlobalScope objects act as if,
// when invoked, it immediately invoked the respective postMessage(message, transfer) and postMessage(message, options)

View file

@ -25,7 +25,7 @@ public:
virtual ~DedicatedWorkerGlobalScope() override;
WebIDL::ExceptionOr<void> post_message(JS::Value message, Bindings::StructuredSerializeOptions const&);
WebIDL::ExceptionOr<void> post_message(JS::Value message, Vector<GC::Root<JS::Object>> const& transfer);
WebIDL::ExceptionOr<void> post_message(JS::Value message, GC::RootVector<GC::Ref<JS::Object>> const& transfer);
void close();

View file

@ -60,13 +60,13 @@ WebIDL::ExceptionOr<void> ElementInternals::set_form_value(ElementInternalsFormV
// 3. Set target element's submission value to value if value is not a FormData object, or to a clone of value's entry list otherwise.
auto submission_value = value.visit(
[](GC::Root<FileAPI::File> const& file) -> FormAssociatedElement::FACESubmissionValue {
return GC::Ref { *file };
[](GC::Ref<FileAPI::File> file) -> FormAssociatedElement::FACESubmissionValue {
return file;
},
[](String const& string) -> FormAssociatedElement::FACESubmissionValue {
return string;
},
[](GC::Root<XHR::FormData> const& form_data) -> FormAssociatedElement::FACESubmissionValue {
[](GC::Ref<XHR::FormData> form_data) -> FormAssociatedElement::FACESubmissionValue {
return form_data->entry_list();
},
[](Empty const& empty) -> FormAssociatedElement::FACESubmissionValue {

View file

@ -27,7 +27,7 @@ public:
GC::Ptr<DOM::ShadowRoot> shadow_root() const;
using ElementInternalsFormValue = Variant<GC::Root<FileAPI::File>, String, GC::Root<XHR::FormData>, Empty>;
using ElementInternalsFormValue = Variant<GC::Ref<FileAPI::File>, String, GC::Ref<XHR::FormData>, Empty>;
WebIDL::ExceptionOr<void> set_form_value(ElementInternalsFormValue value, Optional<ElementInternalsFormValue> state);
WebIDL::ExceptionOr<GC::Ptr<HTMLFormElement>> form() const;

View file

@ -11,6 +11,7 @@
#include <LibJS/Runtime/VM.h>
#include <LibWeb/Bindings/EventSource.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/Bindings/MessageEvent.h>
#include <LibWeb/DOM/Event.h>
#include <LibWeb/Fetch/Fetching/Fetching.h>
#include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h>
@ -23,6 +24,7 @@
#include <LibWeb/HTML/EventNames.h>
#include <LibWeb/HTML/EventSource.h>
#include <LibWeb/HTML/MessageEvent.h>
#include <LibWeb/HTML/MessagePort.h>
#include <LibWeb/HTML/PotentialCORSRequest.h>
#include <LibWeb/HTML/Scripting/Environments.h>
#include <LibWeb/HTML/WindowOrWorkerGlobalScope.h>
@ -442,7 +444,7 @@ void EventSource::dispatch_the_event()
// the event source.
// 6. If the event type buffer has a value other than the empty string, change the type of the newly created event to equal
// the value of the event type buffer.
Bindings::MessageEventInit init {};
Bindings::MessageEventInit init;
init.data = JS::PrimitiveString::create(vm(), data_buffer);
init.last_event_id = last_event_id;

View file

@ -39,7 +39,7 @@ WebIDL::ExceptionOr<XHR::FormDataEntry> create_entry(JS::Realm& realm, String co
Bindings::FilePropertyBag options {};
options.type = blob->type();
blob = TRY(FileAPI::File::create(realm, { GC::make_root(*blob) }, "blob"_string, move(options)));
blob = TRY(FileAPI::File::create(realm, { { blob } }, "blob"_string, move(options)));
}
// 2. If filename is given, then set value to a new File object, representing the same bytes, whose name
@ -49,7 +49,7 @@ WebIDL::ExceptionOr<XHR::FormDataEntry> create_entry(JS::Realm& realm, String co
options.type = blob->type();
options.last_modified = as<FileAPI::File>(*blob).last_modified();
blob = TRY(FileAPI::File::create(realm, { GC::make_root(*blob) }, *filename, move(options)));
blob = TRY(FileAPI::File::create(realm, { { blob } }, *filename, move(options)));
}
return GC::Ref { as<FileAPI::File>(*blob) };
@ -249,8 +249,7 @@ WebIDL::ExceptionOr<Optional<GC::ConservativeVector<XHR::FormDataEntry>>> constr
auto form_data = TRY(XHR::FormData::construct_impl(realm, move(entry_list)));
// 7. Fire an event named formdata at form using FormDataEvent, with the formData attribute initialized to form data and the bubbles attribute initialized to true.
Bindings::FormDataEventInit init {};
init.form_data = form_data;
Bindings::FormDataEventInit init { Bindings::EventInit {}, form_data };
auto form_data_event = TRY(FormDataEvent::construct_impl(realm, HTML::EventNames::formdata, init));
form_data_event->set_bubbles(true);
form.dispatch_event(form_data_event);

View file

@ -288,7 +288,7 @@ JS::ThrowCompletionOr<HTMLCanvasElement::RenderingContext> HTMLCanvasElement::ge
// NOTE: See the spec for the full table.
if (type == "2d"sv) {
if (TRY(create_2d_context(options)) == HasOrCreatedContext::Yes)
return GC::make_root(*m_context.get<GC::Ref<HTML::CanvasRenderingContext2D>>());
return m_context.get<GC::Ref<HTML::CanvasRenderingContext2D>>();
return Empty {};
}
@ -296,14 +296,14 @@ JS::ThrowCompletionOr<HTMLCanvasElement::RenderingContext> HTMLCanvasElement::ge
// NOTE: The WebGL spec says "experimental-webgl" is also acceptable and must be equivalent to "webgl". Other engines accept this, so we do too.
if (type.is_one_of("webgl"sv, "experimental-webgl"sv)) {
if (TRY(create_webgl_context<WebGL::WebGLRenderingContext>(options)) == HasOrCreatedContext::Yes)
return GC::make_root(*m_context.get<GC::Ref<WebGL::WebGLRenderingContext>>());
return m_context.get<GC::Ref<WebGL::WebGLRenderingContext>>();
return Empty {};
}
if (type == "webgl2"sv) {
if (TRY(create_webgl_context<WebGL::WebGL2RenderingContext>(options)) == HasOrCreatedContext::Yes)
return GC::make_root(*m_context.get<GC::Ref<WebGL::WebGL2RenderingContext>>());
return m_context.get<GC::Ref<WebGL::WebGL2RenderingContext>>();
return Empty {};
}
@ -331,7 +331,7 @@ Gfx::IntSize HTMLCanvasElement::bitmap_size_for_canvas(size_t minimum_width, siz
}
// https://html.spec.whatwg.org/multipage/canvas.html#dom-canvas-todataurl
String HTMLCanvasElement::to_data_url(StringView type, JS::Value js_quality)
String HTMLCanvasElement::to_data_url(StringView type, Optional<JS::Value> js_quality)
{
// It is possible the canvas doesn't have an associated bitmap so create one
allocate_painting_surface_if_needed();
@ -351,7 +351,7 @@ String HTMLCanvasElement::to_data_url(StringView type, JS::Value js_quality)
// 3. Let file be a serialization of this canvas element's bitmap as a file, passing type and quality if given.
auto bitmap = surface->snapshot_bitmap();
Optional<double> quality = js_quality.is_number() ? js_quality.as_double() : Optional<double>();
Optional<double> quality = js_quality.has_value() && js_quality->is_number() ? js_quality->as_double() : Optional<double>();
auto file = serialize_bitmap(bitmap, type, quality);
// 4. If file is null, then return "data:,".
@ -369,7 +369,7 @@ String HTMLCanvasElement::to_data_url(StringView type, JS::Value js_quality)
}
// https://html.spec.whatwg.org/multipage/canvas.html#dom-canvas-toblob
WebIDL::ExceptionOr<void> HTMLCanvasElement::to_blob(GC::Ref<WebIDL::CallbackType> callback, StringView type, JS::Value js_quality)
WebIDL::ExceptionOr<void> HTMLCanvasElement::to_blob(GC::Ref<WebIDL::CallbackType> callback, StringView type, Optional<JS::Value> js_quality)
{
// FIXME: 1. If this canvas element's bitmap's origin-clean flag is set to false, then throw a "SecurityError" DOMException.
@ -378,7 +378,7 @@ WebIDL::ExceptionOr<void> HTMLCanvasElement::to_blob(GC::Ref<WebIDL::CallbackTyp
// then set result to a copy of this canvas element's bitmap.
auto bitmap_result = get_bitmap_from_surface();
Optional<double> quality = js_quality.is_number() ? js_quality.as_double() : Optional<double>();
Optional<double> quality = js_quality.has_value() && js_quality->is_number() ? js_quality->as_double() : Optional<double>();
// 4. Run these steps in parallel:
Platform::EventLoopPlugin::the().deferred_invoke(GC::create_function(heap(), [this, callback, bitmap_result, type, quality] {

View file

@ -22,7 +22,7 @@ class HTMLCanvasElement final : public HTMLElement {
public:
static constexpr bool OVERRIDES_FINALIZE = true;
using RenderingContext = Variant<GC::Root<CanvasRenderingContext2D>, GC::Root<WebGL::WebGLRenderingContext>, GC::Root<WebGL::WebGL2RenderingContext>, Empty>;
using RenderingContext = Variant<GC::Ref<CanvasRenderingContext2D>, GC::Ref<WebGL::WebGLRenderingContext>, GC::Ref<WebGL::WebGL2RenderingContext>, Empty>;
virtual ~HTMLCanvasElement() override;
@ -43,8 +43,8 @@ public:
virtual void attribute_changed(FlyString const& local_name, Optional<String> const& old_value, Optional<String> const& value, Optional<FlyString> const& namespace_) override;
String to_data_url(StringView type, JS::Value quality);
WebIDL::ExceptionOr<void> to_blob(GC::Ref<WebIDL::CallbackType> callback, StringView type, JS::Value quality);
String to_data_url(StringView type, Optional<JS::Value> quality);
WebIDL::ExceptionOr<void> to_blob(GC::Ref<WebIDL::CallbackType> callback, StringView type, Optional<JS::Value> quality);
RefPtr<Gfx::Bitmap> get_bitmap_from_surface();
void present();

View file

@ -272,12 +272,12 @@ void HTMLDetailsElement::update_shadow_tree_slots()
if (!shadow_root())
return;
Vector<HTMLSlotElement::SlottableHandle> summary_assignment;
Vector<HTMLSlotElement::SlottableHandle> descendants_assignment;
GC::ConservativeVector<HTMLSlotElement::SlottableHandle> summary_assignment;
GC::ConservativeVector<HTMLSlotElement::SlottableHandle> descendants_assignment;
auto* summary = first_child_of_type<HTMLSummaryElement>();
if (summary != nullptr)
summary_assignment.append(GC::make_root(static_cast<DOM::Element&>(*summary)));
summary_assignment.append(GC::Ref { static_cast<DOM::Element&>(*summary) });
for_each_in_subtree([&](auto& child) {
if (&child == summary)
@ -286,7 +286,7 @@ void HTMLDetailsElement::update_shadow_tree_slots()
return TraversalDecision::Continue;
child.as_slottable().visit([&](auto& node) {
descendants_assignment.append(GC::make_root(node));
descendants_assignment.append(node);
});
return TraversalDecision::Continue;

View file

@ -10,6 +10,7 @@
#include <LibWeb/ARIA/Roles.h>
#include <LibWeb/Bindings/ExceptionOrUtils.h>
#include <LibWeb/Bindings/HTMLElement.h>
#include <LibWeb/Bindings/PointerEvent.h>
#include <LibWeb/CSS/ComputedProperties.h>
#include <LibWeb/CSS/StyleValues/DisplayStyleValue.h>
#include <LibWeb/DOM/Document.h>
@ -1205,7 +1206,7 @@ WebIDL::ExceptionOr<bool> HTMLElement::check_popover_validity(ExpectedToBeShowin
WebIDL::ExceptionOr<void> HTMLElement::show_popover_for_bindings(Bindings::ShowPopoverOptions const& options)
{
// 1. Let source be options["source"] if it exists; otherwise, null.
auto source = options.source.has_value() ? GC::Ptr<HTMLElement> { options.source->ptr() } : GC::Ptr<HTMLElement> {};
auto source = GC::Ptr<HTMLElement> { options.source };
// 2. Run show popover given this, true, and source.
return show_popover(ThrowExceptions::Yes, source);
}
@ -1579,8 +1580,7 @@ WebIDL::ExceptionOr<bool> HTMLElement::toggle_popover(TogglePopoverOptionsOrForc
// 3. Otherwise, if options["force"] exists, set force to options["force"].
force = options.force;
// 4. Let source be options["source"] if it exists; otherwise, null.
if (options.source.has_value())
source = options.source->ptr();
source = options.source;
});
// 5. If this's popover visibility state is showing, and force is null or false, then run the hide popover algorithm given this, true, true, true, false, and null.

View file

@ -35,7 +35,7 @@ void HTMLFormControlsCollection::initialize(JS::Realm& realm)
}
// https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#dom-htmlformcontrolscollection-nameditem
Variant<Empty, DOM::Element*, GC::Root<RadioNodeList>> HTMLFormControlsCollection::named_item_or_radio_node_list(FlyString const& name) const
Variant<Empty, GC::Ref<DOM::Element>, GC::Ref<RadioNodeList>> HTMLFormControlsCollection::named_item_or_radio_node_list(FlyString const& name) const
{
// 1. If name is the empty string, return null and stop the algorithm.
if (name.is_empty())
@ -63,18 +63,18 @@ Variant<Empty, DOM::Element*, GC::Root<RadioNodeList>> HTMLFormControlsCollectio
return {};
if (!multiple_matching)
return matching_element;
return GC::Ref { *matching_element };
// 4. Otherwise, create a new RadioNodeList object representing a live view of the HTMLFormControlsCollection object, further filtered so that the only nodes in the
// RadioNodeList object are those that have either an id attribute or a name attribute equal to name. The nodes in the RadioNodeList object must be sorted in tree
// order. Return that RadioNodeList object.
return GC::make_root(RadioNodeList::create(realm(), root(), DOM::LiveNodeList::Scope::Descendants, [name](auto const& node) {
return RadioNodeList::create(realm(), root(), DOM::LiveNodeList::Scope::Descendants, [name](auto const& node) {
if (!is<DOM::Element>(node))
return false;
auto const& element = as<DOM::Element>(node);
return element.id() == name || element.name() == name;
}));
});
}
JS::Value HTMLFormControlsCollection::named_item_value(FlyString const& name) const

View file

@ -19,7 +19,7 @@ public:
virtual ~HTMLFormControlsCollection() override;
Variant<Empty, DOM::Element*, GC::Root<RadioNodeList>> named_item_or_radio_node_list(FlyString const& name) const;
Variant<Empty, GC::Ref<DOM::Element>, GC::Ref<RadioNodeList>> named_item_or_radio_node_list(FlyString const& name) const;
protected:
virtual void initialize(JS::Realm&) override;

Some files were not shown because too many files have changed in this diff Show more