Always give class literals a block scope

Class methods always have the class scope on their scope chain in order
to implement strong mode checks. Previously, that scope wasn't attached
to the ClassLiteral for anonymous classes (since the scope contained
no bindings).

This patch simply puts that same scope on the ClassLiteral, anonymous
or not, which simplifies other code that needs to reason about the scope
of a class and its methods.

Review URL: https://codereview.chromium.org/1413903002

Cr-Commit-Position: refs/heads/master@{#31371}
This commit is contained in:
adamk 2015-10-19 04:38:14 -07:00 committed by Commit bot
parent 80df08b59f
commit cf13dda1ba
3 changed files with 11 additions and 20 deletions

View File

@ -1533,20 +1533,15 @@ void AstGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) {
if (expr->scope() == NULL) {
// Visit class literal in the same scope, no declarations.
// Visit declarations and class literal in a block scope.
if (expr->scope()->ContextLocalCount() > 0) {
Node* context = BuildLocalBlockContext(expr->scope());
ContextScope scope(this, expr->scope(), context);
VisitDeclarations(expr->scope()->declarations());
VisitClassLiteralContents(expr);
} else {
// Visit declarations and class literal in a block scope.
if (expr->scope()->ContextLocalCount() > 0) {
Node* context = BuildLocalBlockContext(expr->scope());
ContextScope scope(this, expr->scope(), context);
VisitDeclarations(expr->scope()->declarations());
VisitClassLiteralContents(expr);
} else {
VisitDeclarations(expr->scope()->declarations());
VisitClassLiteralContents(expr);
}
VisitDeclarations(expr->scope()->declarations());
VisitClassLiteralContents(expr);
}
}
@ -1644,8 +1639,7 @@ void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) {
literal = NewNode(op, literal, proto);
// Assign to class variable.
if (expr->scope() != NULL) {
DCHECK_NOT_NULL(expr->class_variable_proxy());
if (expr->class_variable_proxy() != nullptr) {
Variable* var = expr->class_variable_proxy()->var();
FrameStateBeforeAndAfter states(this, BailoutId::None());
VectorSlotPair feedback = CreateVectorSlotPair(

View File

@ -1273,8 +1273,7 @@ void FullCodeGenerator::VisitClassLiteral(ClassLiteral* lit) {
EmitClassDefineProperties(lit);
if (lit->scope() != NULL) {
DCHECK_NOT_NULL(lit->class_variable_proxy());
if (lit->class_variable_proxy() != nullptr) {
EmitVariableAssignment(lit->class_variable_proxy()->var(),
Token::INIT_CONST, lit->ProxySlot());
}

View File

@ -4895,15 +4895,13 @@ ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name,
block_scope->language_mode());
}
// Note that we do not finalize this block scope because strong
// mode uses it as a sentinel value indicating an anonymous class.
block_scope->set_end_position(end_pos);
if (name != NULL) {
DCHECK_NOT_NULL(proxy);
proxy->var()->set_initializer_position(end_pos);
} else {
// Unnamed classes should not have scopes (the scope will be empty).
DCHECK_EQ(block_scope->num_var_or_const(), 0);
block_scope = nullptr;
}
return factory()->NewClassLiteral(name, block_scope, proxy, extends,