зеркало из https://github.com/mozilla/gecko-dev.git
Bug 636635 - Do not create named lambda binding for a function created by Function constructor. r=till
This commit is contained in:
Родитель
1488382d5a
Коммит
2ed4747eb8
|
@ -2158,7 +2158,7 @@ Parser<ParseHandler>::declareDotGeneratorName()
|
|||
|
||||
template <typename ParseHandler>
|
||||
bool
|
||||
Parser<ParseHandler>::finishFunctionScopes()
|
||||
Parser<ParseHandler>::finishFunctionScopes(bool isStandaloneFunction)
|
||||
{
|
||||
FunctionBox* funbox = pc->functionBox();
|
||||
|
||||
|
@ -2167,7 +2167,7 @@ Parser<ParseHandler>::finishFunctionScopes()
|
|||
return false;
|
||||
}
|
||||
|
||||
if (funbox->function()->isNamedLambda()) {
|
||||
if (funbox->function()->isNamedLambda() && !isStandaloneFunction) {
|
||||
if (!propagateFreeNamesAndMarkClosedOverBindings(pc->namedLambdaScope()))
|
||||
return false;
|
||||
}
|
||||
|
@ -2177,9 +2177,9 @@ Parser<ParseHandler>::finishFunctionScopes()
|
|||
|
||||
template <>
|
||||
bool
|
||||
Parser<FullParseHandler>::finishFunction()
|
||||
Parser<FullParseHandler>::finishFunction(bool isStandaloneFunction /* = false */)
|
||||
{
|
||||
if (!finishFunctionScopes())
|
||||
if (!finishFunctionScopes(isStandaloneFunction))
|
||||
return false;
|
||||
|
||||
FunctionBox* funbox = pc->functionBox();
|
||||
|
@ -2200,7 +2200,7 @@ Parser<FullParseHandler>::finishFunction()
|
|||
funbox->functionScopeBindings().set(*bindings);
|
||||
}
|
||||
|
||||
if (funbox->function()->isNamedLambda()) {
|
||||
if (funbox->function()->isNamedLambda() && !isStandaloneFunction) {
|
||||
Maybe<LexicalScope::Data*> bindings = newLexicalScopeData(pc->namedLambdaScope());
|
||||
if (!bindings)
|
||||
return false;
|
||||
|
@ -2212,14 +2212,14 @@ Parser<FullParseHandler>::finishFunction()
|
|||
|
||||
template <>
|
||||
bool
|
||||
Parser<SyntaxParseHandler>::finishFunction()
|
||||
Parser<SyntaxParseHandler>::finishFunction(bool isStandaloneFunction /* = false */)
|
||||
{
|
||||
// The LazyScript for a lazily parsed function needs to know its set of
|
||||
// free variables and inner functions so that when it is fully parsed, we
|
||||
// can skip over any already syntax parsed inner functions and still
|
||||
// retain correct scope information.
|
||||
|
||||
if (!finishFunctionScopes())
|
||||
if (!finishFunctionScopes(isStandaloneFunction))
|
||||
return false;
|
||||
|
||||
// There are too many bindings or inner functions to be saved into the
|
||||
|
@ -2312,7 +2312,7 @@ Parser<FullParseHandler>::standaloneFunction(HandleFunction fun,
|
|||
YieldHandling yieldHandling = GetYieldHandling(generatorKind, asyncKind);
|
||||
AutoAwaitIsKeyword awaitIsKeyword(&tokenStream, asyncKind == AsyncFunction);
|
||||
if (!functionFormalParametersAndBody(InAllowed, yieldHandling, fn, Statement,
|
||||
parameterListEnd))
|
||||
parameterListEnd, /* isStandaloneFunction = */ true))
|
||||
{
|
||||
return null();
|
||||
}
|
||||
|
@ -3378,7 +3378,8 @@ bool
|
|||
Parser<ParseHandler>::functionFormalParametersAndBody(InHandling inHandling,
|
||||
YieldHandling yieldHandling,
|
||||
Node pn, FunctionSyntaxKind kind,
|
||||
Maybe<uint32_t> parameterListEnd /* = Nothing() */)
|
||||
Maybe<uint32_t> parameterListEnd /* = Nothing() */,
|
||||
bool isStandaloneFunction /* = false */)
|
||||
{
|
||||
// Given a properly initialized parse context, try to parse an actual
|
||||
// function without concern for conversion to strict mode, use of lazy
|
||||
|
@ -3487,7 +3488,7 @@ Parser<ParseHandler>::functionFormalParametersAndBody(InHandling inHandling,
|
|||
if (IsMethodDefinitionKind(kind) && pc->superScopeNeedsHomeObject())
|
||||
funbox->setNeedsHomeObject();
|
||||
|
||||
if (!finishFunction())
|
||||
if (!finishFunction(isStandaloneFunction))
|
||||
return false;
|
||||
|
||||
handler.setEndPosition(body, pos().begin);
|
||||
|
|
|
@ -1072,7 +1072,8 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
// ParseContext is already on the stack.
|
||||
bool functionFormalParametersAndBody(InHandling inHandling, YieldHandling yieldHandling,
|
||||
Node pn, FunctionSyntaxKind kind,
|
||||
mozilla::Maybe<uint32_t> parameterListEnd = mozilla::Nothing());
|
||||
mozilla::Maybe<uint32_t> parameterListEnd = mozilla::Nothing(),
|
||||
bool isStandaloneFunction = false);
|
||||
|
||||
// Determine whether |yield| is a valid name in the current context, or
|
||||
// whether it's prohibited due to strictness, JS version, or occurrence
|
||||
|
@ -1347,8 +1348,8 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
|
||||
bool tryAnnexB,
|
||||
Directives inheritedDirectives, Directives* newDirectives);
|
||||
bool finishFunctionScopes();
|
||||
bool finishFunction();
|
||||
bool finishFunctionScopes(bool isStandaloneFunction);
|
||||
bool finishFunction(bool isStandaloneFunction = false);
|
||||
bool leaveInnerFunction(ParseContext* outerpc);
|
||||
|
||||
bool matchOrInsertSemicolonHelper(TokenStream::Modifier modifier);
|
||||
|
|
|
@ -37,6 +37,7 @@ UNIFIED_SOURCES += [
|
|||
'testForOfIterator.cpp',
|
||||
'testForwardSetProperty.cpp',
|
||||
'testFreshGlobalEvalRedefinition.cpp',
|
||||
'testFunctionBinding.cpp',
|
||||
'testFunctionProperties.cpp',
|
||||
'testGCAllocator.cpp',
|
||||
'testGCCellPtr.cpp',
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
*
|
||||
* Test function name binding.
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "jsfriendapi.h"
|
||||
|
||||
#include "jsapi-tests/tests.h"
|
||||
|
||||
using namespace js;
|
||||
|
||||
BEGIN_TEST(test_functionBinding)
|
||||
{
|
||||
RootedFunction fun(cx);
|
||||
|
||||
JS::CompileOptions options(cx);
|
||||
options.setFileAndLine(__FILE__, __LINE__);
|
||||
|
||||
// Named function shouldn't have it's binding.
|
||||
const char s1chars[] = "return (typeof s1) == 'undefined';";
|
||||
JS::AutoObjectVector emptyScopeChain(cx);
|
||||
CHECK(JS::CompileFunction(cx, emptyScopeChain, options, "s1", 0, nullptr, s1chars,
|
||||
strlen(s1chars), &fun));
|
||||
CHECK(fun);
|
||||
|
||||
JS::AutoValueVector args(cx);
|
||||
RootedValue rval(cx);
|
||||
CHECK(JS::Call(cx, UndefinedHandleValue, fun, args, &rval));
|
||||
CHECK(rval.isBoolean());
|
||||
CHECK(rval.toBoolean());
|
||||
|
||||
// Named function shouldn't have `anonymous` binding.
|
||||
const char s2chars[] = "return (typeof anonymous) == 'undefined';";
|
||||
CHECK(JS::CompileFunction(cx, emptyScopeChain, options, "s2", 0, nullptr, s2chars,
|
||||
strlen(s2chars), &fun));
|
||||
CHECK(fun);
|
||||
|
||||
CHECK(JS::Call(cx, UndefinedHandleValue, fun, args, &rval));
|
||||
CHECK(rval.isBoolean());
|
||||
CHECK(rval.toBoolean());
|
||||
|
||||
// Anonymous function shouldn't have `anonymous` binding.
|
||||
const char s3chars[] = "return (typeof anonymous) == 'undefined';";
|
||||
CHECK(JS::CompileFunction(cx, emptyScopeChain, options, nullptr, 0, nullptr, s3chars,
|
||||
strlen(s3chars), &fun));
|
||||
CHECK(fun);
|
||||
|
||||
CHECK(JS::Call(cx, UndefinedHandleValue, fun, args, &rval));
|
||||
CHECK(rval.isBoolean());
|
||||
CHECK(rval.toBoolean());
|
||||
|
||||
return true;
|
||||
}
|
||||
END_TEST(test_functionBinding)
|
|
@ -0,0 +1,11 @@
|
|||
var BUGNUMBER = 636635;
|
||||
var summary = "A function created by Function constructor shouldn't have anonymous binding";
|
||||
|
||||
print(BUGNUMBER + ": " + summary);
|
||||
|
||||
assertEq(new Function("return typeof anonymous")(), "undefined");
|
||||
assertEq(new Function("return function() { return typeof anonymous; }")()(), "undefined");
|
||||
assertEq(new Function("return function() { eval(''); return typeof anonymous; }")()(), "undefined");
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
Загрузка…
Ссылка в новой задаче