capybara-simulated 0.10.0 → 0.11.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 +1 -1
- data/lib/capybara/simulated/asset_cache.rb +6 -3
- data/lib/capybara/simulated/browser.rb +407 -27
- data/lib/capybara/simulated/js/bridge.bundle.js +36424 -26793
- data/lib/capybara/simulated/quickjs_runtime.rb +11 -10
- data/lib/capybara/simulated/runtime_shared.rb +7 -0
- data/lib/capybara/simulated/v8_runtime.rb +4 -1
- data/lib/capybara/simulated/version.rb +1 -1
- metadata +15 -1
|
@@ -253,24 +253,24 @@ module Capybara
|
|
|
253
253
|
# precompiled bytecode. Partial in-VM resets carry the same
|
|
254
254
|
# library-init-leak hazards V8Runtime documents.
|
|
255
255
|
#
|
|
256
|
-
#
|
|
257
|
-
#
|
|
258
|
-
#
|
|
259
|
-
#
|
|
260
|
-
#
|
|
261
|
-
#
|
|
256
|
+
# The OLD VM is disposed here, not left to Ruby's GC: a VM holding the bridge is ~40 MB of
|
|
257
|
+
# C heap behind a Ruby object a few hundred bytes big, so nothing prompts a collection and
|
|
258
|
+
# the dead VMs pile up — a flatware worker climbed monotonically from 300 MB to 4.6 GB over
|
|
259
|
+
# one QuickJS gate, and 30 sessions of two visits each held 1945 MB (measured 2026-09-03).
|
|
260
|
+
# `dispose!` on a bridge-sized VM costs ~4 ms (the same thirty sessions: 3.69 s → 3.92 s,
|
|
261
|
+
# 515 MB), not the hundreds of milliseconds this used to fear.
|
|
262
262
|
def rebuild_ctx
|
|
263
|
+
old = @vm
|
|
263
264
|
@vm = build_vm
|
|
265
|
+
old&.dispose!
|
|
264
266
|
end
|
|
265
267
|
|
|
266
268
|
# Same operation as `rebuild_ctx` since per-visit rebuilds are
|
|
267
269
|
# already the inter-test reset point.
|
|
268
270
|
def reset_page = rebuild_ctx
|
|
269
271
|
|
|
270
|
-
# PERMANENTLY drop this runtime
|
|
271
|
-
#
|
|
272
|
-
# and `dispose!` blocks on the quickjs GC with the GVL held. Here it runs
|
|
273
|
-
# once, when a session is dropped for good, and the cost is the point.
|
|
272
|
+
# PERMANENTLY drop this runtime: the current VM goes the way every superseded one goes in
|
|
273
|
+
# `rebuild_ctx`, disposed rather than left to a GC that has no reason to run.
|
|
274
274
|
#
|
|
275
275
|
# This used to be intentionally absent, on the reasoning that Ruby GC's
|
|
276
276
|
# dfree would reach an unreferenced `@vm` on its own. Measured, it does not
|
|
@@ -480,6 +480,7 @@ module Capybara
|
|
|
480
480
|
resolved = browser.resolve_module_specifier(specifier, importer)
|
|
481
481
|
body = browser.rack_fetch_body(resolved)
|
|
482
482
|
return nil unless body
|
|
483
|
+
browser.note_module_fetch(resolved.to_s) # its Resource Timing entry ('script')
|
|
483
484
|
# `.json` (and `?import` JSON) imports come from Vite's
|
|
484
485
|
# `import.meta.glob` and `import x from './data.json'`
|
|
485
486
|
# patterns. quickjs.rb's loader passes the source through
|
|
@@ -43,6 +43,7 @@ module Capybara
|
|
|
43
43
|
BROWSER_HOST_FNS = {
|
|
44
44
|
'__rackFetch' => ->(b, *a) { b.rack_fetch(a[0], a[1], a[2], a[3], a[4], a[5], credentials: a[6] || 'same-origin', referrer_policy: a[7], referrer: a[8], cache_mode: a[9] || 'default', initiator: a[10], site_seed: a[11], origin_null: a[12], client_url: a[13], cookie_cross_site: a[14] == true, nav_dest: a[15]) },
|
|
45
45
|
'__csimExternalAsset' => ->(b, *a) { b.external_asset_source(a[0]) },
|
|
46
|
+
'__csimExternalAssetMeta' => ->(b, *a) { b.external_asset_meta(a[0]) },
|
|
46
47
|
# fetch(…, {keepalive}) — eager detached-thread dispatch + one-shot result poll.
|
|
47
48
|
'__csim_keepaliveStart' => ->(b, *a) { b.keepalive_start(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10]) },
|
|
48
49
|
'__csim_keepaliveTake' => ->(b, *a) { b.keepalive_take(a[0]) },
|
|
@@ -229,6 +230,12 @@ module Capybara
|
|
|
229
230
|
'__csim_decodeImage' => ->(b, *a) { b.decode_image(a[0], a[1], a[2]) },
|
|
230
231
|
'__csim_renderText' => ->(b, *a) { b.render_text(a[0], a[1], a[2], a[3], a[4]) },
|
|
231
232
|
'__csim_fontAdvances' => ->(b, *a) { b.font_advance_table(a[0], a[1]) },
|
|
233
|
+
'__csim_fontAdvancesFromUrl' => ->(b, *a) { b.font_advance_table_from_url(a[0]) },
|
|
234
|
+
'__csim_localFontTable' => ->(b, *a) { b.local_font_table(a[0], a[1] || '') },
|
|
235
|
+
'__csim_resourceTimingFetch' => ->(b, *a) { b.resource_timing_fetch(a[0], a[1] == true, a[2] || 'same-origin') },
|
|
236
|
+
'__csim_takeModuleRt' => ->(b, *a) { b.take_module_rt },
|
|
237
|
+
'__csim_takeWorkerRt' => ->(b, *a) { b.take_worker_rt },
|
|
238
|
+
'__csim_fontAdvancesFromBytes' => ->(b, *a) { b.font_advance_table_from_bytes(a[0]) },
|
|
232
239
|
'__csim_loadImage' => ->(b, *a) { b.load_image(a[0], !!a[1], a[2] || 'same-origin') },
|
|
233
240
|
'__csim_imageLoadStart' => ->(b, *a) { b.image_load_start(a[0], !!a[1], a[2] || 'same-origin') },
|
|
234
241
|
'__csim_blobRegister' => ->(b, *a) { b.blob_register(a[0], a[1], a[2]); nil },
|
|
@@ -1169,7 +1169,10 @@ module Capybara
|
|
|
1169
1169
|
return handles[url] = nil if r && r['blocked'] # respondWith failed the load
|
|
1170
1170
|
src = r && r['body']
|
|
1171
1171
|
end
|
|
1172
|
-
src
|
|
1172
|
+
if src.nil?
|
|
1173
|
+
src = @browser.rack_fetch_body(url_s)
|
|
1174
|
+
@browser.note_module_fetch(url_s) if src # its Resource Timing entry ('script')
|
|
1175
|
+
end
|
|
1173
1176
|
return handles[url] = nil unless src
|
|
1174
1177
|
body = module_body(url_s, src)
|
|
1175
1178
|
# No-cd warm path: once this isolate has compiled a URL, its in-memory
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: capybara-simulated
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.11.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Keita Urashima
|
|
@@ -65,6 +65,20 @@ dependencies:
|
|
|
65
65
|
- - "~>"
|
|
66
66
|
- !ruby/object:Gem::Version
|
|
67
67
|
version: '2.2'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: brotli
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '0.5'
|
|
75
|
+
type: :runtime
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0.5'
|
|
68
82
|
description: A Capybara driver that runs JavaScript against an in-process JS-resident
|
|
69
83
|
DOM — V8 via rusty_racer or QuickJS via quickjs.rb, whichever is installed. No Chrome,
|
|
70
84
|
no Node toolchain. Forms submit through Rack::MockRequest, inline <script> + event
|