isomorfeus-preact 22.9.0.rc9 → 22.10.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/isomorfeus_preact_ext/extconf.rb +5 -0
- data/ext/isomorfeus_preact_ext/fio-stl.h +35006 -0
- data/ext/isomorfeus_preact_ext/isomorfeus_preact_ext.c +9 -0
- data/ext/isomorfeus_preact_ext/isomorfeus_preact_ext.h +24 -0
- data/ext/isomorfeus_preact_ext/preact.c +538 -0
- data/ext/isomorfeus_preact_ext/vnode.c +91 -0
- data/lib/isomorfeus/preact/ssr.rb +0 -1
- data/lib/isomorfeus/preact/version.rb +1 -1
- data/lib/isomorfeus-preact.rb +6 -3
- data/lib/link.rb +2 -1
- data/lib/lucid_app.rb +2 -3
- data/lib/lucid_component.rb +4 -7
- data/lib/nano_css.rb +28 -35
- data/lib/preact/component.rb +1 -10
- data/lib/preact/context.rb +8 -14
- data/lib/preact/html_elements.rb +58 -0
- data/lib/preact/math_ml_elements.rb +53 -0
- data/lib/preact/{elements.rb → svg_elements.rb} +17 -31
- data/lib/preact.rb +32 -308
- data/lib/redirect.rb +2 -1
- data/lib/route.rb +3 -1
- data/lib/switch.rb +3 -1
- metadata +33 -10
@@ -0,0 +1,24 @@
|
|
1
|
+
/*
|
2
|
+
class VNode
|
3
|
+
attr_accessor :__c
|
4
|
+
attr_reader :key
|
5
|
+
attr_reader :props
|
6
|
+
attr_reader :ref
|
7
|
+
attr_reader :type
|
8
|
+
|
9
|
+
def initialize(type, props, key, ref)
|
10
|
+
@type = type
|
11
|
+
@props = props
|
12
|
+
@key = key
|
13
|
+
@ref = ref
|
14
|
+
end
|
15
|
+
end
|
16
|
+
*/
|
17
|
+
|
18
|
+
typedef struct VNode {
|
19
|
+
VALUE component;
|
20
|
+
VALUE key;
|
21
|
+
VALUE props;
|
22
|
+
VALUE ref;
|
23
|
+
VALUE type;
|
24
|
+
} VNode;
|
@@ -0,0 +1,538 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#define FIO_STR_NAME render_result
|
3
|
+
#include "fio-stl.h"
|
4
|
+
#include "isomorfeus_preact_ext.h"
|
5
|
+
|
6
|
+
static ID id_ancestors;
|
7
|
+
static ID id_checked;
|
8
|
+
static ID id_children;
|
9
|
+
static ID id_class;
|
10
|
+
static ID id_class_name;
|
11
|
+
static ID id_class_name2;
|
12
|
+
static ID id_context_id;
|
13
|
+
static ID id_context_type;
|
14
|
+
static ID id_dangerously_set_inner_html;
|
15
|
+
static ID id_default_checked;
|
16
|
+
static ID id_default_selected;
|
17
|
+
static ID id_default_value;
|
18
|
+
static ID id_development;
|
19
|
+
static ID id_downcase;
|
20
|
+
static ID id_encode_entities;
|
21
|
+
static ID id_eqeq;
|
22
|
+
static ID id_for;
|
23
|
+
static ID id_get_child_context;
|
24
|
+
static ID id_get_derived_state_from_props;
|
25
|
+
static ID id_gsub;
|
26
|
+
static ID id_html_for;
|
27
|
+
static ID id_include;
|
28
|
+
static ID id_is_a;
|
29
|
+
static ID id_is_renderable;
|
30
|
+
static ID id_key;
|
31
|
+
static ID id_keyq;
|
32
|
+
static ID id_keys;
|
33
|
+
static ID id_match;
|
34
|
+
static ID id_merge;
|
35
|
+
static ID id_new;
|
36
|
+
static ID id_props;
|
37
|
+
static ID id_ref;
|
38
|
+
static ID id_render;
|
39
|
+
static ID id_render_buffer;
|
40
|
+
static ID id_selected;
|
41
|
+
static ID id_self;
|
42
|
+
static ID id_source;
|
43
|
+
static ID id_start_withq;
|
44
|
+
static ID id_state;
|
45
|
+
static ID id_style;
|
46
|
+
static ID id_style_obj_to_css;
|
47
|
+
static ID id_validate_props;
|
48
|
+
static ID id_value;
|
49
|
+
|
50
|
+
static ID iv_context;
|
51
|
+
static ID iv_declared_props;
|
52
|
+
static ID iv_next_state;
|
53
|
+
static ID iv_props;
|
54
|
+
static ID iv_state;
|
55
|
+
|
56
|
+
static char *str_foreign_object = "foreignObject";
|
57
|
+
static char *str_option = "option";
|
58
|
+
static char *str_select = "select";
|
59
|
+
static char *str_selected = "selected";
|
60
|
+
static char *str_svg = "svg";
|
61
|
+
static char *str_textarea = "textarea";
|
62
|
+
|
63
|
+
static char *str_rve = "^(area|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr)$";
|
64
|
+
static char *str_run = "[\\s\\n\\\\\\/='\"\\0<>]";
|
65
|
+
static char *str_rxl = "^xlink:?.";
|
66
|
+
static char *str_rx2 = "^xlink:?";
|
67
|
+
// static char *str_ree = "[\"&<]";
|
68
|
+
|
69
|
+
static VALUE s_aria;
|
70
|
+
static VALUE s_false;
|
71
|
+
static VALUE s_true;
|
72
|
+
static VALUE s_xlink;
|
73
|
+
|
74
|
+
static VALUE sym_children;
|
75
|
+
static VALUE sym_class;
|
76
|
+
static VALUE sym_default;
|
77
|
+
static VALUE sym_for;
|
78
|
+
static VALUE sym_html;
|
79
|
+
static VALUE sym_key;
|
80
|
+
static VALUE sym_ref;
|
81
|
+
static VALUE sym_selected;
|
82
|
+
static VALUE sym_value;
|
83
|
+
|
84
|
+
static VALUE mIsomorfeus;
|
85
|
+
static VALUE mPreact;
|
86
|
+
static VALUE cFragment;
|
87
|
+
static VALUE cProc;
|
88
|
+
static VALUE cRegexp;
|
89
|
+
|
90
|
+
extern VALUE cVNode;
|
91
|
+
|
92
|
+
static VALUE rXlink;
|
93
|
+
static VALUE rUnsafe;
|
94
|
+
static VALUE rVoid;
|
95
|
+
static VALUE rXlink2;
|
96
|
+
|
97
|
+
int set_default_prop_value(VALUE prop, VALUE value, VALUE props) {
|
98
|
+
if ((rb_funcall(value, id_keyq, 1, sym_default) == Qtrue) && (rb_funcall(props, id_keyq, 1, prop) == Qfalse)) {
|
99
|
+
rb_hash_aset(props, props, rb_hash_lookup(value, sym_default));
|
100
|
+
}
|
101
|
+
return 0;
|
102
|
+
}
|
103
|
+
|
104
|
+
ID normalize_prop_name(ID name_id, VALUE is_svg_mode) {
|
105
|
+
if (name_id == id_class_name || name_id == id_class_name2) { return id_class; }
|
106
|
+
if (name_id == id_html_for) { return id_for; }
|
107
|
+
if (name_id == id_default_value) { return id_value; }
|
108
|
+
if (name_id == id_default_checked) { return id_checked; }
|
109
|
+
if (name_id == id_default_selected) { return id_selected; }
|
110
|
+
if (is_svg_mode == Qtrue) {
|
111
|
+
VALUE name_s = rb_id2str(name_id);
|
112
|
+
if (rb_funcall(rXlink, id_match, 1, name_s) == Qtrue) {
|
113
|
+
name_s = rb_funcall(name_s, id_downcase, 0);
|
114
|
+
name_s = rb_funcall(name_s, id_gsub, 2, rXlink2, s_xlink);
|
115
|
+
return SYM2ID(rb_to_symbol(name_s));
|
116
|
+
}
|
117
|
+
}
|
118
|
+
return name_id;
|
119
|
+
}
|
120
|
+
|
121
|
+
VALUE normalize_prop_value(ID name_id, VALUE name_s, VALUE value, VALUE self) {
|
122
|
+
if (name_id == id_style && value != Qnil && TYPE(value) == T_HASH) {
|
123
|
+
return rb_funcall(self, id_style_obj_to_css, 1, value);
|
124
|
+
}
|
125
|
+
// name[0] === 'a' && name[1] === 'r'
|
126
|
+
if (value == Qtrue && rb_funcall(name_s, id_start_withq, 1, s_aria) == Qtrue) {
|
127
|
+
// always use string values instead of booleans for aria attributes
|
128
|
+
// also see https://github.com/preactjs/preact/pull/2347/files
|
129
|
+
return s_true;
|
130
|
+
}
|
131
|
+
if (value == Qfalse && rb_funcall(name_s, id_start_withq, 1, s_aria) == Qtrue) {
|
132
|
+
// always use string values instead of booleans for aria attributes
|
133
|
+
// also see https://github.com/preactjs/preact/pull/2347/files
|
134
|
+
return s_false;
|
135
|
+
}
|
136
|
+
return value;
|
137
|
+
}
|
138
|
+
|
139
|
+
VALUE get_context(VALUE node_type, VALUE context) {
|
140
|
+
VALUE ctx_type = rb_funcall(node_type, id_context_type, 0);
|
141
|
+
VALUE provider = Qnil;
|
142
|
+
VALUE cctx = context;
|
143
|
+
if (ctx_type != Qnil) {
|
144
|
+
provider = rb_hash_lookup(context, rb_funcall(ctx_type, id_context_id, 0));
|
145
|
+
if (provider != Qnil) {
|
146
|
+
cctx = rb_hash_lookup(rb_funcall(provider, id_props, 0), sym_value); }
|
147
|
+
else {
|
148
|
+
cctx = rb_funcall(ctx_type, id_value, 0); }
|
149
|
+
}
|
150
|
+
return cctx;
|
151
|
+
}
|
152
|
+
|
153
|
+
VALUE render_class_component(VALUE vnode, VALUE context) {
|
154
|
+
VNode *v = (VNode *)DATA_PTR(vnode);
|
155
|
+
|
156
|
+
VALUE node_type = v->type;
|
157
|
+
VALUE props = v->props;
|
158
|
+
|
159
|
+
// get context
|
160
|
+
VALUE cctx = get_context(node_type, context);
|
161
|
+
|
162
|
+
// validate props
|
163
|
+
VALUE declared_props = rb_ivar_get(node_type, iv_declared_props);
|
164
|
+
if (declared_props != Qnil) {
|
165
|
+
rb_hash_foreach(declared_props, set_default_prop_value, props);
|
166
|
+
if (rb_funcall(mIsomorfeus, id_development, 0) == Qtrue) { rb_funcall(node_type, id_validate_props, 1, props); }
|
167
|
+
}
|
168
|
+
|
169
|
+
// instantiate component
|
170
|
+
VALUE c = rb_funcall(node_type, id_new, 2, props, cctx);
|
171
|
+
v->component = c;
|
172
|
+
|
173
|
+
// set state, props, context
|
174
|
+
rb_ivar_set(c, iv_props, props);
|
175
|
+
if (rb_funcall(c, id_state, 0) == Qnil) { rb_ivar_set(c, iv_state, rb_hash_new()); }
|
176
|
+
if (rb_ivar_get(c, iv_next_state) == Qnil) { rb_ivar_set(c, iv_next_state, rb_funcall(c, id_state, 0)); }
|
177
|
+
rb_ivar_set(c, iv_context, cctx);
|
178
|
+
|
179
|
+
// get_derived_state_from_props
|
180
|
+
if (rb_respond_to(c, id_get_derived_state_from_props)) {
|
181
|
+
VALUE state = rb_funcall(c, id_state, 0);
|
182
|
+
VALUE res = rb_funcall(c, id_get_derived_state_from_props, 2, rb_funcall(c, id_props, 0), state);
|
183
|
+
rb_ivar_set(c, iv_state, rb_funcall(state, id_merge, res));
|
184
|
+
}
|
185
|
+
|
186
|
+
// render
|
187
|
+
return rb_funcall(c, id_render, 0);
|
188
|
+
}
|
189
|
+
|
190
|
+
void internal_render_to_string(VALUE vnode, VALUE context, VALUE is_svg_mode, VALUE select_value, VALUE self, render_result_s *rres) {
|
191
|
+
VNode *v;
|
192
|
+
VALUE res;
|
193
|
+
VALUE node_type, props;
|
194
|
+
int i, len;
|
195
|
+
|
196
|
+
if (vnode == Qnil || vnode == Qfalse || vnode == Qtrue || ((TYPE(vnode) == T_STRING) && RSTRING_LEN(vnode) == 0)) {
|
197
|
+
return;
|
198
|
+
}
|
199
|
+
|
200
|
+
switch (TYPE(vnode)) {
|
201
|
+
case T_STRING:
|
202
|
+
res = rb_funcall(self, id_encode_entities, 1, vnode);
|
203
|
+
render_result_write(rres, RSTRING_PTR(res), RSTRING_LEN(res));
|
204
|
+
return;
|
205
|
+
case T_FIXNUM:
|
206
|
+
case T_BIGNUM:
|
207
|
+
res = rb_obj_as_string(vnode);
|
208
|
+
render_result_write(rres, RSTRING_PTR(res), RSTRING_LEN(res));
|
209
|
+
return;
|
210
|
+
case T_ARRAY:
|
211
|
+
len = RARRAY_LEN(vnode);
|
212
|
+
for (i = 0; i < len; i++) {
|
213
|
+
internal_render_to_string(RARRAY_PTR(vnode)[i], context, is_svg_mode, select_value, self, rres);
|
214
|
+
}
|
215
|
+
return;
|
216
|
+
}
|
217
|
+
|
218
|
+
v = (VNode *)DATA_PTR(vnode);
|
219
|
+
node_type = v->type;
|
220
|
+
props = v->props;
|
221
|
+
|
222
|
+
if (TYPE(node_type) != T_STRING) {
|
223
|
+
// components and Fragments
|
224
|
+
VALUE rendered;
|
225
|
+
VALUE ancestors = rb_funcall(node_type, id_ancestors, 0);
|
226
|
+
rb_funcall(ancestors, id_include, 1, cFragment);
|
227
|
+
|
228
|
+
if (RARRAY_PTR(ancestors)[0] == cFragment) {
|
229
|
+
rendered = rb_hash_lookup(props, sym_children);
|
230
|
+
} else {
|
231
|
+
rendered = render_class_component(vnode, context);
|
232
|
+
|
233
|
+
VALUE component = v->component;
|
234
|
+
if (rb_respond_to(component, id_get_child_context)) {
|
235
|
+
context = rb_funcall(context, id_merge, 1, rb_funcall(component, id_get_child_context, 0));
|
236
|
+
}
|
237
|
+
}
|
238
|
+
|
239
|
+
internal_render_to_string(rendered, context, is_svg_mode, select_value, self, rres);
|
240
|
+
return;
|
241
|
+
}
|
242
|
+
|
243
|
+
props = v->props;
|
244
|
+
|
245
|
+
// render JSX to HTML
|
246
|
+
VALUE node_type_s = rb_obj_as_string(node_type);
|
247
|
+
render_result_write(rres, "<", 1);
|
248
|
+
render_result_write(rres, RSTRING_PTR(node_type_s), RSTRING_LEN(node_type_s));
|
249
|
+
|
250
|
+
VALUE children = Qnil;
|
251
|
+
VALUE html = Qnil;
|
252
|
+
|
253
|
+
if (props != Qnil) {
|
254
|
+
children = rb_hash_lookup(props, sym_children);
|
255
|
+
VALUE attrs = rb_funcall(props, id_keys, 0);
|
256
|
+
len = RARRAY_LEN(attrs);
|
257
|
+
for (i = 0; i < len; i++) {
|
258
|
+
VALUE name = RARRAY_PTR(attrs)[i];
|
259
|
+
if (TYPE(name) == T_STRING) { name = rb_to_symbol(name); }
|
260
|
+
ID name_id = SYM2ID(name);
|
261
|
+
VALUE value = rb_hash_lookup(props, name);
|
262
|
+
|
263
|
+
if (name_id == id_key || name_id == id_ref || name_id == id_self || name_id == id_source || name_id == id_children ||
|
264
|
+
((name_id == id_class_name || name_id == id_class_name2) && (rb_hash_lookup(props, sym_class) != Qnil)) ||
|
265
|
+
((name_id == id_html_for) && (rb_hash_lookup(props, sym_for) != Qnil))) {
|
266
|
+
continue;
|
267
|
+
}
|
268
|
+
|
269
|
+
VALUE name_s = rb_id2str(name_id);
|
270
|
+
if (rb_funcall(rUnsafe, id_match, 1, name_s) == Qtrue) {
|
271
|
+
continue;
|
272
|
+
}
|
273
|
+
|
274
|
+
name_id = normalize_prop_name(name_id, is_svg_mode);
|
275
|
+
name_s = rb_id2str(name_id);
|
276
|
+
value = normalize_prop_value(name_id, name_s, value, self);
|
277
|
+
|
278
|
+
if (name_id == id_dangerously_set_inner_html && value != Qnil) {
|
279
|
+
html = rb_hash_lookup(value, sym_html);
|
280
|
+
} else if (name_id == id_value && strcmp(RSTRING_PTR(node_type_s), str_textarea) == 0) {
|
281
|
+
// <textarea value="a&b"> --> <textarea>a&b</textarea>
|
282
|
+
children = value;
|
283
|
+
} else if (value != Qnil && value != Qfalse && rb_funcall(value, id_is_a, 1, cProc) != Qtrue) {
|
284
|
+
if (value == Qtrue || ((TYPE(value) == T_STRING) && (RSTRING_PTR(value)[0] == 0))) {
|
285
|
+
// if (name_id == id_class || name_id == id_style) { continue; }
|
286
|
+
value = name_s;
|
287
|
+
render_result_write(rres, " ", 1);
|
288
|
+
render_result_write(rres, RSTRING_PTR(name_s), RSTRING_LEN(name_s));
|
289
|
+
continue;
|
290
|
+
}
|
291
|
+
|
292
|
+
if (name_id == id_value) {
|
293
|
+
if (strcmp(RSTRING_PTR(node_type_s), str_select) == 0) {
|
294
|
+
select_value = value;
|
295
|
+
continue;
|
296
|
+
} else if (
|
297
|
+
// If we're looking at an <option> and it's the currently selected one
|
298
|
+
strcmp(RSTRING_PTR(node_type_s), str_option) == 0 &&
|
299
|
+
rb_funcall(select_value, id_eqeq, 1, value) == Qtrue &&
|
300
|
+
// and the <option> doesn't already have a selected attribute on it
|
301
|
+
rb_hash_lookup(props, sym_selected) == Qnil
|
302
|
+
) {
|
303
|
+
render_result_write(rres, " ", 1);
|
304
|
+
render_result_write(rres, str_selected, strlen(str_selected));
|
305
|
+
}
|
306
|
+
}
|
307
|
+
|
308
|
+
render_result_write(rres, " ", 1);
|
309
|
+
render_result_write(rres, RSTRING_PTR(name_s), RSTRING_LEN(name_s));
|
310
|
+
render_result_write(rres, "=\"", 2);
|
311
|
+
res = rb_funcall(self, id_encode_entities, 1, value);
|
312
|
+
render_result_write(rres, RSTRING_PTR(res), RSTRING_LEN(res));
|
313
|
+
render_result_write(rres, "\"", 1);
|
314
|
+
}
|
315
|
+
}
|
316
|
+
}
|
317
|
+
|
318
|
+
render_result_write(rres, ">", 1);
|
319
|
+
|
320
|
+
if (rb_funcall(rUnsafe, id_match, 1, node_type_s) == Qtrue) {
|
321
|
+
rb_raise(rb_eRuntimeError, "%s is not a valid HTML tag name in %s", RSTRING_PTR(node_type_s), render_result2ptr(rres));
|
322
|
+
}
|
323
|
+
|
324
|
+
render_result_s *pieces = render_result_new();
|
325
|
+
VALUE has_children = Qfalse;
|
326
|
+
int children_type = TYPE(children);
|
327
|
+
|
328
|
+
if (html != Qnil) {
|
329
|
+
render_result_write(pieces, RSTRING_PTR(html), RSTRING_LEN(html));
|
330
|
+
has_children = Qtrue;
|
331
|
+
} else if (children_type == T_STRING) {
|
332
|
+
res = rb_funcall(self, id_encode_entities, 1, children);
|
333
|
+
render_result_write(pieces, RSTRING_PTR(res), RSTRING_LEN(res));
|
334
|
+
has_children = Qtrue;
|
335
|
+
} else if (children_type == T_ARRAY) {
|
336
|
+
VALUE child;
|
337
|
+
len = RARRAY_LEN(children);
|
338
|
+
for (i = 0; i < len; i++) {
|
339
|
+
child = RARRAY_PTR(children)[i];
|
340
|
+
if (child != Qnil && child != Qfalse) {
|
341
|
+
VALUE child_svg_mode;
|
342
|
+
if (strcmp(RSTRING_PTR(node_type_s), str_svg) == 0) {
|
343
|
+
child_svg_mode = Qtrue;
|
344
|
+
} else if (strcmp(RSTRING_PTR(node_type_s), str_foreign_object) == 0 && is_svg_mode == Qtrue) {
|
345
|
+
child_svg_mode = Qfalse;
|
346
|
+
} else {
|
347
|
+
child_svg_mode = is_svg_mode;
|
348
|
+
}
|
349
|
+
size_t len = render_result_len(pieces);
|
350
|
+
internal_render_to_string(child, context, child_svg_mode, select_value, self, pieces);
|
351
|
+
if (len < render_result_len(pieces)) { has_children = Qtrue; }
|
352
|
+
}
|
353
|
+
}
|
354
|
+
} else if (children != Qnil && children != Qfalse && children != Qtrue) {
|
355
|
+
VALUE child_svg_mode;
|
356
|
+
if (strcmp(RSTRING_PTR(node_type_s), str_svg) == 0) {
|
357
|
+
child_svg_mode = Qtrue;
|
358
|
+
} else if (strcmp(RSTRING_PTR(node_type_s), str_foreign_object) == 0 && is_svg_mode == Qtrue) {
|
359
|
+
child_svg_mode = Qfalse;
|
360
|
+
} else {
|
361
|
+
child_svg_mode = is_svg_mode;
|
362
|
+
}
|
363
|
+
size_t len = render_result_len(pieces);
|
364
|
+
internal_render_to_string(children, context, child_svg_mode, select_value, self, pieces);
|
365
|
+
if (len < render_result_len(pieces)) { has_children = Qtrue; }
|
366
|
+
}
|
367
|
+
|
368
|
+
if (has_children == Qtrue) {
|
369
|
+
render_result_concat(rres, pieces);
|
370
|
+
} else if (rb_funcall(rVoid, id_match, 1, node_type_s) == Qtrue) {
|
371
|
+
char *s = render_result2ptr(rres);
|
372
|
+
char l = s[render_result_len(rres) - 1];
|
373
|
+
if (l == '>') {
|
374
|
+
render_result_resize(rres, render_result_len(rres) - 1);
|
375
|
+
render_result_write(rres, " />", 3);
|
376
|
+
}
|
377
|
+
return;
|
378
|
+
}
|
379
|
+
|
380
|
+
render_result_free(pieces);
|
381
|
+
|
382
|
+
render_result_write(rres, "</", 2);
|
383
|
+
render_result_write(rres, RSTRING_PTR(node_type_s), RSTRING_LEN(node_type_s));
|
384
|
+
render_result_write(rres, ">", 1);
|
385
|
+
|
386
|
+
return;
|
387
|
+
}
|
388
|
+
|
389
|
+
VALUE render_to_string(int argc, VALUE *argv, VALUE self) {
|
390
|
+
VALUE vnode, context, is_svg_mode, select_value, res;
|
391
|
+
render_result_s *rres = render_result_new();
|
392
|
+
rb_scan_args(argc, argv, "22", &vnode, &context, &is_svg_mode, &select_value);
|
393
|
+
internal_render_to_string(vnode, context, is_svg_mode, select_value, self, rres);
|
394
|
+
res = rb_str_new(render_result2ptr(rres), render_result_len(rres));
|
395
|
+
render_result_free(rres);
|
396
|
+
return res;
|
397
|
+
}
|
398
|
+
|
399
|
+
VALUE create_element(int argc, VALUE *argv, VALUE self) {
|
400
|
+
VALUE type, props, children;
|
401
|
+
rb_scan_args(argc, argv, "12", &type, &props, &children);
|
402
|
+
VALUE normalized_props, key, ref;
|
403
|
+
|
404
|
+
if (props != Qnil) {
|
405
|
+
if (TYPE(props) == T_HASH) {
|
406
|
+
normalized_props = rb_hash_dup(props);
|
407
|
+
key = rb_hash_delete(normalized_props, sym_key);
|
408
|
+
ref = rb_hash_delete(normalized_props, sym_ref);
|
409
|
+
} else {
|
410
|
+
children = props;
|
411
|
+
normalized_props = rb_hash_new();
|
412
|
+
key = Qnil;
|
413
|
+
ref = Qnil;
|
414
|
+
}
|
415
|
+
} else {
|
416
|
+
normalized_props = rb_hash_new();
|
417
|
+
key = Qnil;
|
418
|
+
ref = Qnil;
|
419
|
+
}
|
420
|
+
|
421
|
+
if (rb_block_given_p()) {
|
422
|
+
VALUE pr = rb_funcall(mPreact, id_render_buffer, 0);
|
423
|
+
pr = rb_ary_push(pr, rb_ary_new());
|
424
|
+
VALUE block_result = rb_yield(Qnil);
|
425
|
+
VALUE c = rb_ary_pop(pr);
|
426
|
+
if (rb_funcall(mPreact, id_is_renderable, 1, block_result) == Qtrue) {
|
427
|
+
rb_ary_push(c, block_result);
|
428
|
+
}
|
429
|
+
if (RARRAY_LEN(c) > 0) {
|
430
|
+
children = c;
|
431
|
+
}
|
432
|
+
}
|
433
|
+
|
434
|
+
if (children != Qnil) {
|
435
|
+
rb_hash_aset(normalized_props, sym_children, children);
|
436
|
+
}
|
437
|
+
|
438
|
+
return rb_funcall(cVNode, id_new, 4, type, normalized_props, key, ref);
|
439
|
+
}
|
440
|
+
|
441
|
+
void Init_Preact(void) {
|
442
|
+
id_ancestors = rb_intern("ancestors");
|
443
|
+
id_checked = rb_intern("checked");
|
444
|
+
id_children = rb_intern("children");
|
445
|
+
id_class = rb_intern("class");
|
446
|
+
id_class_name = rb_intern("class_name");
|
447
|
+
id_class_name2 = rb_intern("className");
|
448
|
+
id_context_id = rb_intern("context_id");
|
449
|
+
id_context_type = rb_intern("context_type");
|
450
|
+
id_dangerously_set_inner_html = rb_intern("dangerouslySetInnerHTML");
|
451
|
+
id_default_checked = rb_intern("default_checked");
|
452
|
+
id_default_selected = rb_intern("default_selected");
|
453
|
+
id_default_value = rb_intern("default_value");
|
454
|
+
id_development = rb_intern("development?");
|
455
|
+
id_downcase = rb_intern("downcase");
|
456
|
+
id_encode_entities = rb_intern("_encode_entities");
|
457
|
+
id_eqeq = rb_intern("==");
|
458
|
+
id_get_child_context = rb_intern("get_child_context");
|
459
|
+
id_get_derived_state_from_props = rb_intern("get_derived_state_from_props");
|
460
|
+
id_gsub = rb_intern("gsub");
|
461
|
+
id_html_for = rb_intern("html_for");
|
462
|
+
id_for = rb_intern("for");
|
463
|
+
id_include = rb_intern("include?");
|
464
|
+
id_is_a = rb_intern("is_a?");
|
465
|
+
id_is_renderable = rb_intern("is_renderable?");
|
466
|
+
id_key = rb_intern("key");
|
467
|
+
id_keyq = rb_intern("key?");
|
468
|
+
id_keys = rb_intern("keys");
|
469
|
+
id_match = rb_intern("match?");
|
470
|
+
id_merge = rb_intern("merge");
|
471
|
+
id_new = rb_intern("new");
|
472
|
+
id_props = rb_intern("props");
|
473
|
+
id_ref = rb_intern("ref");
|
474
|
+
id_render = rb_intern("render");
|
475
|
+
id_render_buffer = rb_intern("render_buffer");
|
476
|
+
id_selected = rb_intern("selected");
|
477
|
+
id_self = rb_intern("__self");
|
478
|
+
id_source = rb_intern("__source");
|
479
|
+
id_start_withq = rb_intern("start_with?");
|
480
|
+
id_state = rb_intern("state");
|
481
|
+
id_style = rb_intern("style");
|
482
|
+
id_style_obj_to_css = rb_intern("_style_obj_to_css");
|
483
|
+
id_validate_props = rb_intern("validate_props");
|
484
|
+
id_value = rb_intern("value");
|
485
|
+
|
486
|
+
iv_context = rb_intern("@context");
|
487
|
+
iv_declared_props = rb_intern("@declared_props");
|
488
|
+
iv_next_state = rb_intern("@_nextState");
|
489
|
+
iv_props = rb_intern("@props");
|
490
|
+
iv_state = rb_intern("@state");
|
491
|
+
|
492
|
+
sym_children = ID2SYM(rb_intern("children"));
|
493
|
+
sym_class = ID2SYM(rb_intern("class"));
|
494
|
+
sym_default = ID2SYM(rb_intern("default"));
|
495
|
+
sym_for = ID2SYM(id_for);
|
496
|
+
sym_html = ID2SYM(rb_intern("__html"));
|
497
|
+
sym_key = ID2SYM(rb_intern("key"));
|
498
|
+
sym_ref = ID2SYM(rb_intern("ref"));
|
499
|
+
sym_selected = ID2SYM(rb_intern("selected"));
|
500
|
+
sym_value = ID2SYM(id_value);
|
501
|
+
|
502
|
+
cProc = rb_const_get(rb_cObject, rb_intern("Proc"));
|
503
|
+
cRegexp = rb_const_get(rb_cObject, rb_intern("Regexp"));
|
504
|
+
mIsomorfeus = rb_const_get(rb_cObject, rb_intern("Isomorfeus"));
|
505
|
+
mPreact = rb_define_module("Preact");
|
506
|
+
cFragment = rb_define_class("Fragment", rb_cObject);
|
507
|
+
|
508
|
+
// set instance variables on the module to keep references to these objects
|
509
|
+
// to prevent garbage colloction
|
510
|
+
rUnsafe = rb_funcall(cRegexp, id_new, 1, rb_str_new_cstr(str_run));
|
511
|
+
rb_obj_freeze(rUnsafe);
|
512
|
+
rb_ivar_set(mPreact, rb_intern("@_r_unsafe"), rUnsafe);
|
513
|
+
rVoid = rb_funcall(cRegexp, id_new, 1, rb_str_new_cstr(str_rve));
|
514
|
+
rb_obj_freeze(rVoid);
|
515
|
+
rb_ivar_set(mPreact, rb_intern("@_r_void"), rVoid);
|
516
|
+
rXlink = rb_funcall(cRegexp, id_new, 1, rb_str_new_cstr(str_rxl));
|
517
|
+
rb_obj_freeze(rXlink);
|
518
|
+
rb_ivar_set(mPreact, rb_intern("@_r_xlink"), rXlink);
|
519
|
+
rXlink2 = rb_funcall(cRegexp, id_new, 1, rb_str_new_cstr(str_rx2));
|
520
|
+
rb_obj_freeze(rXlink2);
|
521
|
+
rb_ivar_set(mPreact, rb_intern("@_r_xlink2"), rXlink2);
|
522
|
+
|
523
|
+
s_aria = rb_str_new_cstr("aria");
|
524
|
+
rb_obj_freeze(s_aria);
|
525
|
+
rb_ivar_set(mPreact, rb_intern("@_s_aria"), s_aria);
|
526
|
+
s_false = rb_str_new_cstr("false");
|
527
|
+
rb_obj_freeze(s_false);
|
528
|
+
rb_ivar_set(mPreact, rb_intern("@_s_false"), s_false);
|
529
|
+
s_true = rb_str_new_cstr("true");
|
530
|
+
rb_obj_freeze(s_true);
|
531
|
+
rb_ivar_set(mPreact, rb_intern("@_s_true"), s_true);
|
532
|
+
s_xlink = rb_str_new_cstr("xlink:");
|
533
|
+
rb_obj_freeze(s_xlink);
|
534
|
+
rb_ivar_set(mPreact, rb_intern("@_s_xlink"), s_xlink);
|
535
|
+
|
536
|
+
rb_define_module_function(mPreact, "_render_to_string", render_to_string, -1);
|
537
|
+
rb_define_module_function(mPreact, "create_element", create_element, -1);
|
538
|
+
}
|
@@ -0,0 +1,91 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#define FIO_MEMORY_NAME vnode
|
3
|
+
#include "fio-stl.h"
|
4
|
+
#include "isomorfeus_preact_ext.h"
|
5
|
+
|
6
|
+
VALUE cVNode;
|
7
|
+
|
8
|
+
static void preact_vnode_mark(void *p) {
|
9
|
+
VNode *v = (VNode *)p;
|
10
|
+
rb_gc_mark(v->component);
|
11
|
+
rb_gc_mark(v->key);
|
12
|
+
rb_gc_mark(v->props);
|
13
|
+
rb_gc_mark(v->ref);
|
14
|
+
rb_gc_mark(v->type);
|
15
|
+
}
|
16
|
+
|
17
|
+
static void preact_vnode_free(void *p) {
|
18
|
+
vnode_free(p);
|
19
|
+
}
|
20
|
+
|
21
|
+
static size_t preact_vnode_size(const void *p) {
|
22
|
+
return sizeof(VNode);
|
23
|
+
(void)p;
|
24
|
+
}
|
25
|
+
|
26
|
+
const rb_data_type_t preact_vnode_t = {
|
27
|
+
.wrap_struct_name = "VNode",
|
28
|
+
.function = {
|
29
|
+
.dmark = preact_vnode_mark,
|
30
|
+
.dfree = preact_vnode_free,
|
31
|
+
.dsize = preact_vnode_size,
|
32
|
+
.dcompact = NULL,
|
33
|
+
.reserved = {0}
|
34
|
+
},
|
35
|
+
.parent = NULL,
|
36
|
+
.data = NULL,
|
37
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
38
|
+
};
|
39
|
+
|
40
|
+
static VALUE preact_vnode_alloc(VALUE rclass) {
|
41
|
+
void *v = vnode_malloc(sizeof(VNode));
|
42
|
+
return TypedData_Wrap_Struct(rclass, &preact_vnode_t, v);
|
43
|
+
}
|
44
|
+
|
45
|
+
static VALUE preact_vnode_init(VALUE self, VALUE type, VALUE props, VALUE key, VALUE ref) {
|
46
|
+
VNode *v = (VNode *)DATA_PTR(self);
|
47
|
+
v->component = Qnil;
|
48
|
+
v->key = key;
|
49
|
+
v->props = props;
|
50
|
+
v->type = type;
|
51
|
+
v->ref = ref;
|
52
|
+
return self;
|
53
|
+
}
|
54
|
+
|
55
|
+
static VALUE preact_vnode_set_c(VALUE self, VALUE c) {
|
56
|
+
VNode *v = (VNode *)DATA_PTR(self);
|
57
|
+
v->component = c;
|
58
|
+
return c;
|
59
|
+
}
|
60
|
+
|
61
|
+
static VALUE preact_vnode_get_c(VALUE self) {
|
62
|
+
return ((VNode *)DATA_PTR(self))->component;
|
63
|
+
}
|
64
|
+
|
65
|
+
static VALUE preact_vnode_get_key(VALUE self) {
|
66
|
+
return ((VNode *)DATA_PTR(self))->key;
|
67
|
+
}
|
68
|
+
|
69
|
+
static VALUE preact_vnode_get_props(VALUE self) {
|
70
|
+
return ((VNode *)DATA_PTR(self))->props;
|
71
|
+
}
|
72
|
+
|
73
|
+
static VALUE preact_vnode_get_ref(VALUE self) {
|
74
|
+
return ((VNode *)DATA_PTR(self))->ref;
|
75
|
+
}
|
76
|
+
|
77
|
+
static VALUE preact_vnode_get_type(VALUE self) {
|
78
|
+
return ((VNode *)DATA_PTR(self))->type;
|
79
|
+
}
|
80
|
+
|
81
|
+
void Init_VNode(void) {
|
82
|
+
cVNode = rb_define_class("VNode", rb_cObject);
|
83
|
+
rb_define_alloc_func(cVNode, preact_vnode_alloc);
|
84
|
+
rb_define_method(cVNode, "initialize", preact_vnode_init, 4);
|
85
|
+
rb_define_method(cVNode, "component=", preact_vnode_set_c, 1);
|
86
|
+
rb_define_method(cVNode, "component", preact_vnode_get_c, 0);
|
87
|
+
rb_define_method(cVNode, "key", preact_vnode_get_key, 0);
|
88
|
+
rb_define_method(cVNode, "props", preact_vnode_get_props, 0);
|
89
|
+
rb_define_method(cVNode, "ref", preact_vnode_get_ref, 0);
|
90
|
+
rb_define_method(cVNode, "type", preact_vnode_get_type, 0);
|
91
|
+
}
|
@@ -30,7 +30,6 @@ module Isomorfeus
|
|
30
30
|
|
31
31
|
def render_component_to_string(component_name, props)
|
32
32
|
component = component_name.is_a?(String) ? self.class.const_get(component_name) : component_name
|
33
|
-
::Preact._vnode_id = 0
|
34
33
|
::Preact.render_to_string(::Preact.create_element(component, props))
|
35
34
|
end
|
36
35
|
end
|