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.
- checksums.yaml +7 -0
- data/Cargo.toml +5 -0
- data/README.md +188 -0
- data/ext/rusty_racer/Cargo.lock +952 -0
- data/ext/rusty_racer/Cargo.toml +23 -0
- data/ext/rusty_racer/extconf.rb +11 -0
- data/ext/rusty_racer/src/lib.rs +4883 -0
- data/lib/rusty_racer/version.rb +5 -0
- data/lib/rusty_racer.rb +122 -0
- metadata +67 -0
data/lib/rusty_racer.rb
ADDED
|
@@ -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: []
|