capybara-simulated 0.6.0 → 0.8.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/README.md +4 -3
- data/lib/capybara/simulated/asset_cache.rb +15 -5
- data/lib/capybara/simulated/browser.rb +3214 -253
- data/lib/capybara/simulated/driver.rb +56 -3
- data/lib/capybara/simulated/js/bridge.bundle.js +26800 -13087
- data/lib/capybara/simulated/node.rb +25 -7
- data/lib/capybara/simulated/quickjs_runtime.rb +52 -9
- data/lib/capybara/simulated/runtime_shared.rb +425 -7
- data/lib/capybara/simulated/v8_runtime.rb +81 -6
- data/lib/capybara/simulated/version.rb +1 -1
- data/vendor/js/vendor.bundle.js +12 -11
- metadata +2 -2
|
@@ -71,7 +71,12 @@ module Capybara
|
|
|
71
71
|
# level and inject them into every per-window Browser. Each
|
|
72
72
|
# Browser still has its own sessionStorage + DOM + JS VM.
|
|
73
73
|
@cookies = {}
|
|
74
|
+
@auth_cache = {}
|
|
74
75
|
@local_storage = {}
|
|
76
|
+
# Cache Storage (caches/Cache) is origin-shared like localStorage — owned at the
|
|
77
|
+
# Driver level and injected, so a service worker and every same-origin window see
|
|
78
|
+
# the same caches (partitioned by origin key within the store).
|
|
79
|
+
@cache_storage = {}
|
|
75
80
|
# Capture the universal-server flag ONCE, at session construction — the WPT
|
|
76
81
|
# runner sets CSIM_LOCAL_ALL_HOSTS only while building the session, then
|
|
77
82
|
# restores it. Every window (incl. aux windows opened later) inherits this so
|
|
@@ -100,7 +105,9 @@ module Capybara
|
|
|
100
105
|
driver: self,
|
|
101
106
|
js_engine: @js_engine,
|
|
102
107
|
cookies: @cookies,
|
|
108
|
+
auth_cache: @auth_cache,
|
|
103
109
|
local_storage: @local_storage,
|
|
110
|
+
cache_storage: @cache_storage,
|
|
104
111
|
all_hosts_local: @all_hosts_local)
|
|
105
112
|
end
|
|
106
113
|
|
|
@@ -274,11 +281,37 @@ module Capybara
|
|
|
274
281
|
def visit(path) = current_browser.visit(path)
|
|
275
282
|
def refresh = current_browser.refresh
|
|
276
283
|
def reset!
|
|
284
|
+
reset_windows!
|
|
285
|
+
browser.reset!
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
# Dispose every auxiliary window and return focus to the primary — a fresh
|
|
289
|
+
# browsing context has no sibling windows. Disposing each aux Browser tears
|
|
290
|
+
# down its worker / SSE / websocket threads and its V8 isolate eagerly; left
|
|
291
|
+
# alone they pile into V8Runtime's process-wide `@@live` set and are only
|
|
292
|
+
# reclaimed by the at_exit hook, which on a long-lived multi-file session
|
|
293
|
+
# (the WPT runner) means a slow — sometimes minutes-long — process exit. Split
|
|
294
|
+
# out of `reset!` so a caller can drop windows WITHOUT resetting the primary's
|
|
295
|
+
# page state (the WPT runner rebuilds the primary itself, per file, via visit).
|
|
296
|
+
def reset_windows!
|
|
277
297
|
@aux_windows.each {|w| w[:browser].dispose rescue nil }
|
|
278
298
|
@aux_windows.clear
|
|
279
299
|
@active_handle = nil
|
|
280
300
|
@blob_partitions_lock.synchronize { @blob_partitions.clear }
|
|
281
|
-
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
# Full teardown of the whole driver: aux windows AND the primary browser's
|
|
304
|
+
# V8 isolate. `reset_windows!` deliberately keeps the primary alive (the
|
|
305
|
+
# per-test reset path rebuilds only its page); this is for permanently
|
|
306
|
+
# DROPPING a session. A caller that nils its session without this leaks the
|
|
307
|
+
# primary isolate — with its heap, canvas pixel buffers, and worker threads —
|
|
308
|
+
# into V8Runtime's process-wide `@@live` until at_exit. The WPT runner recycles
|
|
309
|
+
# the cross-origin session per `.sub.`/`.https.` file, so that leak is ~one
|
|
310
|
+
# isolate per cross-origin file (hundreds over the suite); disposing here
|
|
311
|
+
# incrementally is what reset_windows! already does for aux windows.
|
|
312
|
+
def dispose
|
|
313
|
+
reset_windows!
|
|
314
|
+
@browser.dispose rescue nil
|
|
282
315
|
end
|
|
283
316
|
def go_back = current_browser.go_back
|
|
284
317
|
def go_forward = current_browser.go_forward
|
|
@@ -494,10 +527,30 @@ module Capybara
|
|
|
494
527
|
|
|
495
528
|
# `BroadcastChannel.postMessage` — deliver to every OTHER window's channels
|
|
496
529
|
# with the same name (same-window delivery is handled in-VM by the sender).
|
|
497
|
-
def broadcast_channel(source_browser, name, data)
|
|
530
|
+
def broadcast_channel(source_browser, name, data, origin = nil)
|
|
531
|
+
# An opaque origin is unique to its own agent cluster; its key is a token ('opaque:…') minted
|
|
532
|
+
# per-realm and therefore only unique WITHIN one isolate — two unrelated opaque contexts in
|
|
533
|
+
# DIFFERENT windows could mint the same token. A BroadcastChannel never bridges two distinct
|
|
534
|
+
# opaque origins, and no opaque origin spans separate top-level windows here, so a cross-
|
|
535
|
+
# WINDOW post from an opaque origin reaches no one: drop it rather than risk a cross-isolate
|
|
536
|
+
# token collision. (Same-isolate opaque peers are reached in-VM / via enqueue_broadcast; an
|
|
537
|
+
# inherited-origin blob worker via its own inbox — neither goes through this cross-window path.)
|
|
538
|
+
return if origin.to_s.start_with?('opaque:')
|
|
539
|
+
window_entries.each do |w|
|
|
540
|
+
next if w[:browser].equal?(source_browser)
|
|
541
|
+
w[:browser].enqueue_broadcast(name, data, nil, origin)
|
|
542
|
+
end
|
|
543
|
+
end
|
|
544
|
+
|
|
545
|
+
# A localStorage change fans out to every OTHER window (localStorage spans same-origin
|
|
546
|
+
# browsing contexts). Every window shares the Driver's one `@local_storage` jar, so all
|
|
547
|
+
# windows are same-origin peers here (cross-origin storage partitioning is a separate
|
|
548
|
+
# backlog item); a nil source realm reaches each target's every realm. sessionStorage is
|
|
549
|
+
# per-context and never reaches this path.
|
|
550
|
+
def storage_broadcast(source_browser, kind, key, old, new, url)
|
|
498
551
|
window_entries.each do |w|
|
|
499
552
|
next if w[:browser].equal?(source_browser)
|
|
500
|
-
w[:browser].
|
|
553
|
+
w[:browser].enqueue_storage_event(kind, key, old, new, url, nil)
|
|
501
554
|
end
|
|
502
555
|
end
|
|
503
556
|
|