[builtins] Add support for NewTarget to Execution::New.
[platform/upstream/v8.git] / src / runtime / runtime-classes.cc
1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/runtime/runtime-utils.h"
6
7 #include <stdlib.h>
8 #include <limits>
9
10 #include "src/arguments.h"
11 #include "src/debug/debug.h"
12 #include "src/frames-inl.h"
13 #include "src/isolate-inl.h"
14 #include "src/messages.h"
15 #include "src/runtime/runtime.h"
16
17 namespace v8 {
18 namespace internal {
19
20
21 RUNTIME_FUNCTION(Runtime_ThrowNonMethodError) {
22   HandleScope scope(isolate);
23   DCHECK(args.length() == 0);
24   THROW_NEW_ERROR_RETURN_FAILURE(
25       isolate, NewReferenceError(MessageTemplate::kNonMethod));
26 }
27
28
29 RUNTIME_FUNCTION(Runtime_ThrowUnsupportedSuperError) {
30   HandleScope scope(isolate);
31   DCHECK(args.length() == 0);
32   THROW_NEW_ERROR_RETURN_FAILURE(
33       isolate, NewReferenceError(MessageTemplate::kUnsupportedSuper));
34 }
35
36
37 RUNTIME_FUNCTION(Runtime_ThrowConstructorNonCallableError) {
38   HandleScope scope(isolate);
39   DCHECK(args.length() == 0);
40   THROW_NEW_ERROR_RETURN_FAILURE(
41       isolate, NewTypeError(MessageTemplate::kConstructorNonCallable));
42 }
43
44
45 RUNTIME_FUNCTION(Runtime_ThrowArrayNotSubclassableError) {
46   HandleScope scope(isolate);
47   DCHECK(args.length() == 0);
48   THROW_NEW_ERROR_RETURN_FAILURE(
49       isolate, NewTypeError(MessageTemplate::kArrayNotSubclassable));
50 }
51
52
53 static Object* ThrowStaticPrototypeError(Isolate* isolate) {
54   THROW_NEW_ERROR_RETURN_FAILURE(
55       isolate, NewTypeError(MessageTemplate::kStaticPrototype));
56 }
57
58
59 RUNTIME_FUNCTION(Runtime_ThrowStaticPrototypeError) {
60   HandleScope scope(isolate);
61   DCHECK(args.length() == 0);
62   return ThrowStaticPrototypeError(isolate);
63 }
64
65
66 RUNTIME_FUNCTION(Runtime_ThrowIfStaticPrototype) {
67   HandleScope scope(isolate);
68   DCHECK(args.length() == 1);
69   CONVERT_ARG_HANDLE_CHECKED(Name, name, 0);
70   if (Name::Equals(name, isolate->factory()->prototype_string())) {
71     return ThrowStaticPrototypeError(isolate);
72   }
73   return *name;
74 }
75
76
77 RUNTIME_FUNCTION(Runtime_ToMethod) {
78   HandleScope scope(isolate);
79   DCHECK(args.length() == 2);
80   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
81   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
82   Handle<JSFunction> clone = JSFunction::CloneClosure(fun);
83   Handle<Symbol> home_object_symbol(isolate->factory()->home_object_symbol());
84   JSObject::SetOwnPropertyIgnoreAttributes(clone, home_object_symbol,
85                                            home_object, DONT_ENUM).Assert();
86   return *clone;
87 }
88
89
90 RUNTIME_FUNCTION(Runtime_HomeObjectSymbol) {
91   DCHECK(args.length() == 0);
92   return isolate->heap()->home_object_symbol();
93 }
94
95
96 static MaybeHandle<Object> DefineClass(Isolate* isolate, Handle<Object> name,
97                                        Handle<Object> super_class,
98                                        Handle<JSFunction> constructor,
99                                        int start_position, int end_position) {
100   Handle<Object> prototype_parent;
101   Handle<Object> constructor_parent;
102
103   if (super_class->IsTheHole()) {
104     prototype_parent = isolate->initial_object_prototype();
105   } else {
106     if (super_class->IsNull()) {
107       prototype_parent = isolate->factory()->null_value();
108     } else if (super_class->IsJSFunction()) {  // TODO(bmeurer): IsConstructor.
109       if (Handle<JSFunction>::cast(super_class)->shared()->is_generator()) {
110         THROW_NEW_ERROR(
111             isolate,
112             NewTypeError(MessageTemplate::kExtendsValueGenerator, super_class),
113             Object);
114       }
115       ASSIGN_RETURN_ON_EXCEPTION(
116           isolate, prototype_parent,
117           Runtime::GetObjectProperty(isolate, super_class,
118                                      isolate->factory()->prototype_string(),
119                                      SLOPPY),
120           Object);
121       if (!prototype_parent->IsNull() && !prototype_parent->IsSpecObject()) {
122         THROW_NEW_ERROR(
123             isolate, NewTypeError(MessageTemplate::kPrototypeParentNotAnObject,
124                                   prototype_parent),
125             Object);
126       }
127       constructor_parent = super_class;
128     } else {
129       THROW_NEW_ERROR(
130           isolate,
131           NewTypeError(MessageTemplate::kExtendsValueNotFunction, super_class),
132           Object);
133     }
134   }
135
136   Handle<Map> map =
137       isolate->factory()->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
138   if (constructor->map()->is_strong()) {
139     map->set_is_strong();
140     if (super_class->IsNull()) {
141       // Strong class is not permitted to extend null.
142       THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kStrongExtendNull),
143                       Object);
144     }
145   } else {
146     if (Handle<HeapObject>::cast(super_class)->map()->is_strong()) {
147       // Weak class is not permitted to extend strong class.
148       THROW_NEW_ERROR(isolate,
149                       NewTypeError(MessageTemplate::kStrongWeakExtend, name),
150                       Object);
151     }
152   }
153   Map::SetPrototype(map, prototype_parent);
154   map->SetConstructor(*constructor);
155   Handle<JSObject> prototype = isolate->factory()->NewJSObjectFromMap(map);
156
157   Handle<String> name_string = name->IsString()
158                                    ? Handle<String>::cast(name)
159                                    : isolate->factory()->empty_string();
160   constructor->shared()->set_name(*name_string);
161
162   if (!super_class->IsTheHole()) {
163     Handle<Code> stub(isolate->builtins()->JSConstructStubForDerived());
164     constructor->shared()->set_construct_stub(*stub);
165   }
166
167   JSFunction::SetPrototype(constructor, prototype);
168   PropertyAttributes attribs =
169       static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
170   RETURN_ON_EXCEPTION(isolate,
171                       JSObject::SetOwnPropertyIgnoreAttributes(
172                           constructor, isolate->factory()->prototype_string(),
173                           prototype, attribs),
174                       Object);
175
176   // TODO(arv): Only do this conditionally.
177   Handle<Symbol> home_object_symbol(isolate->heap()->home_object_symbol());
178   RETURN_ON_EXCEPTION(
179       isolate, JSObject::SetOwnPropertyIgnoreAttributes(
180                    constructor, home_object_symbol, prototype, DONT_ENUM),
181       Object);
182
183   if (!constructor_parent.is_null()) {
184     RETURN_ON_EXCEPTION(
185         isolate, JSObject::SetPrototype(constructor, constructor_parent, false),
186         Object);
187   }
188
189   JSObject::AddProperty(prototype, isolate->factory()->constructor_string(),
190                         constructor, DONT_ENUM);
191
192   // Install private properties that are used to construct the FunctionToString.
193   RETURN_ON_EXCEPTION(
194       isolate,
195       Object::SetProperty(
196           constructor, isolate->factory()->class_start_position_symbol(),
197           handle(Smi::FromInt(start_position), isolate), STRICT),
198       Object);
199   RETURN_ON_EXCEPTION(
200       isolate, Object::SetProperty(
201                    constructor, isolate->factory()->class_end_position_symbol(),
202                    handle(Smi::FromInt(end_position), isolate), STRICT),
203       Object);
204
205   return constructor;
206 }
207
208
209 RUNTIME_FUNCTION(Runtime_DefineClass) {
210   HandleScope scope(isolate);
211   DCHECK(args.length() == 5);
212   CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
213   CONVERT_ARG_HANDLE_CHECKED(Object, super_class, 1);
214   CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 2);
215   CONVERT_SMI_ARG_CHECKED(start_position, 3);
216   CONVERT_SMI_ARG_CHECKED(end_position, 4);
217
218   Handle<Object> result;
219   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
220       isolate, result, DefineClass(isolate, name, super_class, constructor,
221                                    start_position, end_position));
222   return *result;
223 }
224
225
226 RUNTIME_FUNCTION(Runtime_DefineClassMethod) {
227   HandleScope scope(isolate);
228   DCHECK(args.length() == 3);
229   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
230   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
231   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 2);
232
233   RETURN_FAILURE_ON_EXCEPTION(isolate,
234                               JSObject::DefinePropertyOrElementIgnoreAttributes(
235                                   object, name, function, DONT_ENUM));
236   return isolate->heap()->undefined_value();
237 }
238
239
240 RUNTIME_FUNCTION(Runtime_FinalizeClassDefinition) {
241   HandleScope scope(isolate);
242   DCHECK(args.length() == 2);
243   CONVERT_ARG_HANDLE_CHECKED(JSObject, constructor, 0);
244   CONVERT_ARG_HANDLE_CHECKED(JSObject, prototype, 1);
245
246   JSObject::MigrateSlowToFast(prototype, 0, "RuntimeToFastProperties");
247   JSObject::MigrateSlowToFast(constructor, 0, "RuntimeToFastProperties");
248
249   if (constructor->map()->is_strong()) {
250     DCHECK(prototype->map()->is_strong());
251     RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::Freeze(prototype));
252     Handle<Object> result;
253     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
254                                        JSObject::Freeze(constructor));
255     return *result;
256   }
257   return *constructor;
258 }
259
260
261 RUNTIME_FUNCTION(Runtime_ClassGetSourceCode) {
262   HandleScope shs(isolate);
263   DCHECK(args.length() == 1);
264   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
265
266   Handle<Symbol> start_position_symbol(
267       isolate->heap()->class_start_position_symbol());
268   Handle<Object> start_position =
269       JSReceiver::GetDataProperty(fun, start_position_symbol);
270   if (!start_position->IsSmi()) return isolate->heap()->undefined_value();
271
272   Handle<Symbol> end_position_symbol(
273       isolate->heap()->class_end_position_symbol());
274   Handle<Object> end_position =
275       JSReceiver::GetDataProperty(fun, end_position_symbol);
276   CHECK(end_position->IsSmi());
277
278   Handle<String> source(
279       String::cast(Script::cast(fun->shared()->script())->source()));
280   return *isolate->factory()->NewSubString(
281       source, Handle<Smi>::cast(start_position)->value(),
282       Handle<Smi>::cast(end_position)->value());
283 }
284
285
286 static MaybeHandle<Object> LoadFromSuper(Isolate* isolate,
287                                          Handle<Object> receiver,
288                                          Handle<JSObject> home_object,
289                                          Handle<Name> name,
290                                          LanguageMode language_mode) {
291   if (home_object->IsAccessCheckNeeded() && !isolate->MayAccess(home_object)) {
292     isolate->ReportFailedAccessCheck(home_object);
293     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
294   }
295
296   PrototypeIterator iter(isolate, home_object);
297   Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
298   if (!proto->IsJSReceiver()) {
299     return Object::ReadAbsentProperty(isolate, proto, name, language_mode);
300   }
301
302   LookupIterator it(receiver, name, Handle<JSReceiver>::cast(proto));
303   Handle<Object> result;
304   ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
305                              Object::GetProperty(&it, language_mode), Object);
306   return result;
307 }
308
309
310 static MaybeHandle<Object> LoadElementFromSuper(Isolate* isolate,
311                                                 Handle<Object> receiver,
312                                                 Handle<JSObject> home_object,
313                                                 uint32_t index,
314                                                 LanguageMode language_mode) {
315   if (home_object->IsAccessCheckNeeded() && !isolate->MayAccess(home_object)) {
316     isolate->ReportFailedAccessCheck(home_object);
317     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
318   }
319
320   PrototypeIterator iter(isolate, home_object);
321   Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
322   if (!proto->IsJSReceiver()) {
323     Handle<Object> name = isolate->factory()->NewNumberFromUint(index);
324     return Object::ReadAbsentProperty(isolate, proto, name, language_mode);
325   }
326
327   LookupIterator it(isolate, receiver, index, Handle<JSReceiver>::cast(proto));
328   Handle<Object> result;
329   ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
330                              Object::GetProperty(&it, language_mode), Object);
331   return result;
332 }
333
334
335 // TODO(conradw): It would be more efficient to have a separate runtime function
336 // for strong mode.
337 RUNTIME_FUNCTION(Runtime_LoadFromSuper) {
338   HandleScope scope(isolate);
339   DCHECK(args.length() == 4);
340   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
341   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
342   CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
343   CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 3);
344
345   Handle<Object> result;
346   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
347       isolate, result,
348       LoadFromSuper(isolate, receiver, home_object, name, language_mode));
349   return *result;
350 }
351
352
353 RUNTIME_FUNCTION(Runtime_LoadKeyedFromSuper) {
354   HandleScope scope(isolate);
355   DCHECK(args.length() == 4);
356   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
357   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
358   CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
359   CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 3);
360
361   uint32_t index = 0;
362   Handle<Object> result;
363
364   if (key->ToArrayIndex(&index)) {
365     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
366         isolate, result, LoadElementFromSuper(isolate, receiver, home_object,
367                                               index, language_mode));
368     return *result;
369   }
370
371   Handle<Name> name;
372   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
373                                      Object::ToName(isolate, key));
374   // TODO(verwaest): Unify using LookupIterator.
375   if (name->AsArrayIndex(&index)) {
376     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
377         isolate, result, LoadElementFromSuper(isolate, receiver, home_object,
378                                               index, language_mode));
379     return *result;
380   }
381   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
382       isolate, result,
383       LoadFromSuper(isolate, receiver, home_object, name, language_mode));
384   return *result;
385 }
386
387
388 static Object* StoreToSuper(Isolate* isolate, Handle<JSObject> home_object,
389                             Handle<Object> receiver, Handle<Name> name,
390                             Handle<Object> value, LanguageMode language_mode) {
391   if (home_object->IsAccessCheckNeeded() && !isolate->MayAccess(home_object)) {
392     isolate->ReportFailedAccessCheck(home_object);
393     RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
394   }
395
396   PrototypeIterator iter(isolate, home_object);
397   Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
398   if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
399
400   LookupIterator it(receiver, name, Handle<JSReceiver>::cast(proto));
401   Handle<Object> result;
402   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
403       isolate, result,
404       Object::SetSuperProperty(&it, value, language_mode,
405                                Object::CERTAINLY_NOT_STORE_FROM_KEYED));
406   return *result;
407 }
408
409
410 static Object* StoreElementToSuper(Isolate* isolate,
411                                    Handle<JSObject> home_object,
412                                    Handle<Object> receiver, uint32_t index,
413                                    Handle<Object> value,
414                                    LanguageMode language_mode) {
415   if (home_object->IsAccessCheckNeeded() && !isolate->MayAccess(home_object)) {
416     isolate->ReportFailedAccessCheck(home_object);
417     RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
418   }
419
420   PrototypeIterator iter(isolate, home_object);
421   Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
422   if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
423
424   LookupIterator it(isolate, receiver, index, Handle<JSReceiver>::cast(proto));
425   Handle<Object> result;
426   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
427       isolate, result,
428       Object::SetSuperProperty(&it, value, language_mode,
429                                Object::MAY_BE_STORE_FROM_KEYED));
430   return *result;
431 }
432
433
434 RUNTIME_FUNCTION(Runtime_StoreToSuper_Strict) {
435   HandleScope scope(isolate);
436   DCHECK(args.length() == 4);
437   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
438   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
439   CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
440   CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
441
442   return StoreToSuper(isolate, home_object, receiver, name, value, STRICT);
443 }
444
445
446 RUNTIME_FUNCTION(Runtime_StoreToSuper_Sloppy) {
447   HandleScope scope(isolate);
448   DCHECK(args.length() == 4);
449   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
450   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
451   CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
452   CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
453
454   return StoreToSuper(isolate, home_object, receiver, name, value, SLOPPY);
455 }
456
457
458 static Object* StoreKeyedToSuper(Isolate* isolate, Handle<JSObject> home_object,
459                                  Handle<Object> receiver, Handle<Object> key,
460                                  Handle<Object> value,
461                                  LanguageMode language_mode) {
462   uint32_t index = 0;
463
464   if (key->ToArrayIndex(&index)) {
465     return StoreElementToSuper(isolate, home_object, receiver, index, value,
466                                language_mode);
467   }
468   Handle<Name> name;
469   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
470                                      Object::ToName(isolate, key));
471   // TODO(verwaest): Unify using LookupIterator.
472   if (name->AsArrayIndex(&index)) {
473     return StoreElementToSuper(isolate, home_object, receiver, index, value,
474                                language_mode);
475   }
476   return StoreToSuper(isolate, home_object, receiver, name, value,
477                       language_mode);
478 }
479
480
481 RUNTIME_FUNCTION(Runtime_StoreKeyedToSuper_Strict) {
482   HandleScope scope(isolate);
483   DCHECK(args.length() == 4);
484   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
485   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
486   CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
487   CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
488
489   return StoreKeyedToSuper(isolate, home_object, receiver, key, value, STRICT);
490 }
491
492
493 RUNTIME_FUNCTION(Runtime_StoreKeyedToSuper_Sloppy) {
494   HandleScope scope(isolate);
495   DCHECK(args.length() == 4);
496   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
497   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
498   CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
499   CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
500
501   return StoreKeyedToSuper(isolate, home_object, receiver, key, value, SLOPPY);
502 }
503
504
505 RUNTIME_FUNCTION(Runtime_HandleStepInForDerivedConstructors) {
506   HandleScope scope(isolate);
507   DCHECK(args.length() == 1);
508   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
509   Debug* debug = isolate->debug();
510   // Handle stepping into constructors if step into is active.
511   if (debug->StepInActive()) debug->HandleStepIn(function, true);
512   return *isolate->factory()->undefined_value();
513 }
514
515
516 RUNTIME_FUNCTION(Runtime_DefaultConstructorCallSuper) {
517   HandleScope scope(isolate);
518   DCHECK(args.length() == 2);
519   CONVERT_ARG_HANDLE_CHECKED(JSFunction, original_constructor, 0);
520   CONVERT_ARG_HANDLE_CHECKED(JSFunction, super_constructor, 1);
521   JavaScriptFrameIterator it(isolate);
522
523   // Determine the actual arguments passed to the function.
524   int argument_count = 0;
525   base::SmartArrayPointer<Handle<Object>> arguments =
526       Runtime::GetCallerArguments(isolate, 0, &argument_count);
527
528   Handle<Object> result;
529   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
530       isolate, result, Execution::New(super_constructor, original_constructor,
531                                       argument_count, arguments.get()));
532
533   return *result;
534 }
535
536 }  // namespace internal
537 }  // namespace v8