klenod-runtime 0.0.27 → 0.0.28
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/README.md +6 -0
- data/lib/klenod/runtime/bundle.rb +25 -8
- data/lib/klenod/runtime/bundle_format.rb +11 -8
- data/lib/klenod/runtime/version.rb +1 -1
- data/lib/klenod/runtime.rb +6 -6
- 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: d9f47b3f5b7633bc5266d7d84b085d0712911addf1c3801257016bca575592de
|
|
4
|
+
data.tar.gz: 104d04cde8bc7140f8dfb719008b76ceb2355d262823067fda91253b773cded4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ff96f298c6cb62fd3a6d9ddc6be0da629fe2286a8904ec6d26a37aa8b27dcf74dd20bc54c63221b5bcb8cc23b3dea9cba7278fb16b4a9b2577a34e44a07f7e96
|
|
7
|
+
data.tar.gz: 1776d55bbb39e6286da64179dd8ac313f996c809381b278cf23039dd7ea80187689e7c1d0f372bcb26c77a371f5fa7ad51ab71228057b691a0db9b06490a7574
|
data/README.md
CHANGED
|
@@ -21,6 +21,12 @@ bundle = Klenod::Runtime.load_bundle("dist/klenod.bundle")
|
|
|
21
21
|
exports = bundle.exports("pages/server")
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
+
Pass `namespace:` a named module when instances of bundled classes must be marshaled. The default anonymous namespace gives those classes names that Ruby cannot resolve:
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
bundle = Klenod::Runtime.load_bundle("dist/klenod.bundle", namespace: MyApp::Modules)
|
|
28
|
+
```
|
|
29
|
+
|
|
24
30
|
Production servers can explicitly preload bundled modules:
|
|
25
31
|
|
|
26
32
|
```ruby
|
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "digest"
|
|
4
|
+
|
|
3
5
|
require_relative "asset_url"
|
|
4
6
|
|
|
5
7
|
module Klenod
|
|
6
8
|
module Runtime
|
|
9
|
+
# `transformed_hash` is the SHA256 hex digest of `source`, the transformed
|
|
10
|
+
# module source. It is computed when omitted, e.g. for older bundles.
|
|
7
11
|
ModuleSpec =
|
|
8
|
-
Data.define(:id, :source_path, :source, :imports, :source_map, :version, :constant_name)
|
|
12
|
+
Data.define(:id, :source_path, :source, :imports, :source_map, :version, :constant_name, :transformed_hash) do
|
|
13
|
+
def initialize(transformed_hash: nil, **fields)
|
|
14
|
+
transformed_hash ||= Digest::SHA256.hexdigest(fields.fetch(:source))
|
|
15
|
+
super
|
|
16
|
+
end
|
|
17
|
+
end
|
|
9
18
|
|
|
10
19
|
ImportSpec = Data.define(:target_id, :value, :eager)
|
|
11
20
|
DefaultImport = Data.define(:name)
|
|
@@ -28,12 +37,12 @@ module Klenod
|
|
|
28
37
|
class Bundle
|
|
29
38
|
attr_reader :entrypoints, :modules, :assets, :source_root, :base, :asset_origin, :namespace
|
|
30
39
|
|
|
31
|
-
def self.load(source, source_root: nil)
|
|
32
|
-
BundleFormat.load(source, source_root: source_root)
|
|
40
|
+
def self.load(source, source_root: nil, namespace: Module.new)
|
|
41
|
+
BundleFormat.load(source, source_root: source_root, namespace: namespace)
|
|
33
42
|
end
|
|
34
43
|
|
|
35
|
-
def self.load_file(path, source_root: nil)
|
|
36
|
-
load(path, source_root: source_root)
|
|
44
|
+
def self.load_file(path, source_root: nil, namespace: Module.new)
|
|
45
|
+
load(path, source_root: source_root, namespace: namespace)
|
|
37
46
|
end
|
|
38
47
|
|
|
39
48
|
def initialize(entrypoints, modules, assets, source_root: nil, base: AssetUrl::DEFAULT_BASE, namespace: Module.new)
|
|
@@ -147,16 +156,24 @@ module Klenod
|
|
|
147
156
|
@mods = {}
|
|
148
157
|
end
|
|
149
158
|
|
|
159
|
+
def namespace=(namespace)
|
|
160
|
+
@namespace = namespace
|
|
161
|
+
@mods = {}
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# A named namespace is dumped by reference, so the loading process must
|
|
165
|
+
# define the same constant. Anonymous namespaces cannot be dumped and are
|
|
166
|
+
# replaced with a fresh anonymous module.
|
|
150
167
|
def marshal_dump
|
|
151
|
-
[@entrypoints, @modules, @assets, @source_root, @base]
|
|
168
|
+
[@entrypoints, @modules, @assets, @source_root, @base, (@namespace if @namespace.name)]
|
|
152
169
|
end
|
|
153
170
|
|
|
154
171
|
def marshal_load(data)
|
|
155
|
-
@entrypoints, @modules, assets, @source_root, base = data
|
|
172
|
+
@entrypoints, @modules, assets, @source_root, base, namespace = data
|
|
156
173
|
@base = AssetUrl.normalize(base)
|
|
157
174
|
@asset_origin = AssetUrl.origin(@base)
|
|
158
175
|
@assets = bind_asset_urls(assets)
|
|
159
|
-
@namespace = Module.new
|
|
176
|
+
@namespace = namespace || Module.new
|
|
160
177
|
@mods = {}
|
|
161
178
|
end
|
|
162
179
|
|
|
@@ -21,16 +21,16 @@ module Klenod
|
|
|
21
21
|
MAGIC + JSON.generate(payload_for(bundle))
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
def load(source, source_root: nil)
|
|
25
|
-
load_bytes(read_source(source), source_root: source_root)
|
|
24
|
+
def load(source, source_root: nil, namespace: Module.new)
|
|
25
|
+
load_bytes(read_source(source), source_root: source_root, namespace: namespace)
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
def load_bytes(bytes, source_root: nil)
|
|
28
|
+
def load_bytes(bytes, source_root: nil, namespace: Module.new)
|
|
29
29
|
raise BundleFormatError, "Invalid Klenod bundle header" unless bytes.start_with?(MAGIC)
|
|
30
30
|
|
|
31
31
|
body = bytes.byteslice(MAGIC.bytesize, bytes.bytesize - MAGIC.bytesize)
|
|
32
32
|
payload = JSON.parse(body)
|
|
33
|
-
bundle_from_payload(payload, source_root: source_root)
|
|
33
|
+
bundle_from_payload(payload, source_root: source_root, namespace: namespace)
|
|
34
34
|
rescue JSON::ParserError => error
|
|
35
35
|
raise BundleFormatError, "Invalid Klenod bundle JSON: #{error.message}"
|
|
36
36
|
end
|
|
@@ -47,7 +47,7 @@ module Klenod
|
|
|
47
47
|
}
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
-
def bundle_from_payload(payload, source_root: nil)
|
|
50
|
+
def bundle_from_payload(payload, source_root: nil, namespace: Module.new)
|
|
51
51
|
validate_payload!(payload)
|
|
52
52
|
|
|
53
53
|
bundle =
|
|
@@ -56,7 +56,8 @@ module Klenod
|
|
|
56
56
|
decode_modules(payload.fetch("modules")),
|
|
57
57
|
decode_assets(payload.fetch("assets")),
|
|
58
58
|
source_root: decode_value(payload["source_root"]),
|
|
59
|
-
base: payload.key?("base") ? payload.fetch("base") : AssetUrl::DEFAULT_BASE
|
|
59
|
+
base: payload.key?("base") ? payload.fetch("base") : AssetUrl::DEFAULT_BASE,
|
|
60
|
+
namespace: namespace
|
|
60
61
|
)
|
|
61
62
|
bundle.source_root = source_root if source_root
|
|
62
63
|
bundle
|
|
@@ -90,7 +91,8 @@ module Klenod
|
|
|
90
91
|
"imports" => encode_imports(spec.imports),
|
|
91
92
|
"source_map" => encode_source_map(spec.source_map),
|
|
92
93
|
"version" => spec.version,
|
|
93
|
-
"constant_name" => spec.constant_name
|
|
94
|
+
"constant_name" => spec.constant_name,
|
|
95
|
+
"transformed_hash" => spec.transformed_hash
|
|
94
96
|
}
|
|
95
97
|
]
|
|
96
98
|
end
|
|
@@ -108,7 +110,8 @@ module Klenod
|
|
|
108
110
|
decode_imports(spec_payload.fetch("imports")),
|
|
109
111
|
decode_source_map(spec_payload["source_map"], spec_payload.fetch("source")),
|
|
110
112
|
spec_payload.fetch("version"),
|
|
111
|
-
spec_payload.fetch("constant_name")
|
|
113
|
+
spec_payload.fetch("constant_name"),
|
|
114
|
+
spec_payload["transformed_hash"]
|
|
112
115
|
)
|
|
113
116
|
]
|
|
114
117
|
end
|
data/lib/klenod/runtime.rb
CHANGED
|
@@ -12,18 +12,18 @@ module Klenod
|
|
|
12
12
|
module Runtime
|
|
13
13
|
EXECUTABLE_BUNDLE_MARKER = "\n__END__\n".b.freeze
|
|
14
14
|
|
|
15
|
-
def self.load_bundle(source, source_root: nil)
|
|
16
|
-
Bundle.load(source, source_root: source_root)
|
|
15
|
+
def self.load_bundle(source, source_root: nil, namespace: Module.new)
|
|
16
|
+
Bundle.load(source, source_root: source_root, namespace: namespace)
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
def self.load_bundle_in_box(source, source_root: nil, box: nil)
|
|
19
|
+
def self.load_bundle_in_box(source, source_root: nil, box: nil, namespace: Module.new)
|
|
20
20
|
unless defined?(Ruby::Box) && Ruby::Box.enabled?
|
|
21
21
|
raise "Ruby::Box is disabled. Set RUBY_BOX=1 environment variable to use Ruby::Box."
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
bytes = source.respond_to?(:read) ? source.read : File.binread(source)
|
|
25
25
|
box = prepare_box(box)
|
|
26
|
-
box::Klenod::Runtime::BundleFormat.load_bytes(bytes, source_root: source_root)
|
|
26
|
+
box::Klenod::Runtime::BundleFormat.load_bytes(bytes, source_root: source_root, namespace: namespace)
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def self.prepare_box(box = nil)
|
|
@@ -41,13 +41,13 @@ module Klenod
|
|
|
41
41
|
box::Klenod.const_defined?(:Runtime, false)
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
def self.load_executable_bundle(path, source_root: nil)
|
|
44
|
+
def self.load_executable_bundle(path, source_root: nil, namespace: Module.new)
|
|
45
45
|
bytes = File.binread(path)
|
|
46
46
|
marker_index = bytes.index(EXECUTABLE_BUNDLE_MARKER)
|
|
47
47
|
raise ArgumentError, "Missing __END__ marker in executable bundle: #{path}" unless marker_index
|
|
48
48
|
|
|
49
49
|
payload = bytes.byteslice(marker_index + EXECUTABLE_BUNDLE_MARKER.bytesize, bytes.bytesize)
|
|
50
|
-
BundleFormat.load_bytes(payload, source_root: source_root)
|
|
50
|
+
BundleFormat.load_bytes(payload, source_root: source_root, namespace: namespace)
|
|
51
51
|
end
|
|
52
52
|
end
|
|
53
53
|
end
|