diff --git a/crates/js/src/parser.rs b/crates/js/src/parser.rs index ebecab4ca..17424e42f 100644 --- a/crates/js/src/parser.rs +++ b/crates/js/src/parser.rs @@ -500,6 +500,11 @@ impl<'s> Parser<'s> { let mut decls = self.parse_var_decls(true)?; if decls.len() == 1 && self.at_keyword(Keyword::In) { let decl = decls.pop().ok_or_else(|| self.unexpected())?; + // The variable of a for-in loop takes an initializer only outside strict mode + // code (ECMA-262 2017 Annex B.3.6). + if self.ctx.strict && decl.init.is_some() { + return Err(self.error_at_token(&self.tok, "a for-in variable cannot have an initializer in strict mode code")); + } return self.parse_for_in(ForInTarget::Var(decl), start); } Some(ForInit::Var(decls)) diff --git a/crates/js/src/tests.rs b/crates/js/src/tests.rs index a4e73d275..fc4b5b1a1 100644 --- a/crates/js/src/tests.rs +++ b/crates/js/src/tests.rs @@ -466,6 +466,10 @@ fn strict_mode_early_errors() { } assert!(strict_err("function f(a, a) {}").message.contains("duplicate parameter")); ok("function f(a, a) {}"); + let e = strict_err("for (var x = 1 in o) {}"); + assert!(e.message.contains("initializer"), "{}", e.message); + assert_eq!((e.line, e.column), (2, 16)); + ok("'use strict'; for (var x in o) {}"); } #[test]