kobako 0.2.1 → 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 +205 -59
- data/data/kobako.wasm +0 -0
- data/ext/kobako/Cargo.toml +2 -2
- data/ext/kobako/src/wasm/cache.rs +15 -7
- data/ext/kobako/src/wasm/dispatch.rs +88 -36
- data/ext/kobako/src/wasm/host_state.rs +298 -55
- data/ext/kobako/src/wasm/instance.rs +477 -160
- data/ext/kobako/src/wasm.rs +20 -5
- data/lib/kobako/capture.rb +12 -10
- data/lib/kobako/codec/decoder.rb +3 -4
- data/lib/kobako/codec/encoder.rb +1 -1
- data/lib/kobako/codec/error.rb +3 -2
- data/lib/kobako/codec/factory.rb +24 -17
- data/lib/kobako/codec/utils.rb +105 -12
- data/lib/kobako/codec.rb +2 -1
- data/lib/kobako/errors.rb +22 -10
- data/lib/kobako/handle.rb +62 -0
- data/lib/kobako/handle_table.rb +119 -0
- data/lib/kobako/invocation.rb +143 -0
- data/lib/kobako/outcome/panic.rb +2 -2
- data/lib/kobako/outcome.rb +61 -24
- data/lib/kobako/rpc/dispatcher.rb +30 -28
- data/lib/kobako/rpc/envelope.rb +10 -10
- data/lib/kobako/rpc/fault.rb +4 -3
- data/lib/kobako/rpc/namespace.rb +3 -3
- data/lib/kobako/rpc/server.rb +23 -33
- data/lib/kobako/rpc/wire_error.rb +23 -0
- data/lib/kobako/sandbox.rb +211 -136
- data/lib/kobako/sandbox_options.rb +73 -0
- data/lib/kobako/snippet/binary.rb +30 -0
- data/lib/kobako/snippet/source.rb +28 -0
- data/lib/kobako/snippet/table.rb +174 -0
- data/lib/kobako/snippet.rb +20 -0
- 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/errors.rbs +3 -0
- data/sig/kobako/handle.rbs +19 -0
- data/sig/kobako/handle_table.rbs +23 -0
- data/sig/kobako/invocation.rbs +25 -0
- 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 +22 -17
- data/sig/kobako/sandbox_options.rbs +32 -0
- data/sig/kobako/snippet/binary.rbs +12 -0
- data/sig/kobako/snippet/source.rbs +13 -0
- data/sig/kobako/snippet/table.rbs +36 -0
- data/sig/kobako/snippet.rbs +4 -0
- data/sig/kobako/usage.rbs +11 -0
- data/sig/kobako/wasm.rbs +5 -1
- metadata +21 -5
- data/lib/kobako/rpc/handle.rb +0 -38
- 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
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module Kobako
|
|
2
|
+
class SandboxOptions < Data
|
|
3
|
+
DEFAULT_TIMEOUT_SECONDS: Float
|
|
4
|
+
DEFAULT_MEMORY_LIMIT: Integer
|
|
5
|
+
DEFAULT_OUTPUT_LIMIT: Integer
|
|
6
|
+
|
|
7
|
+
attr_reader timeout: Float?
|
|
8
|
+
attr_reader memory_limit: Integer?
|
|
9
|
+
attr_reader stdout_limit: Integer
|
|
10
|
+
attr_reader stderr_limit: Integer
|
|
11
|
+
|
|
12
|
+
def self.new: (
|
|
13
|
+
?timeout: (Float | Integer)?,
|
|
14
|
+
?memory_limit: Integer?,
|
|
15
|
+
?stdout_limit: Integer?,
|
|
16
|
+
?stderr_limit: Integer?
|
|
17
|
+
) -> SandboxOptions
|
|
18
|
+
|
|
19
|
+
def initialize: (
|
|
20
|
+
?timeout: (Float | Integer)?,
|
|
21
|
+
?memory_limit: Integer?,
|
|
22
|
+
?stdout_limit: Integer?,
|
|
23
|
+
?stderr_limit: Integer?
|
|
24
|
+
) -> void
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def normalize_timeout: ((Float | Integer)? timeout) -> Float?
|
|
29
|
+
|
|
30
|
+
def normalize_memory_limit: (Integer? memory_limit) -> Integer?
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module Kobako
|
|
2
|
+
module Snippet
|
|
3
|
+
class Table
|
|
4
|
+
NAME_PATTERN: Regexp
|
|
5
|
+
|
|
6
|
+
type entry = Kobako::Snippet::Source | Kobako::Snippet::Binary
|
|
7
|
+
|
|
8
|
+
def initialize: () -> void
|
|
9
|
+
|
|
10
|
+
def register: (?code: String?, ?name: (Symbol | String)?, ?binary: String?) -> (Symbol | nil)
|
|
11
|
+
|
|
12
|
+
def encode: () -> String
|
|
13
|
+
|
|
14
|
+
def each: () { (entry) -> void } -> Array[entry]
|
|
15
|
+
| () -> Enumerator[entry, Array[entry]]
|
|
16
|
+
|
|
17
|
+
def names: () -> Array[Symbol]
|
|
18
|
+
|
|
19
|
+
def size: () -> Integer
|
|
20
|
+
|
|
21
|
+
def empty?: () -> bool
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def register_source!: (String? code, (Symbol | String)? name) -> Symbol
|
|
26
|
+
|
|
27
|
+
def ensure_source_args!: (String? code, (Symbol | String)? name) -> [String, Symbol | String]
|
|
28
|
+
|
|
29
|
+
def register_binary!: (String bytes) -> nil
|
|
30
|
+
|
|
31
|
+
def entry_payload: (entry) -> Hash[String, untyped]
|
|
32
|
+
|
|
33
|
+
def normalize_name: (Symbol | String name) -> Symbol
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
data/sig/kobako/wasm.rbs
CHANGED
|
@@ -25,13 +25,17 @@ module Kobako
|
|
|
25
25
|
|
|
26
26
|
def server=: (Kobako::RPC::Server server) -> void
|
|
27
27
|
|
|
28
|
-
def
|
|
28
|
+
def eval: (String preamble, String source, String snippets) -> void
|
|
29
|
+
|
|
30
|
+
def run: (String preamble, String snippets, String envelope) -> void
|
|
29
31
|
|
|
30
32
|
def stdout: () -> [String, bool]
|
|
31
33
|
|
|
32
34
|
def stderr: () -> [String, bool]
|
|
33
35
|
|
|
34
36
|
def outcome!: () -> String
|
|
37
|
+
|
|
38
|
+
def usage: () -> [Float, Integer]
|
|
35
39
|
end
|
|
36
40
|
end
|
|
37
41
|
end
|
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,17 +69,25 @@ 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
|
|
74
|
+
- lib/kobako/invocation.rb
|
|
72
75
|
- lib/kobako/outcome.rb
|
|
73
76
|
- lib/kobako/outcome/panic.rb
|
|
74
77
|
- lib/kobako/rpc.rb
|
|
75
78
|
- lib/kobako/rpc/dispatcher.rb
|
|
76
79
|
- lib/kobako/rpc/envelope.rb
|
|
77
80
|
- lib/kobako/rpc/fault.rb
|
|
78
|
-
- lib/kobako/rpc/handle.rb
|
|
79
|
-
- lib/kobako/rpc/handle_table.rb
|
|
80
81
|
- lib/kobako/rpc/namespace.rb
|
|
81
82
|
- lib/kobako/rpc/server.rb
|
|
83
|
+
- lib/kobako/rpc/wire_error.rb
|
|
82
84
|
- lib/kobako/sandbox.rb
|
|
85
|
+
- lib/kobako/sandbox_options.rb
|
|
86
|
+
- lib/kobako/snippet.rb
|
|
87
|
+
- lib/kobako/snippet/binary.rb
|
|
88
|
+
- lib/kobako/snippet/source.rb
|
|
89
|
+
- lib/kobako/snippet/table.rb
|
|
90
|
+
- lib/kobako/usage.rb
|
|
83
91
|
- lib/kobako/version.rb
|
|
84
92
|
- lib/kobako/wasm.rb
|
|
85
93
|
- sig/kobako.rbs
|
|
@@ -90,17 +98,25 @@ files:
|
|
|
90
98
|
- sig/kobako/codec/factory.rbs
|
|
91
99
|
- sig/kobako/codec/utils.rbs
|
|
92
100
|
- sig/kobako/errors.rbs
|
|
101
|
+
- sig/kobako/handle.rbs
|
|
102
|
+
- sig/kobako/handle_table.rbs
|
|
103
|
+
- sig/kobako/invocation.rbs
|
|
93
104
|
- sig/kobako/outcome.rbs
|
|
94
105
|
- sig/kobako/outcome/panic.rbs
|
|
95
106
|
- sig/kobako/rpc.rbs
|
|
96
107
|
- sig/kobako/rpc/dispatcher.rbs
|
|
97
108
|
- sig/kobako/rpc/envelope.rbs
|
|
98
109
|
- sig/kobako/rpc/fault.rbs
|
|
99
|
-
- sig/kobako/rpc/handle.rbs
|
|
100
|
-
- sig/kobako/rpc/handle_table.rbs
|
|
101
110
|
- sig/kobako/rpc/namespace.rbs
|
|
102
111
|
- sig/kobako/rpc/server.rbs
|
|
112
|
+
- sig/kobako/rpc/wire_error.rbs
|
|
103
113
|
- sig/kobako/sandbox.rbs
|
|
114
|
+
- sig/kobako/sandbox_options.rbs
|
|
115
|
+
- sig/kobako/snippet.rbs
|
|
116
|
+
- sig/kobako/snippet/binary.rbs
|
|
117
|
+
- sig/kobako/snippet/source.rbs
|
|
118
|
+
- sig/kobako/snippet/table.rbs
|
|
119
|
+
- sig/kobako/usage.rbs
|
|
104
120
|
- sig/kobako/wasm.rbs
|
|
105
121
|
homepage: https://github.com/elct9620/kobako
|
|
106
122
|
licenses:
|
data/lib/kobako/rpc/handle.rb
DELETED
|
@@ -1,38 +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 (Wire Codec → Ext Types → ext 0x01). ID 0 is reserved as the
|
|
9
|
-
# invalid sentinel; the maximum valid ID is 0x7fff_ffff (2^31 - 1).
|
|
10
|
-
#
|
|
11
|
-
# This is intentionally a thin value object built on +Data.define+ so
|
|
12
|
-
# equality, hash, and immutability are inherited. The runtime-facing
|
|
13
|
-
# +Kobako::RPC::Handle+ class lives at a higher layer and may add behaviour
|
|
14
|
-
# (HandleTable bookkeeping, reset semantics). The codec only needs to
|
|
15
|
-
# carry the opaque integer ID across the wire.
|
|
16
|
-
Handle = Data.define(:id) do
|
|
17
|
-
# +MIN_ID+ / +MAX_ID+ live on the Handle class (defined below this
|
|
18
|
-
# block), not in this block's binding — Data.define's block scope
|
|
19
|
-
# resolves bare constants against the enclosing +Wire+ module, so
|
|
20
|
-
# +MIN_ID+ would raise +NameError+. Use +self.class::CONST+ to
|
|
21
|
-
# reach the constants attached to the Handle class itself. Do not
|
|
22
|
-
# "simplify" this back to bare +MIN_ID+/+MAX_ID+.
|
|
23
|
-
# steep:ignore:start
|
|
24
|
-
def initialize(id:)
|
|
25
|
-
min = self.class::MIN_ID
|
|
26
|
-
max = self.class::MAX_ID
|
|
27
|
-
raise ArgumentError, "Handle id must be Integer" unless id.is_a?(Integer)
|
|
28
|
-
raise ArgumentError, "Handle id #{id} out of range [#{min}, #{max}]" unless id.between?(min, max)
|
|
29
|
-
|
|
30
|
-
super
|
|
31
|
-
end
|
|
32
|
-
# steep:ignore:end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
Handle::MIN_ID = 1
|
|
36
|
-
Handle::MAX_ID = 0x7fff_ffff
|
|
37
|
-
end
|
|
38
|
-
end
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "handle"
|
|
4
|
-
|
|
5
|
-
module Kobako
|
|
6
|
-
module RPC
|
|
7
|
-
# Host-side mapping from opaque integer Handle IDs to Ruby objects
|
|
8
|
-
# (capability proxies). One table is owned per +Kobako::RPC::Server+
|
|
9
|
-
# instance (and therefore per +Kobako::Sandbox+ instance). See
|
|
10
|
-
# {SPEC.md B-15}[link:../../../SPEC.md].
|
|
11
|
-
#
|
|
12
|
-
# Lifecycle invariants ({SPEC.md}[link:../../../SPEC.md]):
|
|
13
|
-
#
|
|
14
|
-
# - {SPEC.md B-15}[link:../../../SPEC.md] — Handle IDs are allocated by
|
|
15
|
-
# a monotonically increasing counter scoped to a single `#run`. The
|
|
16
|
-
# first ID issued in a run is 1; ID 0 is reserved as the invalid
|
|
17
|
-
# sentinel and is never returned by #alloc.
|
|
18
|
-
#
|
|
19
|
-
# - {SPEC.md B-19}[link:../../../SPEC.md] — When between `#run`
|
|
20
|
-
# invocations (via `#reset!`), every Handle issued under the old state
|
|
21
|
-
# becomes invalid.
|
|
22
|
-
#
|
|
23
|
-
# - {SPEC.md B-21}[link:../../../SPEC.md] — The cap is `0x7fff_ffff`
|
|
24
|
-
# (2³¹ − 1). Allocation beyond the cap raises immediately — no silent
|
|
25
|
-
# truncation, no wrap, no ID reuse.
|
|
26
|
-
class HandleTable
|
|
27
|
-
# Build a fresh, empty HandleTable. +next_id+ is an internal seam that
|
|
28
|
-
# sets the starting value of the monotonic counter (defaults to 1 per
|
|
29
|
-
# B-15); tests pass a value near +RPC::Handle::MAX_ID+ to exercise
|
|
30
|
-
# the cap-exhaustion path without 2³¹ allocations.
|
|
31
|
-
def initialize(next_id: 1)
|
|
32
|
-
@entries = {} # : Hash[Integer, untyped]
|
|
33
|
-
@next_id = next_id
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# Bind +object+ in the table and return its newly-allocated Handle ID.
|
|
37
|
-
# +object+ is any host-side Ruby object to bind. Returns a freshly-
|
|
38
|
-
# allocated Handle ID in +[1, RPC::Handle::MAX_ID]+. Raises
|
|
39
|
-
# +Kobako::HandleTableExhausted+ if the next ID would exceed the cap.
|
|
40
|
-
# The cap is anchored on +RPC::Handle+ — the wire codec and the
|
|
41
|
-
# allocator share the same invariant ({SPEC.md B-21}[link:../../../SPEC.md]).
|
|
42
|
-
def alloc(object)
|
|
43
|
-
id = @next_id
|
|
44
|
-
cap = RPC::Handle::MAX_ID
|
|
45
|
-
raise HandleTableExhausted, "HandleTable exhausted: id #{id} exceeds MAX_ID #{cap}" if id > cap
|
|
46
|
-
|
|
47
|
-
@entries[id] = object
|
|
48
|
-
@next_id = id + 1
|
|
49
|
-
id
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
# Resolve a Handle ID to its bound object. +id+ is a Handle ID previously
|
|
53
|
-
# returned by +#alloc+. Returns the bound object. Raises
|
|
54
|
-
# +Kobako::HandleTableError+ if +id+ is not currently bound.
|
|
55
|
-
def fetch(id)
|
|
56
|
-
require_bound!(id)
|
|
57
|
-
@entries[id]
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
# Remove and return the binding for +id+. +id+ is the Handle ID to
|
|
61
|
-
# release. Returns the previously-bound object. Raises
|
|
62
|
-
# +Kobako::HandleTableError+ if +id+ is not currently bound.
|
|
63
|
-
def release(id)
|
|
64
|
-
require_bound!(id)
|
|
65
|
-
@entries.delete(id)
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
# Clear all entries AND reset the counter to 1. Called at the per-run
|
|
69
|
-
# boundary — see {SPEC.md B-19}[link:../../../SPEC.md].
|
|
70
|
-
# Returns +self+.
|
|
71
|
-
def reset!
|
|
72
|
-
@entries.clear
|
|
73
|
-
@next_id = 1
|
|
74
|
-
self
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
# Mark the entry at +id+ as disconnected (ABA protection). +id+ is the
|
|
78
|
-
# Handle ID to poison; silently ignored if +id+ is not currently bound.
|
|
79
|
-
# Returns +self+ for chainability, matching the convention of +#reset!+.
|
|
80
|
-
def mark_disconnected(id)
|
|
81
|
-
@entries[id] = :disconnected if @entries.key?(id)
|
|
82
|
-
self
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
# Returns the number of currently-bound entries.
|
|
86
|
-
def size
|
|
87
|
-
@entries.size
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
# Returns +true+ when +id+ is currently bound, +false+ otherwise.
|
|
91
|
-
def include?(id)
|
|
92
|
-
@entries.key?(id)
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
private
|
|
96
|
-
|
|
97
|
-
# Single source of truth for the "unknown Handle id" raise shared by
|
|
98
|
-
# {#fetch} and {#release}. Returns +nil+ on success; raises
|
|
99
|
-
# +Kobako::HandleTableError+ when +id+ is not currently bound.
|
|
100
|
-
def require_bound!(id)
|
|
101
|
-
return if @entries.key?(id)
|
|
102
|
-
|
|
103
|
-
raise HandleTableError, "unknown Handle id: #{id.inspect}"
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
end
|
data/sig/kobako/rpc/handle.rbs
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
module Kobako
|
|
2
|
-
module RPC
|
|
3
|
-
class Handle
|
|
4
|
-
MIN_ID: Integer
|
|
5
|
-
MAX_ID: Integer
|
|
6
|
-
|
|
7
|
-
attr_reader id: Integer
|
|
8
|
-
|
|
9
|
-
def initialize: (Integer id) -> void
|
|
10
|
-
| (id: Integer) -> void
|
|
11
|
-
|
|
12
|
-
def with: (?id: Integer) -> Handle
|
|
13
|
-
|
|
14
|
-
def ==: (untyped other) -> bool
|
|
15
|
-
|
|
16
|
-
def hash: () -> Integer
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
module Kobako
|
|
2
|
-
module RPC
|
|
3
|
-
class HandleTable
|
|
4
|
-
def initialize: (?next_id: Integer) -> void
|
|
5
|
-
|
|
6
|
-
def alloc: (untyped object) -> Integer
|
|
7
|
-
|
|
8
|
-
def fetch: (Integer id) -> untyped
|
|
9
|
-
|
|
10
|
-
def release: (Integer id) -> untyped
|
|
11
|
-
|
|
12
|
-
def reset!: () -> self
|
|
13
|
-
|
|
14
|
-
def mark_disconnected: (Integer id) -> self
|
|
15
|
-
|
|
16
|
-
def size: () -> Integer
|
|
17
|
-
|
|
18
|
-
def include?: (Integer id) -> bool
|
|
19
|
-
|
|
20
|
-
private
|
|
21
|
-
|
|
22
|
-
def require_bound!: (Integer id) -> void
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|