mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-12-07 21:59:54 +00:00
LibWeb: Implement basic CSS random() function
At the moment this is limited to only fixed value sharing and does not support step values
This commit is contained in:
parent
8944130fde
commit
2a5e389f63
Notes:
github-actions[bot]
2025-12-01 11:02:05 +00:00
Author: https://github.com/Calme1709
Commit: 2a5e389f63
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6707
Reviewed-by: https://github.com/AtkinsSJ ✅
Reviewed-by: https://github.com/gmta
17 changed files with 380 additions and 31 deletions
|
|
@ -265,6 +265,7 @@ set(SOURCES
|
|||
CSS/StyleValues/PositionStyleValue.cpp
|
||||
CSS/StyleValues/RGBColorStyleValue.cpp
|
||||
CSS/StyleValues/RadialGradientStyleValue.cpp
|
||||
CSS/StyleValues/RandomValueSharingStyleValue.cpp
|
||||
CSS/StyleValues/RectStyleValue.cpp
|
||||
CSS/StyleValues/RepeatStyleStyleValue.cpp
|
||||
CSS/StyleValues/ScrollbarColorStyleValue.cpp
|
||||
|
|
|
|||
|
|
@ -168,6 +168,28 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"random": {
|
||||
"parameter-validation": "consistent",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "random-value-sharing",
|
||||
"type": "<random-value-sharing>",
|
||||
"required": false,
|
||||
"default": "auto",
|
||||
"__comment": "NOTE: The actual default is hardcoded and we don't respect the value above, we have it there so we know that this argument has a default"
|
||||
},
|
||||
{
|
||||
"name": "minimum",
|
||||
"type": "<number>|<dimension>|<percentage>",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "maximum",
|
||||
"type": "<number>|<dimension>|<percentage>",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"rem": {
|
||||
"parameter-validation": "same",
|
||||
"parameters": [
|
||||
|
|
|
|||
|
|
@ -1718,6 +1718,12 @@ bool Parser::context_allows_tree_counting_functions() const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Parser::context_allows_random_functions() const
|
||||
{
|
||||
// For now we only allow random functions within property contexts, see https://drafts.csswg.org/css-values-5/#issue-cd071f29
|
||||
return m_value_context.find_first_index_if([](ValueParsingContext context) { return context.has<PropertyID>(); }).has_value();
|
||||
}
|
||||
|
||||
Vector<ComponentValue> Parser::parse_as_list_of_component_values()
|
||||
{
|
||||
return parse_a_list_of_component_values(m_token_stream);
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ enum SpecialContext : u8 {
|
|||
CubicBezierFunctionXCoordinate,
|
||||
DOMMatrixInitString,
|
||||
MediaCondition,
|
||||
RandomValueSharingFixedValue,
|
||||
ShadowBlurRadius,
|
||||
StepsIntervalsJumpNone,
|
||||
StepsIntervalsNormal,
|
||||
|
|
@ -379,6 +380,7 @@ private:
|
|||
RefPtr<CustomIdentStyleValue const> parse_custom_ident_value(TokenStream<ComponentValue>&, ReadonlySpan<StringView> blacklist);
|
||||
Optional<FlyString> parse_dashed_ident(TokenStream<ComponentValue>&);
|
||||
RefPtr<CustomIdentStyleValue const> parse_dashed_ident_value(TokenStream<ComponentValue>&);
|
||||
RefPtr<RandomValueSharingStyleValue const> parse_random_value_sharing(TokenStream<ComponentValue>&);
|
||||
// NOTE: Implemented in generated code. (GenerateCSSMathFunctions.cpp)
|
||||
RefPtr<CalculationNode const> parse_math_function(Function const&, CalculationContext const&);
|
||||
RefPtr<CalculationNode const> parse_a_calc_function_node(Function const&, CalculationContext const&);
|
||||
|
|
@ -593,6 +595,7 @@ private:
|
|||
}
|
||||
bool context_allows_quirky_length() const;
|
||||
bool context_allows_tree_counting_functions() const;
|
||||
bool context_allows_random_functions() const;
|
||||
|
||||
Vector<RuleContext> m_rule_context;
|
||||
HashTable<FlyString> m_declared_namespaces;
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@
|
|||
#include <LibWeb/CSS/StyleValues/PositionStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/RGBColorStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/RadialGradientStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/RandomValueSharingStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/RatioStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/RectStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/RepeatStyleStyleValue.h>
|
||||
|
|
@ -3789,6 +3790,40 @@ RefPtr<CustomIdentStyleValue const> Parser::parse_custom_ident_value(TokenStream
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/css-values-5/#typedef-random-value-sharing
|
||||
RefPtr<RandomValueSharingStyleValue const> Parser::parse_random_value_sharing(TokenStream<ComponentValue>& tokens)
|
||||
{
|
||||
// <random-value-sharing> = [ [ auto | <dashed-ident> ] || element-shared ] | fixed <number [0,1]>
|
||||
auto transaction = tokens.begin_transaction();
|
||||
|
||||
tokens.discard_whitespace();
|
||||
|
||||
// fixed <number [0,1]>
|
||||
if (tokens.next_token().is_ident("fixed"sv)) {
|
||||
tokens.discard_a_token();
|
||||
tokens.discard_whitespace();
|
||||
|
||||
auto context_guard = push_temporary_value_parsing_context(SpecialContext::RandomValueSharingFixedValue);
|
||||
if (auto fixed_value = parse_number_value(tokens)) {
|
||||
tokens.discard_whitespace();
|
||||
|
||||
if (tokens.has_next_token())
|
||||
return nullptr;
|
||||
|
||||
if (fixed_value->is_number() && (fixed_value->as_number().number() < 0 || fixed_value->as_number().number() >= 1))
|
||||
return nullptr;
|
||||
|
||||
transaction.commit();
|
||||
return RandomValueSharingStyleValue::create_fixed(fixed_value.release_nonnull());
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// FIXME: Support non-fixed values
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/css-values-4/#typedef-dashed-ident
|
||||
Optional<FlyString> Parser::parse_dashed_ident(TokenStream<ComponentValue>& tokens)
|
||||
{
|
||||
|
|
@ -4384,6 +4419,9 @@ RefPtr<CalculatedStyleValue const> Parser::parse_calculated_value(ComponentValue
|
|||
case SpecialContext::CubicBezierFunctionXCoordinate:
|
||||
// Coordinates on the X axis must be between 0 and 1
|
||||
return CalculationContext { .accepted_type_ranges = { { ValueType::Number, { 0, 1 } } } };
|
||||
case SpecialContext::RandomValueSharingFixedValue:
|
||||
// Fixed values have to be less than one and numbers serialize with six digits of precision
|
||||
return CalculationContext { .accepted_type_ranges = { { ValueType::Number, { 0, 0.999999 } } } };
|
||||
case SpecialContext::StepsIntervalsJumpNone:
|
||||
return CalculationContext { .resolve_numbers_as_integers = true, .accepted_type_ranges = { { ValueType::Integer, { 2, NumericLimits<float>::max() } } } };
|
||||
case SpecialContext::StepsIntervalsNormal:
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include <LibWeb/CSS/StyleValues/LengthStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/NumberStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/PercentageStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/RandomValueSharingStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/ResolutionStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/TimeStyleValue.h>
|
||||
|
||||
|
|
@ -284,6 +285,11 @@ static String serialize_a_math_function(CalculationNode const& fn, CalculationCo
|
|||
}
|
||||
}
|
||||
|
||||
// AD-HOC: We serialize random() directly since it has abnormal children (e.g. m_random_value_sharing which is not a
|
||||
// calculation node).
|
||||
if (fn.type() == CalculationNode::Type::Random)
|
||||
return as<RandomCalculationNode>(fn).to_string(context, serialization_mode);
|
||||
|
||||
// 3. If the calculation tree’s root node is a numeric value, or a calc-operator node, let s be a string initially
|
||||
// containing "calc(".
|
||||
// Otherwise, let s be a string initially containing the name of the root node, lowercased (such as "sin" or
|
||||
|
|
@ -572,6 +578,8 @@ StringView CalculationNode::name() const
|
|||
return "log"sv;
|
||||
case Type::Exp:
|
||||
return "exp"sv;
|
||||
case Type::Random:
|
||||
return "random"sv;
|
||||
case Type::Round:
|
||||
return "round"sv;
|
||||
case Type::Mod:
|
||||
|
|
@ -2434,6 +2442,134 @@ bool ModCalculationNode::equals(CalculationNode const& other) const
|
|||
&& m_y->equals(*static_cast<ModCalculationNode const&>(other).m_y);
|
||||
}
|
||||
|
||||
NonnullRefPtr<RandomCalculationNode const> RandomCalculationNode::create(NonnullRefPtr<RandomValueSharingStyleValue const> random_value_sharing, NonnullRefPtr<CalculationNode const> minimum, NonnullRefPtr<CalculationNode const> maximum)
|
||||
{
|
||||
Optional<NumericType> numeric_type = add_the_types(*minimum, *maximum);
|
||||
|
||||
return adopt_ref(*new (nothrow) RandomCalculationNode(move(random_value_sharing), move(minimum), move(maximum), move(numeric_type)));
|
||||
}
|
||||
|
||||
RandomCalculationNode::RandomCalculationNode(NonnullRefPtr<RandomValueSharingStyleValue const> random_value_sharing, NonnullRefPtr<CalculationNode const> minimum, NonnullRefPtr<CalculationNode const> maximum, Optional<NumericType> numeric_type)
|
||||
: CalculationNode(Type::Random, move(numeric_type))
|
||||
, m_random_value_sharing(move(random_value_sharing))
|
||||
, m_minimum(move(minimum))
|
||||
, m_maximum(move(maximum))
|
||||
{
|
||||
}
|
||||
|
||||
RandomCalculationNode::~RandomCalculationNode() = default;
|
||||
|
||||
bool RandomCalculationNode::contains_percentage() const
|
||||
{
|
||||
return m_minimum->contains_percentage() || m_maximum->contains_percentage();
|
||||
}
|
||||
|
||||
NonnullRefPtr<CalculationNode const> RandomCalculationNode::with_simplified_children(CalculationContext const& context, CalculationResolutionContext const& resolution_context) const
|
||||
{
|
||||
ValueComparingRefPtr<RandomValueSharingStyleValue const> simplified_random_value_sharing;
|
||||
|
||||
// When we are in the absolutization process we should absolutize m_random_value_sharing
|
||||
if (resolution_context.length_resolution_context.has_value()) {
|
||||
ComputationContext computation_context {
|
||||
.length_resolution_context = resolution_context.length_resolution_context.value(),
|
||||
.abstract_element = resolution_context.abstract_element
|
||||
};
|
||||
|
||||
simplified_random_value_sharing = m_random_value_sharing->absolutized(computation_context)->as_random_value_sharing();
|
||||
} else {
|
||||
simplified_random_value_sharing = m_random_value_sharing;
|
||||
}
|
||||
|
||||
ValueComparingNonnullRefPtr<CalculationNode const> simplified_minimum = simplify_a_calculation_tree(m_minimum, context, resolution_context);
|
||||
ValueComparingNonnullRefPtr<CalculationNode const> simplified_maximum = simplify_a_calculation_tree(m_maximum, context, resolution_context);
|
||||
|
||||
if (simplified_random_value_sharing == m_random_value_sharing && simplified_minimum == m_minimum && simplified_maximum == m_maximum)
|
||||
return *this;
|
||||
|
||||
return RandomCalculationNode::create(simplified_random_value_sharing.release_nonnull(), move(simplified_minimum), move(simplified_maximum));
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/css-values-5/#random-evaluation
|
||||
Optional<CalculatedStyleValue::CalculationResult> RandomCalculationNode::run_operation_if_possible(CalculationContext const& context, CalculationResolutionContext const& resolution_context) const
|
||||
{
|
||||
// NB: We don't want to resolve this before computation time even if it's possible
|
||||
if (!resolution_context.abstract_element.has_value() && !resolution_context.length_resolution_context.has_value() && resolution_context.percentage_basis.has<Empty>())
|
||||
return {};
|
||||
|
||||
auto random_base_value = m_random_value_sharing->random_base_value();
|
||||
|
||||
auto minimum = try_get_value_with_canonical_unit(m_minimum, context, resolution_context);
|
||||
auto maximum = try_get_value_with_canonical_unit(m_maximum, context, resolution_context);
|
||||
|
||||
if (!minimum.has_value() || !maximum.has_value())
|
||||
return {};
|
||||
|
||||
auto minimum_value = minimum->value();
|
||||
auto maximum_value = maximum->value();
|
||||
|
||||
// https://drafts.csswg.org/css-values-5/#random-infinities
|
||||
// If the maximum value is less than the minimum value, it behaves as if it’s equal to the minimum value.
|
||||
if (maximum_value < minimum_value)
|
||||
maximum_value = minimum_value;
|
||||
|
||||
// https://drafts.csswg.org/css-values-5/#random-infinities
|
||||
// In random(A, B), if A is infinite, the result is infinite.
|
||||
if (isinf(minimum_value))
|
||||
return CalculatedStyleValue::CalculationResult { AK::Infinity<double>, numeric_type() };
|
||||
|
||||
// If A is finite, but the difference between A and B is either infinite or large enough to be treated as infinite
|
||||
// in the user agent, the result is NaN.
|
||||
if (isinf(maximum_value))
|
||||
return CalculatedStyleValue::CalculationResult { AK::NaN<double>, numeric_type() };
|
||||
|
||||
// Note: As usual for math functions, if any argument calculation is NaN, the result is NaN.
|
||||
if (isnan(minimum_value) || isnan(maximum_value))
|
||||
return CalculatedStyleValue::CalculationResult { AK::NaN<double>, numeric_type() };
|
||||
|
||||
// Given a random function with a random base value R, the value of the function is:
|
||||
// - for a random() function with min and max, but no step
|
||||
// Return min + R * (max - min)
|
||||
return CalculatedStyleValue::CalculationResult {
|
||||
minimum_value + (random_base_value * (maximum_value - minimum_value)),
|
||||
numeric_type()
|
||||
};
|
||||
}
|
||||
|
||||
String RandomCalculationNode::to_string(CalculationContext const& context, SerializationMode serialization_mode) const
|
||||
{
|
||||
StringBuilder builder;
|
||||
|
||||
builder.append("random("sv);
|
||||
builder.appendff("{}, ", m_random_value_sharing->to_string(serialization_mode));
|
||||
builder.appendff("{}, ", serialize_a_calculation_tree(m_minimum, context, serialization_mode));
|
||||
builder.appendff("{})", serialize_a_calculation_tree(m_maximum, context, serialization_mode));
|
||||
|
||||
return builder.to_string_without_validation();
|
||||
}
|
||||
|
||||
void RandomCalculationNode::dump(StringBuilder& builder, int indent) const
|
||||
{
|
||||
builder.appendff("{: >{}}RANDOM:\n", "", indent);
|
||||
builder.appendff("{}\n", m_random_value_sharing->to_string(SerializationMode::Normal));
|
||||
m_minimum->dump(builder, indent + 2);
|
||||
m_maximum->dump(builder, indent + 2);
|
||||
}
|
||||
|
||||
bool RandomCalculationNode::equals(CalculationNode const& other) const
|
||||
{
|
||||
if (this == &other)
|
||||
return true;
|
||||
|
||||
if (type() != other.type())
|
||||
return false;
|
||||
|
||||
auto const& other_random = as<RandomCalculationNode>(other);
|
||||
|
||||
return m_random_value_sharing == other_random.m_random_value_sharing
|
||||
&& m_minimum == other_random.m_minimum
|
||||
&& m_maximum == other_random.m_maximum;
|
||||
}
|
||||
|
||||
NonnullRefPtr<RemCalculationNode const> RemCalculationNode::create(NonnullRefPtr<CalculationNode const> x, NonnullRefPtr<CalculationNode const> y)
|
||||
{
|
||||
// https://www.w3.org/TR/css-values-4/#determine-the-type-of-a-calculation
|
||||
|
|
|
|||
|
|
@ -190,6 +190,10 @@ public:
|
|||
Mod,
|
||||
Rem,
|
||||
|
||||
// Random value generation
|
||||
// https://drafts.csswg.org/css-values-5/#random
|
||||
Random,
|
||||
|
||||
// Non-math functions
|
||||
NonMathFunction
|
||||
};
|
||||
|
|
@ -228,6 +232,7 @@ public:
|
|||
case Type::Round:
|
||||
case Type::Mod:
|
||||
case Type::Rem:
|
||||
case Type::Random:
|
||||
return true;
|
||||
|
||||
default:
|
||||
|
|
@ -747,6 +752,30 @@ private:
|
|||
NonnullRefPtr<CalculationNode const> m_y;
|
||||
};
|
||||
|
||||
class RandomCalculationNode final : public CalculationNode {
|
||||
public:
|
||||
static NonnullRefPtr<RandomCalculationNode const> create(NonnullRefPtr<RandomValueSharingStyleValue const>, NonnullRefPtr<CalculationNode const> minimum, NonnullRefPtr<CalculationNode const> maximum);
|
||||
~RandomCalculationNode();
|
||||
|
||||
virtual bool contains_percentage() const override;
|
||||
virtual NonnullRefPtr<CalculationNode const> with_simplified_children(CalculationContext const&, CalculationResolutionContext const&) const override;
|
||||
virtual Optional<CalculatedStyleValue::CalculationResult> run_operation_if_possible(CalculationContext const&, CalculationResolutionContext const&) const override;
|
||||
|
||||
// NOTE: We don't return children here as serialization is handled ad-hoc
|
||||
virtual Vector<NonnullRefPtr<CalculationNode const>> children() const override { return {}; }
|
||||
|
||||
String to_string(CalculationContext const&, SerializationMode serialization_mode) const;
|
||||
|
||||
virtual void dump(StringBuilder&, int indent) const override;
|
||||
virtual bool equals(CalculationNode const&) const override;
|
||||
|
||||
private:
|
||||
RandomCalculationNode(NonnullRefPtr<RandomValueSharingStyleValue const>, NonnullRefPtr<CalculationNode const>, NonnullRefPtr<CalculationNode const>, Optional<NumericType>);
|
||||
ValueComparingNonnullRefPtr<RandomValueSharingStyleValue const> m_random_value_sharing;
|
||||
ValueComparingNonnullRefPtr<CalculationNode const> m_minimum;
|
||||
ValueComparingNonnullRefPtr<CalculationNode const> m_maximum;
|
||||
};
|
||||
|
||||
class RemCalculationNode final : public CalculationNode {
|
||||
public:
|
||||
static NonnullRefPtr<RemCalculationNode const> create(NonnullRefPtr<CalculationNode const>, NonnullRefPtr<CalculationNode const>);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2025, Callum Law <callumlaw1709@outlook.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "RandomValueSharingStyleValue.h"
|
||||
#include <LibWeb/CSS/StyleValues/CalculatedStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/NumberStyleValue.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
||||
ValueComparingNonnullRefPtr<StyleValue const> RandomValueSharingStyleValue::absolutized(ComputationContext const& computation_context) const
|
||||
{
|
||||
if (m_fixed_value) {
|
||||
auto const& absolutized_fixed_value = m_fixed_value->absolutized(computation_context);
|
||||
|
||||
if (m_fixed_value == absolutized_fixed_value)
|
||||
return *this;
|
||||
|
||||
return RandomValueSharingStyleValue::create_fixed(absolutized_fixed_value);
|
||||
}
|
||||
|
||||
TODO();
|
||||
}
|
||||
|
||||
double RandomValueSharingStyleValue::random_base_value() const
|
||||
{
|
||||
VERIFY(m_fixed_value);
|
||||
VERIFY(m_fixed_value->is_number() || (m_fixed_value->is_calculated() && m_fixed_value->as_calculated().resolves_to_number()));
|
||||
|
||||
if (m_fixed_value->is_number())
|
||||
return m_fixed_value->as_number().number();
|
||||
|
||||
if (m_fixed_value->is_calculated())
|
||||
return m_fixed_value->as_calculated().resolve_number({}).value();
|
||||
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
String RandomValueSharingStyleValue::to_string(SerializationMode serialization_mode) const
|
||||
{
|
||||
if (m_fixed_value)
|
||||
return MUST(String::formatted("fixed {}", m_fixed_value->to_string(serialization_mode)));
|
||||
|
||||
TODO();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2025, Callum Law <callumlaw1709@outlook.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/CSS/Enums.h>
|
||||
#include <LibWeb/CSS/StyleValues/StyleValue.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
||||
class RandomValueSharingStyleValue : public StyleValueWithDefaultOperators<RandomValueSharingStyleValue> {
|
||||
public:
|
||||
static ValueComparingNonnullRefPtr<RandomValueSharingStyleValue const> create_fixed(NonnullRefPtr<StyleValue const> const& fixed_value)
|
||||
{
|
||||
return adopt_ref(*new (nothrow) RandomValueSharingStyleValue(fixed_value));
|
||||
}
|
||||
|
||||
virtual ~RandomValueSharingStyleValue() override = default;
|
||||
|
||||
virtual ValueComparingNonnullRefPtr<StyleValue const> absolutized(ComputationContext const&) const override;
|
||||
|
||||
double random_base_value() const;
|
||||
|
||||
virtual String to_string(SerializationMode serialization_mode) const override;
|
||||
|
||||
bool properties_equal(RandomValueSharingStyleValue const& other) const
|
||||
{
|
||||
return m_fixed_value == other.m_fixed_value;
|
||||
}
|
||||
|
||||
private:
|
||||
explicit RandomValueSharingStyleValue(RefPtr<StyleValue const> fixed_value)
|
||||
: StyleValueWithDefaultOperators(Type::RandomValueSharing)
|
||||
, m_fixed_value(move(fixed_value))
|
||||
{
|
||||
}
|
||||
|
||||
ValueComparingRefPtr<StyleValue const> m_fixed_value;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -55,6 +55,7 @@
|
|||
#include <LibWeb/CSS/StyleValues/PercentageStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/PositionStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/RadialGradientStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/RandomValueSharingStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/RatioStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/RectStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/RepeatStyleStyleValue.h>
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ namespace Web::CSS {
|
|||
__ENUMERATE_CSS_STYLE_VALUE_TYPE(Percentage, percentage, PercentageStyleValue) \
|
||||
__ENUMERATE_CSS_STYLE_VALUE_TYPE(Position, position, PositionStyleValue) \
|
||||
__ENUMERATE_CSS_STYLE_VALUE_TYPE(RadialGradient, radial_gradient, RadialGradientStyleValue) \
|
||||
__ENUMERATE_CSS_STYLE_VALUE_TYPE(RandomValueSharing, random_value_sharing, RandomValueSharingStyleValue) \
|
||||
__ENUMERATE_CSS_STYLE_VALUE_TYPE(Ratio, ratio, RatioStyleValue) \
|
||||
__ENUMERATE_CSS_STYLE_VALUE_TYPE(Rect, rect, RectStyleValue) \
|
||||
__ENUMERATE_CSS_STYLE_VALUE_TYPE(RepeatStyle, repeat_style, RepeatStyleStyleValue) \
|
||||
|
|
|
|||
|
|
@ -350,6 +350,7 @@ class PercentageStyleValue;
|
|||
class PositionStyleValue;
|
||||
class PropertyNameAndID;
|
||||
class RadialGradientStyleValue;
|
||||
class RandomValueSharingStyleValue;
|
||||
class Ratio;
|
||||
class RatioStyleValue;
|
||||
class RectStyleValue;
|
||||
|
|
|
|||
|
|
@ -98,6 +98,8 @@ ErrorOr<void> generate_implementation_file(JsonObject& functions_data, Core::Fil
|
|||
#include <LibWeb/CSS/Parser/ErrorReporter.h>
|
||||
#include <LibWeb/CSS/Parser/Parser.h>
|
||||
#include <LibWeb/CSS/StyleValues/CalculatedStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/NumberStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/RandomValueSharingStyleValue.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
||||
|
|
@ -260,6 +262,13 @@ RefPtr<CalculationNode const> Parser::parse_math_function(Function const& functi
|
|||
function_generator.set("min_argument_count", String::number(min_argument_count));
|
||||
function_generator.set("max_argument_count", String::number(max_argument_count));
|
||||
|
||||
if (name == "random") {
|
||||
function_generator.append(R"~~~(
|
||||
if (!context_allows_random_functions())
|
||||
return nullptr;
|
||||
)~~~");
|
||||
}
|
||||
|
||||
function_generator.append(R"~~~(
|
||||
if (arguments.size() < @min_argument_count@ || arguments.size() > @max_argument_count@) {
|
||||
ErrorReporter::the().report(InvalidValueError {
|
||||
|
|
@ -295,6 +304,14 @@ RefPtr<CalculationNode const> Parser::parse_math_function(Function const& functi
|
|||
} else {
|
||||
parameter_generator.set("parameter_default", ""_string);
|
||||
}
|
||||
} else if (parameter_type_string == "<random-value-sharing>") {
|
||||
parameter_is_calculation = false;
|
||||
parameter_generator.set("parameter_type", "RefPtr<RandomValueSharingStyleValue const>"_string);
|
||||
parameter_generator.set("parse_function", MUST(String::formatted("parse_random_value_sharing(tokens_{})", parameter_index)));
|
||||
parameter_generator.set("check_function", " != nullptr"_string);
|
||||
parameter_generator.set("release_function", ".release_nonnull()"_string);
|
||||
// FIXME: This should be 'auto' rather than 'fixed 0' by default
|
||||
parameter_generator.set("parameter_default", MUST(String::formatted(" = RandomValueSharingStyleValue::create_fixed(NumberStyleValue::create(0))")));
|
||||
} else {
|
||||
// NOTE: This assumes everything not handled above is a calculation node of some kind.
|
||||
parameter_is_calculation = true;
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ Harness status: OK
|
|||
|
||||
Found 72 tests
|
||||
|
||||
4 Pass
|
||||
68 Fail
|
||||
Fail Property scale value 'random(1, 11)'
|
||||
27 Pass
|
||||
45 Fail
|
||||
Pass Property scale value 'random(1, 11)'
|
||||
Fail Property scale value 'random(--foo, 2, 12)'
|
||||
Fail Property scale value 'random(--foo element-shared, 3, 13)'
|
||||
Fail Property scale value 'random(element-shared --foo, 4, 14)'
|
||||
|
|
@ -12,15 +12,15 @@ Fail Property scale value 'random(0, 10, 5)'
|
|||
Fail Property scale value 'random(--foo, 10, 20, 5)'
|
||||
Fail Property scale value 'random(--foo element-shared, 20, 30, 5)'
|
||||
Fail Property scale value 'random(element-shared --foo, 30, 40, 5)'
|
||||
Fail Property scale value 'random(100, 10)'
|
||||
Fail Property scale value 'random(-10, -100)'
|
||||
Fail Property scale value 'random(-100, -10)'
|
||||
Pass Property scale value 'random(100, 10)'
|
||||
Pass Property scale value 'random(-10, -100)'
|
||||
Pass Property scale value 'random(-100, -10)'
|
||||
Fail Property scale value 'random(40, 50, -5)'
|
||||
Fail Property scale value 'random(5 * 1, 30 / 2)'
|
||||
Fail Property scale value 'calc(2 * random(6, 16))'
|
||||
Fail Property scale value 'random(NaN, 100)'
|
||||
Fail Property scale value 'random(10, NaN)'
|
||||
Fail Property scale value 'random(NaN, NaN)'
|
||||
Pass Property scale value 'random(5 * 1, 30 / 2)'
|
||||
Pass Property scale value 'calc(2 * random(6, 16))'
|
||||
Pass Property scale value 'random(NaN, 100)'
|
||||
Pass Property scale value 'random(10, NaN)'
|
||||
Pass Property scale value 'random(NaN, NaN)'
|
||||
Fail Property scale value 'random(NaN, 100, 10)'
|
||||
Fail Property scale value 'random(10, NaN, 10)'
|
||||
Fail Property scale value 'random(NaN, NaN, 10)'
|
||||
|
|
@ -28,9 +28,9 @@ Fail Property scale value 'random(NaN, 100, NaN)'
|
|||
Fail Property scale value 'random(10, NaN, NaN)'
|
||||
Fail Property scale value 'random(NaN, NaN, NaN)'
|
||||
Fail Property scale value 'random(10, 100, NaN)'
|
||||
Fail Property scale value 'calc(10 + random(NaN, 100))'
|
||||
Fail Property scale value 'calc(10 + random(10, NaN))'
|
||||
Fail Property scale value 'calc(10 + random(NaN, NaN))'
|
||||
Pass Property scale value 'calc(10 + random(NaN, 100))'
|
||||
Pass Property scale value 'calc(10 + random(10, NaN))'
|
||||
Pass Property scale value 'calc(10 + random(NaN, NaN))'
|
||||
Fail Property scale value 'calc(10 + random(NaN, 100, 10))'
|
||||
Fail Property scale value 'calc(10 + random(10, NaN, 10))'
|
||||
Fail Property scale value 'calc(10 + random(NaN, NaN, 10))'
|
||||
|
|
@ -38,35 +38,35 @@ Fail Property scale value 'calc(10 + random(NaN, 100, NaN))'
|
|||
Fail Property scale value 'calc(10 + random(10, NaN, NaN))'
|
||||
Fail Property scale value 'calc(10 + random(NaN, NaN, NaN))'
|
||||
Fail Property scale value 'calc(10 + random(10, 100, NaN))'
|
||||
Fail Property scale value 'random(infinity, 100)'
|
||||
Fail Property scale value 'random(infinity, infinity)'
|
||||
Pass Property scale value 'random(infinity, 100)'
|
||||
Pass Property scale value 'random(infinity, infinity)'
|
||||
Fail Property scale value 'random(infinity, 100, 10)'
|
||||
Fail Property scale value 'random(infinity, infinity, 10)'
|
||||
Fail Property scale value 'random(infinity, 100, infinity)'
|
||||
Fail Property scale value 'random(infinity, infinity, infinity)'
|
||||
Fail Property scale value 'calc(10 + random(infinity, 100))'
|
||||
Fail Property scale value 'calc(10 + random(infinity, infinity))'
|
||||
Pass Property scale value 'calc(10 + random(infinity, 100))'
|
||||
Pass Property scale value 'calc(10 + random(infinity, infinity))'
|
||||
Fail Property scale value 'calc(10 + random(infinity, infinity, 10))'
|
||||
Fail Property scale value 'calc(10 + random(infinity, 100, infinity))'
|
||||
Fail Property scale value 'calc(10 + random(infinity, infinity, infinity))'
|
||||
Fail Property scale value 'calc(10 + random(infinity, 100, 10))'
|
||||
Fail Property scale value 'random(10, infinity)'
|
||||
Pass Property scale value 'random(10, infinity)'
|
||||
Fail Property scale value 'random(10, infinity, 10)'
|
||||
Fail Property scale value 'random(10, infinity, infinity)'
|
||||
Fail Property scale value 'calc(10 + random(10, infinity))'
|
||||
Pass Property scale value 'calc(10 + random(10, infinity))'
|
||||
Fail Property scale value 'calc(10 + random(10, infinity, 10))'
|
||||
Fail Property scale value 'calc(10 + random(10, infinity, infinity))'
|
||||
Fail Property scale value 'random(10, 100, infinity)'
|
||||
Fail Property scale value 'calc(10 + random(10, 100, infinity))'
|
||||
Fail Property scale value 'random(10, 100, -infinity)'
|
||||
Fail Property scale value 'calc(10 + random(10, 100, -infinity))'
|
||||
Fail Property scale value on pseudo element '::before' 'random(7, 17)'
|
||||
Pass Property scale value on pseudo element '::before' 'random(7, 17)'
|
||||
Fail Property scale value on pseudo element '::before' 'random(--bar, 8, 18)'
|
||||
Fail Property scale value on pseudo element '::before' 'random(element-shared, 9, 19)'
|
||||
Fail Property scale value on pseudo element '::before' 'random(element-shared --foo, 10, 20)'
|
||||
Fail Property translate value 'random(10%, 100%)'
|
||||
Fail Property translate value 'random(fixed random(1, 2), 10%, 100%)'
|
||||
Fail Property translate value 'random(fixed random(-2, -1), 10%, 100%)'
|
||||
Pass Property translate value 'random(10%, 100%)'
|
||||
Pass Property translate value 'random(fixed random(1, 2), 10%, 100%)'
|
||||
Pass Property translate value 'random(fixed random(-2, -1), 10%, 100%)'
|
||||
Fail Maximum random: 'random(a, b)'
|
||||
Fail Maximum random - shorthand: random(a, b))
|
||||
Fail Shared by name within an element: 'random(--identifier, a, b)'
|
||||
|
|
@ -75,4 +75,4 @@ Pass Shared between elements within a property: random(element-shared, a, b)
|
|||
Pass Shared between elements within a property - shorthand: random(element-shared, a, b))
|
||||
Fail Shared globally: random(--identifier element-shared, a, b)
|
||||
Pass Shared globally - shorthand: random(element-shared, a, b))
|
||||
Fail Fixed: random(fixed <number>, a, b)
|
||||
Pass Fixed: random(fixed <number>, a, b)
|
||||
|
|
@ -2,5 +2,5 @@ Harness status: OK
|
|||
|
||||
Found 1 tests
|
||||
|
||||
1 Fail
|
||||
Fail random() is not ignored in keyframe
|
||||
1 Pass
|
||||
Pass random() is not ignored in keyframe
|
||||
|
|
@ -25,4 +25,4 @@ Pass e.style['width'] = "random(fixed 0.5 --foo, 1px, 2px)" should not set the p
|
|||
Pass e.style['width'] = "random(fixed 0.5px, 1px, 2px)" should not set the property value
|
||||
Pass e.style['width'] = "random(fixed 0.5%, 1px, 2px)" should not set the property value
|
||||
Pass e.style['width'] = "random(fixed -1, 1px, 2px)" should not set the property value
|
||||
Pass e.style['width'] = "random(10deg, 20deg)" should not set the property value
|
||||
Pass e.style['width'] = "random(10deg, 20deg)" should not set the property value
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@ Harness status: OK
|
|||
|
||||
Found 32 tests
|
||||
|
||||
32 Fail
|
||||
2 Pass
|
||||
30 Fail
|
||||
Fail e.style['width'] = "random(0px, 100px)" should set the property value
|
||||
Fail e.style['width'] = "random(0px, 100px, 50px)" should set the property value
|
||||
Fail e.style['width'] = "random(--foo, 0px, 100px)" should set the property value
|
||||
|
|
@ -11,7 +12,7 @@ Fail e.style['width'] = "random(--foo element-shared, 0px, 100px)" should set th
|
|||
Fail e.style['width'] = "random(auto element-shared, 0px, 100px)" should set the property value
|
||||
Fail e.style['width'] = "random(element-shared --foo, 0px, 100px)" should set the property value
|
||||
Fail e.style['width'] = "random(element-shared auto, 0px, 100px)" should set the property value
|
||||
Fail e.style['width'] = "random(fixed 0.5, 0px, 100px)" should set the property value
|
||||
Pass e.style['width'] = "random(fixed 0.5, 0px, 100px)" should set the property value
|
||||
Fail e.style['width'] = "random(--foo, 0px, 100px, 50px)" should set the property value
|
||||
Fail e.style['width'] = "random(auto, 0px, 100px, 50px)" should set the property value
|
||||
Fail e.style['width'] = "random(--foo element-shared, 0px, 100px, 50px)" should set the property value
|
||||
|
|
@ -25,7 +26,7 @@ Fail e.style['width'] = "random(-100px, -10px)" should set the property value
|
|||
Fail e.style['width'] = "random(-100px, -10px, -5px)" should set the property value
|
||||
Fail e.style['width'] = "random(1em, 200rem)" should set the property value
|
||||
Fail e.style['width'] = "random(10 * 100px, 200em / 2)" should set the property value
|
||||
Fail e.style['width'] = "random(fixed calc(2 / 4), 0px, 100px)" should set the property value
|
||||
Pass e.style['width'] = "random(fixed calc(2 / 4), 0px, 100px)" should set the property value
|
||||
Fail e.style['width'] = "calc(2 * random(0px, 100px))" should set the property value
|
||||
Fail e.style['max-lines'] = "random(25, 50)" should set the property value
|
||||
Fail e.style['max-lines'] = "random(25, 50, 5)" should set the property value
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue