homura-runtime 0.2.7 → 0.2.9
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 +18 -0
- data/exe/compile-erb +3 -0
- data/exe/homura-build +4 -1
- data/lib/cloudflare_workers/auto_await/analyzer.rb +5 -1
- data/lib/cloudflare_workers/auto_await/transformer.rb +5 -0
- data/lib/cloudflare_workers/build_support.rb +1 -1
- data/lib/cloudflare_workers/version.rb +1 -1
- data/lib/cloudflare_workers.rb +16 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d41fae3606bacf17566d5d2b423547fffcb490a70fde78bb9e0e34e9cff357cd
|
|
4
|
+
data.tar.gz: 2c7f98a9cfa158acdb8287788176af5515d3bf736c791de2d849e8ee4c29d06d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: adeef4db820e46d80748ebd3aa9ebc8d8224d1e3a796a07582d47c73eee6ea21541805b087d1aa16a6dbfb19434b4fe9f3c7ff2ab36943d01df1b8263fc22137
|
|
7
|
+
data.tar.gz: a3b35377f1d55af94598f1728edec1a6a06acc9f42ffe02090116dfa022a2548349c5da1fa5b061d96cf5b734372ce54c6b3dbbf5192b78e0988a7464ddfb210
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.9 (2026-04-24)
|
|
4
|
+
|
|
5
|
+
- Skip auto-await rewrites when the source expression is already followed by
|
|
6
|
+
`.__await__`, avoiding noisy double-application in rewritten standalone app
|
|
7
|
+
code.
|
|
8
|
+
|
|
9
|
+
## 0.2.8 (2026-04-24)
|
|
10
|
+
|
|
11
|
+
- Compile standalone `config.ru` inputs from `build/auto_await/` so ordinary
|
|
12
|
+
`require_relative 'app/app'` entrypoints pick up the auto-awaited app copy
|
|
13
|
+
instead of silently falling back to the original source.
|
|
14
|
+
- Teach the auto-await analyzer to prefer locally inferred helper return types
|
|
15
|
+
over generic registry defaults, and infer memoized `foo ||= ...` helper bodies.
|
|
16
|
+
- Preserve redirect headers when awaited routes resolve to Rack tuples through
|
|
17
|
+
the Promise response builder.
|
|
18
|
+
- Add `layout.erb` by default in the precompiled ERB runtime so `erb :index`
|
|
19
|
+
behaves like ordinary Sinatra unless the app passes `layout: false`.
|
|
20
|
+
|
|
3
21
|
## 0.2.7 (2026-04-24)
|
|
4
22
|
|
|
5
23
|
- Auto-detect standalone app entrypoints from `config.ru`, `app/hello.rb`, then
|
data/exe/compile-erb
CHANGED
|
@@ -264,6 +264,9 @@ def emit_sinatra_patch(io, namespace)
|
|
|
264
264
|
|
|
265
265
|
layout = options[:layout]
|
|
266
266
|
layout = false if layout.nil? && options.include?(:layout)
|
|
267
|
+
if layout.nil? && template.to_sym != :layout && ::#{namespace}.registered?(:layout)
|
|
268
|
+
layout = :layout
|
|
269
|
+
end
|
|
267
270
|
if layout
|
|
268
271
|
layout = :layout if layout == true
|
|
269
272
|
layout = layout.to_sym
|
data/exe/homura-build
CHANGED
|
@@ -163,7 +163,10 @@ def prepare_opal_input(root, input_path)
|
|
|
163
163
|
rel = root.join(rel).relative_path_from(root) if rel.absolute?
|
|
164
164
|
return [rel.to_s, nil] unless rel.extname == '.ru'
|
|
165
165
|
|
|
166
|
-
|
|
166
|
+
tmp_dir = root.join('build', 'auto_await')
|
|
167
|
+
tmp_dir = root unless tmp_dir.directory?
|
|
168
|
+
tmp = tmp_dir.join(".homura-build-#{rel.basename}.rb")
|
|
169
|
+
FileUtils.mkdir_p(tmp.dirname)
|
|
167
170
|
File.write(tmp, root.join(rel).read)
|
|
168
171
|
[tmp.relative_path_from(root).to_s, tmp]
|
|
169
172
|
end
|
|
@@ -144,16 +144,20 @@ module CloudflareWorkers
|
|
|
144
144
|
when :send
|
|
145
145
|
receiver, method_name = *node
|
|
146
146
|
if receiver.nil?
|
|
147
|
-
return @env[method_name] if @env.key?(method_name)
|
|
148
147
|
return @method_returns[method_name] if @method_returns.key?(method_name)
|
|
148
|
+
return @env[method_name] if @env.key?(method_name)
|
|
149
149
|
end
|
|
150
150
|
infer_send_class(node)
|
|
151
151
|
when :index
|
|
152
152
|
infer_index_class(node)
|
|
153
|
+
when :begin
|
|
154
|
+
infer_class(node.children.last)
|
|
153
155
|
when :lvar
|
|
154
156
|
@env[node.children[0]]
|
|
155
157
|
when :ivar
|
|
156
158
|
nil
|
|
159
|
+
when :or_asgn
|
|
160
|
+
infer_class(node.children.last)
|
|
157
161
|
when :const
|
|
158
162
|
const_path(node)
|
|
159
163
|
else
|
|
@@ -10,10 +10,15 @@ module CloudflareWorkers
|
|
|
10
10
|
await_nodes.each do |node|
|
|
11
11
|
range = node.loc.expression
|
|
12
12
|
next unless range
|
|
13
|
+
next if already_awaited?(buffer, range)
|
|
13
14
|
rewriter.replace(range, "#{range.source}.__await__")
|
|
14
15
|
end
|
|
15
16
|
rewriter.process
|
|
16
17
|
end
|
|
18
|
+
|
|
19
|
+
def self.already_awaited?(buffer, range)
|
|
20
|
+
buffer.source[range.end_pos..]&.match?(/\A\s*\.__await__\b/)
|
|
21
|
+
end
|
|
17
22
|
end
|
|
18
23
|
end
|
|
19
24
|
end
|
|
@@ -61,7 +61,7 @@ module CloudflareWorkers
|
|
|
61
61
|
hv = vendor_from_gemfile(root)
|
|
62
62
|
load_paths << hv.to_s if hv
|
|
63
63
|
|
|
64
|
-
load_paths += ['.', 'build/auto_await/app', 'app']
|
|
64
|
+
load_paths += ['.', 'build/auto_await', 'build/auto_await/app', 'app']
|
|
65
65
|
[
|
|
66
66
|
gem_lib(RUNTIME_GEM_NAME, loaded_specs: loaded_specs),
|
|
67
67
|
gem_vendor(RUNTIME_GEM_NAME, loaded_specs: loaded_specs),
|
data/lib/cloudflare_workers.rb
CHANGED
|
@@ -405,7 +405,7 @@ module Rack
|
|
|
405
405
|
# used for 101 WebSocket upgrades where the Workers
|
|
406
406
|
# runtime's own Response carries runtime-only properties
|
|
407
407
|
# (`.webSocket`) that a reconstructed Response would lose.
|
|
408
|
-
`Promise.all(#{js_chunks}).then(function(resolved) { var bodyToText = function(v) { if (v == null) { return ''; } if (Array.isArray(v)) { var joined = ''; for (var j = 0; j < v.length; j++) { joined += bodyToText(v[j]); } return joined; } if (typeof v === 'string') { return v; } if (v != null && v.$$is_string) { return v.toString(); } try { return JSON.stringify(v); } catch (e) { return String(v); } }; for (var i = 0; i < resolved.length; i++) { var r = resolved[i]; if (r != null && typeof r === 'object' && typeof r['$raw_response?'] === 'function' && typeof r['$js_response'] === 'function') { try { if (r['$raw_response?']()) { return r['$js_response'](); } } catch (_) {} } } for (var i = 0; i < resolved.length; i++) { var r = resolved[i]; if (r != null && r.stream != null && r.content_type != null) { var bh = {}; bh['content-type'] = r.content_type; if (r.cache_control) bh['cache-control'] = r.cache_control; return new Response(r.stream, { status: #{status_int}, headers: bh }); } } if (resolved.length === 1 && resolved[0] != null && Array.isArray(resolved[0]) && resolved[0].length >= 1 && typeof resolved[0][0] === 'number') { var ov = resolved[0]; var ovs = ov[0]|0; var ovh = #{js_headers}; var ovb = ''; if (ov.length >= 3 && ov[1] != null
|
|
408
|
+
`Promise.all(#{js_chunks}).then(function(resolved) { var bodyToText = function(v) { if (v == null) { return ''; } if (Array.isArray(v)) { var joined = ''; for (var j = 0; j < v.length; j++) { joined += bodyToText(v[j]); } return joined; } if (typeof v === 'string') { return v; } if (v != null && v.$$is_string) { return v.toString(); } try { return JSON.stringify(v); } catch (e) { return String(v); } }; for (var i = 0; i < resolved.length; i++) { var r = resolved[i]; if (r != null && typeof r === 'object' && typeof r['$raw_response?'] === 'function' && typeof r['$js_response'] === 'function') { try { if (r['$raw_response?']()) { return r['$js_response'](); } } catch (_) {} } } for (var i = 0; i < resolved.length; i++) { var r = resolved[i]; if (r != null && r.stream != null && r.content_type != null) { var bh = {}; bh['content-type'] = r.content_type; if (r.cache_control) bh['cache-control'] = r.cache_control; return new Response(r.stream, { status: #{status_int}, headers: bh }); } } if (resolved.length === 1 && resolved[0] != null && Array.isArray(resolved[0]) && resolved[0].length >= 1 && typeof resolved[0][0] === 'number') { var ov = resolved[0]; var ovs = ov[0]|0; var ovh = #{Cloudflare}.$headers_to_js(nil, #{js_headers}); var ovb = ''; if (ov.length >= 3 && ov[1] != null) { ovh = #{Cloudflare}.$headers_to_js(ov[1], #{js_headers}); ovb = bodyToText(ov[2]); } else if (ov.length >= 2) { ovb = bodyToText(ov[ov.length - 1]); } return new Response(ovb, { status: ovs, headers: ovh }); } var parts = []; for (var i = 0; i < resolved.length; i++) { var r = resolved[i]; if (r == null) { parts.push(''); continue; } if (typeof r === 'string') { parts.push(r); continue; } if (r != null && r.$$is_string) { parts.push(r.toString()); continue; } try { parts.push(JSON.stringify(r)); } catch (e) { parts.push(String(r)); } } return new Response(parts.join(''), { status: #{status_int}, headers: #{js_headers} }); })`
|
|
409
409
|
else
|
|
410
410
|
body_str = ''
|
|
411
411
|
chunks.each { |c| body_str = body_str + c.to_s }
|
|
@@ -512,6 +512,21 @@ module Cloudflare
|
|
|
512
512
|
h
|
|
513
513
|
end
|
|
514
514
|
|
|
515
|
+
def self.headers_to_js(headers, fallback = nil)
|
|
516
|
+
return fallback || `({})` if headers.nil?
|
|
517
|
+
return headers if `#{headers} != null && #{headers}.constructor === Object`
|
|
518
|
+
|
|
519
|
+
js_headers = fallback || `({})`
|
|
520
|
+
if headers.respond_to?(:each)
|
|
521
|
+
headers.each do |key, value|
|
|
522
|
+
ks = key.to_s
|
|
523
|
+
vs = value.to_s
|
|
524
|
+
`#{js_headers}[#{ks}] = #{vs}`
|
|
525
|
+
end
|
|
526
|
+
end
|
|
527
|
+
js_headers
|
|
528
|
+
end
|
|
529
|
+
|
|
515
530
|
# RawResponse wraps an already-constructed JS `Response` so routes
|
|
516
531
|
# can return it through Sinatra and have `build_js_response` pass
|
|
517
532
|
# it through to the Workers runtime untouched. Needed when the
|