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