Commit c9049c03 authored by dslomov@chromium.org's avatar dslomov@chromium.org

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
parent 1adc1565
......@@ -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;
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();
}());
(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[oReturnsNumericString];
super[oThrowsInToString];
} catch(e) { ex = e }
assertTrue(ex instanceof ReferenceError);
assertEquals(eToThrow, ex);
ex = null;
try {
super[1]; // Indexed properties unsupported yet.
} catch (e) { ex = e; }
assertTrue(ex instanceof ReferenceError);
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);
}());
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