diff options
-rw-r--r-- | js/src/frontend/Parser.cpp | 26 | ||||
-rw-r--r-- | js/src/tests/ecma_6/LexicalEnvironment/block-scoped-functions-annex-b-parameter.js | 5 | ||||
-rw-r--r-- | js/src/vm/Scope.cpp | 8 | ||||
-rw-r--r-- | js/src/vm/Scope.h | 11 |
4 files changed, 41 insertions, 9 deletions
diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 7e43bc3b5..2e13910df 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -1211,6 +1211,25 @@ Parser<ParseHandler>::tryDeclareVarForAnnexBLexicalFunction(HandlePropertyName n if (!tryDeclareVar(name, DeclarationKind::VarForAnnexBLexicalFunction, &redeclaredKind)) return false; + if (!redeclaredKind && pc->isFunctionBox()) { + ParseContext::Scope& funScope = pc->functionScope(); + ParseContext::Scope& varScope = pc->varScope(); + if (&funScope != &varScope) { + // Annex B.3.3.1 disallows redeclaring parameter names. In the + // presence of parameter expressions, parameter names are on the + // function scope, which encloses the var scope. This means + // tryDeclareVar call above would not catch this case, so test it + // manually. + if (AddDeclaredNamePtr p = funScope.lookupDeclaredNameForAdd(name)) { + DeclarationKind declaredKind = p->value()->kind(); + if (DeclarationKindIsParameter(declaredKind)) + redeclaredKind = Some(declaredKind); + else + MOZ_ASSERT(FunctionScope::isSpecialName(context, name)); + } + } + } + if (redeclaredKind) { // If an early error would have occurred, undo all the // VarForAnnexBLexicalFunction declarations. @@ -1751,11 +1770,8 @@ Parser<FullParseHandler>::newFunctionScopeData(ParseContext::Scope& scope, bool case BindingKind::Var: // The only vars in the function scope when there are parameter // exprs, which induces a separate var environment, should be the - // special internal bindings. - MOZ_ASSERT_IF(hasParameterExprs, - bi.name() == context->names().arguments || - bi.name() == context->names().dotThis || - bi.name() == context->names().dotGenerator); + // special bindings. + MOZ_ASSERT_IF(hasParameterExprs, FunctionScope::isSpecialName(context, bi.name())); if (!vars.append(binding)) return Nothing(); break; diff --git a/js/src/tests/ecma_6/LexicalEnvironment/block-scoped-functions-annex-b-parameter.js b/js/src/tests/ecma_6/LexicalEnvironment/block-scoped-functions-annex-b-parameter.js index f0adedf7d..ae7fbe879 100644 --- a/js/src/tests/ecma_6/LexicalEnvironment/block-scoped-functions-annex-b-parameter.js +++ b/js/src/tests/ecma_6/LexicalEnvironment/block-scoped-functions-annex-b-parameter.js @@ -11,6 +11,11 @@ assertEq(f, 123); }(123)); +(function(f = 123) { + assertEq(f, 123); + { function f() { } } + assertEq(f, 123); +}()); if (typeof reportCompare === "function") reportCompare(true, true); diff --git a/js/src/vm/Scope.cpp b/js/src/vm/Scope.cpp index a71c03695..0f80d7b69 100644 --- a/js/src/vm/Scope.cpp +++ b/js/src/vm/Scope.cpp @@ -669,6 +669,14 @@ FunctionScope::script() const return canonicalFunction()->nonLazyScript(); } +/* static */ bool +FunctionScope::isSpecialName(ExclusiveContext* cx, JSAtom* name) +{ + return name == cx->names().arguments || + name == cx->names().dotThis || + name == cx->names().dotGenerator; +} + /* static */ Shape* FunctionScope::getEmptyEnvironmentShape(ExclusiveContext* cx, bool hasParameterExprs) { diff --git a/js/src/vm/Scope.h b/js/src/vm/Scope.h index 1d04fd9f6..4a4ae8090 100644 --- a/js/src/vm/Scope.h +++ b/js/src/vm/Scope.h @@ -446,10 +446,11 @@ Scope::is<LexicalScope>() const } // -// Scope corresponding to a function. Holds formal parameter names and, if the -// function parameters contain no expressions that might possibly be -// evaluated, the function's var bindings. For example, in these functions, -// the FunctionScope will store a/b/c bindings but not d/e/f bindings: +// Scope corresponding to a function. Holds formal parameter names, special +// internal names (see FunctionScope::isSpecialName), and, if the function +// parameters contain no expressions that might possibly be evaluated, the +// function's var bindings. For example, in these functions, the FunctionScope +// will store a/b/c bindings but not d/e/f bindings: // // function f1(a, b) { // var cÍž @@ -562,6 +563,8 @@ class FunctionScope : public Scope return data().nonPositionalFormalStart; } + static bool isSpecialName(ExclusiveContext* cx, JSAtom* name); + static Shape* getEmptyEnvironmentShape(ExclusiveContext* cx, bool hasParameterExprs); }; |