[es6] Fix parsing of expressions in patterns
authorrossberg <rossberg@chromium.org>
Fri, 7 Aug 2015 21:55:44 +0000 (14:55 -0700)
committerCommit bot <commit-bot@chromium.org>
Fri, 7 Aug 2015 21:56:00 +0000 (21:56 +0000)
Fixes the use of eval calls in strict parameter lists in particular.

R=adamk@chromium.org
BUG=v8:811
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#30074}

src/expression-classifier.h
src/preparser.h
test/mjsunit/harmony/destructuring.js

index fc89015d1fcee8a8f88cbb20169476cb523b14b1..716d4c7a3f29c24d2da337721c9089c4c3273616 100644 (file)
@@ -225,18 +225,6 @@ class ExpressionClassifier {
     }
   }
 
-  void AccumulateReclassifyingAsPattern(const ExpressionClassifier& inner) {
-    Accumulate(inner, AllProductions & ~PatternProductions);
-    if (!inner.is_valid_expression()) {
-      if (is_valid_binding_pattern()) {
-        binding_pattern_error_ = inner.expression_error();
-      }
-      if (is_valid_assignment_pattern()) {
-        assignment_pattern_error_ = inner.expression_error();
-      }
-    }
-  }
-
  private:
   unsigned invalid_productions_;
   Error expression_error_;
index 22633b6a030b39824e01f387b336bc04903b85d6..91e37912d163926131607322f3f1064b8c13b017 100644 (file)
@@ -2506,7 +2506,8 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParsePropertyName(
       ExpressionClassifier computed_name_classifier;
       ExpressionT expression =
           ParseAssignmentExpression(true, &computed_name_classifier, CHECK_OK);
-      classifier->AccumulateReclassifyingAsPattern(computed_name_classifier);
+      classifier->Accumulate(computed_name_classifier,
+                             ExpressionClassifier::ExpressionProduction);
       Expect(Token::RBRACK, CHECK_OK);
       return expression;
     }
@@ -2651,7 +2652,8 @@ ParserBase<Traits>::ParsePropertyDefinition(
       ExpressionClassifier rhs_classifier;
       ExpressionT rhs = this->ParseAssignmentExpression(
           true, &rhs_classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
-      classifier->AccumulateReclassifyingAsPattern(rhs_classifier);
+      classifier->Accumulate(rhs_classifier,
+                             ExpressionClassifier::ExpressionProduction);
       value = factory()->NewAssignment(Token::ASSIGN, lhs, rhs,
                                        RelocInfo::kNoPosition);
     } else {
@@ -2889,7 +2891,8 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN,
   ExpressionClassifier rhs_classifier;
   ExpressionT right =
       this->ParseAssignmentExpression(accept_IN, &rhs_classifier, CHECK_OK);
-  classifier->AccumulateReclassifyingAsPattern(rhs_classifier);
+  classifier->Accumulate(rhs_classifier,
+                         ExpressionClassifier::ExpressionProduction);
 
   // TODO(1231235): We try to estimate the set of properties set by
   // constructors. We define a new property whenever there is an
index 2a525faccbeab5ed5c3b3ccd95c23092677286f0..05013c2a3aea8afe1504381d2f31c539f6c13cc6 100644 (file)
 }());
 
 
+(function TestExpressionsInParameters() {
+  function f1({a = eval(1)}) { return a }
+  assertEquals(1, f1({}));
+  function f2([x = eval(2)]) { return x }
+  assertEquals(2, f2([]));
+  function f3({[eval(7)]: x}) { return x }
+  assertEquals(3, f3({7: 3}));
+  // TODO(rossberg, caitp): Add tests for default parameters.
+})();
+
+
 (function TestParameterScoping() {
   var x = 1;
 
   assertEquals(1, f4({}));
   function f5({a = x}) { 'use strict'; function x() {}; return a; }
   assertEquals(1, f5({}));
-  // TODO(rossberg): Apparently, eval in default expressions is not working yet.
-  // function f6({a = eval("x")}) { var x; return a; }
-  // assertEquals(1, f6({}));
-  // function f61({a = eval("x")}) { 'use strict'; var x; return a; }
-  // assertEquals(1, f61({}));
-  // function f62({a = eval("'use strict'; x")}) { var x; return a; }
-  // assertEquals(1, f62({}));
+  function f6({a = eval("x")}) { var x; return a; }
+  assertEquals(1, f6({}));
+  function f61({a = eval("x")}) { 'use strict'; var x; return a; }
+  assertEquals(1, f61({}));
+  function f62({a = eval("'use strict'; x")}) { var x; return a; }
+  assertEquals(1, f62({}));
   function f7({a = function() { return x }}) { var x; return a(); }
   assertEquals(1, f7({}));
   function f8({a = () => x}) { var x; return a(); }
   assertEquals(1, f8({}));
-  // function f9({a = () => eval("x")}) { var x; return a(); }
-  // assertEquals(1, f9({}));
-  // function f91({a = () => eval("x")}) { 'use strict'; var x; return a(); }
-  // assertEquals(1, f91({}));
-  // function f92({a = () => { 'use strict'; return eval("x") }}) { var x; return a(); }
-  // assertEquals(1, f92({}));
-  // function f93({a = () => eval("'use strict'; x")}) { var x; return a(); }
-  // assertEquals(1, f93({}));
+  function f9({a = () => eval("x")}) { var x; return a(); }
+  assertEquals(1, f9({}));
+  function f91({a = () => eval("x")}) { 'use strict'; var x; return a(); }
+  assertEquals(1, f91({}));
+  function f92({a = () => { 'use strict'; return eval("x") }}) { var x; return a(); }
+  assertEquals(1, f92({}));
+  function f93({a = () => eval("'use strict'; x")}) { var x; return a(); }
+  assertEquals(1, f93({}));
 
   var g1 = ({a = x}) => { var x = 2; return a; };
   assertEquals(1, g1({}));
   assertEquals(1, g4({}));
   var g5 = ({a = x}) => { 'use strict'; function x() {}; return a; };
   assertEquals(1, g5({}));
-  // var g6 = ({a = eval("x")}) => { var x; return a; };
-  // assertEquals(1, g6({}));
-  // var g61 = ({a = eval("x")}) => { 'use strict'; var x; return a; };
-  // assertEquals(1, g61({}));
-  // var g62 = ({a = eval("'use strict'; x")}) => { var x; return a; };
-  // assertEquals(1, g62({}));
+  var g6 = ({a = eval("x")}) => { var x; return a; };
+  assertEquals(1, g6({}));
+  var g61 = ({a = eval("x")}) => { 'use strict'; var x; return a; };
+  assertEquals(1, g61({}));
+  var g62 = ({a = eval("'use strict'; x")}) => { var x; return a; };
+  assertEquals(1, g62({}));
   var g7 = ({a = function() { return x }}) => { var x; return a(); };
   assertEquals(1, g7({}));
   var g8 = ({a = () => x}) => { var x; return a(); };
   assertEquals(1, g8({}));
-  // var g9 = ({a = () => eval("x")}) => { var x; return a(); };
-  // assertEquals(1, g9({}));
-  // var g91 = ({a = () => eval("x")}) => { 'use strict'; var x; return a(); };
-  // assertEquals(1, g91({}));
-  // var g92 = ({a = () => { 'use strict'; return eval("x") }}) => { var x; return a(); };
-  // assertEquals(1, g92({}));
-  // var g93 = ({a = () => eval("'use strict'; x")}) => { var x; return a(); };
-  // assertEquals(1, g93({}));
+  var g9 = ({a = () => eval("x")}) => { var x; return a(); };
+  assertEquals(1, g9({}));
+  var g91 = ({a = () => eval("x")}) => { 'use strict'; var x; return a(); };
+  assertEquals(1, g91({}));
+  var g92 = ({a = () => { 'use strict'; return eval("x") }}) => { var x; return a(); };
+  assertEquals(1, g92({}));
+  var g93 = ({a = () => eval("'use strict'; x")}) => { var x; return a(); };
+  assertEquals(1, g93({}));
 
   var f11 = function f({x = f}) { var f; return x; }
   assertSame(f11, f11({}));
   var y = 'a';
   function f20({[y]: x}) { var y = 'b'; return x; }
   assertEquals(1, f20({a: 1, b: 2}));
-  // function f21({[eval('y')]: x}) { var y = 'b'; return x; }
-  // assertEquals(1, f21({a: 1, b: 2}));
+  function f21({[eval('y')]: x}) { var y = 'b'; return x; }
+  assertEquals(1, f21({a: 1, b: 2}));
   var g20 = ({[y]: x}) => { var y = 'b'; return x; };
   assertEquals(1, g20({a: 1, b: 2}));
-  // var g21 = ({[eval('y')]: x}) => { var y = 'b'; return x; };
-  // assertEquals(1, g21({a: 1, b: 2}));
+  var g21 = ({[eval('y')]: x}) => { var y = 'b'; return x; };
+  assertEquals(1, g21({a: 1, b: 2}));
 })();
 
 
   function f1({a = x}, x) { return a }
   assertThrows(() => f1({}, 4), ReferenceError);
   assertEquals(4, f1({a: 4}, 5));
-  // TODO(rossberg): eval in default expressions is not working yet.
-  // function f2({a = eval("x")}, x) { return a }
-  // assertThrows(() => f2({}, 4), ReferenceError);
-  // assertEquals(4, f2({a: 4}, 5));
-  // function f3({a = eval("x")}, x) { 'use strict'; return a }
-  // assertThrows(() => f3({}, 4), ReferenceError);
-  // assertEquals(4, f3({a: 4}, 5));
-  // function f4({a = eval("'use strict'; x")}, x) { return a }
-  // assertThrows(() => f4({}, 4), ReferenceError);
-  // assertEquals(4, f4({a: 4}, 5));
+  function f2({a = eval("x")}, x) { return a }
+  assertThrows(() => f2({}, 4), ReferenceError);
+  assertEquals(4, f2({a: 4}, 5));
+  function f3({a = eval("x")}, x) { 'use strict'; return a }
+  assertThrows(() => f3({}, 4), ReferenceError);
+  assertEquals(4, f3({a: 4}, 5));
+  function f4({a = eval("'use strict'; x")}, x) { return a }
+  assertThrows(() => f4({}, 4), ReferenceError);
+  assertEquals(4, f4({a: 4}, 5));
 
   function f5({a = () => x}, x) { return a() }
   assertEquals(4, f5({a: () => 4}, 5));
-  // TODO(rossberg): eval in default expressions is not working yet.
-  // function f6({a = () => eval("x")}, x) { return a() }
-  // assertEquals(4, f6({a: () => 4}, 5));
-  // function f7({a = () => eval("x")}, x) { 'use strict'; return a() }
-  // assertEquals(4, f7({a: () => 4}, 5));
-  // function f8({a = () => eval("'use strict'; x")}, x) { return a() }
-  // assertEquals(4, f8({a: () => 4}, 5));
+  function f6({a = () => eval("x")}, x) { return a() }
+  assertEquals(4, f6({a: () => 4}, 5));
+  function f7({a = () => eval("x")}, x) { 'use strict'; return a() }
+  assertEquals(4, f7({a: () => 4}, 5));
+  function f8({a = () => eval("'use strict'; x")}, x) { return a() }
+  assertEquals(4, f8({a: () => 4}, 5));
 
   function f11({a = b}, {b}) { return a }
   assertThrows(() => f11({}, {b: 4}), ReferenceError);
   assertEquals(4, f11({a: 4}, {b: 5}));
-  // function f12({a = eval("b")}, {b}) { return a }
-  // assertThrows(() => f12({}, {b: 4}), ReferenceError);
-  // assertEquals(4, f12({a: 4}, {b: 5}));
-  // function f13({a = eval("b")}, {b}) { 'use strict'; return a }
-  // assertThrows(() => f13({}, {b: 4}), ReferenceError);
-  // assertEquals(4, f13({a: 4}, {b: 5}));
-  // function f14({a = eval("'use strict'; b")}, {b}) { return a }
-  // assertThrows(() => f14({}, {b: 4}), ReferenceError);
-  // assertEquals(4, f14({a: 4}, {b: 5}));
+  function f12({a = eval("b")}, {b}) { return a }
+  assertThrows(() => f12({}, {b: 4}), ReferenceError);
+  assertEquals(4, f12({a: 4}, {b: 5}));
+  function f13({a = eval("b")}, {b}) { 'use strict'; return a }
+  assertThrows(() => f13({}, {b: 4}), ReferenceError);
+  assertEquals(4, f13({a: 4}, {b: 5}));
+  function f14({a = eval("'use strict'; b")}, {b}) { return a }
+  assertThrows(() => f14({}, {b: 4}), ReferenceError);
+  assertEquals(4, f14({a: 4}, {b: 5}));
 
   function f15({a = () => b}, {b}) { return a() }
   assertEquals(4, f15({a: () => 4}, {b: 5}));
-  // function f16({a = () => eval("b")}, {b}) { return a() }
-  // assertEquals(4, f16({a: () => 4}, {b: 5}));
-  // function f17({a = () => eval("b")}, {b}) { 'use strict'; return a() }
-  // assertEquals(4, f17({a: () => 4}, {b: 5}));
-  // function f18({a = () => eval("'use strict'; b")}, {b}) { return a() }
-  // assertEquals(4, f18({a: () => 4}, {b: 5}));
+  function f16({a = () => eval("b")}, {b}) { return a() }
+  assertEquals(4, f16({a: () => 4}, {b: 5}));
+  function f17({a = () => eval("b")}, {b}) { 'use strict'; return a() }
+  assertEquals(4, f17({a: () => 4}, {b: 5}));
+  function f18({a = () => eval("'use strict'; b")}, {b}) { return a() }
+  assertEquals(4, f18({a: () => 4}, {b: 5}));
 
   // TODO(caitp): TDZ for rest parameters is not working yet.
   // function f30({x = a}, ...a) { return x[0] }
   assertEquals(4, f34({}, 4));
   function f35({x = () => a}, ...a) { return x()[0] }
   assertEquals(4, f35({}, 4));
-  // function f36({x = () => eval("a")}, ...a) { return x()[0] }
-  // assertEquals(4, f36({}, 4));
-  // function f37({x = () => eval("a")}, ...a) { 'use strict'; return x()[0] }
-  // assertEquals(4, f37({}, 4));
-  // function f38({x = () => { 'use strict'; return eval("a") }}, ...a) { return x()[0] }
-  // assertEquals(4, f38({}, 4));
-  // function f39({x = () => eval("'use strict'; a")}, ...a) { return x()[0] }
-  // assertEquals(4, f39({}, 4));
+  function f36({x = () => eval("a")}, ...a) { return x()[0] }
+  assertEquals(4, f36({}, 4));
+  function f37({x = () => eval("a")}, ...a) { 'use strict'; return x()[0] }
+  assertEquals(4, f37({}, 4));
+  function f38({x = () => { 'use strict'; return eval("a") }}, ...a) { return x()[0] }
+  assertEquals(4, f38({}, 4));
+  function f39({x = () => eval("'use strict'; a")}, ...a) { return x()[0] }
+  assertEquals(4, f39({}, 4));
 
   // var g30 = ({x = a}, ...a) => {};
   // assertThrows(() => g30({}), ReferenceError);
   assertEquals(5, f7({a: 5}));
   function f8(x, ...a) { a = []; return arguments[1] }
   assertEquals(6, f8(5, 6));
-  // TODO(caitp, rossberg): add cases for default parameters.
+  // TODO(rossberg, caitp): Add cases for default parameters.
 }());