LibWeb/HTML: Correct color parsing for CanvasGradient color

This resolves all WPT timeouts in
wpt/html/canvas/offscreen/fill-and-stroke-styles
This commit is contained in:
ljamar 2025-09-19 18:39:30 +02:00 committed by Jelle Raaijmakers
parent ce16bdd07d
commit 0d62803f15
3 changed files with 26 additions and 3 deletions

View File

@ -8,6 +8,7 @@
#include <AK/QuickSort.h>
#include <LibWeb/Bindings/CanvasGradientPrototype.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/CSS/Parser/Parser.h>
#include <LibWeb/HTML/CanvasGradient.h>
#include <LibWeb/WebIDL/ExceptionOr.h>
@ -64,14 +65,17 @@ WebIDL::ExceptionOr<void> CanvasGradient::add_color_stop(double offset, StringVi
return WebIDL::IndexSizeError::create(realm(), "CanvasGradient color stop offset out of bounds"_utf16);
// 2. Let parsed color be the result of parsing color.
auto parsed_color = Color::from_string(color);
// https://drafts.csswg.org/css-color/#parse-a-css-color-value
auto const maybe_color = parse_css_value(CSS::Parser::ParsingParams(), color, CSS::PropertyID::Color);
// 3. If parsed color is failure, throw a "SyntaxError" DOMException.
if (!parsed_color.has_value())
if (maybe_color.is_null() || !maybe_color->has_color())
return WebIDL::SyntaxError::create(realm(), "Could not parse color for CanvasGradient"_utf16);
auto const parsed_color = maybe_color->to_color({}).value();
// 4. Place a new stop on the gradient, at offset offset relative to the whole gradient, and with the color parsed color.
TRY_OR_THROW_OOM(realm().vm(), m_gradient->add_color_stop(offset, parsed_color.value()));
TRY_OR_THROW_OOM(realm().vm(), m_gradient->add_color_stop(offset, parsed_color));
// FIXME: If multiple stops are added at the same offset on a gradient, then they must be placed in the order added,
// with the first one closest to the start of the gradient, and each subsequent one infinitesimally further along

View File

@ -0,0 +1,18 @@
<!DOCTYPE html>
<script src="../include.js"></script>
<canvas id="canvas" width="100" height="50"> </canvas>
<script>
test(() => {
try {
const canvas = document.getElementById("canvas");
const context = canvas.getContext("2d");
var gradient = context.createLinearGradient(0, 0, 100, 0);
gradient.addColorStop(0, "color(srgb 1 0 0)");
gradient.addColorStop(1, "color(srgb 0 1 0)");
println("PASS");
} catch (e) {
println("FAIL");
}
});
</script>