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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2063a6335f55bcddf4a9db6b162b0ea69ccce3aaa4c8b7bd45069850992c98ca
|
|
4
|
+
data.tar.gz: 725b6c8395b377fcddbda372ecb55709f169e0143b5a0bc404f78036db18e243
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7a4af1e30b2e3efe5de479b05c67d770e7ca6e11b71db0fc932c5ba382cee6e52a65ebebfb63be3aa2ac8e431efec5e1da9f97fcbc85fd3fea7e12926b3f4350
|
|
7
|
+
data.tar.gz: 0dab9637f563f76636614616d79b2422e618ac92aff8cc39a5b8f3c64730ee1af68b48f09b76b37d5b9c2b85bcd38131549863862ee598f4c5b7b0b0d449b42e
|
data/lib/dommy/animation.rb
CHANGED
data/lib/dommy/backend.rb
CHANGED
|
@@ -91,6 +91,9 @@ module Dommy
|
|
|
91
91
|
doc.is_a?(::Makiri::XML::Document) ? empty_xml_document : empty_document
|
|
92
92
|
end
|
|
93
93
|
|
|
94
|
+
# Whether backend node `node` belongs to an XML document's tree.
|
|
95
|
+
def xml_node?(node) = node.is_a?(::Makiri::XML::NodeMethods)
|
|
96
|
+
|
|
94
97
|
# Bring `node` (already detached from its old tree) into `target_doc`,
|
|
95
98
|
# returning the backend node now owned by `target_doc`. Lexbor's arenas
|
|
96
99
|
# can't move a node between documents, so adoption imports a detached
|
data/lib/dommy/blob.rb
CHANGED
|
@@ -187,6 +187,12 @@ module Dommy
|
|
|
187
187
|
@last_modified = (raw_lm || (Time.now.to_f * 1000)).to_i
|
|
188
188
|
end
|
|
189
189
|
|
|
190
|
+
# A File under another name keeps its lastModified (XHR's "create an
|
|
191
|
+
# entry"); only a Blob gets a new one.
|
|
192
|
+
def __internal_file_named__(name)
|
|
193
|
+
File.new([@data], name, {"type" => @type, "lastModified" => @last_modified}, @window)
|
|
194
|
+
end
|
|
195
|
+
|
|
190
196
|
# File's serialization + deserialization steps: bytes, type, name and
|
|
191
197
|
# lastModified.
|
|
192
198
|
def __internal_structured_clone__(_for_storage = false)
|
data/lib/dommy/browser.rb
CHANGED
|
@@ -58,8 +58,11 @@ module Dommy
|
|
|
58
58
|
browser
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
+
# `encoding` is the encoding the page's bytes were decoded with
|
|
62
|
+
# (Encodings.decode_document), when it came from bytes; HTML given as a
|
|
63
|
+
# string makes a UTF-8 document.
|
|
61
64
|
def initialize(html, url: "http://localhost/", resources: nil, execute_scripts: true, strict: true, settle: true,
|
|
62
|
-
wasm_memory_shim: false, backend: nil, navigable: false, same_origin: false)
|
|
65
|
+
wasm_memory_shim: false, backend: nil, navigable: false, same_origin: false, encoding: nil)
|
|
63
66
|
@resources = resources
|
|
64
67
|
@same_origin = same_origin
|
|
65
68
|
@backend = backend
|
|
@@ -81,7 +84,7 @@ module Dommy
|
|
|
81
84
|
@cookie_jar = CookieJar.new
|
|
82
85
|
@before_unload_handler = nil
|
|
83
86
|
|
|
84
|
-
@window = Dommy.parse(html)
|
|
87
|
+
@window = Dommy.parse(html, encoding: encoding)
|
|
85
88
|
@window.location.__internal_set_url__(url) if url
|
|
86
89
|
@window.storage_provider = @storage_provider
|
|
87
90
|
@window.cookie_jar = @cookie_jar
|
|
@@ -558,7 +561,12 @@ module Dommy
|
|
|
558
561
|
fire_unload(old_window)
|
|
559
562
|
check_js_errors!
|
|
560
563
|
|
|
561
|
-
|
|
564
|
+
# HTML's <meta charset> prescan is for an HTML document (one that names
|
|
565
|
+
# no type is taken for one); an XML type's encoding is not a <meta>'s.
|
|
566
|
+
content_type = response_header(response, "content-type")
|
|
567
|
+
type = Internal::MimeType.essence(content_type)
|
|
568
|
+
text, encoding = Encodings.decode_document(response.body, content_type, html: type.empty? || type == "text/html")
|
|
569
|
+
new_window = Dommy.parse(text, encoding: encoding)
|
|
562
570
|
new_window.location.__internal_set_url__(final_url)
|
|
563
571
|
new_window.document.__internal_set_last_modified__(response_header(response, "last-modified"))
|
|
564
572
|
new_window.document.__internal_referrer__ = referrer if referrer
|
|
@@ -763,7 +771,7 @@ module Dommy
|
|
|
763
771
|
document = window.document
|
|
764
772
|
window.dispatch_event(document.__internal_page_transition_event__("pagehide"))
|
|
765
773
|
unload = Dommy::Event.new("unload")
|
|
766
|
-
unload.
|
|
774
|
+
unload.__internal_set_legacy_target_override__(document)
|
|
767
775
|
window.dispatch_event(unload.__internal_mark_trusted__)
|
|
768
776
|
end
|
|
769
777
|
|
data/lib/dommy/character_data.rb
CHANGED
|
@@ -269,19 +269,7 @@ module Dommy
|
|
|
269
269
|
# no `slot` attribute, so it targets the default (unnamed) slot of its parent
|
|
270
270
|
# element's shadow tree; a closed shadow tree hides the assignment (null).
|
|
271
271
|
def assigned_slot
|
|
272
|
-
|
|
273
|
-
return nil unless parent&.element?
|
|
274
|
-
|
|
275
|
-
host = @document.wrap_node(parent)
|
|
276
|
-
return nil unless host.respond_to?(:shadow_root)
|
|
277
|
-
|
|
278
|
-
sr = host.shadow_root
|
|
279
|
-
return nil unless sr
|
|
280
|
-
return nil if sr.__js_get__("mode") == "closed"
|
|
281
|
-
|
|
282
|
-
sr.query_selector_all("slot").find do |slot|
|
|
283
|
-
(slot.respond_to?(:name) ? slot.name.to_s : "") == ""
|
|
284
|
-
end
|
|
272
|
+
Internal::SlotAssignment.find_slot(@document, @__node__, open: true)
|
|
285
273
|
end
|
|
286
274
|
|
|
287
275
|
def __js_set__(key, value)
|
data/lib/dommy/cookie_store.rb
CHANGED
|
@@ -10,6 +10,7 @@ module Dommy
|
|
|
10
10
|
# Spec: https://cookiestore.spec.whatwg.org/
|
|
11
11
|
class CookieStore
|
|
12
12
|
include EventTarget
|
|
13
|
+
include Internal::WindowBound
|
|
13
14
|
|
|
14
15
|
def initialize(window)
|
|
15
16
|
@window = window
|
|
@@ -95,7 +96,7 @@ module Dommy
|
|
|
95
96
|
opts = arg.transform_keys(&:to_s)
|
|
96
97
|
url = document_url
|
|
97
98
|
if opts["url"]
|
|
98
|
-
parsed = @window.__internal_parse_url__(opts["url"].to_s)
|
|
99
|
+
parsed = @window.__internal_parse_url__(opts["url"].to_s, utf8: true)
|
|
99
100
|
raise Bridge::TypeError, "invalid url" unless parsed && Internal::Origin.of_url(parsed) == @window.origin
|
|
100
101
|
|
|
101
102
|
url = parsed
|
data/lib/dommy/document.rb
CHANGED
|
@@ -693,12 +693,18 @@ module Dommy
|
|
|
693
693
|
@quirks_mode = value
|
|
694
694
|
end
|
|
695
695
|
|
|
696
|
-
# The document's character encoding, as an Encoding Standard name
|
|
697
|
-
#
|
|
698
|
-
# HTML's
|
|
699
|
-
#
|
|
696
|
+
# The document's character encoding, as an Encoding Standard name: what
|
|
697
|
+
# its bytes were decoded with (Encodings.decode_document, which reads a
|
|
698
|
+
# `<meta charset>` from an HTML document's bytes); a document parsed from a
|
|
699
|
+
# string, which is text already, is UTF-8. The DOM is held as UTF-8
|
|
700
|
+
# either way; the encoding is what HTML's "encoding-parse a URL" (a link's
|
|
701
|
+
# query) and form submission encode with.
|
|
700
702
|
def character_encoding
|
|
701
|
-
"UTF-8"
|
|
703
|
+
@character_encoding || "UTF-8"
|
|
704
|
+
end
|
|
705
|
+
|
|
706
|
+
def __internal_character_encoding__=(name)
|
|
707
|
+
@character_encoding = name
|
|
702
708
|
end
|
|
703
709
|
|
|
704
710
|
# ----- Public Ruby API (snake_case) -----
|
|
@@ -845,6 +851,13 @@ module Dommy
|
|
|
845
851
|
@creator_url || "about:blank"
|
|
846
852
|
end
|
|
847
853
|
|
|
854
|
+
# The window whose event loop runs this document's tasks and microtasks:
|
|
855
|
+
# its own, or for a document with none, the window of the document whose
|
|
856
|
+
# API made it.
|
|
857
|
+
def __internal_event_loop_window__
|
|
858
|
+
@default_view || @origin_document&.__internal_event_loop_window__
|
|
859
|
+
end
|
|
860
|
+
|
|
848
861
|
# A document made by a parsing or creation API (DOMParser,
|
|
849
862
|
# DOMImplementation) takes its origin from `document` — the relevant
|
|
850
863
|
# global object's associated Document — and, for DOMParser, its URL too.
|
|
@@ -1092,41 +1105,28 @@ module Dommy
|
|
|
1092
1105
|
# wrapper is owned by `this`. Per spec, the source node is left
|
|
1093
1106
|
# in place. `deep: true` copies the entire subtree.
|
|
1094
1107
|
def import_node(node, deep = false)
|
|
1108
|
+
# WebIDL converts `options` before the method steps run, so a bad
|
|
1109
|
+
# customElementRegistry is a TypeError whatever `node` is — an Attr, or
|
|
1110
|
+
# even a Document.
|
|
1111
|
+
deep, registry = import_node_options(deep)
|
|
1112
|
+
|
|
1095
1113
|
# Step 1: "If node is a document or shadow root, throw a
|
|
1096
1114
|
# NotSupportedError." Neither has anywhere to go in another document.
|
|
1097
1115
|
if node.is_a?(Document) || node.is_a?(ShadowRoot)
|
|
1098
1116
|
raise DOMException::NotSupportedError, "a #{node.is_a?(Document) ? "document" : "shadow root"} cannot be imported"
|
|
1099
1117
|
end
|
|
1100
1118
|
|
|
1119
|
+
# Step 5.3: a global registry stands only for its own document.
|
|
1120
|
+
if registry && !registry.scoped? && !registry.equal?(__internal_custom_element_registry__)
|
|
1121
|
+
raise DOMException::NotSupportedError, "a global registry other than the document's"
|
|
1122
|
+
end
|
|
1123
|
+
|
|
1101
1124
|
# An Attr is a Node but not a backend-tree node: it is copied by rebuilding
|
|
1102
1125
|
# it here with the same qualified name, namespace, prefix and value, owned
|
|
1103
1126
|
# by no element (importNode never attaches the copy to anything).
|
|
1104
1127
|
return import_attribute(node) if node.is_a?(Attr)
|
|
1105
1128
|
return nil unless node.is_a?(Node) && node.__dommy_backend_node__
|
|
1106
1129
|
|
|
1107
|
-
# `(boolean or ImportNodeOptions) options = false`: missing or undefined
|
|
1108
|
-
# is the default, false. Null and an object convert to the dictionary,
|
|
1109
|
-
# whose `selfOnly` negates `deep` (so null clones deep) and whose
|
|
1110
|
-
# `customElementRegistry` (a scoped one, or this document's) is the
|
|
1111
|
-
# registry the copies fall back to. Anything else is a boolean, read
|
|
1112
|
-
# with ToBoolean.
|
|
1113
|
-
registry = nil
|
|
1114
|
-
deep = false if deep.equal?(Bridge::UNDEFINED)
|
|
1115
|
-
if deep.nil? || deep.is_a?(Hash)
|
|
1116
|
-
options = deep || {}
|
|
1117
|
-
deep = !Internal::WebIDL.boolean(options["selfOnly"])
|
|
1118
|
-
given = options.fetch("customElementRegistry", Bridge::UNDEFINED)
|
|
1119
|
-
unless given.equal?(Bridge::UNDEFINED)
|
|
1120
|
-
raise Bridge::TypeError, "customElementRegistry is not a CustomElementRegistry" unless given.is_a?(CustomElementRegistry)
|
|
1121
|
-
if !given.scoped? && !given.equal?(__internal_custom_element_registry__)
|
|
1122
|
-
raise DOMException::NotSupportedError, "a global registry other than the document's"
|
|
1123
|
-
end
|
|
1124
|
-
|
|
1125
|
-
registry = given
|
|
1126
|
-
end
|
|
1127
|
-
else
|
|
1128
|
-
deep = Internal::WebIDL.boolean(deep)
|
|
1129
|
-
end
|
|
1130
1130
|
# "Clone a single node": the node's own registry — a global one standing
|
|
1131
1131
|
# for this document's — and the fallback only for a node without one.
|
|
1132
1132
|
fallback = registry || __internal_custom_element_registry__
|
|
@@ -2530,7 +2530,7 @@ module Dommy
|
|
|
2530
2530
|
view = @default_view
|
|
2531
2531
|
if view
|
|
2532
2532
|
load = Event.new("load")
|
|
2533
|
-
load.
|
|
2533
|
+
load.__internal_set_legacy_target_override__(self)
|
|
2534
2534
|
view.dispatch_event(load.__internal_mark_trusted__)
|
|
2535
2535
|
view.dispatch_event(__internal_page_transition_event__("pageshow"))
|
|
2536
2536
|
end
|
|
@@ -2569,7 +2569,7 @@ module Dommy
|
|
|
2569
2569
|
# back/forward cache), targeted at the document (legacy target override).
|
|
2570
2570
|
def __internal_page_transition_event__(type, persisted: false)
|
|
2571
2571
|
event = PageTransitionEvent.new(type, "persisted" => persisted, "bubbles" => true, "cancelable" => true)
|
|
2572
|
-
event.
|
|
2572
|
+
event.__internal_set_legacy_target_override__(self)
|
|
2573
2573
|
event.__internal_mark_trusted__
|
|
2574
2574
|
end
|
|
2575
2575
|
|
|
@@ -2635,6 +2635,7 @@ module Dommy
|
|
|
2635
2635
|
script.__internal_mark_parser_document__
|
|
2636
2636
|
end
|
|
2637
2637
|
parsed_css("meta[http-equiv]").each { |node| __internal_html_element_wrapper__(node)&.__internal_run_pragma__ }
|
|
2638
|
+
parsed_css("meta[name][content]").each { |node| __internal_html_element_wrapper__(node)&.__internal_run_referrer_metadata__ }
|
|
2638
2639
|
# An open dialog the parser inserted runs its dialog setup steps.
|
|
2639
2640
|
parsed_css("dialog[open]").each do |node|
|
|
2640
2641
|
dialog = __internal_html_element_wrapper__(node)
|
|
@@ -2667,6 +2668,12 @@ module Dommy
|
|
|
2667
2668
|
# content=…>`): nil until such a pragma has been processed.
|
|
2668
2669
|
attr_accessor :__internal_pragma_default_language__
|
|
2669
2670
|
|
|
2671
|
+
# The document's referrer policy as `<meta name=referrer>` sets it
|
|
2672
|
+
# (HTMLMetaElement#__internal_run_referrer_metadata__): "" (the default)
|
|
2673
|
+
# until one does.
|
|
2674
|
+
def __internal_referrer_policy__ = @__internal_referrer_policy__ || ""
|
|
2675
|
+
attr_writer :__internal_referrer_policy__
|
|
2676
|
+
|
|
2670
2677
|
# DOMParser parses with scripting disabled (HTML) or XML scripting support
|
|
2671
2678
|
# disabled, so every script it makes is "already started": moved or cloned
|
|
2672
2679
|
# into a document that runs scripts, it still does not run. Found by local
|
|
@@ -2730,6 +2737,10 @@ module Dommy
|
|
|
2730
2737
|
# node back to its shadow boundary.
|
|
2731
2738
|
# Delegate to ShadowRootRegistry
|
|
2732
2739
|
|
|
2740
|
+
def __internal_unregister_shadow_root__(fragment_node, host_node)
|
|
2741
|
+
@shadow_registry.unregister(fragment_node, host_node)
|
|
2742
|
+
end
|
|
2743
|
+
|
|
2733
2744
|
def __internal_register_shadow_fragment__(fragment_node, shadow_root)
|
|
2734
2745
|
@shadow_registry.register(fragment_node, shadow_root)
|
|
2735
2746
|
end
|
|
@@ -2820,12 +2831,20 @@ module Dommy
|
|
|
2820
2831
|
@shadow_registry.find_enclosing(node)
|
|
2821
2832
|
end
|
|
2822
2833
|
|
|
2834
|
+
# Whether any shadow root is attached in this document.
|
|
2835
|
+
def __internal_any_shadow_roots__ = @shadow_registry.any?
|
|
2836
|
+
|
|
2823
2837
|
# Every ShadowRoot attached in this document — the cascade collects each
|
|
2824
2838
|
# one's <style> sheets and scopes them to that shadow tree.
|
|
2825
2839
|
def __internal_all_shadow_roots__
|
|
2826
2840
|
@shadow_registry.all
|
|
2827
2841
|
end
|
|
2828
2842
|
|
|
2843
|
+
# The slots whose slotchange is pending (DOM "signal slots").
|
|
2844
|
+
def __internal_slot_signals__
|
|
2845
|
+
@slot_signals ||= Internal::SlotSignals.new(self)
|
|
2846
|
+
end
|
|
2847
|
+
|
|
2829
2848
|
# Lifecycle callback dispatchers. Errors raised inside user
|
|
2830
2849
|
# callbacks are swallowed so a single buggy custom element can't
|
|
2831
2850
|
# break the whole mutation pipeline.
|
|
@@ -3423,6 +3442,24 @@ module Dommy
|
|
|
3423
3442
|
|
|
3424
3443
|
private
|
|
3425
3444
|
|
|
3445
|
+
# `(boolean or ImportNodeOptions) options = false`, as [deep, registry]:
|
|
3446
|
+
# missing or undefined is the default, false. Null and an object convert
|
|
3447
|
+
# to the dictionary, whose `selfOnly` negates `deep` (so null clones deep)
|
|
3448
|
+
# and whose `customElementRegistry` has to be a CustomElementRegistry.
|
|
3449
|
+
# Anything else is a boolean, read with ToBoolean.
|
|
3450
|
+
def import_node_options(options)
|
|
3451
|
+
return [false, nil] if options.equal?(Bridge::UNDEFINED)
|
|
3452
|
+
return [Internal::WebIDL.boolean(options), nil] unless options.nil? || options.is_a?(Hash)
|
|
3453
|
+
|
|
3454
|
+
options ||= {}
|
|
3455
|
+
deep = !Internal::WebIDL.boolean(options["selfOnly"])
|
|
3456
|
+
registry = options.fetch("customElementRegistry", Bridge::UNDEFINED)
|
|
3457
|
+
return [deep, nil] if registry.equal?(Bridge::UNDEFINED)
|
|
3458
|
+
raise Bridge::TypeError, "customElementRegistry is not a CustomElementRegistry" unless registry.is_a?(CustomElementRegistry)
|
|
3459
|
+
|
|
3460
|
+
[deep, registry]
|
|
3461
|
+
end
|
|
3462
|
+
|
|
3426
3463
|
# HTML "is a registrable domain suffix of or is equal to" (a single label
|
|
3427
3464
|
# stands in for the public suffix; see #domain=).
|
|
3428
3465
|
def registrable_domain_suffix_or_equal?(suffix_string, original_host)
|
data/lib/dommy/element.rb
CHANGED
|
@@ -1398,6 +1398,17 @@ module Dommy
|
|
|
1398
1398
|
Backend.no_namespace_attribute_value(@__node__, local_name)
|
|
1399
1399
|
end
|
|
1400
1400
|
|
|
1401
|
+
# An ARIA attribute (`role`, `aria-*`) as accessibility reads it: the
|
|
1402
|
+
# content attribute, else a custom element's default ARIA semantics from
|
|
1403
|
+
# its ElementInternals (ARIA §"default implicit ARIA semantics").
|
|
1404
|
+
def __internal_aria_value__(attr)
|
|
1405
|
+
value = __internal_attribute_value__(attr)
|
|
1406
|
+
return value unless value.nil?
|
|
1407
|
+
|
|
1408
|
+
internals = __internal_element_internals__ if respond_to?(:__internal_element_internals__)
|
|
1409
|
+
internals&.__internal_default_aria__(attr)
|
|
1410
|
+
end
|
|
1411
|
+
|
|
1401
1412
|
# HTML's cloning steps, for the state an element keeps beside its
|
|
1402
1413
|
# attributes: what a copy takes over, as a Hash, or nil when there is
|
|
1403
1414
|
# nothing. Each interface and mixin with such state adds its own to what
|
|
@@ -35,6 +35,18 @@ module Dommy
|
|
|
35
35
|
@validity = nil
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
+
# The element's default ARIA value for content attribute `attr` ("role",
|
|
39
|
+
# "aria-label"), as set through these internals; nil when unset.
|
|
40
|
+
def __internal_default_aria__(attr)
|
|
41
|
+
value = @aria[ARIA_IDL_BY_ATTRIBUTE[attr]]
|
|
42
|
+
value&.to_s
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
ARIA_IDL_BY_ATTRIBUTE = Internal::IdlReflection::TABLE.fetch("Element")
|
|
46
|
+
.select { |name, _| ARIA_ATTRIBUTES.include?(name) }
|
|
47
|
+
.to_h { |name, spec| [spec[:attr] || name, name] }.freeze
|
|
48
|
+
private_constant :ARIA_IDL_BY_ATTRIBUTE
|
|
49
|
+
|
|
38
50
|
# Whether the custom state `name` is set (`:state(name)`).
|
|
39
51
|
def state?(name) = @states.include?(name)
|
|
40
52
|
|