[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}
This commit is contained in:
parent
cc3f59db55
commit
cf9492ddd8
@ -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};
|
||||
|
9
test/message/destructuring-modify-const.js
Normal file
9
test/message/destructuring-modify-const.js
Normal file
@ -0,0 +1,9 @@
|
||||
// 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++;
|
5
test/message/destructuring-modify-const.out
Normal file
5
test/message/destructuring-modify-const.out
Normal file
@ -0,0 +1,5 @@
|
||||
*%(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);
|
||||
}
|
||||
}());
|
||||
|
Loading…
Reference in New Issue
Block a user