From d90013d1d1f9676ca8ad4ae4bf462d219e66b2c0 Mon Sep 17 00:00:00 2001 From: arv Date: Fri, 10 Jul 2015 09:39:47 -0700 Subject: [PATCH] [es6] Handle conflicts for sloppy let We have to call CheckConflictingVarDeclarations in case we have enabled --harmony-sloppy BUG=v8:4287 LOG=N R=littledan@chromium.org, rossberg@chromium.org Review URL: https://codereview.chromium.org/1226103002 Cr-Commit-Position: refs/heads/master@{#29578} --- src/parser.cc | 4 + src/preparser.h | 2 + test/mjsunit/harmony/block-conflicts-sloppy.js | 174 +++++++++++++++++++++++++ 3 files changed, 180 insertions(+) create mode 100644 test/mjsunit/harmony/block-conflicts-sloppy.js diff --git a/src/parser.cc b/src/parser.cc index a45a4b1..bf12fa4 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -1062,6 +1062,8 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) { if (ok && is_strict(language_mode())) { CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok); + } + if (ok && (is_strict(language_mode()) || allow_harmony_sloppy())) { CheckConflictingVarDeclarations(scope_, &ok); } @@ -4141,6 +4143,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral( if (is_strict(language_mode())) { CheckStrictOctalLiteral(scope->start_position(), scope->end_position(), CHECK_OK); + } + if (is_strict(language_mode()) || allow_harmony_sloppy()) { CheckConflictingVarDeclarations(scope, CHECK_OK); } } diff --git a/src/preparser.h b/src/preparser.h index cff443a..9f58646 100644 --- a/src/preparser.h +++ b/src/preparser.h @@ -3770,6 +3770,8 @@ ParserBase::ParseArrowFunctionLiteral( if (is_strict(language_mode())) { CheckStrictOctalLiteral(formal_parameters.scope->start_position(), scanner()->location().end_pos, CHECK_OK); + } + if (is_strict(language_mode()) || allow_harmony_sloppy()) { this->CheckConflictingVarDeclarations(formal_parameters.scope, CHECK_OK); } } diff --git a/test/mjsunit/harmony/block-conflicts-sloppy.js b/test/mjsunit/harmony/block-conflicts-sloppy.js new file mode 100644 index 0000000..25694ed --- /dev/null +++ b/test/mjsunit/harmony/block-conflicts-sloppy.js @@ -0,0 +1,174 @@ +// Copyright 2011 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 for conflicting variable bindings. + +// Flags: --no-legacy-const --harmony-sloppy + +function CheckException(e) { + var string = e.toString(); + assertTrue(string.indexOf("has already been declared") >= 0 || + string.indexOf("redeclaration") >= 0); + return 'Conflict'; +} + + +function TestGlobal(s,e) { + try { + return eval(s + e); + } catch (x) { + return CheckException(x); + } +} + + +function TestFunction(s,e) { + try { + return eval("(function(){" + s + " return " + e + "})")(); + } catch (x) { + return CheckException(x); + } +} + + +function TestBlock(s,e) { + try { + return eval("(function(){ {" + s + "} return " + e + "})")(); + } catch (x) { + return CheckException(x); + } +} + +function TestAll(expected,s,opt_e) { + var e = ""; + var msg = s; + if (opt_e) { e = opt_e; msg += opt_e; } + // TODO(littledan): https://code.google.com/p/v8/issues/detail?id=4288 + // It is also not clear whether these tests makes sense in sloppy mode. + // TODO(littledan): Add tests using Realm.eval to ensure that global eval + // works as expected. + // assertEquals(expected === 'LocalConflict' ? 'NoConflict' : expected, + // TestGlobal(s,e), "global:'" + msg + "'"); + assertEquals(expected === 'LocalConflict' ? 'NoConflict' : expected, + TestFunction(s,e), "function:'" + msg + "'"); + assertEquals(expected === 'LocalConflict' ? 'Conflict' : expected, + TestBlock(s,e), "block:'" + msg + "'"); +} + + +function TestConflict(s) { + TestAll('Conflict', s); + // TODO(littledan): https://code.google.com/p/v8/issues/detail?id=4288 + // It is also not clear whether these tests makes sense in sloppy mode. + // TestAll('Conflict', 'eval("' + s + '");'); +} + +function TestNoConflict(s) { + TestAll('NoConflict', s, "'NoConflict'"); + // TODO(littledan): https://code.google.com/p/v8/issues/detail?id=4288 + // TestAll('NoConflict', 'eval("' + s + '");', "'NoConflict'"); +} + +function TestLocalConflict(s) { + TestAll('LocalConflict', s, "'NoConflict'"); + // TODO(littledan): https://code.google.com/p/v8/issues/detail?id=4288 + // It is also not clear whether these tests makes sense in sloppy mode. + // TestAll('NoConflict', 'eval("' + s + '");', "'NoConflict'"); +} + +var letbinds = [ "let x;", + "let x = 0;", + "let x = undefined;", + "let x = function() {};", + "let x, y;", + "let y, x;", + "const x = 0;", + "const x = undefined;", + "const x = function() {};", + "const x = 2, y = 3;", + "const y = 4, x = 5;", + ]; +var varbinds = [ "var x;", + "var x = 0;", + "var x = undefined;", + "var x = function() {};", + "var x, y;", + "var y, x;", + ]; +var funbind = "function x() {}"; + +for (var l = 0; l < letbinds.length; ++l) { + // Test conflicting let/var bindings. + for (var v = 0; v < varbinds.length; ++v) { + // Same level. + TestConflict(letbinds[l] + varbinds[v]); + TestConflict(varbinds[v] + letbinds[l]); + // Different level. + TestConflict(letbinds[l] + '{' + varbinds[v] + '}'); + TestConflict('{' + varbinds[v] +'}' + letbinds[l]); + TestNoConflict(varbinds[v] + '{' + letbinds[l] + '}'); + TestNoConflict('{' + letbinds[l] + '}' + varbinds[v]); + // For loop. + TestConflict('for (' + letbinds[l] + '0;) {' + varbinds[v] + '}'); + TestNoConflict('for (' + varbinds[v] + '0;) {' + letbinds[l] + '}'); + } + + // Test conflicting let/let bindings. + for (var k = 0; k < letbinds.length; ++k) { + // Same level. + TestConflict(letbinds[l] + letbinds[k]); + TestConflict(letbinds[k] + letbinds[l]); + // Different level. + TestNoConflict(letbinds[l] + '{ ' + letbinds[k] + '}'); + TestNoConflict('{' + letbinds[k] +'} ' + letbinds[l]); + // For loop. + TestNoConflict('for (' + letbinds[l] + '0;) {' + letbinds[k] + '}'); + TestNoConflict('for (' + letbinds[k] + '0;) {' + letbinds[l] + '}'); + } + + // Test conflicting function/let bindings. + // Same level. + TestConflict(letbinds[l] + funbind); + TestConflict(funbind + letbinds[l]); + // Different level. + TestNoConflict(letbinds[l] + '{' + funbind + '}'); + TestNoConflict('{' + funbind + '}' + letbinds[l]); + TestNoConflict(funbind + '{' + letbinds[l] + '}'); + TestNoConflict('{' + letbinds[l] + '}' + funbind); + // For loop. + TestNoConflict('for (' + letbinds[l] + '0;) {' + funbind + '}'); + + // Test conflicting parameter/let bindings. + TestConflict('(function(x) {' + letbinds[l] + '})();'); +} + +// Test conflicting function/var bindings. +for (var v = 0; v < varbinds.length; ++v) { + // Same level. + TestLocalConflict(varbinds[v] + funbind); + TestLocalConflict(funbind + varbinds[v]); + // Different level. + TestLocalConflict(funbind + '{' + varbinds[v] + '}'); + TestLocalConflict('{' + varbinds[v] +'}' + funbind); + TestNoConflict(varbinds[v] + '{' + funbind + '}'); + TestNoConflict('{' + funbind + '}' + varbinds[v]); + // For loop. + TestNoConflict('for (' + varbinds[v] + '0;) {' + funbind + '}'); +} + +// Test conflicting catch/var bindings. +for (var v = 0; v < varbinds.length; ++v) { + TestNoConflict('try {} catch(x) {' + varbinds[v] + '}'); +} + +// Test conflicting parameter/var bindings. +for (var v = 0; v < varbinds.length; ++v) { + TestNoConflict('(function (x) {' + varbinds[v] + '})();'); +} + +// Test conflicting catch/function bindings. +TestNoConflict('try {} catch(x) {' + funbind + '}'); + +// Test conflicting parameter/function bindings. +TestNoConflict('(function (x) {' + funbind + '})();'); -- 2.7.4