dommy 0.16.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/dommy/animation.rb +1 -0
- data/lib/dommy/backend.rb +3 -0
- data/lib/dommy/blob.rb +6 -0
- data/lib/dommy/browser.rb +12 -4
- data/lib/dommy/character_data.rb +1 -13
- data/lib/dommy/cookie_store.rb +2 -1
- data/lib/dommy/document.rb +67 -30
- data/lib/dommy/element.rb +11 -0
- data/lib/dommy/element_internals.rb +12 -0
- data/lib/dommy/encodings/legacy_multibyte.rb +800 -0
- data/lib/dommy/encodings/multibyte_overrides.rb +76 -0
- data/lib/dommy/encodings/prescan.rb +234 -0
- data/lib/dommy/encodings.rb +121 -57
- data/lib/dommy/event.rb +107 -54
- data/lib/dommy/event_source.rb +1 -0
- data/lib/dommy/fetch.rb +244 -53
- data/lib/dommy/file_reader.rb +1 -0
- data/lib/dommy/form_data.rb +22 -9
- data/lib/dommy/form_entry_list.rb +3 -3
- data/lib/dommy/html_canvas_element.rb +85 -12
- data/lib/dommy/html_elements/base.rb +1 -0
- data/lib/dommy/html_elements/forms/input.rb +3 -0
- data/lib/dommy/html_elements/interactive.rb +56 -48
- data/lib/dommy/html_elements/metadata.rb +23 -0
- data/lib/dommy/interaction/form_submission.rb +24 -42
- data/lib/dommy/internal/accessibility_tree.rb +149 -162
- data/lib/dommy/internal/accessibility_visibility.rb +16 -17
- data/lib/dommy/internal/accessible_name.rb +231 -246
- data/lib/dommy/internal/aria_role.rb +182 -195
- data/lib/dommy/internal/aria_snapshot.rb +35 -38
- data/lib/dommy/internal/aria_state.rb +102 -118
- data/lib/dommy/internal/autofill.rb +75 -75
- data/lib/dommy/internal/backend_prefilter.rb +127 -130
- data/lib/dommy/internal/child_navigable.rb +86 -83
- data/lib/dommy/internal/close_watcher_manager.rb +1 -0
- data/lib/dommy/internal/css/ancestor_filter.rb +64 -64
- data/lib/dommy/internal/css/calc.rb +90 -71
- data/lib/dommy/internal/css/cascade.rb +69 -67
- data/lib/dommy/internal/css/color.rb +249 -187
- data/lib/dommy/internal/css/computed_style_builder.rb +34 -0
- data/lib/dommy/internal/css/computed_style_declaration.rb +50 -11
- data/lib/dommy/internal/css/counters.rb +67 -67
- data/lib/dommy/internal/css/custom_properties.rb +114 -114
- data/lib/dommy/internal/css/parser.rb +277 -239
- data/lib/dommy/internal/css/property_registry.rb +321 -302
- data/lib/dommy/internal/css/renderability.rb +37 -35
- data/lib/dommy/internal/css/rule_index.rb +2 -2
- data/lib/dommy/internal/css/rule_index_inputs.rb +2 -2
- data/lib/dommy/internal/css/supports.rb +115 -113
- data/lib/dommy/internal/css/ua_stylesheet.rb +55 -53
- data/lib/dommy/internal/css_rule_text.rb +121 -119
- data/lib/dommy/internal/css_source.rb +1 -3
- data/lib/dommy/internal/css_syntax.rb +157 -92
- data/lib/dommy/internal/declarative_shadow_roots.rb +1 -0
- data/lib/dommy/internal/directionality.rb +120 -123
- data/lib/dommy/internal/document_live_ranges.rb +26 -1
- data/lib/dommy/internal/dom_matching.rb +185 -184
- data/lib/dommy/internal/element_geometry.rb +8 -1
- data/lib/dommy/internal/element_matching.rb +71 -69
- data/lib/dommy/internal/element_shadow.rb +1 -13
- data/lib/dommy/internal/element_state.rb +255 -265
- data/lib/dommy/internal/event_handlers.rb +66 -64
- data/lib/dommy/internal/exception_report.rb +88 -86
- data/lib/dommy/internal/focusability.rb +205 -205
- data/lib/dommy/internal/global_functions.rb +49 -47
- data/lib/dommy/internal/idl_reflection.rb +99 -97
- data/lib/dommy/internal/js_number.rb +35 -33
- data/lib/dommy/internal/light_dismiss.rb +130 -132
- data/lib/dommy/internal/literal_lookup.rb +75 -75
- data/lib/dommy/internal/mime_type.rb +54 -49
- data/lib/dommy/internal/mutation_coordinator.rb +46 -0
- data/lib/dommy/internal/mutation_observer_microtask.rb +60 -0
- data/lib/dommy/internal/namespaces.rb +51 -49
- data/lib/dommy/internal/node_adopter.rb +25 -1
- data/lib/dommy/internal/node_equality.rb +61 -59
- data/lib/dommy/internal/post_insertion_steps.rb +1 -0
- data/lib/dommy/internal/referrer.rb +144 -0
- data/lib/dommy/internal/rendered_text/collector.rb +22 -3
- data/lib/dommy/internal/rendered_text/computed_box.rb +3 -2
- data/lib/dommy/internal/rendered_text/fragment.rb +37 -38
- data/lib/dommy/internal/rendered_text/items.rb +7 -5
- data/lib/dommy/internal/selector_matcher.rb +361 -359
- data/lib/dommy/internal/selector_parser.rb +74 -62
- data/lib/dommy/internal/sequential_focus_navigation.rb +150 -151
- data/lib/dommy/internal/shadow_root_registry.rb +7 -0
- data/lib/dommy/internal/slot_assignment.rb +117 -0
- data/lib/dommy/internal/slot_signals.rb +125 -0
- data/lib/dommy/internal/unsafe_html.rb +79 -77
- data/lib/dommy/internal/url_parser.rb +5 -29
- data/lib/dommy/internal/web_idl.rb +158 -153
- data/lib/dommy/internal/window_bound.rb +14 -0
- data/lib/dommy/internal/window_constructors.rb +3 -0
- data/lib/dommy/internal/xml_serialization.rb +298 -296
- data/lib/dommy/js/dom_interfaces.rb +13 -1
- data/lib/dommy/js/host_bridge.rb +23 -1
- data/lib/dommy/js/host_callbacks.rb +7 -0
- data/lib/dommy/js/host_runtime.js +625 -61
- data/lib/dommy/js/import_map.rb +1 -1
- data/lib/dommy/js/observable_runtime.js +295 -128
- data/lib/dommy/js/webidl_members.js +1 -1
- data/lib/dommy/js/webidl_signatures.js +35 -6
- data/lib/dommy/media_query_list.rb +1 -0
- data/lib/dommy/message_channel.rb +2 -0
- data/lib/dommy/mutation_observer.rb +25 -29
- data/lib/dommy/navigator.rb +4 -1
- data/lib/dommy/node.rb +4 -0
- data/lib/dommy/notification.rb +1 -0
- data/lib/dommy/promise.rb +12 -0
- data/lib/dommy/range.rb +20 -3
- data/lib/dommy/shadow_root.rb +25 -1
- data/lib/dommy/streams.rb +18 -0
- data/lib/dommy/style_declaration.rb +15 -4
- data/lib/dommy/text_codec.rb +7 -5
- data/lib/dommy/tree_walker.rb +68 -61
- data/lib/dommy/version.rb +1 -1
- data/lib/dommy/web_socket.rb +1 -0
- data/lib/dommy/window.rb +22 -4
- data/lib/dommy/worker.rb +1 -0
- data/lib/dommy/xml_http_request.rb +12 -2
- data/lib/dommy.rb +17 -2
- metadata +11 -3
data/lib/dommy/event.rb
CHANGED
|
@@ -344,27 +344,23 @@ module Dommy
|
|
|
344
344
|
end
|
|
345
345
|
|
|
346
346
|
event.__internal_set_current_target__(entry.invocation_target)
|
|
347
|
-
|
|
348
|
-
# then restored — but NOT for a listener inside a shadow tree, which would
|
|
349
|
-
# otherwise hand an encapsulated event to the outer global.
|
|
350
|
-
window = window_of(entry.invocation_target)
|
|
351
|
-
previous_event = window&.__internal_current_event__
|
|
352
|
-
window.__internal_set_current_event__(event) if window && !entry.in_shadow_tree
|
|
353
|
-
begin
|
|
354
|
-
entry.invocation_target.__internal_deliver_event__(event, phase)
|
|
355
|
-
ensure
|
|
356
|
-
window&.__internal_set_current_event__(previous_event)
|
|
357
|
-
end
|
|
347
|
+
entry.invocation_target.__internal_deliver_event__(event, phase, in_shadow_tree: entry.in_shadow_tree)
|
|
358
348
|
throw :stop_propagation if event.propagation_stopped?
|
|
359
349
|
end
|
|
360
350
|
|
|
361
|
-
# The Window whose `event` global covers this
|
|
362
|
-
# no browsing context.
|
|
351
|
+
# The Window whose `event` global covers this target, or nil for a node
|
|
352
|
+
# with no browsing context. A target that is not a node (an
|
|
353
|
+
# XMLHttpRequest, a WebSocket, a MessagePort) is covered by the window it
|
|
354
|
+
# was made for (Internal::WindowBound); one made for none
|
|
355
|
+
# (`new EventTarget()`, an AbortSignal) has none.
|
|
363
356
|
def window_of(node)
|
|
364
357
|
return node if node.is_a?(Window)
|
|
365
358
|
|
|
366
359
|
document = node.is_a?(Document) ? node : (node.document if node.respond_to?(:document))
|
|
367
|
-
document.default_view if document.respond_to?(:default_view)
|
|
360
|
+
return document.default_view if document.respond_to?(:default_view)
|
|
361
|
+
|
|
362
|
+
window = node.__internal_relevant_window__ if node.respond_to?(:__internal_relevant_window__)
|
|
363
|
+
window if window.is_a?(Window)
|
|
368
364
|
end
|
|
369
365
|
|
|
370
366
|
# WHATWG dispatch steps 5-12: walk from the target outward, recording one
|
|
@@ -468,16 +464,9 @@ module Dommy
|
|
|
468
464
|
# `assignedSlot` deliberately reports null for a closed tree, but the event
|
|
469
465
|
# path still has to route through the slot.
|
|
470
466
|
def assigned_slot_of(node)
|
|
471
|
-
return nil unless node.
|
|
472
|
-
|
|
473
|
-
host = node.parent_node
|
|
474
|
-
return nil unless host.respond_to?(:__internal_shadow_root__)
|
|
467
|
+
return nil unless node.is_a?(Node) && (document = node.owner_document) && (backend = node.__dommy_backend_node__)
|
|
475
468
|
|
|
476
|
-
|
|
477
|
-
return nil unless root
|
|
478
|
-
|
|
479
|
-
name = node.respond_to?(:__internal_attribute_value__) ? node.__internal_attribute_value__("slot").to_s : ""
|
|
480
|
-
root.query_selector_all("slot").find { |slot| (slot.respond_to?(:name) ? slot.name.to_s : "") == name }
|
|
469
|
+
Internal::SlotAssignment.find_slot(document, backend)
|
|
481
470
|
end
|
|
482
471
|
|
|
483
472
|
def closed_shadow_root?(node)
|
|
@@ -493,7 +482,9 @@ module Dommy
|
|
|
493
482
|
|
|
494
483
|
# `phase` is :capture (capture listeners), :bubble (non-capture), or :both
|
|
495
484
|
# (at the target). stopImmediatePropagation ends delivery within this node.
|
|
496
|
-
|
|
485
|
+
# `in_shadow_tree` is DOM's invocationTargetInShadowTree, which keeps
|
|
486
|
+
# `window.event` from showing an encapsulated event.
|
|
487
|
+
def __internal_deliver_event__(event, phase = :both, in_shadow_tree: false)
|
|
497
488
|
listeners = listeners_for(event.type).dup
|
|
498
489
|
listeners.each do |entry|
|
|
499
490
|
next if entry.removed?
|
|
@@ -513,17 +504,19 @@ module Dommy
|
|
|
513
504
|
end
|
|
514
505
|
end
|
|
515
506
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
507
|
+
with_current_event(listener_global(entry.listener), event, in_shadow_tree) do
|
|
508
|
+
if entry.event_handler?
|
|
509
|
+
# The event handler processing algorithm: the handler's CURRENT value
|
|
510
|
+
# runs, and its return value is processed — onerror on a global
|
|
511
|
+
# cancels on `true`, every other handler on `false`
|
|
512
|
+
# (`onsubmit="return false"`).
|
|
513
|
+
invoked, result = invoke_event_handler(entry, event)
|
|
514
|
+
__internal_process_event_handler_return__(event, result) if invoked
|
|
515
|
+
elsif entry.passive?
|
|
516
|
+
event.__internal_run_passive__ { invoke_listener_isolated(entry.listener, event, self) }
|
|
517
|
+
else
|
|
518
|
+
invoke_listener_isolated(entry.listener, event, self)
|
|
519
|
+
end
|
|
527
520
|
end
|
|
528
521
|
|
|
529
522
|
break if event.immediate_propagation_stopped?
|
|
@@ -532,6 +525,31 @@ module Dommy
|
|
|
532
525
|
nil
|
|
533
526
|
end
|
|
534
527
|
|
|
528
|
+
# DOM "inner invoke" steps 8-11: the legacy `window.event` of the listener's
|
|
529
|
+
# global is the event while the listener runs (unless the invocation target
|
|
530
|
+
# is in a shadow tree), and what it was before afterwards. A global that is
|
|
531
|
+
# not a Window has none.
|
|
532
|
+
def with_current_event(window, event, in_shadow_tree)
|
|
533
|
+
return yield unless window.is_a?(Window)
|
|
534
|
+
|
|
535
|
+
previous_event = window.__internal_current_event__
|
|
536
|
+
window.__internal_set_current_event__(event) unless in_shadow_tree
|
|
537
|
+
begin
|
|
538
|
+
yield
|
|
539
|
+
ensure
|
|
540
|
+
window.__internal_set_current_event__(previous_event)
|
|
541
|
+
end
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
# The global of a listener's callback's realm: a script function's
|
|
545
|
+
# window. A Ruby listener (or an event handler, which Dommy compiles in
|
|
546
|
+
# the target's window) has no realm of its own; the target's window
|
|
547
|
+
# stands for it.
|
|
548
|
+
def listener_global(listener)
|
|
549
|
+
window = listener.__internal_window__ if listener.respond_to?(:__internal_window__)
|
|
550
|
+
window || window_of(self)
|
|
551
|
+
end
|
|
552
|
+
|
|
535
553
|
# WHATWG event handler processing algorithm, step "process return value":
|
|
536
554
|
# the special error handler (onerror on a Window) cancels the event when the
|
|
537
555
|
# handler returns true; onbeforeunload has its own returnValue handling
|
|
@@ -859,8 +877,20 @@ module Dommy
|
|
|
859
877
|
@in_passive_listener = previous
|
|
860
878
|
end
|
|
861
879
|
|
|
880
|
+
# Dispatch's targetOverride: the target itself, or the document a Window
|
|
881
|
+
# event carries under the legacy target override. The override holds for
|
|
882
|
+
# one dispatch only, so a re-dispatch starts from its own target rather
|
|
883
|
+
# than from where the previous dispatch left `target`.
|
|
862
884
|
def __internal_prepare_for_dispatch__(target)
|
|
863
|
-
@target
|
|
885
|
+
@target = @legacy_target_override || target
|
|
886
|
+
@legacy_target_override = nil
|
|
887
|
+
end
|
|
888
|
+
|
|
889
|
+
# HTML's "legacy target override flag": a Window's load, pageshow,
|
|
890
|
+
# pagehide and unload are targeted at its document.
|
|
891
|
+
def __internal_set_legacy_target_override__(document)
|
|
892
|
+
@legacy_target_override = document
|
|
893
|
+
self
|
|
864
894
|
end
|
|
865
895
|
|
|
866
896
|
# The shadow-adjusted target for the node currently being visited. The
|
|
@@ -957,8 +987,9 @@ module Dommy
|
|
|
957
987
|
@propagation_stopped = true if value
|
|
958
988
|
when "returnValue"
|
|
959
989
|
# Legacy alias: returnValue = false cancels the event (like
|
|
960
|
-
# preventDefault); a truthy value does
|
|
961
|
-
|
|
990
|
+
# preventDefault, so not from a passive listener); a truthy value does
|
|
991
|
+
# not un-cancel.
|
|
992
|
+
@default_prevented = true if !Internal::WebIDL.boolean(value) && @cancelable && !@in_passive_listener
|
|
962
993
|
else
|
|
963
994
|
return Bridge::UNHANDLED
|
|
964
995
|
end
|
|
@@ -2061,8 +2092,8 @@ module Dommy
|
|
|
2061
2092
|
@key = nullable_string(args[3])
|
|
2062
2093
|
@old_value = nullable_string(args[4])
|
|
2063
2094
|
@new_value = nullable_string(args[5])
|
|
2064
|
-
@url = (args[6]
|
|
2065
|
-
@storage_area = args[7]
|
|
2095
|
+
@url = optional_url(args[6])
|
|
2096
|
+
@storage_area = args[7].equal?(Bridge::UNDEFINED) ? nil : args[7]
|
|
2066
2097
|
end
|
|
2067
2098
|
nil
|
|
2068
2099
|
else
|
|
@@ -2072,6 +2103,12 @@ module Dommy
|
|
|
2072
2103
|
|
|
2073
2104
|
private
|
|
2074
2105
|
|
|
2106
|
+
# initStorageEvent's `optional USVString url = ""`: an undefined (or
|
|
2107
|
+
# omitted) argument takes the default.
|
|
2108
|
+
def optional_url(value)
|
|
2109
|
+
value.nil? || value.equal?(Bridge::UNDEFINED) ? "" : value.to_s
|
|
2110
|
+
end
|
|
2111
|
+
|
|
2075
2112
|
# The IDL's nullable DOMString: a present value stringifies, null/undefined
|
|
2076
2113
|
# stay null rather than becoming "".
|
|
2077
2114
|
def nullable_string(value)
|
|
@@ -2374,6 +2411,19 @@ module Dommy
|
|
|
2374
2411
|
nil
|
|
2375
2412
|
end
|
|
2376
2413
|
|
|
2414
|
+
# DOM "remove an algorithm from a signal": for a caller whose algorithm
|
|
2415
|
+
# has nothing left to abort, so a long-lived signal does not keep it.
|
|
2416
|
+
def __internal_remove_abort_algorithm__(callback)
|
|
2417
|
+
@abort_algorithms.delete(callback)
|
|
2418
|
+
nil
|
|
2419
|
+
end
|
|
2420
|
+
|
|
2421
|
+
# Drop the algorithms the block says have nothing left to abort.
|
|
2422
|
+
def __internal_remove_abort_algorithms_if__(&block)
|
|
2423
|
+
@abort_algorithms.reject!(&block)
|
|
2424
|
+
nil
|
|
2425
|
+
end
|
|
2426
|
+
|
|
2377
2427
|
# Sentinel meaning "no reason argument was supplied" — distinct from an
|
|
2378
2428
|
# explicit `null` reason (`abort(null)` keeps reason null, but `abort()` /
|
|
2379
2429
|
# `abort(undefined)` default to a fresh AbortError).
|
|
@@ -2398,8 +2448,12 @@ module Dommy
|
|
|
2398
2448
|
dependents_to_abort << dependent
|
|
2399
2449
|
end
|
|
2400
2450
|
|
|
2401
|
-
__internal_run_abort_steps__
|
|
2402
|
-
dependents_to_abort.each
|
|
2451
|
+
error = __internal_run_abort_steps__
|
|
2452
|
+
dependents_to_abort.each do |dependent|
|
|
2453
|
+
dependent_error = dependent.__internal_run_abort_steps__
|
|
2454
|
+
error ||= dependent_error
|
|
2455
|
+
end
|
|
2456
|
+
raise error if error
|
|
2403
2457
|
end
|
|
2404
2458
|
|
|
2405
2459
|
# ----- dependent-signal plumbing (package-private, used by .any) -----
|
|
@@ -2433,22 +2487,21 @@ module Dommy
|
|
|
2433
2487
|
|
|
2434
2488
|
# The spec's "abort steps": run the registered abort algorithms first
|
|
2435
2489
|
# (synchronously, ahead of any listener), then fire the trusted "abort" event.
|
|
2490
|
+
# What a JS algorithm throws is returned (the first one) for `abort()` to
|
|
2491
|
+
# throw to its caller once every step has run.
|
|
2436
2492
|
def __internal_run_abort_steps__
|
|
2437
2493
|
algorithms = @abort_algorithms
|
|
2438
2494
|
@abort_algorithms = []
|
|
2439
|
-
|
|
2495
|
+
error = nil
|
|
2496
|
+
algorithms.each do |algo|
|
|
2497
|
+
CallableInvoker.invoke_raising(algo)
|
|
2498
|
+
rescue Bridge::ThrowValue => e
|
|
2499
|
+
error ||= e
|
|
2500
|
+
rescue StandardError
|
|
2501
|
+
nil
|
|
2502
|
+
end
|
|
2440
2503
|
dispatch_event(Event.new("abort", "bubbles" => false, "cancelable" => false).__internal_mark_trusted__)
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
# Run one abort algorithm (a JS callback over the bridge, or a Ruby proc).
|
|
2444
|
-
# A throw is swallowed deliberately: WHATWG runs every abort algorithm and
|
|
2445
|
-
# then fires the "abort" event regardless, so one algorithm's failure must
|
|
2446
|
-
# not abort the run. (The sole caller — the Observable polyfill — already
|
|
2447
|
-
# catches inside its own teardown, so this is a defensive backstop.)
|
|
2448
|
-
def invoke_abort_algorithm(algo)
|
|
2449
|
-
CallableInvoker.invoke(algo)
|
|
2450
|
-
rescue StandardError
|
|
2451
|
-
nil
|
|
2504
|
+
error
|
|
2452
2505
|
end
|
|
2453
2506
|
end
|
|
2454
2507
|
|
data/lib/dommy/event_source.rb
CHANGED