diff --git a/moli-benchmark/wpt-cross-current/failed-cases.txt b/moli-benchmark/wpt-cross-current/failed-cases.txt index 42b3fa988..34ecb8ccf 100644 --- a/moli-benchmark/wpt-cross-current/failed-cases.txt +++ b/moli-benchmark/wpt-cross-current/failed-cases.txt @@ -3796,7 +3796,6 @@ trusted-types/trusted-types-reporting.html trusted-types/trusted-types-secondary-document.html trusted-types/trusted-types-svg-script-set-href.html uievents/order-of-events/focus-events/focus-automated-blink-webkit.html -uievents/ui_event_pseudo_target.html url/a-element.html?exclude=(file|javascript|mailto) url/a-element.html?include=file url/a-element.html?include=javascript diff --git a/moli-benchmark/wpt-cross-current/passed-cases.txt b/moli-benchmark/wpt-cross-current/passed-cases.txt index af7942745..04de918b8 100644 --- a/moli-benchmark/wpt-cross-current/passed-cases.txt +++ b/moli-benchmark/wpt-cross-current/passed-cases.txt @@ -7823,6 +7823,7 @@ uievents/legacy-domevents-tests/approved/stopPropagation.deferred.effect.html uievents/legacy-domevents-tests/submissions/Microsoft/converted/EventListener.dispatch.new.event.html uievents/legacy/Event-subclasses-init.html uievents/textInput/api.html +uievents/ui_event_pseudo_target.html url/a-element-origin.html url/data-uri-fragment.html user-timing/clearMarks.html diff --git a/moli-renderer-v8/src/context_bootstrap/event_template.rs b/moli-renderer-v8/src/context_bootstrap/event_template.rs index 96aa1913a..045f0fbf9 100644 --- a/moli-renderer-v8/src/context_bootstrap/event_template.rs +++ b/moli-renderer-v8/src/context_bootstrap/event_template.rs @@ -20,6 +20,7 @@ use super::{ focus_event_related_target_getter_function, form_data_event_form_data_getter_function, mouse_event_related_target_getter_function, pointer_event_get_predicted_events_callback, submit_event_submitter_getter_function, track_event_track_getter_function, + ui_event_pseudo_target_getter_function, }, selection_surface::document_get_selection_callback, specs::{ConstructorKind, ConstructorSpec}, @@ -185,6 +186,12 @@ struct FormDataEventTemplateAccessorsDeclaration { struct UiEventTemplateMethodsDeclaration { #[webapi(method = "initUIEvent", length = 0, callback = ui_event_init_callback)] init_ui_event: (), + + #[webapi( + accessor_property = "pseudoTarget", + getter = ui_event_pseudo_target_getter_function + )] + pseudo_target: (), } #[derive(WebApiFunctionTemplate)] diff --git a/moli-renderer-v8/src/context_bootstrap/events.rs b/moli-renderer-v8/src/context_bootstrap/events.rs index 48c13a9a3..902540437 100644 --- a/moli-renderer-v8/src/context_bootstrap/events.rs +++ b/moli-renderer-v8/src/context_bootstrap/events.rs @@ -260,6 +260,42 @@ pub(crate) fn event_is_mouse_event<'s>( ) } +fn event_is_ui_event<'s>( + scope: &mut v8::PinScope<'s, '_>, + event: v8::Local<'s, v8::Object>, +) -> bool { + matches!( + event_subclass_kind(scope, event), + Some( + EventSubclassKind::UiEvent + | EventSubclassKind::FocusEvent + | EventSubclassKind::TextEvent + | EventSubclassKind::CompositionEvent + | EventSubclassKind::MouseEvent + | EventSubclassKind::DragEvent + | EventSubclassKind::KeyboardEvent + | EventSubclassKind::InputEvent + | EventSubclassKind::WheelEvent + | EventSubclassKind::PointerEvent + | EventSubclassKind::TouchEvent + ) + ) +} + +pub(super) fn ui_event_pseudo_target_getter_function<'s>( + scope: &mut v8::PinScope<'s, '_>, + args: v8::FunctionCallbackArguments<'s>, + mut rv: v8::ReturnValue<'_, v8::Value>, +) { + if !event_is_ui_event(scope, args.this()) { + throw_type_error(scope, "Illegal invocation"); + return; + } + // Moli does not currently synthesize UI events whose origin is a CSS + // pseudo-element, so every supported UIEvent has the default null value. + rv.set(v8::null(scope).into()); +} + fn event_related_target_value<'s>( scope: &mut v8::PinScope<'s, '_>, event: v8::Local<'s, v8::Object>, diff --git a/moli-renderer-v8/src/script_vm/tests/browser_api/events_selection_storage.rs b/moli-renderer-v8/src/script_vm/tests/browser_api/events_selection_storage.rs index ae429d04c..fb750ed3e 100644 --- a/moli-renderer-v8/src/script_vm/tests/browser_api/events_selection_storage.rs +++ b/moli-renderer-v8/src/script_vm/tests/browser_api/events_selection_storage.rs @@ -2177,6 +2177,63 @@ fn event_timestamp_uses_performance_origin_and_safe_resolution() { r#"{"hasGetter":true,"getterName":"get timeStamp","getterLength":0,"enumerable":true,"configurable":true,"hasOwnTimeStamp":false,"withinNowRange":true,"getterMatchesOwnValue":true,"safeResolution":true}"# ); } + +#[test] +fn ui_event_pseudo_target_is_declared_once_and_inherited() { + let mut vm = new_storage_test_vm("https://ui-event-pseudo-target.test/"); + + let result = vm + .eval( + r#" + (() => { + const descriptor = + Object.getOwnPropertyDescriptor(UIEvent.prototype, "pseudoTarget"); + const getter = descriptor.get; + const thrownName = receiver => { + try { + getter.call(receiver); + return "none"; + } catch (error) { + return error && error.name; + } + }; + const textEvent = document.createEvent("TextEvent"); + + return JSON.stringify({ + descriptor: [ + getter.name, + getter.length, + typeof descriptor.set, + descriptor.enumerable, + descriptor.configurable + ], + placement: [ + Object.prototype.hasOwnProperty.call(Event.prototype, "pseudoTarget"), + Object.prototype.hasOwnProperty.call(UIEvent.prototype, "pseudoTarget"), + Object.prototype.hasOwnProperty.call(MouseEvent.prototype, "pseudoTarget"), + "pseudoTarget" in MouseEvent.prototype + ], + values: [ + new UIEvent("ui").pseudoTarget, + new MouseEvent("mouse").pseudoTarget, + getter.call(textEvent) + ], + illegalReceivers: [ + thrownName(new Event("event")), + thrownName({}) + ] + }); + })() + "#, + ) + .expect("UIEvent pseudoTarget prototype probe should evaluate"); + + assert_eq!( + result, + r#"{"descriptor":["get pseudoTarget",0,"undefined",true,true],"placement":[false,true,false,true],"values":[null,null,null],"illegalReceivers":["TypeError","TypeError"]}"# + ); +} + #[test] fn performance_entry_accessors_return_entries_sorted_by_start_time() { let mut vm = new_storage_test_vm("https://performance-entry-order.test/");