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.
5 #include "src/runtime/runtime-utils.h"
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"
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));
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));
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));
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));
53 static Object* ThrowStaticPrototypeError(Isolate* isolate) {
54 THROW_NEW_ERROR_RETURN_FAILURE(
55 isolate, NewTypeError(MessageTemplate::kStaticPrototype));
59 RUNTIME_FUNCTION(Runtime_ThrowStaticPrototypeError) {
60 HandleScope scope(isolate);
61 DCHECK(args.length() == 0);
62 return ThrowStaticPrototypeError(isolate);
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);
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();
90 RUNTIME_FUNCTION(Runtime_HomeObjectSymbol) {
91 DCHECK(args.length() == 0);
92 return isolate->heap()->home_object_symbol();
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;
103 if (super_class->IsTheHole()) {
104 prototype_parent = isolate->initial_object_prototype();
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()) {
112 NewTypeError(MessageTemplate::kExtendsValueGenerator, super_class),
115 ASSIGN_RETURN_ON_EXCEPTION(
116 isolate, prototype_parent,
117 Runtime::GetObjectProperty(isolate, super_class,
118 isolate->factory()->prototype_string(),
121 if (!prototype_parent->IsNull() && !prototype_parent->IsSpecObject()) {
123 isolate, NewTypeError(MessageTemplate::kPrototypeParentNotAnObject,
127 constructor_parent = super_class;
131 NewTypeError(MessageTemplate::kExtendsValueNotFunction, super_class),
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),
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),
153 Map::SetPrototype(map, prototype_parent);
154 map->SetConstructor(*constructor);
155 Handle<JSObject> prototype = isolate->factory()->NewJSObjectFromMap(map);
157 Handle<String> name_string = name->IsString()
158 ? Handle<String>::cast(name)
159 : isolate->factory()->empty_string();
160 constructor->shared()->set_name(*name_string);
162 if (!super_class->IsTheHole()) {
163 Handle<Code> stub(isolate->builtins()->JSConstructStubForDerived());
164 constructor->shared()->set_construct_stub(*stub);
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(),
176 // TODO(arv): Only do this conditionally.
177 Handle<Symbol> home_object_symbol(isolate->heap()->home_object_symbol());
179 isolate, JSObject::SetOwnPropertyIgnoreAttributes(
180 constructor, home_object_symbol, prototype, DONT_ENUM),
183 if (!constructor_parent.is_null()) {
185 isolate, JSObject::SetPrototype(constructor, constructor_parent, false),
189 JSObject::AddProperty(prototype, isolate->factory()->constructor_string(),
190 constructor, DONT_ENUM);
192 // Install private properties that are used to construct the FunctionToString.
196 constructor, isolate->factory()->class_start_position_symbol(),
197 handle(Smi::FromInt(start_position), isolate), STRICT),
200 isolate, Object::SetProperty(
201 constructor, isolate->factory()->class_end_position_symbol(),
202 handle(Smi::FromInt(end_position), isolate), STRICT),
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);
218 Handle<Object> result;
219 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
220 isolate, result, DefineClass(isolate, name, super_class, constructor,
221 start_position, end_position));
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);
233 RETURN_FAILURE_ON_EXCEPTION(isolate,
234 JSObject::DefinePropertyOrElementIgnoreAttributes(
235 object, name, function, DONT_ENUM));
236 return isolate->heap()->undefined_value();
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);
246 JSObject::MigrateSlowToFast(prototype, 0, "RuntimeToFastProperties");
247 JSObject::MigrateSlowToFast(constructor, 0, "RuntimeToFastProperties");
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));
261 RUNTIME_FUNCTION(Runtime_ClassGetSourceCode) {
262 HandleScope shs(isolate);
263 DCHECK(args.length() == 1);
264 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
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();
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());
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());
286 static MaybeHandle<Object> LoadFromSuper(Isolate* isolate,
287 Handle<Object> receiver,
288 Handle<JSObject> home_object,
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);
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);
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);
310 static MaybeHandle<Object> LoadElementFromSuper(Isolate* isolate,
311 Handle<Object> receiver,
312 Handle<JSObject> home_object,
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);
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);
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);
335 // TODO(conradw): It would be more efficient to have a separate runtime function
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);
345 Handle<Object> result;
346 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
348 LoadFromSuper(isolate, receiver, home_object, name, language_mode));
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);
362 Handle<Object> result;
364 if (key->ToArrayIndex(&index)) {
365 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
366 isolate, result, LoadElementFromSuper(isolate, receiver, home_object,
367 index, language_mode));
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));
381 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
383 LoadFromSuper(isolate, receiver, home_object, name, language_mode));
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);
396 PrototypeIterator iter(isolate, home_object);
397 Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
398 if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
400 LookupIterator it(receiver, name, Handle<JSReceiver>::cast(proto));
401 Handle<Object> result;
402 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
404 Object::SetSuperProperty(&it, value, language_mode,
405 Object::CERTAINLY_NOT_STORE_FROM_KEYED));
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);
420 PrototypeIterator iter(isolate, home_object);
421 Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
422 if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
424 LookupIterator it(isolate, receiver, index, Handle<JSReceiver>::cast(proto));
425 Handle<Object> result;
426 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
428 Object::SetSuperProperty(&it, value, language_mode,
429 Object::MAY_BE_STORE_FROM_KEYED));
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);
442 return StoreToSuper(isolate, home_object, receiver, name, value, STRICT);
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);
454 return StoreToSuper(isolate, home_object, receiver, name, value, SLOPPY);
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) {
464 if (key->ToArrayIndex(&index)) {
465 return StoreElementToSuper(isolate, home_object, receiver, index, value,
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,
476 return StoreToSuper(isolate, home_object, receiver, name, value,
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);
489 return StoreKeyedToSuper(isolate, home_object, receiver, key, value, STRICT);
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);
501 return StoreKeyedToSuper(isolate, home_object, receiver, key, value, SLOPPY);
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();
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);
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);
528 Handle<Object> result;
529 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
530 isolate, result, Execution::New(super_constructor, original_constructor,
531 argument_count, arguments.get()));
536 } // namespace internal