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 { ...@@ -2536,22 +2536,26 @@ class ClassLiteral FINAL : public Expression {
Expression* extends() const { return extends_; } Expression* extends() const { return extends_; }
Expression* constructor() const { return constructor_; } Expression* constructor() const { return constructor_; }
ZoneList<Property*>* properties() const { return properties_; } ZoneList<Property*>* properties() const { return properties_; }
int start_position() const { return position(); }
int end_position() const { return end_position_; }
protected: protected:
ClassLiteral(Zone* zone, const AstRawString* name, Expression* extends, ClassLiteral(Zone* zone, const AstRawString* name, Expression* extends,
Expression* constructor, ZoneList<Property*>* properties, Expression* constructor, ZoneList<Property*>* properties,
int position, IdGen* id_gen) int start_position, int end_position, IdGen* id_gen)
: Expression(zone, position, id_gen), : Expression(zone, start_position, id_gen),
raw_name_(name), raw_name_(name),
extends_(extends), extends_(extends),
constructor_(constructor), constructor_(constructor),
properties_(properties) {} properties_(properties),
end_position_(end_position) {}
private: private:
const AstRawString* raw_name_; const AstRawString* raw_name_;
Expression* extends_; Expression* extends_;
Expression* constructor_; Expression* constructor_;
ZoneList<Property*>* properties_; ZoneList<Property*>* properties_;
int end_position_;
}; };
...@@ -3550,9 +3554,10 @@ class AstNodeFactory FINAL BASE_EMBEDDED { ...@@ -3550,9 +3554,10 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
ClassLiteral* NewClassLiteral(const AstRawString* name, Expression* extends, ClassLiteral* NewClassLiteral(const AstRawString* name, Expression* extends,
Expression* constructor, Expression* constructor,
ZoneList<ObjectLiteral::Property*>* properties, ZoneList<ObjectLiteral::Property*>* properties,
int position) { int start_position, int end_position) {
ClassLiteral* lit = new (zone_) ClassLiteral( ClassLiteral* lit =
zone_, name, extends, constructor, properties, position, id_gen_); new (zone_) ClassLiteral(zone_, name, extends, constructor, properties,
start_position, end_position, id_gen_);
VISIT_AND_RETURN(ClassLiteral, lit) VISIT_AND_RETURN(ClassLiteral, lit)
} }
......
...@@ -1541,30 +1541,34 @@ void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { ...@@ -1541,30 +1541,34 @@ void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
} }
void FullCodeGenerator::VisitClassLiteral(ClassLiteral* expr) { void FullCodeGenerator::VisitClassLiteral(ClassLiteral* lit) {
Comment cmnt(masm_, "[ ClassLiteral"); Comment cmnt(masm_, "[ ClassLiteral");
if (expr->raw_name() != NULL) { if (lit->raw_name() != NULL) {
__ Push(expr->name()); __ Push(lit->name());
} else { } else {
__ Push(isolate()->factory()->undefined_value()); __ Push(isolate()->factory()->undefined_value());
} }
if (expr->extends() != NULL) { if (lit->extends() != NULL) {
VisitForStackValue(expr->extends()); VisitForStackValue(lit->extends());
} else { } else {
__ Push(isolate()->factory()->the_hole_value()); __ Push(isolate()->factory()->the_hole_value());
} }
if (expr->constructor() != NULL) { if (lit->constructor() != NULL) {
VisitForStackValue(expr->constructor()); VisitForStackValue(lit->constructor());
} else { } else {
__ Push(isolate()->factory()->undefined_value()); __ Push(isolate()->factory()->undefined_value());
} }
__ Push(script());
__ Push(Smi::FromInt(lit->start_position()));
__ Push(Smi::FromInt(lit->end_position()));
// TODO(arv): Process methods // TODO(arv): Process methods
__ CallRuntime(Runtime::kDefineClass, 3); __ CallRuntime(Runtime::kDefineClass, 6);
context()->Plug(result_register()); context()->Plug(result_register());
} }
......
...@@ -340,7 +340,10 @@ namespace internal { ...@@ -340,7 +340,10 @@ namespace internal {
V(intl_initialized_marker_symbol) \ V(intl_initialized_marker_symbol) \
V(intl_impl_object_symbol) \ V(intl_impl_object_symbol) \
V(promise_debug_marker_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. // Forward declarations.
class HeapStats; class HeapStats;
......
...@@ -648,9 +648,10 @@ Expression* ParserTraits::SuperReference( ...@@ -648,9 +648,10 @@ Expression* ParserTraits::SuperReference(
Expression* ParserTraits::ClassExpression( Expression* ParserTraits::ClassExpression(
const AstRawString* name, Expression* extends, Expression* constructor, const AstRawString* name, Expression* extends, Expression* constructor,
ZoneList<ObjectLiteral::Property*>* properties, int pos, ZoneList<ObjectLiteral::Property*>* properties, int start_position,
AstNodeFactory<AstConstructionVisitor>* factory) { int end_position, AstNodeFactory<AstConstructionVisitor>* factory) {
return factory->NewClassLiteral(name, extends, constructor, properties, pos); return factory->NewClassLiteral(name, extends, constructor, properties,
start_position, end_position);
} }
Literal* ParserTraits::ExpressionFromLiteral( Literal* ParserTraits::ExpressionFromLiteral(
......
...@@ -558,7 +558,7 @@ class ParserTraits { ...@@ -558,7 +558,7 @@ class ParserTraits {
Expression* ClassExpression(const AstRawString* name, Expression* extends, Expression* ClassExpression(const AstRawString* name, Expression* extends,
Expression* constructor, Expression* constructor,
ZoneList<ObjectLiteral::Property*>* properties, ZoneList<ObjectLiteral::Property*>* properties,
int pos, int start_position, int end_position,
AstNodeFactory<AstConstructionVisitor>* factory); AstNodeFactory<AstConstructionVisitor>* factory);
Literal* ExpressionFromLiteral( Literal* ExpressionFromLiteral(
......
...@@ -1102,7 +1102,7 @@ class PreParserFactory { ...@@ -1102,7 +1102,7 @@ class PreParserFactory {
PreParserExpression extends, PreParserExpression extends,
PreParserExpression constructor, PreParserExpression constructor,
PreParserExpressionList properties, PreParserExpressionList properties,
int position) { int start_position, int end_position) {
return PreParserExpression::Default(); return PreParserExpression::Default();
} }
...@@ -1334,12 +1334,10 @@ class PreParserTraits { ...@@ -1334,12 +1334,10 @@ class PreParserTraits {
return PreParserExpression::Super(); return PreParserExpression::Super();
} }
static PreParserExpression ClassExpression(PreParserIdentifier name, static PreParserExpression ClassExpression(
PreParserExpression extends, PreParserIdentifier name, PreParserExpression extends,
PreParserExpression constructor, PreParserExpression constructor, PreParserExpressionList properties,
PreParserExpressionList properties, int start_position, int end_position, PreParserFactory* factory) {
int position,
PreParserFactory* factory) {
return PreParserExpression::Default(); return PreParserExpression::Default();
} }
...@@ -2805,10 +2803,12 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseClassLiteral( ...@@ -2805,10 +2803,12 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseClassLiteral(
fni_->Leave(); fni_->Leave();
} }
} }
int end_pos = peek_position();
Expect(Token::RBRACE, CHECK_OK); Expect(Token::RBRACE, CHECK_OK);
return this->ClassExpression(name, extends, constructor, properties, pos, return this->ClassExpression(name, extends, constructor, properties, pos,
factory()); end_pos + 1, factory());
} }
......
...@@ -155,10 +155,13 @@ RUNTIME_FUNCTION(Runtime_StoreToSuper_Sloppy) { ...@@ -155,10 +155,13 @@ RUNTIME_FUNCTION(Runtime_StoreToSuper_Sloppy) {
RUNTIME_FUNCTION(Runtime_DefineClass) { RUNTIME_FUNCTION(Runtime_DefineClass) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK(args.length() == 3); DCHECK(args.length() == 6);
CONVERT_ARG_HANDLE_CHECKED(Object, name, 0); CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, super_class, 1); CONVERT_ARG_HANDLE_CHECKED(Object, super_class, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, constructor, 2); 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> prototype_parent;
Handle<Object> constructor_parent; Handle<Object> constructor_parent;
...@@ -228,7 +231,58 @@ RUNTIME_FUNCTION(Runtime_DefineClass) { ...@@ -228,7 +231,58 @@ RUNTIME_FUNCTION(Runtime_DefineClass) {
JSObject::AddProperty(prototype, isolate->factory()->constructor_string(), JSObject::AddProperty(prototype, isolate->factory()->constructor_string(),
ctor, DONT_ENUM); 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; 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 } // namespace v8::internal
...@@ -193,7 +193,8 @@ namespace internal { ...@@ -193,7 +193,8 @@ namespace internal {
F(LoadKeyedFromSuper, 3, 1) \ F(LoadKeyedFromSuper, 3, 1) \
F(StoreToSuper_Strict, 4, 1) \ F(StoreToSuper_Strict, 4, 1) \
F(StoreToSuper_Sloppy, 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) \ #define RUNTIME_FUNCTION_LIST_ALWAYS_2(F) \
......
...@@ -1739,6 +1739,11 @@ function FunctionSourceString(func) { ...@@ -1739,6 +1739,11 @@ function FunctionSourceString(func) {
throw new $TypeError('Function.prototype.toString is not generic'); throw new $TypeError('Function.prototype.toString is not generic');
} }
var classSource = %ClassGetSourceCode(func);
if (IS_STRING(classSource)) {
return classSource;
}
var source = %FunctionGetSourceCode(func); var source = %FunctionGetSourceCode(func);
if (!IS_STRING(source) || %FunctionIsBuiltin(func)) { if (!IS_STRING(source) || %FunctionIsBuiltin(func)) {
var name = %FunctionGetName(func); var name = %FunctionGetName(func);
......
...@@ -165,3 +165,15 @@ ...@@ -165,3 +165,15 @@
new C(); 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