rusty_racer 0.1.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.
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RustyRacer
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "set" # JS Set <-> Ruby Set marshalling needs the stdlib Set constant
4
+
5
+ require_relative "rusty_racer/version"
6
+
7
+ # Load the compiled extension (defines RustyRacer::Isolate etc.). A precompiled
8
+ # ("fat") gem ships one binary per Ruby minor version under
9
+ # rusty_racer/<major.minor>/ (the .so is ABI-specific — a 3.3 build malfunctions
10
+ # on 4.0); the source gem and a local `rake compile` build a single flat
11
+ # rusty_racer/rusty_racer instead. Pick by existence rather than rescuing
12
+ # LoadError, so a binary that IS present but fails to load (a missing transitive
13
+ # lib, an init error) surfaces its real error instead of being masked by the
14
+ # flat fallback.
15
+ versioned = "rusty_racer/#{RUBY_VERSION[/\d+\.\d+/]}/rusty_racer"
16
+
17
+ if File.exist?(File.join(__dir__, "#{versioned}.#{RbConfig::CONFIG['DLEXT']}"))
18
+ require_relative versioned
19
+ else
20
+ require "rusty_racer/rusty_racer"
21
+ end
22
+
23
+ module RustyRacer
24
+ # JS exceptions map to these (see err_class on the Rust side).
25
+ class Error < StandardError; end
26
+ class EvalError < Error; end
27
+ class ParseError < EvalError; end
28
+ class RuntimeError < EvalError; end
29
+ class ScriptTerminatedError < EvalError; end
30
+ class SnapshotError < Error; end
31
+ class PlatformAlreadyInitialized < Error; end
32
+
33
+ # Raised when an Isolate (or a Context/Module/Script it handed out) is used
34
+ # from a thread other than the one that created it. An isolate is
35
+ # thread-confined: every operation must run on its owner thread. The lone
36
+ # exception is Isolate#terminate, which is safe from any thread.
37
+ class WrongThreadError < Error; end
38
+
39
+ # A V8 isolate. Owns the VM and its lifecycle; hands out Contexts to run JS in.
40
+ class Isolate
41
+ # Keyword-arg constructor over the positional Rust primitive. A snapshot
42
+ # (RustyRacer::Snapshot) boots the isolate with its baked-in state;
43
+ # timeout_ms caps each eval/call (0 = no limit) against in-V8 infinite
44
+ # loops. microtasks mirrors V8's kAuto/kExplicit: :auto (default) drains
45
+ # the microtask queue when the outermost eval/call/run/evaluate completes
46
+ # (the standard embedder contract); :explicit drains only on
47
+ # #perform_microtask_checkpoint.
48
+ def self.new(host_namespace: nil, snapshot: nil, timeout_ms: 0, microtasks: :auto)
49
+ unless %i[auto explicit].include?(microtasks)
50
+ raise ArgumentError, "microtasks must be :auto or :explicit, got #{microtasks.inspect}"
51
+ end
52
+
53
+ _new(host_namespace, snapshot, timeout_ms, microtasks == :explicit)
54
+ end
55
+
56
+ # ->(specifier, referrer_url, context) { Module } for JS import(). |context|
57
+ # is the realm import() actually fired in (the Context, not just its id), so
58
+ # an import() from an extra realm resolves/compiles in THAT realm rather than
59
+ # the main one — return e.g. context.compile_module(src, filename: specifier).
60
+ # The block may return a merely compiled Module: linking and evaluation are
61
+ # the binding's job (V8's host contract), and static imports met while linking
62
+ # resolve through this same block (also with the realm as the 3rd arg).
63
+ # (Module#instantiate's own resolve block keeps its 2-arg form.)
64
+ # Held in an ivar so the proc stays alive for the isolate's lifetime (the
65
+ # native side only keeps a weak handle).
66
+ def dynamic_import_resolver=(resolver)
67
+ @dynamic_import_resolver = resolver
68
+ _set_dynamic_import_resolver(resolver)
69
+ end
70
+ end
71
+
72
+ # A v8::Context (realm) handed out by an Isolate: where JS actually runs.
73
+ class Context
74
+ # `timeout_ms` (0 = the isolate default) caps this eval; `filename` names the
75
+ # script in stack traces and parse-error locations.
76
+ def eval(source, timeout_ms: 0, filename: '<eval>')
77
+ _eval(source, timeout_ms, filename)
78
+ end
79
+
80
+ # Compile a classic <script>; returns a RustyRacer::Script to #run.
81
+ # cached_data:/produce_cache: are the bytecode cache (see #compile_module).
82
+ # eager: (see #compile_module).
83
+ def compile(source, filename: '<compile>', cached_data: nil, produce_cache: false, eager: false)
84
+ _compile(source, filename, cached_data, produce_cache, eager)
85
+ end
86
+
87
+ # Compile an ES module; returns a RustyRacer::Module to instantiate/evaluate.
88
+ # cached_data: a binary bytecode cache to consume (skip reparse); the result
89
+ # reports #cache_rejected? if stale. produce_cache: collect a fresh cache,
90
+ # readable via Module#cached_data for cross-process reuse.
91
+ #
92
+ # eager: (default false) compiles every function up front
93
+ # (CompileOptions::EagerCompile) instead of V8's default lazy top-level-only
94
+ # compile. It roughly doubles compile time and uses more memory, so it's only
95
+ # worth it when producing a cache to reuse. Ignored when cached_data: is given
96
+ # (V8 forbids consuming a cache and eager-compiling at once). NOTE: as of
97
+ # V8-150, create_code_cache at compile time still doesn't serialize the eager
98
+ # inner functions, so eager: alone doesn't change the cache yet — it's a
99
+ # forward-looking, semantically-correct switch. For a cache that DOES carry
100
+ # inner functions, run the script/module and call #create_code_cache.
101
+ def compile_module(source, filename: '<compile_module>', cached_data: nil, produce_cache: false, eager: false)
102
+ _compile_module(source, filename, cached_data, produce_cache, eager)
103
+ end
104
+ end
105
+
106
+ class Module
107
+ # instantiate { |specifier, referrer_url| dependency_module } — the block
108
+ # resolves each import to an already-compiled Module. Returns self.
109
+ def instantiate(&block)
110
+ raise ArgumentError, 'instantiate requires a resolver block' unless block
111
+
112
+ _instantiate(block)
113
+ self
114
+ end
115
+
116
+ # The V8 module status: :uninstantiated, :instantiating, :instantiated,
117
+ # :evaluating, :evaluated or :errored.
118
+ def status
119
+ _status.to_sym
120
+ end
121
+ end
122
+ end
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rusty_racer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Keita Urashima
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-06-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rb_sys
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.9'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.9'
27
+ description: 'A V8 engine for Ruby built on rusty_v8 and Magnus: eval, host functions,
28
+ ES modules, snapshots, realms, bytecode cache, and faithful value marshalling.'
29
+ email:
30
+ - ursm@ursm.jp
31
+ executables: []
32
+ extensions:
33
+ - ext/rusty_racer/extconf.rb
34
+ extra_rdoc_files: []
35
+ files:
36
+ - Cargo.toml
37
+ - README.md
38
+ - ext/rusty_racer/Cargo.lock
39
+ - ext/rusty_racer/Cargo.toml
40
+ - ext/rusty_racer/extconf.rb
41
+ - ext/rusty_racer/src/lib.rs
42
+ - lib/rusty_racer.rb
43
+ - lib/rusty_racer/version.rb
44
+ homepage: https://github.com/ursm/rusty_racer
45
+ licenses:
46
+ - MIT
47
+ metadata: {}
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '3.3'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubygems_version: 3.5.22
64
+ signing_key:
65
+ specification_version: 4
66
+ summary: Embed V8 in Ruby via rusty_v8 + Magnus (rb-sys)
67
+ test_files: []