MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

correctly handle continue statements inside switches within loops

+82 -21
examples/npm/preact/ant.lockb

This is a binary file and will not be displayed.

+17
examples/npm/preact/app.jsx
··· 1 + import { render } from 'https://esm.sh/preact-render-to-string'; 2 + 3 + const App = () => ( 4 + <div id="root"> 5 + <h1>Hello from Preact!</h1> 6 + <p style="color:red;font-size:16px">Styled text</p> 7 + <input type="text" disabled /> 8 + <ul> 9 + <li>No Babel</li> 10 + <li>No Webpack</li> 11 + <li>Just Preact</li> 12 + </ul> 13 + </div> 14 + ); 15 + 16 + const html = render(<App />); 17 + console.log(html);
+15
examples/npm/preact/index.js
··· 1 + import { build } from 'esbuild'; 2 + import { join } from 'node:path'; 3 + 4 + const { outputFiles } = await build({ 5 + entryPoints: [join(import.meta.dirname, 'app.jsx')], 6 + bundle: true, 7 + write: false, 8 + jsx: 'automatic', 9 + format: 'esm', 10 + jsxImportSource: 'preact', 11 + platform: 'neutral' 12 + }); 13 + 14 + const code = outputFiles[0].text; 15 + await import(`data:text/javascript,${encodeURIComponent(code)}`);
+13
examples/npm/preact/package.json
··· 1 + { 2 + "name": "preact", 3 + "version": "1.0.0", 4 + "type": "module", 5 + "main": "index.js", 6 + "scripts": { 7 + "start": "ant index.js" 8 + }, 9 + "dependencies": { 10 + "preact": "^10.29.0", 11 + "esbuild": "^0.27.3" 12 + } 13 + }
+21 -21
src/silver/compiler.c
··· 34 34 int scope_depth; 35 35 const char *label; 36 36 uint32_t label_len; 37 + bool is_switch; 37 38 } sv_loop_t; 38 39 39 40 typedef struct { ··· 533 534 534 535 static void push_loop( 535 536 sv_compiler_t *c, int loop_start, 536 - const char *label, uint32_t label_len 537 + const char *label, uint32_t label_len, 538 + bool is_switch 537 539 ) { 538 540 if (c->loop_count >= c->loop_cap) { 539 541 c->loop_cap = c->loop_cap ? c->loop_cap * 2 : 4; ··· 549 551 .loop_start = loop_start, 550 552 .scope_depth = c->scope_depth, 551 553 .label = label, .label_len = label_len, 554 + .is_switch = is_switch, 552 555 }; 553 556 } 554 557 ··· 2643 2646 2644 2647 static void compile_while(sv_compiler_t *c, sv_ast_t *node) { 2645 2648 int loop_start = c->code_len; 2646 - push_loop(c, loop_start, NULL, 0); 2649 + push_loop(c, loop_start, NULL, 0, false); 2647 2650 2648 2651 compile_expr(c, node->cond); 2649 2652 int exit_jump = emit_jump(c, OP_JMP_FALSE); ··· 2661 2664 2662 2665 static void compile_do_while(sv_compiler_t *c, sv_ast_t *node) { 2663 2666 int loop_start = c->code_len; 2664 - push_loop(c, loop_start, NULL, 0); 2667 + push_loop(c, loop_start, NULL, 0, false); 2665 2668 2666 2669 compile_stmt(c, node->body); 2667 2670 ··· 2761 2764 } 2762 2765 2763 2766 int loop_start = c->code_len; 2764 - push_loop(c, loop_start, NULL, 0); 2767 + push_loop(c, loop_start, NULL, 0, false); 2765 2768 2766 2769 int exit_jump = -1; 2767 2770 if (node->cond) { ··· 2947 2950 } 2948 2951 2949 2952 int loop_start = c->code_len; 2950 - push_loop(c, loop_start, NULL, 0); 2953 + push_loop(c, loop_start, NULL, 0, false); 2951 2954 2952 2955 if (is_for_of) { 2953 2956 emit_op(c, is_for_await ? OP_AWAIT_ITER_NEXT : OP_ITER_NEXT); ··· 3068 3071 3069 3072 3070 3073 static void compile_continue(sv_compiler_t *c, sv_ast_t *node) { 3071 - if (c->loop_count == 0) return; 3072 - 3073 - int target = c->loop_count - 1; 3074 + for (int i = c->loop_count - 1; i >= 0; i--) { 3074 3075 if (node->str) { 3075 - for (int i = c->loop_count - 1; i >= 0; i--) { 3076 - if (c->loops[i].label && 3077 - c->loops[i].label_len == node->len && 3078 - memcmp(c->loops[i].label, node->str, node->len) == 0) { 3079 - target = i; 3080 - break; 3081 - } 3076 + if ( 3077 + c->loops[i].label && 3078 + c->loops[i].label_len == node->len && 3079 + memcmp(c->loops[i].label, node->str, node->len) == 0) { 3080 + patch_list_add(&c->loops[i].continues, emit_jump(c, OP_JMP)); 3081 + return; 3082 3082 } 3083 + } else if (!c->loops[i].is_switch) { 3084 + patch_list_add(&c->loops[i].continues, emit_jump(c, OP_JMP)); 3085 + return; 3083 3086 } 3084 - 3085 - int offset = emit_jump(c, OP_JMP); 3086 - patch_list_add(&c->loops[target].continues, offset); 3087 - } 3087 + }} 3088 3088 3089 3089 static void compile_finally_block(sv_compiler_t *c, sv_ast_t *finally_body) { 3090 3090 int finally_jump = emit_jump(c, OP_FINALLY); ··· 3184 3184 3185 3185 compile_expr(c, node->cond); 3186 3186 begin_scope(c); 3187 - push_loop(c, c->code_len, NULL, 0); 3187 + push_loop(c, c->code_len, NULL, 0, true); 3188 3188 3189 3189 for (int i = 0; i < case_count; i++) { 3190 3190 sv_ast_t *cas = node->args.items[i]; ··· 3250 3250 c->pending_label = NULL; 3251 3251 c->pending_label_len = 0; 3252 3252 } else { 3253 - push_loop(c, c->code_len, node->str, node->len); 3253 + push_loop(c, c->code_len, node->str, node->len, false); 3254 3254 compile_stmt(c, node->body); 3255 3255 pop_loop(c); 3256 3256 }
+16
tests/continue_inner_check.js
··· 1 + // MVP: "continue" inside switch inside for...in loop 2 + 3 + const obj = { a: 1, b: 2, c: 3 }; 4 + const results = []; 5 + 6 + for (let key in obj) { 7 + switch (key) { 8 + case "b": 9 + continue; // should skip to next for...in iteration 10 + default: 11 + results.push(key); 12 + } 13 + } 14 + 15 + console.log("expected: ['a','c']"); 16 + console.log("got:", JSON.stringify(results));