From c8b1c3e78483090a30a83aa84370fa616aa4eb6b Mon Sep 17 00:00:00 2001 From: "arv@chromium.org" Date: Wed, 8 Oct 2014 14:48:48 +0000 Subject: [PATCH] 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 --- src/ast.h | 17 ++++++++----- src/full-codegen.cc | 20 +++++++++------ src/heap/heap.h | 5 +++- src/parser.cc | 7 +++--- src/parser.h | 2 +- src/preparser.h | 16 ++++++------ src/runtime/runtime-classes.cc | 56 ++++++++++++++++++++++++++++++++++++++++- src/runtime/runtime.h | 3 ++- src/v8natives.js | 5 ++++ test/mjsunit/harmony/classes.js | 12 +++++++++ 10 files changed, 114 insertions(+), 29 deletions(-) diff --git a/src/ast.h b/src/ast.h index c75938e..506afa2 100644 --- a/src/ast.h +++ b/src/ast.h @@ -2536,22 +2536,26 @@ class ClassLiteral FINAL : public Expression { Expression* extends() const { return extends_; } Expression* constructor() const { return constructor_; } ZoneList* 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* 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* properties_; + int end_position_; }; @@ -3550,9 +3554,10 @@ class AstNodeFactory FINAL BASE_EMBEDDED { ClassLiteral* NewClassLiteral(const AstRawString* name, Expression* extends, Expression* constructor, ZoneList* 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) } diff --git a/src/full-codegen.cc b/src/full-codegen.cc index 8177a35..a5814c5 100644 --- a/src/full-codegen.cc +++ b/src/full-codegen.cc @@ -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()); } diff --git a/src/heap/heap.h b/src/heap/heap.h index f26fd77..110237a 100644 --- a/src/heap/heap.h +++ b/src/heap/heap.h @@ -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; diff --git a/src/parser.cc b/src/parser.cc index 04efd1e..24d1f8a 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -648,9 +648,10 @@ Expression* ParserTraits::SuperReference( Expression* ParserTraits::ClassExpression( const AstRawString* name, Expression* extends, Expression* constructor, - ZoneList* properties, int pos, - AstNodeFactory* factory) { - return factory->NewClassLiteral(name, extends, constructor, properties, pos); + ZoneList* properties, int start_position, + int end_position, AstNodeFactory* factory) { + return factory->NewClassLiteral(name, extends, constructor, properties, + start_position, end_position); } Literal* ParserTraits::ExpressionFromLiteral( diff --git a/src/parser.h b/src/parser.h index e461a99..7d77767 100644 --- a/src/parser.h +++ b/src/parser.h @@ -558,7 +558,7 @@ class ParserTraits { Expression* ClassExpression(const AstRawString* name, Expression* extends, Expression* constructor, ZoneList* properties, - int pos, + int start_position, int end_position, AstNodeFactory* factory); Literal* ExpressionFromLiteral( diff --git a/src/preparser.h b/src/preparser.h index 1def94f..ba58c10 100644 --- a/src/preparser.h +++ b/src/preparser.h @@ -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::ExpressionT ParserBase::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()); } diff --git a/src/runtime/runtime-classes.cc b/src/runtime/runtime-classes.cc index b8cfa9b..74f3372 100644 --- a/src/runtime/runtime-classes.cc +++ b/src/runtime/runtime-classes.cc @@ -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 prototype_parent; Handle 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 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 start_position_symbol( + isolate->heap()->class_start_position_symbol()); + Handle start_position; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, start_position, Object::GetProperty(fun, start_position_symbol)); + + Handle end_position_symbol( + isolate->heap()->class_end_position_symbol()); + Handle end_position; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, end_position, Object::GetProperty(fun, end_position_symbol)); + + if (!start_position->IsSmi() || !end_position->IsSmi() || + !Handle