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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ec22e411f49459149641d8ea8b1aaa0a55e619c4c45e4d34a189b0ff0f4fcb9b
4
- data.tar.gz: d800fd32dc4db55d8595fb0227f62de71860c8da8048c2fa7dd8dae2ef38efce
3
+ metadata.gz: d9f47b3f5b7633bc5266d7d84b085d0712911addf1c3801257016bca575592de
4
+ data.tar.gz: 104d04cde8bc7140f8dfb719008b76ceb2355d262823067fda91253b773cded4
5
5
  SHA512:
6
- metadata.gz: ae054ac59be068695833d60a5115f16d222dc0861ecdca5f71b3b0a7568ab2ba89c4f016b9d80535867239102ca4fcea8c059290a9e48117f00c50193300a76a
7
- data.tar.gz: 60a7dff20e4563100af20037ccdfee2f940e407c512e1c7c409e5b0c37d9955e19e0b3989a5e4ce2290e9859c639d6b2198166f3215b793a756e6c654620158d
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
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Klenod
4
4
  module Runtime
5
- VERSION = "0.0.27"
5
+ VERSION = "0.0.28"
6
6
  end
7
7
  end
@@ -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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: klenod-runtime
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.27
4
+ version: 0.0.28
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrés Alin