homura-runtime 0.2.4 → 0.2.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a7e0278919623ca0bd4057dd685cc0a6121efa0d36e0f0a7eeb8bc9e404938a8
4
- data.tar.gz: 3896ecbe9174de362fd6e9dc4d24ec015adf495bce80b045bd61d2c4a305791d
3
+ metadata.gz: f2b3ce399f63be057b0f83676eb0634e304af26474f2377ffbda23d1e89c2107
4
+ data.tar.gz: 5dc9a30ab22c1688c167c052ac92660190193282f73e0aa314433e5de9596b53
5
5
  SHA512:
6
- metadata.gz: 2607d862746d48cad7eb8c28a8e1cb39477c95fab45c6f90ea0cc8e773dadfca54d1e2d3cb0842774cec3bddbe7216ce0efd433f147f48c86a97a2118f29edd4
7
- data.tar.gz: 14a8a0faca16aa7f1f8ed9a49c2bbc194afd4417a2d4b808519d1d144a94b9ac2a75a01fbdbceb385e732228f3b0bba91667f3d17d5004cec8f3d17ccf72f380
6
+ metadata.gz: f406f03d5fc65c9c89499aae50e8fba67b4a277dc702033937e9f54f7a8c9408fce6927a06ac96e6ec864fd6492ae0e700b006ddeafd4018ca55722b0fd2351d
7
+ data.tar.gz: b6ab470270263184c1298fd22799b4b2a35185b1695539eea81b135f1715454043f2682f1158b42eb940d2a3dfc3283ea1631ed73cbed63c8fad0f22aa02eaab
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.5 (2026-04-23)
4
+
5
+ - Load Workers-only `zlib`, `tempfile`, and `tilt` shims via `require_relative`
6
+ so plain `opal` CLI builds can require `opal_patches` without extra vendor
7
+ load path wiring.
8
+ - Recursively convert nested plain JS objects in `Cloudflare.js_object_to_hash`
9
+ so D1 metadata behaves like Ruby `Hash` values all the way down.
10
+ - Pin `opal-homura` to `1.8.3.rc1.3` for the restored `digest` stdlib shim.
11
+
3
12
  ## 0.2.4 (2026-04-23)
4
13
 
5
14
  - Guard the Rack body close hook against raw JS `undefined` so Workers request teardown
data/README.md CHANGED
@@ -14,7 +14,7 @@ Core Ruby + Module Worker glue for [Opal](https://opalrb.com/) on [Cloudflare Wo
14
14
 
15
15
  ## Quick start (homura monorepo)
16
16
 
17
- 1. `Gemfile`: `gem 'homura-runtime', path: 'gems/homura-runtime'` and `gem 'opal-homura', '= 1.8.3.rc1.2', require: 'opal'` (path or exact pin).
17
+ 1. `Gemfile`: `gem 'homura-runtime', path: 'gems/homura-runtime'` and `gem 'opal-homura', '= 1.8.3.rc1.3', require: 'opal'` (path or exact pin).
18
18
  2. `bundle exec homura build` — writes `build/hello.no-exit.mjs` and `build/worker.entrypoint.mjs`.
19
19
  3. `wrangler.toml`: `main = "build/worker.entrypoint.mjs"`, `compatibility_flags = ["nodejs_compat"]`.
20
20
 
@@ -25,7 +25,7 @@ Core Ruby + Module Worker glue for [Opal](https://opalrb.com/) on [Cloudflare Wo
25
25
  | Ruby | 3.4.x |
26
26
  | Node | ≥ 20 |
27
27
  | Wrangler | ^3.99 |
28
- | Opal | = 1.8.3.rc1.2 |
28
+ | Opal | = 1.8.3.rc1.3 |
29
29
 
30
30
  ## Wrangler config
31
31
 
@@ -79,7 +79,7 @@ module CloudflareWorkers
79
79
  next unless Dir.exist?(lib_dir)
80
80
 
81
81
  Dir.glob(File.join(lib_dir, '**', '*.rb')).each do |path|
82
- next unless File.read(path, 8192).include?('register_async_source')
82
+ next unless File.read(path).include?('register_async_source')
83
83
 
84
84
  require_path = path.sub(Regexp.new("^#{Regexp.escape(lib_dir)}/"), '').sub(/\.rb\z/, '')
85
85
  begin
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CloudflareWorkers
4
- VERSION = '0.2.4'
4
+ VERSION = '0.2.5'
5
5
  end
@@ -144,7 +144,10 @@ module Rack
144
144
  raise '`run app` was never called from user code' if @app.nil?
145
145
 
146
146
  env = build_rack_env(js_req, js_env, js_ctx, body_text)
147
- status, headers, body = @app.call(env)
147
+ result = @app.call(env)
148
+ result = result.__await__ if defined?(::Cloudflare) && ::Cloudflare.js_promise?(result)
149
+
150
+ status, headers, body = result
148
151
  build_js_response(status, headers, body)
149
152
  ensure
150
153
  body.close if body && body.respond_to?(:close)
@@ -484,7 +487,9 @@ module Cloudflare
484
487
  out
485
488
  end
486
489
 
487
- # Shallow copy of a JS object's own enumerable string keys into a Hash.
490
+ # Deep copy of a JS object's own enumerable string keys into a Hash.
491
+ # Recursively converts nested plain objects so Opal code can call
492
+ # Ruby methods (e.g. #is_a?) on every value.
488
493
  def self.js_object_to_hash(js_obj)
489
494
  h = {}
490
495
  return h if `#{js_obj} == null`
@@ -494,6 +499,8 @@ module Cloudflare
494
499
  while i < len
495
500
  k = `#{keys}[#{i}]`
496
501
  v = `#{js_obj}[#{k}]`
502
+ # Recurse for nested plain objects (but not Arrays, Dates, etc.)
503
+ v = js_object_to_hash(v) if `typeof #{v} === 'object' && #{v} != null && !Array.isArray(#{v}) && !(#{v} instanceof Date)`
497
504
  h[k] = v
498
505
  i += 1
499
506
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stringio'
4
+
5
+ class Tempfile < StringIO
6
+ def initialize(*)
7
+ super('')
8
+ end
9
+
10
+ def self.open(*)
11
+ raise NotImplementedError, 'Tempfile is stubbed in homura (Workers have no writable FS)'
12
+ end
13
+
14
+ def path
15
+ raise NotImplementedError, 'Tempfile#path stubbed (no FS)'
16
+ end
17
+
18
+ def unlink
19
+ self
20
+ end
21
+
22
+ def delete
23
+ self
24
+ end
25
+
26
+ def close!
27
+ close
28
+ end
29
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tilt
4
+ class TemplateNotFound < StandardError; end
5
+
6
+ class Cache
7
+ def initialize
8
+ @cache = {}
9
+ end
10
+
11
+ def fetch(*key)
12
+ @cache[key] ||= yield
13
+ end
14
+
15
+ def clear
16
+ @cache.clear
17
+ end
18
+ end
19
+
20
+ class Mapping
21
+ def initialize
22
+ @extensions = {}
23
+ end
24
+
25
+ def register(template_class, *extensions)
26
+ extensions.each { |ext| @extensions[ext.to_s] = template_class }
27
+ end
28
+
29
+ def [](name)
30
+ @extensions[name.to_s]
31
+ end
32
+
33
+ def extensions_for(engine_or_class)
34
+ @extensions.each_with_object([]) do |(ext, klass), out|
35
+ out << ext if klass == engine_or_class
36
+ end
37
+ end
38
+
39
+ def template_for(name)
40
+ @extensions[name.to_s]
41
+ end
42
+ end
43
+
44
+ class << self
45
+ def default_mapping
46
+ @default_mapping ||= Mapping.new
47
+ end
48
+
49
+ def [](name)
50
+ default_mapping[name]
51
+ end
52
+
53
+ def register(template_class, *extensions)
54
+ default_mapping.register(template_class, *extensions)
55
+ end
56
+
57
+ def new(file = nil, line = nil, options = {}, &block)
58
+ raise NotImplementedError,
59
+ 'Tilt template rendering is not available in homura Phase 2 ' \
60
+ '(stubbed). Return Strings or arrays from your Sinatra handlers.'
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Zlib
4
+ class Error < StandardError; end
5
+
6
+ class GzipFile
7
+ class Error < Zlib::Error; end
8
+ class CRCError < Error; end
9
+ class LengthError < Error; end
10
+ class NoFooter < Error; end
11
+ end
12
+
13
+ class GzipReader < GzipFile
14
+ def self.wrap(*)
15
+ raise NotImplementedError, 'Zlib stubbed'
16
+ end
17
+ end
18
+
19
+ class GzipWriter < GzipFile
20
+ def self.wrap(*)
21
+ raise NotImplementedError, 'Zlib stubbed'
22
+ end
23
+ end
24
+
25
+ class Deflate
26
+ def self.deflate(*)
27
+ raise NotImplementedError, 'Zlib stubbed'
28
+ end
29
+
30
+ def initialize(*); end
31
+
32
+ def deflate(*)
33
+ raise NotImplementedError, 'Zlib stubbed'
34
+ end
35
+
36
+ def finish
37
+ raise NotImplementedError, 'Zlib stubbed'
38
+ end
39
+
40
+ def close; end
41
+ end
42
+
43
+ class Inflate
44
+ def self.inflate(*)
45
+ raise NotImplementedError, 'Zlib stubbed'
46
+ end
47
+ end
48
+
49
+ DEFAULT_COMPRESSION = -1
50
+ BEST_SPEED = 1
51
+ BEST_COMPRESSION = 9
52
+ end
data/lib/opal_patches.rb CHANGED
@@ -396,14 +396,15 @@ end
396
396
  # same strength CRuby Sinatra gives you when SecureRandom is unavailable
397
397
  # (it falls back to `Kernel.rand`), so we are not reducing security
398
398
  # beyond upstream's own fallback path.
399
- # Ensure our Digest/Zlib/Tempfile/Tilt stubs from vendor/ are available
400
- # everywhere, even when a gem references `Digest::SHA1` at class body
401
- # time without explicitly `require 'digest'`-ing first.
399
+ # Ensure our Digest/Zlib/Tempfile/Tilt shims are available when
400
+ # `opal_patches` is loaded directly through the plain Opal CLI as well as
401
+ # through `homura build`. Digest itself now lives in opal-homura stdlib;
402
+ # the remaining Workers-specific shims stay local to this gem.
402
403
  require 'digest'
403
404
  require 'digest/sha2'
404
- require 'zlib'
405
- require 'tempfile'
406
- require 'tilt'
405
+ require 'homura_vendor_zlib'
406
+ require 'homura_vendor_tempfile'
407
+ require 'homura_vendor_tilt'
407
408
 
408
409
  module ::SecureRandom
409
410
  # Raised when neither node:crypto.randomBytes nor Web Crypto
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: homura-runtime
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kazuhiro Homma
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - '='
17
17
  - !ruby/object:Gem::Version
18
- version: 1.8.3.rc1.2
18
+ version: 1.8.3.rc1.3
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - '='
24
24
  - !ruby/object:Gem::Version
25
- version: 1.8.3.rc1.2
25
+ version: 1.8.3.rc1.3
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: parser
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -68,6 +68,9 @@ files:
68
68
  - lib/cloudflare_workers/scheduled.rb
69
69
  - lib/cloudflare_workers/stream.rb
70
70
  - lib/cloudflare_workers/version.rb
71
+ - lib/homura_vendor_tempfile.rb
72
+ - lib/homura_vendor_tilt.rb
73
+ - lib/homura_vendor_zlib.rb
71
74
  - lib/opal_patches.rb
72
75
  - runtime/patch-opal-evals.mjs
73
76
  - runtime/setup-node-crypto.mjs