@react-native-quickjs/quickjs 1.0.0-alpha.1 → 1.0.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,583 @@
1
+ /* Runtime-width backtracking VM body, included once from libregexp.c. */
2
+ static intptr_t LRE_BT_FUNC(REExecContext *s, uint8_t **capture,
3
+ const uint8_t *pc, const uint8_t *cptr)
4
+ {
5
+ int opcode;
6
+ const int cbuf_type = LRE_CBUF_TYPE_INIT;
7
+ uint32_t val, c, idx;
8
+ const uint8_t *cbuf_end;
9
+ StackElem *sp, *bp, *stack_end;
10
+ #ifdef DUMP_EXEC
11
+ const uint8_t *pc_start = pc; /* TEST */
12
+ #endif
13
+ cbuf_end = s->cbuf_end;
14
+
15
+ sp = s->stack_buf;
16
+ bp = s->stack_buf;
17
+ stack_end = s->stack_buf + s->stack_size;
18
+
19
+ #define CHECK_STACK_SPACE(n) \
20
+ if (unlikely((stack_end - sp) < (n))) { \
21
+ size_t saved_sp = sp - s->stack_buf; \
22
+ size_t saved_bp = bp - s->stack_buf; \
23
+ if (stack_realloc(s, sp - s->stack_buf + (n))) \
24
+ return LRE_RET_MEMORY_ERROR; \
25
+ stack_end = s->stack_buf + s->stack_size; \
26
+ sp = s->stack_buf + saved_sp; \
27
+ bp = s->stack_buf + saved_bp; \
28
+ }
29
+
30
+ /* XXX: could test if the value was saved to reduce the stack size
31
+ but slower */
32
+ #define SAVE_CAPTURE(idx, value) \
33
+ { \
34
+ CHECK_STACK_SPACE(2); \
35
+ sp[0].val = idx; \
36
+ sp[1].ptr = capture[idx]; \
37
+ sp += 2; \
38
+ capture[idx] = (value); \
39
+ }
40
+
41
+ /* avoid saving the previous value if already saved */
42
+ #define SAVE_CAPTURE_CHECK(idx, value) \
43
+ { \
44
+ StackElem *sp1; \
45
+ sp1 = sp; \
46
+ for(;;) { \
47
+ if (sp1 > bp) { \
48
+ if (sp1[-2].val == idx) \
49
+ break; \
50
+ sp1 -= 2; \
51
+ } else { \
52
+ CHECK_STACK_SPACE(2); \
53
+ sp[0].val = idx; \
54
+ sp[1].ptr = capture[idx]; \
55
+ sp += 2; \
56
+ break; \
57
+ } \
58
+ } \
59
+ capture[idx] = (value); \
60
+ }
61
+
62
+
63
+ #ifdef DUMP_EXEC
64
+ #define LRE_DUMP_OP() \
65
+ printf("%5ld %5ld %5ld %5ld %s\n", \
66
+ (long)(pc - 1 - pc_start), \
67
+ (long)(cbuf_type == 0 ? cptr - s->cbuf : (cptr - s->cbuf) / 2), \
68
+ (long)(bp - s->stack_buf), \
69
+ (long)(sp - s->stack_buf), \
70
+ reopcode_info[opcode].name)
71
+ #else
72
+ #define LRE_DUMP_OP()
73
+ #endif
74
+
75
+ /* Threaded-code dispatch: on compilers with the GCC label-as-value
76
+ extension, jump directly from one opcode handler to the next via a
77
+ table instead of returning to a central switch. Falls back to a plain
78
+ switch elsewhere (MSVC, Emscripten). */
79
+ #if !LRE_DIRECT_DISPATCH
80
+ #define SWITCH(pc) opcode = *pc++; LRE_DUMP_OP(); switch(opcode)
81
+ #define CASE(op) case op
82
+ #define DEFAULT default
83
+ #define BREAK break
84
+ #else
85
+ static const void * const dispatch_table[256] = {
86
+ #define DEF(id, size) [REOP_ ## id] = && case_REOP_ ## id,
87
+ #include "libregexp-opcode.h"
88
+ #undef DEF
89
+ [REOP_COUNT ... 255] = && case_default,
90
+ };
91
+ /* Wrapped in a statement-expression with a trailing ';' so that BREAK is a
92
+ single statement usable in unbraced contexts like 'if (cond) BREAK;'. */
93
+ #define SWITCH(pc) __extension__ ({ opcode = *pc++; LRE_DUMP_OP(); goto *dispatch_table[opcode]; });
94
+ #define CASE(op) case_ ## op
95
+ #define DEFAULT case_default
96
+ #define BREAK SWITCH(pc)
97
+ #endif
98
+
99
+ #ifdef DUMP_EXEC
100
+ printf("%5s %5s %5s %5s %s\n", "PC", "CP", "BP", "SP", "OPCODE");
101
+ #endif
102
+ for(;;) {
103
+ SWITCH(pc) {
104
+ CASE(REOP_match):
105
+ return 1;
106
+ no_match:
107
+ for(;;) {
108
+ REExecStateEnum type;
109
+ if (bp == s->stack_buf)
110
+ return 0;
111
+ /* undo the modifications to capture[] */
112
+ while (sp > bp) {
113
+ capture[sp[-2].val] = sp[-1].ptr;
114
+ sp -= 2;
115
+ }
116
+
117
+ pc = sp[-3].ptr;
118
+ cptr = sp[-2].ptr;
119
+ type = sp[-1].bp.type;
120
+ bp = s->stack_buf + sp[-1].bp.val;
121
+ sp -= 3;
122
+ if (type != RE_EXEC_STATE_LOOKAHEAD)
123
+ break;
124
+ }
125
+ if (lre_poll_timeout(s))
126
+ return LRE_RET_TIMEOUT;
127
+ BREAK;
128
+ CASE(REOP_lookahead_match):
129
+ /* pop all the saved states until reaching the start of
130
+ the lookahead and keep the updated captures and
131
+ variables and the corresponding undo info. */
132
+ {
133
+ StackElem *sp1, *sp_top, *next_sp;
134
+ REExecStateEnum type;
135
+
136
+ sp_top = sp;
137
+ for(;;) {
138
+ sp1 = sp;
139
+ sp = bp;
140
+ pc = sp[-3].ptr;
141
+ cptr = sp[-2].ptr;
142
+ type = sp[-1].bp.type;
143
+ bp = s->stack_buf + sp[-1].bp.val;
144
+ sp[-1].ptr = (void *)sp1; /* save the next value for the copy step */
145
+ sp -= 3;
146
+ if (type == RE_EXEC_STATE_LOOKAHEAD)
147
+ break;
148
+ }
149
+ if (sp != s->stack_buf) {
150
+ /* keep the undo info if there is a saved state */
151
+ sp1 = sp;
152
+ while (sp1 < sp_top) {
153
+ next_sp = (void *)sp1[2].ptr;
154
+ sp1 += 3;
155
+ while (sp1 < next_sp)
156
+ *sp++ = *sp1++;
157
+ }
158
+ }
159
+ }
160
+ BREAK;
161
+ CASE(REOP_negative_lookahead_match):
162
+ /* pop all the saved states until reaching start of the negative lookahead */
163
+ for(;;) {
164
+ REExecStateEnum type;
165
+ type = bp[-1].bp.type;
166
+ /* undo the modifications to capture[] */
167
+ while (sp > bp) {
168
+ capture[sp[-2].val] = sp[-1].ptr;
169
+ sp -= 2;
170
+ }
171
+ pc = sp[-3].ptr;
172
+ cptr = sp[-2].ptr;
173
+ type = sp[-1].bp.type;
174
+ bp = s->stack_buf + sp[-1].bp.val;
175
+ sp -= 3;
176
+ if (type == RE_EXEC_STATE_NEGATIVE_LOOKAHEAD)
177
+ break;
178
+ }
179
+ goto no_match;
180
+ CASE(REOP_char32):
181
+ CASE(REOP_char32_i):
182
+ val = get_u32(pc);
183
+ pc += 4;
184
+ goto test_char;
185
+ CASE(REOP_char):
186
+ CASE(REOP_char_i):
187
+ val = get_u16(pc);
188
+ pc += 2;
189
+ test_char:
190
+ if (cptr >= cbuf_end)
191
+ goto no_match;
192
+ GET_CHAR(c, cptr, cbuf_end, cbuf_type);
193
+ if (opcode == REOP_char_i || opcode == REOP_char32_i) {
194
+ c = lre_canonicalize(c, s->is_unicode);
195
+ }
196
+ if (val != c)
197
+ goto no_match;
198
+ BREAK;
199
+ CASE(REOP_split_goto_first):
200
+ CASE(REOP_split_next_first):
201
+ {
202
+ const uint8_t *pc1;
203
+
204
+ val = get_u32(pc);
205
+ pc += 4;
206
+ if (opcode == REOP_split_next_first) {
207
+ pc1 = pc + (int)val;
208
+ } else {
209
+ pc1 = pc;
210
+ pc = pc + (int)val;
211
+ }
212
+ CHECK_STACK_SPACE(3);
213
+ sp[0].ptr = (uint8_t *)pc1;
214
+ sp[1].ptr = (uint8_t *)cptr;
215
+ sp[2].bp.val = bp - s->stack_buf;
216
+ sp[2].bp.type = RE_EXEC_STATE_SPLIT;
217
+ sp += 3;
218
+ bp = sp;
219
+ }
220
+ BREAK;
221
+ CASE(REOP_lookahead):
222
+ CASE(REOP_negative_lookahead):
223
+ val = get_u32(pc);
224
+ pc += 4;
225
+ CHECK_STACK_SPACE(3);
226
+ sp[0].ptr = (uint8_t *)(pc + (int)val);
227
+ sp[1].ptr = (uint8_t *)cptr;
228
+ sp[2].bp.val = bp - s->stack_buf;
229
+ sp[2].bp.type = RE_EXEC_STATE_LOOKAHEAD + opcode - REOP_lookahead;
230
+ sp += 3;
231
+ bp = sp;
232
+ BREAK;
233
+ CASE(REOP_goto):
234
+ val = get_u32(pc);
235
+ pc += 4 + (int)val;
236
+ if (lre_poll_timeout(s))
237
+ return LRE_RET_TIMEOUT;
238
+ BREAK;
239
+ CASE(REOP_line_start):
240
+ CASE(REOP_line_start_m):
241
+ if (cptr == s->cbuf)
242
+ BREAK;
243
+ if (opcode == REOP_line_start)
244
+ goto no_match;
245
+ PEEK_PREV_CHAR(c, cptr, s->cbuf, cbuf_type);
246
+ if (!is_line_terminator(c))
247
+ goto no_match;
248
+ BREAK;
249
+ CASE(REOP_line_end):
250
+ CASE(REOP_line_end_m):
251
+ if (cptr == cbuf_end)
252
+ BREAK;
253
+ if (opcode == REOP_line_end)
254
+ goto no_match;
255
+ PEEK_CHAR(c, cptr, cbuf_end, cbuf_type);
256
+ if (!is_line_terminator(c))
257
+ goto no_match;
258
+ BREAK;
259
+ CASE(REOP_dot):
260
+ if (cptr == cbuf_end)
261
+ goto no_match;
262
+ GET_CHAR(c, cptr, cbuf_end, cbuf_type);
263
+ if (is_line_terminator(c))
264
+ goto no_match;
265
+ BREAK;
266
+ CASE(REOP_any):
267
+ if (cptr == cbuf_end)
268
+ goto no_match;
269
+ GET_CHAR(c, cptr, cbuf_end, cbuf_type);
270
+ BREAK;
271
+ CASE(REOP_space):
272
+ if (cptr == cbuf_end)
273
+ goto no_match;
274
+ GET_CHAR(c, cptr, cbuf_end, cbuf_type);
275
+ if (!lre_is_space(c))
276
+ goto no_match;
277
+ BREAK;
278
+ CASE(REOP_not_space):
279
+ if (cptr == cbuf_end)
280
+ goto no_match;
281
+ GET_CHAR(c, cptr, cbuf_end, cbuf_type);
282
+ if (lre_is_space(c))
283
+ goto no_match;
284
+ BREAK;
285
+ CASE(REOP_save_start):
286
+ CASE(REOP_save_end):
287
+ val = *pc++;
288
+ if (val >= (uint32_t)s->capture_count)
289
+ return LRE_RET_BYTECODE_ERROR;
290
+ idx = 2 * val + opcode - REOP_save_start;
291
+ SAVE_CAPTURE(idx, (uint8_t *)cptr);
292
+ BREAK;
293
+ CASE(REOP_save_reset):
294
+ {
295
+ uint32_t val2;
296
+ val = pc[0];
297
+ val2 = pc[1];
298
+ pc += 2;
299
+ if (val2 >= (uint32_t)s->capture_count)
300
+ return LRE_RET_BYTECODE_ERROR;
301
+ CHECK_STACK_SPACE(2 * (val2 - val + 1));
302
+ while (val <= val2) {
303
+ idx = 2 * val;
304
+ SAVE_CAPTURE(idx, NULL);
305
+ idx = 2 * val + 1;
306
+ SAVE_CAPTURE(idx, NULL);
307
+ val++;
308
+ }
309
+ }
310
+ BREAK;
311
+ CASE(REOP_set_i32):
312
+ idx = 2 * s->capture_count + pc[0];
313
+ val = get_u32(pc + 1);
314
+ pc += 5;
315
+ SAVE_CAPTURE_CHECK(idx, (void *)(uintptr_t)val);
316
+ BREAK;
317
+ CASE(REOP_loop):
318
+ {
319
+ uint32_t val2;
320
+ idx = 2 * s->capture_count + pc[0];
321
+ val = get_u32(pc + 1);
322
+ pc += 5;
323
+
324
+ val2 = (uintptr_t)capture[idx] - 1;
325
+ SAVE_CAPTURE_CHECK(idx, (void *)(uintptr_t)val2);
326
+ if (val2 != 0) {
327
+ pc += (int)val;
328
+ if (lre_poll_timeout(s))
329
+ return LRE_RET_TIMEOUT;
330
+ }
331
+ }
332
+ BREAK;
333
+ CASE(REOP_loop_split_goto_first):
334
+ CASE(REOP_loop_split_next_first):
335
+ CASE(REOP_loop_check_adv_split_goto_first):
336
+ CASE(REOP_loop_check_adv_split_next_first):
337
+ {
338
+ const uint8_t *pc1;
339
+ uint32_t val2, limit;
340
+ idx = 2 * s->capture_count + pc[0];
341
+ limit = get_u32(pc + 1);
342
+ val = get_u32(pc + 5);
343
+ pc += 9;
344
+
345
+ /* decrement the counter */
346
+ val2 = (uintptr_t)capture[idx] - 1;
347
+ SAVE_CAPTURE_CHECK(idx, (void *)(uintptr_t)val2);
348
+
349
+ if (val2 > limit) {
350
+ /* normal loop if counter > limit */
351
+ pc += (int)val;
352
+ if (lre_poll_timeout(s))
353
+ return LRE_RET_TIMEOUT;
354
+ } else {
355
+ /* check advance */
356
+ if ((opcode == REOP_loop_check_adv_split_goto_first ||
357
+ opcode == REOP_loop_check_adv_split_next_first) &&
358
+ capture[idx + 1] == cptr &&
359
+ val2 != limit) {
360
+ goto no_match;
361
+ }
362
+
363
+ /* otherwise conditional split */
364
+ if (val2 != 0) {
365
+ if (opcode == REOP_loop_split_next_first ||
366
+ opcode == REOP_loop_check_adv_split_next_first) {
367
+ pc1 = pc + (int)val;
368
+ } else {
369
+ pc1 = pc;
370
+ pc = pc + (int)val;
371
+ }
372
+ CHECK_STACK_SPACE(3);
373
+ sp[0].ptr = (uint8_t *)pc1;
374
+ sp[1].ptr = (uint8_t *)cptr;
375
+ sp[2].bp.val = bp - s->stack_buf;
376
+ sp[2].bp.type = RE_EXEC_STATE_SPLIT;
377
+ sp += 3;
378
+ bp = sp;
379
+ }
380
+ }
381
+ }
382
+ BREAK;
383
+ CASE(REOP_set_char_pos):
384
+ idx = 2 * s->capture_count + pc[0];
385
+ pc++;
386
+ SAVE_CAPTURE_CHECK(idx, (uint8_t *)cptr);
387
+ BREAK;
388
+ CASE(REOP_check_advance):
389
+ idx = 2 * s->capture_count + pc[0];
390
+ pc++;
391
+ if (capture[idx] == cptr)
392
+ goto no_match;
393
+ BREAK;
394
+ CASE(REOP_word_boundary):
395
+ CASE(REOP_word_boundary_i):
396
+ CASE(REOP_not_word_boundary):
397
+ CASE(REOP_not_word_boundary_i):
398
+ {
399
+ bool v1, v2;
400
+ int ignore_case = (opcode == REOP_word_boundary_i || opcode == REOP_not_word_boundary_i);
401
+ bool is_boundary = (opcode == REOP_word_boundary || opcode == REOP_word_boundary_i);
402
+ /* char before */
403
+ if (cptr == s->cbuf) {
404
+ v1 = false;
405
+ } else {
406
+ PEEK_PREV_CHAR(c, cptr, s->cbuf, cbuf_type);
407
+ if (c < 256) {
408
+ v1 = (lre_is_word_byte(c) != 0);
409
+ } else {
410
+ v1 = ignore_case && (c == 0x017f || c == 0x212a);
411
+ }
412
+ }
413
+ /* current char */
414
+ if (cptr >= cbuf_end) {
415
+ v2 = false;
416
+ } else {
417
+ PEEK_CHAR(c, cptr, cbuf_end, cbuf_type);
418
+ if (c < 256) {
419
+ v2 = (lre_is_word_byte(c) != 0);
420
+ } else {
421
+ v2 = ignore_case && (c == 0x017f || c == 0x212a);
422
+ }
423
+ }
424
+ if (v1 ^ v2 ^ is_boundary)
425
+ goto no_match;
426
+ }
427
+ BREAK;
428
+ CASE(REOP_back_reference):
429
+ CASE(REOP_back_reference_i):
430
+ CASE(REOP_backward_back_reference):
431
+ CASE(REOP_backward_back_reference_i):
432
+ {
433
+ const uint8_t *cptr1, *cptr1_end, *cptr1_start;
434
+ const uint8_t *pc1;
435
+ uint32_t c1, c2;
436
+ int i, n;
437
+
438
+ n = *pc++;
439
+ pc1 = pc;
440
+ pc += n;
441
+
442
+ for(i = 0; i < n; i++) {
443
+ val = pc1[i];
444
+ if (val >= s->capture_count)
445
+ goto no_match;
446
+ cptr1_start = capture[2 * val];
447
+ cptr1_end = capture[2 * val + 1];
448
+ /* test the first not empty capture */
449
+ if (cptr1_start && cptr1_end) {
450
+ if (opcode == REOP_back_reference ||
451
+ opcode == REOP_back_reference_i) {
452
+ cptr1 = cptr1_start;
453
+ while (cptr1 < cptr1_end) {
454
+ if (cptr >= cbuf_end)
455
+ goto no_match;
456
+ GET_CHAR(c1, cptr1, cptr1_end, cbuf_type);
457
+ GET_CHAR(c2, cptr, cbuf_end, cbuf_type);
458
+ if (opcode == REOP_back_reference_i) {
459
+ c1 = lre_canonicalize(c1, s->is_unicode);
460
+ c2 = lre_canonicalize(c2, s->is_unicode);
461
+ }
462
+ if (c1 != c2)
463
+ goto no_match;
464
+ }
465
+ } else {
466
+ cptr1 = cptr1_end;
467
+ while (cptr1 > cptr1_start) {
468
+ if (cptr == s->cbuf)
469
+ goto no_match;
470
+ GET_PREV_CHAR(c1, cptr1, cptr1_start, cbuf_type);
471
+ GET_PREV_CHAR(c2, cptr, s->cbuf, cbuf_type);
472
+ if (opcode == REOP_backward_back_reference_i) {
473
+ c1 = lre_canonicalize(c1, s->is_unicode);
474
+ c2 = lre_canonicalize(c2, s->is_unicode);
475
+ }
476
+ if (c1 != c2)
477
+ goto no_match;
478
+ }
479
+ }
480
+ break;
481
+ }
482
+ }
483
+ }
484
+ BREAK;
485
+ CASE(REOP_range):
486
+ CASE(REOP_range_i):
487
+ {
488
+ int n;
489
+ uint32_t low, high, idx_min, idx_max, idx;
490
+
491
+ n = get_u16(pc); /* n must be >= 1 */
492
+ pc += 2;
493
+ if (cptr >= cbuf_end)
494
+ goto no_match;
495
+ GET_CHAR(c, cptr, cbuf_end, cbuf_type);
496
+ if (opcode == REOP_range_i) {
497
+ c = lre_canonicalize(c, s->is_unicode);
498
+ }
499
+ idx_min = 0;
500
+ low = get_u16(pc + 0 * 4);
501
+ if (c < low)
502
+ goto no_match;
503
+ idx_max = n - 1;
504
+ high = get_u16(pc + idx_max * 4 + 2);
505
+ /* 0xffff in for last value means +infinity */
506
+ if (unlikely(c >= 0xffff) && high == 0xffff)
507
+ goto range_match;
508
+ if (c > high)
509
+ goto no_match;
510
+ while (idx_min <= idx_max) {
511
+ idx = (idx_min + idx_max) / 2;
512
+ low = get_u16(pc + idx * 4);
513
+ high = get_u16(pc + idx * 4 + 2);
514
+ if (c < low)
515
+ idx_max = idx - 1;
516
+ else if (c > high)
517
+ idx_min = idx + 1;
518
+ else
519
+ goto range_match;
520
+ }
521
+ goto no_match;
522
+ range_match:
523
+ pc += 4 * n;
524
+ }
525
+ BREAK;
526
+ CASE(REOP_range32):
527
+ CASE(REOP_range32_i):
528
+ {
529
+ int n;
530
+ uint32_t low, high, idx_min, idx_max, idx;
531
+
532
+ n = get_u16(pc); /* n must be >= 1 */
533
+ pc += 2;
534
+ if (cptr >= cbuf_end)
535
+ goto no_match;
536
+ GET_CHAR(c, cptr, cbuf_end, cbuf_type);
537
+ if (opcode == REOP_range32_i) {
538
+ c = lre_canonicalize(c, s->is_unicode);
539
+ }
540
+ idx_min = 0;
541
+ low = get_u32(pc + 0 * 8);
542
+ if (c < low)
543
+ goto no_match;
544
+ idx_max = n - 1;
545
+ high = get_u32(pc + idx_max * 8 + 4);
546
+ if (c > high)
547
+ goto no_match;
548
+ while (idx_min <= idx_max) {
549
+ idx = (idx_min + idx_max) / 2;
550
+ low = get_u32(pc + idx * 8);
551
+ high = get_u32(pc + idx * 8 + 4);
552
+ if (c < low)
553
+ idx_max = idx - 1;
554
+ else if (c > high)
555
+ idx_min = idx + 1;
556
+ else
557
+ goto range32_match;
558
+ }
559
+ goto no_match;
560
+ range32_match:
561
+ pc += 8 * n;
562
+ }
563
+ BREAK;
564
+ CASE(REOP_prev):
565
+ /* go to the previous char */
566
+ if (cptr == s->cbuf)
567
+ goto no_match;
568
+ PREV_CHAR(cptr, s->cbuf, cbuf_type);
569
+ BREAK;
570
+ CASE(REOP_invalid):
571
+ DEFAULT:
572
+ #ifdef DUMP_EXEC
573
+ printf("unknown opcode pc=%ld\n", (long)(pc - 1 - pc_start));
574
+ #endif
575
+ abort();
576
+ }
577
+ }
578
+ #undef SWITCH
579
+ #undef CASE
580
+ #undef DEFAULT
581
+ #undef BREAK
582
+ #undef LRE_DUMP_OP
583
+ }