isomorfeus-preact 10.6.33 → 10.6.37

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/lib/isomorfeus/preact/config.rb +1 -1
  3. data/lib/isomorfeus/preact_view_helper.rb +92 -100
  4. data/lib/isomorfeus/ssr.rb +75 -0
  5. data/lib/isomorfeus/top_level.rb +2 -24
  6. data/lib/isomorfeus/top_level_ssr.rb +23 -0
  7. data/lib/isomorfeus-preact.rb +1 -0
  8. data/lib/isomorfeus_preact/lucid_component/api.rb +0 -1
  9. data/lib/isomorfeus_preact/lucid_component/initializer.rb +0 -1
  10. data/lib/isomorfeus_preact/lucid_func/initializer.rb +0 -1
  11. data/lib/lucid_app/context.rb +1 -1
  12. data/lib/nano_css.rb +10 -10
  13. data/lib/preact/version.rb +1 -1
  14. data/lib/preact.rb +4 -3
  15. data/node_modules/.package-lock.json +3 -3
  16. data/node_modules/preact/compat/LICENSE +21 -0
  17. data/node_modules/preact/compat/jsx-dev-runtime.js +2 -0
  18. data/node_modules/preact/compat/jsx-dev-runtime.mjs +2 -0
  19. data/node_modules/preact/compat/jsx-runtime.js +2 -0
  20. data/node_modules/preact/compat/jsx-runtime.mjs +2 -0
  21. data/node_modules/preact/debug/LICENSE +21 -0
  22. data/node_modules/preact/devtools/LICENSE +21 -0
  23. data/node_modules/preact/devtools/dist/devtools.js +1 -1
  24. data/node_modules/preact/devtools/dist/devtools.js.map +1 -1
  25. data/node_modules/preact/devtools/dist/devtools.mjs +1 -1
  26. data/node_modules/preact/devtools/dist/devtools.module.js +1 -1
  27. data/node_modules/preact/devtools/dist/devtools.module.js.map +1 -1
  28. data/node_modules/preact/devtools/dist/devtools.umd.js +1 -1
  29. data/node_modules/preact/devtools/dist/devtools.umd.js.map +1 -1
  30. data/node_modules/preact/devtools/src/devtools.js +1 -1
  31. data/node_modules/preact/dist/preact.js +1 -1
  32. data/node_modules/preact/dist/preact.js.map +1 -1
  33. data/node_modules/preact/dist/preact.min.js +1 -1
  34. data/node_modules/preact/dist/preact.min.js.map +1 -1
  35. data/node_modules/preact/dist/preact.mjs +1 -1
  36. data/node_modules/preact/dist/preact.module.js +1 -1
  37. data/node_modules/preact/dist/preact.module.js.map +1 -1
  38. data/node_modules/preact/dist/preact.umd.js +1 -1
  39. data/node_modules/preact/dist/preact.umd.js.map +1 -1
  40. data/node_modules/preact/hooks/LICENSE +21 -0
  41. data/node_modules/preact/jsx-runtime/LICENSE +21 -0
  42. data/node_modules/preact/package.json +1 -1
  43. data/node_modules/preact/src/diff/index.js +6 -3
  44. data/package.json +1 -1
  45. metadata +15 -9
  46. data/lib/isomorfeus_preact/lucid_component/instance_store_proxy.rb +0 -44
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dc07c6bee9a5ccb2910f7c5d9d6ecfa419a398cffd823750f05dbc34080fc93d
4
- data.tar.gz: e4b629929b8140883f1e199d47e7b8d050f46b1cd864d4c46b8497e543003abc
3
+ metadata.gz: f82bf99a53bc67d3fd34a366579d35c1e560c6dd860e9981dca3c24e58a4bed6
4
+ data.tar.gz: c031adbcb8102d1225012d1526e602b70275b872be1b74c96828c1e53c20c78d
5
5
  SHA512:
6
- metadata.gz: e548a9592e54326e4333dadbd615106a20829063bc2417efbd55a8fb247f3f5a89627867411552a4b9b43f1092065b724140c84622444cb109f7e64dd2760043
7
- data.tar.gz: f610b788abbb7c585c44c852e51bbf3885ba97faf2424dce64ca294bce30ceb0fa739a697a286aecd664602be40a8568c4d0e976b34347593e3d725906deb3b5
6
+ metadata.gz: c238454b703626f7db793109fe26c81443e55ffe6bae3e0a717132369bcdb8854c5319bc56db2780f976b4721e1e0f26bd07ddb21cddcb04fe0d8a15bc63e4cf
7
+ data.tar.gz: 28b3a937f2e305534e7cfc038de0f76445128b58c464d6596b5de36e79d3f25f709956d34969f8e681d3780c0d2fe9e4a07d672005aba5cc205c9ab477493e15
@@ -83,7 +83,7 @@ module Isomorfeus
83
83
 
84
84
  def start_app!
85
85
  Isomorfeus.zeitwerk.setup
86
- Isomorfeus::TopLevel.mount!
86
+ Isomorfeus::TopLevel.mount! unless on_ssr?
87
87
  end
88
88
 
89
89
  def force_render
@@ -4,9 +4,9 @@ module Isomorfeus
4
4
  base.include Isomorfeus::AssetManager::ViewHelper
5
5
  end
6
6
 
7
- def cached_mount_component(component_name, props = {}, asset_key = 'ssr.js', skip_ssr: false, use_ssr: false, max_passes: 4)
7
+ def cached_mount_component(component_name, props = {}, asset_key = 'ssr.js', skip_ssr: false, use_ssr: false, max_passes: 4, force: false)
8
8
  key = "#{component_name}#{props}#{asset}"
9
- if Isomorfeus.production?
9
+ if Isomorfeus.production? && !force
10
10
  render_result, @ssr_response_status, @ssr_styles = component_cache.fetch(key)
11
11
  return render_result if render_result
12
12
  end
@@ -17,19 +17,13 @@ module Isomorfeus
17
17
  end
18
18
 
19
19
  def mount_component(component_name, props = {}, asset_key = 'ssr.js', skip_ssr: false, use_ssr: false, max_passes: 4)
20
+ ssr_start_time = Time.now if Isomorfeus.development?
20
21
  @ssr_response_status = nil
21
22
  @ssr_styles = nil
22
- thread_id_asset = "#{Thread.current.object_id}#{asset_key}"
23
23
  render_result = "<div data-iso-env=\"#{Isomorfeus.env}\" data-iso-root=\"#{component_name}\" data-iso-props='#{Oj.dump(props, mode: :strict)}'"
24
24
  if !skip_ssr && (Isomorfeus.server_side_rendering || use_ssr)
25
+ thread_id_asset = "#{Thread.current.object_id}#{asset_key}"
25
26
  if Isomorfeus.development?
26
- # always create a new context, effectively reloading code
27
- # delete the existing context first, saves memory
28
- if Isomorfeus.ssr_contexts.key?(thread_id_asset)
29
- uuid = Isomorfeus.ssr_contexts[thread_id_asset].instance_variable_get(:@uuid)
30
- runtime = Isomorfeus.ssr_contexts[thread_id_asset].instance_variable_get(:@runtime)
31
- runtime.vm.delete_context(uuid)
32
- end
33
27
  begin
34
28
  init_speednode_context(asset_key, thread_id_asset)
35
29
  rescue Exception => e
@@ -41,7 +35,7 @@ module Isomorfeus
41
35
  end
42
36
  end
43
37
 
44
- start_time = Time.now if Isomorfeus.development?
38
+ ctx = Isomorfeus.ssr_contexts[thread_id_asset]
45
39
  pass = 0
46
40
  # if location_host and scheme are given and if Transport is loaded, connect and then render,
47
41
  # otherwise do not render because only one pass is required
@@ -53,110 +47,84 @@ module Isomorfeus
53
47
  # build javascript for rendering first pass
54
48
  # it will initialize buffers to guard against leaks, maybe caused by previous exceptions
55
49
  javascript = <<~JAVASCRIPT
56
- global.Opal.Preact.render_buffer = [];
57
- global.Opal.Preact.active_components = [];
58
- global.Opal.Preact.active_redux_components = [];
59
- global.FirstPassFinished = false;
60
- global.Exception = false;
61
- global.IsomorfeusSessionId = '#{Thread.current[:isomorfeus_session_id]}';
62
- global.Opal.Isomorfeus['$env=']('#{Isomorfeus.env}');
63
- if (typeof global.Opal.Isomorfeus["$current_locale="] === 'function') {
64
- global.Opal.Isomorfeus["$current_locale="]('#{props[:locale]}');
65
- } else if (typeof global.Opal.Isomorfeus["$negotiated_locale="] === 'function') { // remove later on
66
- global.Opal.Isomorfeus["$negotiated_locale="]('#{props[:locale]}');
67
- }
68
- global.Opal.Isomorfeus['$force_init!']();
69
- global.Opal.Isomorfeus['$ssr_response_status='](200);
70
- global.Opal.Isomorfeus.TopLevel['$ssr_route_path=']('#{props[:location]}');
71
- let api_ws_path = '#{api_ws_path}';
72
- let exception;
73
- if (typeof global.Opal.Isomorfeus.Transport !== 'undefined' && api_ws_path !== '') {
74
- global.Opal.Isomorfeus.TopLevel["$transport_ws_url="]("#{transport_ws_url}");
75
- global.Opal.send(global.Opal.Isomorfeus.Transport.$promise_connect(global.IsomorfeusSessionId), 'then', [], ($$1 = function(){
76
- try {
77
- global.Opal.Isomorfeus.TopLevel.$render_component_to_string('#{component_name}', #{Oj.dump(props, mode: :strict)});
78
- global.FirstPassFinished = 'transport';
79
- } catch (e) {
80
- global.Exception = e;
81
- global.FirstPassFinished = 'transport';
82
- }
83
- }, $$1.$$s = this, $$1.$$arity = 0, $$1))
84
- return false;
85
- } else { global.FirstPassFinished = true; return true; };
50
+ return Opal.Isomorfeus.SSR.first_pass('#{Thread.current[:isomorfeus_session_id]}', '#{Isomorfeus.env}', '#{props[:locale]}', '#{props[:location]}', '#{api_ws_path}', '#{transport_ws_url}', '#{component_name}', #{Oj.dump(props, mode: :strict)})
86
51
  JAVASCRIPT
52
+
53
+ finished = false
87
54
  # execute first render pass
88
55
  begin
89
56
  pass += 1
90
- first_pass_skipped = Isomorfeus.ssr_contexts[thread_id_asset].exec(javascript)
57
+ has_transport, has_store, need_further_pass, exception = ctx.exec(javascript)
58
+ Isomorfeus.raise_error(message: "Server Side Rendering: #{exception['message']}", stack: exception['stack']) if exception
91
59
  rescue Exception => e
92
60
  Isomorfeus.raise_error(error: e)
93
61
  end
94
- # wait for first pass to finish
95
- unless first_pass_skipped
96
- first_pass_finished, exception = Isomorfeus.ssr_contexts[thread_id_asset].exec('return [global.FirstPassFinished, global.Exception ? { message: global.Exception.message, stack: global.Exception.stack } : false ]')
62
+
63
+ if has_transport
64
+ # wait for first pass to finish
65
+ first_pass_finished, need_further_pass, exception = ctx.eval_script(key: :first_pass_check)
97
66
  Isomorfeus.raise_error(message: "Server Side Rendering: #{exception['message']}", stack: exception['stack']) if exception
98
67
  unless first_pass_finished
99
68
  start_time = Time.now
100
69
  while !first_pass_finished
101
70
  break if (Time.now - start_time) > 10
102
- sleep 0.01
103
- first_pass_finished = Isomorfeus.ssr_contexts[thread_id_asset].exec('return global.FirstPassFinished')
71
+ sleep 0.005
72
+ first_pass_finished, need_further_pass, exception = ctx.eval_script(key: :first_pass_check)
73
+ Isomorfeus.raise_error(message: "Server Side Rendering: #{exception['message']}", stack: exception['stack']) if exception
104
74
  end
105
75
  end
106
- # wait for transport requests to finish
107
- if first_pass_finished == 'transport'
108
- transport_busy = Isomorfeus.ssr_contexts[thread_id_asset].exec('return global.Opal.Isomorfeus.Transport["$busy?"]()')
109
- if transport_busy
110
- start_time = Time.now
111
- while transport_busy
112
- break if (Time.now - start_time) > 5
113
- sleep 0.01
114
- transport_busy = Isomorfeus.ssr_contexts[thread_id_asset].exec('return global.Opal.Isomorfeus.Transport["$busy?"]()')
115
- end
76
+
77
+ # wait for transport to settle
78
+ transport_busy = ctx.eval_script(key: :transport_busy)
79
+ if transport_busy
80
+ start_time = Time.now
81
+ while transport_busy
82
+ break if (Time.now - start_time) > 5
83
+ sleep 0.005
84
+ transport_busy = ctx.eval_script(key: :transport_busy)
116
85
  end
117
86
  end
118
87
  end
119
- # build javascript for additional render passes
120
- # guard against leaks from first pass, maybe because of a exception
121
- javascript = <<~JAVASCRIPT
122
- global.Opal.Preact.render_buffer = [];
123
- global.Opal.Preact.active_components = [];
124
- global.Opal.Preact.active_redux_components = [];
125
- global.Exception = false;
126
- let rendered_tree;
127
- let ssr_styles;
128
- let component;
129
- try {
130
- rendered_tree = global.Opal.Isomorfeus.TopLevel.$render_component_to_string('#{component_name}', #{Oj.dump(props, mode: :strict)});
131
- } catch (e) {
132
- global.Exception = e;
133
- }
134
- let application_state = global.Opal.Isomorfeus.store.native.getState();
135
- let transport_busy = false;
136
- if (typeof global.Opal.Isomorfeus.Transport !== 'undefined' && global.Opal.Isomorfeus.Transport["$busy?"]()) { transport_busy = true; }
137
- if (typeof global.NanoCSSInstance !== 'undefined') { ssr_styles = global.NanoCSSInstance.raw }
138
- return [rendered_tree, application_state, ssr_styles, global.Opal.Isomorfeus['$ssr_response_status'](), transport_busy, global.Exception ? { message: global.Exception.message, stack: global.Exception.stack } : false];
139
- JAVASCRIPT
140
- # execute further render passes
141
- pass += 1
142
- rendered_tree, application_state, @ssr_styles, @ssr_response_status, transport_busy, exception = Isomorfeus.ssr_contexts[thread_id_asset].exec(javascript)
143
- start_time = Time.now
144
- while transport_busy
145
- break if (Time.now - start_time) > 5
146
- while transport_busy
147
- break if (Time.now - start_time) > 4
148
- sleep 0.01
149
- transport_busy = Isomorfeus.ssr_contexts[thread_id_asset].exec('return global.Opal.Isomorfeus.Transport["$busy?"]()')
88
+
89
+ if !need_further_pass
90
+ rendered_tree, application_state, @ssr_styles, @ssr_response_status, exception = ctx.eval_script(key: :first_pass_result)
91
+ Isomorfeus.raise_error(message: "Server Side Rendering: #{exception['message']}", stack: exception['stack']) if exception
92
+ else
93
+ start_time = Time.now
94
+ script_key = if has_transport && has_store
95
+ :sill_busy
96
+ elsif has_transport
97
+ :transport_busy
98
+ elsif has_store
99
+ :store_busy
100
+ else
101
+ nil
102
+ end
103
+ while need_further_pass
104
+ # execute further render passes
105
+ javascript = <<~JAVASCRIPT
106
+ return Opal.Isomorfeus.SSR.further_pass('#{component_name}', #{Oj.dump(props, mode: :strict)})
107
+ JAVASCRIPT
108
+ pass += 1
109
+ rendered_tree, application_state, @ssr_styles, @ssr_response_status, need_further_pass, exception = ctx.exec(javascript)
110
+ Isomorfeus.raise_error(message: "Server Side Rendering: #{exception['message']}", stack: exception['stack']) if exception
111
+ if need_further_pass && script_key
112
+ break if (Time.now - start_time) > 5
113
+ need_further_pass = ctx.eval_script(key: script_key)
114
+ while need_further_pass
115
+ break if (Time.now - start_time) > 4
116
+ sleep 0.01
117
+ need_further_pass = ctx.eval_script(key: script_key)
118
+ end
119
+ break if pass >= max_passes
120
+ else
121
+ break
122
+ end
150
123
  end
151
- pass += 1
152
- rendered_tree, application_state, @ssr_styles, @ssr_response_status, transport_busy, exception = Isomorfeus.ssr_contexts[thread_id_asset].exec(javascript)
153
- break if pass >= max_passes
154
124
  end
155
- javascript = <<~JAVASCRIPT
156
- if (typeof global.Opal.Isomorfeus.Transport !== 'undefined') { global.Opal.Isomorfeus.Transport.$disconnect(); }
157
- JAVASCRIPT
158
- Isomorfeus.ssr_contexts[thread_id_asset].exec(javascript)
159
- Isomorfeus.raise_error(message: exception['message'], stack: exception['stack']) if exception
125
+
126
+ ctx.eval_script(key: :transport_disconnect) if has_transport
127
+
160
128
  render_result << " data-iso-hydrated='true'" if rendered_tree
161
129
  if Isomorfeus.respond_to?(:current_user) && Isomorfeus.current_user && !Isomorfeus.current_user.anonymous?
162
130
  render_result << " data-iso-usid=#{Oj.dump(Isomorfeus.current_user.sid, mode: :strict)}"
@@ -170,10 +138,10 @@ module Isomorfeus
170
138
  render_result << " data-iso-nloc='#{props[:locale]}'>"
171
139
  end
172
140
  render_result << '</div>'
173
- if Isomorfeus.server_side_rendering
141
+ if Isomorfeus.server_side_rendering && !skip_ssr
174
142
  render_result = "<script type='application/javascript'>\nServerSideRenderingStateJSON = #{Oj.dump(application_state, mode: :strict)}\n</script>\n" << render_result
143
+ puts "PreactViewHelper Server Side Rendering rendered #{pass} passes and took ~#{((Time.now - ssr_start_time)*1000).to_i}ms" if Isomorfeus.development?
175
144
  end
176
- STDERR.puts "PreactViewHelper Server Side Rendering rendered #{pass} passes and took ~#{((Time.now - start_time)*1000).to_i}ms" if Isomorfeus.development? && !skip_ssr
177
145
  render_result
178
146
  end
179
147
 
@@ -198,8 +166,32 @@ module Isomorfeus
198
166
  def init_speednode_context(asset_key, thread_id_asset)
199
167
  asset = Isomorfeus.assets[asset_key]
200
168
  raise "#{self.class.name}: Asset not found: #{asset_key}" unless asset
201
- asset_manager.transition(asset_key, asset)
202
- Isomorfeus.ssr_contexts[thread_id_asset] = ExecJS.permissive_compile(asset.bundle)
169
+ if !Isomorfeus.ssr_contexts.key?(thread_id_asset) || !asset.bundled?
170
+ if Isomorfeus.ssr_contexts.key?(thread_id_asset)
171
+ uuid = Isomorfeus.ssr_contexts[thread_id_asset].instance_variable_get(:@uuid)
172
+ runtime = Isomorfeus.ssr_contexts[thread_id_asset].instance_variable_get(:@runtime)
173
+ runtime.vm.delete_context(uuid)
174
+ end
175
+ asset_manager.transition(asset_key, asset)
176
+ Isomorfeus.ssr_contexts[thread_id_asset] = ExecJS.permissive_compile(asset.bundle)
177
+ ctx = Isomorfeus.ssr_contexts[thread_id_asset]
178
+ ctx.exec(top_level_mod)
179
+ ctx.exec(ssr_mod)
180
+ ctx.add_script(key: :first_pass_check, source: '[global.FirstPassFinished, global.NeedFurtherPass, global.Exception ? { message: global.Exception.message, stack: global.Exception.stack } : false ]')
181
+ ctx.add_script(key: :first_pass_result, source: 'Opal.Isomorfeus.SSR.first_pass_result()')
182
+ ctx.add_script(key: :still_busy, source: 'let nfp = global.Opal.Isomorfeus.Transport["$busy?"]() || global.Opal.Isomorfeus.store["$recently_dispatched?"](); (nfp == nil) ? false : nfp;')
183
+ ctx.add_script(key: :store_busy, source: 'let nfp = global.Opal.Isomorfeus.store["$recently_dispatched?"](); (nfp == nil) ? false : nfp;')
184
+ ctx.add_script(key: :transport_busy, source: 'global.Opal.Isomorfeus.Transport["$busy?"]()')
185
+ ctx.add_script(key: :transport_disconnect, source: 'global.Opal.Isomorfeus.Transport.$disconnect()')
186
+ end
187
+ end
188
+
189
+ def ssr_mod
190
+ @_ssr_mod ||= Opal.compile(File.read(File.expand_path(File.join(File.dirname(__FILE__), 'ssr.rb'))))
191
+ end
192
+
193
+ def top_level_mod
194
+ @_top_level_mod ||= Opal.compile(File.read(File.expand_path(File.join(File.dirname(__FILE__), 'top_level_ssr.rb'))))
203
195
  end
204
196
  end
205
197
  end
@@ -0,0 +1,75 @@
1
+ module Isomorfeus
2
+ module SSR
3
+ %x{
4
+ self.first_pass = function(session_id, env, locale, location, api_ws_path, transport_ws_url, component_name, props) {
5
+ global.Opal.Preact.render_buffer = [];
6
+ global.Opal.Preact.active_components = [];
7
+ global.Opal.Preact.active_redux_components = [];
8
+ global.FirstPassFinished = false;
9
+ global.NeedFurtherPass = false;
10
+ global.RenderedTree = '';
11
+ global.Exception = false;
12
+ global.IsomorfeusSessionId = session_id;
13
+ global.HasTransport = (typeof global.Opal.Isomorfeus.Transport !== 'undefined') && (api_ws_path !== '');
14
+ global.HasStore = typeof global.Opal.Isomorfeus.store !== 'undefined';
15
+ global.Opal.Isomorfeus['$env='](env);
16
+ if (typeof global.Opal.Isomorfeus["$current_locale="] === 'function') { global.Opal.Isomorfeus["$current_locale="](''); }
17
+ global.Opal.Isomorfeus['$force_init!']();
18
+ global.Opal.Isomorfeus['$ssr_response_status='](200);
19
+ global.Opal.Isomorfeus.TopLevel['$ssr_route_path='](location);
20
+ if (global.HasTransport) {
21
+ global.Opal.Isomorfeus.TopLevel["$transport_ws_url="](transport_ws_url);
22
+ global.Opal.send(global.Opal.Isomorfeus.Transport.$promise_connect(global.IsomorfeusSessionId), 'then', [], ($$1 = function(){
23
+ try {
24
+ global.RenderedTree = global.Opal.Isomorfeus.TopLevel.$render_component_to_string(component_name, props);
25
+ let nfp = global.Opal.Isomorfeus.Transport["$busy?"]() || global.Opal.Isomorfeus.store['$recently_dispatched?']();
26
+ global.NeedFurtherPass = (nfp == nil) ? false : nfp;
27
+ global.FirstPassFinished = false;
28
+ } catch (e) {
29
+ global.Exception = e;
30
+ global.NeedFurtherPass = false;
31
+ }
32
+ }, $$1.$$s = this, $$1.$$arity = 0, $$1))
33
+ } else {
34
+ try {
35
+ global.RenderedTree = global.Opal.Isomorfeus.TopLevel.$render_component_to_string(component_name, props);
36
+ if (global.HasStore) {
37
+ let nfp = global.Opal.Isomorfeus.store['$recently_dispatched?']();
38
+ global.NeedFurtherPass = (nfp == nil) ? false : nfp;
39
+ }
40
+ } catch (e) {
41
+ global.Exception = e;
42
+ global.NeedFurtherPass = false;
43
+ }
44
+ };
45
+ return [global.HasTransport, global.HasStore, global.NeedFurtherPass, global.Exception ? { message: global.Exception.message, stack: global.Exception.stack } : false];
46
+ }
47
+
48
+ self.first_pass_result = function() {
49
+ let ssr_styles;
50
+ let application_state = global.Opal.Isomorfeus.store.native.getState();
51
+ if (typeof global.NanoCSSInstance !== 'undefined') { ssr_styles = global.NanoCSSInstance.raw }
52
+ return [global.RenderedTree, application_state, ssr_styles, global.Opal.Isomorfeus['$ssr_response_status'](), global.Exception ? { message: global.Exception.message, stack: global.Exception.stack } : false];
53
+ }
54
+
55
+ self.further_pass = function(component_name, props) {
56
+ global.Opal.Preact.render_buffer = [];
57
+ global.Opal.Preact.active_components = [];
58
+ global.Opal.Preact.active_redux_components = [];
59
+ global.Exception = false;
60
+ let rendered_tree;
61
+ let ssr_styles;
62
+ try {
63
+ rendered_tree = global.Opal.Isomorfeus.TopLevel.$render_component_to_string(component_name, props);
64
+ } catch (e) {
65
+ global.Exception = e;
66
+ }
67
+ let application_state = global.Opal.Isomorfeus.store.native.getState();
68
+ if (typeof global.NanoCSSInstance !== 'undefined') { ssr_styles = global.NanoCSSInstance.raw }
69
+ let nfp = (global.HasTransport && global.Opal.Isomorfeus.Transport["$busy?"]()) || (global.HasStore && global.Opal.Isomorfeus.store["$recently_dispatched?"]());
70
+ global.NeedFurtherPass = (nfp == nil) ? false : nfp;
71
+ return [rendered_tree, application_state, ssr_styles, global.Opal.Isomorfeus['$ssr_response_status'](), global.NeedFurtherPass, global.Exception ? { message: global.Exception.message, stack: global.Exception.stack } : false];
72
+ }
73
+ }
74
+ end
75
+ end
@@ -1,7 +1,7 @@
1
1
  module Isomorfeus
2
2
  class TopLevel
3
3
  class << self
4
- if on_browser? # execution environment
4
+ if on_browser?
5
5
  def mount!
6
6
  Isomorfeus.init
7
7
  Isomorfeus::TopLevel.on_ready do
@@ -94,29 +94,7 @@ module Isomorfeus
94
94
  hydrated ? Preact.hydrate(top, element) : Preact.render(top, element)
95
95
  Isomorfeus.top_component = top
96
96
  end
97
- else # execution environment
98
- attr_accessor :ssr_route_path
99
- attr_accessor :transport_ws_url
100
-
101
- def mount!
102
- # nothing, but keep it for compatibility with browser
103
- end
104
-
105
- def render_component_to_string(component_name, props)
106
- component = nil
107
- %x{
108
- if (typeof component_name === 'string' || component_name instanceof String) {
109
- component = component_name.split(".").reduce(function(o, x) {
110
- return (o !== null && typeof o[x] !== "undefined" && o[x] !== null) ? o[x] : null;
111
- }, Opal.global)
112
- } else {
113
- component = component_name;
114
- }
115
- }
116
- component = Isomorfeus.cached_component_class(component_name) unless component
117
- Preact.render_to_string(Preact.create_element(component, `Opal.Hash.$new(props)`))
118
- end
119
- end # execution environment
97
+ end
120
98
  end
121
99
  end
122
100
  end
@@ -0,0 +1,23 @@
1
+ module Isomorfeus
2
+ class TopLevel
3
+ class << self
4
+ attr_accessor :ssr_route_path
5
+ attr_accessor :transport_ws_url
6
+
7
+ def render_component_to_string(component_name, props)
8
+ component = nil
9
+ %x{
10
+ if (typeof component_name === 'string' || component_name instanceof String) {
11
+ component = component_name.split(".").reduce(function(o, x) {
12
+ return (o !== null && typeof o[x] !== "undefined" && o[x] !== null) ? o[x] : null;
13
+ }, Opal.global)
14
+ } else {
15
+ component = component_name;
16
+ }
17
+ }
18
+ component = Isomorfeus.cached_component_class(component_name) unless component
19
+ Preact.render_to_string(Preact.create_element(component, `Opal.Hash.$new(props)`))
20
+ end
21
+ end
22
+ end
23
+ end
@@ -81,6 +81,7 @@ else
81
81
  require 'uri'
82
82
  require 'oj'
83
83
  require 'opal'
84
+ require 'opal/compiler'
84
85
  require 'opal-activesupport'
85
86
  require 'opal-zeitwerk'
86
87
  require 'isomorfeus-speednode'
@@ -4,7 +4,6 @@ module LucidComponent::Api
4
4
  # stores
5
5
  attr_accessor :app_store
6
6
  attr_accessor :class_store
7
- attr_accessor :store
8
7
 
9
8
  def class_store
10
9
  @class_store ||= ::LucidComponent::ClassStoreProxy.new(self.to_s)
@@ -3,7 +3,6 @@ module LucidComponent::Initializer
3
3
  @native = native_component
4
4
  @app_store = LucidComponent::AppStoreProxy.new(self)
5
5
  @class_store = LucidComponent::ClassStoreProxy.new(self.class.to_s, self, @native)
6
- @store = LucidComponent::InstanceStoreProxy.new(self)
7
6
  @props = `Opal.Preact.Props.$new(#@native)`
8
7
  @state = `Opal.Preact.State.$new(#@native)`
9
8
  end
@@ -4,6 +4,5 @@ module LucidFunc::Initializer
4
4
  @native_props = `Opal.Preact.Props.$new(#{self})`
5
5
  @app_store = LucidComponent::AppStoreProxy.new(self)
6
6
  @class_store = LucidComponent::ClassStoreProxy.new(self.class.to_s, self, self)
7
- @store = LucidComponent::InstanceStoreProxy.new(self)
8
7
  end
9
8
  end
@@ -5,7 +5,7 @@ module LucidApp
5
5
  css_server = `null`
6
6
  css_server = `document.getElementById('css-server-side')` unless on_ssr?
7
7
  %x{
8
- n = Opal.NanoCSS;
8
+ let n = Opal.NanoCSS;
9
9
  nano_css = (css_server) ? n.create({ sh: css_server }) : n.create();
10
10
  n.rule(nano_css);
11
11
  n.sheet(nano_css);
data/lib/nano_css.rb CHANGED
@@ -1,22 +1,22 @@
1
1
  module NanoCSS
2
2
  %x{
3
3
  var KEBAB_REGEX = /[A-Z]/g;
4
+ var on_browser = #{on_browser?};
5
+ var in_dev = #{Isomorfeus.development?};
4
6
 
5
7
  function hash(str) {
6
8
  var h = 5381, i = str.length;
7
9
  while (i) h = (h * 33) ^ str.charCodeAt(--i);
8
10
  return '_' + (h >>> 0).toString(36);
9
11
  };
10
- }
11
12
 
12
- %x{
13
13
  self.create = function (config) {
14
14
  config = config || {};
15
15
  var assign = config.assign || Object.assign;
16
16
  var client = typeof window === 'object';
17
17
 
18
18
  // Check if we are really in browser environment.
19
- if (process.env.NODE_ENV !== 'production') {
19
+ if (on_browser && in_dev) {
20
20
  if (client) {
21
21
  if ((typeof document !== 'object') || !document.getElementsByTagName('HTML')) {
22
22
  console.error('nano-css detected browser environment because of "window" global, but "document" global seems to be defective.');
@@ -47,7 +47,7 @@ module NanoCSS
47
47
  if (renderer.client) {
48
48
  if (!renderer.sh) { document.head.appendChild(renderer.sh = document.createElement('style')); }
49
49
 
50
- if (process.env.NODE_ENV !== 'production') {
50
+ if (in_dev) {
51
51
  renderer.sh.setAttribute('data-nano-css-dev', '');
52
52
 
53
53
  // Test style sheet used in DEV mode to test if .insetRule() would throw.
@@ -60,7 +60,7 @@ module NanoCSS
60
60
  // .insertRule() is faster than .appendChild(), that's why we use it in PROD.
61
61
  // But CSS injected using .insertRule() is not displayed in Chrome Devtools
62
62
  var sheet = renderer.sh.sheet;
63
- if (process.env.NODE_ENV === 'production') {
63
+ if (!in_dev) {
64
64
  // Unknown pseudo-selectors will throw, this try/catch swallows all errors.
65
65
  try { sheet.insertRule(rawCssRule, sheet.cssRules.length); }
66
66
  catch (error) {}
@@ -91,7 +91,7 @@ module NanoCSS
91
91
  if ((value instanceof Object) && !(value instanceof Array)) {
92
92
  postponed.push(prop);
93
93
  } else {
94
- if ((process.env.NODE_ENV !== 'production') && !renderer.sourcemaps) {
94
+ if (in_dev && !renderer.sourcemaps) {
95
95
  str += ' ' + renderer.decl(prop, value, selector, atrule) + '\n';
96
96
  } else {
97
97
  str += renderer.decl(prop, value, selector, atrule);
@@ -100,7 +100,7 @@ module NanoCSS
100
100
  }
101
101
 
102
102
  if (str) {
103
- if ((process.env.NODE_ENV !== 'production') && !renderer.sourcemaps) {
103
+ if (in_dev && !renderer.sourcemaps) {
104
104
  str = '\n' + selector + ' {\n' + str + '}\n';
105
105
  } else {
106
106
  str = selector + '{' + str + '}';
@@ -129,7 +129,7 @@ module NanoCSS
129
129
 
130
130
  %x{
131
131
  self.rule = function (renderer) {
132
- if (process.env.NODE_ENV !== 'production') {
132
+ if (in_dev) {
133
133
  renderer.rule_blocks = {};
134
134
  }
135
135
 
@@ -142,7 +142,7 @@ module NanoCSS
142
142
 
143
143
  renderer.rule = function (css, block) {
144
144
  // Warn user if CSS selectors clash.
145
- if (process.env.NODE_ENV !== 'production') {
145
+ if (in_dev) {
146
146
  if (block) {
147
147
  if (typeof block !== 'string') {
148
148
  throw new TypeError(
@@ -194,7 +194,7 @@ module NanoCSS
194
194
  var onElementModifier = function (elementModifier) {
195
195
  var styles = map[elementModifier];
196
196
 
197
- if ((process.env.NODE_ENV !== 'production') && renderer.sourcemaps) {
197
+ if (in_dev && renderer.sourcemaps) {
198
198
  // In dev mode emit CSS immediately to generate sourcemaps.
199
199
  result[elementModifier] = renderer.rule(styles, block + '-' + elementModifier);
200
200
  } else {
@@ -1,3 +1,3 @@
1
1
  module Preact
2
- VERSION = '10.6.33'
2
+ VERSION = '10.6.37'
3
3
  end
data/lib/preact.rb CHANGED
@@ -196,11 +196,12 @@ module Preact
196
196
  };
197
197
 
198
198
  self.internal_render = function(component, props, string_child, block) {
199
+ const oper = Opal.global.Preact;
199
200
  const operabu = self.render_buffer;
200
201
  let native_props;
201
202
  if (props && props !== nil) { native_props = self.to_native_preact_props(props); }
202
203
  if (string_child) {
203
- operabu[operabu.length - 1].push(Opal.global.Preact.createElement(component, native_props, string_child));
204
+ operabu[operabu.length - 1].push(oper.createElement(component, native_props, string_child));
204
205
  } else if (block && block !== nil) {
205
206
  operabu.push([]);
206
207
  // console.log("internal_render pushed", Opal.Preact.render_buffer, Opal.Preact.render_buffer.toString());
@@ -208,9 +209,9 @@ module Preact
208
209
  if (block_result && block_result !== nil) { Opal.Preact.render_block_result(block_result); }
209
210
  // console.log("internal_render popping", Opal.Preact.render_buffer, Opal.Preact.render_buffer.toString());
210
211
  let children = operabu.pop();
211
- operabu[operabu.length - 1].push(Opal.global.Preact.createElement.apply(this, [component, native_props].concat(children)));
212
+ operabu[operabu.length - 1].push(oper.createElement.apply(this, [component, native_props].concat(children)));
212
213
  } else {
213
- operabu[operabu.length - 1].push(Opal.global.Preact.createElement(component, native_props));
214
+ operabu[operabu.length - 1].push(oper.createElement(component, native_props));
214
215
  }
215
216
  };
216
217
 
@@ -4,9 +4,9 @@
4
4
  "requires": true,
5
5
  "packages": {
6
6
  "node_modules/preact": {
7
- "version": "10.6.5",
8
- "resolved": "https://registry.npmjs.org/preact/-/preact-10.6.5.tgz",
9
- "integrity": "sha512-i+LXM6JiVjQXSt2jG2vZZFapGpCuk1fl8o6ii3G84MA3xgj686FKjs4JFDkmUVhtxyq21+4ay74zqPykz9hU6w==",
7
+ "version": "10.6.6",
8
+ "resolved": "https://registry.npmjs.org/preact/-/preact-10.6.6.tgz",
9
+ "integrity": "sha512-dgxpTFV2vs4vizwKohYKkk7g7rmp1wOOcfd4Tz3IB3Wi+ivZzsn/SpeKJhRENSE+n8sUfsAl4S3HiCVT923ABw==",
10
10
  "funding": {
11
11
  "type": "opencollective",
12
12
  "url": "https://opencollective.com/preact"
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015-present Jason Miller
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1 +1,3 @@
1
+ require('preact/compat');
2
+
1
3
  module.exports = require('preact/jsx-runtime');
@@ -1 +1,3 @@
1
+ import 'preact/compat';
2
+
1
3
  export * from 'preact/jsx-runtime';
@@ -1 +1,3 @@
1
+ require('preact/compat');
2
+
1
3
  module.exports = require('preact/jsx-runtime');