From 6773e2961de8f9e588cbf0e939ab3f325dd6fef9 Mon Sep 17 00:00:00 2001 From: littledan Date: Fri, 28 Aug 2015 15:43:00 -0700 Subject: [PATCH] Propagate switch statement value for 'eval' This patch changes the switch scope desugaring to create blocks which propagate their 'return value' for eval. BUG=v8:4399 R=adamk LOG=Y Review URL: https://codereview.chromium.org/1309303006 Cr-Commit-Position: refs/heads/master@{#30454} --- src/parser.cc | 13 +++++++++++-- test/cctest/test-ast-expression-visitor.cc | 1 + test/mjsunit/regress/regress-4399.js | 17 +++++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 test/mjsunit/regress/regress-4399.js diff --git a/src/parser.cc b/src/parser.cc index a357aa177..43694df11 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -2987,7 +2987,7 @@ Statement* Parser::ParseSwitchStatement(ZoneList* labels, // } Block* switch_block = - factory()->NewBlock(NULL, 2, true, RelocInfo::kNoPosition); + factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition); int switch_pos = peek_position(); Expect(Token::SWITCH, CHECK_OK); @@ -3004,8 +3004,17 @@ Statement* Parser::ParseSwitchStatement(ZoneList* labels, factory()->NewExpressionStatement(tag_assign, RelocInfo::kNoPosition); switch_block->AddStatement(tag_statement, zone()); + // make statement: undefined; + // This is needed so the tag isn't returned as the value, in case the switch + // statements don't have a value. + switch_block->AddStatement( + factory()->NewExpressionStatement( + factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), + RelocInfo::kNoPosition), + zone()); + Block* cases_block = - factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition); + factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition); Scope* cases_scope = NewScope(scope_, BLOCK_SCOPE); cases_scope->SetNonlinear(); diff --git a/test/cctest/test-ast-expression-visitor.cc b/test/cctest/test-ast-expression-visitor.cc index c7ef3605f..f4c1028ab 100644 --- a/test/cctest/test-ast-expression-visitor.cc +++ b/test/cctest/test-ast-expression-visitor.cc @@ -303,6 +303,7 @@ TEST(VisitSwitchStatment) { CHECK_VAR(.switch_tag, DEFAULT_TYPE); CHECK_EXPR(Literal, DEFAULT_TYPE); } + CHECK_EXPR(Literal, DEFAULT_TYPE); CHECK_VAR(.switch_tag, DEFAULT_TYPE); CHECK_EXPR(Literal, DEFAULT_TYPE); } diff --git a/test/mjsunit/regress/regress-4399.js b/test/mjsunit/regress/regress-4399.js new file mode 100644 index 000000000..c76c0c83b --- /dev/null +++ b/test/mjsunit/regress/regress-4399.js @@ -0,0 +1,17 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Test that switch has the appropriate 'eval' value + +assertEquals("foo", eval('switch(1) { case 1: "foo" }')); +assertEquals("foo", eval('{ switch(1) { case 1: "foo" } }')); +assertEquals("foo", eval('switch(1) { case 1: { "foo" } }')); +assertEquals("foo", eval('switch(1) { case 1: "foo"; break; case 2: "bar"; break }')); +assertEquals("bar", eval('switch(2) { case 1: "foo"; break; case 2: "bar"; break }')); +assertEquals("bar", eval('switch(1) { case 1: "foo"; case 2: "bar"; break }')); + +// The tag is not the value, if there's no value + +assertEquals(undefined, eval('switch (1) {}')); +assertEquals(undefined, eval('switch (1) { case 1: {} }')); -- 2.34.1