]> git.kaiwu.me - njs.git/commitdiff
Parser: report an invalid "for-in" target as a SyntaxError
authorDmitry Volyntsev <xeioex@nginx.com>
Tue, 1 Sep 2026 01:31:20 +0000 (18:31 -0700)
committerDmitry Volyntsev <xeioexception@gmail.com>
Fri, 4 Sep 2026 20:56:37 +0000 (13:56 -0700)
Previously, an invalid for-in target was a ReferenceError when the
initializer happened to parse as a LeftHandSideExpression and a SyntaxError
otherwise, so the same target changed class once parenthesized:

    for (a = 1 in {});     SyntaxError
    for ((a = 1) in {});   ReferenceError

The fix is to report a SyntaxError for both, as the specification and V8 do.
The type is observable through Function(), so this is a compatibility change.
njs keeps ReferenceError for invalid assignment targets elsewhere.

src/njs_parser.c
src/test/njs_unit_test.c

index de447acd5af6e3b451b2c38d6eada32a03dd2104..010a9b4ec391cef68859aaac376e4f1a2741efdb 100644 (file)
@@ -5832,12 +5832,12 @@ njs_parser_for_expression_map_continue(njs_parser_t *parser,
         if (!njs_parser_is_lvalue(parser->node)) {
             text = (njs_str_t *) parser->target;
 
-            njs_parser_ref_error(parser, "Invalid left-hand side \"%V\" "
-                                 "in for-in statement", text);
-
             njs_mp_free(parser->vm->mem_pool, text);
 
-            return NJS_DONE;
+            njs_parser_syntax_error(parser,
+                                    "Invalid left-hand side in for-loop");
+
+            return NJS_ERROR;
         }
 
         parser->node = njs_parser_lvalue_ref(parser->node);
index 924dd9437ab9635b35a3b0b28517b8ba888a2feb..3f7a56a6e0dc1d49ea76d6136e5b2974a9fe0e98 100644 (file)
@@ -3403,8 +3403,38 @@ static njs_unit_test_t  njs_test[] =
 
     /* for in. */
 
+    /* An invalid for-in target is a SyntaxError, parenthesized or not. */
+
     { njs_str("for (null in undefined);"),
-      njs_str("ReferenceError: Invalid left-hand side \"null\" in for-in statement") },
+      njs_str("SyntaxError: Invalid left-hand side in for-loop") },
+
+    { njs_str("for ((null) in undefined);"),
+      njs_str("SyntaxError: Invalid left-hand side in for-loop") },
+
+    { njs_str("for (1 in {});"),
+      njs_str("SyntaxError: Invalid left-hand side in for-loop") },
+
+    { njs_str("for (this in {});"),
+      njs_str("SyntaxError: Invalid left-hand side in for-loop") },
+
+    { njs_str("for (function(){} in x);"),
+      njs_str("SyntaxError: Invalid left-hand side in for-loop") },
+
+    { njs_str("for ((a = 1) in {});"),
+      njs_str("SyntaxError: Invalid left-hand side in for-loop") },
+
+    { njs_str("for ((x => x) in {});"),
+      njs_str("SyntaxError: Invalid left-hand side in for-loop") },
+
+    { njs_str("var r; try { Function('for (null in undefined);') }"
+              "catch (e) { r = e.name } r"),
+      njs_str("SyntaxError") },
+
+    { njs_str("var d = {}; for (d.a in {x:1}); d.a"),
+      njs_str("x") },
+
+    { njs_str("var d = {}; for ((d.a) in {x:1}); d.a"),
+      njs_str("x") },
 
     { njs_str("for (var a, b in []);"),
       njs_str("SyntaxError: Unexpected token \"in\"") },