Keyed loads from super with numeric keys.
R=ishell@chromium.org, arv@chromium.org BUG=v8:3330 LOG=N Review URL: https://codereview.chromium.org/638193004 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24522 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
1adc1565b2
commit
c9049c0325
@ -57,25 +57,6 @@ RUNTIME_FUNCTION(Runtime_HomeObjectSymbol) {
|
||||
}
|
||||
|
||||
|
||||
static Object* LoadFromSuper(Isolate* isolate, Handle<Object> receiver,
|
||||
Handle<JSObject> home_object, Handle<Name> name) {
|
||||
if (home_object->IsAccessCheckNeeded() &&
|
||||
!isolate->MayNamedAccess(home_object, name, v8::ACCESS_GET)) {
|
||||
isolate->ReportFailedAccessCheck(home_object, v8::ACCESS_GET);
|
||||
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();
|
||||
|
||||
LookupIterator it(receiver, name, Handle<JSReceiver>::cast(proto));
|
||||
Handle<Object> result;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it));
|
||||
return *result;
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_DefineClass) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(args.length() == 6);
|
||||
@ -209,6 +190,46 @@ RUNTIME_FUNCTION(Runtime_ClassGetSourceCode) {
|
||||
}
|
||||
|
||||
|
||||
static Object* LoadFromSuper(Isolate* isolate, Handle<Object> receiver,
|
||||
Handle<JSObject> home_object, Handle<Name> name) {
|
||||
if (home_object->IsAccessCheckNeeded() &&
|
||||
!isolate->MayNamedAccess(home_object, name, v8::ACCESS_GET)) {
|
||||
isolate->ReportFailedAccessCheck(home_object, v8::ACCESS_GET);
|
||||
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();
|
||||
|
||||
LookupIterator it(receiver, name, Handle<JSReceiver>::cast(proto));
|
||||
Handle<Object> result;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it));
|
||||
return *result;
|
||||
}
|
||||
|
||||
|
||||
static Object* LoadElementFromSuper(Isolate* isolate, Handle<Object> receiver,
|
||||
Handle<JSObject> home_object,
|
||||
uint32_t index) {
|
||||
if (home_object->IsAccessCheckNeeded() &&
|
||||
!isolate->MayIndexedAccess(home_object, index, v8::ACCESS_GET)) {
|
||||
isolate->ReportFailedAccessCheck(home_object, v8::ACCESS_GET);
|
||||
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::GetElementWithReceiver(isolate, proto, receiver, index));
|
||||
return *result;
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_LoadFromSuper) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(args.length() == 3);
|
||||
@ -227,13 +248,16 @@ RUNTIME_FUNCTION(Runtime_LoadKeyedFromSuper) {
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
|
||||
|
||||
uint32_t index;
|
||||
if (key->ToArrayIndex(&index)) {
|
||||
return LoadElementFromSuper(isolate, receiver, home_object, index);
|
||||
}
|
||||
|
||||
Handle<Name> name;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
|
||||
Runtime::ToName(isolate, key));
|
||||
uint32_t index;
|
||||
if (name->AsArrayIndex(&index)) {
|
||||
// TODO(dslomov): Implement.
|
||||
return ThrowUnsupportedSuper(isolate);
|
||||
return LoadElementFromSuper(isolate, receiver, home_object, index);
|
||||
}
|
||||
return LoadFromSuper(isolate, receiver, home_object, name);
|
||||
}
|
||||
|
@ -9703,6 +9703,15 @@ TEST(SuperAccessControl) {
|
||||
CHECK(try_catch.HasCaught());
|
||||
}
|
||||
|
||||
{
|
||||
v8::TryCatch try_catch;
|
||||
CompileRun(
|
||||
"function f() { return super[42]; };"
|
||||
"var m = f.toMethod(prohibited);"
|
||||
"m();");
|
||||
CHECK(try_catch.HasCaught());
|
||||
}
|
||||
|
||||
{
|
||||
v8::TryCatch try_catch;
|
||||
CompileRun(
|
||||
|
@ -72,6 +72,41 @@
|
||||
}());
|
||||
|
||||
|
||||
(function TestSuperNumericKeyedLoads() {
|
||||
var x = 1;
|
||||
var derivedDataProperty = 2;
|
||||
var f = 3;
|
||||
function Base() { }
|
||||
function Derived() {
|
||||
this[derivedDataProperty] = 'xxx';
|
||||
}
|
||||
Derived.prototype = Object.create(Base.prototype);
|
||||
|
||||
function fBase() { return "Base " + this.toString(); }
|
||||
|
||||
Base.prototype[f] = fBase.toMethod(Base.prototype);
|
||||
|
||||
function fDerived() {
|
||||
assertEquals("Base this is Derived", super[f]());
|
||||
var a = super[x];
|
||||
assertEquals(15, a);
|
||||
assertEquals(15, super[x]);
|
||||
assertEquals(27, this[x]);
|
||||
|
||||
return "Derived"
|
||||
}
|
||||
|
||||
Base.prototype[x] = 15;
|
||||
Base.prototype.toString = function() { return "this is Base"; };
|
||||
Derived.prototype.toString = function() { return "this is Derived"; };
|
||||
Derived.prototype[x] = 27;
|
||||
Derived.prototype[f] = fDerived.toMethod(Derived.prototype);
|
||||
|
||||
assertEquals("Base this is Base", new Base()[f]());
|
||||
assertEquals("Derived", new Derived()[f]());
|
||||
}());
|
||||
|
||||
|
||||
(function TestSuperKeywordNonMethod() {
|
||||
function f() {
|
||||
super.unknown();
|
||||
@ -167,17 +202,75 @@
|
||||
return "1";
|
||||
} };
|
||||
|
||||
ex = null;
|
||||
try {
|
||||
super[oReturnsNumericString];
|
||||
} catch(e) { ex = e }
|
||||
assertTrue(ex instanceof ReferenceError);
|
||||
assertEquals(undefined, super[oReturnsNumericString]);
|
||||
assertEquals(undefined, super[1]);
|
||||
}.toMethod(Derived.prototype);
|
||||
derived = new Derived();
|
||||
assertEquals('derived', derived.testGetter());
|
||||
derived = new Derived();
|
||||
assertEquals('derived', derived.testGetterStrict());
|
||||
derived = new Derived();
|
||||
derived.testGetterWithToString();
|
||||
}());
|
||||
|
||||
ex = null;
|
||||
|
||||
(function TestGetterNumericKeyed() {
|
||||
var x = 42;
|
||||
function Base() {}
|
||||
var derived;
|
||||
Base.prototype = {
|
||||
constructor: Base,
|
||||
_x: 'base'
|
||||
};
|
||||
|
||||
Object.defineProperty(Base.prototype, x, { get: function() {
|
||||
assertSame(this, derived);
|
||||
return this._x;
|
||||
}});
|
||||
|
||||
function Derived() {}
|
||||
Derived.__proto__ = Base;
|
||||
Derived.prototype = {
|
||||
__proto__: Base.prototype,
|
||||
constructor: Derived,
|
||||
_x: 'derived'
|
||||
};
|
||||
Derived.prototype.testGetter = function() {
|
||||
return super[x];
|
||||
}.toMethod(Derived.prototype);
|
||||
Derived.prototype.testGetterStrict = function() {
|
||||
'use strict';
|
||||
return super[x];
|
||||
}.toMethod(Derived.prototype);
|
||||
|
||||
Derived.prototype.testGetterWithToString = function() {
|
||||
var toStringCalled;
|
||||
var o = { toString: function() {
|
||||
toStringCalled++;
|
||||
return '42';
|
||||
} };
|
||||
|
||||
toStringCalled = 0;
|
||||
assertEquals('derived', super[o]);
|
||||
assertEquals(1, toStringCalled);
|
||||
|
||||
var eToThrow = new Error();
|
||||
var oThrowsInToString = { toString: function() {
|
||||
throw eToThrow;
|
||||
} };
|
||||
|
||||
var ex = null;
|
||||
try {
|
||||
super[1]; // Indexed properties unsupported yet.
|
||||
} catch (e) { ex = e; }
|
||||
assertTrue(ex instanceof ReferenceError);
|
||||
super[oThrowsInToString];
|
||||
} catch(e) { ex = e }
|
||||
assertEquals(eToThrow, ex);
|
||||
|
||||
var oReturnsNumericString = { toString: function() {
|
||||
return "42";
|
||||
} };
|
||||
|
||||
assertEquals('derived', super[oReturnsNumericString]);
|
||||
assertEquals('derived', super[42]);
|
||||
}.toMethod(Derived.prototype);
|
||||
derived = new Derived();
|
||||
assertEquals('derived', derived.testGetter());
|
||||
@ -1096,9 +1189,7 @@
|
||||
|
||||
|
||||
(function TestUnsupportedCases() {
|
||||
function f1(x) { return super[x]; }
|
||||
function f2(x) { super[x] = 5; }
|
||||
function f(x) { super[x] = 5; }
|
||||
var o = {};
|
||||
assertThrows(function(){f1.toMethod(o)(15);}, ReferenceError);
|
||||
assertThrows(function(){f2.toMethod(o)(15);}, ReferenceError);
|
||||
assertThrows(function(){f.toMethod(o)(15);}, ReferenceError);
|
||||
}());
|
||||
|
Loading…
Reference in New Issue
Block a user