Allow 'undefined' in let or const declaration (#639)

Except at the global scope of a classic script because... who knows,
that's just how it is.

Fixes: https://github.com/quickjs-ng/quickjs/issues/633
This commit is contained in:
Ben Noordhuis 2024-10-29 22:55:22 +01:00 committed by GitHub
parent 42262a7c53
commit dfe5675f25
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 35 additions and 4 deletions

View file

@ -22709,9 +22709,17 @@ static __exception int js_define_var(JSParseState *s, JSAtom name, int tok)
&& fd->is_strict_mode) { && fd->is_strict_mode) {
return js_parse_error(s, "invalid variable name in strict mode"); return js_parse_error(s, "invalid variable name in strict mode");
} }
if ((name == JS_ATOM_let || name == JS_ATOM_undefined) if (tok == TOK_LET || tok == TOK_CONST) {
&& (tok == TOK_LET || tok == TOK_CONST)) { if (name == JS_ATOM_let)
return js_parse_error(s, "invalid lexical variable name"); return js_parse_error(s, "invalid lexical variable name 'let'");
// |undefined| is allowed as an identifier except at the global
// scope of a classic script; sloppy or strict doesn't matter
if (name == JS_ATOM_undefined
&& fd->scope_level == 1
&& fd->is_global_var
&& !fd->module) {
return js_parse_error(s, "'undefined' already declared");
}
} }
switch(tok) { switch(tok) {
case TOK_LET: case TOK_LET:

View file

@ -1783,6 +1783,7 @@ int run_test(const char *filename, int *msec)
char *error_type; char *error_type;
int ret, eval_flags, use_strict, use_nostrict; int ret, eval_flags, use_strict, use_nostrict;
BOOL is_negative, is_nostrict, is_onlystrict, is_async, is_module, skip; BOOL is_negative, is_nostrict, is_onlystrict, is_async, is_module, skip;
BOOL detect_module = TRUE;
BOOL can_block; BOOL can_block;
namelist_t include_list = { 0 }, *ip = &include_list; namelist_t include_list = { 0 }, *ip = &include_list;
@ -1838,6 +1839,9 @@ int run_test(const char *filename, int *msec)
is_async = TRUE; is_async = TRUE;
skip |= skip_async; skip |= skip_async;
} }
else if (str_equal(option, "qjs:no-detect-module")) {
detect_module = FALSE;
}
else if (str_equal(option, "module")) { else if (str_equal(option, "module")) {
is_module = TRUE; is_module = TRUE;
skip |= skip_module; skip |= skip_module;
@ -1920,7 +1924,7 @@ int run_test(const char *filename, int *msec)
atomic_inc(&test_skipped); atomic_inc(&test_skipped);
ret = -2; ret = -2;
} else { } else {
if (local) { if (local && detect_module) {
is_module = JS_DetectModule(buf, buf_len); is_module = JS_DetectModule(buf, buf_len);
} }
if (is_module) { if (is_module) {

7
tests/bug633/0.js Normal file
View file

@ -0,0 +1,7 @@
/*---
flags: [qjs:no-detect-module]
negative:
phase: parse
type: SyntaxError
---*/
const undefined = 42 // SyntaxError at global scope

4
tests/bug633/1.js Normal file
View file

@ -0,0 +1,4 @@
/*---
flags: [qjs:no-detect-module, module]
---*/
const undefined = 42 // not a SyntaxError at toplevel module scope

4
tests/bug633/2.js Normal file
View file

@ -0,0 +1,4 @@
/*---
flags: [qjs:no-detect-module]
---*/
{ const undefined = 42 } // not a SyntaxError, not at global scope

4
tests/bug633/3.js Normal file
View file

@ -0,0 +1,4 @@
/*---
flags: [qjs:no-detect-module]
---*/
;(function() { const undefined = 42 })() // not a SyntaxError, not at global scope