1340148 - Disallow function redeclarations at module top level.
This commit is contained in:
parent
bc64f5e333
commit
0154fa01b6
|
@ -78,6 +78,7 @@ enum class DeclarationKind : uint8_t
|
|||
Const,
|
||||
Import,
|
||||
BodyLevelFunction,
|
||||
ModuleBodyLevelFunction,
|
||||
LexicalFunction,
|
||||
VarForAnnexBLexicalFunction,
|
||||
SimpleCatchParameter,
|
||||
|
@ -95,6 +96,7 @@ DeclarationKindToBindingKind(DeclarationKind kind)
|
|||
|
||||
case DeclarationKind::Var:
|
||||
case DeclarationKind::BodyLevelFunction:
|
||||
case DeclarationKind::ModuleBodyLevelFunction:
|
||||
case DeclarationKind::VarForAnnexBLexicalFunction:
|
||||
case DeclarationKind::ForOfVar:
|
||||
return BindingKind::Var;
|
||||
|
|
|
@ -119,6 +119,7 @@ DeclarationKindString(DeclarationKind kind)
|
|||
case DeclarationKind::Import:
|
||||
return "import";
|
||||
case DeclarationKind::BodyLevelFunction:
|
||||
case DeclarationKind::ModuleBodyLevelFunction:
|
||||
case DeclarationKind::LexicalFunction:
|
||||
return "function";
|
||||
case DeclarationKind::VarForAnnexBLexicalFunction:
|
||||
|
@ -1380,6 +1381,24 @@ Parser<ParseHandler>::noteDeclaredName(HandlePropertyName name, DeclarationKind
|
|||
break;
|
||||
}
|
||||
|
||||
case DeclarationKind::ModuleBodyLevelFunction: {
|
||||
MOZ_ASSERT(pc->atModuleLevel());
|
||||
|
||||
AddDeclaredNamePtr p = pc->varScope().lookupDeclaredNameForAdd(name);
|
||||
if (p) {
|
||||
reportRedeclaration(name, p->value()->kind(), pos, p->value()->pos());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!pc->varScope().addDeclaredName(pc, p, name, kind, pos.begin))
|
||||
return false;
|
||||
|
||||
// Body-level functions in modules are always closed over.
|
||||
pc->varScope().lookupDeclaredName(name)->value()->setClosedOver();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DeclarationKind::FormalParameter: {
|
||||
// It is an early error if any non-positional formal parameter name
|
||||
// (e.g., destructuring formal parameter) is duplicated.
|
||||
|
@ -3750,12 +3769,11 @@ Parser<ParseHandler>::functionStmt(uint32_t preludeStart, YieldHandling yieldHan
|
|||
if (!noteDeclaredName(name, DeclarationKind::LexicalFunction, pos()))
|
||||
return null();
|
||||
} else {
|
||||
if (!noteDeclaredName(name, DeclarationKind::BodyLevelFunction, pos()))
|
||||
DeclarationKind kind = pc->atModuleLevel()
|
||||
? DeclarationKind::ModuleBodyLevelFunction
|
||||
: DeclarationKind::BodyLevelFunction;
|
||||
if (!noteDeclaredName(name, kind, pos()))
|
||||
return null();
|
||||
|
||||
// Body-level functions in modules are always closed over.
|
||||
if (pc->atModuleLevel())
|
||||
pc->varScope().lookupDeclaredName(name)->value()->setClosedOver();
|
||||
}
|
||||
|
||||
Node pn = handler.newFunctionStatement();
|
||||
|
|
2
js/src/jit-test/modules/export-default-async-asi.js
Normal file
2
js/src/jit-test/modules/export-default-async-asi.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
export default async // ASI occurs here due to the [no LineTerminator here] restriction on default-exporting an async function
|
||||
function async() { return 17; }
|
94
js/src/jit-test/tests/modules/function-redeclaration.js
Normal file
94
js/src/jit-test/tests/modules/function-redeclaration.js
Normal file
|
@ -0,0 +1,94 @@
|
|||
load(libdir + "asserts.js");
|
||||
|
||||
var functionDeclarations = [
|
||||
"function f(){}",
|
||||
"function* f(){}",
|
||||
"async function f(){}",
|
||||
];
|
||||
|
||||
var varDeclarations = [
|
||||
"var f",
|
||||
"{ var f; }",
|
||||
"for (var f in null);",
|
||||
"for (var f of null);",
|
||||
"for (var f; ;);",
|
||||
];
|
||||
|
||||
var lexicalDeclarations = [
|
||||
"let f;",
|
||||
"const f = 0;",
|
||||
"class f {};",
|
||||
];
|
||||
|
||||
var imports = [
|
||||
"import f from '';",
|
||||
"import f, {} from '';",
|
||||
"import d, {f} from '';",
|
||||
"import d, {f as f} from '';",
|
||||
"import d, {foo as f} from '';",
|
||||
"import f, * as d from '';",
|
||||
"import d, * as f from '';",
|
||||
"import {f} from '';",
|
||||
"import {f as f} from '';",
|
||||
"import {foo as f} from '';",
|
||||
"import* as f from '';",
|
||||
];
|
||||
|
||||
var exports = [
|
||||
"export var f;",
|
||||
...functionDeclarations.map(fn => `export ${fn};`),
|
||||
...lexicalDeclarations.map(ld => `export ${ld};`),
|
||||
...functionDeclarations.map(fn => `export default ${fn};`),
|
||||
"export default class f {};",
|
||||
];
|
||||
|
||||
var redeclarations = [
|
||||
...functionDeclarations,
|
||||
...varDeclarations,
|
||||
...lexicalDeclarations,
|
||||
...imports,
|
||||
...exports,
|
||||
];
|
||||
|
||||
var noredeclarations = [
|
||||
...functionDeclarations.map(fn => `{ ${fn} }`),
|
||||
...lexicalDeclarations.map(ld => `{ ${ld} }`),
|
||||
...["let", "const"].map(ld => `for (${ld} f in null);`),
|
||||
...["let", "const"].map(ld => `for (${ld} f of null);`),
|
||||
...["let", "const"].map(ld => `for (${ld} f = 0; ;);`),
|
||||
"export {f};",
|
||||
"export {f as f};",
|
||||
"export {foo as f}; var foo;",
|
||||
"export {f} from '';",
|
||||
"export {f as f} from '';",
|
||||
"export {foo as f} from '';",
|
||||
];
|
||||
|
||||
for (var decl of functionDeclarations) {
|
||||
for (var redecl of redeclarations) {
|
||||
assertThrowsInstanceOf(() => {
|
||||
parseModule(`
|
||||
${decl}
|
||||
${redecl}
|
||||
`);
|
||||
}, SyntaxError);
|
||||
|
||||
assertThrowsInstanceOf(() => {
|
||||
parseModule(`
|
||||
${redecl}
|
||||
${decl}
|
||||
`);
|
||||
}, SyntaxError);
|
||||
}
|
||||
|
||||
for (var redecl of noredeclarations) {
|
||||
parseModule(`
|
||||
${decl}
|
||||
${redecl}
|
||||
`);
|
||||
parseModule(`
|
||||
${redecl}
|
||||
${decl}
|
||||
`);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user