e88a76ac9e7d7b834ccfc818f37bd9e7533dd1b2
[platform/upstream/nodejs.git] / deps / v8 / 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 <stdlib.h>
6 #include <limits>
7
8 #include "src/v8.h"
9
10 #include "src/isolate-inl.h"
11 #include "src/runtime/runtime.h"
12 #include "src/runtime/runtime-utils.h"
13
14
15 namespace v8 {
16 namespace internal {
17
18
19 RUNTIME_FUNCTION(Runtime_ThrowNonMethodError) {
20   HandleScope scope(isolate);
21   DCHECK(args.length() == 0);
22   THROW_NEW_ERROR_RETURN_FAILURE(
23       isolate, NewReferenceError("non_method", HandleVector<Object>(NULL, 0)));
24 }
25
26
27 static Object* ThrowUnsupportedSuper(Isolate* isolate) {
28   THROW_NEW_ERROR_RETURN_FAILURE(
29       isolate,
30       NewReferenceError("unsupported_super", HandleVector<Object>(NULL, 0)));
31 }
32
33
34 RUNTIME_FUNCTION(Runtime_ThrowUnsupportedSuperError) {
35   HandleScope scope(isolate);
36   DCHECK(args.length() == 0);
37   return ThrowUnsupportedSuper(isolate);
38 }
39
40
41 RUNTIME_FUNCTION(Runtime_ThrowConstructorNonCallableError) {
42   HandleScope scope(isolate);
43   DCHECK(args.length() == 0);
44   THROW_NEW_ERROR_RETURN_FAILURE(
45       isolate,
46       NewTypeError("constructor_noncallable", HandleVector<Object>(NULL, 0)));
47 }
48
49
50 RUNTIME_FUNCTION(Runtime_ThrowArrayNotSubclassableError) {
51   HandleScope scope(isolate);
52   DCHECK(args.length() == 0);
53   THROW_NEW_ERROR_RETURN_FAILURE(
54       isolate,
55       NewTypeError("array_not_subclassable", HandleVector<Object>(NULL, 0)));
56 }
57
58
59 RUNTIME_FUNCTION(Runtime_ToMethod) {
60   HandleScope scope(isolate);
61   DCHECK(args.length() == 2);
62   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
63   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
64   Handle<JSFunction> clone = JSFunction::CloneClosure(fun);
65   Handle<Symbol> home_object_symbol(isolate->heap()->home_object_symbol());
66   JSObject::SetOwnPropertyIgnoreAttributes(clone, home_object_symbol,
67                                            home_object, DONT_ENUM).Assert();
68   return *clone;
69 }
70
71
72 RUNTIME_FUNCTION(Runtime_HomeObjectSymbol) {
73   DCHECK(args.length() == 0);
74   return isolate->heap()->home_object_symbol();
75 }
76
77
78 RUNTIME_FUNCTION(Runtime_DefineClass) {
79   HandleScope scope(isolate);
80   DCHECK(args.length() == 6);
81   CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
82   CONVERT_ARG_HANDLE_CHECKED(Object, super_class, 1);
83   CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 2);
84   CONVERT_ARG_HANDLE_CHECKED(Script, script, 3);
85   CONVERT_SMI_ARG_CHECKED(start_position, 4);
86   CONVERT_SMI_ARG_CHECKED(end_position, 5);
87
88   Handle<Object> prototype_parent;
89   Handle<Object> constructor_parent;
90
91   if (super_class->IsTheHole()) {
92     prototype_parent = isolate->initial_object_prototype();
93   } else {
94     if (super_class->IsNull()) {
95       prototype_parent = isolate->factory()->null_value();
96     } else if (super_class->IsSpecFunction()) {
97       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
98           isolate, prototype_parent,
99           Runtime::GetObjectProperty(isolate, super_class,
100                                      isolate->factory()->prototype_string()));
101       if (!prototype_parent->IsNull() && !prototype_parent->IsSpecObject()) {
102         Handle<Object> args[1] = {prototype_parent};
103         THROW_NEW_ERROR_RETURN_FAILURE(
104             isolate, NewTypeError("prototype_parent_not_an_object",
105                                   HandleVector(args, 1)));
106       }
107       constructor_parent = super_class;
108     } else {
109       // TODO(arv): Should be IsConstructor.
110       Handle<Object> args[1] = {super_class};
111       THROW_NEW_ERROR_RETURN_FAILURE(
112           isolate,
113           NewTypeError("extends_value_not_a_function", HandleVector(args, 1)));
114     }
115   }
116
117   Handle<Map> map =
118       isolate->factory()->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
119   map->SetPrototype(prototype_parent);
120   map->set_constructor(*constructor);
121   Handle<JSObject> prototype = isolate->factory()->NewJSObjectFromMap(map);
122
123   Handle<String> name_string = name->IsString()
124                                    ? Handle<String>::cast(name)
125                                    : isolate->factory()->empty_string();
126   constructor->shared()->set_name(*name_string);
127
128   if (!super_class->IsTheHole()) {
129     Handle<Code> stub(isolate->builtins()->JSConstructStubForDerived());
130     constructor->shared()->set_construct_stub(*stub);
131   }
132
133   JSFunction::SetPrototype(constructor, prototype);
134   PropertyAttributes attribs =
135       static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
136   RETURN_FAILURE_ON_EXCEPTION(
137       isolate, JSObject::SetOwnPropertyIgnoreAttributes(
138                    constructor, isolate->factory()->prototype_string(),
139                    prototype, attribs));
140
141   // TODO(arv): Only do this conditionally.
142   Handle<Symbol> home_object_symbol(isolate->heap()->home_object_symbol());
143   RETURN_FAILURE_ON_EXCEPTION(
144       isolate, JSObject::SetOwnPropertyIgnoreAttributes(
145                    constructor, home_object_symbol, prototype, DONT_ENUM));
146
147   if (!constructor_parent.is_null()) {
148     RETURN_FAILURE_ON_EXCEPTION(
149         isolate,
150         JSObject::SetPrototype(constructor, constructor_parent, false));
151   }
152
153   JSObject::AddProperty(prototype, isolate->factory()->constructor_string(),
154                         constructor, DONT_ENUM);
155
156   // Install private properties that are used to construct the FunctionToString.
157   RETURN_FAILURE_ON_EXCEPTION(
158       isolate, Object::SetProperty(constructor,
159                                    isolate->factory()->class_script_symbol(),
160                                    script, STRICT));
161   RETURN_FAILURE_ON_EXCEPTION(
162       isolate,
163       Object::SetProperty(
164           constructor, isolate->factory()->class_start_position_symbol(),
165           handle(Smi::FromInt(start_position), isolate), STRICT));
166   RETURN_FAILURE_ON_EXCEPTION(
167       isolate, Object::SetProperty(
168                    constructor, isolate->factory()->class_end_position_symbol(),
169                    handle(Smi::FromInt(end_position), isolate), STRICT));
170
171   return *constructor;
172 }
173
174
175 RUNTIME_FUNCTION(Runtime_DefineClassMethod) {
176   HandleScope scope(isolate);
177   DCHECK(args.length() == 3);
178   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
179   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
180   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 2);
181
182   uint32_t index;
183   if (name->AsArrayIndex(&index)) {
184     RETURN_FAILURE_ON_EXCEPTION(
185         isolate,
186         JSObject::SetOwnElement(object, index, function, DONT_ENUM, STRICT));
187   } else {
188     RETURN_FAILURE_ON_EXCEPTION(
189         isolate, JSObject::SetOwnPropertyIgnoreAttributes(object, name,
190                                                           function, DONT_ENUM));
191   }
192   return isolate->heap()->undefined_value();
193 }
194
195
196 RUNTIME_FUNCTION(Runtime_ClassGetSourceCode) {
197   HandleScope shs(isolate);
198   DCHECK(args.length() == 1);
199   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
200
201   Handle<Object> script;
202   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
203       isolate, script,
204       Object::GetProperty(fun, isolate->factory()->class_script_symbol()));
205   if (!script->IsScript()) {
206     return isolate->heap()->undefined_value();
207   }
208
209   Handle<Symbol> start_position_symbol(
210       isolate->heap()->class_start_position_symbol());
211   Handle<Object> start_position;
212   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
213       isolate, start_position, Object::GetProperty(fun, start_position_symbol));
214
215   Handle<Symbol> end_position_symbol(
216       isolate->heap()->class_end_position_symbol());
217   Handle<Object> end_position;
218   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
219       isolate, end_position, Object::GetProperty(fun, end_position_symbol));
220
221   if (!start_position->IsSmi() || !end_position->IsSmi() ||
222       !Handle<Script>::cast(script)->HasValidSource()) {
223     return isolate->ThrowIllegalOperation();
224   }
225
226   Handle<String> source(String::cast(Handle<Script>::cast(script)->source()));
227   return *isolate->factory()->NewSubString(
228       source, Handle<Smi>::cast(start_position)->value(),
229       Handle<Smi>::cast(end_position)->value());
230 }
231
232
233 static Object* LoadFromSuper(Isolate* isolate, Handle<Object> receiver,
234                              Handle<JSObject> home_object, Handle<Name> name) {
235   if (home_object->IsAccessCheckNeeded() &&
236       !isolate->MayNamedAccess(home_object, name, v8::ACCESS_GET)) {
237     isolate->ReportFailedAccessCheck(home_object, v8::ACCESS_GET);
238     RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
239   }
240
241   PrototypeIterator iter(isolate, home_object);
242   Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
243   if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
244
245   LookupIterator it(receiver, name, Handle<JSReceiver>::cast(proto));
246   Handle<Object> result;
247   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it));
248   return *result;
249 }
250
251
252 static Object* LoadElementFromSuper(Isolate* isolate, Handle<Object> receiver,
253                                     Handle<JSObject> home_object,
254                                     uint32_t index) {
255   if (home_object->IsAccessCheckNeeded() &&
256       !isolate->MayIndexedAccess(home_object, index, v8::ACCESS_GET)) {
257     isolate->ReportFailedAccessCheck(home_object, v8::ACCESS_GET);
258     RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
259   }
260
261   PrototypeIterator iter(isolate, home_object);
262   Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
263   if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
264
265   Handle<Object> result;
266   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
267       isolate, result,
268       Object::GetElementWithReceiver(isolate, proto, receiver, index));
269   return *result;
270 }
271
272
273 RUNTIME_FUNCTION(Runtime_LoadFromSuper) {
274   HandleScope scope(isolate);
275   DCHECK(args.length() == 3);
276   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
277   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
278   CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
279
280   return LoadFromSuper(isolate, receiver, home_object, name);
281 }
282
283
284 RUNTIME_FUNCTION(Runtime_LoadKeyedFromSuper) {
285   HandleScope scope(isolate);
286   DCHECK(args.length() == 3);
287   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
288   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
289   CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
290
291   uint32_t index;
292   if (key->ToArrayIndex(&index)) {
293     return LoadElementFromSuper(isolate, receiver, home_object, index);
294   }
295
296   Handle<Name> name;
297   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
298                                      Runtime::ToName(isolate, key));
299   if (name->AsArrayIndex(&index)) {
300     return LoadElementFromSuper(isolate, receiver, home_object, index);
301   }
302   return LoadFromSuper(isolate, receiver, home_object, name);
303 }
304
305
306 static Object* StoreToSuper(Isolate* isolate, Handle<JSObject> home_object,
307                             Handle<Object> receiver, Handle<Name> name,
308                             Handle<Object> value, LanguageMode language_mode) {
309   if (home_object->IsAccessCheckNeeded() &&
310       !isolate->MayNamedAccess(home_object, name, v8::ACCESS_SET)) {
311     isolate->ReportFailedAccessCheck(home_object, v8::ACCESS_SET);
312     RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
313   }
314
315   PrototypeIterator iter(isolate, home_object);
316   Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
317   if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
318
319   LookupIterator it(receiver, name, Handle<JSReceiver>::cast(proto));
320   Handle<Object> result;
321   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
322       isolate, result,
323       Object::SetSuperProperty(&it, value, language_mode,
324                                Object::CERTAINLY_NOT_STORE_FROM_KEYED));
325   return *result;
326 }
327
328
329 static Object* StoreElementToSuper(Isolate* isolate,
330                                    Handle<JSObject> home_object,
331                                    Handle<Object> receiver, uint32_t index,
332                                    Handle<Object> value,
333                                    LanguageMode language_mode) {
334   if (home_object->IsAccessCheckNeeded() &&
335       !isolate->MayIndexedAccess(home_object, index, v8::ACCESS_SET)) {
336     isolate->ReportFailedAccessCheck(home_object, v8::ACCESS_SET);
337     RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
338   }
339
340   PrototypeIterator iter(isolate, home_object);
341   Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
342   if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
343
344   Handle<Object> result;
345   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
346       isolate, result,
347       Object::SetElementWithReceiver(isolate, proto, receiver, index, value,
348                                      language_mode));
349   return *result;
350 }
351
352
353 RUNTIME_FUNCTION(Runtime_StoreToSuper_Strict) {
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(Name, name, 2);
359   CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
360
361   return StoreToSuper(isolate, home_object, receiver, name, value, STRICT);
362 }
363
364
365 RUNTIME_FUNCTION(Runtime_StoreToSuper_Sloppy) {
366   HandleScope scope(isolate);
367   DCHECK(args.length() == 4);
368   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
369   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
370   CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
371   CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
372
373   return StoreToSuper(isolate, home_object, receiver, name, value, SLOPPY);
374 }
375
376
377 static Object* StoreKeyedToSuper(Isolate* isolate, Handle<JSObject> home_object,
378                                  Handle<Object> receiver, Handle<Object> key,
379                                  Handle<Object> value,
380                                  LanguageMode language_mode) {
381   uint32_t index;
382
383   if (key->ToArrayIndex(&index)) {
384     return StoreElementToSuper(isolate, home_object, receiver, index, value,
385                                language_mode);
386   }
387   Handle<Name> name;
388   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
389                                      Runtime::ToName(isolate, key));
390   if (name->AsArrayIndex(&index)) {
391     return StoreElementToSuper(isolate, home_object, receiver, index, value,
392                                language_mode);
393   }
394   return StoreToSuper(isolate, home_object, receiver, name, value,
395                       language_mode);
396 }
397
398
399 RUNTIME_FUNCTION(Runtime_StoreKeyedToSuper_Strict) {
400   HandleScope scope(isolate);
401   DCHECK(args.length() == 4);
402   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
403   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
404   CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
405   CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
406
407   return StoreKeyedToSuper(isolate, home_object, receiver, key, value, STRICT);
408 }
409
410
411 RUNTIME_FUNCTION(Runtime_StoreKeyedToSuper_Sloppy) {
412   HandleScope scope(isolate);
413   DCHECK(args.length() == 4);
414   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
415   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
416   CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
417   CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
418
419   return StoreKeyedToSuper(isolate, home_object, receiver, key, value, SLOPPY);
420 }
421
422
423 RUNTIME_FUNCTION(Runtime_HandleStepInForDerivedConstructors) {
424   HandleScope scope(isolate);
425   DCHECK(args.length() == 1);
426   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
427   Debug* debug = isolate->debug();
428   // Handle stepping into constructors if step into is active.
429   if (debug->StepInActive()) {
430     debug->HandleStepIn(function, Handle<Object>::null(), 0, true);
431   }
432   return *isolate->factory()->undefined_value();
433 }
434
435
436 RUNTIME_FUNCTION(RuntimeReference_DefaultConstructorCallSuper) {
437   UNREACHABLE();
438   return nullptr;
439 }
440 }
441 }  // namespace v8::internal