Class: Capybara::Simulated::V8Runtime::Ctx

Inherits:
Object
  • Object
show all
Defined in:
lib/capybara/simulated/v8_runtime.rb

Overview

One isolate + its default context, presented as a single handle — the shape the rest of the runtime (and ‘ScriptCache`) passes around. rusty splits the VM into an `Isolate` (lifecycle / realms / microtasks / terminate) and the `Context`s it hands out (eval / call / attach / compile / reset); this class pairs them and replays recorded host-fn attaches onto per-frame realm contexts (rusty’s attach is per-context).

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(snapshot: nil, timeout: 0) ⇒ Ctx

Returns a new instance of Ctx.



102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/capybara/simulated/v8_runtime.rb', line 102

def initialize(snapshot: nil, timeout: 0)
  @iso        = RustyRacer::Isolate.new(host_namespace: HOST_NAMESPACE_NAME,
                                        snapshot:       snapshot,
                                        timeout_ms:     timeout.to_i)
  @ctx        = @iso.context
  @attached   = []
  @generation = 0
  # rusty's heap-accounting API (heap_statistics / low_memory_notification)
  # landed in 0.1.9. Probe the real Isolate once here — the Ctx wrapper
  # delegates these unconditionally, so a `respond_to?` on the wrapper
  # would always be true and never gate the version. Cached so the
  # per-visit pressure check (rule 3) is an ivar read, not a dispatch.
  @heap_accounting = @iso.respond_to?(:heap_statistics)
end

Instance Attribute Details

#generationObject (readonly)

Bumped on every realm reset: realm-bound caches (module handles) key off ‘[object_id, generation]` so invalidation is intrinsic to reset — the Ctx OBJECT survives a warm reset, so object_id alone can’t detect one.



146
147
148
# File 'lib/capybara/simulated/v8_runtime.rb', line 146

def generation
  @generation
end

Instance Method Details

#attach(name, prc) ⇒ Object

Record every attach so ‘create_context` can replay them: the bridge in a per-frame realm reaches the same Ruby host fns as the main context, but rusty’s attach is per-context.



131
132
133
134
# File 'lib/capybara/simulated/v8_runtime.rb', line 131

def attach(name, prc)
  @attached << [name, prc]
  @ctx.attach(name, prc)
end

#attach_many(fns) ⇒ Object

One rendezvous for the whole host-fn table (vs one per fn).



137
138
139
140
# File 'lib/capybara/simulated/v8_runtime.rb', line 137

def attach_many(fns)
  @attached.concat(fns.to_a)
  @ctx.attach_many(fns)
end

#call(name, *args) ⇒ Object



126
# File 'lib/capybara/simulated/v8_runtime.rb', line 126

def call(name, *args)  = @ctx.call(name, *args)

#compile(src, **kw) ⇒ Object



158
# File 'lib/capybara/simulated/v8_runtime.rb', line 158

def compile(src, **kw)        = @ctx.compile(src, **kw)

#compile_module(src, **kw) ⇒ Object



159
# File 'lib/capybara/simulated/v8_runtime.rb', line 159

def compile_module(src, **kw) = @ctx.compile_module(src, **kw)

#create_contextObject

A per-iframe realm: a fresh context in the SAME isolate (shared heap, own global + intrinsics). Carries ‘.id` / eval / call / dispose — the rest of the surface `create_frame_realm` needs.

‘to_h` dedups re-attached names to their latest proc, matching attach’s override semantics. NOTE: context-bound fns (‘__csim_runScript*`, `__csim_evalEsmEntry`) get realm-bound overrides in `create_frame_realm` after this replay.



182
183
184
185
186
# File 'lib/capybara/simulated/v8_runtime.rb', line 182

def create_context
  realm = @iso.create_context
  realm.attach_many(@attached.to_h)
  realm
end

#disposeObject



163
# File 'lib/capybara/simulated/v8_runtime.rb', line 163

def dispose                          = @iso.dispose

#dynamic_import_resolver=(prc) ⇒ Object



170
171
172
# File 'lib/capybara/simulated/v8_runtime.rb', line 170

def dynamic_import_resolver=(prc)
  @iso.dynamic_import_resolver = prc
end

#eval(src) ⇒ Object

── Context surface ─────────────────────────────────────────rusty drains microtasks at call-depth zero (V8’s default kAuto policy), so a returned eval/call has already run its end-of-script microtasks.



125
# File 'lib/capybara/simulated/v8_runtime.rb', line 125

def eval(src)          = @ctx.eval(src)

#heap_accounting?Boolean

True iff the underlying rusty Isolate exposes the 0.1.9 heap-accounting API. Drives ‘relieve_heap_pressure`’s version gate.

Returns:

  • (Boolean)


119
# File 'lib/capybara/simulated/v8_runtime.rb', line 119

def heap_accounting? = @heap_accounting

#heap_statisticsObject

rusty >= 0.1.9: V8 heap accounting + a forced full GC. Used by the per-visit heap-pressure relief in ‘rebuild_ctx` (see there).



167
# File 'lib/capybara/simulated/v8_runtime.rb', line 167

def heap_statistics                  = @iso.heap_statistics

#low_memory_notificationObject



168
# File 'lib/capybara/simulated/v8_runtime.rb', line 168

def low_memory_notification          = @iso.low_memory_notification

#perform_microtask_checkpointObject



164
165
166
# File 'lib/capybara/simulated/v8_runtime.rb', line 164

def perform_microtask_checkpoint     = @iso.perform_microtask_checkpoint
# rusty >= 0.1.9: V8 heap accounting + a forced full GC. Used by the
# per-visit heap-pressure relief in `rebuild_ctx` (see there).

#resetObject

Swap the realm for a snapshot-fresh one on the warm isolate. Per rusty’s contract the host fns die with the old context — drop the replay record so the caller’s re-attach doesn’t accumulate stale entries visit over visit.



152
153
154
155
156
# File 'lib/capybara/simulated/v8_runtime.rb', line 152

def reset
  @ctx.reset
  @attached.clear
  @generation += 1
end

#terminateObject

── Isolate surface ─────────────────────────────────────────



162
# File 'lib/capybara/simulated/v8_runtime.rb', line 162

def terminate                        = @iso.terminate