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 +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +2 -2
- data/lib/cloudflare_workers/async_registry.rb +1 -1
- data/lib/cloudflare_workers/version.rb +1 -1
- data/lib/cloudflare_workers.rb +9 -2
- data/lib/homura_vendor_tempfile.rb +29 -0
- data/lib/homura_vendor_tilt.rb +63 -0
- data/lib/homura_vendor_zlib.rb +52 -0
- data/lib/opal_patches.rb +7 -6
- metadata +6 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f2b3ce399f63be057b0f83676eb0634e304af26474f2377ffbda23d1e89c2107
|
|
4
|
+
data.tar.gz: 5dc9a30ab22c1688c167c052ac92660190193282f73e0aa314433e5de9596b53
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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.
|
|
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.
|
|
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
|
|
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
|
data/lib/cloudflare_workers.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
-
#
|
|
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
|
|
400
|
-
#
|
|
401
|
-
#
|
|
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 '
|
|
405
|
-
require '
|
|
406
|
-
require '
|
|
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
|
+
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.
|
|
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.
|
|
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
|