kobako 0.9.2-aarch64-linux → 0.11.0-aarch64-linux

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.
@@ -9,26 +9,24 @@ module Kobako
9
9
  # consumed by +__kobako_run+.
10
10
  module Transport
11
11
  # Host-side value object for a single +Sandbox#run+ invocation
12
- # ({docs/wire-codec.md Invocation channels}[link:../../../docs/wire-codec.md];
13
- # {docs/behavior.md B-31}[link:../../../docs/behavior.md]).
12
+ # ({docs/wire-codec.md Invocation channels}[link:../../../docs/wire-codec.md]).
14
13
  #
15
14
  # A Run captures the host-layer concept of "a single +#run+
16
15
  # call": the entrypoint constant name plus its positional and keyword
17
- # arguments. Host pre-flight (E-24 / E-25 / E-29 / E-30) is enforced at
18
- # construction so the Value Object is the single source of truth
19
- # anything that passes +Run.new+ is safe to encode and ship to
20
- # the guest.
16
+ # arguments. Host pre-flight (entrypoint type / name pattern, forged
17
+ # Handle, kwargs-key type) is enforced at construction so the Value
18
+ # Object is the single source of truth anything that passes
19
+ # +Run.new+ is safe to encode and ship to the guest.
21
20
  #
22
21
  # Run is the host→guest entrypoint dispatch envelope (the +#run+
23
22
  # request shape), the symmetric counterpart to the guest→host
24
23
  # +Request+ envelope. +#encode+ takes the Sandbox's
25
24
  # +Catalog::Handles+ and routes any non-wire-representable +args+ /
26
- # +kwargs+ leaf through it as a +Kobako::Handle+
27
- # ({docs/behavior.md B-34}[link:../../../docs/behavior.md]) — the
25
+ # +kwargs+ leaf through it as a +Kobako::Handle+ — the
28
26
  # symmetric counterpart of the guest→host wrap path in the
29
- # dispatcher (B-14). A +Kobako::Handle+ that arrives **already
27
+ # dispatcher. A +Kobako::Handle+ that arrives **already
30
28
  # constructed** in the caller's +args+ / +kwargs+ is rejected at
31
- # construction (E-29): legitimate Handles only enter Host App code
29
+ # construction: legitimate Handles only enter Host App code
32
30
  # through error fields, so a Handle reaching the call site is by
33
31
  # definition smuggled in. The +#encode+ output is the "Run envelope"
34
32
  # that ships through the +__kobako_run+ command buffer.
@@ -36,8 +34,8 @@ module Kobako
36
34
  # Built on the +class X < Data.define(...)+ subclass form (the
37
35
  # Steep-friendly shape — see +lib/kobako/outcome/panic.rb+).
38
36
  class Run < Data.define(:entrypoint, :args, :kwargs)
39
- # Ruby constant-name pattern enforced on the +entrypoint+ Symbol
40
- # ({docs/behavior.md E-25}[link:../../../docs/behavior.md]). Parallel to
37
+ # Ruby constant-name pattern enforced on the +entrypoint+ Symbol.
38
+ # Parallel to
41
39
  # +Kobako::Catalog::Snippets::NAME_PATTERN+; the two constants name the
42
40
  # same regex but cover distinct surfaces (snippet identity vs.
43
41
  # entrypoint resolution) so a future divergence stays local.
@@ -55,10 +53,9 @@ module Kobako
55
53
  # ({docs/wire-codec.md Invocation channels}[link:../../../docs/wire-codec.md]).
56
54
  # Walks +args+ / +kwargs+ through {Codec::Utils.deep_wrap} so any
57
55
  # non-wire-representable leaf is allocated into +handler+ and
58
- # replaced with a +Kobako::Handle+
59
- # ({docs/behavior.md B-34}[link:../../../docs/behavior.md]); the
56
+ # replaced with a +Kobako::Handle+; the
60
57
  # +handler+ argument is the Sandbox's table, sharing the same
61
- # allocator the guest→host return path (B-14) uses.
58
+ # allocator the guest→host return path uses.
62
59
  #
63
60
  # Layout: msgpack map with string keys +"entrypoint"+ (Symbol via
64
61
  # ext 0x00), +"args"+ (Array), +"kwargs"+ (Map with Symbol keys);
@@ -74,9 +71,9 @@ module Kobako
74
71
 
75
72
  private
76
73
 
77
- # E-24: target must be a Symbol or String (TypeError, not
74
+ # The target must be a Symbol or String (TypeError, not
78
75
  # ArgumentError — the wrong-type case is a Host App programming
79
- # error before the run reaches the guest). E-25: after +.to_s+
76
+ # error before the run reaches the guest). After +.to_s+
80
77
  # the value must match NAME_PATTERN (ArgumentError), rejecting
81
78
  # +::+-segmented names and any non-constant form.
82
79
  def normalize_entrypoint(target)
@@ -93,12 +90,12 @@ module Kobako
93
90
  target_str.to_sym
94
91
  end
95
92
 
96
- # E-29: +args+ must not contain a +Kobako::Handle+. The Handle
93
+ # +args+ must not contain a +Kobako::Handle+. The Handle
97
94
  # allocator lives inside the Host Gem; legitimate paths surface
98
95
  # Handle objects only through raised error fields, so a Handle
99
96
  # reaching +args+ is a forged or smuggled token. Non-wire-
100
97
  # representable arguments that are not Handles are handled by
101
- # auto-wrap inside +#encode+ (B-34) — the reject path is reserved
98
+ # auto-wrap inside +#encode+ — the reject path is reserved
102
99
  # for Handle objects specifically.
103
100
  def validate_args!(args)
104
101
  raise ArgumentError, "arguments must be an Array" unless args.is_a?(Array)
@@ -107,11 +104,10 @@ module Kobako
107
104
  args
108
105
  end
109
106
 
110
- # E-30 covers the non-Symbol kwargs-key case; E-29 also rejects a
111
- # +Kobako::Handle+ arriving as a kwargs value (same forged-token
112
- # principle as the +args+ branch). Both checks live here so the
113
- # Host App sees the host-side error message before any encode /
114
- # decode boundary.
107
+ # Reject a non-Symbol kwargs key, and a +Kobako::Handle+ arriving
108
+ # as a kwargs value (same forged-token principle as the +args+
109
+ # branch). Both checks live here so the Host App sees the
110
+ # host-side error message before any encode / decode boundary.
115
111
  def validate_kwargs!(kwargs)
116
112
  raise ArgumentError, "keyword arguments must be a Hash" unless kwargs.is_a?(Hash)
117
113
 
@@ -125,11 +121,10 @@ module Kobako
125
121
  kwargs
126
122
  end
127
123
 
128
- # Single source of truth for the E-29 reject message so the args
129
- # and kwargs branches stay phrased identically. Message stays in
124
+ # Single source of truth for the forged-Handle reject message so the
125
+ # args and kwargs branches stay phrased identically. Message stays in
130
126
  # caller vocabulary: it names the affected slot and the reason
131
- # without leaking SPEC anchor identifiers (B-xx / E-xx live in
132
- # source comments, not user-visible errors) or self-referential
127
+ # without leaking internal SPEC identifiers or self-referential
133
128
  # architecture terms — the error is raised BY kobako, so saying
134
129
  # "allocated by the Host Gem" reads as third-person about self.
135
130
  def forged_handle_message(slot)
@@ -8,29 +8,25 @@ module Kobako
8
8
  # owns the host-side object that materialises a guest-supplied block as
9
9
  # a Ruby callable the Service method can yield into.
10
10
  module Transport
11
- # Host-side stand-in for a guest-supplied block (B-23).
11
+ # Host-side stand-in for a guest-supplied block.
12
12
  #
13
13
  # Each guest call that carries +block_given: true+ gets a Yielder
14
14
  # that the Dispatcher hands to the Service method as +&block+. The
15
15
  # Service method observes it as an ordinary Ruby Proc through
16
16
  # {#to_proc}; +yield val+ / +block.call(val)+ invokes {#yield}, which
17
17
  # serialises the positional args, re-enters the guest via the injected
18
- # +yield_to_guest+ lambda
19
- # ({docs/behavior.md B-24}[link:../../../docs/behavior.md]), and
20
- # reifies the +YieldResponse+ into Ruby control flow:
18
+ # +yield_to_guest+ lambda, and reifies the +YieldResponse+ into Ruby
19
+ # control flow:
21
20
  #
22
21
  # * +tag 0x01+ ok — return the decoded value to +yield+'s caller
23
22
  # * +tag 0x02+ break — +throw break_tag, value+ so the Dispatcher's
24
23
  # +catch+ frame unwinds the Service method
25
- # ({docs/behavior.md B-25}[link:../../../docs/behavior.md])
26
24
  # * +tag 0x04+ error — raise the +{class, message}+ payload at the
27
25
  # Service's yield site
28
26
  #
29
27
  # The Dispatcher calls {#invalidate!} from its +ensure+ block once
30
28
  # dispatch completes; any later call to a stashed Yielder then raises
31
- # +LocalJumpError+ — the observable shape of
32
- # {docs/behavior.md E-23}[link:../../../docs/behavior.md] (escaped
33
- # Yielder).
29
+ # +LocalJumpError+ — the observable shape of an escaped Yielder.
34
30
  class Yielder
35
31
  # +yield_to_guest+ is a +String → String+ callable (typically
36
32
  # +Runtime#yield_to_active_invocation+ bound through a lambda) that
@@ -38,8 +34,7 @@ module Kobako
38
34
  # throw tag the Dispatcher matches against to unwind the Service on
39
35
  # +tag 0x02+. +handler+ is the Sandbox's +Kobako::Catalog::Handles+,
40
36
  # used to restore a Capability Handle in the block's ok value back to
41
- # its host object before it reaches the Service +yield+ site
42
- # ({docs/behavior.md B-37}[link:../../../docs/behavior.md]).
37
+ # its host object before it reaches the Service +yield+ site.
43
38
  def initialize(yield_to_guest, break_tag, handler)
44
39
  @yield_to_guest = yield_to_guest
45
40
  @break_tag = break_tag
@@ -49,10 +44,10 @@ module Kobako
49
44
 
50
45
  # Re-enter the guest with +args+ and reify the YieldResponse into
51
46
  # Ruby control flow. Raises +LocalJumpError+ if called after
52
- # {#invalidate!} (E-23). The ok value is consumed by the host Service
53
- # method, so a Capability Handle in it is restored to its host object
54
- # (B-37). The break value unwinds past the Service back to the guest
55
- # Member call (B-25), so it passes through verbatim — a Handle stays a
47
+ # {#invalidate!}. The ok value is consumed by the host Service
48
+ # method, so a Capability Handle in it is restored to its host object.
49
+ # The break value unwinds past the Service back to the guest
50
+ # Member call, so it passes through verbatim — a Handle stays a
56
51
  # Handle and rides back on the same id rather than churning a new one.
57
52
  def yield(*args)
58
53
  raise LocalJumpError, "guest block invoked after host dispatch frame returned" unless @active
@@ -73,7 +68,7 @@ module Kobako
73
68
 
74
69
  # Mark this Yielder dead. Called by the Dispatcher's +ensure+ block
75
70
  # when the originating dispatch frame returns; any later {#yield}
76
- # call then raises +LocalJumpError+ (E-23).
71
+ # call then raises +LocalJumpError+.
77
72
  def invalidate!
78
73
  @active = false
79
74
  end
@@ -81,8 +76,7 @@ module Kobako
81
76
  private
82
77
 
83
78
  # Restore any Capability Handle in a block's ok value to its host
84
- # object via the injected +Catalog::Handles+
85
- # ({docs/behavior.md B-37}[link:../../../docs/behavior.md]). Only the
79
+ # object via the injected +Catalog::Handles+. Only the
86
80
  # ok path calls this — host code consumes the ok value, whereas a
87
81
  # break value returns to the guest and stays a Handle. Walks nested
88
82
  # Array / Hash one level at a time; a plain value passes through
@@ -13,9 +13,8 @@ module Kobako
13
13
  # Houses the envelope value objects (Request / Response / Run / Yield),
14
14
  # the guest→host +Dispatcher+, and the host→guest +Yielder+.
15
15
  # +Sandbox#initialize+ composes them onto the
16
- # +Runtime+ as a dispatch +Proc+ + +yield_to_guest+ lambda pair
17
- # ({docs/behavior.md B-12}[link:../../docs/behavior.md]). "RPC" was
18
- # deliberately not chosen — it implies a cross-process boundary that
16
+ # +Runtime+ as a dispatch +Proc+ + +yield_to_guest+ lambda pair.
17
+ # "RPC" was deliberately not chosen — it implies a cross-process boundary that
19
18
  # kobako does not have, since host and guest share one OS thread and
20
19
  # one wasm linear memory. See
21
20
  # {SPEC.md Refinement → Internal Concepts}[link:../../SPEC.md].
data/lib/kobako/usage.rb CHANGED
@@ -1,14 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
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:
4
+ # Per-last-invocation resource accounting for a +Kobako::Sandbox+.
5
+ # Carries two readers populated by every +#eval+ / +#run+ invocation:
7
6
  #
8
7
  # * +wall_time+ — the Float number of seconds the guest export call
9
8
  # 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
9
+ # measurement bracket aligns with the +timeout+ deadline; time spent
12
10
  # in host Service callbacks is included, but everything that runs
13
11
  # after the guest export returns — the post-export
14
12
  # +OUTCOME_BUFFER+ fetch and decode, plus stdout / stderr capture
@@ -16,11 +14,11 @@ module Kobako
16
14
  # * +memory_peak+ — the Integer high-water mark, in bytes, of the
17
15
  # per-invocation +memory.grow+ delta past the linear-memory size
18
16
  # 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.
17
+ # +memory_limit+: the mruby image's initial allocation and any
18
+ # prior-invocation watermark sit outside the measurement. On
19
+ # +MemoryLimitError+ +memory_peak+ never exceeds the configured
20
+ # cap because the rejected +desired+ value is not promoted into
21
+ # the high-water.
24
22
  #
25
23
  # Both readers are populated on every outcome, including +TrapError+
26
24
  # branches, so the Host App can read +Sandbox#usage+ after rescuing a
@@ -31,9 +29,8 @@ module Kobako
31
29
  # Built on the +class X < Data.define(...)+ subclass form (the
32
30
  # Steep-friendly shape — see +lib/kobako/outcome/panic.rb+).
33
31
  class Usage < Data.define(:wall_time, :memory_peak)
34
- # Pre-invocation sentinel ({docs/behavior.md B-35}[link:../../docs/behavior.md]).
35
- # Reused by +Sandbox+ before any invocation has run so callers do not
36
- # need to handle a +nil+ +#usage+.
32
+ # Pre-invocation sentinel. Reused by +Sandbox+ before any invocation
33
+ # has run so callers do not need to handle a +nil+ +#usage+.
37
34
  EMPTY = new(wall_time: 0.0, memory_peak: 0)
38
35
  end
39
36
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kobako
4
- VERSION = "0.9.2"
4
+ VERSION = "0.11.0"
5
5
  end
data/lib/kobako.rb CHANGED
@@ -15,3 +15,4 @@ require_relative "kobako/catalog"
15
15
  require_relative "kobako/runtime"
16
16
  require_relative "kobako/snapshot"
17
17
  require_relative "kobako/sandbox"
18
+ require_relative "kobako/pool"
@@ -73,13 +73,28 @@
73
73
  "path": "/wasm/kobako-regexp/README.md"
74
74
  }
75
75
  ]
76
+ },
77
+ "wasm/kobako-baker": {
78
+ "component": "kobako-baker",
79
+ "release-type": "rust",
80
+ "extra-files": [
81
+ {
82
+ "type": "toml",
83
+ "path": "/wasm/kobako-baker/Cargo.lock",
84
+ "jsonpath": "$.package[?(@.name=='kobako-baker')].version"
85
+ },
86
+ {
87
+ "type": "generic",
88
+ "path": "/wasm/kobako-baker/README.md"
89
+ }
90
+ ]
76
91
  }
77
92
  },
78
93
  "plugins": [
79
94
  {
80
95
  "type": "linked-versions",
81
96
  "groupName": "kobako guest crates",
82
- "components": ["kobako-core", "kobako-rs", "kobako-io", "kobako-regexp"]
97
+ "components": ["kobako-core", "kobako-rs", "kobako-io", "kobako-regexp", "kobako-baker"]
83
98
  }
84
99
  ],
85
100
  "extra-files": [
@@ -1,8 +1,6 @@
1
1
  module Kobako
2
2
  module Catalog
3
3
  class Handles
4
- UNWRAPPABLE_TYPES: Array[Module]
5
-
6
4
  def initialize: (?next_id: Integer) -> void
7
5
 
8
6
  def alloc: (untyped object) -> Kobako::Handle
@@ -52,4 +52,7 @@ module Kobako
52
52
 
53
53
  class BytecodeError < SandboxError
54
54
  end
55
+
56
+ class PoolTimeoutError < Error
57
+ end
55
58
  end
@@ -8,6 +8,8 @@ module Kobako
8
8
 
9
9
  def bind: (Symbol | String member, untyped object) -> self
10
10
 
11
+ def seal!: () -> self
12
+
11
13
  def fetch: (Symbol | String member) -> untyped
12
14
 
13
15
  def to_preamble: () -> [String, Array[String]]
@@ -0,0 +1,44 @@
1
+ module Kobako
2
+ class Pool
3
+ DEFAULT_CHECKOUT_TIMEOUT_SECONDS: Float
4
+
5
+ @slots: Integer
6
+ @checkout_timeout: Float?
7
+ @sandbox_options: Hash[Symbol, untyped]
8
+ @setup: ^(Kobako::Sandbox) -> void | nil
9
+ @idle: Array[Kobako::Sandbox]
10
+ @constructed: Integer
11
+ @mutex: Thread::Mutex
12
+ @slot_freed: Thread::ConditionVariable
13
+
14
+ def initialize: (
15
+ slots: Integer,
16
+ ?checkout_timeout: (Float | Integer)?,
17
+ **untyped sandbox_options
18
+ ) ?{ (Kobako::Sandbox) -> void } -> void
19
+
20
+ def with: [T] () { (Kobako::Sandbox) -> T } -> T
21
+
22
+ private
23
+
24
+ def checkout: () -> Kobako::Sandbox
25
+
26
+ def acquire: () -> Kobako::Sandbox
27
+
28
+ def claim_or_wait: (Float? deadline) -> [Symbol, Kobako::Sandbox?]
29
+
30
+ def await_slot!: (Float? deadline) -> void
31
+
32
+ def construct_slot: () -> Kobako::Sandbox
33
+
34
+ def checkin: (Kobako::Sandbox sandbox) -> void
35
+
36
+ def release_capacity!: () -> void
37
+
38
+ def monotonic_now: () -> Float
39
+
40
+ def validate_slots!: (untyped slots) -> void
41
+
42
+ def normalize_checkout_timeout: ((Float | Integer)? checkout_timeout) -> Float?
43
+ end
44
+ end
@@ -38,12 +38,12 @@ module Kobako
38
38
 
39
39
  def eval: (String code) -> untyped
40
40
 
41
+ def reset_invocation_state!: () -> void
42
+
41
43
  private
42
44
 
43
45
  def install_dispatch_proc!: () -> void
44
46
 
45
- def reset_invocation_state!: () -> void
46
-
47
47
  def begin_invocation!: () -> void
48
48
 
49
49
  def read_usage!: () -> void
@@ -22,6 +22,8 @@ module Kobako
22
22
 
23
23
  def self?.reject_meta_method!: (untyped target, Symbol name) -> void
24
24
 
25
+ def self?.reject_unexposed!: (untyped target, Symbol name) -> void
26
+
25
27
  def self?.resolve_arg: (untyped value, Kobako::Catalog::Handles handler) -> untyped
26
28
 
27
29
  def self?.resolve_target: (String | Kobako::Handle target, Kobako::Catalog::Namespaces namespaces, Kobako::Catalog::Handles handler) -> untyped
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kobako
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.2
4
+ version: 0.11.0
5
5
  platform: aarch64-linux
6
6
  authors:
7
7
  - Aotokitsuruya
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-06-11 00:00:00.000000000 Z
11
+ date: 2026-06-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: msgpack
@@ -59,6 +59,7 @@ files:
59
59
  - lib/kobako/namespace.rb
60
60
  - lib/kobako/outcome.rb
61
61
  - lib/kobako/outcome/panic.rb
62
+ - lib/kobako/pool.rb
62
63
  - lib/kobako/runtime.rb
63
64
  - lib/kobako/sandbox.rb
64
65
  - lib/kobako/sandbox_options.rb
@@ -96,6 +97,7 @@ files:
96
97
  - sig/kobako/namespace.rbs
97
98
  - sig/kobako/outcome.rbs
98
99
  - sig/kobako/outcome/panic.rbs
100
+ - sig/kobako/pool.rbs
99
101
  - sig/kobako/runtime.rbs
100
102
  - sig/kobako/sandbox.rbs
101
103
  - sig/kobako/sandbox_options.rbs