Implement data property creation for assignments to super.x.

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

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24331 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
dslomov@chromium.org 2014-09-30 13:19:47 +00:00
parent f3a19a7e76
commit b43ebcd800
2 changed files with 214 additions and 11 deletions

View File

@ -2906,13 +2906,11 @@ MaybeHandle<Object> Object::SetProperty(LookupIterator* it,
}
if (data_store_mode == SUPER_PROPERTY) {
if (strict_mode == STRICT) {
Handle<Object> args[1] = {it->name()};
THROW_NEW_ERROR(it->isolate(),
NewReferenceError("not_defined", HandleVector(args, 1)),
Object);
}
return value;
LookupIterator own_lookup(it->GetReceiver(), it->name(),
LookupIterator::OWN);
return JSObject::SetProperty(&own_lookup, value, strict_mode, store_mode,
NORMAL_PROPERTY);
}
return AddDataProperty(it, value, NONE, strict_mode, store_mode);

View File

@ -119,6 +119,30 @@
}());
(function TestSetterDataProperties() {
function Base() {}
Base.prototype = {
constructor: Base,
x : "x from Base"
};
function Derived() {}
Derived.prototype = {
__proto__: Base.prototype,
constructor: Derived,
};
Derived.prototype.testSetter = function() {
assertEquals("x from Base", super.x);
super.x = "data property";
assertEquals("x from Base", super.x);
assertEquals("data property", this.x);
}.toMethod(Derived.prototype);
new Derived().testSetter();
}());
(function TestAccessorsOnPrimitives() {
var getCalled = 0;
var setCalled = 0;
@ -157,6 +181,10 @@
assertEquals(6, super.x += 5);
assertEquals(2, getCalled);
assertEquals(2, setCalled);
super.newProperty = 15;
assertEquals(15, this.newProperty);
assertEquals(undefined, super.newProperty);
}.toMethod(Derived.prototype);
Derived.prototype.testSetterStrict = function() {
@ -176,6 +204,12 @@
assertEquals(6, super.x += 5);
assertEquals(2, getCalled);
assertEquals(2, setCalled);
var ex;
try {
super.newProperty = 15;
} catch(e) { ex = e; }
assertTrue(ex instanceof TypeError);
}.toMethod(Derived.prototype);
Derived.prototype.testSetter.call(42);
@ -199,25 +233,196 @@
}());
(function TestSetterFailures() {
(function TestSetterUndefinedProperties() {
function Base() {}
function Derived() {}
Derived.prototype = { __proto__ : Base.prototype };
Derived.prototype.mSloppy = function () {
assertEquals(undefined, super.x);
assertEquals(undefined, this.x);
super.x = 10;
assertEquals(10, this.x);
assertEquals(undefined, super.x);
}.toMethod(Derived.prototype);
Derived.prototype.mStrict = function () {
'use strict';
assertEquals(undefined, super.x);
assertEquals(undefined, this.x);
super.x = 10;
assertEquals(10, this.x);
assertEquals(undefined, super.x);
}.toMethod(Derived.prototype);
var d = new Derived();
d.mSloppy();
assertEquals(undefined, d.x);
assertEquals(10, d.x);
var d1 = new Derived();
assertThrows(function() { d.mStrict(); }, ReferenceError);
assertEquals(undefined, d.x);
d1.mStrict();
assertEquals(10, d.x);
}());
(function TestSetterCreatingOwnProperties() {
function Base() {}
function Derived() {}
Derived.prototype = { __proto__ : Base.prototype };
var setterCalled;
Derived.prototype.mSloppy = function() {
assertEquals(42, this.ownReadOnly);
super.ownReadOnly = 55;
assertEquals(42, this.ownReadOnly);
assertEquals(15, this.ownReadonlyAccessor);
super.ownReadonlyAccessor = 55;
assertEquals(15, this.ownReadonlyAccessor);
setterCalled = 0;
super.ownSetter = 42;
assertEquals(1, setterCalled);
}.toMethod(Derived.prototype);
Derived.prototype.mStrict = function() {
'use strict';
assertEquals(42, this.ownReadOnly);
var ex;
try {
super.ownReadOnly = 55;
} catch(e) { ex = e; }
assertTrue(ex instanceof TypeError);
assertEquals(42, this.ownReadOnly);
assertEquals(15, this.ownReadonlyAccessor);
ex = null;
try {
super.ownReadonlyAccessor = 55;
} catch(e) { ex = e; }
assertTrue(ex instanceof TypeError);
assertEquals(15, this.ownReadonlyAccessor);
setterCalled = 0;
super.ownSetter = 42;
assertEquals(1, setterCalled);
}.toMethod(Derived.prototype);
var d = new Derived();
Object.defineProperty(d, 'ownReadOnly', { value : 42, writable : false });
Object.defineProperty(d, 'ownSetter',
{ set : function() { setterCalled++; } });
Object.defineProperty(d, 'ownReadonlyAccessor',
{ get : function() { return 15; }});
d.mSloppy();
d.mStrict();
}());
(function TestSetterNoProtoWalk() {
function Base() {}
function Derived() {}
var getCalled;
var setCalled;
Derived.prototype = {
__proto__ : Base.prototype,
get x() { getCalled++; return 42; },
set x(v) { setCalled++; }
};
Derived.prototype.mSloppy = function() {
setCalled = 0;
getCalled = 0;
assertEquals(42, this.x);
assertEquals(1, getCalled);
assertEquals(0, setCalled);
getCalled = 0;
setCalled = 0;
this.x = 43;
assertEquals(0, getCalled);
assertEquals(1, setCalled);
getCalled = 0;
setCalled = 0;
super.x = 15;
assertEquals(0, setCalled);
assertEquals(0, getCalled);
assertEquals(15, this.x);
assertEquals(0, getCalled);
assertEquals(0, setCalled);
}.toMethod(Derived.prototype);
Derived.prototype.mStrict = function() {
'use strict';
setCalled = 0;
getCalled = 0;
assertEquals(42, this.x);
assertEquals(1, getCalled);
assertEquals(0, setCalled);
getCalled = 0;
setCalled = 0;
this.x = 43;
assertEquals(0, getCalled);
assertEquals(1, setCalled);
getCalled = 0;
setCalled = 0;
super.x = 15;
assertEquals(0, setCalled);
assertEquals(0, getCalled);
assertEquals(15, this.x);
assertEquals(0, getCalled);
assertEquals(0, setCalled);
}.toMethod(Derived.prototype);
new Derived().mSloppy();
new Derived().mStrict();
}());
(function TestSetterDoesNotReconfigure() {
function Base() {}
function Derived() {}
Derived.prototype.mStrict = function (){
'use strict';
super.nonEnumConfig = 5;
var d1 = Object.getOwnPropertyDescriptor(this, 'nonEnumConfig');
assertEquals(5, d1.value);
assertTrue(d1.configurable);
assertFalse(d1.enumerable);
super.nonEnumNonConfig = 5;
var d1 = Object.getOwnPropertyDescriptor(this, 'nonEnumNonConfig');
assertEquals(5, d1.value);
assertFalse(d1.configurable);
assertFalse(d1.enumerable);
}.toMethod(Derived.prototype);
Derived.prototype.mSloppy = function (){
super.nonEnumConfig = 42;
var d1 = Object.getOwnPropertyDescriptor(this, 'nonEnumConfig');
assertEquals(42, d1.value);
assertTrue(d1.configurable);
assertFalse(d1.enumerable);
super.nonEnumNonConfig = 42;
var d1 = Object.getOwnPropertyDescriptor(this, 'nonEnumNonConfig');
assertEquals(42, d1.value);
assertFalse(d1.configurable);
assertFalse(d1.enumerable);
}.toMethod(Derived.prototype);
var d = new Derived();
Object.defineProperty(d, 'nonEnumConfig',
{ value : 0, enumerable : false, configurable : true, writable : true });
Object.defineProperty(d, 'nonEnumNonConfig',
{ value : 0, enumerable : false, configurable : false, writable : true });
d.mStrict();
d.mSloppy();
}());