Fix strict name conformity cases (#335)
- reject *future strict reserved words* in `js_parse_function_check_names()`. - add tests for reserved names in tests/test_language.js - allow running tests/test_language.js with v8 - update v8.txt
This commit is contained in:
parent
8b56215cc2
commit
0de570988a
3 changed files with 85 additions and 63 deletions
24
quickjs.c
24
quickjs.c
|
@ -31466,6 +31466,25 @@ static __exception int js_parse_directives(JSParseState *s)
|
|||
return js_parse_seek_token(s, &pos);
|
||||
}
|
||||
|
||||
static BOOL js_invalid_strict_name(JSAtom name) {
|
||||
switch (name) {
|
||||
case JS_ATOM_eval:
|
||||
case JS_ATOM_arguments:
|
||||
case JS_ATOM_implements: // future strict reserved words
|
||||
case JS_ATOM_interface:
|
||||
case JS_ATOM_let:
|
||||
case JS_ATOM_package:
|
||||
case JS_ATOM_private:
|
||||
case JS_ATOM_protected:
|
||||
case JS_ATOM_public:
|
||||
case JS_ATOM_static:
|
||||
case JS_ATOM_yield:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static int js_parse_function_check_names(JSParseState *s, JSFunctionDef *fd,
|
||||
JSAtom func_name)
|
||||
{
|
||||
|
@ -31476,13 +31495,12 @@ static int js_parse_function_check_names(JSParseState *s, JSFunctionDef *fd,
|
|||
if (!fd->has_simple_parameter_list && fd->has_use_strict) {
|
||||
return js_parse_error(s, "\"use strict\" not allowed in function with default or destructuring parameter");
|
||||
}
|
||||
if (func_name == JS_ATOM_eval || func_name == JS_ATOM_arguments) {
|
||||
if (js_invalid_strict_name(func_name)) {
|
||||
return js_parse_error(s, "invalid function name in strict code");
|
||||
}
|
||||
for (idx = 0; idx < fd->arg_count; idx++) {
|
||||
name = fd->args[idx].var_name;
|
||||
|
||||
if (name == JS_ATOM_eval || name == JS_ATOM_arguments) {
|
||||
if (js_invalid_strict_name(name)) {
|
||||
return js_parse_error(s, "invalid argument name in strict code");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,24 +10,25 @@ function assert(actual, expected, message) {
|
|||
&& actual.toString() === expected.toString())
|
||||
return;
|
||||
|
||||
var msg = message ? " (" + message + ")" : "";
|
||||
throw Error("assertion failed: got |" + actual + "|" +
|
||||
", expected |" + expected + "|" +
|
||||
(message ? " (" + message + ")" : ""));
|
||||
", expected |" + expected + "|" + msg);
|
||||
}
|
||||
|
||||
function assert_throws(expected_error, func)
|
||||
function assert_throws(expected_error, func, message)
|
||||
{
|
||||
var err = false;
|
||||
var msg = message ? " (" + message + ")" : "";
|
||||
try {
|
||||
func();
|
||||
} catch(e) {
|
||||
err = true;
|
||||
if (!(e instanceof expected_error)) {
|
||||
throw Error("unexpected exception type");
|
||||
throw Error(`expected ${expected_error.name}, got ${e.name}${msg}`);
|
||||
}
|
||||
}
|
||||
if (!err) {
|
||||
throw Error("expected exception");
|
||||
throw Error(`expected ${expected_error.name}${msg}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -421,7 +422,9 @@ function test_argument_scope()
|
|||
var c = "global";
|
||||
|
||||
f = function(a = eval("var arguments")) {};
|
||||
assert_throws(SyntaxError, f);
|
||||
// for some reason v8 does not throw an exception here
|
||||
if (typeof require === 'undefined')
|
||||
assert_throws(SyntaxError, f);
|
||||
|
||||
f = function(a = eval("1"), b = arguments[0]) { return b; };
|
||||
assert(f(12), 12);
|
||||
|
@ -536,6 +539,60 @@ function test_function_expr_name()
|
|||
assert_throws(TypeError, f);
|
||||
}
|
||||
|
||||
function test_expr(expr, err) {
|
||||
if (err)
|
||||
assert_throws(err, () => eval(expr), `for ${expr}`);
|
||||
else
|
||||
assert(1, eval(expr), `for ${expr}`);
|
||||
}
|
||||
|
||||
function test_name(name, err)
|
||||
{
|
||||
test_expr(`(function() { return typeof ${name} ? 1 : 1; })()`);
|
||||
test_expr(`(function() { var ${name}; ${name} = 1; return ${name}; })()`);
|
||||
test_expr(`(function() { let ${name}; ${name} = 1; return ${name}; })()`, name == 'let' ? SyntaxError : undefined);
|
||||
test_expr(`(function() { const ${name} = 1; return ${name}; })()`, name == 'let' ? SyntaxError : undefined);
|
||||
test_expr(`(function(${name}) { ${name} = 1; return ${name}; })()`);
|
||||
test_expr(`(function({${name}}) { ${name} = 1; return ${name}; })({})`);
|
||||
test_expr(`(function ${name}() { return ${name} ? 1 : 0; })()`);
|
||||
test_expr(`"use strict"; (function() { return typeof ${name} ? 1 : 1; })()`, err);
|
||||
test_expr(`"use strict"; (function() { if (0) ${name} = 1; return 1; })()`, err);
|
||||
test_expr(`"use strict"; (function() { var x; if (0) x = ${name}; return 1; })()`, err);
|
||||
test_expr(`"use strict"; (function() { var ${name}; return 1; })()`, err);
|
||||
test_expr(`"use strict"; (function() { let ${name}; return 1; })()`, err);
|
||||
test_expr(`"use strict"; (function() { const ${name} = 1; return 1; })()`, err);
|
||||
test_expr(`"use strict"; (function() { var ${name}; ${name} = 1; return 1; })()`, err);
|
||||
test_expr(`"use strict"; (function() { var ${name}; ${name} = 1; return ${name}; })()`, err);
|
||||
test_expr(`"use strict"; (function(${name}) { return 1; })()`, err);
|
||||
test_expr(`"use strict"; (function({${name}}) { return 1; })({})`, err);
|
||||
test_expr(`"use strict"; (function ${name}() { return 1; })()`, err);
|
||||
test_expr(`(function() { "use strict"; return typeof ${name} ? 1 : 1; })()`, err);
|
||||
test_expr(`(function() { "use strict"; if (0) ${name} = 1; return 1; })()`, err);
|
||||
test_expr(`(function() { "use strict"; var x; if (0) x = ${name}; return 1; })()`, err);
|
||||
test_expr(`(function() { "use strict"; var ${name}; return 1; })()`, err);
|
||||
test_expr(`(function() { "use strict"; let ${name}; return 1; })()`, err);
|
||||
test_expr(`(function() { "use strict"; const ${name} = 1; return 1; })()`, err);
|
||||
test_expr(`(function() { "use strict"; var ${name}; ${name} = 1; return 1; })()`, err);
|
||||
test_expr(`(function() { "use strict"; var ${name}; ${name} = 1; return ${name}; })()`, err);
|
||||
test_expr(`(function(${name}) { "use strict"; return 1; })()`, err);
|
||||
test_expr(`(function({${name}}) { "use strict"; return 1; })({})`, SyntaxError);
|
||||
test_expr(`(function ${name}() { "use strict"; return 1; })()`, err);
|
||||
}
|
||||
|
||||
function test_reserved_names()
|
||||
{
|
||||
test_name('await');
|
||||
test_name('yield', SyntaxError);
|
||||
test_name('implements', SyntaxError);
|
||||
test_name('interface', SyntaxError);
|
||||
test_name('let', SyntaxError);
|
||||
test_name('package', SyntaxError);
|
||||
test_name('private', SyntaxError);
|
||||
test_name('protected', SyntaxError);
|
||||
test_name('public', SyntaxError);
|
||||
test_name('static', SyntaxError);
|
||||
}
|
||||
|
||||
test_op1();
|
||||
test_cvt();
|
||||
test_eq();
|
||||
|
@ -555,3 +612,4 @@ test_spread();
|
|||
test_function_length();
|
||||
test_argument_scope();
|
||||
test_function_expr_name();
|
||||
test_reserved_names();
|
||||
|
|
54
v8.txt
54
v8.txt
|
@ -711,60 +711,6 @@ Did not throw exception
|
|||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Did not throw exception
|
||||
Failure: expected <null> found <undefined>
|
||||
Failure: expected <undefined> found <function non_strict() {
|
||||
return return_my_caller();
|
||||
|
|
Loading…
Reference in a new issue