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_;
};
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)
}
}
-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());
}
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;
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(
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(
PreParserExpression extends,
PreParserExpression constructor,
PreParserExpressionList properties,
- int position) {
+ int start_position, int end_position) {
return PreParserExpression::Default();
}
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();
}
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());
}
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;
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
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) \
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);
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());
+})();