fix(webapi): migrate replayed SVG and internal object bindings

Use shared SVG interface identities and plain-object declarations for
internal stream callbacks and Window proxy handlers. Align imports with
the current receiver APIs and format the replayed bindings.

Consolidate the duplicate DOMMatrix serialization test while preserving
both inferred and explicit dimension assertions. Keep the XHR and child
script tests that still have only one declaration at this replay point.

Bring forward the applicable parts of 0500891ecc independently of the
pending stylesheet MIME and committed-origin conflict resolution.

Validation: cargo fmt --all; cargo clippy --workspace --all-targets
--all-features -- -D warnings; cargo nextest run --no-fail-fast
(17751 passed, 13 skipped).
This commit is contained in:
ldm0
2026-09-16 22:06:41 +08:00
parent 4dea0265e1
commit aaf6cc4f7e
13 changed files with 114 additions and 125 deletions
+4 -19
View File
@@ -38,6 +38,10 @@ mod tests {
matrix.dom_matrix_text().unwrap(),
format!("matrix(1, 0, 0, 1, 0, {expected})")
);
assert_eq!(
matrix.dom_matrix_text_with_dimension(true).unwrap(),
format!("matrix(1, 0, 0, 1, 0, {expected})")
);
}
}
@@ -81,25 +85,6 @@ mod tests {
);
}
#[test]
fn dom_matrix_text_uses_ecmascript_number_serialization() {
for (value, expected) in [
(1.0 / 300_000_000.0, "3.3333333333333334e-9"),
(f64::MAX, "1.7976931348623157e+308"),
(f64::MIN_POSITIVE * f64::EPSILON, "5e-324"),
] {
let matrix = DomMatrixComponents {
m42: value,
..DomMatrixComponents::identity()
};
assert_eq!(
matrix.dom_matrix_text_with_dimension(true).unwrap(),
format!("matrix(1, 0, 0, 1, 0, {expected})")
);
}
}
#[test]
fn inverse_handles_invertible_3d_matrix() {
let matrix = DomMatrixComponents::identity()
+1 -1
View File
@@ -1,4 +1,4 @@
use crate::web_api_interfaces;
use crate::{native_bridge, web_api_interfaces};
use moli_file_api::{
BlobId, BlobLineEndings, BlobStore, blob_slice_relative_index, clamp_blob_long_long,
normalize_blob_line_endings_with_native_ending, normalize_blob_mime_type,
+2 -2
View File
@@ -236,7 +236,7 @@ pub(crate) use self::css_stylesheet_runtime::{
sync_css_style_sheet_shadow_root_adopted_owner_tracking,
};
pub(crate) use self::dom_rect::build_dom_rect_object;
pub(crate) use self::dom_rect_list::{build_dom_rect_list_object};
pub(crate) use self::dom_rect_list::build_dom_rect_list_object;
pub(crate) use self::events::{
EVENT_DISPATCHING_SLOT, EVENT_PASSIVE_SLOT, EVENT_STOP_IMMEDIATE_PROPAGATION_SLOT,
EVENT_STOP_PROPAGATION_SLOT, EventHandlerType, apply_before_unload_event_handler_return_value,
@@ -253,7 +253,7 @@ pub(crate) use self::file_api::{
pub(crate) use self::file_api::{apply_drag_modifier_drop_effect, build_data_transfer_object};
pub(crate) use self::file_api::{
build_file_list_object, build_file_object, file_list_files_from_object,
flush_one_pending_file_reader, is_file_list_object, selected_file_from_object,
flush_one_pending_file_reader, selected_file_from_object,
};
pub(crate) use self::form_data_runtime::form_data_request_body;
pub(crate) use self::geometry_clone::{
@@ -109,14 +109,20 @@ const NODE_BRIDGE_DESCRIPTORS: &[BridgeDescriptor] = &[
ELEMENT_GROUPS,
),
descriptor(web_api_interfaces::SVGAElement::DESCRIPTOR, ELEMENT_GROUPS),
descriptor(web_api_interfaces::SVGClipPathElement::DESCRIPTOR, ELEMENT_GROUPS),
descriptor(
web_api_interfaces::SVGClipPathElement::DESCRIPTOR,
ELEMENT_GROUPS,
),
specialized_descriptor(
web_api_interfaces::SVGCircleElement::DESCRIPTOR,
ELEMENT_GROUPS,
SpecializedTemplateInstaller::None,
SVG_GEOMETRY_RUNTIME_INSTALL_GROUPS,
),
descriptor(web_api_interfaces::SVGFilterElement::DESCRIPTOR, ELEMENT_GROUPS),
descriptor(
web_api_interfaces::SVGFilterElement::DESCRIPTOR,
ELEMENT_GROUPS,
),
descriptor(
web_api_interfaces::SVGDefsElement::DESCRIPTOR,
ELEMENT_GROUPS,
@@ -151,12 +157,18 @@ const NODE_BRIDGE_DESCRIPTORS: &[BridgeDescriptor] = &[
web_api_interfaces::SVGFEFuncRElement::DESCRIPTOR,
ELEMENT_GROUPS,
),
descriptor(web_api_interfaces::SVGFEBlendElement::DESCRIPTOR, ELEMENT_GROUPS),
descriptor(
web_api_interfaces::SVGFEBlendElement::DESCRIPTOR,
ELEMENT_GROUPS,
),
descriptor(
web_api_interfaces::SVGFEColorMatrixElement::DESCRIPTOR,
ELEMENT_GROUPS,
),
descriptor(web_api_interfaces::SVGFECompositeElement::DESCRIPTOR, ELEMENT_GROUPS),
descriptor(
web_api_interfaces::SVGFECompositeElement::DESCRIPTOR,
ELEMENT_GROUPS,
),
descriptor(
web_api_interfaces::SVGFEConvolveMatrixElement::DESCRIPTOR,
ELEMENT_GROUPS,
@@ -173,20 +185,38 @@ const NODE_BRIDGE_DESCRIPTORS: &[BridgeDescriptor] = &[
web_api_interfaces::SVGFEDistantLightElement::DESCRIPTOR,
ELEMENT_GROUPS,
),
descriptor(web_api_interfaces::SVGFEDropShadowElement::DESCRIPTOR, ELEMENT_GROUPS),
descriptor(
web_api_interfaces::SVGFEDropShadowElement::DESCRIPTOR,
ELEMENT_GROUPS,
),
descriptor(
web_api_interfaces::SVGFEGaussianBlurElement::DESCRIPTOR,
ELEMENT_GROUPS,
),
descriptor(web_api_interfaces::SVGFEMorphologyElement::DESCRIPTOR, ELEMENT_GROUPS),
descriptor(web_api_interfaces::SVGFEOffsetElement::DESCRIPTOR, ELEMENT_GROUPS),
descriptor(web_api_interfaces::SVGFEPointLightElement::DESCRIPTOR, ELEMENT_GROUPS),
descriptor(
web_api_interfaces::SVGFEMorphologyElement::DESCRIPTOR,
ELEMENT_GROUPS,
),
descriptor(
web_api_interfaces::SVGFEOffsetElement::DESCRIPTOR,
ELEMENT_GROUPS,
),
descriptor(
web_api_interfaces::SVGFEPointLightElement::DESCRIPTOR,
ELEMENT_GROUPS,
),
descriptor(
web_api_interfaces::SVGFESpecularLightingElement::DESCRIPTOR,
ELEMENT_GROUPS,
),
descriptor(web_api_interfaces::SVGFESpotLightElement::DESCRIPTOR, ELEMENT_GROUPS),
descriptor(web_api_interfaces::SVGFETurbulenceElement::DESCRIPTOR, ELEMENT_GROUPS),
descriptor(
web_api_interfaces::SVGFESpotLightElement::DESCRIPTOR,
ELEMENT_GROUPS,
),
descriptor(
web_api_interfaces::SVGFETurbulenceElement::DESCRIPTOR,
ELEMENT_GROUPS,
),
descriptor(
web_api_interfaces::SVGForeignObjectElement::DESCRIPTOR,
ELEMENT_GROUPS,
@@ -218,12 +248,30 @@ const NODE_BRIDGE_DESCRIPTORS: &[BridgeDescriptor] = &[
svg_gradient_transform: true,
},
),
descriptor(web_api_interfaces::SVGMarkerElement::DESCRIPTOR, ELEMENT_GROUPS),
descriptor(web_api_interfaces::SVGMaskElement::DESCRIPTOR, ELEMENT_GROUPS),
descriptor(web_api_interfaces::SVGMetadataElement::DESCRIPTOR, ELEMENT_GROUPS),
descriptor(web_api_interfaces::SVGScriptElement::DESCRIPTOR, ELEMENT_GROUPS),
descriptor(web_api_interfaces::SVGStopElement::DESCRIPTOR, ELEMENT_GROUPS),
descriptor(web_api_interfaces::SVGStyleElement::DESCRIPTOR, ELEMENT_GROUPS),
descriptor(
web_api_interfaces::SVGMarkerElement::DESCRIPTOR,
ELEMENT_GROUPS,
),
descriptor(
web_api_interfaces::SVGMaskElement::DESCRIPTOR,
ELEMENT_GROUPS,
),
descriptor(
web_api_interfaces::SVGMetadataElement::DESCRIPTOR,
ELEMENT_GROUPS,
),
descriptor(
web_api_interfaces::SVGScriptElement::DESCRIPTOR,
ELEMENT_GROUPS,
),
descriptor(
web_api_interfaces::SVGStopElement::DESCRIPTOR,
ELEMENT_GROUPS,
),
descriptor(
web_api_interfaces::SVGStyleElement::DESCRIPTOR,
ELEMENT_GROUPS,
),
specialized_descriptor(
web_api_interfaces::SVGPathElement::DESCRIPTOR,
ELEMENT_GROUPS,
@@ -318,7 +366,10 @@ const NODE_BRIDGE_DESCRIPTORS: &[BridgeDescriptor] = &[
web_api_interfaces::SVGUseElement::DESCRIPTOR,
ELEMENT_GROUPS,
),
descriptor(web_api_interfaces::SVGViewElement::DESCRIPTOR, ELEMENT_GROUPS),
descriptor(
web_api_interfaces::SVGViewElement::DESCRIPTOR,
ELEMENT_GROUPS,
),
specialized_descriptor(
web_api_interfaces::SVGRectElement::DESCRIPTOR,
ELEMENT_GROUPS,
@@ -38,8 +38,7 @@ pub(crate) use file_entry_file::{
};
pub(super) use file_list::file_list_item_callback;
pub(crate) use file_list::{
build_file_list_object, file_list_files_from_object, is_file_list_object,
sync_file_list_contents,
build_file_list_object, file_list_files_from_object, sync_file_list_contents,
};
pub(crate) use file_reader::flush_one_pending_file_reader;
pub(super) use file_reader::{
@@ -10,7 +10,6 @@ const FILE_LIST_FILES_SLOT: &str = "__lmFileListFiles";
#[derive(WebApiObject)]
#[webapi(interface = web_api_interfaces::FileList, require_prototype)]
struct FileListObjectDeclaration {
#[webapi(slot = FILE_LIST_LENGTH_SLOT)]
length: f64,
}
@@ -110,7 +110,10 @@ impl v8::ValueSerializerImpl for IndexedDbStructuredCloneSerializer {
return Some(true);
}
}
Some("DOMPoint" | "DOMPointReadOnly" | "DOMRect" | "DOMRectReadOnly" | "DOMQuad" | "DOMMatrix" | "DOMMatrixReadOnly") => {
Some(
"DOMPoint" | "DOMPointReadOnly" | "DOMRect" | "DOMRectReadOnly" | "DOMQuad"
| "DOMMatrix" | "DOMMatrixReadOnly",
) => {
if let Some(payload) = geometry_clone_payload_from_object(scope, object) {
write_geometry_clone_payload(serializer, payload);
return Some(true);
@@ -98,7 +98,6 @@ pub(super) use super::performance_observer_runtime::{
performance_observer_disconnect_callback, performance_observer_observe_callback,
performance_observer_take_records_callback,
};
pub(crate) use entries::is_performance_entry_object;
use entries::{
append_performance_entry, create_performance_entry, initialize_resource_timing_slots,
push_performance_entry,
@@ -9,7 +9,7 @@ const READABLE_STREAM_FROM_REACTION_STREAM_SLOT: &str = "__moliReadableStreamFro
const READABLE_STREAM_FROM_REACTION_SYNC_SLOT: &str = "__moliReadableStreamFromReactionSync";
#[derive(WebApiObject)]
#[webapi(interface = "Object")]
#[webapi(plain)]
struct ReadableStreamFromSourceDeclaration<'scope> {
#[webapi(slot = READABLE_STREAM_FROM_ITERATOR_SLOT)]
iterator: v8::Local<'scope, v8::Object>,
@@ -24,7 +24,7 @@ struct ReadableStreamFromSourceDeclaration<'scope> {
}
#[derive(WebApiObject)]
#[webapi(interface = "Object")]
#[webapi(plain)]
struct ReadableStreamFromReactionDeclaration<'scope> {
#[webapi(slot = READABLE_STREAM_FROM_REACTION_STREAM_SLOT)]
stream: v8::Local<'scope, v8::Object>,
@@ -713,13 +713,7 @@ pub(super) fn svg_marker_set_orient_to_angle_callback<'s>(
);
return;
};
if !require_svg_receiver(
scope,
angle,
SVG_ANGLE_UNIT_TYPE_SLOT,
"SVGAngle",
"setOrientToAngle argument",
) {
if !require_svg_receiver(scope, angle, "SVGAngle", "setOrientToAngle argument") {
return;
}
sync_svg_angle_from_owner_attribute(scope, angle);
@@ -810,7 +804,7 @@ fn require_svg_interface_receiver<'s>(
}
let Some(parent) =
crate::context_bootstrap::bridge_descriptor::node_bridge_descriptor(interface_name)
.and_then(|descriptor| descriptor.parent_constructor)
.and_then(|descriptor| descriptor.interface.parent_name())
else {
break;
};
@@ -1140,7 +1134,6 @@ pub(super) fn svg_animated_boolean_getter<'s>(
if !require_svg_receiver(
scope,
args.this(),
SVG_ANIMATED_BOOLEAN_BASE_VAL_SLOT,
"SVGAnimatedBoolean",
&format!("{name} getter"),
) {
@@ -1175,7 +1168,6 @@ pub(super) fn svg_animated_boolean_setter<'s>(
if !require_svg_receiver(
scope,
args.this(),
SVG_ANIMATED_BOOLEAN_BASE_VAL_SLOT,
"SVGAnimatedBoolean",
&format!("{name} setter"),
) || name != "baseVal"
@@ -1282,7 +1274,6 @@ pub(super) fn svg_animated_angle_getter<'s>(
if !require_svg_receiver(
scope,
args.this(),
SVG_ANIMATED_ANGLE_BASE_VAL_SLOT,
"SVGAnimatedAngle",
&format!("{name} getter"),
) {
@@ -1318,7 +1309,6 @@ pub(super) fn svg_animated_rect_getter<'s>(
if !require_svg_receiver(
scope,
args.this(),
SVG_ANIMATED_RECT_BASE_VAL_SLOT,
"SVGAnimatedRect",
&format!("{name} getter"),
) {
@@ -1354,7 +1344,6 @@ pub(super) fn svg_animated_preserve_aspect_ratio_getter<'s>(
if !require_svg_receiver(
scope,
args.this(),
SVG_ANIMATED_PRESERVE_ASPECT_RATIO_BASE_VAL_SLOT,
"SVGAnimatedPreserveAspectRatio",
&format!("{name} getter"),
) {
@@ -1391,7 +1380,6 @@ pub(super) fn svg_preserve_aspect_ratio_getter<'s>(
if !require_svg_receiver(
scope,
aspect_ratio,
SVG_PRESERVE_ASPECT_RATIO_ALIGN_SLOT,
"SVGPreserveAspectRatio",
&format!("{name} getter"),
) {
@@ -1433,7 +1421,6 @@ pub(super) fn svg_preserve_aspect_ratio_setter<'s>(
if !require_svg_receiver(
scope,
aspect_ratio,
SVG_PRESERVE_ASPECT_RATIO_ALIGN_SLOT,
"SVGPreserveAspectRatio",
&format!("{name} setter"),
) {
@@ -1582,13 +1569,7 @@ pub(super) fn svg_angle_getter<'s>(
rv.set_undefined();
return;
};
if !require_svg_receiver(
scope,
args.this(),
SVG_ANGLE_UNIT_TYPE_SLOT,
"SVGAngle",
&format!("{name} getter"),
) {
if !require_svg_receiver(scope, args.this(), "SVGAngle", &format!("{name} getter")) {
return;
}
sync_svg_angle_from_owner_attribute(scope, args.this());
@@ -1630,13 +1611,7 @@ pub(super) fn svg_angle_setter<'s>(
) else {
return;
};
if !require_svg_receiver(
scope,
args.this(),
SVG_ANGLE_UNIT_TYPE_SLOT,
"SVGAngle",
&format!("{name} setter"),
) {
if !require_svg_receiver(scope, args.this(), "SVGAngle", &format!("{name} setter")) {
return;
}
if svg_angle_is_read_only(scope, args.this()) {
@@ -1847,7 +1822,6 @@ pub(super) fn svg_animated_integer_getter<'s>(
if !require_svg_receiver(
scope,
args.this(),
SVG_ANIMATED_INTEGER_BASE_VAL_SLOT,
"SVGAnimatedInteger",
&format!("{name} getter"),
) {
@@ -2046,7 +2020,6 @@ pub(super) fn svg_animated_integer_setter<'s>(
if !require_svg_receiver(
scope,
args.this(),
SVG_ANIMATED_INTEGER_BASE_VAL_SLOT,
"SVGAnimatedInteger",
&format!("{name} setter"),
) || name != "baseVal"
@@ -3720,13 +3693,7 @@ pub(super) fn svg_length_new_value_specified_units_callback<'s>(
args: v8::FunctionCallbackArguments<'s>,
mut rv: v8::ReturnValue<'_, v8::Value>,
) {
if !require_svg_receiver(
scope,
args.this(),
SVG_LENGTH_UNIT_TYPE_SLOT,
"SVGLength",
"newValueSpecifiedUnits",
) {
if !require_svg_receiver(scope, args.this(), "SVGLength", "newValueSpecifiedUnits") {
return;
}
let Some(parsed) = webidl::parse_args::<SvgLengthNewValueSpecifiedUnitsArgs>(scope, &args)
@@ -3753,13 +3720,7 @@ pub(super) fn svg_angle_new_value_specified_units_callback<'s>(
args: v8::FunctionCallbackArguments<'s>,
mut rv: v8::ReturnValue<'_, v8::Value>,
) {
if !require_svg_receiver(
scope,
args.this(),
SVG_ANGLE_UNIT_TYPE_SLOT,
"SVGAngle",
"newValueSpecifiedUnits",
) {
if !require_svg_receiver(scope, args.this(), "SVGAngle", "newValueSpecifiedUnits") {
return;
}
if svg_angle_is_read_only(scope, args.this()) {
@@ -3793,13 +3754,7 @@ pub(super) fn svg_length_convert_to_specified_units_callback<'s>(
args: v8::FunctionCallbackArguments<'s>,
mut rv: v8::ReturnValue<'_, v8::Value>,
) {
if !require_svg_receiver(
scope,
args.this(),
SVG_LENGTH_UNIT_TYPE_SLOT,
"SVGLength",
"convertToSpecifiedUnits",
) {
if !require_svg_receiver(scope, args.this(), "SVGLength", "convertToSpecifiedUnits") {
return;
}
let Some(parsed) = webidl::parse_args::<SvgLengthConvertToSpecifiedUnitsArgs>(scope, &args)
@@ -3838,13 +3793,7 @@ pub(super) fn svg_angle_convert_to_specified_units_callback<'s>(
args: v8::FunctionCallbackArguments<'s>,
mut rv: v8::ReturnValue<'_, v8::Value>,
) {
if !require_svg_receiver(
scope,
args.this(),
SVG_ANGLE_UNIT_TYPE_SLOT,
"SVGAngle",
"convertToSpecifiedUnits",
) {
if !require_svg_receiver(scope, args.this(), "SVGAngle", "convertToSpecifiedUnits") {
return;
}
if svg_angle_is_read_only(scope, args.this()) {
@@ -28,7 +28,7 @@ use moli_webapi_declare::{WebApiFunctionTemplate, WebApiObject};
const WINDOW_NAMED_PROPERTIES_REFLECT_SET_SLOT: &str = "__moliWindowNamedPropertiesReflectSet";
#[derive(WebApiObject)]
#[webapi(interface = "Object")]
#[webapi(plain)]
struct WindowNamedPropertiesProxyHandlerDeclaration {
#[webapi(method, length = 4, callback = window_named_properties_proxy_set_callback)]
set: (),
@@ -1,6 +1,5 @@
use crate::document_runtime::DomHandle;
use crate::dom::{forms::InputType, native::Node};
use crate::native_bridge::document::XHTML_NS;
use crate::util::v8_string;
use crate::webidl;
+23 -18
View File
@@ -11,22 +11,21 @@ use crate::{
CryptoKeyAlgorithmClonePayload, CryptoKeyClonePayload, FileSystemFileSnapshotClonePayload,
FileSystemHandleClonePayload, GeometryClonePayload, ImageDataClonePayload,
ReadableStreamClonePayload, TransformStreamClonePayload, WritableStreamClonePayload,
attach_file_system_file_snapshot_clone_payload, build_file_object,
build_file_list_object, file_list_files_from_object,
build_file_system_handle_from_clone_payload, build_image_data_object_from_clone_payload,
build_readable_stream_clone_shell, build_transform_stream_clone_shell,
build_writable_stream_clone_shell, crypto_key_clone_payload_from_object,
crypto_key_object_from_clone_payload, detach_message_port_owner_for_transfer,
detach_transferred_message_port, dom_exception_clone_fields,
ensure_message_port_wrapper_for_id, file_system_file_snapshot_clone_payload_from_object,
file_system_handle_clone_payload_from_object, image_data_clone_payload_from_object,
initialize_readable_stream_clone_shell, initialize_transform_stream_clone_shell,
initialize_writable_stream_clone_shell, message_port_id_from_object,
new_dom_exception_value, new_quota_exceeded_error_value, prepare_readable_stream_transfer,
prepare_transform_stream_transfer, prepare_writable_stream_transfer,
quota_exceeded_error_clone_fields, require_internal_stream_value,
selected_file_from_object,
build_geometry_object_from_clone_payload, geometry_clone_payload_from_object,
attach_file_system_file_snapshot_clone_payload, build_file_list_object, build_file_object,
build_file_system_handle_from_clone_payload, build_geometry_object_from_clone_payload,
build_image_data_object_from_clone_payload, build_readable_stream_clone_shell,
build_transform_stream_clone_shell, build_writable_stream_clone_shell,
crypto_key_clone_payload_from_object, crypto_key_object_from_clone_payload,
detach_message_port_owner_for_transfer, detach_transferred_message_port,
dom_exception_clone_fields, ensure_message_port_wrapper_for_id,
file_list_files_from_object, file_system_file_snapshot_clone_payload_from_object,
file_system_handle_clone_payload_from_object, geometry_clone_payload_from_object,
image_data_clone_payload_from_object, initialize_readable_stream_clone_shell,
initialize_transform_stream_clone_shell, initialize_writable_stream_clone_shell,
message_port_id_from_object, new_dom_exception_value, new_quota_exceeded_error_value,
prepare_readable_stream_transfer, prepare_transform_stream_transfer,
prepare_writable_stream_transfer, quota_exceeded_error_clone_fields,
require_internal_stream_value, selected_file_from_object,
},
dom::native::SelectedFile,
types::MessagePortId,
@@ -379,7 +378,10 @@ impl v8::ValueSerializerImpl for WireSerializer {
return Some(true);
}
}
Some("DOMPoint" | "DOMPointReadOnly" | "DOMRect" | "DOMRectReadOnly" | "DOMQuad" | "DOMMatrix" | "DOMMatrixReadOnly") => {
Some(
"DOMPoint" | "DOMPointReadOnly" | "DOMRect" | "DOMRectReadOnly" | "DOMQuad"
| "DOMMatrix" | "DOMMatrixReadOnly",
) => {
if let Some(payload) = geometry_clone_payload_from_object(scope, object) {
write_geometry_clone_payload(serializer, payload);
return Some(true);
@@ -465,7 +467,10 @@ impl v8::ValueSerializerImpl for WireSerializer {
return None;
};
let Ok(length) = u32::try_from(files.len()) else {
throw_data_clone_exception(scope, "Too many Files in structured clone FileList.");
throw_data_clone_exception(
scope,
"Too many Files in structured clone FileList.",
);
return None;
};
let mut clone_ids = Vec::with_capacity(files.len());