mirror of
https://github.com/lexmount/moli.git
synced 2026-10-30 16:07:24 +00:00
fix(build): reconcile native SVG bindings after main rebase
Remove duplicated SVG declarations and stale shims introduced while replaying the topic history onto the native SVG interfaces commit in main. Preserve the later derive, UTF-16 and SMIL implementations and all active tests. Enable main's lone-surrogate SVG animated-string regression now that the native attribute storage supports UTF-16. Validation: cargo fmt --all; cargo clippy --workspace --all-targets --all-features -- -D warnings; cargo nextest run --no-fail-fast (21730 passed, 16 skipped; 32 threads; no automatic retries).
This commit is contained in:
@@ -99,10 +99,16 @@ pub fn svg_element_interface_name(local_name: &str) -> &'static str {
|
||||
"defs" => "SVGDefsElement",
|
||||
"desc" => "SVGDescElement",
|
||||
"ellipse" => "SVGEllipseElement",
|
||||
"feComponentTransfer" => "SVGFEComponentTransferElement",
|
||||
"feConvolveMatrix" => "SVGFEConvolveMatrixElement",
|
||||
"feFlood" => "SVGFEFloodElement",
|
||||
"feImage" => "SVGFEImageElement",
|
||||
"feMerge" => "SVGFEMergeElement",
|
||||
"feMergeNode" => "SVGFEMergeNodeElement",
|
||||
"feTile" => "SVGFETileElement",
|
||||
"feBlend" => "SVGFEBlendElement",
|
||||
"feColorMatrix" => "SVGFEColorMatrixElement",
|
||||
"feComposite" => "SVGFECompositeElement",
|
||||
"feConvolveMatrix" => "SVGFEConvolveMatrixElement",
|
||||
"feDiffuseLighting" => "SVGFEDiffuseLightingElement",
|
||||
"feDisplacementMap" => "SVGFEDisplacementMapElement",
|
||||
"feDistantLight" => "SVGFEDistantLightElement",
|
||||
|
||||
@@ -133,18 +133,6 @@ const NODE_BRIDGE_DESCRIPTORS: &[BridgeDescriptor] = &[
|
||||
web_api_interfaces::SVGClipPathElement::DESCRIPTOR,
|
||||
ELEMENT_GROUPS,
|
||||
),
|
||||
descriptor(
|
||||
web_api_interfaces::SVGFilterElement::DESCRIPTOR,
|
||||
ELEMENT_GROUPS,
|
||||
),
|
||||
descriptor(
|
||||
web_api_interfaces::SVGMaskElement::DESCRIPTOR,
|
||||
ELEMENT_GROUPS,
|
||||
),
|
||||
descriptor(
|
||||
web_api_interfaces::SVGViewElement::DESCRIPTOR,
|
||||
ELEMENT_GROUPS,
|
||||
),
|
||||
specialized_descriptor(
|
||||
web_api_interfaces::SVGCircleElement::DESCRIPTOR,
|
||||
ELEMENT_GROUPS,
|
||||
@@ -169,6 +157,30 @@ const NODE_BRIDGE_DESCRIPTORS: &[BridgeDescriptor] = &[
|
||||
SpecializedTemplateInstaller::None,
|
||||
SVG_GEOMETRY_RUNTIME_INSTALL_GROUPS,
|
||||
),
|
||||
descriptor(
|
||||
web_api_interfaces::SVGFEComponentTransferElement::DESCRIPTOR,
|
||||
ELEMENT_GROUPS,
|
||||
),
|
||||
descriptor(
|
||||
web_api_interfaces::SVGFEFloodElement::DESCRIPTOR,
|
||||
ELEMENT_GROUPS,
|
||||
),
|
||||
descriptor(
|
||||
web_api_interfaces::SVGFEImageElement::DESCRIPTOR,
|
||||
ELEMENT_GROUPS,
|
||||
),
|
||||
descriptor(
|
||||
web_api_interfaces::SVGFEMergeElement::DESCRIPTOR,
|
||||
ELEMENT_GROUPS,
|
||||
),
|
||||
descriptor(
|
||||
web_api_interfaces::SVGFEMergeNodeElement::DESCRIPTOR,
|
||||
ELEMENT_GROUPS,
|
||||
),
|
||||
descriptor(
|
||||
web_api_interfaces::SVGFETileElement::DESCRIPTOR,
|
||||
ELEMENT_GROUPS,
|
||||
),
|
||||
descriptor(
|
||||
web_api_interfaces::SVGComponentTransferFunctionElement::DESCRIPTOR,
|
||||
ELEMENT_GROUPS,
|
||||
@@ -284,6 +296,10 @@ const NODE_BRIDGE_DESCRIPTORS: &[BridgeDescriptor] = &[
|
||||
web_api_interfaces::SVGMarkerElement::DESCRIPTOR,
|
||||
ELEMENT_GROUPS,
|
||||
),
|
||||
descriptor(
|
||||
web_api_interfaces::SVGMaskElement::DESCRIPTOR,
|
||||
ELEMENT_GROUPS,
|
||||
),
|
||||
descriptor(
|
||||
web_api_interfaces::SVGMetadataElement::DESCRIPTOR,
|
||||
ELEMENT_GROUPS,
|
||||
|
||||
@@ -774,37 +774,6 @@ pub(in crate::context_bootstrap) fn build_dom_point_object<'s>(
|
||||
.expect("DOMPoint declaration should bind")
|
||||
}
|
||||
|
||||
pub(super) fn dom_point_init_from_object<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
object: v8::Local<'s, v8::Object>,
|
||||
) -> DomPointInit {
|
||||
DomPointInit {
|
||||
x: dom_point_slot(scope, object, DOM_POINT_X_SLOT, 0.0),
|
||||
y: dom_point_slot(scope, object, DOM_POINT_Y_SLOT, 0.0),
|
||||
z: dom_point_slot(scope, object, DOM_POINT_Z_SLOT, 0.0),
|
||||
w: dom_point_slot(scope, object, DOM_POINT_W_SLOT, 1.0),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn dom_point_clone_data<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
object: v8::Local<'s, v8::Object>,
|
||||
) -> Option<(bool, [f64; 4])> {
|
||||
if !dom_point_receiver_branded(scope, object) {
|
||||
return None;
|
||||
}
|
||||
let mutable = web_api_interfaces::DOMPoint::is_instance(scope, object);
|
||||
Some((
|
||||
mutable,
|
||||
[
|
||||
dom_point_slot(scope, object, DOM_POINT_X_SLOT, 0.0),
|
||||
dom_point_slot(scope, object, DOM_POINT_Y_SLOT, 0.0),
|
||||
dom_point_slot(scope, object, DOM_POINT_Z_SLOT, 0.0),
|
||||
dom_point_slot(scope, object, DOM_POINT_W_SLOT, 1.0),
|
||||
],
|
||||
))
|
||||
}
|
||||
|
||||
pub(in crate::context_bootstrap) fn build_svg_point_object<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
) -> v8::Local<'s, v8::Object> {
|
||||
@@ -3044,76 +3013,3 @@ const DOM_MATRIX_ATTRIBUTES: &[DomMatrixAttribute] = &[
|
||||
DOM_MATRIX_READONLY_ATTRIBUTES[0],
|
||||
DOM_MATRIX_READONLY_ATTRIBUTES[1],
|
||||
];
|
||||
|
||||
#[derive(Default, webidl::WebIdlDictionary)]
|
||||
#[webidl(prefix = "DOMMatrix2DInit")]
|
||||
struct DomMatrix2DInit {
|
||||
a: Option<f64>,
|
||||
b: Option<f64>,
|
||||
c: Option<f64>,
|
||||
d: Option<f64>,
|
||||
e: Option<f64>,
|
||||
f: Option<f64>,
|
||||
m11: Option<f64>,
|
||||
m12: Option<f64>,
|
||||
m21: Option<f64>,
|
||||
m22: Option<f64>,
|
||||
m41: Option<f64>,
|
||||
m42: Option<f64>,
|
||||
}
|
||||
|
||||
pub(in crate::context_bootstrap) fn dom_matrix_2d_init_arg<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
args: &v8::FunctionCallbackArguments<'s>,
|
||||
index: i32,
|
||||
prefix: &'static str,
|
||||
) -> Option<[f64; 6]> {
|
||||
if index >= args.length() || args.get(index).is_undefined() {
|
||||
return Some([1.0, 0.0, 0.0, 1.0, 0.0, 0.0]);
|
||||
}
|
||||
let init = match webidl::parse_dictionary::<DomMatrix2DInit>(
|
||||
scope,
|
||||
args.get(index),
|
||||
webidl::Context::argument(prefix, (index + 1) as usize),
|
||||
) {
|
||||
Ok(Some(init)) => init,
|
||||
Ok(None) => DomMatrix2DInit::default(),
|
||||
Err(error) => {
|
||||
webidl::throw_error(scope, &error);
|
||||
return None;
|
||||
}
|
||||
};
|
||||
Some([
|
||||
validated_dom_matrix_2d_alias(scope, "DOMMatrix2DInit", "a", init.a, "m11", init.m11, 1.0)?,
|
||||
validated_dom_matrix_2d_alias(scope, "DOMMatrix2DInit", "b", init.b, "m12", init.m12, 0.0)?,
|
||||
validated_dom_matrix_2d_alias(scope, "DOMMatrix2DInit", "c", init.c, "m21", init.m21, 0.0)?,
|
||||
validated_dom_matrix_2d_alias(scope, "DOMMatrix2DInit", "d", init.d, "m22", init.m22, 1.0)?,
|
||||
validated_dom_matrix_2d_alias(scope, "DOMMatrix2DInit", "e", init.e, "m41", init.m41, 0.0)?,
|
||||
validated_dom_matrix_2d_alias(scope, "DOMMatrix2DInit", "f", init.f, "m42", init.m42, 0.0)?,
|
||||
])
|
||||
}
|
||||
|
||||
fn validated_dom_matrix_2d_alias(
|
||||
scope: &mut v8::PinScope<'_, '_>,
|
||||
dictionary_name: &'static str,
|
||||
alias_name: &'static str,
|
||||
alias: Option<f64>,
|
||||
matrix_name: &'static str,
|
||||
matrix: Option<f64>,
|
||||
default: f64,
|
||||
) -> Option<f64> {
|
||||
if let (Some(alias), Some(matrix)) = (alias, matrix)
|
||||
&& !same_dom_matrix_2d_number(alias, matrix)
|
||||
{
|
||||
throw_type_error(
|
||||
scope,
|
||||
&format!("{dictionary_name} {alias_name} and {matrix_name} values differ."),
|
||||
);
|
||||
return None;
|
||||
}
|
||||
Some(matrix.or(alias).unwrap_or(default))
|
||||
}
|
||||
|
||||
fn same_dom_matrix_2d_number(lhs: f64, rhs: f64) -> bool {
|
||||
lhs == rhs || (lhs.is_nan() && rhs.is_nan())
|
||||
}
|
||||
|
||||
@@ -840,66 +840,6 @@ struct SvgMarkerElementTemplateMethodsDeclaration {
|
||||
set_orient_to_angle: (),
|
||||
}
|
||||
|
||||
#[derive(WebApiFunctionTemplate)]
|
||||
#[webapi(interface = web_api_interfaces::SVGMarkerElement, enumerable)]
|
||||
struct SvgMarkerElementTemplateMethodsDeclaration {
|
||||
#[webapi(
|
||||
constant = "SVG_MARKERUNITS_UNKNOWN",
|
||||
value = SVG_MARKER_UNITS_UNKNOWN
|
||||
)]
|
||||
marker_units_unknown: (),
|
||||
|
||||
#[webapi(
|
||||
constant = "SVG_MARKERUNITS_USERSPACEONUSE",
|
||||
value = SVG_MARKER_UNITS_USER_SPACE_ON_USE
|
||||
)]
|
||||
marker_units_user_space_on_use: (),
|
||||
|
||||
#[webapi(
|
||||
constant = "SVG_MARKERUNITS_STROKEWIDTH",
|
||||
value = SVG_MARKER_UNITS_STROKE_WIDTH
|
||||
)]
|
||||
marker_units_stroke_width: (),
|
||||
|
||||
#[webapi(
|
||||
constant = "SVG_MARKER_ORIENT_UNKNOWN",
|
||||
value = SVG_MARKER_ORIENT_UNKNOWN
|
||||
)]
|
||||
marker_orient_unknown: (),
|
||||
|
||||
#[webapi(
|
||||
constant = "SVG_MARKER_ORIENT_AUTO",
|
||||
value = SVG_MARKER_ORIENT_AUTO
|
||||
)]
|
||||
marker_orient_auto: (),
|
||||
|
||||
#[webapi(
|
||||
constant = "SVG_MARKER_ORIENT_ANGLE",
|
||||
value = SVG_MARKER_ORIENT_ANGLE
|
||||
)]
|
||||
marker_orient_angle: (),
|
||||
|
||||
#[webapi(
|
||||
constant = "SVG_MARKER_ORIENT_AUTO_START_REVERSE",
|
||||
value = SVG_MARKER_ORIENT_AUTO_START_REVERSE
|
||||
)]
|
||||
marker_orient_auto_start_reverse: (),
|
||||
|
||||
#[webapi(
|
||||
method = "setOrientToAuto",
|
||||
length = 0,
|
||||
callback = svg_marker_set_orient_to_auto_callback
|
||||
)]
|
||||
set_orient_to_auto: (),
|
||||
|
||||
#[webapi(
|
||||
method = "setOrientToAngle",
|
||||
length = 1,
|
||||
callback = svg_marker_set_orient_to_angle_callback
|
||||
)]
|
||||
set_orient_to_angle: (),
|
||||
}
|
||||
|
||||
#[derive(WebApiFunctionTemplate)]
|
||||
#[webapi(interface = web_api_interfaces::SVGSVGElement, enumerable, receiver)]
|
||||
struct SvgSvgElementTemplateMethodsDeclaration {
|
||||
|
||||
@@ -1245,44 +1245,6 @@ pub(super) fn build_svg_angle_from_parsed<'s>(
|
||||
.expect("SVGAngle declaration should bind")
|
||||
}
|
||||
|
||||
pub(super) fn build_svg_animated_angle_for_attribute<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
owner: v8::Local<'s, v8::Object>,
|
||||
attribute: &str,
|
||||
) -> v8::Local<'s, v8::Object> {
|
||||
let parsed = svg_owner_attribute_value(scope, owner, attribute)
|
||||
.as_deref()
|
||||
.and_then(parse_svg_orient_angle_value)
|
||||
.unwrap_or_default();
|
||||
let base_val = build_svg_angle_from_parsed(scope, &parsed, false);
|
||||
set_svg_angle_owner_attribute(scope, base_val, owner, attribute);
|
||||
let anim_val = build_svg_angle_from_parsed(scope, &parsed, true);
|
||||
set_svg_angle_owner_attribute(scope, anim_val, owner, attribute);
|
||||
SvgAnimatedAngleObjectDeclaration::new(base_val, anim_val)
|
||||
.bind(scope)
|
||||
.expect("SVGAnimatedAngle declaration should bind")
|
||||
}
|
||||
|
||||
pub(super) fn build_svg_angle<'s>(scope: &mut v8::PinScope<'s, '_>) -> v8::Local<'s, v8::Object> {
|
||||
build_svg_angle_from_parsed(scope, &SvgParsedAngle::default(), false)
|
||||
}
|
||||
|
||||
pub(super) fn build_svg_angle_from_parsed<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
parsed: &SvgParsedAngle,
|
||||
read_only: bool,
|
||||
) -> v8::Local<'s, v8::Object> {
|
||||
SvgAngleObjectDeclaration::new(
|
||||
parsed.unit_type,
|
||||
parsed.value,
|
||||
parsed.value_in_specified_units,
|
||||
parsed.value_as_string.clone(),
|
||||
read_only,
|
||||
)
|
||||
.bind(scope)
|
||||
.expect("SVGAngle declaration should bind")
|
||||
}
|
||||
|
||||
pub(super) fn build_svg_length<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
value: f64,
|
||||
|
||||
@@ -3326,26 +3326,6 @@ pub(super) fn svg_svg_element_create_point_callback<'s>(
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn svg_svg_element_create_angle_callback<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
args: v8::FunctionCallbackArguments<'s>,
|
||||
mut rv: v8::ReturnValue<'_, v8::Value>,
|
||||
) {
|
||||
if require_svg_svg_element_receiver(scope, args.this(), "createSVGAngle") {
|
||||
rv.set(build_svg_angle(scope).into());
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn svg_svg_element_create_point_callback<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
args: v8::FunctionCallbackArguments<'s>,
|
||||
mut rv: v8::ReturnValue<'_, v8::Value>,
|
||||
) {
|
||||
if require_svg_svg_element_receiver(scope, args.this(), "createSVGPoint") {
|
||||
rv.set(super::super::geometry_runtime::build_svg_point_object(scope).into());
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn svg_svg_element_deselect_all_callback<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
args: v8::FunctionCallbackArguments<'s>,
|
||||
|
||||
@@ -243,58 +243,6 @@ struct SvgAnimatedNumberProperty {
|
||||
component: SvgAnimatedNumberComponent,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
enum SvgAnimatedEnumerationKind {
|
||||
Keywords(&'static [(&'static str, u32)]),
|
||||
MarkerOrient,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct SvgAnimatedEnumerationProperty {
|
||||
index: usize,
|
||||
attribute: &'static str,
|
||||
cache_slot: &'static str,
|
||||
initial_value: u32,
|
||||
kind: SvgAnimatedEnumerationKind,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
enum SvgAnimatedIntegerComponent {
|
||||
Scalar,
|
||||
PairFirst,
|
||||
PairSecondOrFirst,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct SvgAnimatedIntegerProperty {
|
||||
index: usize,
|
||||
interface: &'static str,
|
||||
local_name: &'static str,
|
||||
name: &'static str,
|
||||
attribute: &'static str,
|
||||
cache_slot: &'static str,
|
||||
initial_value: i32,
|
||||
component: SvgAnimatedIntegerComponent,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
enum SvgAnimatedNumberComponent {
|
||||
Scalar,
|
||||
PairFirst,
|
||||
PairSecondOrFirst,
|
||||
NumberOrPercentage,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct SvgAnimatedNumberProperty {
|
||||
index: usize,
|
||||
interface: &'static str,
|
||||
name: &'static str,
|
||||
attribute: &'static str,
|
||||
initial_value: f64,
|
||||
component: SvgAnimatedNumberComponent,
|
||||
}
|
||||
|
||||
#[derive(webidl::WebIdlArgs)]
|
||||
#[webidl(prefix = "SVG list item")]
|
||||
struct SvgListItemArgs<'s> {
|
||||
@@ -1098,111 +1046,6 @@ const SVG_ANIMATED_INTEGER_PROPERTIES: &[SvgAnimatedIntegerProperty] = &[
|
||||
initial_value: 1,
|
||||
component: SvgAnimatedIntegerComponent::Scalar,
|
||||
},
|
||||
SvgAnimatedEnumerationProperty {
|
||||
index: 10,
|
||||
attribute: "markerUnits",
|
||||
cache_slot: SVG_MARKER_UNITS_SLOT,
|
||||
initial_value: SVG_MARKER_UNITS_STROKE_WIDTH,
|
||||
kind: SvgAnimatedEnumerationKind::Keywords(SVG_MARKER_UNITS_VALUES),
|
||||
},
|
||||
SvgAnimatedEnumerationProperty {
|
||||
index: 11,
|
||||
attribute: "orient",
|
||||
cache_slot: SVG_MARKER_ORIENT_TYPE_SLOT,
|
||||
initial_value: SVG_MARKER_ORIENT_ANGLE,
|
||||
kind: SvgAnimatedEnumerationKind::MarkerOrient,
|
||||
},
|
||||
SvgAnimatedEnumerationProperty {
|
||||
index: 12,
|
||||
attribute: "type",
|
||||
cache_slot: SVG_COMPONENT_TRANSFER_TYPE_SLOT,
|
||||
initial_value: SVG_COMPONENT_TRANSFER_TYPE_IDENTITY,
|
||||
kind: SvgAnimatedEnumerationKind::Keywords(SVG_COMPONENT_TRANSFER_TYPE_VALUES),
|
||||
},
|
||||
SvgAnimatedEnumerationProperty {
|
||||
index: 13,
|
||||
attribute: "mode",
|
||||
cache_slot: SVG_FE_BLEND_MODE_SLOT,
|
||||
initial_value: SVG_FE_BLEND_MODE_NORMAL,
|
||||
kind: SvgAnimatedEnumerationKind::Keywords(SVG_FE_BLEND_MODE_VALUES),
|
||||
},
|
||||
SvgAnimatedEnumerationProperty {
|
||||
index: 14,
|
||||
attribute: "type",
|
||||
cache_slot: SVG_FE_COLOR_MATRIX_TYPE_SLOT,
|
||||
initial_value: SVG_FE_COLOR_MATRIX_TYPE_MATRIX,
|
||||
kind: SvgAnimatedEnumerationKind::Keywords(SVG_FE_COLOR_MATRIX_TYPE_VALUES),
|
||||
},
|
||||
SvgAnimatedEnumerationProperty {
|
||||
index: 15,
|
||||
attribute: "operator",
|
||||
cache_slot: SVG_FE_COMPOSITE_OPERATOR_SLOT,
|
||||
initial_value: SVG_FE_COMPOSITE_OPERATOR_OVER,
|
||||
kind: SvgAnimatedEnumerationKind::Keywords(SVG_FE_COMPOSITE_OPERATOR_VALUES),
|
||||
},
|
||||
SvgAnimatedEnumerationProperty {
|
||||
index: 16,
|
||||
attribute: "edgeMode",
|
||||
cache_slot: SVG_FE_CONVOLVE_MATRIX_EDGE_MODE_SLOT,
|
||||
initial_value: SVG_EDGE_MODE_DUPLICATE,
|
||||
kind: SvgAnimatedEnumerationKind::Keywords(SVG_EDGE_MODE_VALUES),
|
||||
},
|
||||
SvgAnimatedEnumerationProperty {
|
||||
index: 17,
|
||||
attribute: "xChannelSelector",
|
||||
cache_slot: SVG_FE_DISPLACEMENT_MAP_X_CHANNEL_SLOT,
|
||||
initial_value: SVG_CHANNEL_A,
|
||||
kind: SvgAnimatedEnumerationKind::Keywords(SVG_CHANNEL_VALUES),
|
||||
},
|
||||
SvgAnimatedEnumerationProperty {
|
||||
index: 18,
|
||||
attribute: "yChannelSelector",
|
||||
cache_slot: SVG_FE_DISPLACEMENT_MAP_Y_CHANNEL_SLOT,
|
||||
initial_value: SVG_CHANNEL_A,
|
||||
kind: SvgAnimatedEnumerationKind::Keywords(SVG_CHANNEL_VALUES),
|
||||
},
|
||||
SvgAnimatedEnumerationProperty {
|
||||
index: 19,
|
||||
attribute: "operator",
|
||||
cache_slot: SVG_FE_MORPHOLOGY_OPERATOR_SLOT,
|
||||
initial_value: SVG_MORPHOLOGY_OPERATOR_ERODE,
|
||||
kind: SvgAnimatedEnumerationKind::Keywords(SVG_MORPHOLOGY_OPERATOR_VALUES),
|
||||
},
|
||||
SvgAnimatedEnumerationProperty {
|
||||
index: 20,
|
||||
attribute: "stitchTiles",
|
||||
cache_slot: SVG_FE_TURBULENCE_STITCH_TILES_SLOT,
|
||||
initial_value: SVG_STITCH_TYPE_NO_STITCH,
|
||||
kind: SvgAnimatedEnumerationKind::Keywords(SVG_STITCH_TYPE_VALUES),
|
||||
},
|
||||
SvgAnimatedEnumerationProperty {
|
||||
index: 21,
|
||||
attribute: "type",
|
||||
cache_slot: SVG_FE_TURBULENCE_TYPE_SLOT,
|
||||
initial_value: SVG_TURBULENCE_TYPE_TURBULENCE,
|
||||
kind: SvgAnimatedEnumerationKind::Keywords(SVG_TURBULENCE_TYPE_VALUES),
|
||||
},
|
||||
SvgAnimatedEnumerationProperty {
|
||||
index: 22,
|
||||
attribute: "method",
|
||||
cache_slot: SVG_TEXT_PATH_METHOD_SLOT,
|
||||
initial_value: SVG_TEXT_PATH_METHOD_TYPE_ALIGN,
|
||||
kind: SvgAnimatedEnumerationKind::Keywords(SVG_TEXT_PATH_METHOD_TYPE_VALUES),
|
||||
},
|
||||
SvgAnimatedEnumerationProperty {
|
||||
index: 23,
|
||||
attribute: "spacing",
|
||||
cache_slot: SVG_TEXT_PATH_SPACING_SLOT,
|
||||
initial_value: SVG_TEXT_PATH_SPACING_TYPE_EXACT,
|
||||
kind: SvgAnimatedEnumerationKind::Keywords(SVG_TEXT_PATH_SPACING_TYPE_VALUES),
|
||||
},
|
||||
SvgAnimatedEnumerationProperty {
|
||||
index: 24,
|
||||
attribute: "side",
|
||||
cache_slot: SVG_TEXT_PATH_SIDE_SLOT,
|
||||
initial_value: SVG_TEXT_PATH_SIDE_TYPE_LEFT,
|
||||
kind: SvgAnimatedEnumerationKind::Keywords(SVG_TEXT_PATH_SIDE_TYPE_VALUES),
|
||||
},
|
||||
];
|
||||
|
||||
pub(in crate::context_bootstrap) fn install_svg_template_bindings<'s>(
|
||||
@@ -1257,6 +1100,7 @@ pub(in crate::context_bootstrap) fn install_svg_template_bindings<'s>(
|
||||
"SVGTextContentElement" => {
|
||||
bindings::install_svg_text_content_element_bindings(scope, template)
|
||||
}
|
||||
"SVGGradientElement" => bindings::install_svg_gradient_element_bindings(scope, template),
|
||||
"SVGMarkerElement" => bindings::install_svg_marker_element_bindings(scope, template),
|
||||
"SVGSVGElement" => bindings::install_svg_svg_element_bindings(scope, template),
|
||||
_ => {}
|
||||
|
||||
@@ -272,14 +272,12 @@ pub(crate) use details_dialog::{
|
||||
use event_handlers::install_global_event_handler_template_bindings as install_global_event_handler_templates_for_owner;
|
||||
use event_handlers::install_node_event_handler_template_bindings;
|
||||
pub(crate) use event_handlers::{
|
||||
GlobalEventHandlerOwner, body_or_frameset_reflects_window_event_type,
|
||||
canonical_event_handler_event_type, compile_body_window_event_attribute,
|
||||
GlobalEventHandlerOwner, ParserAddedBodyWindowHandlers,
|
||||
body_or_frameset_reflects_window_event_type, canonical_event_handler_event_type,
|
||||
compile_body_window_event_attribute, compile_window_event_attribute_handler,
|
||||
event_handler_content_attribute_name, initialize_parser_inserted_body_window_event_handlers,
|
||||
resolve_window_event_handler_content_attribute,
|
||||
node_event_handler_getter_function, node_event_handler_setter_function,
|
||||
legacy_lenient_this_event_handler,
|
||||
compile_window_event_attribute_handler,
|
||||
ParserAddedBodyWindowHandlers,
|
||||
legacy_lenient_this_event_handler, node_event_handler_getter_function,
|
||||
node_event_handler_setter_function, resolve_window_event_handler_content_attribute,
|
||||
};
|
||||
use event_handlers::{
|
||||
HtmlBodyWindowEventHandlersDeclaration, HtmlFrameSetWindowEventHandlersDeclaration,
|
||||
|
||||
@@ -451,88 +451,3 @@ pub(crate) fn prepare_trusted_script_text(
|
||||
.set_script_text_internal_slot(handle, &source);
|
||||
Some(source)
|
||||
}
|
||||
|
||||
fn svg_animated_string_attribute_namespace(
|
||||
runtime: &JsContextHost,
|
||||
handle: DomHandle,
|
||||
attribute: &str,
|
||||
) -> Option<&'static str> {
|
||||
(attribute == "href"
|
||||
&& !runtime.dom_host().has_attribute_ns(handle, None, attribute)
|
||||
&& runtime.dom_host().has_attribute_ns(
|
||||
handle,
|
||||
Some(crate::native_bridge::document::XLINK_NS),
|
||||
attribute,
|
||||
))
|
||||
.then_some(crate::native_bridge::document::XLINK_NS)
|
||||
}
|
||||
|
||||
pub(crate) fn set_svg_animated_string_base_value<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
owner: v8::Local<'s, v8::Object>,
|
||||
attribute: &str,
|
||||
value: v8::Local<'s, v8::Value>,
|
||||
) -> Option<String> {
|
||||
let (runtime_ptr, handle) =
|
||||
crate::native_bridge::node_runtime_and_handle_from_object_or_detached(scope, owner).ok()?;
|
||||
let script_href = {
|
||||
let element = unsafe { &*runtime_ptr }
|
||||
.dom_host()
|
||||
.node(handle)?
|
||||
.as_element()?;
|
||||
element.namespace() == "http://www.w3.org/2000/svg"
|
||||
&& element.local_name() == "script"
|
||||
&& attribute == "href"
|
||||
};
|
||||
let value = if script_href {
|
||||
let requirements = unsafe { &*runtime_ptr }.trusted_types_for_script_requirements(scope);
|
||||
crate::context_bootstrap::trusted_script_url_string_or_throw(
|
||||
scope,
|
||||
value,
|
||||
requirements,
|
||||
"SVGScriptElement href",
|
||||
"baseVal",
|
||||
)?
|
||||
} else {
|
||||
match crate::webidl::convert::<crate::webidl::DomString>(
|
||||
scope,
|
||||
value,
|
||||
crate::webidl::Context::member("SVGAnimatedString", "baseVal"),
|
||||
) {
|
||||
Ok(value) => value.0,
|
||||
Err(error) => {
|
||||
crate::webidl::throw_error(scope, &error);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
};
|
||||
let (runtime_ptr, handle) =
|
||||
crate::native_bridge::node_runtime_and_handle_from_object_or_detached(scope, owner).ok()?;
|
||||
let namespace =
|
||||
svg_animated_string_attribute_namespace(unsafe { &*runtime_ptr }, handle, attribute);
|
||||
if attribute == "href" {
|
||||
let _ = unsafe { &mut *runtime_ptr }.set_attribute_ns(
|
||||
scope,
|
||||
runtime_ptr,
|
||||
handle,
|
||||
namespace,
|
||||
namespace.map(|_| "xlink"),
|
||||
attribute,
|
||||
if namespace.is_some() {
|
||||
"xlink:href"
|
||||
} else {
|
||||
attribute
|
||||
},
|
||||
&value,
|
||||
);
|
||||
} else {
|
||||
let _ = unsafe { &mut *runtime_ptr }.set_attribute(
|
||||
scope,
|
||||
runtime_ptr,
|
||||
handle,
|
||||
attribute,
|
||||
&value,
|
||||
);
|
||||
}
|
||||
Some(value)
|
||||
}
|
||||
|
||||
@@ -3142,114 +3142,3 @@ fn service_worker_register_converts_options_before_the_default_policy() {
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn svg_script_href_base_val_uses_the_owner_reflected_trusted_script_url_sink() {
|
||||
let mut vm = new_storage_test_vm("https://svg-script-href-trusted-types.test/");
|
||||
vm.set_response_content_security_policies(&["require-trusted-types-for 'script'".to_owned()]);
|
||||
|
||||
let result = vm
|
||||
.eval(
|
||||
r#"
|
||||
(() => {
|
||||
const violations = [];
|
||||
document.addEventListener("securitypolicyviolation", event => {
|
||||
violations.push({
|
||||
blockedURI: event.blockedURI,
|
||||
effectiveDirective: event.effectiveDirective,
|
||||
sample: event.sample
|
||||
});
|
||||
});
|
||||
globalThis.__svgScriptHrefViolations = violations;
|
||||
|
||||
const svgScript = document.createElementNS("http://www.w3.org/2000/svg", "script");
|
||||
const href = svgScript.href;
|
||||
let illegalConstructor = false;
|
||||
try {
|
||||
new SVGAnimatedString();
|
||||
} catch (error) {
|
||||
illegalConstructor = error instanceof TypeError;
|
||||
}
|
||||
let plainRejected = false;
|
||||
try {
|
||||
href.baseVal = "plain.js";
|
||||
} catch (error) {
|
||||
plainRejected = error instanceof TypeError;
|
||||
}
|
||||
const rejectedAttribute = svgScript.getAttribute("href");
|
||||
|
||||
const explicit = trustedTypes.createPolicy("svg-script-href", {
|
||||
createScriptURL: value => value
|
||||
});
|
||||
href.baseVal = explicit.createScriptURL("trusted.js");
|
||||
const trustedValues = [
|
||||
svgScript.getAttribute("href"),
|
||||
href.baseVal,
|
||||
href.animVal
|
||||
];
|
||||
svgScript.setAttribute("href", explicit.createScriptURL("attribute.js"));
|
||||
const externallySynced = [href.baseVal, href.animVal];
|
||||
const className = svgScript.className;
|
||||
className.baseVal = explicit.createScriptURL("trusted-class");
|
||||
const use = document.createElementNS("http://www.w3.org/2000/svg", "use");
|
||||
const useHref = use.href;
|
||||
useHref.baseVal = explicit.createScriptURL("trusted-use");
|
||||
|
||||
const defaultCalls = [];
|
||||
trustedTypes.createPolicy("default", {
|
||||
createScriptURL: (value, type, sink) => {
|
||||
defaultCalls.push([value, type, sink]);
|
||||
return `safe-${value}`;
|
||||
}
|
||||
});
|
||||
href.baseVal = "default-input";
|
||||
className.baseVal = "plain-class";
|
||||
useHref.baseVal = "plain-use";
|
||||
|
||||
return JSON.stringify({
|
||||
shape: [
|
||||
href instanceof SVGAnimatedString,
|
||||
Object.prototype.toString.call(href),
|
||||
svgScript.href === href,
|
||||
illegalConstructor
|
||||
],
|
||||
plainRejected,
|
||||
rejectedAttribute,
|
||||
trustedValues,
|
||||
externallySynced,
|
||||
ordinaryAnimatedStrings: [
|
||||
className instanceof SVGAnimatedString,
|
||||
svgScript.className === className,
|
||||
className.baseVal,
|
||||
className.animVal,
|
||||
svgScript.getAttribute("class"),
|
||||
useHref instanceof SVGAnimatedString,
|
||||
use.href === useHref,
|
||||
useHref.baseVal,
|
||||
useHref.animVal,
|
||||
use.getAttribute("href")
|
||||
],
|
||||
defaulted: [svgScript.getAttribute("href"), href.baseVal, href.animVal],
|
||||
defaultCalls,
|
||||
violations
|
||||
});
|
||||
})()
|
||||
"#,
|
||||
)
|
||||
.expect("SVGScriptElement href Trusted Types sink probe should evaluate");
|
||||
|
||||
assert_eq!(
|
||||
result,
|
||||
r#"{"shape":[true,"[object SVGAnimatedString]",true,true],"plainRejected":true,"rejectedAttribute":null,"trustedValues":["trusted.js","trusted.js","trusted.js"],"externallySynced":["attribute.js","attribute.js"],"ordinaryAnimatedStrings":[true,true,"plain-class","plain-class","plain-class",true,true,"plain-use","plain-use","plain-use"],"defaulted":["safe-default-input","safe-default-input","safe-default-input"],"defaultCalls":[["default-input","TrustedScriptURL","SVGScriptElement href"]],"violations":[]}"#
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
drain_pre_domcontentloaded_non_script_page_tasks_for_test(&mut vm),
|
||||
1
|
||||
);
|
||||
assert_eq!(
|
||||
vm.eval("JSON.stringify(globalThis.__svgScriptHrefViolations)")
|
||||
.expect("queued SVGScriptElement href violation should be observable"),
|
||||
r#"[{"blockedURI":"trusted-types-sink","effectiveDirective":"require-trusted-types-for","sample":"SVGScriptElement href|plain.js"}]"#
|
||||
);
|
||||
}
|
||||
|
||||
-233
@@ -2734,239 +2734,6 @@ fn detached_plain_document_all_matches_chromium_htmldda_surface() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn svg_value_lists_enforce_item_types_indices_and_read_only_anim_values() {
|
||||
let mut vm = new_storage_test_vm("https://svg-value-list-semantics.test/");
|
||||
|
||||
let result = vm
|
||||
.eval(
|
||||
r#"
|
||||
(() => {
|
||||
const assert = (condition, message) => {
|
||||
if (!condition) throw new Error(message);
|
||||
};
|
||||
const errorName = callback => {
|
||||
try {
|
||||
callback();
|
||||
return "none";
|
||||
} catch (error) {
|
||||
return error.name;
|
||||
}
|
||||
};
|
||||
const SVG_NS = "http://www.w3.org/2000/svg";
|
||||
const text = document.createElementNS(SVG_NS, "text");
|
||||
const svg = document.createElementNS(SVG_NS, "svg");
|
||||
text.setAttribute("x", "10 20");
|
||||
text.setAttribute("rotate", "15 30");
|
||||
|
||||
const lengths = text.x;
|
||||
const lengthBase = lengths.baseVal;
|
||||
const lengthAnim = lengths.animVal;
|
||||
const numbers = text.rotate;
|
||||
const numberBase = numbers.baseVal;
|
||||
const numberAnim = numbers.animVal;
|
||||
const invalidItems = [30, "invalid", text, null];
|
||||
|
||||
for (const item of invalidItems) {
|
||||
assert(errorName(() => lengthBase.initialize(item)) === "TypeError",
|
||||
"SVGLengthList.initialize item type");
|
||||
assert(errorName(() => lengthBase.insertItemBefore(item, 0)) === "TypeError",
|
||||
"SVGLengthList.insertItemBefore item type");
|
||||
assert(errorName(() => lengthBase.replaceItem(item, 0)) === "TypeError",
|
||||
"SVGLengthList.replaceItem item type");
|
||||
assert(errorName(() => lengthBase.appendItem(item)) === "TypeError",
|
||||
"SVGLengthList.appendItem item type");
|
||||
assert(errorName(() => { lengthBase[0] = item; }) === "TypeError",
|
||||
"SVGLengthList indexed setter item type");
|
||||
}
|
||||
|
||||
const length = svg.createSVGLength();
|
||||
length.value = 42;
|
||||
lengthBase[0] = length;
|
||||
assert(lengthBase[0] === length, "SVGLengthList indexed getter");
|
||||
assert(text.getAttribute("x") === "42 20", "SVGLengthList indexed reflection");
|
||||
|
||||
const number = svg.createSVGNumber();
|
||||
number.value = 7;
|
||||
numberBase[1] = number;
|
||||
assert(numberBase[1] === number, "SVGNumberList indexed getter");
|
||||
assert(text.getAttribute("rotate") === "15 7", "SVGNumberList indexed reflection");
|
||||
assert(errorName(() => lengthBase.appendItem(number)) === "TypeError",
|
||||
"SVGLengthList rejects SVGNumber");
|
||||
assert(errorName(() => numberBase.appendItem(length)) === "TypeError",
|
||||
"SVGNumberList rejects SVGLength");
|
||||
|
||||
text.setAttribute("x", "1 2 3");
|
||||
assert(lengthBase.length === 3 && lengthBase[2].value === 3,
|
||||
"saved baseVal resynchronizes");
|
||||
assert(text.x.animVal.length === 3 && text.x.animVal[2].value === 3,
|
||||
"animVal resynchronizes after direct baseVal access");
|
||||
|
||||
assert(errorName(() => lengthAnim.clear()) === "NoModificationAllowedError",
|
||||
"SVGLengthList animVal clear");
|
||||
assert(errorName(() => { lengthAnim[0] = length; }) === "NoModificationAllowedError",
|
||||
"SVGLengthList animVal indexed setter");
|
||||
assert(errorName(() => numberAnim.appendItem(number)) === "NoModificationAllowedError",
|
||||
"SVGNumberList animVal appendItem");
|
||||
assert(errorName(() => SVGLengthList.prototype.clear.call({})) === "TypeError",
|
||||
"SVGLengthList receiver brand");
|
||||
return "ok";
|
||||
})()
|
||||
"#,
|
||||
)
|
||||
.expect("SVG value list semantics probe should evaluate");
|
||||
|
||||
assert_eq!(result, "ok");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn svg_point_lists_are_live_mutable_and_clear_invalid_content() {
|
||||
let mut vm = new_storage_test_vm("https://svg-point-list-semantics.test/");
|
||||
|
||||
let result = vm
|
||||
.eval(
|
||||
r#"
|
||||
(() => {
|
||||
const assert = (condition, message) => {
|
||||
if (!condition) throw new Error(message);
|
||||
};
|
||||
const errorName = callback => {
|
||||
try {
|
||||
callback();
|
||||
return "none";
|
||||
} catch (error) {
|
||||
return error.name;
|
||||
}
|
||||
};
|
||||
const ns = "http://www.w3.org/2000/svg";
|
||||
const polygon = document.createElementNS(ns, "polygon");
|
||||
const polyline = document.createElementNS(ns, "polyline");
|
||||
const svg = document.createElementNS(ns, "svg");
|
||||
|
||||
assert(typeof SVGPointList === "function", "constructor exposed");
|
||||
assert(errorName(() => new SVGPointList()) === "TypeError",
|
||||
"illegal constructor");
|
||||
for (const [constructor, element] of [
|
||||
[SVGPolygonElement, polygon],
|
||||
[SVGPolylineElement, polyline],
|
||||
]) {
|
||||
const pointsDescriptor = Object.getOwnPropertyDescriptor(
|
||||
constructor.prototype,
|
||||
"points",
|
||||
);
|
||||
const animatedDescriptor = Object.getOwnPropertyDescriptor(
|
||||
constructor.prototype,
|
||||
"animatedPoints",
|
||||
);
|
||||
assert(typeof pointsDescriptor.get === "function" &&
|
||||
pointsDescriptor.set === undefined, `${constructor.name}.points descriptor`);
|
||||
assert(typeof animatedDescriptor.get === "function" &&
|
||||
animatedDescriptor.set === undefined,
|
||||
`${constructor.name}.animatedPoints descriptor`);
|
||||
assert(pointsDescriptor.enumerable && pointsDescriptor.configurable &&
|
||||
animatedDescriptor.enumerable && animatedDescriptor.configurable,
|
||||
`${constructor.name} descriptor flags`);
|
||||
assert(element.points instanceof SVGPointList &&
|
||||
element.animatedPoints instanceof SVGPointList,
|
||||
`${constructor.name} point list interfaces`);
|
||||
assert(element.points === element.points &&
|
||||
element.animatedPoints === element.animatedPoints &&
|
||||
element.points !== element.animatedPoints,
|
||||
`${constructor.name} SameObject lists`);
|
||||
}
|
||||
|
||||
polygon.setAttribute("points", "0,0 100,0 100,100 0,100");
|
||||
const points = polygon.points;
|
||||
const animatedPoints = polygon.animatedPoints;
|
||||
assert(Object.prototype.toString.call(points) === "[object SVGPointList]",
|
||||
"point list tag");
|
||||
assert(points.length === 4 && points.numberOfItems === 4,
|
||||
"valid content points");
|
||||
assert(points.getItem(1) === points[1] && points[1] instanceof DOMPoint &&
|
||||
points[1] instanceof SVGPoint && points[1].x === 100 && points[1].y === 0,
|
||||
"indexed point identity and values");
|
||||
|
||||
polygon.setAttribute("points", "0,0 100,0 INVALID");
|
||||
assert(points.numberOfItems === 0,
|
||||
"invalid token clears the whole point list");
|
||||
polygon.setAttribute("points", "0,0 100,0 20");
|
||||
assert(points.numberOfItems === 2,
|
||||
"missing final y coordinate truncates the point list");
|
||||
polygon.setAttribute("points", "0,0 100,0 20,");
|
||||
assert(points.numberOfItems === 2,
|
||||
"trailing comma with missing y truncates the point list");
|
||||
|
||||
polygon.setAttribute("points", "0,0 10,20");
|
||||
const first = points[0];
|
||||
first.x = 2;
|
||||
assert(polygon.getAttribute("points") === "2 0 10 20",
|
||||
"point coordinate mutation reflects to content");
|
||||
|
||||
const point = svg.createSVGPoint();
|
||||
point.x = 5;
|
||||
point.y = 6;
|
||||
points.clear();
|
||||
assert(points.length === 0 && polygon.getAttribute("points") === "",
|
||||
"clear reflects an empty list");
|
||||
assert(points.initialize(point) === point && points[0] === point,
|
||||
"initialize keeps point identity");
|
||||
assert(polygon.getAttribute("points") === "5 6", "initialize reflection");
|
||||
point.x = 7;
|
||||
assert(polygon.getAttribute("points") === "7 6", "owned point stays live");
|
||||
|
||||
const second = svg.createSVGPoint();
|
||||
second.x = 8;
|
||||
second.y = 9;
|
||||
assert(points.appendItem(second) === second && points.length === 2,
|
||||
"appendItem");
|
||||
const third = svg.createSVGPoint();
|
||||
third.x = 10;
|
||||
third.y = 11;
|
||||
assert(points.insertItemBefore(third, 1) === third && points.length === 3,
|
||||
"insertItemBefore");
|
||||
const replacement = svg.createSVGPoint();
|
||||
replacement.x = 12;
|
||||
replacement.y = 13;
|
||||
assert(points.replaceItem(replacement, 0) === replacement &&
|
||||
points[0] === replacement,
|
||||
"replaceItem");
|
||||
assert(points.removeItem(1) === third && points.length === 2,
|
||||
"removeItem");
|
||||
points[0] = point;
|
||||
assert(points[0] === point, "indexed setter");
|
||||
|
||||
for (const invalid of [1, "point", polygon, null]) {
|
||||
assert(errorName(() => points.appendItem(invalid)) === "TypeError",
|
||||
"point item type enforcement");
|
||||
}
|
||||
assert(errorName(() => points.getItem(99)) === "IndexSizeError",
|
||||
"getItem bounds");
|
||||
|
||||
polygon.setAttribute("points", "1,2 3,4");
|
||||
assert(animatedPoints.length === 2 && animatedPoints[1].x === 3,
|
||||
"animatedPoints live synchronization");
|
||||
assert(errorName(() => animatedPoints.clear()) === "NoModificationAllowedError",
|
||||
"animatedPoints list is read-only");
|
||||
assert(errorName(() => { animatedPoints[0].x = 9; }) ===
|
||||
"NoModificationAllowedError", "animated point is read-only");
|
||||
assert(errorName(() => SVGPointList.prototype.clear.call({})) === "TypeError",
|
||||
"point list receiver brand");
|
||||
|
||||
const pointsDescriptor = Object.getOwnPropertyDescriptor(
|
||||
SVGPolygonElement.prototype,
|
||||
"points",
|
||||
);
|
||||
assert(errorName(() => pointsDescriptor.get.call(svg)) === "TypeError",
|
||||
"animated points receiver brand");
|
||||
return "ok";
|
||||
})()
|
||||
"#,
|
||||
)
|
||||
.expect("SVG point list semantics probe should evaluate");
|
||||
|
||||
assert_eq!(result, "ok");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn element_heading_reflections_drive_flat_tree_heading_matching() {
|
||||
let mut vm = new_storage_test_vm("https://heading-offset.test/");
|
||||
|
||||
+96
-1858
File diff suppressed because it is too large
Load Diff
@@ -552,12 +552,12 @@ interfaces! {
|
||||
SVGAnimatedNumberList;
|
||||
SVGAnimatedTransformList;
|
||||
SVGCircleElement: SVGGeometryElement;
|
||||
SVGDefsElement: SVGGraphicsElement;
|
||||
SVGDescElement: SVGElement;
|
||||
SVGClipPathElement: SVGElement;
|
||||
SVGFilterElement: SVGElement;
|
||||
SVGMaskElement: SVGElement;
|
||||
SVGViewElement: SVGElement;
|
||||
SVGDefsElement: SVGGraphicsElement;
|
||||
SVGDescElement: SVGElement;
|
||||
SVGComponentTransferFunctionElement: SVGElement;
|
||||
SVGFEFuncAElement: SVGComponentTransferFunctionElement;
|
||||
SVGFEFuncBElement: SVGComponentTransferFunctionElement;
|
||||
@@ -618,6 +618,7 @@ interfaces! {
|
||||
SVGTextElement: SVGTextPositioningElement;
|
||||
SVGTextPositioningElement: SVGTextContentElement;
|
||||
SVGTitleElement: SVGElement;
|
||||
SVGUnitTypes;
|
||||
SVGPointList;
|
||||
SVGStringList;
|
||||
SVGTransform;
|
||||
|
||||
Reference in New Issue
Block a user