fix(webapi): adapt replayed bindings to current interfaces

Use shared interface descriptors for document and SVG receivers, remove
duplicate Performance and DOMParser declarations, and align existing CSP
and import-map test calls with the interfaces at this replay point.

Bring forward the applicable parts of 0500891ecc so the image request
conflict resolution can remain a separate commit. Keep the original
regression assertions and duplicate-policy coverage.

Validation: cargo fmt --all; cargo clippy --workspace --all-targets
--all-features -- -D warnings; cargo nextest run --no-fail-fast
(17642 passed, 13 skipped).
This commit is contained in:
ldm0
2026-10-02 03:27:48 +08:00
parent d653edfb14
commit 7d44d7fd4b
7 changed files with 16 additions and 121 deletions
@@ -4450,7 +4450,7 @@ mod tests {
let policy = format!("trusted-types {name}");
let expected = byte.is_ascii_alphanumeric() || b"-#=_/@.%".contains(&byte);
assert_eq!(
policy_allows_trusted_type_policy_name(&policy, &name),
policy_allows_trusted_type_policy_name(&policy, &name, false),
expected,
"invalid tt-policy-name byte {byte:#04x} must not match literally",
);
@@ -4458,21 +4458,25 @@ mod tests {
for name in ["none", "allow-duplicates", "A-z_09#=/@.%"] {
assert!(policy_allows_trusted_type_policy_name(
&format!("trusted-types {name}"),
name
name,
false
));
}
assert!(policy_allows_trusted_type_policy_name(
"trusted-types valid policy*name",
"valid"
"valid",
false
));
assert!(!policy_allows_trusted_type_policy_name(
"trusted-types valid policy*name",
"policy*name"
"policy*name",
false
));
for wildcard in ["\u{000b}*", "*\u{000b}", "policy*"] {
assert!(!policy_allows_trusted_type_policy_name(
&format!("trusted-types {wildcard}"),
"valid"
"valid",
false
));
}
}
@@ -4488,7 +4492,7 @@ mod tests {
"\0",
] {
for policy in ["", "trusted-types *"] {
assert!(policy_allows_trusted_type_policy_name(policy, name));
assert!(policy_allows_trusted_type_policy_name(policy, name, false));
}
}
}
@@ -954,13 +954,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 {
@@ -407,7 +407,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"),
) {
@@ -433,13 +432,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();
@@ -832,7 +832,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)
}
@@ -905,7 +907,7 @@ fn trusted_types_factory_receiver_is_valid<'s>(
scope: &mut v8::PinScope<'s, '_>,
receiver: v8::Local<'s, v8::Object>,
) -> bool {
if web_api_interfaces::TrustedTypePolicyFactory::is_instance(scope, receiver.into()) {
if web_api_interfaces::TrustedTypePolicyFactory::is_instance(scope, receiver) {
return true;
}
throw_type_error(scope, "Illegal invocation");
@@ -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);
}
@@ -2557,87 +2557,6 @@ fn service_worker_register_gates_script_url_before_url_resolution() {
);
}
#[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"]]}"#
);
}
#[test]
fn service_worker_register_converts_options_before_the_default_policy() {
let mut vm = new_storage_test_vm("https://service-worker-register-options.test/");