diff --git a/src/pattern-rewriter.cc b/src/pattern-rewriter.cc index a97c009708..5871740c14 100644 --- a/src/pattern-rewriter.cc +++ b/src/pattern-rewriter.cc @@ -224,13 +224,11 @@ Variable* Parser::PatternRewriter::CreateTempVar(Expression* value) { void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern) { auto temp = CreateTempVar(current_value_); - if (pattern->properties()->length() == 0) { - block_->AddStatement(descriptor_->parser->BuildAssertIsCoercible(temp), - zone()); - } + + block_->AddStatement(descriptor_->parser->BuildAssertIsCoercible(temp), + zone()); for (ObjectLiteralProperty* property : *pattern->properties()) { - // TODO(dslomov): computed property names. RecurseIntoSubpattern( property->value(), factory()->NewProperty(factory()->NewVariableProxy(temp), diff --git a/src/preparser.h b/src/preparser.h index c870c9bf5e..e5bb891680 100644 --- a/src/preparser.h +++ b/src/preparser.h @@ -2555,8 +2555,10 @@ typename ParserBase::ExpressionT ParserBase::ParsePropertyName( if (allow_harmony_computed_property_names_) { *is_computed_name = true; Consume(Token::LBRACK); - ExpressionT expression = - ParseAssignmentExpression(true, classifier, CHECK_OK); + ExpressionClassifier computed_name_classifier; + ExpressionT expression = ParseAssignmentExpression( + true, &computed_name_classifier, CHECK_OK); + classifier->AccumulateReclassifyingAsPattern(computed_name_classifier); Expect(Token::RBRACK, CHECK_OK); return expression; } diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc index 16f0cf3749..da63f39ae6 100644 --- a/test/cctest/test-parsing.cc +++ b/test/cctest/test-parsing.cc @@ -6356,6 +6356,7 @@ TEST(StrongModeFreeVariablesNotDeclared) { TEST(DestructuringPositiveTests) { i::FLAG_harmony_destructuring = true; + i::FLAG_harmony_computed_property_names = true; const char* context_data[][2] = {{"'use strict'; let ", " = {};"}, {"var ", " = {};"}, @@ -6390,10 +6391,14 @@ TEST(DestructuringPositiveTests) { "{'hi' : x = 42}", "{var: x}", "{var: x = 42}", + "{[x] : z}", + "{[1+1] : z}", + "{[foo()] : z}", "{}", NULL}; // clang-format on static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals, + kAllowHarmonyComputedPropertyNames, kAllowHarmonyDestructuring}; RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags, arraysize(always_flags)); @@ -6402,7 +6407,9 @@ TEST(DestructuringPositiveTests) { TEST(DestructuringNegativeTests) { i::FLAG_harmony_destructuring = true; + i::FLAG_harmony_computed_property_names = true; static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals, + kAllowHarmonyComputedPropertyNames, kAllowHarmonyDestructuring}; { // All modes. @@ -6459,6 +6466,7 @@ TEST(DestructuringNegativeTests) { "{x : x = (a+)}", "{x : x += a}", "{m() {} = 0}", + "{[1+1]}", NULL}; // clang-format on RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags, diff --git a/test/mjsunit/harmony/destructuring.js b/test/mjsunit/harmony/destructuring.js index 3e1726fdc2..257c4a164d 100644 --- a/test/mjsunit/harmony/destructuring.js +++ b/test/mjsunit/harmony/destructuring.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// Flags: --harmony-destructuring +// Flags: --harmony-destructuring --harmony-computed-property-names (function TestObjectLiteralPattern() { var { x : x, y : y } = { x : 1, y : 2 }; @@ -283,6 +283,100 @@ }()); +(function TestComputedNames() { + var x = 1; + var {[x]:y} = {1:2}; + assertSame(2, y); + + (function(){ + 'use strict'; + let {[x]:y} = {1:2}; + assertSame(2, y); + }()); + + var callCount = 0; + function foo(v) { callCount++; return v; } + + (function() { + callCount = 0; + var {[foo("abc")]:x} = {abc:42}; + assertSame(42, x); + assertEquals(1, callCount); + }()); + + (function() { + 'use strict'; + callCount = 0; + let {[foo("abc")]:x} = {abc:42}; + assertSame(42, x); + assertEquals(1, callCount); + }()); + + (function() { + callCount = 0; + var {[foo("abc")]:x} = {}; + assertSame(undefined, x); + assertEquals(1, callCount); + }()); + + (function() { + 'use strict'; + callCount = 0; + let {[foo("abc")]:x} = {}; + assertSame(undefined, x); + assertEquals(1, callCount); + }()); + + for (val of [null, undefined]) { + callCount = 0; + assertThrows(function() { + var {[foo()]:x} = val; + }, TypeError); + assertEquals(0, callCount); + + callCount = 0; + assertThrows(function() { + 'use strict'; + let {[foo()]:x} = val; + }, TypeError); + assertEquals(0, callCount); + } + + var log = []; + var o = { + get x() { log.push("get x"); return 1; }, + get y() { log.push("get y"); return 2; } + } + function f(v) { log.push("f " + v); return v; } + + (function() { + log = []; + var { [f('x')]:x, [f('y')]:y } = o; + assertSame(1, x); + assertSame(2, y); + assertArrayEquals(["f x", "get x", "f y", "get y"], log); + }()); + + (function() { + 'use strict'; + log = []; + let { [f('x')]:x, [f('y')]:y } = o; + assertSame(1, x); + assertSame(2, y); + assertArrayEquals(["f x", "get x", "f y", "get y"], log); + }()); + + (function() { + 'use strict'; + log = []; + const { [f('x')]:x, [f('y')]:y } = o; + assertSame(1, x); + assertSame(2, y); + assertArrayEquals(["f x", "get x", "f y", "get y"], log); + }()); +}()); + + (function TestExceptions() { for (var val of [null, undefined]) { assertThrows(function() { var {} = val; }, TypeError);