LibWeb/CSS: Implement CSSUnparsedValue and CSSVariableReferenceValue

We don't serialize these the way WPT expects, because we don't implement
the comment-insertion rules from CSS-Syntax. We don't implement that
for regular serialization either, so it's something we can worry about
later.
This commit is contained in:
Sam Atkins 2025-08-14 16:43:12 +01:00
commit 6428c9990d
Notes: github-actions[bot] 2025-08-21 09:23:12 +00:00
21 changed files with 442 additions and 35 deletions

View file

@ -132,6 +132,8 @@ set(SOURCES
CSS/CSSStyleValue.cpp
CSS/CSSSupportsRule.cpp
CSS/CSSTransition.cpp
CSS/CSSUnparsedValue.cpp
CSS/CSSVariableReferenceValue.cpp
CSS/Descriptor.cpp
CSS/Display.cpp
CSS/EdgeRect.cpp

View file

@ -0,0 +1,144 @@
/*
* Copyright (c) 2025, Sam Atkins <sam@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "CSSUnparsedValue.h"
#include <LibWeb/Bindings/CSSUnparsedValuePrototype.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/CSS/CSSVariableReferenceValue.h>
#include <LibWeb/WebIDL/ExceptionOr.h>
namespace Web::CSS {
GC_DEFINE_ALLOCATOR(CSSUnparsedValue);
GC::Ref<CSSUnparsedValue> CSSUnparsedValue::create(JS::Realm& realm, Vector<GCRootCSSUnparsedSegment> value)
{
// NB: Convert our GC::Roots into GC::Refs.
Vector<CSSUnparsedSegment> converted_value;
for (auto const& variant : value) {
variant.visit(
[&](GC::Root<CSSVariableReferenceValue> const& it) { converted_value.append(GC::Ref { *it }); },
[&](String const& it) { converted_value.append(it); });
}
return realm.create<CSSUnparsedValue>(realm, move(converted_value));
}
// 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)
{
// 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)
: CSSStyleValue(realm)
, m_tokens(move(value))
{
m_legacy_platform_object_flags = LegacyPlatformObjectFlags {
.supports_indexed_properties = true,
.has_indexed_property_setter = true,
};
}
CSSUnparsedValue::~CSSUnparsedValue() = default;
void CSSUnparsedValue::initialize(JS::Realm& realm)
{
WEB_SET_PROTOTYPE_FOR_INTERFACE(CSSUnparsedValue);
Base::initialize(realm);
}
void CSSUnparsedValue::visit_edges(Visitor& visitor)
{
Base::visit_edges(visitor);
for (auto const& token : m_tokens) {
if (auto* variable = token.get_pointer<GC::Ref<CSSVariableReferenceValue>>()) {
visitor.visit(*variable);
}
}
}
// https://drafts.css-houdini.org/css-typed-om-1/#dom-cssunparsedvalue-length
WebIDL::UnsignedLong CSSUnparsedValue::length() const
{
// The length attribute returns the size of the [[tokens]] internal slot.
return m_tokens.size();
}
// https://drafts.css-houdini.org/css-typed-om-1/#ref-for-dfn-determine-the-value-of-an-indexed-property
Optional<JS::Value> CSSUnparsedValue::item_value(size_t index) const
{
// To determine the value of an indexed property of a CSSUnparsedValue this and an index n, let tokens be thiss
// [[tokens]] internal slot, and return tokens[n].
if (index >= m_tokens.size())
return {};
auto value = m_tokens[index];
return value.visit(
[&](GC::Ref<CSSVariableReferenceValue> const& variable) -> JS::Value { return variable; },
[&](String const& string) -> JS::Value { return JS::PrimitiveString::create(vm(), string); });
}
static WebIDL::ExceptionOr<CSSUnparsedSegment> unparsed_segment_from_js_value(JS::VM& vm, JS::Value& value)
{
if (value.is_object()) {
if (auto* variable_reference = as_if<CSSVariableReferenceValue>(value.as_object())) {
return GC::Ref { *variable_reference };
}
}
return TRY(value.to_string(vm));
}
// https://drafts.css-houdini.org/css-typed-om-1/#ref-for-dfn-set-the-value-of-an-existing-indexed-property
WebIDL::ExceptionOr<void> CSSUnparsedValue::set_value_of_existing_indexed_property(u32 n, JS::Value value)
{
// To set the value of an existing indexed property of a CSSUnparsedValue this, an index n, and a value new value,
// let tokens be thiss [[tokens]] internal slot, and set tokens[n] to new value.
m_tokens[n] = TRY(unparsed_segment_from_js_value(vm(), value));
return {};
}
// https://drafts.css-houdini.org/css-typed-om-1/#ref-for-dfn-set-the-value-of-a-new-indexed-property
WebIDL::ExceptionOr<void> CSSUnparsedValue::set_value_of_new_indexed_property(u32 n, JS::Value value)
{
// To set the value of a new indexed property of a CSSUnparsedValue this, an index n, and a value new value,
// let tokens be thiss [[tokens]] internal slot. If n is not equal to the size of tokens, throw a RangeError.
// Otherwise, append new value to tokens.
if (n != m_tokens.size())
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::RangeError, "Index out of range"sv };
m_tokens.append(TRY(unparsed_segment_from_js_value(vm(), value)));
return {};
}
// https://drafts.css-houdini.org/css-typed-om-1/#serialize-a-cssunparsedvalue
String CSSUnparsedValue::to_string() const
{
// To serialize a CSSUnparsedValue this:
// 1. Let s initially be the empty string.
StringBuilder s;
// 2. For each item in thiss [[tokens]] internal slot:
for (auto const& item : m_tokens) {
// FIXME: In order to match the expected test behaviour, this should insert comments, with the same rules as
// serialize_a_series_of_component_values(). See https://github.com/w3c/css-houdini-drafts/issues/1148
item.visit(
// 1. If item is a USVString, append it to s.
[&](String const& string) {
s.append(string);
},
// 2. Otherwise, item is a CSSVariableReferenceValue. Serialize it, then append the result to s.
[&](GC::Ref<CSSVariableReferenceValue> const& variable) {
s.append(variable->to_string());
});
}
// 3. Return s.
return s.to_string_without_validation();
}
}

View file

@ -0,0 +1,47 @@
/*
* Copyright (c) 2025, Sam Atkins <sam@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/CSS/CSSStyleValue.h>
#include <LibWeb/WebIDL/Types.h>
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 : public CSSStyleValue {
WEB_PLATFORM_OBJECT(CSSUnparsedValue, 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>);
virtual ~CSSUnparsedValue() override;
WebIDL::UnsignedLong length() const;
virtual Optional<JS::Value> item_value(size_t index) const override;
virtual WebIDL::ExceptionOr<void> set_value_of_existing_indexed_property(u32, JS::Value) override;
virtual WebIDL::ExceptionOr<void> set_value_of_new_indexed_property(u32, JS::Value) override;
virtual String to_string() const override;
private:
explicit CSSUnparsedValue(JS::Realm&, Vector<CSSUnparsedSegment>);
virtual void initialize(JS::Realm&) override;
virtual void visit_edges(Visitor&) override;
// https://drafts.css-houdini.org/css-typed-om-1/#dom-cssunparsedvalue-tokens-slot
// They have a [[tokens]] internal slot, which is a list of USVStrings and CSSVariableReferenceValue objects.
// This list is the objects values to iterate over.
Vector<CSSUnparsedSegment> m_tokens;
};
}

View file

@ -0,0 +1,16 @@
#import <CSS/CSSStyleValue.idl>
#import <CSS/CSSVariableReferenceValue.idl>
// https://drafts.css-houdini.org/css-typed-om-1/#cssunparsedvalue
[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)]
interface CSSUnparsedValue : CSSStyleValue {
constructor(sequence<CSSUnparsedSegment> members);
readonly attribute unsigned long length;
getter CSSUnparsedSegment (unsigned long index);
setter undefined (unsigned long index, CSSUnparsedSegment val);
// FIXME: Different order from the spec, because our IDL parser needs the indexed getter to be defined already.
iterable<CSSUnparsedSegment>;
};
// https://drafts.css-houdini.org/css-typed-om-1/#typedefdef-cssunparsedsegment
typedef (USVString or CSSVariableReferenceValue) CSSUnparsedSegment;

View file

@ -0,0 +1,114 @@
/*
* Copyright (c) 2025, Sam Atkins <sam@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "CSSVariableReferenceValue.h"
#include <LibWeb/Bindings/CSSVariableReferenceValuePrototype.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/CSS/CSSUnparsedValue.h>
#include <LibWeb/CSS/PropertyName.h>
#include <LibWeb/HTML/CustomElements/CustomElementName.h>
#include <LibWeb/WebIDL/ExceptionOr.h>
namespace Web::CSS {
GC_DEFINE_ALLOCATOR(CSSVariableReferenceValue);
GC::Ref<CSSVariableReferenceValue> CSSVariableReferenceValue::create(JS::Realm& realm, FlyString variable, GC::Ptr<CSSUnparsedValue> fallback)
{
return realm.create<CSSVariableReferenceValue>(realm, move(variable), move(fallback));
}
// https://drafts.css-houdini.org/css-typed-om-1/#dom-cssvariablereferencevalue-cssvariablereferencevalue
WebIDL::ExceptionOr<GC::Ref<CSSVariableReferenceValue>> CSSVariableReferenceValue::construct_impl(JS::Realm& realm, FlyString variable, GC::Ptr<CSSUnparsedValue> fallback)
{
// The CSSVariableReferenceValue(variable, fallback) constructor must, when called, perform the following steps:
// 1. If variable is not a custom property name string, throw a TypeError.
if (!is_a_custom_property_name_string(variable))
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, MUST(String::formatted("'{}' is not a valid CSS custom property name", variable)) };
// 2. Return a new CSSVariableReferenceValue with its variable internal slot set to variable and its fallback internal slot set to fallback.
return CSSVariableReferenceValue::create(realm, move(variable), move(fallback));
}
CSSVariableReferenceValue::CSSVariableReferenceValue(JS::Realm& realm, FlyString variable, GC::Ptr<CSSUnparsedValue> fallback)
: Bindings::PlatformObject(realm)
, m_variable(move(variable))
, m_fallback(move(fallback))
{
}
CSSVariableReferenceValue::~CSSVariableReferenceValue() = default;
void CSSVariableReferenceValue::initialize(JS::Realm& realm)
{
WEB_SET_PROTOTYPE_FOR_INTERFACE(CSSVariableReferenceValue);
Base::initialize(realm);
}
void CSSVariableReferenceValue::visit_edges(Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(m_fallback);
}
// https://drafts.css-houdini.org/css-typed-om-1/#dom-cssvariablereferencevalue-variable
String CSSVariableReferenceValue::variable() const
{
// The getter for the variable attribute of a CSSVariableReferenceValue this must return its variable internal slot.
return m_variable.to_string();
}
// https://drafts.css-houdini.org/css-typed-om-1/#dom-cssvariablereferencevalue-variable
WebIDL::ExceptionOr<void> CSSVariableReferenceValue::set_variable(FlyString variable)
{
// The variable attribute of a CSSVariableReferenceValue this must, on setting a variable variable, perform the following steps:
// 1. If variable is not a custom property name string, throw a TypeError.
if (!is_a_custom_property_name_string(variable))
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, MUST(String::formatted("'{}' is not a valid CSS custom property name", variable)) };
// 2. Otherwise, set thiss variable internal slot to variable.
m_variable = move(variable);
return {};
}
// https://drafts.css-houdini.org/css-typed-om-1/#dom-cssvariablereferencevalue-fallback
GC::Ptr<CSSUnparsedValue> CSSVariableReferenceValue::fallback() const
{
// AD-HOC: No spec algorithm, see https://github.com/w3c/css-houdini-drafts/issues/1146#issuecomment-3188550133
return m_fallback;
}
// https://drafts.css-houdini.org/css-typed-om-1/#dom-cssvariablereferencevalue-fallback
WebIDL::ExceptionOr<void> CSSVariableReferenceValue::set_fallback(GC::Ptr<CSSUnparsedValue> fallback)
{
// AD-HOC: No spec algorithm, see https://github.com/w3c/css-houdini-drafts/issues/1146#issuecomment-3188550133
m_fallback = move(fallback);
return {};
}
// https://drafts.css-houdini.org/css-typed-om-1/#serialize-a-cssvariablereferencevalue
String CSSVariableReferenceValue::to_string() const
{
// To serialize a CSSVariableReferenceValue this:
// 1. Let s initially be "var(".
StringBuilder s;
s.append("var("sv);
// 2. Append thiss variable internal slot to s.
s.append(m_variable);
// 3. If thiss fallback internal slot is not null, append ", " to s, then serialize the fallback internal slot and append it to s.
if (m_fallback) {
// AD-HOC: Tested behaviour requires we append "," without the space. https://github.com/w3c/css-houdini-drafts/issues/1148
s.append(","sv);
s.append(m_fallback->to_string());
}
// 4. Append ")" to s and return s.
s.append(")"sv);
return s.to_string_without_validation();
}
}

View file

@ -0,0 +1,42 @@
/*
* Copyright (c) 2025, Sam Atkins <sam@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/FlyString.h>
#include <LibWeb/Bindings/PlatformObject.h>
namespace Web::CSS {
class CSSVariableReferenceValue : public Bindings::PlatformObject {
WEB_PLATFORM_OBJECT(CSSVariableReferenceValue, Bindings::PlatformObject);
GC_DECLARE_ALLOCATOR(CSSVariableReferenceValue);
public:
[[nodiscard]] static GC::Ref<CSSVariableReferenceValue> create(JS::Realm&, FlyString variable, GC::Ptr<CSSUnparsedValue> fallback = nullptr);
static WebIDL::ExceptionOr<GC::Ref<CSSVariableReferenceValue>> construct_impl(JS::Realm&, FlyString variable, GC::Ptr<CSSUnparsedValue> fallback);
virtual ~CSSVariableReferenceValue() override;
String variable() const;
WebIDL::ExceptionOr<void> set_variable(FlyString);
GC::Ptr<CSSUnparsedValue> fallback() const;
WebIDL::ExceptionOr<void> set_fallback(GC::Ptr<CSSUnparsedValue>);
String to_string() const;
private:
CSSVariableReferenceValue(JS::Realm&, FlyString variable, GC::Ptr<CSSUnparsedValue> fallback);
virtual void initialize(JS::Realm&) override;
virtual void visit_edges(Visitor&) override;
FlyString m_variable;
GC::Ptr<CSSUnparsedValue> m_fallback;
};
}

View file

@ -0,0 +1,9 @@
#import <CSS/CSSUnparsedValue.idl>
// https://drafts.css-houdini.org/css-typed-om-1/#cssvariablereferencevalue
[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)]
interface CSSVariableReferenceValue {
constructor(USVString variable, optional CSSUnparsedValue? fallback = null);
attribute USVString variable;
readonly attribute CSSUnparsedValue? fallback;
};

View file

@ -256,6 +256,8 @@ class CSSStyleRule;
class CSSStyleSheet;
class CSSStyleValue;
class CSSSupportsRule;
class CSSUnparsedValue;
class CSSVariableReferenceValue;
class CursorStyleValue;
class CustomIdentStyleValue;
class DimensionStyleValue;

View file

@ -52,6 +52,8 @@ libweb_js_bindings(CSS/CSSStyleSheet)
libweb_js_bindings(CSS/CSSStyleValue)
libweb_js_bindings(CSS/CSSSupportsRule)
libweb_js_bindings(CSS/CSSTransition)
libweb_js_bindings(CSS/CSSUnparsedValue)
libweb_js_bindings(CSS/CSSVariableReferenceValue)
libweb_js_bindings(CSS/FontFace)
libweb_js_bindings(CSS/FontFaceSet)
libweb_js_bindings(CSS/MediaList)

View file

@ -56,6 +56,8 @@ static bool is_platform_object(Type const& type)
"CryptoKey"sv,
"CSSKeywordValue"sv,
"CSSStyleValue"sv,
"CSSUnparsedValue"sv,
"CSSVariableReferenceValue"sv,
"CustomStateSet"sv,
"DataTransfer"sv,
"Document"sv,

View file

@ -64,6 +64,8 @@ CSSStyleSheet
CSSStyleValue
CSSSupportsRule
CSSTransition
CSSUnparsedValue
CSSVariableReferenceValue
CacheStorage
CanvasGradient
CanvasPattern

View file

@ -1,3 +1,21 @@
Harness status: Error
Harness status: OK
Found 0 tests
Found 16 tests
16 Fail
Fail Normalizing "var(--A)" on a CSS property returns correct CSSUnparsedValue
Fail Normalizing "var(--A)" on a shorthand returns correct CSSUnparsedValue
Fail Normalizing "var(--A)" on a list-valued property returns correct CSSUnparsedValue
Fail Normalizing "var(--A)" on a custom property returns correct CSSUnparsedValue
Fail Normalizing "var(--A, 1em)" on a CSS property returns correct CSSUnparsedValue
Fail Normalizing "var(--A, 1em)" on a shorthand returns correct CSSUnparsedValue
Fail Normalizing "var(--A, 1em)" on a list-valued property returns correct CSSUnparsedValue
Fail Normalizing "var(--A, 1em)" on a custom property returns correct CSSUnparsedValue
Fail Normalizing "var(--A, var(--B))" on a CSS property returns correct CSSUnparsedValue
Fail Normalizing "var(--A, var(--B))" on a shorthand returns correct CSSUnparsedValue
Fail Normalizing "var(--A, var(--B))" on a list-valued property returns correct CSSUnparsedValue
Fail Normalizing "var(--A, var(--B))" on a custom property returns correct CSSUnparsedValue
Fail Normalizing "calc(42px + var(--foo, 15em) + var(--bar, var(--far) + 15px))" on a CSS property returns correct CSSUnparsedValue
Fail Normalizing "calc(42px + var(--foo, 15em) + var(--bar, var(--far) + 15px))" on a shorthand returns correct CSSUnparsedValue
Fail Normalizing "calc(42px + var(--foo, 15em) + var(--bar, var(--far) + 15px))" on a list-valued property returns correct CSSUnparsedValue
Fail Normalizing "calc(42px + var(--foo, 15em) + var(--bar, var(--far) + 15px))" on a custom property returns correct CSSUnparsedValue

View file

@ -2,9 +2,10 @@ Harness status: OK
Found 5 tests
5 Fail
2 Pass
3 Fail
Fail CSSUnparsedValue containing strings serializes to its tokenized contents
Fail CSSUnparsedValue containing variable references serializes its tokenized contents
Pass CSSUnparsedValue containing variable references serializes its tokenized contents
Fail CSSUnparsedValue containing mix of strings and variable references serializes to its tokenized contents
Fail CSSUnparsedValue can hold same object in multiple places
Pass CSSUnparsedValue can hold same object in multiple places
Fail attributeStyleMap round-trips correctly, though the comment is gone

View file

@ -2,5 +2,5 @@ Harness status: OK
Found 1 tests
1 Fail
Fail Don't crash when serializing empty CSSUnparsedValue
1 Pass
Pass Don't crash when serializing empty CSSUnparsedValue

View file

@ -2,10 +2,10 @@ Harness status: OK
Found 6 tests
6 Fail
Fail Getting invalid index in CSSUnparsedValue returns undefined
Fail Can update fragment in CSSUnparsedValue to a String
Fail Can update fragment in CSSUnparsedValue to a CSSVariableReference
Fail Setting one past the last fragment in a CSSUnparsedValue to a String appends the new fragment
Fail Setting one past the last fragment in a CSSUnparsedValue to a CSSVariableReferenceValue appends the new fragment
Fail Setting out of range index in CSSUnparsedValue throws RangeError
6 Pass
Pass Getting invalid index in CSSUnparsedValue returns undefined
Pass Can update fragment in CSSUnparsedValue to a String
Pass Can update fragment in CSSUnparsedValue to a CSSVariableReference
Pass Setting one past the last fragment in a CSSUnparsedValue to a String appends the new fragment
Pass Setting one past the last fragment in a CSSUnparsedValue to a CSSVariableReferenceValue appends the new fragment
Pass Setting out of range index in CSSUnparsedValue throws RangeError

View file

@ -2,6 +2,6 @@ Harness status: OK
Found 2 tests
2 Fail
Fail Iterating over an empty CSSUnparsedValue produces nothing
Fail Iterating over a CSSUnparsedValue produces all fragments
2 Pass
Pass Iterating over an empty CSSUnparsedValue produces nothing
Pass Iterating over a CSSUnparsedValue produces all fragments

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 4 tests
4 Fail
Fail Length of CSSUnparsedValue with no fragments is zero
Fail Length of CSSUnparsedValue with multiple fragments is the number of fragments
Fail Length of CSSUnparsedValue updates when fragments are appended
Fail Length of CSSUnparsedValue does not change when fragments are modified
4 Pass
Pass Length of CSSUnparsedValue with no fragments is zero
Pass Length of CSSUnparsedValue with multiple fragments is the number of fragments
Pass Length of CSSUnparsedValue updates when fragments are appended
Pass Length of CSSUnparsedValue does not change when fragments are modified

View file

@ -1,3 +1,9 @@
Harness status: Error
Harness status: OK
Found 0 tests
Found 4 tests
4 Pass
Pass CSSUnparsedValue can be constructed from no arguments
Pass CSSUnparsedValue can be constructed from a single empty string
Pass CSSUnparsedValue can be constructed from a single CSSVariableReferenceValue
Pass CSSUnparsedValue can be constructed from a mix of strings and CSSVariableReferenceValues

View file

@ -2,6 +2,6 @@ Harness status: OK
Found 2 tests
2 Fail
Fail Constructing a CSSVariableReferenceValue with an empty variable name throws a TypeError
Fail Constructing a CSSVariableReferenceValue with an invalid variable name throws SyntaxError
2 Pass
Pass Constructing a CSSVariableReferenceValue with an empty variable name throws a TypeError
Pass Constructing a CSSVariableReferenceValue with an invalid variable name throws SyntaxError

View file

@ -2,7 +2,7 @@ Harness status: OK
Found 3 tests
3 Fail
Fail CSSVariableReferenceValue.variable can updated to a valid custom property name
Fail Updating CSSVariableReferenceValue.variable to the empty string throws TypeError
Fail Updating CSSVariableReferenceValue.variable to an invalid custom property name throws TypeError
3 Pass
Pass CSSVariableReferenceValue.variable can updated to a valid custom property name
Pass Updating CSSVariableReferenceValue.variable to the empty string throws TypeError
Pass Updating CSSVariableReferenceValue.variable to an invalid custom property name throws TypeError

View file

@ -2,7 +2,7 @@ Harness status: OK
Found 3 tests
3 Fail
Fail CSSVariableReferenceValue can be constructed with no fallback
Fail CSSVariableReferenceValue can be constructed with null fallback
Fail CSSVariableReferenceValue can be constructed with valid fallback
3 Pass
Pass CSSVariableReferenceValue can be constructed with no fallback
Pass CSSVariableReferenceValue can be constructed with null fallback
Pass CSSVariableReferenceValue can be constructed with valid fallback