Keyed stores to super with numeric keys.
R=verwaest@chromium.org, arv@chromium.org, ishell@chromium.org BUG=v8:3330 LOG=N Review URL: https://codereview.chromium.org/649603003 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24696 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
8854589c79
commit
e149f81eba
124
src/objects.cc
124
src/objects.cc
@ -802,6 +802,82 @@ MaybeHandle<Object> Object::GetElementWithReceiver(Isolate* isolate,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MaybeHandle<Object> Object::SetElementWithReceiver(
|
||||||
|
Isolate* isolate, Handle<Object> object, Handle<Object> receiver,
|
||||||
|
uint32_t index, Handle<Object> value, StrictMode strict_mode) {
|
||||||
|
// Iterate up the prototype chain until an element is found or the null
|
||||||
|
// prototype is encountered.
|
||||||
|
bool done = false;
|
||||||
|
for (PrototypeIterator iter(isolate, object,
|
||||||
|
object->IsJSProxy() || object->IsJSObject()
|
||||||
|
? PrototypeIterator::START_AT_RECEIVER
|
||||||
|
: PrototypeIterator::START_AT_PROTOTYPE);
|
||||||
|
!iter.IsAtEnd() && !done; iter.Advance()) {
|
||||||
|
if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
|
||||||
|
// TODO(dslomov): implement.
|
||||||
|
isolate->ThrowIllegalOperation();
|
||||||
|
return MaybeHandle<Object>();
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle<JSObject> js_object =
|
||||||
|
Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
|
||||||
|
|
||||||
|
// Check access rights if needed.
|
||||||
|
if (js_object->IsAccessCheckNeeded()) {
|
||||||
|
if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_SET)) {
|
||||||
|
isolate->ReportFailedAccessCheck(js_object, v8::ACCESS_SET);
|
||||||
|
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
||||||
|
return isolate->factory()->undefined_value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (js_object->HasIndexedInterceptor()) {
|
||||||
|
Maybe<PropertyAttributes> from_interceptor =
|
||||||
|
JSObject::GetElementAttributeFromInterceptor(js_object, receiver,
|
||||||
|
index);
|
||||||
|
if (!from_interceptor.has_value) return MaybeHandle<Object>();
|
||||||
|
if ((from_interceptor.value & READ_ONLY) != 0) {
|
||||||
|
return WriteToReadOnlyElement(isolate, receiver, index, value,
|
||||||
|
strict_mode);
|
||||||
|
}
|
||||||
|
done = from_interceptor.value != ABSENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!done &&
|
||||||
|
js_object->elements() != isolate->heap()->empty_fixed_array()) {
|
||||||
|
ElementsAccessor* accessor = js_object->GetElementsAccessor();
|
||||||
|
PropertyAttributes attrs =
|
||||||
|
accessor->GetAttributes(receiver, js_object, index);
|
||||||
|
if ((attrs & READ_ONLY) != 0) {
|
||||||
|
return WriteToReadOnlyElement(isolate, receiver, index, value,
|
||||||
|
strict_mode);
|
||||||
|
}
|
||||||
|
Handle<AccessorPair> accessor_pair;
|
||||||
|
if (accessor->GetAccessorPair(receiver, js_object, index)
|
||||||
|
.ToHandle(&accessor_pair)) {
|
||||||
|
return JSObject::SetElementWithCallback(receiver, accessor_pair, index,
|
||||||
|
value, js_object, strict_mode);
|
||||||
|
} else {
|
||||||
|
done = attrs != ABSENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!receiver->IsJSObject()) {
|
||||||
|
return WriteToReadOnlyElement(isolate, receiver, index, value, strict_mode);
|
||||||
|
}
|
||||||
|
Handle<JSObject> target = Handle<JSObject>::cast(receiver);
|
||||||
|
ElementsAccessor* accessor = target->GetElementsAccessor();
|
||||||
|
PropertyAttributes attrs = accessor->GetAttributes(receiver, target, index);
|
||||||
|
if ((attrs & READ_ONLY) != 0) {
|
||||||
|
return WriteToReadOnlyElement(isolate, receiver, index, value, strict_mode);
|
||||||
|
}
|
||||||
|
PropertyAttributes new_attrs = attrs != ABSENT ? attrs : NONE;
|
||||||
|
return JSObject::SetElement(target, index, value, new_attrs, strict_mode,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Map* Object::GetRootMap(Isolate* isolate) {
|
Map* Object::GetRootMap(Isolate* isolate) {
|
||||||
DisallowHeapAllocation no_alloc;
|
DisallowHeapAllocation no_alloc;
|
||||||
if (IsSmi()) {
|
if (IsSmi()) {
|
||||||
@ -2932,6 +3008,21 @@ MaybeHandle<Object> Object::WriteToReadOnlyProperty(LookupIterator* it,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MaybeHandle<Object> Object::WriteToReadOnlyElement(Isolate* isolate,
|
||||||
|
Handle<Object> receiver,
|
||||||
|
uint32_t index,
|
||||||
|
Handle<Object> value,
|
||||||
|
StrictMode strict_mode) {
|
||||||
|
if (strict_mode != STRICT) return value;
|
||||||
|
|
||||||
|
Handle<Object> args[] = {isolate->factory()->NewNumberFromUint(index),
|
||||||
|
receiver};
|
||||||
|
THROW_NEW_ERROR(isolate, NewTypeError("strict_read_only_property",
|
||||||
|
HandleVector(args, arraysize(args))),
|
||||||
|
Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it,
|
MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it,
|
||||||
Handle<Object> value) {
|
Handle<Object> value) {
|
||||||
// Proxies are handled on the WithHandler path. Other non-JSObjects cannot
|
// Proxies are handled on the WithHandler path. Other non-JSObjects cannot
|
||||||
@ -4075,6 +4166,21 @@ Maybe<PropertyAttributes> JSObject::GetElementAttributeWithInterceptor(
|
|||||||
// callbacks or interceptor calls.
|
// callbacks or interceptor calls.
|
||||||
AssertNoContextChange ncc(isolate);
|
AssertNoContextChange ncc(isolate);
|
||||||
|
|
||||||
|
Maybe<PropertyAttributes> from_interceptor =
|
||||||
|
GetElementAttributeFromInterceptor(object, receiver, index);
|
||||||
|
if (!from_interceptor.has_value) return Maybe<PropertyAttributes>();
|
||||||
|
if (from_interceptor.value != ABSENT) return maybe(from_interceptor.value);
|
||||||
|
|
||||||
|
return GetElementAttributeWithoutInterceptor(object, receiver, index,
|
||||||
|
check_prototype);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Maybe<PropertyAttributes> JSObject::GetElementAttributeFromInterceptor(
|
||||||
|
Handle<JSObject> object, Handle<Object> receiver, uint32_t index) {
|
||||||
|
Isolate* isolate = object->GetIsolate();
|
||||||
|
AssertNoContextChange ncc(isolate);
|
||||||
|
|
||||||
Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
|
Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
|
||||||
PropertyCallbackArguments args(
|
PropertyCallbackArguments args(
|
||||||
isolate, interceptor->data(), *receiver, *object);
|
isolate, interceptor->data(), *receiver, *object);
|
||||||
@ -4095,9 +4201,8 @@ Maybe<PropertyAttributes> JSObject::GetElementAttributeWithInterceptor(
|
|||||||
v8::Handle<v8::Value> result = args.Call(getter, index);
|
v8::Handle<v8::Value> result = args.Call(getter, index);
|
||||||
if (!result.IsEmpty()) return maybe(NONE);
|
if (!result.IsEmpty()) return maybe(NONE);
|
||||||
}
|
}
|
||||||
|
RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<PropertyAttributes>());
|
||||||
return GetElementAttributeWithoutInterceptor(
|
return maybe(ABSENT);
|
||||||
object, receiver, index, check_prototype);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -11867,13 +11972,10 @@ MaybeHandle<Object> JSObject::GetElementWithCallback(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MaybeHandle<Object> JSObject::SetElementWithCallback(Handle<JSObject> object,
|
MaybeHandle<Object> JSObject::SetElementWithCallback(
|
||||||
Handle<Object> structure,
|
Handle<Object> object, Handle<Object> structure, uint32_t index,
|
||||||
uint32_t index,
|
Handle<Object> value, Handle<JSObject> holder, StrictMode strict_mode) {
|
||||||
Handle<Object> value,
|
Isolate* isolate = holder->GetIsolate();
|
||||||
Handle<JSObject> holder,
|
|
||||||
StrictMode strict_mode) {
|
|
||||||
Isolate* isolate = object->GetIsolate();
|
|
||||||
|
|
||||||
// We should never get here to initialize a const with the hole
|
// We should never get here to initialize a const with the hole
|
||||||
// value since a const declaration would conflict with the setter.
|
// value since a const declaration would conflict with the setter.
|
||||||
@ -11889,7 +11991,7 @@ MaybeHandle<Object> JSObject::SetElementWithCallback(Handle<JSObject> object,
|
|||||||
if (call_fun == NULL) return value;
|
if (call_fun == NULL) return value;
|
||||||
Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
|
Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
|
||||||
Handle<String> key(isolate->factory()->NumberToString(number));
|
Handle<String> key(isolate->factory()->NumberToString(number));
|
||||||
LOG(isolate, ApiNamedPropertyAccess("store", *object, *key));
|
LOG(isolate, ApiNamedPropertyAccess("store", *holder, *key));
|
||||||
PropertyCallbackArguments
|
PropertyCallbackArguments
|
||||||
args(isolate, data->data(), *object, *holder);
|
args(isolate, data->data(), *object, *holder);
|
||||||
args.Call(call_fun,
|
args.Call(call_fun,
|
||||||
|
@ -1131,6 +1131,9 @@ class Object {
|
|||||||
StorePropertyMode data_store_mode = NORMAL_PROPERTY);
|
StorePropertyMode data_store_mode = NORMAL_PROPERTY);
|
||||||
MUST_USE_RESULT static MaybeHandle<Object> WriteToReadOnlyProperty(
|
MUST_USE_RESULT static MaybeHandle<Object> WriteToReadOnlyProperty(
|
||||||
LookupIterator* it, Handle<Object> value, StrictMode strict_mode);
|
LookupIterator* it, Handle<Object> value, StrictMode strict_mode);
|
||||||
|
MUST_USE_RESULT static MaybeHandle<Object> WriteToReadOnlyElement(
|
||||||
|
Isolate* isolate, Handle<Object> receiver, uint32_t index,
|
||||||
|
Handle<Object> value, StrictMode strict_mode);
|
||||||
MUST_USE_RESULT static MaybeHandle<Object> SetDataProperty(
|
MUST_USE_RESULT static MaybeHandle<Object> SetDataProperty(
|
||||||
LookupIterator* it, Handle<Object> value);
|
LookupIterator* it, Handle<Object> value);
|
||||||
MUST_USE_RESULT static MaybeHandle<Object> AddDataProperty(
|
MUST_USE_RESULT static MaybeHandle<Object> AddDataProperty(
|
||||||
@ -1176,6 +1179,10 @@ class Object {
|
|||||||
Handle<Object> receiver,
|
Handle<Object> receiver,
|
||||||
uint32_t index);
|
uint32_t index);
|
||||||
|
|
||||||
|
MUST_USE_RESULT static MaybeHandle<Object> SetElementWithReceiver(
|
||||||
|
Isolate* isolate, Handle<Object> object, Handle<Object> receiver,
|
||||||
|
uint32_t index, Handle<Object> value, StrictMode strict_mode);
|
||||||
|
|
||||||
static inline Handle<Object> GetPrototypeSkipHiddenPrototypes(
|
static inline Handle<Object> GetPrototypeSkipHiddenPrototypes(
|
||||||
Isolate* isolate, Handle<Object> receiver);
|
Isolate* isolate, Handle<Object> receiver);
|
||||||
|
|
||||||
@ -1927,8 +1934,7 @@ class JSObject: public JSReceiver {
|
|||||||
|
|
||||||
// These methods do not perform access checks!
|
// These methods do not perform access checks!
|
||||||
MUST_USE_RESULT static MaybeHandle<AccessorPair> GetOwnElementAccessorPair(
|
MUST_USE_RESULT static MaybeHandle<AccessorPair> GetOwnElementAccessorPair(
|
||||||
Handle<JSObject> object,
|
Handle<JSObject> object, uint32_t index);
|
||||||
uint32_t index);
|
|
||||||
|
|
||||||
MUST_USE_RESULT static MaybeHandle<Object> SetFastElement(
|
MUST_USE_RESULT static MaybeHandle<Object> SetFastElement(
|
||||||
Handle<JSObject> object,
|
Handle<JSObject> object,
|
||||||
@ -2253,18 +2259,30 @@ class JSObject: public JSReceiver {
|
|||||||
GetElementAttributeWithInterceptor(Handle<JSObject> object,
|
GetElementAttributeWithInterceptor(Handle<JSObject> object,
|
||||||
Handle<JSReceiver> receiver,
|
Handle<JSReceiver> receiver,
|
||||||
uint32_t index, bool continue_search);
|
uint32_t index, bool continue_search);
|
||||||
|
|
||||||
|
// Queries indexed interceptor on an object for property attributes.
|
||||||
|
//
|
||||||
|
// We determine property attributes as follows:
|
||||||
|
// - if interceptor has a query callback, then the property attributes are
|
||||||
|
// the result of query callback for index.
|
||||||
|
// - otherwise if interceptor has a getter callback and it returns
|
||||||
|
// non-empty value on index, then the property attributes is NONE
|
||||||
|
// (property is present, and it is enumerable, configurable, writable)
|
||||||
|
// - otherwise there are no property attributes that can be inferred for
|
||||||
|
// interceptor, and this function returns ABSENT.
|
||||||
|
MUST_USE_RESULT static Maybe<PropertyAttributes>
|
||||||
|
GetElementAttributeFromInterceptor(Handle<JSObject> object,
|
||||||
|
Handle<Object> receiver,
|
||||||
|
uint32_t index);
|
||||||
|
|
||||||
MUST_USE_RESULT static Maybe<PropertyAttributes>
|
MUST_USE_RESULT static Maybe<PropertyAttributes>
|
||||||
GetElementAttributeWithoutInterceptor(Handle<JSObject> object,
|
GetElementAttributeWithoutInterceptor(Handle<JSObject> object,
|
||||||
Handle<JSReceiver> receiver,
|
Handle<JSReceiver> receiver,
|
||||||
uint32_t index,
|
uint32_t index,
|
||||||
bool continue_search);
|
bool continue_search);
|
||||||
MUST_USE_RESULT static MaybeHandle<Object> SetElementWithCallback(
|
MUST_USE_RESULT static MaybeHandle<Object> SetElementWithCallback(
|
||||||
Handle<JSObject> object,
|
Handle<Object> object, Handle<Object> structure, uint32_t index,
|
||||||
Handle<Object> structure,
|
Handle<Object> value, Handle<JSObject> holder, StrictMode strict_mode);
|
||||||
uint32_t index,
|
|
||||||
Handle<Object> value,
|
|
||||||
Handle<JSObject> holder,
|
|
||||||
StrictMode strict_mode);
|
|
||||||
MUST_USE_RESULT static MaybeHandle<Object> SetElementWithInterceptor(
|
MUST_USE_RESULT static MaybeHandle<Object> SetElementWithInterceptor(
|
||||||
Handle<JSObject> object,
|
Handle<JSObject> object,
|
||||||
uint32_t index,
|
uint32_t index,
|
||||||
|
@ -287,6 +287,30 @@ static Object* StoreToSuper(Isolate* isolate, Handle<JSObject> home_object,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static Object* StoreElementToSuper(Isolate* isolate,
|
||||||
|
Handle<JSObject> home_object,
|
||||||
|
Handle<Object> receiver, uint32_t index,
|
||||||
|
Handle<Object> value,
|
||||||
|
StrictMode strict_mode) {
|
||||||
|
if (home_object->IsAccessCheckNeeded() &&
|
||||||
|
!isolate->MayIndexedAccess(home_object, index, v8::ACCESS_SET)) {
|
||||||
|
isolate->ReportFailedAccessCheck(home_object, v8::ACCESS_SET);
|
||||||
|
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
|
||||||
|
}
|
||||||
|
|
||||||
|
PrototypeIterator iter(isolate, home_object);
|
||||||
|
Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
|
||||||
|
if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
|
||||||
|
|
||||||
|
Handle<Object> result;
|
||||||
|
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||||
|
isolate, result,
|
||||||
|
Object::SetElementWithReceiver(isolate, proto, receiver, index, value,
|
||||||
|
strict_mode));
|
||||||
|
return *result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
RUNTIME_FUNCTION(Runtime_StoreToSuper_Strict) {
|
RUNTIME_FUNCTION(Runtime_StoreToSuper_Strict) {
|
||||||
HandleScope scope(isolate);
|
HandleScope scope(isolate);
|
||||||
DCHECK(args.length() == 4);
|
DCHECK(args.length() == 4);
|
||||||
@ -314,13 +338,18 @@ RUNTIME_FUNCTION(Runtime_StoreToSuper_Sloppy) {
|
|||||||
static Object* StoreKeyedToSuper(Isolate* isolate, Handle<JSObject> home_object,
|
static Object* StoreKeyedToSuper(Isolate* isolate, Handle<JSObject> home_object,
|
||||||
Handle<Object> receiver, Handle<Object> key,
|
Handle<Object> receiver, Handle<Object> key,
|
||||||
Handle<Object> value, StrictMode strict_mode) {
|
Handle<Object> value, StrictMode strict_mode) {
|
||||||
|
uint32_t index;
|
||||||
|
|
||||||
|
if (key->ToArrayIndex(&index)) {
|
||||||
|
return StoreElementToSuper(isolate, home_object, receiver, index, value,
|
||||||
|
strict_mode);
|
||||||
|
}
|
||||||
Handle<Name> name;
|
Handle<Name> name;
|
||||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
|
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
|
||||||
Runtime::ToName(isolate, key));
|
Runtime::ToName(isolate, key));
|
||||||
uint32_t index;
|
|
||||||
if (name->AsArrayIndex(&index)) {
|
if (name->AsArrayIndex(&index)) {
|
||||||
// TODO(dslomov): Implement.
|
return StoreElementToSuper(isolate, home_object, receiver, index, value,
|
||||||
return ThrowUnsupportedSuper(isolate);
|
strict_mode);
|
||||||
}
|
}
|
||||||
return StoreToSuper(isolate, home_object, receiver, name, value, strict_mode);
|
return StoreToSuper(isolate, home_object, receiver, name, value, strict_mode);
|
||||||
}
|
}
|
||||||
|
@ -321,6 +321,74 @@
|
|||||||
}());
|
}());
|
||||||
|
|
||||||
|
|
||||||
|
(function TestSetterNumericKeyed() {
|
||||||
|
var x = 42;
|
||||||
|
function Base() {}
|
||||||
|
Base.prototype = {
|
||||||
|
constructor: Base,
|
||||||
|
_x: 'base'
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.defineProperty(Base.prototype, x,
|
||||||
|
{ get: function() { return this._x; },
|
||||||
|
set: function(v) { this._x = v; }
|
||||||
|
});
|
||||||
|
|
||||||
|
function Derived() {}
|
||||||
|
Derived.__proto__ = Base;
|
||||||
|
Derived.prototype = {
|
||||||
|
__proto__: Base.prototype,
|
||||||
|
constructor: Derived,
|
||||||
|
_x: 'derived'
|
||||||
|
};
|
||||||
|
Derived.prototype.testSetter = function() {
|
||||||
|
assertEquals('foobar', super[x] = 'foobar');
|
||||||
|
assertEquals('foobarabc', super[x] += 'abc');
|
||||||
|
}.toMethod(Derived.prototype);
|
||||||
|
var d = new Derived();
|
||||||
|
d.testSetter();
|
||||||
|
assertEquals('base', Base.prototype._x);
|
||||||
|
assertEquals('foobarabc', d._x);
|
||||||
|
d._x = '';
|
||||||
|
Derived.prototype.testSetterStrict = function() {
|
||||||
|
'use strict';
|
||||||
|
assertEquals('foobar', super[x] = 'foobar');
|
||||||
|
assertEquals('foobarabc', super[x] += 'abc');
|
||||||
|
}.toMethod(Derived.prototype);
|
||||||
|
d.testSetterStrict();
|
||||||
|
assertEquals('base', Base.prototype._x);
|
||||||
|
assertEquals('foobarabc', d._x);
|
||||||
|
|
||||||
|
|
||||||
|
Derived.prototype.testSetterWithToString = function() {
|
||||||
|
var toStringCalled;
|
||||||
|
var o = { toString: function() {
|
||||||
|
toStringCalled++;
|
||||||
|
return x;
|
||||||
|
} };
|
||||||
|
|
||||||
|
toStringCalled = 0;
|
||||||
|
super[o] = 'set';
|
||||||
|
assertEquals(1, toStringCalled);
|
||||||
|
assertEquals('set', this._x);
|
||||||
|
|
||||||
|
var eToThrow = new Error();
|
||||||
|
var oThrowsInToString = { toString: function() {
|
||||||
|
throw eToThrow;
|
||||||
|
} };
|
||||||
|
|
||||||
|
var ex = null;
|
||||||
|
try {
|
||||||
|
super[oThrowsInToString] = 'xyz';
|
||||||
|
} catch(e) { ex = e }
|
||||||
|
assertEquals(eToThrow, ex);
|
||||||
|
assertEquals('set', this._x);
|
||||||
|
}.toMethod(Derived.prototype);
|
||||||
|
d = new Derived();
|
||||||
|
d.testSetterWithToString();
|
||||||
|
}());
|
||||||
|
|
||||||
|
|
||||||
(function TestSetterKeyed() {
|
(function TestSetterKeyed() {
|
||||||
var x = 'x';
|
var x = 'x';
|
||||||
function Base() {}
|
function Base() {}
|
||||||
@ -389,19 +457,11 @@
|
|||||||
return "1";
|
return "1";
|
||||||
} };
|
} };
|
||||||
|
|
||||||
ex = null;
|
assertEquals('abc', super[oReturnsNumericString] = 'abc');
|
||||||
try {
|
|
||||||
super[oReturnsNumericString] = 'abc';
|
|
||||||
} catch(e) { ex = e }
|
|
||||||
assertTrue(ex instanceof ReferenceError);
|
|
||||||
|
|
||||||
assertEquals('set', this._x);
|
assertEquals('set', this._x);
|
||||||
|
|
||||||
ex = null;
|
assertEquals(10, super[1] = 10);
|
||||||
try {
|
|
||||||
super[1] = 10; // Indexed properties unsupported yet.
|
|
||||||
} catch (e) { ex = e; }
|
|
||||||
assertTrue(ex instanceof ReferenceError);
|
|
||||||
}.toMethod(Derived.prototype);
|
}.toMethod(Derived.prototype);
|
||||||
d = new Derived();
|
d = new Derived();
|
||||||
d.testSetterWithToString();
|
d.testSetterWithToString();
|
||||||
@ -457,6 +517,31 @@
|
|||||||
}());
|
}());
|
||||||
|
|
||||||
|
|
||||||
|
(function TestKeyedNumericSetterDataProperties() {
|
||||||
|
var x = 42;
|
||||||
|
function Base() {}
|
||||||
|
Base.prototype = {
|
||||||
|
constructor: Base,
|
||||||
|
42: '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() {
|
(function TestAccessorsOnPrimitives() {
|
||||||
var getCalled = 0;
|
var getCalled = 0;
|
||||||
var setCalled = 0;
|
var setCalled = 0;
|
||||||
@ -640,6 +725,122 @@
|
|||||||
}());
|
}());
|
||||||
|
|
||||||
|
|
||||||
|
(function TestNumericKeyedAccessorsOnPrimitives() {
|
||||||
|
var x = 42;
|
||||||
|
var newProperty = 43;
|
||||||
|
var getCalled = 0;
|
||||||
|
var setCalled = 0;
|
||||||
|
function Base() {}
|
||||||
|
Base.prototype = {
|
||||||
|
constructor: Base,
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.defineProperty(Base.prototype, x, {
|
||||||
|
get: function() {
|
||||||
|
getCalled++;
|
||||||
|
return 1;
|
||||||
|
},
|
||||||
|
set: function(v) {
|
||||||
|
setCalled++;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function Derived() {}
|
||||||
|
Derived.prototype = {
|
||||||
|
__proto__: Base.prototype,
|
||||||
|
constructor: Derived,
|
||||||
|
};
|
||||||
|
Derived.prototype.testSetter = function() {
|
||||||
|
setCalled = 0;
|
||||||
|
getCalled = 0;
|
||||||
|
assertEquals('object', typeof this);
|
||||||
|
assertTrue(this instanceof Number)
|
||||||
|
assertEquals(42, this.valueOf());
|
||||||
|
assertEquals(1, super[x]);
|
||||||
|
assertEquals(1, getCalled);
|
||||||
|
assertEquals(0, setCalled);
|
||||||
|
|
||||||
|
assertEquals(5, super[x] = 5);
|
||||||
|
assertEquals(1, getCalled);
|
||||||
|
assertEquals(1, setCalled);
|
||||||
|
|
||||||
|
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() {
|
||||||
|
'use strict';
|
||||||
|
getCalled = 0;
|
||||||
|
setCalled = 0;
|
||||||
|
assertTrue(42 === this);
|
||||||
|
|
||||||
|
assertEquals(1, super[x]);
|
||||||
|
assertEquals(1, getCalled);
|
||||||
|
assertEquals(0, setCalled);
|
||||||
|
|
||||||
|
assertEquals(5, super[x] = 5);
|
||||||
|
assertEquals(1, getCalled);
|
||||||
|
assertEquals(1, setCalled);
|
||||||
|
|
||||||
|
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);
|
||||||
|
Derived.prototype.testSetterStrict.call(42);
|
||||||
|
}());
|
||||||
|
|
||||||
|
|
||||||
|
(function TestKeyedNumericSetterOnExotics() {
|
||||||
|
function Base() {}
|
||||||
|
function Derived() {}
|
||||||
|
Derived.prototype = { __proto__: Base.prototype };
|
||||||
|
|
||||||
|
Derived.prototype.callSetterOnArray = function() {
|
||||||
|
super[42] = 1;
|
||||||
|
}.toMethod(Derived.prototype);
|
||||||
|
|
||||||
|
Derived.prototype.callStrictSetterOnString = function() {
|
||||||
|
'use strict';
|
||||||
|
assertEquals('string', typeof this);
|
||||||
|
assertTrue('abcdef' === this);
|
||||||
|
var ex = null;
|
||||||
|
try {
|
||||||
|
super[5] = 'q';
|
||||||
|
} catch(e) { ex = e; }
|
||||||
|
assertTrue(ex instanceof TypeError);
|
||||||
|
|
||||||
|
ex = null;
|
||||||
|
try {
|
||||||
|
super[1024] = 'q';
|
||||||
|
} catch(e) { ex = e; }
|
||||||
|
assertTrue(ex instanceof TypeError);
|
||||||
|
}.toMethod(Derived.prototype);
|
||||||
|
|
||||||
|
var x = [];
|
||||||
|
assertEquals(0, x.length);
|
||||||
|
Derived.prototype.callSetterOnArray.call(x);
|
||||||
|
assertEquals(43, x.length);
|
||||||
|
assertEquals(1, x[42]);
|
||||||
|
|
||||||
|
var s = 'abcdef';
|
||||||
|
Derived.prototype.callStrictSetterOnString.call(s)
|
||||||
|
}());
|
||||||
|
|
||||||
|
|
||||||
(function TestSetterUndefinedProperties() {
|
(function TestSetterUndefinedProperties() {
|
||||||
function Base() {}
|
function Base() {}
|
||||||
function Derived() {}
|
function Derived() {}
|
||||||
@ -699,6 +900,36 @@
|
|||||||
}());
|
}());
|
||||||
|
|
||||||
|
|
||||||
|
(function TestKeyedNumericSetterUndefinedProperties() {
|
||||||
|
var x = 42;
|
||||||
|
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(10, d[x]);
|
||||||
|
var d1 = new Derived();
|
||||||
|
d1.mStrict();
|
||||||
|
assertEquals(10, d[x]);
|
||||||
|
}());
|
||||||
|
|
||||||
|
|
||||||
(function TestSetterCreatingOwnProperties() {
|
(function TestSetterCreatingOwnProperties() {
|
||||||
function Base() {}
|
function Base() {}
|
||||||
function Derived() {}
|
function Derived() {}
|
||||||
@ -870,6 +1101,63 @@
|
|||||||
}());
|
}());
|
||||||
|
|
||||||
|
|
||||||
|
(function TestKeyedNumericSetterCreatingOwnProperties() {
|
||||||
|
var ownReadOnly = 42;
|
||||||
|
var ownReadonlyAccessor = 43;
|
||||||
|
var ownSetter = 44;
|
||||||
|
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 TestSetterNoProtoWalk() {
|
||||||
function Base() {}
|
function Base() {}
|
||||||
function Derived() {}
|
function Derived() {}
|
||||||
@ -1005,6 +1293,77 @@
|
|||||||
}());
|
}());
|
||||||
|
|
||||||
|
|
||||||
|
(function TestKeyedNumericSetterNoProtoWalk() {
|
||||||
|
var x = 42;
|
||||||
|
function Base() {}
|
||||||
|
function Derived() {}
|
||||||
|
var getCalled;
|
||||||
|
var setCalled;
|
||||||
|
Derived.prototype = {
|
||||||
|
__proto__ : Base.prototype,
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.defineProperty(Derived.prototype, x, {
|
||||||
|
get: function() { getCalled++; return 42; },
|
||||||
|
set: function(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 TestSetterDoesNotReconfigure() {
|
||||||
function Base() {}
|
function Base() {}
|
||||||
function Derived() {}
|
function Derived() {}
|
||||||
@ -1054,16 +1413,18 @@
|
|||||||
function Base() {}
|
function Base() {}
|
||||||
function Derived() {}
|
function Derived() {}
|
||||||
|
|
||||||
|
Derived.prototype = { __proto__: Base.prototype };
|
||||||
|
|
||||||
Derived.prototype.mStrict = function (){
|
Derived.prototype.mStrict = function (){
|
||||||
'use strict';
|
'use strict';
|
||||||
super[nonEnumConfig] = 5;
|
super[nonEnumConfig] = 5;
|
||||||
var d1 = Object.getOwnPropertyDescriptor(this, 'nonEnumConfig');
|
var d1 = Object.getOwnPropertyDescriptor(this, nonEnumConfig);
|
||||||
assertEquals(5, d1.value);
|
assertEquals(5, d1.value);
|
||||||
assertTrue(d1.configurable);
|
assertTrue(d1.configurable);
|
||||||
assertFalse(d1.enumerable);
|
assertFalse(d1.enumerable);
|
||||||
|
|
||||||
super[nonEnumNonConfig] = 5;
|
super[nonEnumNonConfig] = 5;
|
||||||
var d1 = Object.getOwnPropertyDescriptor(this, 'nonEnumNonConfig');
|
var d1 = Object.getOwnPropertyDescriptor(this, nonEnumNonConfig);
|
||||||
assertEquals(5, d1.value);
|
assertEquals(5, d1.value);
|
||||||
assertFalse(d1.configurable);
|
assertFalse(d1.configurable);
|
||||||
assertFalse(d1.enumerable);
|
assertFalse(d1.enumerable);
|
||||||
@ -1071,22 +1432,69 @@
|
|||||||
|
|
||||||
Derived.prototype.mSloppy = function (){
|
Derived.prototype.mSloppy = function (){
|
||||||
super[nonEnumConfig] = 42;
|
super[nonEnumConfig] = 42;
|
||||||
var d1 = Object.getOwnPropertyDescriptor(this, 'nonEnumConfig');
|
var d1 = Object.getOwnPropertyDescriptor(this, nonEnumConfig);
|
||||||
assertEquals(42, d1.value);
|
assertEquals(42, d1.value);
|
||||||
assertTrue(d1.configurable);
|
assertTrue(d1.configurable);
|
||||||
assertFalse(d1.enumerable);
|
assertFalse(d1.enumerable);
|
||||||
|
|
||||||
super[nonEnumNonConfig] = 42;
|
super[nonEnumNonConfig] = 42;
|
||||||
var d1 = Object.getOwnPropertyDescriptor(this, 'nonEnumNonConfig');
|
var d1 = Object.getOwnPropertyDescriptor(this, nonEnumNonConfig);
|
||||||
assertEquals(42, d1.value);
|
assertEquals(42, d1.value);
|
||||||
assertFalse(d1.configurable);
|
assertFalse(d1.configurable);
|
||||||
assertFalse(d1.enumerable);
|
assertFalse(d1.enumerable);
|
||||||
}.toMethod(Derived.prototype);
|
}.toMethod(Derived.prototype);
|
||||||
|
|
||||||
var d = new Derived();
|
var d = new Derived();
|
||||||
Object.defineProperty(d, 'nonEnumConfig',
|
Object.defineProperty(d, nonEnumConfig,
|
||||||
{ value : 0, enumerable : false, configurable : true, writable : true });
|
{ value : 0, enumerable : false, configurable : true, writable : true });
|
||||||
Object.defineProperty(d, 'nonEnumNonConfig',
|
Object.defineProperty(d, nonEnumNonConfig,
|
||||||
|
{ value : 0, enumerable : false, configurable : false, writable : true });
|
||||||
|
d.mStrict();
|
||||||
|
d.mSloppy();
|
||||||
|
}());
|
||||||
|
|
||||||
|
|
||||||
|
(function TestKeyedNumericSetterDoesNotReconfigure() {
|
||||||
|
var nonEnumConfig = 42;
|
||||||
|
var nonEnumNonConfig = 43;
|
||||||
|
function Base() {}
|
||||||
|
function Derived() {}
|
||||||
|
|
||||||
|
Derived.prototype = { __proto__: Base.prototype };
|
||||||
|
|
||||||
|
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 });
|
{ value : 0, enumerable : false, configurable : false, writable : true });
|
||||||
d.mStrict();
|
d.mStrict();
|
||||||
d.mSloppy();
|
d.mSloppy();
|
||||||
@ -1190,6 +1598,143 @@
|
|||||||
}());
|
}());
|
||||||
|
|
||||||
|
|
||||||
|
(function TestKeyedNumericCountOperations() {
|
||||||
|
var x = 42;
|
||||||
|
function Base() {}
|
||||||
|
Base.prototype = {
|
||||||
|
constructor: Base,
|
||||||
|
_x: 1
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.defineProperty(Base.prototype, x, {
|
||||||
|
get: function() { return this._x; },
|
||||||
|
set: function(v) { this._x = v;; }
|
||||||
|
});
|
||||||
|
|
||||||
|
function Derived() {}
|
||||||
|
Derived.__proto__ = Base;
|
||||||
|
Derived.prototype = {
|
||||||
|
__proto__: Base.prototype,
|
||||||
|
constructor: Derived,
|
||||||
|
_x: 2
|
||||||
|
};
|
||||||
|
|
||||||
|
Derived.prototype.testCounts = function() {
|
||||||
|
assertEquals(2, this._x);
|
||||||
|
assertEquals(2, super[x]);
|
||||||
|
super[x]++;
|
||||||
|
assertEquals(3, super[x]);
|
||||||
|
++super[x];
|
||||||
|
assertEquals(4, super[x]);
|
||||||
|
assertEquals(4, super[x]++);
|
||||||
|
assertEquals(5, super[x]);
|
||||||
|
assertEquals(6, ++super[x]);
|
||||||
|
assertEquals(6, super[x]);
|
||||||
|
assertEquals(6, this._x);
|
||||||
|
|
||||||
|
super[x]--;
|
||||||
|
assertEquals(5, super[x]);
|
||||||
|
--super[x];
|
||||||
|
assertEquals(4, super[x]);
|
||||||
|
assertEquals(4, super[x]--);
|
||||||
|
assertEquals(3, super[x]);
|
||||||
|
assertEquals(2, --super[x]);
|
||||||
|
assertEquals(2, super[x]);
|
||||||
|
assertEquals(2, this._x);
|
||||||
|
}.toMethod(Derived.prototype);
|
||||||
|
new Derived().testCounts();
|
||||||
|
}());
|
||||||
|
|
||||||
|
|
||||||
|
(function TestSetterSuperNonWritable() {
|
||||||
|
function Base() {}
|
||||||
|
Object.defineProperty(Base.prototype, 'x', { value : 27, writable: false });
|
||||||
|
function Derived() {}
|
||||||
|
|
||||||
|
Derived.prototype = { __proto__: Base.prototype, constructor: Derived };
|
||||||
|
|
||||||
|
Derived.prototype.mSloppy = function() {
|
||||||
|
assertEquals(27, super.x);
|
||||||
|
assertEquals(27, this.x);
|
||||||
|
super.x = 10;
|
||||||
|
assertEquals(27, super.x);
|
||||||
|
assertEquals(27, this.x);
|
||||||
|
}.toMethod(Derived.prototype);
|
||||||
|
Derived.prototype.mStrict = function() {
|
||||||
|
'use strict';
|
||||||
|
assertEquals(27, super.x);
|
||||||
|
assertEquals(27, this.x);
|
||||||
|
var ex = null;
|
||||||
|
try { super.x = 10; } catch(e) { ex = e; }
|
||||||
|
assertTrue(ex instanceof TypeError);
|
||||||
|
assertEquals(27, super.x);
|
||||||
|
assertEquals(27, this.x);
|
||||||
|
}.toMethod(Derived.prototype);
|
||||||
|
new Derived().mSloppy();
|
||||||
|
new Derived().mStrict();
|
||||||
|
}());
|
||||||
|
|
||||||
|
|
||||||
|
(function TestSetterKeyedSuperNonWritable() {
|
||||||
|
var x = 'xyz';
|
||||||
|
function Base() {}
|
||||||
|
Object.defineProperty(Base.prototype, x, { value : 27, writable: false });
|
||||||
|
function Derived() {}
|
||||||
|
|
||||||
|
Derived.prototype = { __proto__: Base.prototype, constructor: Derived };
|
||||||
|
|
||||||
|
Derived.prototype.mSloppy = function() {
|
||||||
|
assertEquals(27, super[x]);
|
||||||
|
assertEquals(27, this[x]);
|
||||||
|
super[x] = 10;
|
||||||
|
assertEquals(27, super[x]);
|
||||||
|
assertEquals(27, this[x]);
|
||||||
|
}.toMethod(Derived.prototype);
|
||||||
|
Derived.prototype.mStrict = function() {
|
||||||
|
'use strict';
|
||||||
|
assertEquals(27, super[x]);
|
||||||
|
assertEquals(27, this[x]);
|
||||||
|
var ex = null;
|
||||||
|
try { super[x] = 10; } catch(e) { ex = e; }
|
||||||
|
assertTrue(ex instanceof TypeError);
|
||||||
|
assertEquals(27, super[x]);
|
||||||
|
assertEquals(27, this[x]);
|
||||||
|
}.toMethod(Derived.prototype);
|
||||||
|
new Derived().mSloppy();
|
||||||
|
new Derived().mStrict();
|
||||||
|
}());
|
||||||
|
|
||||||
|
|
||||||
|
(function TestSetterKeyedNumericSuperNonWritable() {
|
||||||
|
var x = 42;
|
||||||
|
function Base() {}
|
||||||
|
Object.defineProperty(Base.prototype, x, { value : 27, writable: false });
|
||||||
|
function Derived() {}
|
||||||
|
|
||||||
|
Derived.prototype = { __proto__: Base.prototype, constructor: Derived };
|
||||||
|
|
||||||
|
Derived.prototype.mSloppy = function() {
|
||||||
|
assertEquals(27, super[x]);
|
||||||
|
assertEquals(27, this[x]);
|
||||||
|
super[x] = 10;
|
||||||
|
assertEquals(27, super[x]);
|
||||||
|
assertEquals(27, this[x]);
|
||||||
|
}.toMethod(Derived.prototype);
|
||||||
|
Derived.prototype.mStrict = function() {
|
||||||
|
'use strict';
|
||||||
|
assertEquals(27, super[x]);
|
||||||
|
assertEquals(27, this[x]);
|
||||||
|
var ex = null;
|
||||||
|
try { super[x] = 10; } catch(e) { ex = e; }
|
||||||
|
assertTrue(ex instanceof TypeError);
|
||||||
|
assertEquals(27, super[x]);
|
||||||
|
assertEquals(27, this[x]);
|
||||||
|
}.toMethod(Derived.prototype);
|
||||||
|
new Derived().mSloppy();
|
||||||
|
new Derived().mStrict();
|
||||||
|
}());
|
||||||
|
|
||||||
|
|
||||||
(function TestSuperCall() {
|
(function TestSuperCall() {
|
||||||
function Subclass(base, constructor) {
|
function Subclass(base, constructor) {
|
||||||
var homeObject = {
|
var homeObject = {
|
||||||
@ -1284,10 +1829,3 @@
|
|||||||
// Filed https://bugs.ecmascript.org/show_bug.cgi?id=3282
|
// Filed https://bugs.ecmascript.org/show_bug.cgi?id=3282
|
||||||
assertThrows(function() { new T(); }, TypeError);
|
assertThrows(function() { new T(); }, TypeError);
|
||||||
}());
|
}());
|
||||||
|
|
||||||
|
|
||||||
(function TestUnsupportedCases() {
|
|
||||||
function f(x) { super[x] = 5; }
|
|
||||||
var o = {};
|
|
||||||
assertThrows(function(){f.toMethod(o)(15);}, ReferenceError);
|
|
||||||
}());
|
|
||||||
|
Loading…
Reference in New Issue
Block a user