Commit cf9492dd authored by dslomov's avatar dslomov Committed by Commit bot

[destructuring] More tests for object literal pattern

R=arv@chromium.org,rossberg@chromium.org
BUG=v8:811
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#28457}
parent cc3f59db
......@@ -148,6 +148,7 @@ class CallSite {
"Method invoked on undefined or null value.") \
T(MethodInvokedOnWrongType, "Method invoked on an object that is not %.") \
T(NoAccess, "no access") \
T(NonCoercible, "Cannot match against 'undefined' or 'null'.") \
T(NonExtensibleProto, "% is not extensible") \
T(NonObjectPropertyLoad, "Cannot read property '%' of %") \
T(NonObjectPropertyStore, "Cannot set property '%' of %") \
......
......@@ -4143,6 +4143,32 @@ void Parser::AddAssertIsConstruct(ZoneList<Statement*>* body, int pos) {
}
Statement* Parser::BuildAssertIsCoercible(Variable* var) {
// if (var === null || var === undefined)
// throw /* type error kNonCoercible) */;
Expression* condition = factory()->NewBinaryOperation(
Token::OR, factory()->NewCompareOperation(
Token::EQ_STRICT, factory()->NewVariableProxy(var),
factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
RelocInfo::kNoPosition),
factory()->NewCompareOperation(
Token::EQ_STRICT, factory()->NewVariableProxy(var),
factory()->NewNullLiteral(RelocInfo::kNoPosition),
RelocInfo::kNoPosition),
RelocInfo::kNoPosition);
Expression* throw_type_error = this->NewThrowTypeError(
MessageTemplate::kNonCoercible, ast_value_factory()->empty_string(),
RelocInfo::kNoPosition);
IfStatement* if_statement = factory()->NewIfStatement(
condition, factory()->NewExpressionStatement(throw_type_error,
RelocInfo::kNoPosition),
factory()->NewEmptyStatement(RelocInfo::kNoPosition),
RelocInfo::kNoPosition);
return if_statement;
}
ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
const AstRawString* function_name, int pos, Variable* fvar,
Token::Value fvar_init_op, FunctionKind kind, bool* ok) {
......
......@@ -1013,6 +1013,9 @@ class Parser : public ParserBase<ParserTraits> {
}
bool inside_with() const { return descriptor_->parser->inside_with(); }
Zone* zone() const { return descriptor_->parser->zone(); }
Scope* TemporaryDeclarationScope() const {
return descriptor_->parser->scope_->DeclarationScope();
}
Expression* pattern_;
int initializer_position_;
......@@ -1101,6 +1104,7 @@ class Parser : public ParserBase<ParserTraits> {
IterationStatement* LookupContinueTarget(const AstRawString* label, bool* ok);
void AddAssertIsConstruct(ZoneList<Statement*>* body, int pos);
Statement* BuildAssertIsCoercible(Variable* var);
// Factory methods.
FunctionLiteral* DefaultConstructor(bool call_super, Scope* scope, int pos,
......
......@@ -209,14 +209,21 @@ void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern) {
auto temp = descriptor_->declaration_scope->NewTemporary(
auto temp = TemporaryDeclarationScope()->NewTemporary(
ast_value_factory()->empty_string());
auto assignment =
factory()->NewAssignment(Token::ASSIGN, factory()->NewVariableProxy(temp),
current_value_, RelocInfo::kNoPosition);
block_->AddStatement(
factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
zone());
if (pattern->properties()->length() == 0) {
block_->AddStatement(descriptor_->parser->BuildAssertIsCoercible(temp),
zone());
}
for (ObjectLiteralProperty* property : *pattern->properties()) {
// TODO(dslomov): computed property names.
RecurseIntoSubpattern(
......
......@@ -6378,6 +6378,7 @@ TEST(DestructuringPositiveTests) {
"{42e-2 : x}",
"{'hi' : x}",
"{var: x}",
"{}",
NULL};
// clang-format on
static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring};
......
// 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.
// Flags: --harmony-destructuring
'use strict';
const { x : x, y : y } = { x : 1, y : 2 };
x++;
*%(basename)s:9: TypeError: Assignment to constant variable.
x++;
^
TypeError: Assignment to constant variable.
at *%(basename)s:9:2
......@@ -18,6 +18,26 @@
sum += z;
}
assertEquals(6, sum);
var log = [];
var o = {
get x() {
log.push("x");
return 0;
},
get y() {
log.push("y");
return {
get z() { log.push("z"); return 1; }
}
}
};
var { x : x0, y : { z : z1 }, x : x1 } = o;
assertSame(0, x0);
assertSame(1, z1);
assertSame(0, x1);
assertArrayEquals(["x", "y", "z", "x"], log);
}());
......@@ -30,6 +50,24 @@
let {z} = { z : 3 };
assertEquals(3, z);
let log = [];
let o = {
get x() {
log.push("x");
return 0;
},
get y() {
log.push("y");
return {
get z() { log.push("z"); return 1; }
}
}
};
let { x : x0, y : { z : z1 }, x : x1 } = o;
assertSame(0, x0);
assertSame(1, z1);
assertSame(0, x1);
assertArrayEquals(["x", "y", "z", "x"], log);
let sum = 0;
for(let {x, z} = { x : 0, z : 3 }; z != 0; z--) {
......@@ -46,6 +84,9 @@
assertEquals(1, x);
assertEquals(2, y);
assertThrows(function() { x++; }, TypeError);
assertThrows(function() { y++; }, TypeError);
const {z} = { z : 3 };
assertEquals(3, z);
......@@ -54,3 +95,49 @@
assertTrue(false);
}
}());
(function TestFailingMatchesSloppy() {
var {x, y} = {};
assertSame(undefined, x);
assertSame(undefined, y);
var { x : { z1 }, y2} = { x : {}, y2 : 42 }
assertSame(undefined, z1);
assertSame(42, y2);
}());
(function TestFailingMatchesStrict() {
'use strict';
var {x, y} = {};
assertSame(undefined, x);
assertSame(undefined, y);
var { x : { z1 }, y2} = { x : {}, y2 : 42 }
assertSame(undefined, z1);
assertSame(42, y2);
{
let {x1,y1} = {};
assertSame(undefined, x1);
assertSame(undefined, y1);
let { x : { z1 }, y2} = { x : {}, y2 : 42 }
assertSame(undefined, z1);
assertSame(42, y2);
}
}());
(function TestExceptions() {
for (var val of [null, undefined]) {
assertThrows(function() { var {} = val; }, TypeError);
assertThrows(function() { var {x} = val; }, TypeError);
assertThrows(function() { var { x : {} } = { x : val }; }, TypeError);
assertThrows(function() { 'use strict'; let {} = val; }, TypeError);
assertThrows(function() { 'use strict'; let {x} = val; }, TypeError);
assertThrows(function() { 'use strict'; let { x : {} } = { x : val }; },
TypeError);
}
}());
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