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.
Files changed (183) hide show
  1. checksums.yaml +4 -4
  2. data/.release-please-manifest.json +1 -1
  3. data/CHANGELOG.md +241 -0
  4. data/Cargo.lock +132 -126
  5. data/README.md +240 -147
  6. data/ROADMAP.md +28 -22
  7. data/SECURITY.md +2 -2
  8. data/crates/kobako-runtime/CHANGELOG.md +117 -0
  9. data/crates/kobako-runtime/Cargo.toml +27 -6
  10. data/crates/kobako-runtime/README.md +16 -10
  11. data/crates/kobako-runtime/src/dispatch.rs +8 -0
  12. data/crates/kobako-runtime/src/error.rs +8 -9
  13. data/crates/kobako-runtime/src/filesystem/directory/spelling.rs +194 -0
  14. data/crates/kobako-runtime/src/filesystem/directory.rs +1082 -0
  15. data/crates/kobako-runtime/src/filesystem/memory.rs +1100 -0
  16. data/crates/kobako-runtime/src/filesystem/overlay/exclusive.rs +88 -0
  17. data/crates/kobako-runtime/src/filesystem/overlay/stack.rs +808 -0
  18. data/crates/kobako-runtime/src/filesystem/overlay.rs +1955 -0
  19. data/crates/kobako-runtime/src/filesystem/path.rs +60 -0
  20. data/crates/kobako-runtime/src/filesystem/temporary.rs +167 -0
  21. data/crates/kobako-runtime/src/filesystem.rs +392 -0
  22. data/crates/kobako-runtime/src/grant.rs +20 -0
  23. data/crates/kobako-runtime/src/lib.rs +12 -2
  24. data/crates/kobako-runtime/src/mount.rs +178 -0
  25. data/crates/kobako-runtime/src/profile.rs +4 -4
  26. data/crates/kobako-runtime/src/runtime.rs +43 -17
  27. data/crates/kobako-runtime/src/snapshot.rs +33 -15
  28. data/crates/kobako-runtime/src/yielder.rs +14 -6
  29. data/crates/kobako-transport/CHANGELOG.md +45 -0
  30. data/crates/kobako-transport/Cargo.toml +1 -1
  31. data/crates/kobako-transport/README.md +21 -12
  32. data/crates/kobako-transport/src/abi.rs +11 -14
  33. data/crates/kobako-transport/src/envelope/bytes.rs +18 -6
  34. data/crates/kobako-transport/src/envelope/compile_reply.rs +139 -0
  35. data/crates/kobako-transport/src/envelope/fault.rs +2 -1
  36. data/crates/kobako-transport/src/envelope/outcome.rs +17 -16
  37. data/crates/kobako-transport/src/envelope/preamble.rs +513 -0
  38. data/crates/kobako-transport/src/envelope/reply.rs +103 -61
  39. data/crates/kobako-transport/src/envelope/request.rs +305 -0
  40. data/crates/kobako-transport/src/envelope/run.rs +1 -2
  41. data/crates/kobako-transport/src/envelope/tag.rs +49 -0
  42. data/crates/kobako-transport/src/envelope/unsupported.rs +105 -0
  43. data/crates/kobako-transport/src/envelope.rs +19 -12
  44. data/crates/kobako-transport/src/lib.rs +0 -2
  45. data/crates/kobako-wasmtime/CHANGELOG.md +163 -0
  46. data/crates/kobako-wasmtime/Cargo.toml +23 -16
  47. data/crates/kobako-wasmtime/README.md +6 -4
  48. data/crates/kobako-wasmtime/src/abi.rs +67 -36
  49. data/crates/kobako-wasmtime/src/ambient.rs +64 -5
  50. data/crates/kobako-wasmtime/src/cache.rs +204 -127
  51. data/crates/kobako-wasmtime/src/capture.rs +4 -11
  52. data/crates/kobako-wasmtime/src/config.rs +69 -15
  53. data/crates/kobako-wasmtime/src/descriptors.rs +167 -0
  54. data/crates/kobako-wasmtime/src/dispatch.rs +95 -87
  55. data/crates/kobako-wasmtime/src/driver.rs +174 -125
  56. data/crates/kobako-wasmtime/src/exports.rs +88 -34
  57. data/crates/kobako-wasmtime/src/guest_mem.rs +151 -138
  58. data/crates/kobako-wasmtime/src/imports.rs +46 -0
  59. data/crates/kobako-wasmtime/src/instance_pre.rs +19 -58
  60. data/crates/kobako-wasmtime/src/invocation.rs +84 -412
  61. data/crates/kobako-wasmtime/src/io.rs +89 -0
  62. data/crates/kobako-wasmtime/src/lib.rs +7 -24
  63. data/crates/kobako-wasmtime/src/limiter.rs +253 -0
  64. data/crates/kobako-wasmtime/src/preview1/args.rs +60 -0
  65. data/crates/kobako-wasmtime/src/preview1/beneath.rs +188 -0
  66. data/crates/kobako-wasmtime/src/preview1/differential/mount.rs +609 -0
  67. data/crates/kobako-wasmtime/src/preview1/differential.rs +372 -0
  68. data/crates/kobako-wasmtime/src/preview1/errno.rs +267 -0
  69. data/crates/kobako-wasmtime/src/preview1/fd.rs +672 -0
  70. data/crates/kobako-wasmtime/src/preview1/memory.rs +205 -0
  71. data/crates/kobako-wasmtime/src/preview1/mount_view.rs +2499 -0
  72. data/crates/kobako-wasmtime/src/preview1/path.rs +421 -0
  73. data/crates/kobako-wasmtime/src/preview1/poll.rs +333 -0
  74. data/crates/kobako-wasmtime/src/preview1/sock.rs +30 -0
  75. data/crates/kobako-wasmtime/src/preview1.rs +461 -0
  76. data/crates/kobako-wasmtime/src/trap.rs +66 -59
  77. data/crates/kobako-wasmtime/src/wasi.rs +317 -0
  78. data/crates/kobako-wasmtime/tests/compile_posture.rs +43 -0
  79. data/crates/kobako-wasmtime/tests/guest_file.rs +1054 -0
  80. data/crates/kobako-wasmtime/tests/preamble_flags.rs +70 -0
  81. data/crates/kobako-wasmtime/tests/snippet_compile.rs +95 -0
  82. data/crates/kobako-wasmtime/tests/support/mod.rs +30 -0
  83. data/crates/kobako-wasmtime/tests/unanswered_call.rs +86 -0
  84. data/crates/kobako-wasmtime/tests/unsupported_call.rs +51 -0
  85. data/data/kobako.wasm +0 -0
  86. data/ext/kobako/Cargo.toml +4 -2
  87. data/ext/kobako/src/runtime/bridge.rs +177 -113
  88. data/ext/kobako/src/runtime/errors.rs +26 -32
  89. data/ext/kobako/src/runtime/escape.rs +53 -0
  90. data/ext/kobako/src/runtime/filesystem/grants.rs +91 -0
  91. data/ext/kobako/src/runtime/filesystem/ruby.rs +400 -0
  92. data/ext/kobako/src/runtime/filesystem.rs +236 -0
  93. data/ext/kobako/src/runtime/gvl.rs +11 -13
  94. data/ext/kobako/src/runtime/pinned_value.rs +31 -0
  95. data/ext/kobako/src/runtime/snapshot.rs +127 -0
  96. data/ext/kobako/src/runtime.rs +190 -312
  97. data/lib/kobako/capture.rb +1 -4
  98. data/lib/kobako/catalog/extensions.rb +21 -59
  99. data/lib/kobako/catalog/flags.rb +29 -0
  100. data/lib/kobako/catalog/grants.rb +30 -0
  101. data/lib/kobako/catalog/handles.rb +7 -54
  102. data/lib/kobako/catalog/mount.rb +27 -0
  103. data/lib/kobako/catalog/services.rb +17 -60
  104. data/lib/kobako/catalog/snippets.rb +41 -69
  105. data/lib/kobako/catalog.rb +13 -10
  106. data/lib/kobako/codec/decoder.rb +10 -28
  107. data/lib/kobako/codec/encoder.rb +3 -22
  108. data/lib/kobako/codec/error.rb +6 -27
  109. data/lib/kobako/codec/ext_types.rb +72 -94
  110. data/lib/kobako/codec/handle_walk.rb +65 -130
  111. data/lib/kobako/codec/nesting.rb +3 -8
  112. data/lib/kobako/codec/state.rb +21 -11
  113. data/lib/kobako/codec/utils.rb +6 -34
  114. data/lib/kobako/codec/value_budget.rb +86 -0
  115. data/lib/kobako/codec.rb +10 -22
  116. data/lib/kobako/constant_name.rb +8 -0
  117. data/lib/kobako/context.rb +83 -117
  118. data/lib/kobako/errors.rb +57 -132
  119. data/lib/kobako/execution.rb +16 -21
  120. data/lib/kobako/extension.rb +23 -40
  121. data/lib/kobako/filesystem.rb +38 -0
  122. data/lib/kobako/handle.rb +7 -12
  123. data/lib/kobako/outcome.rb +51 -80
  124. data/lib/kobako/payload/arguments.rb +1 -16
  125. data/lib/kobako/payload.rb +4 -12
  126. data/lib/kobako/pool.rb +25 -55
  127. data/lib/kobako/runtime.rb +7 -21
  128. data/lib/kobako/sandbox.rb +128 -137
  129. data/lib/kobako/sandbox_options.rb +71 -90
  130. data/lib/kobako/snippet/bytecode.rb +11 -0
  131. data/lib/kobako/snippet/source.rb +1 -16
  132. data/lib/kobako/snippet.rb +2 -10
  133. data/lib/kobako/transport/block_failure.rb +35 -0
  134. data/lib/kobako/transport/call.rb +1 -14
  135. data/lib/kobako/transport/dispatcher.rb +127 -206
  136. data/lib/kobako/transport/error.rb +6 -20
  137. data/lib/kobako/transport/exposure.rb +10 -17
  138. data/lib/kobako/transport/reflection.rb +108 -63
  139. data/lib/kobako/transport/run.rb +17 -71
  140. data/lib/kobako/transport/yielder.rb +20 -94
  141. data/lib/kobako/transport.rb +4 -15
  142. data/lib/kobako/unresolved.rb +4 -11
  143. data/lib/kobako/usage.rb +2 -6
  144. data/lib/kobako/version.rb +1 -1
  145. data/lib/kobako.rb +1 -0
  146. data/sig/kobako/catalog/extensions.rbs +2 -2
  147. data/sig/kobako/catalog/flags.rbs +13 -0
  148. data/sig/kobako/catalog/grants.rbs +13 -0
  149. data/sig/kobako/catalog/mount.rbs +28 -0
  150. data/sig/kobako/catalog/services.rbs +3 -5
  151. data/sig/kobako/catalog/snippets.rbs +5 -5
  152. data/sig/kobako/catalog.rbs +1 -0
  153. data/sig/kobako/codec/ext_types.rbs +10 -8
  154. data/sig/kobako/codec/handle_walk.rbs +9 -7
  155. data/sig/kobako/codec/state.rbs +7 -1
  156. data/sig/kobako/codec/utils.rbs +2 -2
  157. data/sig/kobako/codec/value_budget.rbs +23 -0
  158. data/sig/kobako/codec.rbs +4 -2
  159. data/sig/kobako/constant_name.rbs +3 -0
  160. data/sig/kobako/context.rbs +15 -8
  161. data/sig/kobako/errors.rbs +10 -4
  162. data/sig/kobako/filesystem.rbs +88 -0
  163. data/sig/kobako/guest_yielder.rbs +9 -0
  164. data/sig/kobako/outcome.rbs +6 -8
  165. data/sig/kobako/pool.rbs +1 -1
  166. data/sig/kobako/runtime.rbs +21 -45
  167. data/sig/kobako/sandbox.rbs +11 -1
  168. data/sig/kobako/sandbox_options.rbs +25 -7
  169. data/sig/kobako/snapshot.rbs +20 -0
  170. data/sig/kobako/snippet/bytecode.rbs +12 -0
  171. data/sig/kobako/transport/block_failure.rbs +13 -0
  172. data/sig/kobako/transport/dispatcher.rbs +15 -19
  173. data/sig/kobako/transport/exposure.rbs +1 -1
  174. data/sig/kobako/transport/reflection.rbs +19 -4
  175. data/sig/kobako/transport/run.rbs +1 -3
  176. data/sig/kobako/transport/yielder.rbs +5 -9
  177. data/sig/kobako/transport.rbs +9 -8
  178. metadata +75 -10
  179. data/crates/kobako-transport/src/envelope/invocation_frames.rs +0 -241
  180. data/crates/kobako-wasmtime/src/frames.rs +0 -273
  181. data/lib/kobako/snippet/binary.rb +0 -26
  182. data/rust-toolchain.toml +0 -15
  183. 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
+ }