`continue` to an outer label of a label set (`a: b: for (…) continue a;`) gives "break/continue label not found"
I maintainer di solito rispondono entro 3 giorni
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 48/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- c, javascript
Direzione di ricerca
Start in quickjs.c at js_parse_statement_or_decl, push_break_entry, and emit_break; the issue identifies the current limitation and includes a proposed change. Add or inspect regression coverage in tests/test_language.js for chained labels, including valid continue targets and invalid targets through non-loop statements. Run make test and compare test262 results with test262_errors.txt; done means the reproduction prints 2 and the invalid cases remain SyntaxErrors.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Environment
- QuickJS master 712e8c0 (2026-11-02) and release 2026-06-04,
make qjs, Debian 12 x86-64, gcc 12.2 - Reference: node v26.13.0
- Checked on 2026-11-03
Reproduction
var n = 0;
a: b: for (var i = 0; i < 2; i++) { n++; continue a; }
console.log(n);
Expected 2. QuickJS: SyntaxError: break/continue label not found. continue b and break a work. The same
happens with while, do … while, for-in/for-of and longer label chains.
Expected (spec)
ContainsUndefinedContinueTarget:
each LabelledStatement appends its label to labelSet, and BreakableStatement : IterationStatement adds the whole
labelSet to iterationSet. The loop's label set is « a, b », so continue a is valid and continues the loop
(LoopContinues). a: { b: for (;;) continue a; } and
a: b: if (1) for (;;) continue a; must remain SyntaxErrors.
Cause and patch
js_parse_statement_or_decl notes /* XXX: support multiple labels on loop statements */. Only the last label becomes
the loop's BlockEnv.label_name; the outer labels are labelled regular statements with label_cont == -1. The patch
below (with a test in tests/test_language.js; make test passes, and test262 shows no new failures against
test262_errors.txt) lets those entries point at the loop they directly label and maps continue <outer> to the loop's
label in emit_break():
diff --git a/quickjs.c b/quickjs.c
--- a/quickjs.c
+++ b/quickjs.c
@@ -22471,6 +22471,9 @@ enum {
typedef struct BlockEnv {
struct BlockEnv *prev;
+ /* loop directly labelled by this label statement (a: b: for ...), so
+ that `continue a` targets that loop */
+ struct BlockEnv *cont_alias;
JSAtom label_name; /* JS_ATOM_NULL if none */
int label_break; /* -1 if none */
int label_cont; /* -1 if none */
@@ -22482,6 +22485,7 @@ typedef struct BlockEnv {
uint8_t has_iterator : 1;
uint8_t is_async_iterator : 1;
uint8_t is_regular_stmt : 1; /* i.e. not a loop statement */
+ uint8_t labels_next : 1; /* label statement whose body is another label */
uint8_t has_using : 1; /* the block contains a using declaration */
uint8_t is_await_using : 1; /* the block has await using declarations */
} BlockEnv;
@@ -28958,8 +28962,11 @@ static void push_break_entry(JSFunctionDef *fd, BlockEnv *be,
int label_break, int label_cont,
int drop_count)
{
+ BlockEnv *p;
be->prev = fd->top_break;
fd->top_break = be;
+ be->cont_alias = NULL;
+ be->labels_next = 0;
be->label_name = label_name;
be->label_break = label_break;
be->label_cont = label_cont;
@@ -28973,6 +28980,10 @@ static void push_break_entry(JSFunctionDef *fd, BlockEnv *be,
be->is_await_using = FALSE;
be->using_label_catch = -1;
be->using_label_end = -1;
+ if (label_cont != -1) {
+ for (p = be->prev; p && p->is_regular_stmt && p->labels_next; p = p->prev)
+ p->cont_alias = be;
+ }
}
static void js_emit_dispose_scope(JSParseState *s, int scope,
@@ -29089,6 +29100,15 @@ static __exception int emit_break(JSParseState *s, JSAtom name, int is_cont)
int i, scope_level;
scope_level = s->cur_func->scope_level;
+ if (is_cont && name != JS_ATOM_NULL) {
+ for (top = s->cur_func->top_break; top; top = top->prev) {
+ if (top->label_name == name) {
+ if (top->cont_alias)
+ name = top->cont_alias->label_name;
+ break;
+ }
+ }
+ }
top = s->cur_func->top_break;
while (top != NULL) {
close_scopes(s, scope_level, top->scope_level);
@@ -29807,7 +29827,6 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
int tok;
/* specific label handling */
- /* XXX: support multiple labels on loop statements */
label_name = JS_ATOM_NULL;
if (is_label(s)) {
BlockEnv *be;
@@ -29836,6 +29855,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
push_break_entry(s->cur_func, &break_entry,
label_name, label_break, -1, 0);
break_entry.is_regular_stmt = TRUE;
+ s->cur_func->top_break->labels_next = is_label(s);
if (!(s->cur_func->js_mode & JS_MODE_STRICT) &&
(decl_mask & DECL_MASK_FUNC_WITH_LABEL)) {
mask = DECL_MASK_FUNC | DECL_MASK_FUNC_WITH_LABEL;
Related
- quickjs-ng has the same code: quickjs-ng/quickjs#1884
- #592 (
continueinfor (let …)skips the per-iteration copy) is a separate bug in the same loop code. The fixes are independent.
- Lingua principale
- C
- Stelle
- 11.1k
- Fork
- 1.2k
- Merge medio
- 11h 20m
- PR unite (30g)
- 1
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di bellard/quickjs
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 55/100
I maintainer di solito rispondono entro 3 giorni
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 55/100
I maintainer di solito rispondono entro 3 giorni
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 35/100
bellard/quickjs#602 · 1 commento ·
I maintainer di solito rispondono entro 3 giorni
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 45/100
I maintainer di solito rispondono entro 3 giorni
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 58/100
I maintainer di solito rispondono entro 3 giorni
Tutte le issue di bellard/quickjs
Issue simili
-
要トリアージ 辞書
Difficoltà 1/5 1-3 ore Idoneità per principianti 86/100
yksr-melt/Meltype#1625 · 1 reazione ·
I maintainer di solito rispondono entro 1 giorno
-
[yugabyted] xcluster set_up and add_to_replication fail for database names containing - . or (Apertakind/bug priority/medium qa_automation
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
yugabyte/yugabyte-db#37324 ·
I maintainer di solito rispondono entro 1 giorno
-
Add CMake export targetAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
tree-sitter/tree-sitter#6111 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
meshcore-dev/MeshCore#3781 ·
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 80/100
ly05010419/MacNativeGames#1897 ·
I maintainer di solito rispondono entro 1 giorno