Revision: 24403
Author: [email protected]
Date: Mon Oct 6 08:25:27 2014 UTC
Log: Support for super keyed loads where key is a name.
[email protected], [email protected]
BUG=v8:3330
LOG=N
Review URL: https://codereview.chromium.org/622523004
https://code.google.com/p/v8/source/detail?r=24403
Modified:
/branches/bleeding_edge/src/arm/full-codegen-arm.cc
/branches/bleeding_edge/src/arm64/full-codegen-arm64.cc
/branches/bleeding_edge/src/full-codegen.h
/branches/bleeding_edge/src/ia32/full-codegen-ia32.cc
/branches/bleeding_edge/src/runtime/runtime-classes.cc
/branches/bleeding_edge/src/runtime/runtime.cc
/branches/bleeding_edge/src/runtime/runtime.h
/branches/bleeding_edge/src/x64/full-codegen-x64.cc
/branches/bleeding_edge/test/mjsunit/harmony/super.js
=======================================
--- /branches/bleeding_edge/src/arm/full-codegen-arm.cc Mon Sep 29 13:56:32
2014 UTC
+++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Mon Oct 6 08:25:27
2014 UTC
@@ -2380,6 +2380,14 @@
CallIC(ic, prop->PropertyFeedbackId());
}
}
+
+
+void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
+ // Stack: receiver, home_object, key.
+ SetSourcePosition(prop->position());
+
+ __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+}
void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
@@ -2685,11 +2693,19 @@
PrepareForBailoutForId(expr->LoadId(), TOS_REG);
context()->Plug(r0);
} else {
- VisitForStackValue(expr->obj());
- VisitForAccumulatorValue(expr->key());
- __ Move(LoadDescriptor::NameRegister(), r0);
- __ pop(LoadDescriptor::ReceiverRegister());
- EmitKeyedPropertyLoad(expr);
+ if (!expr->IsSuperAccess()) {
+ VisitForStackValue(expr->obj());
+ VisitForAccumulatorValue(expr->key());
+ __ Move(LoadDescriptor::NameRegister(), r0);
+ __ pop(LoadDescriptor::ReceiverRegister());
+ EmitKeyedPropertyLoad(expr);
+ } else {
+ VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(expr->obj()->AsSuperReference());
+ __ Push(result_register());
+ VisitForStackValue(expr->key());
+ EmitKeyedSuperPropertyLoad(expr);
+ }
context()->Plug(r0);
}
}
@@ -2800,6 +2816,43 @@
EmitCall(expr, CallICState::METHOD);
}
+
+void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
+ Expression* callee = expr->expression();
+ DCHECK(callee->IsProperty());
+ Property* prop = callee->AsProperty();
+ DCHECK(prop->IsSuperAccess());
+
+ SetSourcePosition(prop->position());
+ // Load the function from the receiver.
+ const Register scratch = r1;
+ SuperReference* super_ref = prop->obj()->AsSuperReference();
+ EmitLoadHomeObject(super_ref);
+ __ Push(r0);
+ VisitForAccumulatorValue(super_ref->this_var());
+ __ Push(r0);
+ __ Push(r0);
+ __ ldr(scratch, MemOperand(sp, kPointerSize * 2));
+ __ Push(scratch);
+ VisitForStackValue(prop->key());
+
+ // Stack here:
+ // - home_object
+ // - this (receiver)
+ // - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
+ // - home_object
+ // - key
+ __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+
+ // Replace home_object with target function.
+ __ str(r0, MemOperand(sp, kPointerSize));
+
+ // Stack here:
+ // - target function
+ // - this (receiver)
+ EmitCall(expr, CallICState::METHOD);
+}
+
void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType
call_type) {
// Load the arguments.
@@ -2950,9 +3003,12 @@
} else if (call_type == Call::PROPERTY_CALL) {
Property* property = callee->AsProperty();
bool is_named_call = property->key()->IsPropertyName();
- // super.x() is handled in EmitCallWithLoadIC.
- if (property->IsSuperAccess() && is_named_call) {
- EmitSuperCallWithLoadIC(expr);
+ if (property->IsSuperAccess()) {
+ if (is_named_call) {
+ EmitSuperCallWithLoadIC(expr);
+ } else {
+ EmitKeyedSuperCallWithLoadIC(expr);
+ }
} else {
{
PreservePositionScope scope(masm()->positions_recorder());
=======================================
--- /branches/bleeding_edge/src/arm64/full-codegen-arm64.cc Mon Sep 29
13:56:32 2014 UTC
+++ /branches/bleeding_edge/src/arm64/full-codegen-arm64.cc Mon Oct 6
08:25:27 2014 UTC
@@ -2030,6 +2030,14 @@
CallIC(ic, prop->PropertyFeedbackId());
}
}
+
+
+void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
+ // Stack: receiver, home_object, key.
+ SetSourcePosition(prop->position());
+
+ __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+}
void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
@@ -2350,11 +2358,19 @@
PrepareForBailoutForId(expr->LoadId(), TOS_REG);
context()->Plug(x0);
} else {
- VisitForStackValue(expr->obj());
- VisitForAccumulatorValue(expr->key());
- __ Move(LoadDescriptor::NameRegister(), x0);
- __ Pop(LoadDescriptor::ReceiverRegister());
- EmitKeyedPropertyLoad(expr);
+ if (!expr->IsSuperAccess()) {
+ VisitForStackValue(expr->obj());
+ VisitForAccumulatorValue(expr->key());
+ __ Move(LoadDescriptor::NameRegister(), x0);
+ __ Pop(LoadDescriptor::ReceiverRegister());
+ EmitKeyedPropertyLoad(expr);
+ } else {
+ VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(expr->obj()->AsSuperReference());
+ __ Push(result_register());
+ VisitForStackValue(expr->key());
+ EmitKeyedSuperPropertyLoad(expr);
+ }
context()->Plug(x0);
}
}
@@ -2462,6 +2478,43 @@
EmitCall(expr, CallICState::METHOD);
}
+
+void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
+ Expression* callee = expr->expression();
+ DCHECK(callee->IsProperty());
+ Property* prop = callee->AsProperty();
+ DCHECK(prop->IsSuperAccess());
+
+ SetSourcePosition(prop->position());
+
+ // Load the function from the receiver.
+ const Register scratch = x10;
+ SuperReference* super_ref =
callee->AsProperty()->obj()->AsSuperReference();
+ EmitLoadHomeObject(super_ref);
+ __ Push(x0);
+ VisitForAccumulatorValue(super_ref->this_var());
+ __ Push(x0);
+ __ Peek(scratch, kPointerSize);
+ __ Push(x0, scratch);
+ VisitForStackValue(prop->key());
+
+ // Stack here:
+ // - home_object
+ // - this (receiver)
+ // - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
+ // - home_object
+ // - key
+ __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+
+ // Replace home_object with target function.
+ __ Poke(x0, kPointerSize);
+
+ // Stack here:
+ // - target function
+ // - this (receiver)
+ EmitCall(expr, CallICState::METHOD);
+}
+
void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType
call_type) {
// Load the arguments.
@@ -2616,9 +2669,12 @@
} else if (call_type == Call::PROPERTY_CALL) {
Property* property = callee->AsProperty();
bool is_named_call = property->key()->IsPropertyName();
- // super.x() is handled in EmitCallWithLoadIC.
- if (property->IsSuperAccess() && is_named_call) {
- EmitSuperCallWithLoadIC(expr);
+ if (property->IsSuperAccess()) {
+ if (is_named_call) {
+ EmitSuperCallWithLoadIC(expr);
+ } else {
+ EmitKeyedSuperCallWithLoadIC(expr);
+ }
} else {
{
PreservePositionScope scope(masm()->positions_recorder());
=======================================
--- /branches/bleeding_edge/src/full-codegen.h Mon Sep 29 15:17:03 2014 UTC
+++ /branches/bleeding_edge/src/full-codegen.h Mon Oct 6 08:25:27 2014 UTC
@@ -479,6 +479,7 @@
void EmitCallWithLoadIC(Call* expr);
void EmitSuperCallWithLoadIC(Call* expr);
void EmitKeyedCallWithLoadIC(Call* expr, Expression* key);
+ void EmitKeyedSuperCallWithLoadIC(Call* expr);
// Platform-specific code for inline runtime calls.
InlineFunctionGenerator FindInlineFunctionGenerator(Runtime::FunctionId
id);
@@ -525,6 +526,10 @@
// Expect receiver ('this' value) and home_object on the stack.
void EmitNamedSuperPropertyLoad(Property* expr);
+ // Load a value from super[keyed] property.
+ // Expect receiver ('this' value), home_object and key on the stack.
+ void EmitKeyedSuperPropertyLoad(Property* expr);
+
// Load a value from a keyed property.
// The receiver and the key is left on the stack by the IC.
void EmitKeyedPropertyLoad(Property* expr);
=======================================
--- /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Mon Sep 29
13:56:32 2014 UTC
+++ /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Mon Oct 6
08:25:27 2014 UTC
@@ -2298,6 +2298,14 @@
CallIC(ic, prop->PropertyFeedbackId());
}
}
+
+
+void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
+ // Stack: receiver, home_object, key.
+ SetSourcePosition(prop->position());
+
+ __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+}
void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
@@ -2605,11 +2613,19 @@
PrepareForBailoutForId(expr->LoadId(), TOS_REG);
context()->Plug(eax);
} else {
- VisitForStackValue(expr->obj());
- VisitForAccumulatorValue(expr->key());
- __ pop(LoadDescriptor::ReceiverRegister()); // Object.
- __ Move(LoadDescriptor::NameRegister(), result_register()); // Key.
- EmitKeyedPropertyLoad(expr);
+ if (!expr->IsSuperAccess()) {
+ VisitForStackValue(expr->obj());
+ VisitForAccumulatorValue(expr->key());
+ __ pop(LoadDescriptor::ReceiverRegister()); //
Object.
+ __ Move(LoadDescriptor::NameRegister(), result_register()); // Key.
+ EmitKeyedPropertyLoad(expr);
+ } else {
+ VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(expr->obj()->AsSuperReference());
+ __ push(result_register());
+ VisitForStackValue(expr->key());
+ EmitKeyedSuperPropertyLoad(expr);
+ }
context()->Plug(eax);
}
}
@@ -2711,6 +2727,40 @@
EmitCall(expr, CallICState::METHOD);
}
+
+void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
+ Expression* callee = expr->expression();
+ DCHECK(callee->IsProperty());
+ Property* prop = callee->AsProperty();
+ DCHECK(prop->IsSuperAccess());
+
+ SetSourcePosition(prop->position());
+ // Load the function from the receiver.
+ SuperReference* super_ref =
callee->AsProperty()->obj()->AsSuperReference();
+ EmitLoadHomeObject(super_ref);
+ __ push(eax);
+ VisitForAccumulatorValue(super_ref->this_var());
+ __ push(eax);
+ __ push(eax);
+ __ push(Operand(esp, kPointerSize * 2));
+ VisitForStackValue(prop->key());
+ // Stack here:
+ // - home_object
+ // - this (receiver)
+ // - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
+ // - home_object
+ // - key
+ __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+
+ // Replace home_object with target function.
+ __ mov(Operand(esp, kPointerSize), eax);
+
+ // Stack here:
+ // - target function
+ // - this (receiver)
+ EmitCall(expr, CallICState::METHOD);
+}
+
void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType
call_type) {
// Load the arguments.
@@ -2853,9 +2903,12 @@
} else if (call_type == Call::PROPERTY_CALL) {
Property* property = callee->AsProperty();
bool is_named_call = property->key()->IsPropertyName();
- // super.x() is handled in EmitCallWithLoadIC.
- if (property->IsSuperAccess() && is_named_call) {
- EmitSuperCallWithLoadIC(expr);
+ if (property->IsSuperAccess()) {
+ if (is_named_call) {
+ EmitSuperCallWithLoadIC(expr);
+ } else {
+ EmitKeyedSuperCallWithLoadIC(expr);
+ }
} else {
{
PreservePositionScope scope(masm()->positions_recorder());
=======================================
--- /branches/bleeding_edge/src/runtime/runtime-classes.cc Wed Oct 1
12:11:12 2014 UTC
+++ /branches/bleeding_edge/src/runtime/runtime-classes.cc Mon Oct 6
08:25:27 2014 UTC
@@ -16,6 +16,28 @@
namespace internal {
+RUNTIME_FUNCTION(Runtime_ThrowNonMethodError) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 0);
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewReferenceError("non_method", HandleVector<Object>(NULL,
0)));
+}
+
+
+static Object* ThrowUnsupportedSuper(Isolate* isolate) {
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate,
+ NewReferenceError("unsupported_super", HandleVector<Object>(NULL,
0)));
+}
+
+
+RUNTIME_FUNCTION(Runtime_ThrowUnsupportedSuperError) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 0);
+ return ThrowUnsupportedSuper(isolate);
+}
+
+
RUNTIME_FUNCTION(Runtime_ToMethod) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
@@ -35,13 +57,8 @@
}
-RUNTIME_FUNCTION(Runtime_LoadFromSuper) {
- HandleScope scope(isolate);
- DCHECK(args.length() == 3);
- CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
- CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
- CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
-
+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);
@@ -57,6 +74,35 @@
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
Object::GetProperty(&it));
return *result;
}
+
+
+RUNTIME_FUNCTION(Runtime_LoadFromSuper) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 3);
+ CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
+
+ return LoadFromSuper(isolate, receiver, home_object, name);
+}
+
+
+RUNTIME_FUNCTION(Runtime_LoadKeyedFromSuper) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 3);
+ CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
+
+ Handle<Name> name;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
+ Runtime::ToName(isolate, key));
+ uint32_t index;
+ if (name->AsArrayIndex(&index)) {
+ return ThrowUnsupportedSuper(isolate);
+ }
+ return LoadFromSuper(isolate, receiver, home_object, name);
+}
static Object* StoreToSuper(Isolate* isolate, Handle<JSObject> home_object,
=======================================
--- /branches/bleeding_edge/src/runtime/runtime.cc Wed Oct 1 12:11:12 2014
UTC
+++ /branches/bleeding_edge/src/runtime/runtime.cc Mon Oct 6 08:25:27 2014
UTC
@@ -463,8 +463,7 @@
}
-MUST_USE_RESULT
-static MaybeHandle<Name> ToName(Isolate* isolate, Handle<Object> key) {
+MaybeHandle<Name> Runtime::ToName(Isolate* isolate, Handle<Object> key) {
if (key->IsName()) {
return Handle<Name>::cast(key);
} else {
@@ -1740,23 +1739,6 @@
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewReferenceError("not_defined", HandleVector(&name, 1)));
}
-
-
-RUNTIME_FUNCTION(Runtime_ThrowNonMethodError) {
- HandleScope scope(isolate);
- DCHECK(args.length() == 0);
- THROW_NEW_ERROR_RETURN_FAILURE(
- isolate, NewReferenceError("non_method", HandleVector<Object>(NULL,
0)));
-}
-
-
-RUNTIME_FUNCTION(Runtime_ThrowUnsupportedSuperError) {
- HandleScope scope(isolate);
- DCHECK(args.length() == 0);
- THROW_NEW_ERROR_RETURN_FAILURE(
- isolate,
- NewReferenceError("unsupported_super", HandleVector<Object>(NULL,
0)));
-}
RUNTIME_FUNCTION(Runtime_PromiseRejectEvent) {
=======================================
--- /branches/bleeding_edge/src/runtime/runtime.h Wed Oct 1 11:53:29 2014
UTC
+++ /branches/bleeding_edge/src/runtime/runtime.h Mon Oct 6 08:25:27 2014
UTC
@@ -190,6 +190,7 @@
F(ThrowNonMethodError, 0, 1) \
F(ThrowUnsupportedSuperError, 0, 1) \
F(LoadFromSuper, 3, 1) \
+ F(LoadKeyedFromSuper, 3, 1) \
F(StoreToSuper_Strict, 4, 1) \
F(StoreToSuper_Sloppy, 4, 1)
@@ -852,6 +853,9 @@
MUST_USE_RESULT static MaybeHandle<Object> GetObjectProperty(
Isolate* isolate, Handle<Object> object, Handle<Object> key);
+ MUST_USE_RESULT static MaybeHandle<Name> ToName(Isolate* isolate,
+ Handle<Object> key);
+
static void SetupArrayBuffer(Isolate* isolate,
Handle<JSArrayBuffer> array_buffer,
bool is_external, void* data,
=======================================
--- /branches/bleeding_edge/src/x64/full-codegen-x64.cc Mon Sep 29 13:56:32
2014 UTC
+++ /branches/bleeding_edge/src/x64/full-codegen-x64.cc Mon Oct 6 08:25:27
2014 UTC
@@ -2330,6 +2330,14 @@
CallIC(ic, prop->PropertyFeedbackId());
}
}
+
+
+void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
+ // Stack: receiver, home_object, key.
+ SetSourcePosition(prop->position());
+
+ __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+}
void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
@@ -2599,11 +2607,19 @@
PrepareForBailoutForId(expr->LoadId(), TOS_REG);
context()->Plug(rax);
} else {
- VisitForStackValue(expr->obj());
- VisitForAccumulatorValue(expr->key());
- __ Move(LoadDescriptor::NameRegister(), rax);
- __ Pop(LoadDescriptor::ReceiverRegister());
- EmitKeyedPropertyLoad(expr);
+ if (!expr->IsSuperAccess()) {
+ VisitForStackValue(expr->obj());
+ VisitForAccumulatorValue(expr->key());
+ __ Move(LoadDescriptor::NameRegister(), rax);
+ __ Pop(LoadDescriptor::ReceiverRegister());
+ EmitKeyedPropertyLoad(expr);
+ } else {
+ VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(expr->obj()->AsSuperReference());
+ __ Push(result_register());
+ VisitForStackValue(expr->key());
+ EmitKeyedSuperPropertyLoad(expr);
+ }
context()->Plug(rax);
}
}
@@ -2706,6 +2722,41 @@
EmitCall(expr, CallICState::METHOD);
}
+
+void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
+ Expression* callee = expr->expression();
+ DCHECK(callee->IsProperty());
+ Property* prop = callee->AsProperty();
+ DCHECK(prop->IsSuperAccess());
+
+ SetSourcePosition(prop->position());
+ // Load the function from the receiver.
+ SuperReference* super_ref = prop->obj()->AsSuperReference();
+ EmitLoadHomeObject(super_ref);
+ __ Push(rax);
+ VisitForAccumulatorValue(super_ref->this_var());
+ __ Push(rax);
+ __ Push(rax);
+ __ Push(Operand(rsp, kPointerSize * 2));
+ VisitForStackValue(prop->key());
+
+ // Stack here:
+ // - home_object
+ // - this (receiver)
+ // - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
+ // - home_object
+ // - key
+ __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+
+ // Replace home_object with target function.
+ __ movp(Operand(rsp, kPointerSize), rax);
+
+ // Stack here:
+ // - target function
+ // - this (receiver)
+ EmitCall(expr, CallICState::METHOD);
+}
+
void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType
call_type) {
// Load the arguments.
@@ -2849,9 +2900,12 @@
} else if (call_type == Call::PROPERTY_CALL) {
Property* property = callee->AsProperty();
bool is_named_call = property->key()->IsPropertyName();
- // super.x() is handled in EmitCallWithLoadIC.
- if (property->IsSuperAccess() && is_named_call) {
- EmitSuperCallWithLoadIC(expr);
+ if (property->IsSuperAccess()) {
+ if (is_named_call) {
+ EmitSuperCallWithLoadIC(expr);
+ } else {
+ EmitKeyedSuperCallWithLoadIC(expr);
+ }
} else {
{
PreservePositionScope scope(masm()->positions_recorder());
=======================================
--- /branches/bleeding_edge/test/mjsunit/harmony/super.js Tue Sep 30
18:12:22 2014 UTC
+++ /branches/bleeding_edge/test/mjsunit/harmony/super.js Mon Oct 6
08:25:27 2014 UTC
@@ -37,6 +37,41 @@
}());
+(function TestSuperKeyedLoads() {
+ var x = 'x';
+ var derivedDataProperty = 'derivedDataProperty';
+ var f = 'f';
+ 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();
@@ -79,6 +114,80 @@
}());
+(function TestGetterKeyed() {
+ var x = 'x';
+ function Base() {}
+ var derived;
+ Base.prototype = {
+ constructor: Base,
+ get x() {
+ assertSame(this, derived);
+ return this._x;
+ },
+ _x: 'base'
+ };
+
+ 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 'x';
+ } };
+
+ toStringCalled = 0;
+ assertEquals('derived', super[o]);
+ assertEquals(1, toStringCalled);
+
+ var eToThrow = new Error();
+ var oThrowsInToString = { toString: function() {
+ throw eToThrow;
+ } };
+
+ var ex = null;
+ try {
+ super[oThrowsInToString];
+ } catch(e) { ex = e }
+ assertEquals(eToThrow, ex);
+
+ var oReturnsNumericString = { toString: function() {
+ return "1";
+ } };
+
+ ex = null;
+ try {
+ super[oReturnsNumericString];
+ } catch(e) { ex = e }
+ assertTrue(ex instanceof ReferenceError);
+
+ ex = null;
+ try {
+ super[1]; // Indexed properties unsupported yet.
+ } catch (e) { ex = e; }
+ assertTrue(ex instanceof ReferenceError);
+ }.toMethod(Derived.prototype);
+ derived = new Derived();
+ assertEquals('derived', derived.testGetter());
+ derived = new Derived();
+ assertEquals('derived', derived.testGetterStrict());
+ derived = new Derived();
+ derived.testGetterWithToString();
+}());
+
+
(function TestSetter() {
function Base() {}
Base.prototype = {
@@ -536,6 +645,6 @@
function f1(x) { return super[x]; }
function f2(x) { super[x] = 5; }
var o = {};
- assertThrows(function(){f1.toMethod(o)(x);}, ReferenceError);
- assertThrows(function(){f2.toMethod(o)(x);}, ReferenceError);
+ assertThrows(function(){f1.toMethod(o)(15);}, ReferenceError);
+ assertThrows(function(){f2.toMethod(o)(15);}, ReferenceError);
}());
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.