kobako 0.3.0 → 0.4.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/Cargo.lock +1 -1
- data/README.md +85 -5
- data/data/kobako.wasm +0 -0
- data/ext/kobako/Cargo.toml +1 -1
- data/ext/kobako/src/wasm/cache.rs +12 -4
- data/ext/kobako/src/wasm/dispatch.rs +15 -14
- data/ext/kobako/src/wasm/host_state.rs +111 -5
- data/ext/kobako/src/wasm/instance.rs +135 -33
- data/ext/kobako/src/wasm.rs +1 -0
- data/lib/kobako/codec/decoder.rb +0 -2
- data/lib/kobako/codec/factory.rb +13 -10
- data/lib/kobako/codec/utils.rb +105 -13
- data/lib/kobako/handle.rb +62 -0
- data/lib/kobako/handle_table.rb +119 -0
- data/lib/kobako/invocation.rb +56 -25
- data/lib/kobako/outcome.rb +42 -12
- data/lib/kobako/rpc/dispatcher.rb +22 -20
- data/lib/kobako/rpc/envelope.rb +7 -7
- data/lib/kobako/rpc/fault.rb +1 -1
- data/lib/kobako/rpc/server.rb +12 -24
- data/lib/kobako/rpc/wire_error.rb +23 -0
- data/lib/kobako/sandbox.rb +77 -24
- data/lib/kobako/usage.rb +41 -0
- data/lib/kobako/version.rb +1 -1
- data/lib/kobako.rb +1 -0
- data/sig/kobako/codec/factory.rbs +1 -1
- data/sig/kobako/codec/utils.rbs +10 -0
- data/sig/kobako/handle.rbs +19 -0
- data/sig/kobako/handle_table.rbs +23 -0
- data/sig/kobako/invocation.rbs +3 -1
- data/sig/kobako/outcome.rbs +1 -1
- data/sig/kobako/rpc/dispatcher.rbs +7 -7
- data/sig/kobako/rpc/envelope.rbs +3 -3
- data/sig/kobako/rpc/server.rbs +1 -7
- data/sig/kobako/rpc/wire_error.rbs +6 -0
- data/sig/kobako/sandbox.rbs +7 -1
- data/sig/kobako/usage.rbs +11 -0
- data/sig/kobako/wasm.rbs +2 -0
- metadata +9 -5
- data/lib/kobako/rpc/handle.rb +0 -39
- data/lib/kobako/rpc/handle_table.rb +0 -107
- data/sig/kobako/rpc/handle.rbs +0 -19
- data/sig/kobako/rpc/handle_table.rbs +0 -25
data/lib/kobako/sandbox.rb
CHANGED
|
@@ -4,24 +4,28 @@ require "forwardable"
|
|
|
4
4
|
|
|
5
5
|
require_relative "capture"
|
|
6
6
|
require_relative "errors"
|
|
7
|
+
require_relative "handle_table"
|
|
7
8
|
require_relative "invocation"
|
|
8
9
|
require_relative "outcome"
|
|
9
10
|
require_relative "rpc/server"
|
|
10
11
|
require_relative "rpc/envelope"
|
|
11
12
|
require_relative "sandbox_options"
|
|
12
13
|
require_relative "snippet"
|
|
14
|
+
require_relative "usage"
|
|
13
15
|
|
|
14
16
|
module Kobako
|
|
15
17
|
# Kobako::Sandbox — the user-facing entry point for executing guest mruby
|
|
16
18
|
# scripts inside a wasmtime-hosted Wasm module
|
|
17
19
|
# ({docs/behavior.md B-01}[link:../../docs/behavior.md]).
|
|
18
20
|
#
|
|
19
|
-
# The Sandbox owns the +Kobako::Wasm::Instance+, the per-
|
|
20
|
-
# (
|
|
21
|
-
#
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
-
#
|
|
21
|
+
# The Sandbox owns the +Kobako::Wasm::Instance+, the per-Sandbox
|
|
22
|
+
# +Kobako::HandleTable+ ({docs/behavior.md B-19}[link:../../docs/behavior.md]),
|
|
23
|
+
# the per-instance RPC Server (which receives the HandleTable by
|
|
24
|
+
# injection so guest→host dispatch and host→guest auto-wrap share one
|
|
25
|
+
# allocator), and the per-channel byte caches for guest stdout / stderr
|
|
26
|
+
# capture. The underlying wasmtime Engine and compiled Module are cached
|
|
27
|
+
# at process scope by the native ext and never surface to Ruby —
|
|
28
|
+
# constructing many Sandboxes amortises both costs automatically.
|
|
25
29
|
#
|
|
26
30
|
# Output capture policy ({docs/behavior.md B-04}[link:../../docs/behavior.md]): the
|
|
27
31
|
# per-channel cap (+stdout_limit+ / +stderr_limit+) is enforced inside the
|
|
@@ -72,6 +76,17 @@ module Kobako
|
|
|
72
76
|
@stderr_capture.truncated?
|
|
73
77
|
end
|
|
74
78
|
|
|
79
|
+
# Returns the +Kobako::Usage+ value object for the most recent
|
|
80
|
+
# invocation ({docs/behavior.md B-35}[link:../../docs/behavior.md]).
|
|
81
|
+
# Carries +wall_time+ (Float seconds the guest export call spent
|
|
82
|
+
# inside wasmtime) and +memory_peak+ (Integer bytes, high-water of
|
|
83
|
+
# the per-invocation +memory.grow+ delta past the entry-time
|
|
84
|
+
# baseline). Returns +Kobako::Usage::EMPTY+ before any invocation;
|
|
85
|
+
# populated on every outcome — including +TrapError+ — so the Host
|
|
86
|
+
# App can read it after rescuing a trap to diagnose budget
|
|
87
|
+
# consumption.
|
|
88
|
+
attr_reader :usage
|
|
89
|
+
|
|
75
90
|
# Build a fresh Sandbox.
|
|
76
91
|
#
|
|
77
92
|
# +wasm_path+ is the absolute path to the Guest Binary; defaults to the
|
|
@@ -87,12 +102,13 @@ module Kobako
|
|
|
87
102
|
@wasm_path = wasm_path || Kobako::Wasm.default_path
|
|
88
103
|
@options = SandboxOptions.new(timeout: timeout, memory_limit: memory_limit, stdout_limit: stdout_limit,
|
|
89
104
|
stderr_limit: stderr_limit)
|
|
90
|
-
@
|
|
105
|
+
@handle_table = HandleTable.new
|
|
106
|
+
@services = Kobako::RPC::Server.new(handle_table: @handle_table)
|
|
91
107
|
@snippets = Snippet::Table.new
|
|
92
108
|
@instance = Kobako::Wasm::Instance.from_path(@wasm_path, @options.timeout, @options.memory_limit,
|
|
93
109
|
@options.stdout_limit, @options.stderr_limit)
|
|
94
110
|
@instance.server = @services
|
|
95
|
-
|
|
111
|
+
reset_invocation_state!
|
|
96
112
|
end
|
|
97
113
|
|
|
98
114
|
# Declare or retrieve the Namespace named +name+ on this Sandbox
|
|
@@ -154,7 +170,7 @@ module Kobako
|
|
|
154
170
|
def run(target, *args, **kwargs)
|
|
155
171
|
invocation = Invocation.new(entrypoint: target, args: args, kwargs: kwargs)
|
|
156
172
|
invoke!(:run) do
|
|
157
|
-
@instance.run(@services.encoded_preamble, @snippets.encode, invocation.encode)
|
|
173
|
+
@instance.run(@services.encoded_preamble, @snippets.encode, invocation.encode(@handle_table))
|
|
158
174
|
end
|
|
159
175
|
end
|
|
160
176
|
|
|
@@ -195,28 +211,36 @@ module Kobako
|
|
|
195
211
|
# B-33}[link:../../docs/behavior.md]). Seals the Service / snippet
|
|
196
212
|
# registries on first call (idempotent) and zeros the per-invocation
|
|
197
213
|
# capability state — capture buffers, truncation predicates, and the
|
|
198
|
-
# HandleTable counter — before the guest runs.
|
|
214
|
+
# HandleTable counter — before the guest runs. The HandleTable
|
|
215
|
+
# itself is held as +@handle_table+ and never exposed beyond
|
|
216
|
+
# this class: SPEC.md Terminology pins it as "Not exposed to the
|
|
217
|
+
# Host App" (B-19 / B-20 / E-29).
|
|
199
218
|
def begin_invocation!
|
|
200
219
|
@services.seal!
|
|
201
|
-
@
|
|
202
|
-
|
|
220
|
+
@handle_table.reset!
|
|
221
|
+
reset_invocation_state!
|
|
203
222
|
end
|
|
204
223
|
|
|
205
|
-
# Reset
|
|
206
|
-
#
|
|
207
|
-
# (
|
|
208
|
-
#
|
|
209
|
-
|
|
224
|
+
# Reset all per-invocation observable state to its pre-invocation
|
|
225
|
+
# sentinels — both per-channel captures
|
|
226
|
+
# ({docs/behavior.md B-05}[link:../../docs/behavior.md]) and the
|
|
227
|
+
# per-last-invocation usage record
|
|
228
|
+
# ({docs/behavior.md B-35}[link:../../docs/behavior.md]). Shared by
|
|
229
|
+
# +#initialize+ (first-time setup) and +#begin_invocation!+
|
|
230
|
+
# (between-invocation reset) so both paths agree on what
|
|
231
|
+
# "pre-invocation state" means.
|
|
232
|
+
def reset_invocation_state!
|
|
210
233
|
@stdout_capture = Capture::EMPTY
|
|
211
234
|
@stderr_capture = Capture::EMPTY
|
|
235
|
+
@usage = Usage::EMPTY
|
|
212
236
|
end
|
|
213
237
|
|
|
214
238
|
# Read the per-channel capture pairs (+[bytes, truncated]+) from the
|
|
215
239
|
# ext after an invocation completes and wrap each as a +Capture+ value
|
|
216
240
|
# object. The ext clips +bytes+ to the configured cap and sets
|
|
217
241
|
# +truncated+ when the guest produced strictly more than +cap+ bytes
|
|
218
|
-
# ({docs/behavior.md B-04}[link:../../docs/behavior.md]). Mirror of
|
|
219
|
-
# at the post-invocation boundary.
|
|
242
|
+
# ({docs/behavior.md B-04}[link:../../docs/behavior.md]). Mirror of
|
|
243
|
+
# {#reset_invocation_state!} at the post-invocation boundary.
|
|
220
244
|
def read_captures!
|
|
221
245
|
out_bytes, out_truncated = @instance.stdout
|
|
222
246
|
err_bytes, err_truncated = @instance.stderr
|
|
@@ -224,6 +248,37 @@ module Kobako
|
|
|
224
248
|
@stderr_capture = Capture.from_ext(err_bytes, err_truncated)
|
|
225
249
|
end
|
|
226
250
|
|
|
251
|
+
# Read the per-last-invocation +wall_time+ and +memory_peak+ from
|
|
252
|
+
# the ext and wrap them as a +Kobako::Usage+ value object
|
|
253
|
+
# ({docs/behavior.md B-35}[link:../../docs/behavior.md]). Runs in
|
|
254
|
+
# the +invoke!+ +ensure+ block so the usage record is populated on
|
|
255
|
+
# every outcome — value return, +Kobako::TrapError+ (including
|
|
256
|
+
# +TimeoutError+ / +MemoryLimitError+), +Kobako::SandboxError+,
|
|
257
|
+
# and +Kobako::ServiceError+.
|
|
258
|
+
#
|
|
259
|
+
# The ext returns a positional 2-tuple +[wall_time, memory_peak]+
|
|
260
|
+
# whose order matches the +Kobako::Usage+ field order; the
|
|
261
|
+
# destructure-then-kwargs handoff below is the explicit
|
|
262
|
+
# positional→keyword conversion point, mirroring
|
|
263
|
+
# +#read_captures!+'s +Capture.from_ext(bytes, truncated)+ shape.
|
|
264
|
+
def read_usage!
|
|
265
|
+
wall_time, memory_peak = @instance.usage
|
|
266
|
+
@usage = Usage.new(wall_time: wall_time, memory_peak: memory_peak)
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
# Map a wasmtime trap class to the matching three-layer Ruby
|
|
270
|
+
# exception class. Cap-trap subclasses
|
|
271
|
+
# ({docs/behavior.md E-19 / E-20}[link:../../docs/behavior.md])
|
|
272
|
+
# select their named +TrapError+ subclass; everything else
|
|
273
|
+
# collapses to the base +Kobako::TrapError+.
|
|
274
|
+
def trap_class_for(err)
|
|
275
|
+
case err
|
|
276
|
+
when Kobako::Wasm::TimeoutError then TimeoutError
|
|
277
|
+
when Kobako::Wasm::MemoryLimitError then MemoryLimitError
|
|
278
|
+
else TrapError
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
|
|
227
282
|
# Shared prologue / epilogue + trap-class translator for both
|
|
228
283
|
# invocation verbs. +verb+ is +:eval+ or +:run+; it tags the
|
|
229
284
|
# TrapError message so the failing export is identifiable. The
|
|
@@ -239,12 +294,10 @@ module Kobako
|
|
|
239
294
|
yield
|
|
240
295
|
read_captures!
|
|
241
296
|
Outcome.decode(@instance.outcome!)
|
|
242
|
-
rescue Kobako::Wasm::TimeoutError => e
|
|
243
|
-
raise TimeoutError, "guest exceeded timeout: #{e.message}"
|
|
244
|
-
rescue Kobako::Wasm::MemoryLimitError => e
|
|
245
|
-
raise MemoryLimitError, "guest exceeded memory_limit: #{e.message}"
|
|
246
297
|
rescue Kobako::Wasm::Error => e
|
|
247
|
-
raise
|
|
298
|
+
raise trap_class_for(e), "Sandbox##{verb} failed: #{e.message}"
|
|
299
|
+
ensure
|
|
300
|
+
read_usage!
|
|
248
301
|
end
|
|
249
302
|
end
|
|
250
303
|
end
|
data/lib/kobako/usage.rb
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Kobako
|
|
4
|
+
# Per-last-invocation resource accounting for a +Kobako::Sandbox+
|
|
5
|
+
# ({docs/behavior.md B-35}[link:../../docs/behavior.md]). Carries two
|
|
6
|
+
# readers populated by every +#eval+ / +#run+ invocation:
|
|
7
|
+
#
|
|
8
|
+
# * +wall_time+ — the Float number of seconds the guest export call
|
|
9
|
+
# spent inside wasmtime during the most recent invocation. The
|
|
10
|
+
# measurement bracket aligns with the +timeout+ deadline
|
|
11
|
+
# ({docs/behavior.md B-01}[link:../../docs/behavior.md]); time spent
|
|
12
|
+
# in host Service callbacks is included, but everything that runs
|
|
13
|
+
# after the guest export returns — the post-export
|
|
14
|
+
# +OUTCOME_BUFFER+ fetch and decode, plus stdout / stderr capture
|
|
15
|
+
# readout — is excluded.
|
|
16
|
+
# * +memory_peak+ — the Integer high-water mark, in bytes, of the
|
|
17
|
+
# per-invocation +memory.grow+ delta past the linear-memory size
|
|
18
|
+
# captured at invocation entry. Same baseline accounting as
|
|
19
|
+
# +memory_limit+ ({docs/behavior.md E-20}[link:../../docs/behavior.md]):
|
|
20
|
+
# the mruby image's initial allocation and any prior-invocation
|
|
21
|
+
# watermark sit outside the measurement. On +MemoryLimitError+
|
|
22
|
+
# +memory_peak+ never exceeds the configured cap because the
|
|
23
|
+
# rejected +desired+ value is not promoted into the high-water.
|
|
24
|
+
#
|
|
25
|
+
# Both readers are populated on every outcome, including +TrapError+
|
|
26
|
+
# branches, so the Host App can read +Sandbox#usage+ after rescuing a
|
|
27
|
+
# trap to diagnose how much of the budget the failing invocation
|
|
28
|
+
# consumed. Before the first invocation +Sandbox#usage+ returns the
|
|
29
|
+
# pre-invocation sentinel +Kobako::Usage::EMPTY+.
|
|
30
|
+
#
|
|
31
|
+
# Built on the +class X < Data.define(...)+ subclass form so the
|
|
32
|
+
# class body is fully Steep-visible; ruby/rbs upstream documents this
|
|
33
|
+
# as the Steep-friendly shape and the +Style/DataInheritance+ cop is
|
|
34
|
+
# disabled on that basis (see +.rubocop.yml+).
|
|
35
|
+
class Usage < Data.define(:wall_time, :memory_peak)
|
|
36
|
+
# Pre-invocation sentinel ({docs/behavior.md B-35}[link:../../docs/behavior.md]).
|
|
37
|
+
# Reused by +Sandbox+ before any invocation has run so callers do not
|
|
38
|
+
# need to handle a +nil+ +#usage+.
|
|
39
|
+
EMPTY = new(wall_time: 0.0, memory_peak: 0)
|
|
40
|
+
end
|
|
41
|
+
end
|
data/lib/kobako/version.rb
CHANGED
data/lib/kobako.rb
CHANGED
|
@@ -4,6 +4,7 @@ require_relative "kobako/version"
|
|
|
4
4
|
require "kobako/kobako"
|
|
5
5
|
require_relative "kobako/errors"
|
|
6
6
|
require_relative "kobako/rpc"
|
|
7
|
+
require_relative "kobako/rpc/wire_error"
|
|
7
8
|
require_relative "kobako/rpc/server"
|
|
8
9
|
require_relative "kobako/wasm"
|
|
9
10
|
require_relative "kobako/sandbox"
|
|
@@ -23,7 +23,7 @@ module Kobako
|
|
|
23
23
|
def unpack_symbol: (String payload) -> Symbol
|
|
24
24
|
def register_handle: () -> void
|
|
25
25
|
def register_fault: () -> void
|
|
26
|
-
def unpack_handle: (String payload) -> Kobako::
|
|
26
|
+
def unpack_handle: (String payload) -> Kobako::Handle
|
|
27
27
|
def pack_fault: (Kobako::RPC::Fault fault) -> String
|
|
28
28
|
def unpack_fault: (String payload) -> Kobako::RPC::Fault
|
|
29
29
|
end
|
data/sig/kobako/codec/utils.rbs
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
module Kobako
|
|
2
2
|
module Codec
|
|
3
3
|
module Utils
|
|
4
|
+
MSGPACK_INT_RANGE: Range[Integer]
|
|
5
|
+
|
|
4
6
|
def self?.assert_utf8!: (String string, String label) -> void
|
|
5
7
|
|
|
6
8
|
def self?.wire_boundary: [T] () { () -> T } -> T
|
|
9
|
+
|
|
10
|
+
def self?.wire_representable?: (untyped value) -> bool
|
|
11
|
+
|
|
12
|
+
def self?.deep_wrap: (untyped value, Kobako::HandleTable handle_table) -> untyped
|
|
13
|
+
|
|
14
|
+
def self?.primitive_wire_type?: (untyped value) -> bool
|
|
15
|
+
|
|
16
|
+
def self?.container_wire_representable?: (untyped value) -> bool
|
|
7
17
|
end
|
|
8
18
|
end
|
|
9
19
|
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Kobako
|
|
2
|
+
class Handle
|
|
3
|
+
MIN_ID: Integer
|
|
4
|
+
MAX_ID: Integer
|
|
5
|
+
|
|
6
|
+
attr_reader id: Integer
|
|
7
|
+
|
|
8
|
+
def initialize: (Integer id) -> void
|
|
9
|
+
| (id: Integer) -> void
|
|
10
|
+
|
|
11
|
+
def self.from_wire: (Integer id) -> Handle
|
|
12
|
+
|
|
13
|
+
def with: (?id: Integer) -> Handle
|
|
14
|
+
|
|
15
|
+
def ==: (untyped other) -> bool
|
|
16
|
+
|
|
17
|
+
def hash: () -> Integer
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Kobako
|
|
2
|
+
class HandleTable
|
|
3
|
+
def initialize: (?next_id: Integer) -> void
|
|
4
|
+
|
|
5
|
+
def alloc: (untyped object) -> Kobako::Handle
|
|
6
|
+
|
|
7
|
+
def fetch: (Integer id) -> untyped
|
|
8
|
+
|
|
9
|
+
def release: (Integer id) -> untyped
|
|
10
|
+
|
|
11
|
+
def reset!: () -> self
|
|
12
|
+
|
|
13
|
+
def mark_disconnected: (Integer id) -> self
|
|
14
|
+
|
|
15
|
+
def size: () -> Integer
|
|
16
|
+
|
|
17
|
+
def include?: (Integer id) -> bool
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def require_bound!: (Integer id) -> void
|
|
22
|
+
end
|
|
23
|
+
end
|
data/sig/kobako/invocation.rbs
CHANGED
|
@@ -10,7 +10,7 @@ module Kobako
|
|
|
10
10
|
|
|
11
11
|
def initialize: (entrypoint: Symbol | String, ?args: Array[untyped], ?kwargs: Hash[untyped, untyped]) -> void
|
|
12
12
|
|
|
13
|
-
def encode: () -> String
|
|
13
|
+
def encode: (Kobako::HandleTable handle_table) -> String
|
|
14
14
|
|
|
15
15
|
private
|
|
16
16
|
|
|
@@ -19,5 +19,7 @@ module Kobako
|
|
|
19
19
|
def validate_args!: (Array[untyped] args) -> Array[untyped]
|
|
20
20
|
|
|
21
21
|
def validate_kwargs!: (Hash[untyped, untyped] kwargs) -> Hash[Symbol, untyped]
|
|
22
|
+
|
|
23
|
+
def forged_handle_message: (String slot) -> String
|
|
22
24
|
end
|
|
23
25
|
end
|
data/sig/kobako/outcome.rbs
CHANGED
|
@@ -19,6 +19,6 @@ module Kobako
|
|
|
19
19
|
|
|
20
20
|
def self?.panic_target_class: (Panic panic) -> (singleton(SandboxError) | singleton(ServiceError))
|
|
21
21
|
|
|
22
|
-
def self?.build_wire_violation_error: (String message) ->
|
|
22
|
+
def self?.build_wire_violation_error: (String message, ?wire_error: String?) -> RPC::WireError
|
|
23
23
|
end
|
|
24
24
|
end
|
|
@@ -7,25 +7,25 @@ module Kobako
|
|
|
7
7
|
class DisconnectedTargetError < StandardError
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
def self?.dispatch: (String request_bytes, Server server) -> String
|
|
10
|
+
def self?.dispatch: (String request_bytes, Server server, Kobako::HandleTable handle_table) -> String
|
|
11
11
|
|
|
12
12
|
def self?.encode_caught_error: (StandardError error) -> String
|
|
13
13
|
|
|
14
14
|
def self?.invoke: (untyped target, String method, Array[untyped] args, Hash[Symbol, untyped] kwargs) -> untyped
|
|
15
15
|
|
|
16
|
-
def self?.resolve_arg: (untyped value, HandleTable handle_table) -> untyped
|
|
16
|
+
def self?.resolve_arg: (untyped value, Kobako::HandleTable handle_table) -> untyped
|
|
17
17
|
|
|
18
|
-
def self?.resolve_target: (String | Kobako::
|
|
18
|
+
def self?.resolve_target: (String | Kobako::Handle target, Server server, Kobako::HandleTable handle_table) -> untyped
|
|
19
19
|
|
|
20
20
|
def self?.resolve_path: (String path, Server server) -> untyped
|
|
21
21
|
|
|
22
|
-
def self?.resolve_handle: (Kobako::
|
|
22
|
+
def self?.resolve_handle: (Kobako::Handle handle, Kobako::HandleTable handle_table) -> untyped
|
|
23
23
|
|
|
24
|
-
def self?.require_live_object!: (Integer id, HandleTable handle_table) -> untyped
|
|
24
|
+
def self?.require_live_object!: (Integer id, Kobako::HandleTable handle_table) -> untyped
|
|
25
25
|
|
|
26
|
-
def self?.encode_ok: (untyped value,
|
|
26
|
+
def self?.encode_ok: (untyped value, Kobako::HandleTable handle_table) -> String
|
|
27
27
|
|
|
28
|
-
def self?.wrap_as_handle: (untyped value,
|
|
28
|
+
def self?.wrap_as_handle: (untyped value, Kobako::HandleTable handle_table) -> Kobako::Handle
|
|
29
29
|
|
|
30
30
|
def self?.encode_error: (String type, String message) -> String
|
|
31
31
|
end
|
data/sig/kobako/rpc/envelope.rbs
CHANGED
|
@@ -4,14 +4,14 @@ module Kobako
|
|
|
4
4
|
STATUS_ERROR: Integer
|
|
5
5
|
|
|
6
6
|
class Request
|
|
7
|
-
attr_reader target: String | Kobako::
|
|
7
|
+
attr_reader target: String | Kobako::Handle
|
|
8
8
|
attr_reader method_name: String
|
|
9
9
|
attr_reader args: Array[untyped]
|
|
10
10
|
attr_reader kwargs: Hash[Symbol, untyped]
|
|
11
11
|
|
|
12
|
-
def initialize: (target: String | Kobako::
|
|
12
|
+
def initialize: (target: String | Kobako::Handle, method: String, ?args: Array[untyped], ?kwargs: Hash[Symbol, untyped]) -> void
|
|
13
13
|
|
|
14
|
-
def with: (?target: String | Kobako::
|
|
14
|
+
def with: (?target: String | Kobako::Handle, ?method: String, ?args: Array[untyped], ?kwargs: Hash[Symbol, untyped]) -> Request
|
|
15
15
|
|
|
16
16
|
def ==: (untyped other) -> bool
|
|
17
17
|
|
data/sig/kobako/rpc/server.rbs
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
module Kobako
|
|
2
2
|
module RPC
|
|
3
3
|
class Server
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def initialize: (?handle_table: HandleTable) -> void
|
|
4
|
+
def initialize: (?handle_table: Kobako::HandleTable) -> void
|
|
7
5
|
|
|
8
6
|
def define: (Symbol | String name) -> Kobako::RPC::Namespace
|
|
9
7
|
|
|
@@ -11,8 +9,6 @@ module Kobako
|
|
|
11
9
|
|
|
12
10
|
def bound?: (String target) -> bool
|
|
13
11
|
|
|
14
|
-
def namespaces: () -> Array[Kobako::RPC::Namespace]
|
|
15
|
-
|
|
16
12
|
def size: () -> Integer
|
|
17
13
|
|
|
18
14
|
def empty?: () -> bool
|
|
@@ -25,8 +21,6 @@ module Kobako
|
|
|
25
21
|
|
|
26
22
|
def sealed?: () -> bool
|
|
27
23
|
|
|
28
|
-
def reset_handles!: () -> HandleTable
|
|
29
|
-
|
|
30
24
|
def dispatch: (String request_bytes) -> String
|
|
31
25
|
|
|
32
26
|
private
|
data/sig/kobako/sandbox.rbs
CHANGED
|
@@ -30,6 +30,8 @@ module Kobako
|
|
|
30
30
|
|
|
31
31
|
def stderr_truncated?: () -> bool
|
|
32
32
|
|
|
33
|
+
attr_reader usage: Kobako::Usage
|
|
34
|
+
|
|
33
35
|
def define: (Symbol | String name) -> Kobako::RPC::Namespace
|
|
34
36
|
|
|
35
37
|
def preload: (code: String, name: Symbol | String) -> Kobako::Sandbox
|
|
@@ -41,12 +43,16 @@ module Kobako
|
|
|
41
43
|
|
|
42
44
|
private
|
|
43
45
|
|
|
44
|
-
def
|
|
46
|
+
def reset_invocation_state!: () -> void
|
|
45
47
|
|
|
46
48
|
def begin_invocation!: () -> void
|
|
47
49
|
|
|
48
50
|
def read_captures!: () -> void
|
|
49
51
|
|
|
52
|
+
def read_usage!: () -> void
|
|
53
|
+
|
|
54
|
+
def trap_class_for: (Kobako::Wasm::Error err) -> singleton(Kobako::TrapError)
|
|
55
|
+
|
|
50
56
|
def invoke!: (Symbol verb) { () -> void } -> untyped
|
|
51
57
|
end
|
|
52
58
|
end
|
data/sig/kobako/wasm.rbs
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kobako
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Aotokitsuruya
|
|
@@ -69,6 +69,8 @@ files:
|
|
|
69
69
|
- lib/kobako/codec/factory.rb
|
|
70
70
|
- lib/kobako/codec/utils.rb
|
|
71
71
|
- lib/kobako/errors.rb
|
|
72
|
+
- lib/kobako/handle.rb
|
|
73
|
+
- lib/kobako/handle_table.rb
|
|
72
74
|
- lib/kobako/invocation.rb
|
|
73
75
|
- lib/kobako/outcome.rb
|
|
74
76
|
- lib/kobako/outcome/panic.rb
|
|
@@ -76,16 +78,16 @@ files:
|
|
|
76
78
|
- lib/kobako/rpc/dispatcher.rb
|
|
77
79
|
- lib/kobako/rpc/envelope.rb
|
|
78
80
|
- lib/kobako/rpc/fault.rb
|
|
79
|
-
- lib/kobako/rpc/handle.rb
|
|
80
|
-
- lib/kobako/rpc/handle_table.rb
|
|
81
81
|
- lib/kobako/rpc/namespace.rb
|
|
82
82
|
- lib/kobako/rpc/server.rb
|
|
83
|
+
- lib/kobako/rpc/wire_error.rb
|
|
83
84
|
- lib/kobako/sandbox.rb
|
|
84
85
|
- lib/kobako/sandbox_options.rb
|
|
85
86
|
- lib/kobako/snippet.rb
|
|
86
87
|
- lib/kobako/snippet/binary.rb
|
|
87
88
|
- lib/kobako/snippet/source.rb
|
|
88
89
|
- lib/kobako/snippet/table.rb
|
|
90
|
+
- lib/kobako/usage.rb
|
|
89
91
|
- lib/kobako/version.rb
|
|
90
92
|
- lib/kobako/wasm.rb
|
|
91
93
|
- sig/kobako.rbs
|
|
@@ -96,6 +98,8 @@ files:
|
|
|
96
98
|
- sig/kobako/codec/factory.rbs
|
|
97
99
|
- sig/kobako/codec/utils.rbs
|
|
98
100
|
- sig/kobako/errors.rbs
|
|
101
|
+
- sig/kobako/handle.rbs
|
|
102
|
+
- sig/kobako/handle_table.rbs
|
|
99
103
|
- sig/kobako/invocation.rbs
|
|
100
104
|
- sig/kobako/outcome.rbs
|
|
101
105
|
- sig/kobako/outcome/panic.rbs
|
|
@@ -103,16 +107,16 @@ files:
|
|
|
103
107
|
- sig/kobako/rpc/dispatcher.rbs
|
|
104
108
|
- sig/kobako/rpc/envelope.rbs
|
|
105
109
|
- sig/kobako/rpc/fault.rbs
|
|
106
|
-
- sig/kobako/rpc/handle.rbs
|
|
107
|
-
- sig/kobako/rpc/handle_table.rbs
|
|
108
110
|
- sig/kobako/rpc/namespace.rbs
|
|
109
111
|
- sig/kobako/rpc/server.rbs
|
|
112
|
+
- sig/kobako/rpc/wire_error.rbs
|
|
110
113
|
- sig/kobako/sandbox.rbs
|
|
111
114
|
- sig/kobako/sandbox_options.rbs
|
|
112
115
|
- sig/kobako/snippet.rbs
|
|
113
116
|
- sig/kobako/snippet/binary.rbs
|
|
114
117
|
- sig/kobako/snippet/source.rbs
|
|
115
118
|
- sig/kobako/snippet/table.rbs
|
|
119
|
+
- sig/kobako/usage.rbs
|
|
116
120
|
- sig/kobako/wasm.rbs
|
|
117
121
|
homepage: https://github.com/elct9620/kobako
|
|
118
122
|
licenses:
|
data/lib/kobako/rpc/handle.rb
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Kobako
|
|
4
|
-
module RPC
|
|
5
|
-
# Wire-level value object for an ext-0x01 Capability Handle.
|
|
6
|
-
#
|
|
7
|
-
# SPEC pins the binary layout to fixext 4 with a 4-byte big-endian u32
|
|
8
|
-
# payload ({docs/wire-codec.md}[link:../../../docs/wire-codec.md]
|
|
9
|
-
# § Ext Types → ext 0x01). ID 0 is reserved as the invalid sentinel;
|
|
10
|
-
# the maximum valid ID is 0x7fff_ffff (2^31 - 1).
|
|
11
|
-
#
|
|
12
|
-
# This is intentionally a thin value object built on +Data.define+ so
|
|
13
|
-
# equality, hash, and immutability are inherited. The runtime-facing
|
|
14
|
-
# +Kobako::RPC::Handle+ class lives at a higher layer and may add behaviour
|
|
15
|
-
# (HandleTable bookkeeping, reset semantics). The codec only needs to
|
|
16
|
-
# carry the opaque integer ID across the wire.
|
|
17
|
-
Handle = Data.define(:id) do
|
|
18
|
-
# +MIN_ID+ / +MAX_ID+ live on the Handle class (defined below this
|
|
19
|
-
# block), not in this block's binding — Data.define's block scope
|
|
20
|
-
# resolves bare constants against the enclosing +Wire+ module, so
|
|
21
|
-
# +MIN_ID+ would raise +NameError+. Use +self.class::CONST+ to
|
|
22
|
-
# reach the constants attached to the Handle class itself. Do not
|
|
23
|
-
# "simplify" this back to bare +MIN_ID+/+MAX_ID+.
|
|
24
|
-
# steep:ignore:start
|
|
25
|
-
def initialize(id:)
|
|
26
|
-
min = self.class::MIN_ID
|
|
27
|
-
max = self.class::MAX_ID
|
|
28
|
-
raise ArgumentError, "Handle id must be Integer" unless id.is_a?(Integer)
|
|
29
|
-
raise ArgumentError, "Handle id #{id} out of range [#{min}, #{max}]" unless id.between?(min, max)
|
|
30
|
-
|
|
31
|
-
super
|
|
32
|
-
end
|
|
33
|
-
# steep:ignore:end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
Handle::MIN_ID = 1
|
|
37
|
-
Handle::MAX_ID = 0x7fff_ffff
|
|
38
|
-
end
|
|
39
|
-
end
|