Commit c8b1c3e7 authored by arv@chromium.org's avatar arv@chromium.org

Classes: Add support for toString

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

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24472 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent f99fd386
......@@ -2536,22 +2536,26 @@ class ClassLiteral FINAL : public Expression {
Expression* extends() const { return extends_; }
Expression* constructor() const { return constructor_; }
ZoneList<Property*>* properties() const { return properties_; }
int start_position() const { return position(); }
int end_position() const { return end_position_; }
protected:
ClassLiteral(Zone* zone, const AstRawString* name, Expression* extends,
Expression* constructor, ZoneList<Property*>* properties,
int position, IdGen* id_gen)
: Expression(zone, position, id_gen),
int start_position, int end_position, IdGen* id_gen)
: Expression(zone, start_position, id_gen),
raw_name_(name),
extends_(extends),
constructor_(constructor),
properties_(properties) {}
properties_(properties),
end_position_(end_position) {}
private:
const AstRawString* raw_name_;
Expression* extends_;
Expression* constructor_;
ZoneList<Property*>* properties_;
int end_position_;
};
......@@ -3550,9 +3554,10 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
ClassLiteral* NewClassLiteral(const AstRawString* name, Expression* extends,
Expression* constructor,
ZoneList<ObjectLiteral::Property*>* properties,
int position) {
ClassLiteral* lit = new (zone_) ClassLiteral(
zone_, name, extends, constructor, properties, position, id_gen_);
int start_position, int end_position) {
ClassLiteral* lit =
new (zone_) ClassLiteral(zone_, name, extends, constructor, properties,
start_position, end_position, id_gen_);
VISIT_AND_RETURN(ClassLiteral, lit)
}
......
......@@ -1541,30 +1541,34 @@ void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
}
void FullCodeGenerator::VisitClassLiteral(ClassLiteral* expr) {
void FullCodeGenerator::VisitClassLiteral(ClassLiteral* lit) {
Comment cmnt(masm_, "[ ClassLiteral");
if (expr->raw_name() != NULL) {
__ Push(expr->name());
if (lit->raw_name() != NULL) {
__ Push(lit->name());
} else {
__ Push(isolate()->factory()->undefined_value());
}
if (expr->extends() != NULL) {
VisitForStackValue(expr->extends());
if (lit->extends() != NULL) {
VisitForStackValue(lit->extends());
} else {
__ Push(isolate()->factory()->the_hole_value());
}
if (expr->constructor() != NULL) {
VisitForStackValue(expr->constructor());
if (lit->constructor() != NULL) {
VisitForStackValue(lit->constructor());
} else {
__ Push(isolate()->factory()->undefined_value());
}
__ Push(script());
__ Push(Smi::FromInt(lit->start_position()));
__ Push(Smi::FromInt(lit->end_position()));
// TODO(arv): Process methods
__ CallRuntime(Runtime::kDefineClass, 3);
__ CallRuntime(Runtime::kDefineClass, 6);
context()->Plug(result_register());
}
......
......@@ -340,7 +340,10 @@ namespace internal {
V(intl_initialized_marker_symbol) \
V(intl_impl_object_symbol) \
V(promise_debug_marker_symbol) \
V(promise_has_handler_symbol)
V(promise_has_handler_symbol) \
V(class_script_symbol) \
V(class_start_position_symbol) \
V(class_end_position_symbol)
// Forward declarations.
class HeapStats;
......
......@@ -648,9 +648,10 @@ Expression* ParserTraits::SuperReference(
Expression* ParserTraits::ClassExpression(
const AstRawString* name, Expression* extends, Expression* constructor,
ZoneList<ObjectLiteral::Property*>* properties, int pos,
AstNodeFactory<AstConstructionVisitor>* factory) {
return factory->NewClassLiteral(name, extends, constructor, properties, pos);
ZoneList<ObjectLiteral::Property*>* properties, int start_position,
int end_position, AstNodeFactory<AstConstructionVisitor>* factory) {
return factory->NewClassLiteral(name, extends, constructor, properties,
start_position, end_position);
}
Literal* ParserTraits::ExpressionFromLiteral(
......
......@@ -558,7 +558,7 @@ class ParserTraits {
Expression* ClassExpression(const AstRawString* name, Expression* extends,
Expression* constructor,
ZoneList<ObjectLiteral::Property*>* properties,
int pos,
int start_position, int end_position,
AstNodeFactory<AstConstructionVisitor>* factory);
Literal* ExpressionFromLiteral(
......
......@@ -1102,7 +1102,7 @@ class PreParserFactory {
PreParserExpression extends,
PreParserExpression constructor,
PreParserExpressionList properties,
int position) {
int start_position, int end_position) {
return PreParserExpression::Default();
}
......@@ -1334,12 +1334,10 @@ class PreParserTraits {
return PreParserExpression::Super();
}
static PreParserExpression ClassExpression(PreParserIdentifier name,
PreParserExpression extends,
PreParserExpression constructor,
PreParserExpressionList properties,
int position,
PreParserFactory* factory) {
static PreParserExpression ClassExpression(
PreParserIdentifier name, PreParserExpression extends,
PreParserExpression constructor, PreParserExpressionList properties,
int start_position, int end_position, PreParserFactory* factory) {
return PreParserExpression::Default();
}
......@@ -2805,10 +2803,12 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseClassLiteral(
fni_->Leave();
}
}
int end_pos = peek_position();
Expect(Token::RBRACE, CHECK_OK);
return this->ClassExpression(name, extends, constructor, properties, pos,
factory());
end_pos + 1, factory());
}
......
......@@ -155,10 +155,13 @@ RUNTIME_FUNCTION(Runtime_StoreToSuper_Sloppy) {
RUNTIME_FUNCTION(Runtime_DefineClass) {
HandleScope scope(isolate);
DCHECK(args.length() == 3);
DCHECK(args.length() == 6);
CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, super_class, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, constructor, 2);
CONVERT_ARG_HANDLE_CHECKED(Script, script, 3);
CONVERT_SMI_ARG_CHECKED(start_position, 4);
CONVERT_SMI_ARG_CHECKED(end_position, 5);
Handle<Object> prototype_parent;
Handle<Object> constructor_parent;
......@@ -228,7 +231,58 @@ RUNTIME_FUNCTION(Runtime_DefineClass) {
JSObject::AddProperty(prototype, isolate->factory()->constructor_string(),
ctor, DONT_ENUM);
// Install private properties that are used to construct the FunctionToString.
RETURN_FAILURE_ON_EXCEPTION(
isolate,
Object::SetProperty(ctor, isolate->factory()->class_script_symbol(),
script, STRICT));
RETURN_FAILURE_ON_EXCEPTION(
isolate, Object::SetProperty(
ctor, isolate->factory()->class_start_position_symbol(),
handle(Smi::FromInt(start_position), isolate), STRICT));
RETURN_FAILURE_ON_EXCEPTION(
isolate,
Object::SetProperty(ctor, isolate->factory()->class_end_position_symbol(),
handle(Smi::FromInt(end_position), isolate), STRICT));
return *ctor;
}
RUNTIME_FUNCTION(Runtime_ClassGetSourceCode) {
HandleScope shs(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
Handle<Object> script;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, script,
Object::GetProperty(fun, isolate->factory()->class_script_symbol()));
if (!script->IsScript()) {
return isolate->heap()->undefined_value();
}
Handle<Symbol> start_position_symbol(
isolate->heap()->class_start_position_symbol());
Handle<Object> start_position;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, start_position, Object::GetProperty(fun, start_position_symbol));
Handle<Symbol> end_position_symbol(
isolate->heap()->class_end_position_symbol());
Handle<Object> end_position;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, end_position, Object::GetProperty(fun, end_position_symbol));
if (!start_position->IsSmi() || !end_position->IsSmi() ||
!Handle<Script>::cast(script)->HasValidSource()) {
return isolate->ThrowIllegalOperation();
}
Handle<String> source(String::cast(Handle<Script>::cast(script)->source()));
return *isolate->factory()->NewSubString(
source, Handle<Smi>::cast(start_position)->value(),
Handle<Smi>::cast(end_position)->value());
}
}
} // namespace v8::internal
......@@ -193,7 +193,8 @@ namespace internal {
F(LoadKeyedFromSuper, 3, 1) \
F(StoreToSuper_Strict, 4, 1) \
F(StoreToSuper_Sloppy, 4, 1) \
F(DefineClass, 3, 1)
F(DefineClass, 6, 1) \
F(ClassGetSourceCode, 1, 1)
#define RUNTIME_FUNCTION_LIST_ALWAYS_2(F) \
......
......@@ -1739,6 +1739,11 @@ function FunctionSourceString(func) {
throw new $TypeError('Function.prototype.toString is not generic');
}
var classSource = %ClassGetSourceCode(func);
if (IS_STRING(classSource)) {
return classSource;
}
var source = %FunctionGetSourceCode(func);
if (!IS_STRING(source) || %FunctionIsBuiltin(func)) {
var name = %FunctionGetName(func);
......
......@@ -165,3 +165,15 @@
new C();
})();
*/
(function TestToString() {
class C {}
assertEquals('class C {}', C.toString());
class D { constructor() { 42; } }
assertEquals('class D { constructor() { 42; } }', D.toString());
class E { x() { 42; } }
assertEquals('class E { x() { 42; } }', E.toString());
})();
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