isomorfeus-preact 10.6.35 → 10.6.39
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/isomorfeus/preact/config.rb +1 -1
- data/lib/isomorfeus/preact_view_helper.rb +93 -101
- data/lib/isomorfeus/ssr.rb +75 -0
- data/lib/isomorfeus/top_level.rb +2 -24
- data/lib/isomorfeus/top_level_ssr.rb +23 -0
- data/lib/isomorfeus-preact.rb +1 -0
- data/lib/isomorfeus_preact/lucid_component/app_store_proxy.rb +4 -9
- data/lib/isomorfeus_preact/lucid_component/class_store_proxy.rb +4 -11
- data/lib/isomorfeus_preact/lucid_component/initializer.rb +2 -2
- data/lib/isomorfeus_preact/lucid_func/initializer.rb +1 -1
- data/lib/preact/version.rb +1 -1
- data/lib/preact.rb +8 -9
- metadata +10 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b4f34a628322571ed50c6923c8b129c750ce09b90953a9e4512f609e4424efa
|
4
|
+
data.tar.gz: b9e99d2865e4c14e451b22b0c3f993b3500c724a26e4c5fb66f3213385c15ac1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d00ca6d3d6f0a21954627f9c0204617abf73729b1c7f1b89976e4273d9f8080a7a532d8dfdd53d6248c91593910698ed2c695630373c21a42229592282fa6f73
|
7
|
+
data.tar.gz: 3d653b10253888d69175a077959a8d45f9672a8e5f540e3f97e53efebebe2b5b829ea6436fdd598962e229b69862b868bc493c74cb092e7ed50fd188b79e20a1
|
@@ -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, refresh: false)
|
8
8
|
key = "#{component_name}#{props}#{asset}"
|
9
|
-
if Isomorfeus.
|
9
|
+
if !Isomorfeus.development? && !refresh
|
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
|
-
|
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
|
-
|
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
|
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
|
90
59
|
rescue Exception => e
|
91
60
|
Isomorfeus.raise_error(error: e)
|
92
61
|
end
|
93
|
-
|
94
|
-
|
95
|
-
pass
|
96
|
-
first_pass_finished, exception =
|
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.
|
103
|
-
first_pass_finished =
|
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
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
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
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
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, still_busy, exception = Isomorfeus.ssr_contexts[thread_id_asset].exec(javascript)
|
153
|
-
break if pass >= max_passes
|
154
124
|
end
|
155
|
-
|
156
|
-
|
157
|
-
|
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
|
-
|
202
|
-
|
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="](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
|
data/lib/isomorfeus/top_level.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Isomorfeus
|
2
2
|
class TopLevel
|
3
3
|
class << self
|
4
|
-
if on_browser?
|
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
|
-
|
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
|
data/lib/isomorfeus-preact.rb
CHANGED
@@ -1,10 +1,7 @@
|
|
1
1
|
module LucidComponent
|
2
2
|
class AppStoreProxy
|
3
|
-
def initialize(
|
4
|
-
|
5
|
-
@native = component_instance.to_n
|
6
|
-
@component_instance = component_instance
|
7
|
-
end
|
3
|
+
def initialize(native)
|
4
|
+
@native = native
|
8
5
|
end
|
9
6
|
|
10
7
|
def [](key)
|
@@ -22,10 +19,8 @@ module LucidComponent
|
|
22
19
|
Isomorfeus.store.collect_and_defer_dispatch(action)
|
23
20
|
else
|
24
21
|
# check if we have a component local state value
|
25
|
-
if
|
26
|
-
|
27
|
-
return @native.JS[:props].JS[:iso_store].JS[:application_state].JS[key]
|
28
|
-
end
|
22
|
+
if `#@native?.props?.iso_store?.application_state?.hasOwnProperty?.(key)`
|
23
|
+
return `#@native.props.iso_store.application_state[key]`
|
29
24
|
else
|
30
25
|
return AppStore[key]
|
31
26
|
end
|
@@ -1,11 +1,8 @@
|
|
1
1
|
module LucidComponent
|
2
2
|
class ClassStoreProxy
|
3
|
-
def initialize(component_name,
|
3
|
+
def initialize(component_name, native = nil)
|
4
4
|
@component_name = component_name
|
5
|
-
|
6
|
-
@native = native
|
7
|
-
@component_instance = component_instance
|
8
|
-
end
|
5
|
+
@native = native
|
9
6
|
end
|
10
7
|
|
11
8
|
def [](key)
|
@@ -24,12 +21,8 @@ module LucidComponent
|
|
24
21
|
else
|
25
22
|
# get class state
|
26
23
|
# check if we have a component local state value
|
27
|
-
if
|
28
|
-
|
29
|
-
@native.JS[:props].JS[:iso_store].JS[:class_state].JS[@component_name] &&
|
30
|
-
@native.JS[:props].JS[:iso_store].JS[:class_state].JS[@component_name].JS.hasOwnProperty(key)
|
31
|
-
return @native.JS[:props].JS[:iso_store].JS[:class_state].JS[@component_name].JS[key]
|
32
|
-
end
|
24
|
+
if `#@native?.props?.iso_store?.class_state?.[#@component_name]?.hasOwnProperty?.(key)`
|
25
|
+
return `#@native.props.iso_store.class_state[#@component_name][key]`
|
33
26
|
else
|
34
27
|
a_state = Isomorfeus.store.get_state
|
35
28
|
if a_state.key?(:class_state) && a_state[:class_state].key?(@component_name) && a_state[:class_state][@component_name].key?(key)
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module LucidComponent::Initializer
|
2
2
|
def initialize(native_component)
|
3
3
|
@native = native_component
|
4
|
-
@app_store = LucidComponent::AppStoreProxy.new(
|
5
|
-
@class_store = LucidComponent::ClassStoreProxy.new(self.class.to_s,
|
4
|
+
@app_store = LucidComponent::AppStoreProxy.new(@native)
|
5
|
+
@class_store = LucidComponent::ClassStoreProxy.new(self.class.to_s, @native)
|
6
6
|
@props = `Opal.Preact.Props.$new(#@native)`
|
7
7
|
@state = `Opal.Preact.State.$new(#@native)`
|
8
8
|
end
|
@@ -3,6 +3,6 @@ module LucidFunc::Initializer
|
|
3
3
|
self.JS[:native_props] = `{ props: null }`
|
4
4
|
@native_props = `Opal.Preact.Props.$new(#{self})`
|
5
5
|
@app_store = LucidComponent::AppStoreProxy.new(self)
|
6
|
-
@class_store = LucidComponent::ClassStoreProxy.new(self.class.to_s, self
|
6
|
+
@class_store = LucidComponent::ClassStoreProxy.new(self.class.to_s, self)
|
7
7
|
end
|
8
8
|
end
|
data/lib/preact/version.rb
CHANGED
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(
|
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,19 +209,17 @@ 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(
|
212
|
+
operabu[operabu.length - 1].push(oper.createElement.apply(this, [component, native_props].concat(children)));
|
212
213
|
} else {
|
213
|
-
operabu[operabu.length - 1].push(
|
214
|
+
operabu[operabu.length - 1].push(oper.createElement(component, native_props));
|
214
215
|
}
|
215
216
|
};
|
216
217
|
|
217
218
|
self.deep_force_update = function(vnode) {
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
self.deep_force_update(vnode.__k[i]);
|
223
|
-
}
|
219
|
+
vnode?.__c?.forceUpdate?.();
|
220
|
+
if (vnode?.__k) {
|
221
|
+
for (let i=0; i<vnode.__k.length; i++) {
|
222
|
+
self.deep_force_update(vnode.__k[i]);
|
224
223
|
}
|
225
224
|
}
|
226
225
|
};
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: isomorfeus-preact
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 10.6.
|
4
|
+
version: 10.6.39
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jan Biedermann
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-02-
|
11
|
+
date: 2022-02-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -86,42 +86,42 @@ dependencies:
|
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: 0.14.
|
89
|
+
version: 0.14.15
|
90
90
|
type: :runtime
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: 0.14.
|
96
|
+
version: 0.14.15
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: isomorfeus-redux
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: 4.1.
|
103
|
+
version: 4.1.18
|
104
104
|
type: :runtime
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: 4.1.
|
110
|
+
version: 4.1.18
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: isomorfeus-speednode
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: 0.
|
117
|
+
version: 0.5.2
|
118
118
|
type: :runtime
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: 0.
|
124
|
+
version: 0.5.2
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: dalli
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -232,7 +232,9 @@ files:
|
|
232
232
|
- lib/isomorfeus/preact_view_helper.rb
|
233
233
|
- lib/isomorfeus/props/validate_hash_proxy.rb
|
234
234
|
- lib/isomorfeus/props/validator.rb
|
235
|
+
- lib/isomorfeus/ssr.rb
|
235
236
|
- lib/isomorfeus/top_level.rb
|
237
|
+
- lib/isomorfeus/top_level_ssr.rb
|
236
238
|
- lib/isomorfeus_preact/lucid_app/api.rb
|
237
239
|
- lib/isomorfeus_preact/lucid_app/base.rb
|
238
240
|
- lib/isomorfeus_preact/lucid_app/mixin.rb
|