Commit 5b3f9ec7 authored by arv@chromium.org's avatar arv@chromium.org

Classes: Add super support in methods and accessors

This is done by installing the [[HomeObject]] on the method and the
accessor functions.

BUG=v8:3330
LOG=Y
R=dslomov@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#24976}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24976 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 65fb2cf1
......@@ -2530,34 +2530,22 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
}
__ push(scratch);
VisitForStackValue(key);
VisitForStackValue(value);
switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT:
case ObjectLiteral::Property::MATERIALIZED_LITERAL:
case ObjectLiteral::Property::COMPUTED:
case ObjectLiteral::Property::PROTOTYPE:
VisitForStackValue(value);
__ mov(scratch, Operand(Smi::FromInt(NONE)));
__ push(scratch);
__ CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4);
__ CallRuntime(Runtime::kDefineClassMethod, 3);
break;
case ObjectLiteral::Property::GETTER:
VisitForStackValue(value);
__ LoadRoot(scratch, Heap::kNullValueRootIndex);
__ push(scratch);
__ mov(scratch, Operand(Smi::FromInt(NONE)));
__ push(scratch);
__ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
__ CallRuntime(Runtime::kDefineClassGetter, 3);
break;
case ObjectLiteral::Property::SETTER:
__ LoadRoot(scratch, Heap::kNullValueRootIndex);
__ push(scratch);
VisitForStackValue(value);
__ mov(scratch, Operand(Smi::FromInt(NONE)));
__ push(scratch);
__ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
__ CallRuntime(Runtime::kDefineClassSetter, 3);
break;
default:
......
......@@ -2202,34 +2202,22 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
}
__ Push(scratch);
VisitForStackValue(key);
VisitForStackValue(value);
switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT:
case ObjectLiteral::Property::MATERIALIZED_LITERAL:
case ObjectLiteral::Property::COMPUTED:
case ObjectLiteral::Property::PROTOTYPE:
VisitForStackValue(value);
__ Mov(scratch, Smi::FromInt(NONE));
__ Push(scratch);
__ CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4);
__ CallRuntime(Runtime::kDefineClassMethod, 3);
break;
case ObjectLiteral::Property::GETTER:
VisitForStackValue(value);
__ LoadRoot(scratch, Heap::kNullValueRootIndex);
__ push(scratch);
__ Mov(scratch, Smi::FromInt(NONE));
__ Push(scratch);
__ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
__ CallRuntime(Runtime::kDefineClassGetter, 3);
break;
case ObjectLiteral::Property::SETTER:
__ LoadRoot(scratch, Heap::kNullValueRootIndex);
__ push(scratch);
VisitForStackValue(value);
__ Mov(scratch, Smi::FromInt(NONE));
__ Push(scratch);
__ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
__ CallRuntime(Runtime::kDefineClassSetter, 3);
break;
default:
......
......@@ -2444,29 +2444,22 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
__ push(Operand(esp, 0)); // prototype
}
VisitForStackValue(key);
VisitForStackValue(value);
switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT:
case ObjectLiteral::Property::MATERIALIZED_LITERAL:
case ObjectLiteral::Property::COMPUTED:
case ObjectLiteral::Property::PROTOTYPE:
VisitForStackValue(value);
__ push(Immediate(Smi::FromInt(NONE)));
__ CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4);
__ CallRuntime(Runtime::kDefineClassMethod, 3);
break;
case ObjectLiteral::Property::GETTER:
VisitForStackValue(value);
__ push(Immediate(isolate()->factory()->null_value()));
__ push(Immediate(Smi::FromInt(NONE)));
__ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
__ CallRuntime(Runtime::kDefineClassGetter, 3);
break;
case ObjectLiteral::Property::SETTER:
__ push(Immediate(isolate()->factory()->null_value()));
VisitForStackValue(value);
__ push(Immediate(Smi::FromInt(NONE)));
__ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
__ CallRuntime(Runtime::kDefineClassSetter, 3);
break;
default:
......
......@@ -153,6 +153,84 @@ RUNTIME_FUNCTION(Runtime_DefineClass) {
}
RUNTIME_FUNCTION(Runtime_DefineClassMethod) {
HandleScope scope(isolate);
DCHECK(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 2);
RETURN_FAILURE_ON_EXCEPTION(
isolate, JSObject::SetOwnPropertyIgnoreAttributes(
function, isolate->factory()->home_object_symbol(), object,
DONT_ENUM));
uint32_t index;
if (key->ToArrayIndex(&index)) {
RETURN_FAILURE_ON_EXCEPTION(
isolate, JSObject::SetOwnElement(object, index, function, STRICT));
}
Handle<Name> name;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
Runtime::ToName(isolate, key));
if (name->AsArrayIndex(&index)) {
RETURN_FAILURE_ON_EXCEPTION(
isolate, JSObject::SetOwnElement(object, index, function, STRICT));
} else {
RETURN_FAILURE_ON_EXCEPTION(
isolate,
JSObject::SetOwnPropertyIgnoreAttributes(object, name, function, NONE));
}
return isolate->heap()->undefined_value();
}
RUNTIME_FUNCTION(Runtime_DefineClassGetter) {
HandleScope scope(isolate);
DCHECK(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, getter, 2);
Handle<Name> name;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
Runtime::ToName(isolate, key));
RETURN_FAILURE_ON_EXCEPTION(
isolate,
JSObject::SetOwnPropertyIgnoreAttributes(
getter, isolate->factory()->home_object_symbol(), object, DONT_ENUM));
RETURN_FAILURE_ON_EXCEPTION(
isolate,
JSObject::DefineAccessor(object, name, getter,
isolate->factory()->null_value(), NONE));
return isolate->heap()->undefined_value();
}
RUNTIME_FUNCTION(Runtime_DefineClassSetter) {
HandleScope scope(isolate);
DCHECK(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, setter, 2);
Handle<Name> name;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
Runtime::ToName(isolate, key));
RETURN_FAILURE_ON_EXCEPTION(
isolate,
JSObject::SetOwnPropertyIgnoreAttributes(
setter, isolate->factory()->home_object_symbol(), object, DONT_ENUM));
RETURN_FAILURE_ON_EXCEPTION(
isolate,
JSObject::DefineAccessor(object, name, isolate->factory()->null_value(),
setter, NONE));
return isolate->heap()->undefined_value();
}
RUNTIME_FUNCTION(Runtime_ClassGetSourceCode) {
HandleScope shs(isolate);
DCHECK(args.length() == 1);
......
......@@ -188,6 +188,9 @@ namespace internal {
F(ToMethod, 2, 1) \
F(HomeObjectSymbol, 0, 1) \
F(DefineClass, 6, 1) \
F(DefineClassMethod, 3, 1) \
F(DefineClassGetter, 3, 1) \
F(DefineClassSetter, 3, 1) \
F(ClassGetSourceCode, 1, 1) \
F(ThrowNonMethodError, 0, 1) \
F(ThrowUnsupportedSuperError, 0, 1) \
......
......@@ -2443,29 +2443,22 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
__ Push(Operand(rsp, 0)); // prototype
}
VisitForStackValue(key);
VisitForStackValue(value);
switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT:
case ObjectLiteral::Property::MATERIALIZED_LITERAL:
case ObjectLiteral::Property::COMPUTED:
case ObjectLiteral::Property::PROTOTYPE:
VisitForStackValue(value);
__ Push(Smi::FromInt(NONE));
__ CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4);
__ CallRuntime(Runtime::kDefineClassMethod, 3);
break;
case ObjectLiteral::Property::GETTER:
VisitForStackValue(value);
__ Push(isolate()->factory()->null_value());
__ Push(Smi::FromInt(NONE));
__ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
__ CallRuntime(Runtime::kDefineClassGetter, 3);
break;
case ObjectLiteral::Property::SETTER:
__ Push(isolate()->factory()->null_value());
VisitForStackValue(value);
__ Push(Smi::FromInt(NONE));
__ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
__ CallRuntime(Runtime::kDefineClassSetter, 3);
break;
default:
......
......@@ -439,6 +439,156 @@ function assertAccessorDescriptor(object, name) {
})();
(function TestSuperInMethods() {
class B {
method() {
return 1;
}
get x() {
return 2;
}
}
class C extends B {
method() {
assertEquals(2, super.x);
return super.method();
}
}
assertEquals(1, new C().method());
})();
(function TestSuperInGetter() {
class B {
method() {
return 1;
}
get x() {
return 2;
}
}
class C extends B {
get y() {
assertEquals(2, super.x);
return super.method();
}
}
assertEquals(1, new C().y);
})();
(function TestSuperInSetter() {
class B {
method() {
return 1;
}
get x() {
return 2;
}
}
class C extends B {
set y(v) {
assertEquals(3, v);
assertEquals(2, super.x);
assertEquals(1, super.method());
}
}
assertEquals(3, new C().y = 3);
})();
(function TestSuperInStaticMethods() {
class B {
static method() {
return 1;
}
static get x() {
return 2;
}
}
class C extends B {
static method() {
assertEquals(2, super.x);
return super.method();
}
}
assertEquals(1, C.method());
})();
(function TestSuperInStaticGetter() {
class B {
static method() {
return 1;
}
static get x() {
return 2;
}
}
class C extends B {
static get x() {
assertEquals(2, super.x);
return super.method();
}
}
assertEquals(1, C.x);
})();
(function TestSuperInStaticSetter() {
class B {
static method() {
return 1;
}
static get x() {
return 2;
}
}
class C extends B {
static set x(v) {
assertEquals(3, v);
assertEquals(2, super.x);
assertEquals(1, super.method());
}
}
assertEquals(3, C.x = 3);
})();
(function TestNumericPropertyNames() {
class B {
1() { return 1; }
get 2() { return 2; }
set 3(_) {}
static 4() { return 4; }
static get 5() { return 5; }
static set 6(_) {}
}
assertMethodDescriptor(B.prototype, '1');
assertGetterDescriptor(B.prototype, '2');
assertSetterDescriptor(B.prototype, '3');
assertMethodDescriptor(B, '4');
assertGetterDescriptor(B, '5');
assertSetterDescriptor(B, '6');
class C extends B {
1() { return super[1](); }
get 2() { return super[2]; }
static 4() { return super[4](); }
static get 5() { return super[5]; }
}
assertEquals(1, new C()[1]());
assertEquals(2, new C()[2]);
assertEquals(4, C[4]());
assertEquals(5, C[5]);
})();
/* TODO(arv): Implement
(function TestNameBindingInConstructor() {
class C {
......
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