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.
@@ -0,0 +1,9 @@
1
+ #include <ruby.h>
2
+
3
+ extern void Init_VNode(void);
4
+ extern void Init_Preact(void);
5
+
6
+ void Init_isomorfeus_preact_ext(void) {
7
+ Init_VNode();
8
+ Init_Preact();
9
+ }
@@ -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&amp;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
@@ -1,5 +1,5 @@
1
1
  module Isomorfeus
2
2
  module Preact
3
- VERSION = '22.9.0.rc9'
3
+ VERSION = '22.10.0.rc1'
4
4
  end
5
5
  end