Commit 3a91adae authored by arv@chromium.org's avatar arv@chromium.org

Classes: Add support for arguments in default constructor

This is currently done by generating a default constructor that looks
like this:

  constructor() {
    %DefaultConstructorSuperCall();
  }

The a runtime function implements the logic which is pretty similar to
Runtime_Apply except that it uses the [[Prototype]] of the current
function.

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

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

Cr-Commit-Position: refs/heads/master@{#25268}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25268 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 5044c510
......@@ -302,10 +302,12 @@ FunctionLiteral* Parser::DefaultConstructor(bool call_super, Scope* scope,
body = new (zone()) ZoneList<Statement*>(1, zone());
if (call_super) {
Expression* prop = SuperReference(function_scope, factory(), pos);
ZoneList<Expression*>* args =
new (zone()) ZoneList<Expression*>(0, zone());
Call* call = factory()->NewCall(prop, args, pos);
CallRuntime* call = factory()->NewCallRuntime(
ast_value_factory()->empty_string(),
Runtime::FunctionForId(Runtime::kDefaultConstructorSuperCall), args,
pos);
body->Add(factory()->NewExpressionStatement(call, pos), zone());
}
......
......@@ -448,5 +448,52 @@ RUNTIME_FUNCTION(Runtime_StoreKeyedToSuper_Sloppy) {
return StoreKeyedToSuper(isolate, home_object, receiver, key, value, SLOPPY);
}
RUNTIME_FUNCTION(Runtime_DefaultConstructorSuperCall) {
HandleScope scope(isolate);
DCHECK(args.length() == 0);
// Compute the frame holding the arguments.
JavaScriptFrameIterator it(isolate);
it.AdvanceToArgumentsFrame();
JavaScriptFrame* frame = it.frame();
Handle<JSFunction> function(frame->function(), isolate);
Handle<Object> receiver(frame->receiver(), isolate);
Handle<Object> proto_function;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, proto_function,
Runtime::GetPrototype(isolate, function));
// Get the actual number of provided arguments.
const int argc = frame->ComputeParametersCount();
// Loose upper bound to allow fuzzing. We'll most likely run out of
// stack space before hitting this limit.
static int kMaxArgc = 1000000;
RUNTIME_ASSERT(argc >= 0 && argc <= kMaxArgc);
// If there are too many arguments, allocate argv via malloc.
const int argv_small_size = 10;
Handle<Object> argv_small_buffer[argv_small_size];
SmartArrayPointer<Handle<Object> > argv_large_buffer;
Handle<Object>* argv = argv_small_buffer;
if (argc > argv_small_size) {
argv = new Handle<Object>[argc];
if (argv == NULL) return isolate->StackOverflow();
argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
}
for (int i = 0; i < argc; ++i) {
argv[i] = handle(frame->GetParameter(i), isolate);
}
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
Execution::Call(isolate, proto_function, receiver, argc, argv, false));
return *result;
}
}
} // namespace v8::internal
......@@ -242,10 +242,8 @@ MaybeHandle<Object> Runtime::DefineObjectProperty(Handle<JSObject> js_object,
}
RUNTIME_FUNCTION(Runtime_GetPrototype) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
MaybeHandle<Object> Runtime::GetPrototype(Isolate* isolate,
Handle<Object> obj) {
// We don't expect access checks to be needed on JSProxy objects.
DCHECK(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER);
......@@ -257,15 +255,26 @@ RUNTIME_FUNCTION(Runtime_GetPrototype) {
isolate->ReportFailedAccessCheck(
Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)),
v8::ACCESS_GET);
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
return isolate->heap()->undefined_value();
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
return isolate->factory()->undefined_value();
}
iter.AdvanceIgnoringProxies();
if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
return *PrototypeIterator::GetCurrent(iter);
return PrototypeIterator::GetCurrent(iter);
}
} while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN));
return *PrototypeIterator::GetCurrent(iter);
return PrototypeIterator::GetCurrent(iter);
}
RUNTIME_FUNCTION(Runtime_GetPrototype) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
Runtime::GetPrototype(isolate, obj));
return *result;
}
......
......@@ -199,7 +199,8 @@ namespace internal {
F(StoreToSuper_Strict, 4, 1) \
F(StoreToSuper_Sloppy, 4, 1) \
F(StoreKeyedToSuper_Strict, 4, 1) \
F(StoreKeyedToSuper_Sloppy, 4, 1)
F(StoreKeyedToSuper_Sloppy, 4, 1) \
F(DefaultConstructorSuperCall, 0, 1)
#define RUNTIME_FUNCTION_LIST_ALWAYS_2(F) \
......@@ -828,6 +829,9 @@ class Runtime : public AllStatic {
MUST_USE_RESULT static MaybeHandle<Object> GetObjectProperty(
Isolate* isolate, Handle<Object> object, Handle<Object> key);
MUST_USE_RESULT static MaybeHandle<Object> GetPrototype(
Isolate* isolate, Handle<Object> object);
MUST_USE_RESULT static MaybeHandle<Name> ToName(Isolate* isolate,
Handle<Object> key);
......
......@@ -624,6 +624,55 @@ function assertAccessorDescriptor(object, name) {
})();
(function TestDefaultConstructorArguments() {
var args, self;
class Base {
constructor() {
self = this;
args = arguments;
}
}
class Derived extends Base {}
new Derived;
assertEquals(0, args.length);
new Derived(0, 1, 2);
assertEquals(3, args.length);
assertTrue(self instanceof Derived);
var arr = new Array(1e5);
var obj = {};
Derived.apply(obj, arr);
assertEquals(1e5, args.length);
assertEquals(obj, self);
})();
(function TestDefaultConstructorArguments2() {
var args;
class Base {
constructor(x, y) {
args = arguments;
}
}
class Derived extends Base {}
new Derived;
assertEquals(0, args.length);
new Derived(1);
assertEquals(1, args.length);
assertEquals(1, args[0]);
new Derived(1, 2, 3);
assertEquals(3, args.length);
assertEquals(1, args[0]);
assertEquals(2, args[1]);
assertEquals(3, args[2]);
})();
/* 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