mirror of
https://github.com/lexmount/moli.git
synced 2026-10-09 08:01:05 +00:00
fix(svg): reflect animated length attributes
This commit is contained in:
@@ -1298,6 +1298,18 @@ struct SvgTextPositioningElementPrototypeAccessorsDeclaration {
|
||||
#[derive(WebApiFunctionTemplate)]
|
||||
#[webapi(interface = web_api_interfaces::SVGPatternElement, enumerable)]
|
||||
struct SvgPatternElementPrototypeAccessorsDeclaration {
|
||||
#[webapi(accessor_property = "x", getter = svg_pattern_animated_length_getter, data = callback_data_index_value(scope, 0))]
|
||||
x: (),
|
||||
|
||||
#[webapi(accessor_property = "y", getter = svg_pattern_animated_length_getter, data = callback_data_index_value(scope, 1))]
|
||||
y: (),
|
||||
|
||||
#[webapi(accessor_property = "width", getter = svg_pattern_animated_length_getter, data = callback_data_index_value(scope, 2))]
|
||||
width: (),
|
||||
|
||||
#[webapi(accessor_property = "height", getter = svg_pattern_animated_length_getter, data = callback_data_index_value(scope, 3))]
|
||||
height: (),
|
||||
|
||||
#[webapi(
|
||||
accessor_property = "patternUnits",
|
||||
getter = svg_element_animated_enumeration_getter,
|
||||
@@ -1337,6 +1349,60 @@ struct SvgGradientElementPrototypeAccessorsDeclaration {
|
||||
gradient_transform: (),
|
||||
}
|
||||
|
||||
#[derive(WebApiFunctionTemplate)]
|
||||
#[webapi(interface = web_api_interfaces::SVGLinearGradientElement, enumerable)]
|
||||
struct SvgLinearGradientElementPrototypeAccessorsDeclaration {
|
||||
#[webapi(accessor_property = "x1", getter = svg_linear_gradient_animated_length_getter, data = callback_data_index_value(scope, 0))]
|
||||
x1: (),
|
||||
|
||||
#[webapi(accessor_property = "y1", getter = svg_linear_gradient_animated_length_getter, data = callback_data_index_value(scope, 1))]
|
||||
y1: (),
|
||||
|
||||
#[webapi(accessor_property = "x2", getter = svg_linear_gradient_animated_length_getter, data = callback_data_index_value(scope, 2))]
|
||||
x2: (),
|
||||
|
||||
#[webapi(accessor_property = "y2", getter = svg_linear_gradient_animated_length_getter, data = callback_data_index_value(scope, 3))]
|
||||
y2: (),
|
||||
}
|
||||
|
||||
#[derive(WebApiFunctionTemplate)]
|
||||
#[webapi(interface = web_api_interfaces::SVGRadialGradientElement, enumerable)]
|
||||
struct SvgRadialGradientElementPrototypeAccessorsDeclaration {
|
||||
#[webapi(accessor_property = "cx", getter = svg_radial_gradient_animated_length_getter, data = callback_data_index_value(scope, 0))]
|
||||
cx: (),
|
||||
|
||||
#[webapi(accessor_property = "cy", getter = svg_radial_gradient_animated_length_getter, data = callback_data_index_value(scope, 1))]
|
||||
cy: (),
|
||||
|
||||
#[webapi(accessor_property = "r", getter = svg_radial_gradient_animated_length_getter, data = callback_data_index_value(scope, 2))]
|
||||
r: (),
|
||||
|
||||
#[webapi(accessor_property = "fx", getter = svg_radial_gradient_animated_length_getter, data = callback_data_index_value(scope, 3))]
|
||||
fx: (),
|
||||
|
||||
#[webapi(accessor_property = "fy", getter = svg_radial_gradient_animated_length_getter, data = callback_data_index_value(scope, 4))]
|
||||
fy: (),
|
||||
|
||||
#[webapi(accessor_property = "fr", getter = svg_radial_gradient_animated_length_getter, data = callback_data_index_value(scope, 5))]
|
||||
fr: (),
|
||||
}
|
||||
|
||||
#[derive(WebApiFunctionTemplate)]
|
||||
#[webapi(interface = web_api_interfaces::SVGSVGElement, enumerable)]
|
||||
struct SvgSvgElementPrototypeAccessorsDeclaration {
|
||||
#[webapi(accessor_property = "x", getter = svg_svg_animated_length_getter, data = callback_data_index_value(scope, 0))]
|
||||
x: (),
|
||||
|
||||
#[webapi(accessor_property = "y", getter = svg_svg_animated_length_getter, data = callback_data_index_value(scope, 1))]
|
||||
y: (),
|
||||
|
||||
#[webapi(accessor_property = "width", getter = svg_svg_animated_length_getter, data = callback_data_index_value(scope, 2))]
|
||||
width: (),
|
||||
|
||||
#[webapi(accessor_property = "height", getter = svg_svg_animated_length_getter, data = callback_data_index_value(scope, 3))]
|
||||
height: (),
|
||||
}
|
||||
|
||||
#[derive(WebApiFunctionTemplate)]
|
||||
#[webapi(interface = web_api_interfaces::SVGClipPathElement, enumerable)]
|
||||
struct SvgClipPathElementPrototypeAccessorsDeclaration {
|
||||
@@ -1351,6 +1417,18 @@ struct SvgClipPathElementPrototypeAccessorsDeclaration {
|
||||
#[derive(WebApiFunctionTemplate)]
|
||||
#[webapi(interface = web_api_interfaces::SVGFilterElement, enumerable)]
|
||||
struct SvgFilterElementPrototypeAccessorsDeclaration {
|
||||
#[webapi(accessor_property = "x", getter = svg_filter_animated_length_getter, data = callback_data_index_value(scope, 0))]
|
||||
x: (),
|
||||
|
||||
#[webapi(accessor_property = "y", getter = svg_filter_animated_length_getter, data = callback_data_index_value(scope, 1))]
|
||||
y: (),
|
||||
|
||||
#[webapi(accessor_property = "width", getter = svg_filter_animated_length_getter, data = callback_data_index_value(scope, 2))]
|
||||
width: (),
|
||||
|
||||
#[webapi(accessor_property = "height", getter = svg_filter_animated_length_getter, data = callback_data_index_value(scope, 3))]
|
||||
height: (),
|
||||
|
||||
#[webapi(
|
||||
accessor_property = "filterUnits",
|
||||
getter = svg_element_animated_enumeration_getter,
|
||||
@@ -1366,6 +1444,22 @@ struct SvgFilterElementPrototypeAccessorsDeclaration {
|
||||
primitive_units: (),
|
||||
}
|
||||
|
||||
#[derive(WebApiFunctionTemplate)]
|
||||
#[webapi(name = "SVGFilterPrimitiveStandardAttributes", enumerable)]
|
||||
struct SvgFilterPrimitiveStandardAttributesPrototypeAccessorsDeclaration {
|
||||
#[webapi(accessor_property = "x", getter = svg_filter_primitive_animated_length_getter, data = callback_data_index_value(scope, 0))]
|
||||
x: (),
|
||||
|
||||
#[webapi(accessor_property = "y", getter = svg_filter_primitive_animated_length_getter, data = callback_data_index_value(scope, 1))]
|
||||
y: (),
|
||||
|
||||
#[webapi(accessor_property = "width", getter = svg_filter_primitive_animated_length_getter, data = callback_data_index_value(scope, 2))]
|
||||
width: (),
|
||||
|
||||
#[webapi(accessor_property = "height", getter = svg_filter_primitive_animated_length_getter, data = callback_data_index_value(scope, 3))]
|
||||
height: (),
|
||||
}
|
||||
|
||||
#[derive(WebApiFunctionTemplate)]
|
||||
#[webapi(interface = web_api_interfaces::SVGComponentTransferFunctionElement, enumerable)]
|
||||
struct SvgComponentTransferFunctionElementPrototypeAccessorsDeclaration {
|
||||
@@ -1512,6 +1606,9 @@ struct SvgFeTurbulenceElementPrototypeAccessorsDeclaration {
|
||||
#[derive(WebApiFunctionTemplate)]
|
||||
#[webapi(interface = web_api_interfaces::SVGTextPathElement, enumerable)]
|
||||
struct SvgTextPathElementPrototypeAccessorsDeclaration {
|
||||
#[webapi(accessor_property = "startOffset", getter = svg_text_path_animated_length_getter, data = callback_data_index_value(scope, 0))]
|
||||
start_offset: (),
|
||||
|
||||
#[webapi(
|
||||
accessor_property = "method",
|
||||
getter = svg_element_animated_enumeration_getter,
|
||||
@@ -1537,6 +1634,18 @@ struct SvgTextPathElementPrototypeAccessorsDeclaration {
|
||||
#[derive(WebApiFunctionTemplate)]
|
||||
#[webapi(interface = web_api_interfaces::SVGMaskElement, enumerable)]
|
||||
struct SvgMaskElementPrototypeAccessorsDeclaration {
|
||||
#[webapi(accessor_property = "x", getter = svg_mask_animated_length_getter, data = callback_data_index_value(scope, 0))]
|
||||
x: (),
|
||||
|
||||
#[webapi(accessor_property = "y", getter = svg_mask_animated_length_getter, data = callback_data_index_value(scope, 1))]
|
||||
y: (),
|
||||
|
||||
#[webapi(accessor_property = "width", getter = svg_mask_animated_length_getter, data = callback_data_index_value(scope, 2))]
|
||||
width: (),
|
||||
|
||||
#[webapi(accessor_property = "height", getter = svg_mask_animated_length_getter, data = callback_data_index_value(scope, 3))]
|
||||
height: (),
|
||||
|
||||
#[webapi(
|
||||
accessor_property = "maskUnits",
|
||||
getter = svg_element_animated_enumeration_getter,
|
||||
@@ -1638,6 +1747,18 @@ struct SvgGraphicsBoxElementPrototypeAccessorsDeclaration {
|
||||
#[derive(WebApiFunctionTemplate)]
|
||||
#[webapi(interface = web_api_interfaces::SVGMarkerElement, enumerable)]
|
||||
struct SvgMarkerElementPrototypeAccessorsDeclaration {
|
||||
#[webapi(accessor_property = "refX", getter = svg_marker_animated_length_getter, data = callback_data_index_value(scope, 0))]
|
||||
ref_x: (),
|
||||
|
||||
#[webapi(accessor_property = "refY", getter = svg_marker_animated_length_getter, data = callback_data_index_value(scope, 1))]
|
||||
ref_y: (),
|
||||
|
||||
#[webapi(accessor_property = "markerWidth", getter = svg_marker_animated_length_getter, data = callback_data_index_value(scope, 2))]
|
||||
marker_width: (),
|
||||
|
||||
#[webapi(accessor_property = "markerHeight", getter = svg_marker_animated_length_getter, data = callback_data_index_value(scope, 3))]
|
||||
marker_height: (),
|
||||
|
||||
#[webapi(
|
||||
accessor_property = "markerUnits",
|
||||
getter = svg_element_animated_enumeration_getter,
|
||||
@@ -1971,6 +2092,20 @@ pub(super) fn install_svg_element_accessor_bindings<'s>(
|
||||
interface_name: &str,
|
||||
) {
|
||||
let prototype = template.prototype_template(scope);
|
||||
if matches!(
|
||||
interface_name,
|
||||
"SVGFEBlendElement"
|
||||
| "SVGFEColorMatrixElement"
|
||||
| "SVGFECompositeElement"
|
||||
| "SVGFEConvolveMatrixElement"
|
||||
| "SVGFEDisplacementMapElement"
|
||||
| "SVGFEMorphologyElement"
|
||||
| "SVGFETurbulenceElement"
|
||||
) {
|
||||
SvgFilterPrimitiveStandardAttributesPrototypeAccessorsDeclaration::initialize_prototype_template(
|
||||
scope, prototype,
|
||||
);
|
||||
}
|
||||
match interface_name {
|
||||
"SVGElement" => {
|
||||
SvgElementPrototypeAccessorsDeclaration::initialize_prototype_template(
|
||||
@@ -2073,6 +2208,27 @@ pub(super) fn install_svg_element_accessor_bindings<'s>(
|
||||
scope, prototype,
|
||||
);
|
||||
}
|
||||
"SVGLinearGradientElement" => {
|
||||
SvgLinearGradientElementPrototypeAccessorsDeclaration::initialize_prototype_template(
|
||||
scope, prototype,
|
||||
);
|
||||
SvgUriReferencePrototypeAccessorsDeclaration::initialize_prototype_template(
|
||||
scope, prototype,
|
||||
);
|
||||
}
|
||||
"SVGRadialGradientElement" => {
|
||||
SvgRadialGradientElementPrototypeAccessorsDeclaration::initialize_prototype_template(
|
||||
scope, prototype,
|
||||
);
|
||||
SvgUriReferencePrototypeAccessorsDeclaration::initialize_prototype_template(
|
||||
scope, prototype,
|
||||
);
|
||||
}
|
||||
"SVGSVGElement" => {
|
||||
SvgSvgElementPrototypeAccessorsDeclaration::initialize_prototype_template(
|
||||
scope, prototype,
|
||||
);
|
||||
}
|
||||
"SVGRectElement" => {
|
||||
SvgRectElementPrototypeAccessorsDeclaration::initialize_prototype_template(
|
||||
scope, prototype,
|
||||
@@ -2103,10 +2259,7 @@ pub(super) fn install_svg_element_accessor_bindings<'s>(
|
||||
scope, prototype,
|
||||
);
|
||||
}
|
||||
"SVGAElement"
|
||||
| "SVGLinearGradientElement"
|
||||
| "SVGRadialGradientElement"
|
||||
| "SVGScriptElement" => {
|
||||
"SVGAElement" | "SVGScriptElement" => {
|
||||
SvgUriReferencePrototypeAccessorsDeclaration::initialize_prototype_template(
|
||||
scope, prototype,
|
||||
);
|
||||
|
||||
@@ -1095,26 +1095,13 @@ pub(super) fn build_svg_matrix<'s>(
|
||||
.expect("SVGMatrix declaration should bind")
|
||||
}
|
||||
|
||||
pub(super) fn build_svg_animated_length<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
value: f64,
|
||||
) -> v8::Local<'s, v8::Object> {
|
||||
let base_val = build_svg_length(scope, value);
|
||||
let anim_val = build_svg_length(scope, value);
|
||||
SvgAnimatedLengthObjectDeclaration::new(base_val, anim_val)
|
||||
.bind(scope)
|
||||
.expect("SVGAnimatedLength declaration should bind")
|
||||
}
|
||||
|
||||
pub(super) fn build_svg_animated_length_for_attribute<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
owner: v8::Local<'s, v8::Object>,
|
||||
attribute: &str,
|
||||
initial_value: &str,
|
||||
) -> v8::Local<'s, v8::Object> {
|
||||
let parsed = svg_owner_attribute_value(scope, owner, attribute)
|
||||
.as_deref()
|
||||
.and_then(parse_svg_length_value)
|
||||
.unwrap_or_default();
|
||||
let parsed = svg_animated_length_attribute_value(scope, owner, attribute, initial_value);
|
||||
let base_val = build_svg_length_from_parsed(scope, parsed);
|
||||
set_svg_length_owner_attribute(scope, base_val, owner, attribute);
|
||||
let anim_val = build_svg_length_from_parsed(scope, parsed);
|
||||
@@ -2427,6 +2414,15 @@ pub(super) fn svg_animated_length_attribute_slot(name: &str) -> &'static str {
|
||||
"y1" => "__moliSvgAnimatedY1",
|
||||
"x2" => "__moliSvgAnimatedX2",
|
||||
"y2" => "__moliSvgAnimatedY2",
|
||||
"fx" => "__moliSvgAnimatedFx",
|
||||
"fy" => "__moliSvgAnimatedFy",
|
||||
"fr" => "__moliSvgAnimatedFr",
|
||||
"refX" => "__moliSvgAnimatedRefX",
|
||||
"refY" => "__moliSvgAnimatedRefY",
|
||||
"markerWidth" => "__moliSvgAnimatedMarkerWidth",
|
||||
"markerHeight" => "__moliSvgAnimatedMarkerHeight",
|
||||
"textLength" => SVG_TEXT_CONTENT_TEXT_LENGTH_SLOT,
|
||||
"startOffset" => "__moliSvgAnimatedStartOffset",
|
||||
_ => "__moliSvgAnimatedUnknown",
|
||||
}
|
||||
}
|
||||
@@ -2833,11 +2829,9 @@ pub(super) fn sync_svg_animated_length_from_owner_attribute<'s>(
|
||||
animated: v8::Local<'s, v8::Object>,
|
||||
owner: v8::Local<'s, v8::Object>,
|
||||
attribute: &str,
|
||||
initial_value: &str,
|
||||
) {
|
||||
let parsed = svg_owner_attribute_value(scope, owner, attribute)
|
||||
.as_deref()
|
||||
.and_then(parse_svg_length_value)
|
||||
.unwrap_or_default();
|
||||
let parsed = svg_animated_length_attribute_value(scope, owner, attribute, initial_value);
|
||||
if let Some(base_val) = get_private_value(scope, animated, SVG_ANIMATED_LENGTH_BASE_VAL_SLOT)
|
||||
.and_then(|value| v8::Local::<v8::Object>::try_from(value).ok())
|
||||
{
|
||||
@@ -2851,6 +2845,19 @@ pub(super) fn sync_svg_animated_length_from_owner_attribute<'s>(
|
||||
}
|
||||
}
|
||||
|
||||
fn svg_animated_length_attribute_value<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
owner: v8::Local<'s, v8::Object>,
|
||||
attribute: &str,
|
||||
initial_value: &str,
|
||||
) -> SvgParsedLength {
|
||||
svg_owner_attribute_value(scope, owner, attribute)
|
||||
.as_deref()
|
||||
.and_then(parse_svg_length_value)
|
||||
.or_else(|| parse_svg_length_value(initial_value))
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub(super) fn set_svg_animated_string_owner_attribute<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
animated: v8::Local<'s, v8::Object>,
|
||||
|
||||
@@ -4,11 +4,57 @@ use crate::util::serialize_v8_array;
|
||||
use crate::web_api_interfaces;
|
||||
use moli_webapi_declare::DataPropertyDescriptorDeclaration;
|
||||
|
||||
const SVG_RECT_ANIMATED_LENGTH_ATTRIBUTES: &[&str] = &["x", "y", "width", "height", "rx", "ry"];
|
||||
const SVG_CIRCLE_ANIMATED_LENGTH_ATTRIBUTES: &[&str] = &["cx", "cy", "r"];
|
||||
const SVG_ELLIPSE_ANIMATED_LENGTH_ATTRIBUTES: &[&str] = &["cx", "cy", "rx", "ry"];
|
||||
const SVG_LINE_ANIMATED_LENGTH_ATTRIBUTES: &[&str] = &["x1", "y1", "x2", "y2"];
|
||||
const SVG_BOX_ANIMATED_LENGTH_ATTRIBUTES: &[&str] = &["x", "y", "width", "height"];
|
||||
const SVG_RECT_ANIMATED_LENGTH_ATTRIBUTES: &[(&str, &str)] = &[
|
||||
("x", "0"),
|
||||
("y", "0"),
|
||||
("width", "0"),
|
||||
("height", "0"),
|
||||
("rx", "0"),
|
||||
("ry", "0"),
|
||||
];
|
||||
const SVG_CIRCLE_ANIMATED_LENGTH_ATTRIBUTES: &[(&str, &str)] =
|
||||
&[("cx", "0"), ("cy", "0"), ("r", "0")];
|
||||
const SVG_ELLIPSE_ANIMATED_LENGTH_ATTRIBUTES: &[(&str, &str)] =
|
||||
&[("cx", "0"), ("cy", "0"), ("rx", "0"), ("ry", "0")];
|
||||
const SVG_LINE_ANIMATED_LENGTH_ATTRIBUTES: &[(&str, &str)] =
|
||||
&[("x1", "0"), ("y1", "0"), ("x2", "0"), ("y2", "0")];
|
||||
const SVG_BOX_ANIMATED_LENGTH_ATTRIBUTES: &[(&str, &str)] =
|
||||
&[("x", "0"), ("y", "0"), ("width", "0"), ("height", "0")];
|
||||
const SVG_FILTER_ANIMATED_LENGTH_ATTRIBUTES: &[(&str, &str)] = &[
|
||||
("x", "-10%"),
|
||||
("y", "-10%"),
|
||||
("width", "120%"),
|
||||
("height", "120%"),
|
||||
];
|
||||
const SVG_FILTER_PRIMITIVE_ANIMATED_LENGTH_ATTRIBUTES: &[(&str, &str)] = &[
|
||||
("x", "0%"),
|
||||
("y", "0%"),
|
||||
("width", "100%"),
|
||||
("height", "100%"),
|
||||
];
|
||||
const SVG_LINEAR_GRADIENT_ANIMATED_LENGTH_ATTRIBUTES: &[(&str, &str)] =
|
||||
&[("x1", "0%"), ("y1", "0%"), ("x2", "100%"), ("y2", "0%")];
|
||||
const SVG_RADIAL_GRADIENT_ANIMATED_LENGTH_ATTRIBUTES: &[(&str, &str)] = &[
|
||||
("cx", "50%"),
|
||||
("cy", "50%"),
|
||||
("r", "50%"),
|
||||
("fx", "50%"),
|
||||
("fy", "50%"),
|
||||
("fr", "0%"),
|
||||
];
|
||||
const SVG_MARKER_ANIMATED_LENGTH_ATTRIBUTES: &[(&str, &str)] = &[
|
||||
("refX", "0"),
|
||||
("refY", "0"),
|
||||
("markerWidth", "3"),
|
||||
("markerHeight", "3"),
|
||||
];
|
||||
const SVG_SVG_ANIMATED_LENGTH_ATTRIBUTES: &[(&str, &str)] = &[
|
||||
("x", "0"),
|
||||
("y", "0"),
|
||||
("width", "100%"),
|
||||
("height", "100%"),
|
||||
];
|
||||
const SVG_TEXT_PATH_ANIMATED_LENGTH_ATTRIBUTES: &[(&str, &str)] = &[("startOffset", "0")];
|
||||
const SVG_LENGTH_ACCESSOR_NAMES: &[&str] = &[
|
||||
"unitType",
|
||||
"value",
|
||||
@@ -378,27 +424,168 @@ pub(super) fn svg_box_animated_length_getter<'s>(
|
||||
);
|
||||
}
|
||||
|
||||
pub(super) fn svg_filter_animated_length_getter<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
args: v8::FunctionCallbackArguments<'s>,
|
||||
rv: v8::ReturnValue<'_, v8::Value>,
|
||||
) {
|
||||
svg_element_animated_length_getter(
|
||||
scope,
|
||||
&args,
|
||||
rv,
|
||||
SVG_FILTER_ANIMATED_LENGTH_ATTRIBUTES,
|
||||
"SVGFilterElement animated length attributes",
|
||||
);
|
||||
}
|
||||
|
||||
pub(super) fn svg_filter_primitive_animated_length_getter<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
args: v8::FunctionCallbackArguments<'s>,
|
||||
rv: v8::ReturnValue<'_, v8::Value>,
|
||||
) {
|
||||
svg_element_animated_length_getter(
|
||||
scope,
|
||||
&args,
|
||||
rv,
|
||||
SVG_FILTER_PRIMITIVE_ANIMATED_LENGTH_ATTRIBUTES,
|
||||
"SVGFilterPrimitiveStandardAttributes animated length attributes",
|
||||
);
|
||||
}
|
||||
|
||||
pub(super) fn svg_pattern_animated_length_getter<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
args: v8::FunctionCallbackArguments<'s>,
|
||||
rv: v8::ReturnValue<'_, v8::Value>,
|
||||
) {
|
||||
svg_element_animated_length_getter(
|
||||
scope,
|
||||
&args,
|
||||
rv,
|
||||
SVG_BOX_ANIMATED_LENGTH_ATTRIBUTES,
|
||||
"SVGPatternElement animated length attributes",
|
||||
);
|
||||
}
|
||||
|
||||
pub(super) fn svg_linear_gradient_animated_length_getter<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
args: v8::FunctionCallbackArguments<'s>,
|
||||
rv: v8::ReturnValue<'_, v8::Value>,
|
||||
) {
|
||||
svg_element_animated_length_getter(
|
||||
scope,
|
||||
&args,
|
||||
rv,
|
||||
SVG_LINEAR_GRADIENT_ANIMATED_LENGTH_ATTRIBUTES,
|
||||
"SVGLinearGradientElement animated length attributes",
|
||||
);
|
||||
}
|
||||
|
||||
pub(super) fn svg_radial_gradient_animated_length_getter<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
args: v8::FunctionCallbackArguments<'s>,
|
||||
rv: v8::ReturnValue<'_, v8::Value>,
|
||||
) {
|
||||
svg_element_animated_length_getter(
|
||||
scope,
|
||||
&args,
|
||||
rv,
|
||||
SVG_RADIAL_GRADIENT_ANIMATED_LENGTH_ATTRIBUTES,
|
||||
"SVGRadialGradientElement animated length attributes",
|
||||
);
|
||||
}
|
||||
|
||||
pub(super) fn svg_marker_animated_length_getter<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
args: v8::FunctionCallbackArguments<'s>,
|
||||
rv: v8::ReturnValue<'_, v8::Value>,
|
||||
) {
|
||||
svg_element_animated_length_getter(
|
||||
scope,
|
||||
&args,
|
||||
rv,
|
||||
SVG_MARKER_ANIMATED_LENGTH_ATTRIBUTES,
|
||||
"SVGMarkerElement animated length attributes",
|
||||
);
|
||||
}
|
||||
|
||||
pub(super) fn svg_mask_animated_length_getter<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
args: v8::FunctionCallbackArguments<'s>,
|
||||
rv: v8::ReturnValue<'_, v8::Value>,
|
||||
) {
|
||||
svg_element_animated_length_getter(
|
||||
scope,
|
||||
&args,
|
||||
rv,
|
||||
SVG_FILTER_ANIMATED_LENGTH_ATTRIBUTES,
|
||||
"SVGMaskElement animated length attributes",
|
||||
);
|
||||
}
|
||||
|
||||
pub(super) fn svg_svg_animated_length_getter<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
args: v8::FunctionCallbackArguments<'s>,
|
||||
rv: v8::ReturnValue<'_, v8::Value>,
|
||||
) {
|
||||
svg_element_animated_length_getter(
|
||||
scope,
|
||||
&args,
|
||||
rv,
|
||||
SVG_SVG_ANIMATED_LENGTH_ATTRIBUTES,
|
||||
"SVGSVGElement animated length attributes",
|
||||
);
|
||||
}
|
||||
|
||||
pub(super) fn svg_text_path_animated_length_getter<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
args: v8::FunctionCallbackArguments<'s>,
|
||||
rv: v8::ReturnValue<'_, v8::Value>,
|
||||
) {
|
||||
svg_element_animated_length_getter(
|
||||
scope,
|
||||
&args,
|
||||
rv,
|
||||
SVG_TEXT_PATH_ANIMATED_LENGTH_ATTRIBUTES,
|
||||
"SVGTextPathElement animated length attributes",
|
||||
);
|
||||
}
|
||||
|
||||
fn svg_element_animated_length_getter<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
args: &v8::FunctionCallbackArguments<'s>,
|
||||
mut rv: v8::ReturnValue<'_, v8::Value>,
|
||||
attributes: &'static [&'static str],
|
||||
attributes: &'static [(&'static str, &'static str)],
|
||||
label: &'static str,
|
||||
) {
|
||||
let Some(name) = callback_data_item(scope, args, attributes, label) else {
|
||||
let Some((name, initial_value)) = callback_data_item(scope, args, attributes, label) else {
|
||||
rv.set_undefined();
|
||||
return;
|
||||
};
|
||||
svg_animated_length_attribute_getter(scope, args.this(), rv, name, initial_value);
|
||||
}
|
||||
|
||||
fn svg_animated_length_attribute_getter<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
owner: v8::Local<'s, v8::Object>,
|
||||
mut rv: v8::ReturnValue<'_, v8::Value>,
|
||||
name: &'static str,
|
||||
initial_value: &'static str,
|
||||
) {
|
||||
let slot = svg_animated_length_attribute_slot(name);
|
||||
let owner = args.this();
|
||||
if let Some(value) = get_private_value(scope, owner, slot) {
|
||||
if let Ok(object) = v8::Local::<v8::Object>::try_from(value) {
|
||||
sync_svg_animated_length_from_owner_attribute(scope, object, owner, name);
|
||||
sync_svg_animated_length_from_owner_attribute(
|
||||
scope,
|
||||
object,
|
||||
owner,
|
||||
name,
|
||||
initial_value,
|
||||
);
|
||||
}
|
||||
rv.set(value);
|
||||
return;
|
||||
}
|
||||
let value = build_svg_animated_length_for_attribute(scope, owner, name);
|
||||
let value = build_svg_animated_length_for_attribute(scope, owner, name, initial_value);
|
||||
set_private_value(scope, owner, slot, value.into());
|
||||
rv.set(value.into());
|
||||
}
|
||||
@@ -662,21 +849,9 @@ pub(super) fn svg_geometry_path_length_getter<'s>(
|
||||
pub(super) fn svg_text_content_text_length_getter<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
args: v8::FunctionCallbackArguments<'s>,
|
||||
mut rv: v8::ReturnValue<'_, v8::Value>,
|
||||
rv: v8::ReturnValue<'_, v8::Value>,
|
||||
) {
|
||||
let holder = args.this();
|
||||
if let Some(value) = get_private_value(scope, holder, SVG_TEXT_CONTENT_TEXT_LENGTH_SLOT) {
|
||||
rv.set(value);
|
||||
return;
|
||||
}
|
||||
let value = build_svg_animated_length(scope, 0.0);
|
||||
set_private_value(
|
||||
scope,
|
||||
holder,
|
||||
SVG_TEXT_CONTENT_TEXT_LENGTH_SLOT,
|
||||
value.into(),
|
||||
);
|
||||
rv.set(value.into());
|
||||
svg_animated_length_attribute_getter(scope, args.this(), rv, "textLength", "0");
|
||||
}
|
||||
|
||||
pub(super) fn svg_element_animated_enumeration_getter<'s>(
|
||||
|
||||
@@ -1649,6 +1649,97 @@ fn svg_owner_svg_element_tracks_the_nearest_svg_fragment_root() {
|
||||
assert_eq!(result, "ok");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn svg_animated_lengths_reflect_initial_and_content_attribute_values() {
|
||||
let mut vm = new_parsed_test_vm(
|
||||
"https://svg-animated-length-reflection.test/",
|
||||
"<!doctype html><html><head></head><body></body></html>",
|
||||
);
|
||||
|
||||
let result = vm
|
||||
.eval(
|
||||
r#"
|
||||
(() => {
|
||||
const assert = (condition, message) => {
|
||||
if (!condition) throw new Error(message);
|
||||
};
|
||||
const ns = "http://www.w3.org/2000/svg";
|
||||
const cases = [
|
||||
["filter", SVGFilterElement, [
|
||||
["x", "-10%"], ["y", "-10%"],
|
||||
["width", "120%"], ["height", "120%"],
|
||||
]],
|
||||
["feBlend", SVGFEBlendElement, [
|
||||
["x", "0%"], ["y", "0%"],
|
||||
["width", "100%"], ["height", "100%"],
|
||||
]],
|
||||
["linearGradient", SVGLinearGradientElement, [
|
||||
["x1", "0%"], ["y1", "0%"], ["x2", "100%"], ["y2", "0%"],
|
||||
]],
|
||||
["marker", SVGMarkerElement, [
|
||||
["refX", "0"], ["refY", "0"],
|
||||
["markerWidth", "3"], ["markerHeight", "3"],
|
||||
]],
|
||||
["mask", SVGMaskElement, [
|
||||
["x", "-10%"], ["y", "-10%"],
|
||||
["width", "120%"], ["height", "120%"],
|
||||
]],
|
||||
["pattern", SVGPatternElement, [
|
||||
["x", "0"], ["y", "0"], ["width", "0"], ["height", "0"],
|
||||
]],
|
||||
["radialGradient", SVGRadialGradientElement, [
|
||||
["cx", "50%"], ["cy", "50%"], ["r", "50%"],
|
||||
["fx", "50%"], ["fy", "50%"], ["fr", "0%"],
|
||||
]],
|
||||
["svg", SVGSVGElement, [
|
||||
["x", "0"], ["y", "0"], ["width", "100%"], ["height", "100%"],
|
||||
]],
|
||||
["text", SVGTextContentElement, [["textLength", "0"]]],
|
||||
["textPath", SVGTextPathElement, [["startOffset", "0"]]],
|
||||
];
|
||||
|
||||
for (const [tag, owner, attributes] of cases) {
|
||||
const element = document.createElementNS(ns, tag);
|
||||
for (const [name, initial] of attributes) {
|
||||
const descriptor = Object.getOwnPropertyDescriptor(owner.prototype, name);
|
||||
assert(typeof descriptor?.get === "function", `${owner.name}.${name} getter`);
|
||||
assert(descriptor.set === undefined, `${owner.name}.${name} setter`);
|
||||
assert(descriptor.enumerable && descriptor.configurable,
|
||||
`${owner.name}.${name} flags`);
|
||||
|
||||
const animated = element[name];
|
||||
assert(animated instanceof SVGAnimatedLength, `${tag}.${name} interface`);
|
||||
assert(element[name] === animated, `${tag}.${name} SameObject`);
|
||||
assert(animated.baseVal.valueAsString === initial,
|
||||
`${tag}.${name} initial baseVal`);
|
||||
assert(animated.animVal.valueAsString === initial,
|
||||
`${tag}.${name} initial animVal`);
|
||||
|
||||
element.setAttribute(name, "42");
|
||||
assert(element[name] === animated, `${tag}.${name} SameObject after set`);
|
||||
assert(animated.baseVal.valueAsString === "42" &&
|
||||
animated.animVal.valueAsString === "42", `${tag}.${name} content update`);
|
||||
|
||||
element.setAttribute(name, "foobar");
|
||||
assert(element[name] === animated, `${tag}.${name} SameObject after invalid`);
|
||||
assert(animated.baseVal.valueAsString === initial &&
|
||||
animated.animVal.valueAsString === initial, `${tag}.${name} invalid fallback`);
|
||||
|
||||
element.removeAttribute(name);
|
||||
assert(element[name] === animated, `${tag}.${name} SameObject after remove`);
|
||||
assert(animated.baseVal.valueAsString === initial &&
|
||||
animated.animVal.valueAsString === initial, `${tag}.${name} removed fallback`);
|
||||
}
|
||||
}
|
||||
return "ok";
|
||||
})()
|
||||
"#,
|
||||
)
|
||||
.expect("SVG animated length reflection probe should evaluate");
|
||||
|
||||
assert_eq!(result, "ok");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn svg_historical_interfaces_keep_current_element_constructors_only() {
|
||||
let mut vm = new_parsed_test_vm(
|
||||
|
||||
Reference in New Issue
Block a user