var behaves like let

This commit is contained in:
2025-12-29 00:37:26 -06:00
parent 3b53a9dcc3
commit 4f3e2819fe
6 changed files with 149 additions and 106 deletions

View File

@@ -15384,7 +15384,6 @@ enum {
/* FutureReservedWords when parsing strict mode code */
TOK_IMPLEMENTS,
TOK_INTERFACE,
TOK_LET,
TOK_PRIVATE,
TOK_PROTECTED,
TOK_PUBLIC,
@@ -18680,18 +18679,15 @@ static __exception int js_define_var(JSParseState *s, JSAtom name, int tok)
return js_parse_error(s, "invalid variable name in strict mode");
}
if (name == JS_ATOM_let
&& (tok == TOK_LET || tok == TOK_DEF)) {
&& tok == TOK_DEF) {
return js_parse_error(s, "invalid lexical variable name");
}
switch(tok) {
case TOK_LET:
var_def_type = JS_VAR_DEF_LET;
break;
case TOK_DEF:
var_def_type = JS_VAR_DEF_CONST;
break;
case TOK_VAR:
var_def_type = JS_VAR_DEF_VAR;
var_def_type = JS_VAR_DEF_LET;
break;
case TOK_CATCH:
var_def_type = JS_VAR_DEF_CATCH;
@@ -18749,7 +18745,7 @@ duplicate:
return js_parse_error(s, "duplicate parameter names not allowed in this context");
}
/* tok = TOK_VAR, TOK_LET or TOK_DEF. Return whether a reference
/* tok = TOK_VAR or TOK_DEF. Return whether a reference
must be taken to the variable for proper 'with' or global variable
evaluation */
/* Note: this function is needed only because variable references are
@@ -18757,12 +18753,8 @@ duplicate:
static BOOL need_var_reference(JSParseState *s, int tok)
{
JSFunctionDef *fd = s->cur_func;
if (tok != TOK_VAR)
return FALSE; /* no reference for let/const */
if (!fd->is_global_var)
return FALSE; /* local definitions in strict mode in function or direct eval */
return TRUE;
/* var now behaves like let - no reference needed */
return FALSE;
}
static JSAtom js_parse_destructuring_var(JSParseState *s, int tok, int is_arg)
@@ -19075,7 +19067,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
/* store value into lvalue object */
put_lvalue(s, opcode, scope, var_name, label_lvalue,
PUT_LVALUE_NOKEEP_DEPTH,
(tok == TOK_DEF || tok == TOK_LET));
(tok == TOK_DEF || tok == TOK_VAR));
if (s->token.val == '}')
break;
/* accept a trailing comma before the '}' */
@@ -19189,7 +19181,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
/* store value into lvalue object */
put_lvalue(s, opcode, scope, var_name,
label_lvalue, PUT_LVALUE_NOKEEP_DEPTH,
(tok == TOK_DEF || tok == TOK_LET));
(tok == TOK_DEF || tok == TOK_VAR));
}
if (s->token.val == ']')
break;
@@ -20516,7 +20508,7 @@ static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok,
return js_parse_error_reserved_identifier(s);
}
name = JS_DupAtom(ctx, s->token.u.ident.atom);
if (name == JS_ATOM_let && (tok == TOK_LET || tok == TOK_DEF)) {
if (name == JS_ATOM_let && tok == TOK_DEF) {
js_parse_error(s, "'let' is not a valid lexical identifier");
goto var_error;
}
@@ -20549,7 +20541,7 @@ static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok,
if (js_parse_assign_expr2(s, parse_flags))
goto var_error;
set_object_name(s, name);
emit_op(s, (tok == TOK_DEF || tok == TOK_LET) ?
emit_op(s, (tok == TOK_DEF || tok == TOK_VAR) ?
OP_scope_put_var_init : OP_scope_put_var);
emit_atom(s, name);
emit_u16(s, fd->scope_level);
@@ -20559,7 +20551,7 @@ static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok,
js_parse_error(s, "missing initializer for const variable");
goto var_error;
}
if (tok == TOK_LET) {
if (tok == TOK_VAR) {
/* initialize lexical variable upon entering its scope */
emit_op(s, OP_null);
emit_op(s, OP_scope_put_var_init);
@@ -20621,7 +20613,6 @@ static int is_let(JSParseState *s, int decl_mask)
}
if (s->token.val == '{' ||
(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved) ||
s->token.val == TOK_LET ||
s->token.val == TOK_YIELD ||
s->token.val == TOK_AWAIT) {
/* Check for possible ASI if not scanning for Declaration */
@@ -20682,16 +20673,7 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name)
emit_label(s, label_next);
tok = s->token.val;
switch (is_let(s, DECL_MASK_OTHER)) {
case TRUE:
tok = TOK_LET;
break;
case FALSE:
break;
default:
return -1;
}
if (tok == TOK_VAR || tok == TOK_LET || tok == TOK_DEF) {
if (tok == TOK_VAR || tok == TOK_DEF) {
if (next_token(s))
return -1;
@@ -20714,7 +20696,7 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name)
JS_FreeAtom(s->ctx, var_name);
return -1;
}
emit_op(s, (tok == TOK_DEF || tok == TOK_LET) ?
emit_op(s, (tok == TOK_DEF || tok == TOK_VAR) ?
OP_scope_put_var_init : OP_scope_put_var);
emit_atom(s, var_name);
emit_u16(s, fd->scope_level);
@@ -20948,7 +20930,6 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
goto fail;
}
break;
case TOK_LET:
case TOK_DEF:
haslet:
if (!(decl_mask & DECL_MASK_OTHER)) {
@@ -20957,6 +20938,10 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
}
/* fall thru */
case TOK_VAR:
if (!(decl_mask & DECL_MASK_OTHER)) {
js_parse_error(s, "lexical declarations can't appear in single-statement context");
goto fail;
}
if (next_token(s))
goto fail;
if (js_parse_var(s, TRUE, tok, FALSE))
@@ -21096,16 +21081,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
/* initial expression */
tok = s->token.val;
if (tok != ';') {
switch (is_let(s, DECL_MASK_OTHER)) {
case TRUE:
tok = TOK_LET;
break;
case FALSE:
break;
default:
goto fail;
}
if (tok == TOK_VAR || tok == TOK_LET || tok == TOK_DEF) {
if (tok == TOK_VAR || tok == TOK_DEF) {
if (next_token(s))
goto fail;
if (js_parse_var(s, FALSE, tok, FALSE))
@@ -21369,8 +21345,8 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
goto fail;
if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)) {
if (s->token.val == '[' || s->token.val == '{') {
/* XXX: TOK_LET is not completely correct */
if (js_parse_destructuring_element(s, TOK_LET, 0, TRUE, -1, TRUE, FALSE) < 0)
/* catch variables behave like var (block scoped) */
if (js_parse_destructuring_element(s, TOK_VAR, 0, TRUE, -1, TRUE, FALSE) < 0)
goto fail;
} else {
js_parse_error(s, "identifier expected");
@@ -21490,16 +21466,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
js_parse_error_reserved_identifier(s);
goto fail;
}
/* Determine if `let` introduces a Declaration or an ExpressionStatement */
switch (is_let(s, decl_mask)) {
case TRUE:
tok = TOK_LET;
goto haslet;
case FALSE:
break;
default:
goto fail;
}
/* let keyword is no longer supported */
if (token_is_pseudo_keyword(s, JS_ATOM_async) &&
peek_token(s, TRUE) == TOK_FUNCTION) {
if (!(decl_mask & DECL_MASK_OTHER)) {
@@ -25359,7 +25326,6 @@ static __exception int js_parse_directives(JSParseState *s)
case TOK_EXPORT:
case TOK_IMPORT:
case TOK_INTERFACE:
case TOK_LET:
/* automatic insertion of ';' */
if (s->got_lf)
has_semi = TRUE;
@@ -25581,7 +25547,7 @@ static __exception int js_parse_function_decl2(JSParseState *s,
emit_op(s, OP_get_arg);
emit_u16(s, idx);
}
has_initializer = js_parse_destructuring_element(s, fd->has_parameter_expressions ? TOK_LET : TOK_VAR, 1, TRUE, -1, TRUE, FALSE);
has_initializer = js_parse_destructuring_element(s, TOK_VAR, 1, TRUE, -1, TRUE, FALSE);
if (has_initializer < 0)
goto fail;
if (has_initializer)