kobako 0.27.0 → 0.29.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/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +241 -0
- data/Cargo.lock +132 -126
- data/README.md +240 -147
- data/ROADMAP.md +28 -22
- data/SECURITY.md +2 -2
- data/crates/kobako-runtime/CHANGELOG.md +117 -0
- data/crates/kobako-runtime/Cargo.toml +27 -6
- data/crates/kobako-runtime/README.md +16 -10
- data/crates/kobako-runtime/src/dispatch.rs +8 -0
- data/crates/kobako-runtime/src/error.rs +8 -9
- data/crates/kobako-runtime/src/filesystem/directory/spelling.rs +194 -0
- data/crates/kobako-runtime/src/filesystem/directory.rs +1082 -0
- data/crates/kobako-runtime/src/filesystem/memory.rs +1100 -0
- data/crates/kobako-runtime/src/filesystem/overlay/exclusive.rs +88 -0
- data/crates/kobako-runtime/src/filesystem/overlay/stack.rs +808 -0
- data/crates/kobako-runtime/src/filesystem/overlay.rs +1955 -0
- data/crates/kobako-runtime/src/filesystem/path.rs +60 -0
- data/crates/kobako-runtime/src/filesystem/temporary.rs +167 -0
- data/crates/kobako-runtime/src/filesystem.rs +392 -0
- data/crates/kobako-runtime/src/grant.rs +20 -0
- data/crates/kobako-runtime/src/lib.rs +12 -2
- data/crates/kobako-runtime/src/mount.rs +178 -0
- data/crates/kobako-runtime/src/profile.rs +4 -4
- data/crates/kobako-runtime/src/runtime.rs +43 -17
- data/crates/kobako-runtime/src/snapshot.rs +33 -15
- data/crates/kobako-runtime/src/yielder.rs +14 -6
- data/crates/kobako-transport/CHANGELOG.md +45 -0
- data/crates/kobako-transport/Cargo.toml +1 -1
- data/crates/kobako-transport/README.md +21 -12
- data/crates/kobako-transport/src/abi.rs +11 -14
- data/crates/kobako-transport/src/envelope/bytes.rs +18 -6
- data/crates/kobako-transport/src/envelope/compile_reply.rs +139 -0
- data/crates/kobako-transport/src/envelope/fault.rs +2 -1
- data/crates/kobako-transport/src/envelope/outcome.rs +17 -16
- data/crates/kobako-transport/src/envelope/preamble.rs +513 -0
- data/crates/kobako-transport/src/envelope/reply.rs +103 -61
- data/crates/kobako-transport/src/envelope/request.rs +305 -0
- data/crates/kobako-transport/src/envelope/run.rs +1 -2
- data/crates/kobako-transport/src/envelope/tag.rs +49 -0
- data/crates/kobako-transport/src/envelope/unsupported.rs +105 -0
- data/crates/kobako-transport/src/envelope.rs +19 -12
- data/crates/kobako-transport/src/lib.rs +0 -2
- data/crates/kobako-wasmtime/CHANGELOG.md +163 -0
- data/crates/kobako-wasmtime/Cargo.toml +23 -16
- data/crates/kobako-wasmtime/README.md +6 -4
- data/crates/kobako-wasmtime/src/abi.rs +67 -36
- data/crates/kobako-wasmtime/src/ambient.rs +64 -5
- data/crates/kobako-wasmtime/src/cache.rs +204 -127
- data/crates/kobako-wasmtime/src/capture.rs +4 -11
- data/crates/kobako-wasmtime/src/config.rs +69 -15
- data/crates/kobako-wasmtime/src/descriptors.rs +167 -0
- data/crates/kobako-wasmtime/src/dispatch.rs +95 -87
- data/crates/kobako-wasmtime/src/driver.rs +174 -125
- data/crates/kobako-wasmtime/src/exports.rs +88 -34
- data/crates/kobako-wasmtime/src/guest_mem.rs +151 -138
- data/crates/kobako-wasmtime/src/imports.rs +46 -0
- data/crates/kobako-wasmtime/src/instance_pre.rs +19 -58
- data/crates/kobako-wasmtime/src/invocation.rs +84 -412
- data/crates/kobako-wasmtime/src/io.rs +89 -0
- data/crates/kobako-wasmtime/src/lib.rs +7 -24
- data/crates/kobako-wasmtime/src/limiter.rs +253 -0
- data/crates/kobako-wasmtime/src/preview1/args.rs +60 -0
- data/crates/kobako-wasmtime/src/preview1/beneath.rs +188 -0
- data/crates/kobako-wasmtime/src/preview1/differential/mount.rs +609 -0
- data/crates/kobako-wasmtime/src/preview1/differential.rs +372 -0
- data/crates/kobako-wasmtime/src/preview1/errno.rs +267 -0
- data/crates/kobako-wasmtime/src/preview1/fd.rs +672 -0
- data/crates/kobako-wasmtime/src/preview1/memory.rs +205 -0
- data/crates/kobako-wasmtime/src/preview1/mount_view.rs +2499 -0
- data/crates/kobako-wasmtime/src/preview1/path.rs +421 -0
- data/crates/kobako-wasmtime/src/preview1/poll.rs +333 -0
- data/crates/kobako-wasmtime/src/preview1/sock.rs +30 -0
- data/crates/kobako-wasmtime/src/preview1.rs +461 -0
- data/crates/kobako-wasmtime/src/trap.rs +66 -59
- data/crates/kobako-wasmtime/src/wasi.rs +317 -0
- data/crates/kobako-wasmtime/tests/compile_posture.rs +43 -0
- data/crates/kobako-wasmtime/tests/guest_file.rs +1054 -0
- data/crates/kobako-wasmtime/tests/preamble_flags.rs +70 -0
- data/crates/kobako-wasmtime/tests/snippet_compile.rs +95 -0
- data/crates/kobako-wasmtime/tests/support/mod.rs +30 -0
- data/crates/kobako-wasmtime/tests/unanswered_call.rs +86 -0
- data/crates/kobako-wasmtime/tests/unsupported_call.rs +51 -0
- data/data/kobako.wasm +0 -0
- data/ext/kobako/Cargo.toml +4 -2
- data/ext/kobako/src/runtime/bridge.rs +177 -113
- data/ext/kobako/src/runtime/errors.rs +26 -32
- data/ext/kobako/src/runtime/escape.rs +53 -0
- data/ext/kobako/src/runtime/filesystem/grants.rs +91 -0
- data/ext/kobako/src/runtime/filesystem/ruby.rs +400 -0
- data/ext/kobako/src/runtime/filesystem.rs +236 -0
- data/ext/kobako/src/runtime/gvl.rs +11 -13
- data/ext/kobako/src/runtime/pinned_value.rs +31 -0
- data/ext/kobako/src/runtime/snapshot.rs +127 -0
- data/ext/kobako/src/runtime.rs +190 -312
- data/lib/kobako/capture.rb +1 -4
- data/lib/kobako/catalog/extensions.rb +21 -59
- data/lib/kobako/catalog/flags.rb +29 -0
- data/lib/kobako/catalog/grants.rb +30 -0
- data/lib/kobako/catalog/handles.rb +7 -54
- data/lib/kobako/catalog/mount.rb +27 -0
- data/lib/kobako/catalog/services.rb +17 -60
- data/lib/kobako/catalog/snippets.rb +41 -69
- data/lib/kobako/catalog.rb +13 -10
- data/lib/kobako/codec/decoder.rb +10 -28
- data/lib/kobako/codec/encoder.rb +3 -22
- data/lib/kobako/codec/error.rb +6 -27
- data/lib/kobako/codec/ext_types.rb +72 -94
- data/lib/kobako/codec/handle_walk.rb +65 -130
- data/lib/kobako/codec/nesting.rb +3 -8
- data/lib/kobako/codec/state.rb +21 -11
- data/lib/kobako/codec/utils.rb +6 -34
- data/lib/kobako/codec/value_budget.rb +86 -0
- data/lib/kobako/codec.rb +10 -22
- data/lib/kobako/constant_name.rb +8 -0
- data/lib/kobako/context.rb +83 -117
- data/lib/kobako/errors.rb +57 -132
- data/lib/kobako/execution.rb +16 -21
- data/lib/kobako/extension.rb +23 -40
- data/lib/kobako/filesystem.rb +38 -0
- data/lib/kobako/handle.rb +7 -12
- data/lib/kobako/outcome.rb +51 -80
- data/lib/kobako/payload/arguments.rb +1 -16
- data/lib/kobako/payload.rb +4 -12
- data/lib/kobako/pool.rb +25 -55
- data/lib/kobako/runtime.rb +7 -21
- data/lib/kobako/sandbox.rb +128 -137
- data/lib/kobako/sandbox_options.rb +71 -90
- data/lib/kobako/snippet/bytecode.rb +11 -0
- data/lib/kobako/snippet/source.rb +1 -16
- data/lib/kobako/snippet.rb +2 -10
- data/lib/kobako/transport/block_failure.rb +35 -0
- data/lib/kobako/transport/call.rb +1 -14
- data/lib/kobako/transport/dispatcher.rb +127 -206
- data/lib/kobako/transport/error.rb +6 -20
- data/lib/kobako/transport/exposure.rb +10 -17
- data/lib/kobako/transport/reflection.rb +108 -63
- data/lib/kobako/transport/run.rb +17 -71
- data/lib/kobako/transport/yielder.rb +20 -94
- data/lib/kobako/transport.rb +4 -15
- data/lib/kobako/unresolved.rb +4 -11
- data/lib/kobako/usage.rb +2 -6
- data/lib/kobako/version.rb +1 -1
- data/lib/kobako.rb +1 -0
- data/sig/kobako/catalog/extensions.rbs +2 -2
- data/sig/kobako/catalog/flags.rbs +13 -0
- data/sig/kobako/catalog/grants.rbs +13 -0
- data/sig/kobako/catalog/mount.rbs +28 -0
- data/sig/kobako/catalog/services.rbs +3 -5
- data/sig/kobako/catalog/snippets.rbs +5 -5
- data/sig/kobako/catalog.rbs +1 -0
- data/sig/kobako/codec/ext_types.rbs +10 -8
- data/sig/kobako/codec/handle_walk.rbs +9 -7
- data/sig/kobako/codec/state.rbs +7 -1
- data/sig/kobako/codec/utils.rbs +2 -2
- data/sig/kobako/codec/value_budget.rbs +23 -0
- data/sig/kobako/codec.rbs +4 -2
- data/sig/kobako/constant_name.rbs +3 -0
- data/sig/kobako/context.rbs +15 -8
- data/sig/kobako/errors.rbs +10 -4
- data/sig/kobako/filesystem.rbs +88 -0
- data/sig/kobako/guest_yielder.rbs +9 -0
- data/sig/kobako/outcome.rbs +6 -8
- data/sig/kobako/pool.rbs +1 -1
- data/sig/kobako/runtime.rbs +21 -45
- data/sig/kobako/sandbox.rbs +11 -1
- data/sig/kobako/sandbox_options.rbs +25 -7
- data/sig/kobako/snapshot.rbs +20 -0
- data/sig/kobako/snippet/bytecode.rbs +12 -0
- data/sig/kobako/transport/block_failure.rbs +13 -0
- data/sig/kobako/transport/dispatcher.rbs +15 -19
- data/sig/kobako/transport/exposure.rbs +1 -1
- data/sig/kobako/transport/reflection.rbs +19 -4
- data/sig/kobako/transport/run.rbs +1 -3
- data/sig/kobako/transport/yielder.rbs +5 -9
- data/sig/kobako/transport.rbs +9 -8
- metadata +75 -10
- data/crates/kobako-transport/src/envelope/invocation_frames.rs +0 -241
- data/crates/kobako-wasmtime/src/frames.rs +0 -273
- data/lib/kobako/snippet/binary.rb +0 -26
- data/rust-toolchain.toml +0 -15
- data/sig/kobako/snippet/binary.rbs +0 -12
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
//! A Ruby object Rust holds across calls into the guest, registered with
|
|
2
|
+
//! Ruby's collector so it is neither freed nor moved by compaction while
|
|
3
|
+
//! the holder lives.
|
|
4
|
+
|
|
5
|
+
use magnus::value::Opaque;
|
|
6
|
+
use magnus::{Ruby, Value};
|
|
7
|
+
|
|
8
|
+
use super::gvl;
|
|
9
|
+
|
|
10
|
+
pub(crate) struct PinnedValue(Box<Opaque<Value>>);
|
|
11
|
+
|
|
12
|
+
impl PinnedValue {
|
|
13
|
+
pub(crate) fn new(ruby: &Ruby, value: Value) -> Self {
|
|
14
|
+
let value = Box::new(Opaque::from(value));
|
|
15
|
+
ruby.gc_register_address(&*value);
|
|
16
|
+
Self(value)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
pub(crate) fn get(&self) -> Opaque<Value> {
|
|
20
|
+
*self.0
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
impl Drop for PinnedValue {
|
|
25
|
+
fn drop(&mut self) {
|
|
26
|
+
gvl::reenter(|| {
|
|
27
|
+
let ruby = Ruby::get().expect("Ruby handle unavailable releasing a pinned object");
|
|
28
|
+
ruby.gc_unregister_address(&*self.0);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
//! `Kobako::Snapshot`: one invocation's result at the Ruby boundary.
|
|
2
|
+
|
|
3
|
+
use magnus::{
|
|
4
|
+
method, prelude::*, typed_data::DataTypeFunctions, Error as MagnusError, Exception, RModule,
|
|
5
|
+
RString, Ruby, TypedData,
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
use kobako_runtime::snapshot::{Completion, Snapshot as RuntimeSnapshot};
|
|
9
|
+
use kobako_transport::envelope::Outcome;
|
|
10
|
+
|
|
11
|
+
use super::errors;
|
|
12
|
+
|
|
13
|
+
/// A Panic's fields as they cross to Ruby: origin, class, message,
|
|
14
|
+
/// backtrace, and the names the invocation could have used in place of the
|
|
15
|
+
/// one it named. Named so the Ruby side reads them positionally against one
|
|
16
|
+
/// shape, matching the `Kobako::Outcome::panic_fields` alias.
|
|
17
|
+
type PanicFields = (String, String, String, Vec<String>, Vec<String>);
|
|
18
|
+
|
|
19
|
+
pub(super) fn register(ruby: &Ruby, kobako: RModule) -> Result<(), MagnusError> {
|
|
20
|
+
let snapshot = kobako.define_class("Snapshot", ruby.class_object())?;
|
|
21
|
+
snapshot.define_method("outcome", method!(Snapshot::outcome, 0))?;
|
|
22
|
+
snapshot.define_method("trap_error", method!(Snapshot::trap_error, 0))?;
|
|
23
|
+
snapshot.define_method("wall_time", method!(Snapshot::wall_time, 0))?;
|
|
24
|
+
snapshot.define_method("memory_peak", method!(Snapshot::memory_peak, 0))?;
|
|
25
|
+
snapshot.define_method("stdout", method!(Snapshot::stdout, 0))?;
|
|
26
|
+
snapshot.define_method("stdout_truncated?", method!(Snapshot::stdout_truncated, 0))?;
|
|
27
|
+
snapshot.define_method("stderr", method!(Snapshot::stderr, 0))?;
|
|
28
|
+
snapshot.define_method("stderr_truncated?", method!(Snapshot::stderr_truncated, 0))?;
|
|
29
|
+
Ok(())
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/// One invocation's result at the Ruby boundary — the whole `Snapshot` the
|
|
33
|
+
/// driver produced, exposed as `Kobako::Snapshot`. Usage and the
|
|
34
|
+
/// two output captures are present on every outcome, so the trap path
|
|
35
|
+
/// carries them just like the value path; the completion is read as either
|
|
36
|
+
/// the Outcome (`#outcome`) or a trap (`#trap_error`). The verb names the
|
|
37
|
+
/// invocation, so an unsupported one says which operation is lacking.
|
|
38
|
+
#[derive(TypedData)]
|
|
39
|
+
#[magnus(class = "Kobako::Snapshot", free_immediately, size)]
|
|
40
|
+
pub(super) struct Snapshot(RuntimeSnapshot, &'static str);
|
|
41
|
+
|
|
42
|
+
impl DataTypeFunctions for Snapshot {}
|
|
43
|
+
|
|
44
|
+
impl Snapshot {
|
|
45
|
+
pub(super) fn new(snapshot: RuntimeSnapshot, verb: &'static str) -> Self {
|
|
46
|
+
Self(snapshot, verb)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/// Already split off the core envelope, so the Ruby side maps a failure
|
|
50
|
+
/// onto its error taxonomy without decoding a payload byte: the ok
|
|
51
|
+
/// arm's payload, or a Panic's fields beside an empty payload. A trap
|
|
52
|
+
/// has no Outcome; `#trap_error` is the discriminator there.
|
|
53
|
+
fn outcome(&self) -> Result<(RString, Option<PanicFields>), MagnusError> {
|
|
54
|
+
let ruby = Ruby::get().expect("Ruby thread");
|
|
55
|
+
match &self.0.completion {
|
|
56
|
+
Completion::Outcome(Outcome::Ok(value)) => Ok((ruby.str_from_slice(value), None)),
|
|
57
|
+
Completion::Outcome(Outcome::Panic(panic)) => Ok((
|
|
58
|
+
ruby.str_from_slice(&[]),
|
|
59
|
+
Some((
|
|
60
|
+
panic.origin.name().to_owned(),
|
|
61
|
+
panic.error.name.clone(),
|
|
62
|
+
panic.error.message.clone(),
|
|
63
|
+
panic.error.backtrace.clone(),
|
|
64
|
+
panic.available.clone(),
|
|
65
|
+
)),
|
|
66
|
+
)),
|
|
67
|
+
// The Guest Binary answered rather than broke, so it reads as
|
|
68
|
+
// the Sandbox's failure, worded by the host.
|
|
69
|
+
Completion::Outcome(Outcome::Unsupported(_)) => Ok((
|
|
70
|
+
ruby.str_from_slice(&[]),
|
|
71
|
+
Some((
|
|
72
|
+
"sandbox".to_owned(),
|
|
73
|
+
"Kobako::SandboxError".to_owned(),
|
|
74
|
+
format!(
|
|
75
|
+
"the Sandbox runtime does not support #{}; \
|
|
76
|
+
rebuild it against the kobako version in use",
|
|
77
|
+
self.1
|
|
78
|
+
),
|
|
79
|
+
Vec::new(),
|
|
80
|
+
Vec::new(),
|
|
81
|
+
)),
|
|
82
|
+
)),
|
|
83
|
+
Completion::Trap(_) => Err(MagnusError::new(
|
|
84
|
+
ruby.exception_runtime_error(),
|
|
85
|
+
"a trapped run has no outcome",
|
|
86
|
+
)),
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/// Unraised, so the Sandbox layer can attach the run's Execution before
|
|
91
|
+
/// raising it.
|
|
92
|
+
fn trap_error(&self) -> Result<Option<Exception>, MagnusError> {
|
|
93
|
+
let Completion::Trap(trap) = &self.0.completion else {
|
|
94
|
+
return Ok(None);
|
|
95
|
+
};
|
|
96
|
+
let ruby = Ruby::get().expect("Ruby thread");
|
|
97
|
+
errors::trap_class(&ruby, trap)
|
|
98
|
+
.new_instance((trap.to_string(),))
|
|
99
|
+
.map(Some)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
fn wall_time(&self) -> f64 {
|
|
103
|
+
self.0.usage.wall_time
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
fn memory_peak(&self) -> usize {
|
|
107
|
+
self.0.usage.memory_peak
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
fn stdout(&self) -> RString {
|
|
111
|
+
let ruby = Ruby::get().expect("Ruby thread");
|
|
112
|
+
ruby.str_from_slice(&self.0.stdout.bytes)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
fn stdout_truncated(&self) -> bool {
|
|
116
|
+
self.0.stdout.truncated
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
fn stderr(&self) -> RString {
|
|
120
|
+
let ruby = Ruby::get().expect("Ruby thread");
|
|
121
|
+
ruby.str_from_slice(&self.0.stderr.bytes)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
fn stderr_truncated(&self) -> bool {
|
|
125
|
+
self.0.stderr.truncated
|
|
126
|
+
}
|
|
127
|
+
}
|