fix(webapi): adapt rebased bindings to shared interface identities

Use shared interface descriptors and generated receiver checks for the rebased SVG, ImageBitmap, Fetch, and document bindings. Declare internal callback state and proxy handlers as plain objects, and remove stale imports and duplicate declarations introduced by overlapping upstream fixes.

Keep both inferred and explicit DOMMatrix serialization coverage while consolidating duplicate tests. Format the resolved runtime bindings.

Validation: cargo fmt --all; cargo clippy --workspace --all-targets --all-features -- -D warnings; cargo nextest run --no-fail-fast (18131 passed, 13 skipped).
This commit is contained in:
ldm0
2026-09-14 03:38:57 +08:00
parent 51a1b63203
commit 0500891ecc
26 changed files with 127 additions and 306 deletions
-2
View File
@@ -1,5 +1,3 @@
#[path = "scripts/child_script_text.rs"]
mod child_script_text;
#[path = "scripts/integrity.rs"]
mod integrity;
+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 -3
View File
@@ -240,7 +240,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,
@@ -436,8 +436,7 @@ pub(crate) use self::streams::{
initialize_transform_stream_clone_shell, initialize_writable_stream_clone_shell,
new_readable_stream_from_array_buffer, new_readable_stream_from_source,
prepare_readable_stream_transfer, prepare_transform_stream_transfer,
prepare_writable_stream_transfer,
proxy_fetch_body_stream, tee_fetch_body_stream,
prepare_writable_stream_transfer, proxy_fetch_body_stream, tee_fetch_body_stream,
};
#[cfg(test)]
pub(crate) use self::trusted_types::trusted_types_lazy_state_materialized;
@@ -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,
@@ -188,7 +188,7 @@ impl<'s> webidl::WebIdlConverter<'s> for BitmapSource<'s> {
} else if offscreen_canvas_receiver_branded(scope, object) || is_html_canvas(scope, object)
{
BitmapSourceKind::Canvas
} else if crate::context_bootstrap::image_data::is_image_data_object(scope, object) {
} else if web_api_interfaces::ImageData::is_instance(scope, object) {
BitmapSourceKind::ImageData
} else if image_bitmap_receiver_branded(scope, object) {
BitmapSourceKind::ImageBitmap
@@ -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);
@@ -102,7 +102,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,
@@ -1129,13 +1129,6 @@ fn apply_lifecycle_to_navigation_entry<'s>(
}
}
pub(super) fn is_window_performance<'s>(
scope: &mut v8::PinScope<'s, '_>,
performance: v8::Local<'s, v8::Object>,
) -> bool {
get_private_value(scope, performance, PERFORMANCE_NAVIGATION_TYPE_SEED_SLOT).is_some()
}
pub(super) fn performance_navigation_type_seed<'s>(
scope: &mut v8::PinScope<'s, '_>,
performance: v8::Local<'s, v8::Object>,
@@ -30,22 +30,6 @@ struct PerformanceMarkOptions<'s> {
start_time: Option<f64>,
}
#[derive(webidl::WebIdlArgs)]
#[webidl(prefix = "PerformanceMark")]
struct PerformanceMarkConstructorArgs {
#[webidl(required)]
name: String,
}
#[derive(Default, webidl::WebIdlDictionary)]
#[webidl(prefix = "PerformanceMarkOptions")]
struct PerformanceMarkOptions<'s> {
#[webidl(converter = "raw")]
detail: Option<v8::Local<'s, v8::Value>>,
#[webidl(name = "startTime", converter = "double")]
start_time: Option<f64>,
}
#[derive(webidl::WebIdlArgs)]
#[webidl(prefix = "Performance.clearMarks")]
struct PerformanceClearMarksArgs {
@@ -9,9 +9,9 @@ use super::stream_adapter::{
parse_writable_stream_sink_object, readable_stream_byob_request_respond_callback,
readable_stream_byob_request_respond_with_new_view_callback,
readable_stream_byob_request_view_getter, readable_stream_is_byte_stream,
readable_stream_locked, rejected_promise_value, set_resolved_promise, stream_slot_array,
stream_slot_object, suppress_promise_unhandled_rejection, writable_stream_close_internal,
writable_stream_locked, writable_stream_snapshot,
readable_stream_locked, rejected_promise_value, set_resolved_promise, stream_slot_object,
suppress_promise_unhandled_rejection, writable_stream_close_internal, writable_stream_locked,
writable_stream_snapshot,
};
use super::stream_objects::{
new_readable_stream_byob_reader_object, new_readable_stream_reader_object,
@@ -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;
};
@@ -1103,7 +1097,6 @@ pub(super) fn svg_animated_string_getter<'s>(
if !require_svg_receiver(
scope,
args.this(),
SVG_ANIMATED_STRING_BASE_VAL_SLOT,
"SVGAnimatedString",
&format!("{name} getter"),
) {
@@ -1141,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"),
) {
@@ -1176,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"
@@ -1203,13 +1194,7 @@ pub(super) fn svg_animated_string_setter<'s>(
args: v8::FunctionCallbackArguments<'s>,
_rv: v8::ReturnValue<'_, v8::Value>,
) {
if !require_svg_receiver(
scope,
args.this(),
SVG_ANIMATED_STRING_BASE_VAL_SLOT,
"SVGAnimatedString",
"baseVal setter",
) {
if !require_svg_receiver(scope, args.this(), "SVGAnimatedString", "baseVal setter") {
return;
}
let animated = args.this();
@@ -1289,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"),
) {
@@ -1325,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"),
) {
@@ -1361,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"),
) {
@@ -1398,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"),
) {
@@ -1440,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"),
) {
@@ -1589,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());
@@ -1637,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()) {
@@ -1854,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"),
) {
@@ -2053,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"
@@ -3727,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)
@@ -3760,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()) {
@@ -3800,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)
@@ -3845,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()) {
@@ -846,7 +846,9 @@ fn build_trusted_script_code_like_carrier<'s>(
TrustedTypeObjectDeclaration::new(value)
.initialize(scope, object)
.expect("TrustedScript code-like carrier declaration should initialize");
web_api_interfaces::TrustedScript::DESCRIPTOR.initialize(scope, object).ok()?;
web_api_interfaces::TrustedScript::DESCRIPTOR
.initialize(scope, object)
.ok()?;
Some(object)
}
@@ -871,9 +873,8 @@ fn trusted_type_to_string_callback<'s>(
mut rv: v8::ReturnValue<'_, v8::Value>,
) {
let this = args.this();
if !trusted_type_kind(scope, this.into()).is_some_and(|kind| {
v8str(scope, kind.constructor_name()).strict_equals(args.data())
})
if !trusted_type_kind(scope, this.into())
.is_some_and(|kind| v8str(scope, kind.constructor_name()).strict_equals(args.data()))
{
throw_type_error(scope, "Illegal invocation");
return;
@@ -1,5 +1,5 @@
use crate::web_api_interfaces;
use super::{ice_candidate::ice_candidate_receiver_branded, rtc_data_channel_receiver_branded};
use crate::web_api_interfaces;
use crate::{
context_bootstrap::events::{initialize_event_object_with_type, parse_event_init},
util::{
@@ -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: (),
@@ -18,7 +18,7 @@ pub(super) fn build_node_wrapper_template<'s, 'i>(
let template = v8::ObjectTemplate::new(scope);
let _ = template.set_internal_field_count(1);
if descriptor.prototype_name == "HTMLDocument" {
if descriptor.interface.name() == "HTMLDocument" {
named_access::install_document_named_property_handler(template);
}
@@ -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;
@@ -25,7 +25,7 @@ const SUCCEEDED: &str = "__moliBodyConsumerSucceeded";
const REASON: &str = "__moliBodyConsumerReason";
#[derive(WebApiObject)]
#[webapi(interface = "Object")]
#[webapi(plain)]
struct BodyConsumerDeclaration<'scope> {
#[webapi(slot = BODY_OWNER)]
body_owner: v8::Local<'scope, v8::Object>,
@@ -243,7 +243,7 @@ pub(crate) fn parse_fetch_init<'s>(
.map_err(|error| error.to_string())?;
let body_stream = body_value
.and_then(|value| v8::Local::<v8::Object>::try_from(value).ok())
.filter(|object| crate::context_bootstrap::is_readable_stream_object(scope, *object))
.filter(|object| crate::web_api_interfaces::ReadableStream::is_instance(scope, *object))
.map(|stream| v8::Global::new(scope, stream));
let prepared_body = body_value
.map(|value| body_init(scope, value, webidl::Context::member("RequestInit", "body")))
@@ -1,6 +1,5 @@
use super::super::headers::HeadersGuard;
use super::*;
use crate::web_api_interfaces;
use crate::webidl;
pub(super) fn normalize_fetch_request_method(method: &str) -> Result<String, &'static str> {
@@ -5,7 +5,6 @@ use super::super::fetch_surface::{
};
use super::*;
use crate::types::NetworkBodySourceId;
use crate::web_api_interfaces;
use moli_fetch::RequestMode;
use moli_url::WebOrigin;
use moli_webapi_declare::WebApiObject;
@@ -2964,84 +2964,3 @@ fn service_worker_register_gates_script_url_before_url_resolution() {
r#"{"blockedString":"TypeError","blockedWrongType":"TypeError","missing":"TypeError","trustedPromise":true,"defaultPromise":true,"defaultCalls":[["worker.potato","TrustedScriptURL","ServiceWorkerContainer register"]]}"#
);
}
#[test]
fn dom_parser_gates_converted_union_source_after_webidl_argument_conversion() {
let mut vm = new_storage_test_vm("https://dom-parser-trusted-types.test/");
vm.set_response_content_security_policies(&["require-trusted-types-for 'script'".to_owned()]);
let result = vm
.eval(
r#"
(() => {
const errorName = callback => {
try {
callback();
return "none";
} catch (error) {
return error && error.name;
}
};
const parser = new DOMParser();
const custom = trustedTypes.createPolicy("dom-parser-custom", {
createHTML: value => value
});
const blocked = [
errorName(() => parser.parseFromString("<p>blocked</p>", "text/html")),
errorName(() => parser.parseFromString(null, "text/html")),
errorName(() => parser.parseFromString("<root/>", "application/xml"))
];
const accepted = [
parser.parseFromString(
custom.createHTML("<main>trusted</main>"),
"text/html"
).body.innerText,
parser.parseFromString(
custom.createHTML("<root/>"),
"application/xml"
).documentElement.tagName
];
let sourceConversions = 0;
const defaultCalls = [];
trustedTypes.createPolicy("default", {
createHTML: (value, type, sink) => {
defaultCalls.push([value, type, sink]);
return value === "source" ? "<p>default</p>" : value;
}
});
const source = {
toString() {
sourceConversions += 1;
return "source";
}
};
const defaultValues = [
parser.parseFromString(source, "text/html").body.innerText,
parser.parseFromString(null, "text/html").body.innerText,
parser.parseFromString("<root/>", "application/xml").documentElement.tagName
];
const callsBeforeInvalidType = defaultCalls.length;
const invalidType = errorName(() => parser.parseFromString(source, "TEXT/html"));
const invalidTypeSkippedPolicy = defaultCalls.length === callsBeforeInvalidType;
return JSON.stringify({
blocked,
accepted,
defaultValues,
sourceConversions,
invalidType,
invalidTypeSkippedPolicy,
symbolSource: errorName(() => parser.parseFromString(Symbol(), "text/html")),
defaultCalls
});
})()
"#,
)
.expect("DOMParser TrustedHTML union probe should evaluate");
assert_eq!(
result,
r#"{"blocked":["TypeError","TypeError","TypeError"],"accepted":["trusted","root"],"defaultValues":["default","null","root"],"sourceConversions":2,"invalidType":"TypeError","invalidTypeSkippedPolicy":true,"symbolSource":"TypeError","defaultCalls":[["source","TrustedHTML","DOMParser parseFromString"],["null","TrustedHTML","DOMParser parseFromString"],["<root/>","TrustedHTML","DOMParser parseFromString"]]}"#
);
}
@@ -4084,57 +4084,3 @@ async fn streaming_xhr_materialization_failure_errors_body_source_before_close()
vec![crate::types::PendingSubresourceContinueEvent::Completed { internal_id }]
);
}
#[tokio::test(flavor = "current_thread")]
async fn window_xhr_open_freezes_base_url_and_applies_url_credentials() {
let server = StaticHttpServer::spawn(1).await;
let base_url = server.base_url();
let loader = static_http_loader(std::iter::empty::<String>());
let mut vm = new_page_task_executor_test_vm_with_loader(
base_url
.join("page.html")
.expect("page fixture URL")
.as_str(),
&loader,
);
let first_base = base_url.join("first/").expect("first base URL");
let second_base = base_url.join("second/").expect("second base URL");
vm.eval(&format!(
r#"
(() => {{
globalThis.__xhrOpenUrlProbe = "pending";
const base = document.createElement("base");
base.href = {};
document.head.append(base);
const xhr = new XMLHttpRequest();
xhr.open("GET", "resource", true, "alice", "secret");
base.href = {};
xhr.onload = () => {{ globalThis.__xhrOpenUrlProbe = "done"; }};
xhr.onerror = () => {{ globalThis.__xhrOpenUrlProbe = "error"; }};
xhr.send();
return "started";
}})()
"#,
serde_json::to_string(first_base.as_str()).expect("serialize first base URL"),
serde_json::to_string(second_base.as_str()).expect("serialize second base URL"),
))
.expect("XHR open URL probe should evaluate");
advance_page_task_executor_until_eval_equals(
&mut vm,
&loader,
"String(globalThis.__xhrOpenUrlProbe)",
"done",
"XHR open URL probe",
)
.await;
let requests = server.finish().await;
assert_eq!(requests.len(), 1);
assert_eq!(requests[0].target, "/first/resource");
assert_eq!(
requests[0].header_value("authorization"),
Some("Basic YWxpY2U6c2VjcmV0")
);
}
+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());