Commit 06c5127f authored by neis's avatar neis Committed by Commit bot

[full-codegen] Introduce NestedStatement subclass for class literals.

This fixes a bug where returning from a class literal inside
a try-finally didn't restore the context properly when
entering the finally clause.

BUG=v8:4965
LOG=n

Review-Url: https://codereview.chromium.org/1952633002
Cr-Commit-Position: refs/heads/master@{#36021}
parent d3b50cbb
...@@ -1469,6 +1469,7 @@ void FullCodeGenerator::VisitClassLiteral(ClassLiteral* lit) { ...@@ -1469,6 +1469,7 @@ void FullCodeGenerator::VisitClassLiteral(ClassLiteral* lit) {
Comment cmnt(masm_, "[ ClassLiteral"); Comment cmnt(masm_, "[ ClassLiteral");
{ {
NestedClassLiteral nested_class_literal(this, lit);
EnterBlockScopeIfNeeded block_scope_state( EnterBlockScopeIfNeeded block_scope_state(
this, lit->scope(), lit->EntryId(), lit->DeclsId(), lit->ExitId()); this, lit->scope(), lit->EntryId(), lit->DeclsId(), lit->ExitId());
......
...@@ -211,6 +211,23 @@ class FullCodeGenerator: public AstVisitor { ...@@ -211,6 +211,23 @@ class FullCodeGenerator: public AstVisitor {
} }
}; };
// A class literal expression
class NestedClassLiteral : public NestedStatement {
public:
NestedClassLiteral(FullCodeGenerator* codegen, ClassLiteral* lit)
: NestedStatement(codegen),
needs_context_(lit->scope() != nullptr &&
lit->scope()->NeedsContext()) {}
NestedStatement* Exit(int* context_length) override {
if (needs_context_) ++(*context_length);
return previous_;
}
private:
const bool needs_context_;
};
class DeferredCommands { class DeferredCommands {
public: public:
enum Command { kReturn, kThrow, kBreak, kContinue }; enum Command { kReturn, kThrow, kBreak, kContinue };
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// Flags: --allow-natives-syntax // Flags: --allow-natives-syntax --harmony-do-expressions
(function TestBasics() { (function TestBasics() {
var C = class C {} var C = class C {}
...@@ -994,3 +994,55 @@ function testClassRestrictedProperties(C) { ...@@ -994,3 +994,55 @@ function testClassRestrictedProperties(C) {
testClassRestrictedProperties( testClassRestrictedProperties(
class extends Class { constructor() { super(); } }); class extends Class { constructor() { super(); } });
})(); })();
(function testReturnFromClassLiteral() {
function usingDoExpressionInBody() {
let x = 42;
let dummy = function() {x};
try {
class C {
dummy() {C}
[do {return}]() {}
};
} finally {
return x;
}
}
assertEquals(42, usingDoExpressionInBody());
function usingDoExpressionInExtends() {
let x = 42;
let dummy = function() {x};
try {
class C extends (do {return}) { dummy() {C} };
} finally {
return x;
}
}
assertEquals(42, usingDoExpressionInExtends());
function usingYieldInBody() {
function* foo() {
class C {
[yield]() {}
}
}
var g = foo();
g.next();
return g.return(42).value;
}
assertEquals(42, usingYieldInBody());
function usingYieldInExtends() {
function* foo() {
class C extends (yield) {};
}
var g = foo();
g.next();
return g.return(42).value;
}
assertEquals(42, usingYieldInExtends());
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment