dommy 0.8.1 → 0.9.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.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -3
  3. data/lib/dommy/animation.rb +4 -0
  4. data/lib/dommy/attr.rb +11 -5
  5. data/lib/dommy/backend/makiri_adapter.rb +330 -0
  6. data/lib/dommy/backend.rb +114 -33
  7. data/lib/dommy/blob.rb +2 -0
  8. data/lib/dommy/bridge.rb +11 -0
  9. data/lib/dommy/browser.rb +217 -0
  10. data/lib/dommy/compression_streams.rb +4 -0
  11. data/lib/dommy/crypto.rb +4 -0
  12. data/lib/dommy/css.rb +487 -50
  13. data/lib/dommy/custom_elements.rb +2 -2
  14. data/lib/dommy/data_transfer.rb +2 -0
  15. data/lib/dommy/data_uri.rb +35 -0
  16. data/lib/dommy/deferred_response.rb +59 -0
  17. data/lib/dommy/document.rb +386 -228
  18. data/lib/dommy/dom_exception.rb +2 -0
  19. data/lib/dommy/dom_parser.rb +7 -17
  20. data/lib/dommy/element.rb +502 -155
  21. data/lib/dommy/event.rb +240 -9
  22. data/lib/dommy/fetch.rb +152 -34
  23. data/lib/dommy/form_data.rb +2 -0
  24. data/lib/dommy/history.rb +2 -0
  25. data/lib/dommy/html_canvas_element.rb +230 -0
  26. data/lib/dommy/html_collection.rb +5 -6
  27. data/lib/dommy/html_elements.rb +304 -27
  28. data/lib/dommy/interaction/debug.rb +35 -0
  29. data/lib/dommy/interaction/dom_summary.rb +131 -0
  30. data/lib/dommy/interaction/driver.rb +244 -0
  31. data/lib/dommy/interaction/event_synthesis.rb +56 -0
  32. data/lib/dommy/interaction/field_interactor.rb +117 -0
  33. data/lib/dommy/interaction/form_submission.rb +268 -0
  34. data/lib/dommy/interaction/locator.rb +158 -0
  35. data/lib/dommy/interaction/role_query.rb +58 -0
  36. data/lib/dommy/interaction.rb +32 -0
  37. data/lib/dommy/internal/accessibility_tree.rb +215 -0
  38. data/lib/dommy/internal/accessible_description.rb +38 -0
  39. data/lib/dommy/internal/accessible_name.rb +301 -0
  40. data/lib/dommy/internal/aria_role.rb +252 -0
  41. data/lib/dommy/internal/aria_snapshot.rb +64 -0
  42. data/lib/dommy/internal/aria_state.rb +151 -0
  43. data/lib/dommy/internal/css/calc.rb +242 -0
  44. data/lib/dommy/internal/css/cascade.rb +430 -0
  45. data/lib/dommy/internal/css/color.rb +381 -0
  46. data/lib/dommy/internal/css/computed_style_declaration.rb +130 -0
  47. data/lib/dommy/internal/css/counters.rb +227 -0
  48. data/lib/dommy/internal/css/custom_properties.rb +183 -0
  49. data/lib/dommy/internal/css/media_query.rb +302 -0
  50. data/lib/dommy/internal/css/parser.rb +265 -0
  51. data/lib/dommy/internal/css/property_registry.rb +512 -0
  52. data/lib/dommy/internal/css/rule_index.rb +494 -0
  53. data/lib/dommy/internal/css/supports.rb +158 -0
  54. data/lib/dommy/internal/css/ua_stylesheet.rb +53 -0
  55. data/lib/dommy/internal/css_pseudo_handlers.rb +283 -42
  56. data/lib/dommy/internal/css_rule_text.rb +160 -0
  57. data/lib/dommy/internal/dom_matching.rb +80 -9
  58. data/lib/dommy/internal/element_matching.rb +109 -0
  59. data/lib/dommy/internal/global_functions.rb +33 -0
  60. data/lib/dommy/internal/mutation_coordinator.rb +95 -4
  61. data/lib/dommy/internal/namespaces.rb +49 -5
  62. data/lib/dommy/internal/node_wrapper_cache.rb +163 -26
  63. data/lib/dommy/internal/parent_node.rb +82 -5
  64. data/lib/dommy/internal/selector_ast.rb +124 -0
  65. data/lib/dommy/internal/selector_index.rb +146 -0
  66. data/lib/dommy/internal/selector_matcher.rb +756 -0
  67. data/lib/dommy/internal/selector_parser.rb +283 -131
  68. data/lib/dommy/internal/shadow_root_registry.rb +9 -2
  69. data/lib/dommy/internal/template_content_registry.rb +26 -18
  70. data/lib/dommy/internal/xml_serialization.rb +344 -0
  71. data/lib/dommy/intersection_observer.rb +2 -0
  72. data/lib/dommy/js/bridge_conformance.rb +80 -0
  73. data/lib/dommy/js/constructor_resolver.rb +44 -0
  74. data/lib/dommy/js/custom_element_bridge.rb +90 -0
  75. data/lib/dommy/js/dom_interfaces.rb +162 -0
  76. data/lib/dommy/js/handle_table.rb +60 -0
  77. data/lib/dommy/js/host_bridge.rb +517 -0
  78. data/lib/dommy/js/host_runtime.js +1495 -0
  79. data/lib/dommy/js/import_map.rb +58 -0
  80. data/lib/dommy/js/marshaller.rb +240 -0
  81. data/lib/dommy/js/module_loader.rb +99 -0
  82. data/lib/dommy/js/observable_runtime.js +742 -0
  83. data/lib/dommy/js/runtime.rb +115 -0
  84. data/lib/dommy/js/script_boot.rb +221 -0
  85. data/lib/dommy/js/wire_tags.rb +62 -0
  86. data/lib/dommy/location.rb +2 -0
  87. data/lib/dommy/media_query_list.rb +50 -14
  88. data/lib/dommy/message_channel.rb +22 -6
  89. data/lib/dommy/minitest/assertions.rb +27 -0
  90. data/lib/dommy/mutation_observer.rb +89 -4
  91. data/lib/dommy/navigator.rb +34 -2
  92. data/lib/dommy/node.rb +24 -14
  93. data/lib/dommy/notification.rb +2 -0
  94. data/lib/dommy/parser.rb +1 -1
  95. data/lib/dommy/performance.rb +21 -1
  96. data/lib/dommy/promise.rb +94 -10
  97. data/lib/dommy/range.rb +173 -31
  98. data/lib/dommy/resources.rb +178 -0
  99. data/lib/dommy/rspec/capy_style_matchers.rb +126 -0
  100. data/lib/dommy/scheduler.rb +149 -13
  101. data/lib/dommy/screen.rb +91 -0
  102. data/lib/dommy/shadow_root.rb +76 -13
  103. data/lib/dommy/storage.rb +2 -1
  104. data/lib/dommy/streams.rb +6 -0
  105. data/lib/dommy/text_codec.rb +7 -1
  106. data/lib/dommy/tree_walker.rb +33 -10
  107. data/lib/dommy/url.rb +13 -1
  108. data/lib/dommy/version.rb +1 -1
  109. data/lib/dommy/window.rb +199 -11
  110. data/lib/dommy/worker.rb +8 -4
  111. data/lib/dommy/xml_http_request.rb +47 -6
  112. data/lib/dommy.rb +36 -1
  113. metadata +86 -14
  114. data/lib/dommy/backend/nokogiri_adapter.rb +0 -127
  115. data/lib/dommy/backend/nokolexbor_adapter.rb +0 -117
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "base64"
4
+
5
+ module Dommy
6
+ # Decode an RFC 2397 `data:` URI into its bytes + media type, so `fetch` / XHR
7
+ # to an inline `data:` URL resolves like a browser (200 + the decoded payload)
8
+ # instead of falling through to a 404. note.com loads its icon SVGs as
9
+ # `data:image/svg+xml;base64,…` via XHR, which hit this.
10
+ module DataUri
11
+ module_function
12
+
13
+ # `{ body:, content_type: }` for a `data:` URL, or nil for any other URL.
14
+ # The payload is returned as UTF-8 text (the common case for the `text/*` and
15
+ # `image/svg+xml` data URLs fetched this way).
16
+ def parse(url)
17
+ str = url.to_s
18
+ return nil unless str.start_with?("data:")
19
+
20
+ meta, data = str[5..].split(",", 2)
21
+ return nil if data.nil?
22
+
23
+ base64 = meta.end_with?(";base64")
24
+ media = meta.sub(/;base64\z/, "")
25
+ media = "text/plain;charset=US-ASCII" if media.empty?
26
+ bytes =
27
+ if base64
28
+ Base64.decode64(data)
29
+ else
30
+ data.gsub(/%([0-9A-Fa-f]{2})/) { Regexp.last_match(1).hex.chr }
31
+ end
32
+ {body: bytes.dup.force_encoding(Encoding::UTF_8), content_type: media}
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dommy
4
+ # The async-network handoff for fetch / XHR. A `__fetch_handler__` (or XHR stub
5
+ # lookup) may return one of these instead of a response entry to answer a
6
+ # request ASYNCHRONOUSLY: the response is produced off the page thread (e.g. by
7
+ # a network worker doing blocking HTTP), and `#complete(entry)` is called from
8
+ # that thread when it is ready. Delivery is routed through the scheduler's
9
+ # external inbox, so the waiting fetch/XHR is fulfilled on the PAGE thread —
10
+ # single-threaded with the DOM/JS. The worker only ever passes a plain entry
11
+ # Hash (status / headers / body bytes); it never touches Dommy/JS state.
12
+ #
13
+ # `#complete` is thread-safe and races cleanly with `#on_complete` (whichever
14
+ # of register / complete happens last triggers the single delivery).
15
+ class DeferredResponse
16
+ def initialize(scheduler)
17
+ @scheduler = scheduler
18
+ @mutex = Mutex.new
19
+ @on_complete = nil
20
+ @entry = nil
21
+ @completed = false
22
+ @flushed = false
23
+ end
24
+
25
+ # fetch/XHR registers its delivery callback here (invoked on the page thread
26
+ # with the response entry, or nil for a network failure -> a 404-style miss).
27
+ def on_complete(&block)
28
+ @mutex.synchronize { @on_complete = block }
29
+ flush
30
+ self
31
+ end
32
+
33
+ # Called by the worker thread when the response (or nil) is ready. THREAD-SAFE.
34
+ def complete(entry)
35
+ @mutex.synchronize do
36
+ @entry = entry
37
+ @completed = true
38
+ end
39
+ flush
40
+ end
41
+
42
+ private
43
+
44
+ # Once BOTH the callback is registered and the response has arrived, post the
45
+ # one-shot delivery onto the page thread's inbox.
46
+ def flush
47
+ callback = nil
48
+ entry = nil
49
+ @mutex.synchronize do
50
+ return if @flushed || !@completed || @on_complete.nil?
51
+
52
+ @flushed = true
53
+ callback = @on_complete
54
+ entry = @entry
55
+ end
56
+ @scheduler.post_external { callback.call(entry) }
57
+ end
58
+ end
59
+ end