Fix name lookup for named function expressions

Change-Id: Ia36b2b5c5b40475450fe369c7d6cb5e3965a4488
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
Simon Hausmann 2013-03-08 14:11:42 +01:00 committed by Lars Knoll
parent ee7b6a5df5
commit b5181ea199
7 changed files with 32 additions and 9 deletions

View File

@ -400,6 +400,11 @@ Value ExecutionContext::getProperty(String *name)
if (hasProperty)
return v;
}
if (FunctionObject *f = ctx->function) {
if (f->function && f->function->isNamedExpression
&& name->isEqualTo(f->function->name))
return Value::fromObject(ctx->function);
}
}
throwReferenceError(Value::fromString(name));
return Value::undefinedValue();
@ -446,6 +451,11 @@ Value ExecutionContext::getPropertyNoThrow(String *name)
if (hasProperty)
return v;
}
if (FunctionObject *f = ctx->function) {
if (f->function && f->function->isNamedExpression
&& name->isEqualTo(f->function->name))
return Value::fromObject(ctx->function);
}
}
return Value::undefinedValue();
}
@ -494,6 +504,11 @@ Value ExecutionContext::getPropertyAndBase(String *name, Object **base)
if (hasProperty)
return v;
}
if (FunctionObject *f = ctx->function) {
if (f->function && f->function->isNamedExpression
&& name->isEqualTo(f->function->name))
return Value::fromObject(ctx->function);
}
}
throwReferenceError(Value::fromString(name));
return Value::undefinedValue();

View File

@ -404,11 +404,11 @@ protected:
return true;
}
void enterFunction(FunctionExpression *ast, bool enterName)
void enterFunction(FunctionExpression *ast, bool enterName, bool isExpression = true)
{
if (_env->isStrict && (ast->name == QLatin1String("eval") || ast->name == QLatin1String("arguments")))
_cg->throwSyntaxError(ast->identifierToken, QCoreApplication::translate("qv4codegen", "Function name may not be eval or arguments in strict mode"));
enterFunction(ast, ast->name.toString(), ast->formals, ast->body, enterName ? ast : 0);
enterFunction(ast, ast->name.toString(), ast->formals, ast->body, enterName ? ast : 0, isExpression);
}
virtual void endVisit(FunctionExpression *)
@ -418,7 +418,7 @@ protected:
virtual bool visit(PropertyGetterSetter *ast)
{
enterFunction(ast, QString(), ast->formals, ast->functionBody);
enterFunction(ast, QString(), ast->formals, ast->functionBody, /*FunctionExpression*/0, /*isExpression*/false);
return true;
}
@ -429,7 +429,7 @@ protected:
virtual bool visit(FunctionDeclaration *ast)
{
enterFunction(ast, /*enterName*/ true);
enterFunction(ast, /*enterName*/ true, /*isExpression */false);
return true;
}
@ -449,7 +449,7 @@ protected:
}
private:
void enterFunction(Node *ast, const QString &name, FormalParameterList *formals, FunctionBody *body, FunctionExpression *expr = 0)
void enterFunction(Node *ast, const QString &name, FormalParameterList *formals, FunctionBody *body, FunctionExpression *expr, bool isExpression)
{
bool wasStrict = false;
if (_env) {
@ -463,6 +463,8 @@ private:
enterEnvironment(ast);
checkForArguments(formals);
_env->isNamedFunctionExpression = isExpression && !name.isEmpty();
if (body)
checkDirectivePrologue(body->elements);
@ -1977,6 +1979,7 @@ IR::Function *Codegen::defineFunction(const QString &name, AST::Node *ast,
function->usesArgumentsObject = (_env->usesArgumentsObject == Environment::ArgumentsObjectUsed);
function->maxNumberOfArguments = _env->maxNumberOfArguments;
function->isStrict = _env->isStrict;
function->isNamedExpression = _env->isNamedFunctionExpression;
// variables in global code are properties of the global context object, not locals as with other functions.
if (_mode == FunctionCode) {

View File

@ -140,6 +140,7 @@ protected:
bool hasDirectEval;
bool hasNestedFunctions;
bool isStrict;
bool isNamedFunctionExpression;
enum UsesArgumentsObject {
ArgumentsObjectUnknown,
ArgumentsObjectNotUsed,
@ -154,6 +155,7 @@ protected:
, hasDirectEval(false)
, hasNestedFunctions(false)
, isStrict(false)
, isNamedFunctionExpression(false)
, usesArgumentsObject(ArgumentsObjectUnknown)
{
if (parent && parent->isStrict)

View File

@ -131,6 +131,7 @@ struct Function {
bool hasDirectEval;
bool usesArgumentsObject;
bool isStrict;
bool isNamedExpression;
Function(String *name)
: name(name)
@ -143,6 +144,7 @@ struct Function {
, hasDirectEval(false)
, usesArgumentsObject(false)
, isStrict(false)
, isNamedExpression(false)
{}
~Function();

View File

@ -45,6 +45,7 @@ VM::Function *EvalInstructionSelection::createFunctionMapping(VM::Function *oute
vmFunction->hasNestedFunctions = !irFunction->nestedFunctions.isEmpty();
vmFunction->isStrict = irFunction->isStrict;
vmFunction->outer = outer;
vmFunction->isNamedExpression = irFunction->isNamedExpression;
if (outer)
outer->nestedFunctions.append(vmFunction);

View File

@ -654,7 +654,8 @@ struct Function {
uint hasDirectEval: 1;
uint usesArgumentsObject : 1;
uint isStrict: 1;
uint unused : 29;
uint isNamedExpression : 1;
uint unused : 28;
template <typename _Tp> _Tp *New() { return new (pool->allocate(sizeof(_Tp))) _Tp(); }
@ -668,6 +669,7 @@ struct Function {
, hasDirectEval(false)
, usesArgumentsObject(false)
, isStrict(false)
, isNamedExpression(false)
, unused(0)
{ this->name = newString(name); }

View File

@ -11,9 +11,7 @@
S11.5.3_A4_T2 failing
S11.8.6_A5_T2 failing
S13_A15_T4 failing
S13_A3_T1 failing
S13.2.3_A1 failing
S14_A2 failing
14.1-5-s failing
15.4.4.14-9-a-10 failing
15.4.4.14-9-a-17 failing
@ -43,4 +41,4 @@ S15.2.4.4_A14 failing
# Function declaration inside if / while
Sbp_12.5_A9_T3 failing
Sbp_12.6.2_A13_T3 failing
Sbp_12.6.2_A13_T3 failing