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.
10 #include "src/isolate-inl.h"
11 #include "src/runtime/runtime.h"
12 #include "src/runtime/runtime-utils.h"
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)));
27 static Object* ThrowUnsupportedSuper(Isolate* isolate) {
28 THROW_NEW_ERROR_RETURN_FAILURE(
30 NewReferenceError("unsupported_super", HandleVector<Object>(NULL, 0)));
34 RUNTIME_FUNCTION(Runtime_ThrowUnsupportedSuperError) {
35 HandleScope scope(isolate);
36 DCHECK(args.length() == 0);
37 return ThrowUnsupportedSuper(isolate);
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();
54 RUNTIME_FUNCTION(Runtime_HomeObjectSymbol) {
55 DCHECK(args.length() == 0);
56 return isolate->heap()->home_object_symbol();
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);
70 Handle<Object> prototype_parent;
71 Handle<Object> constructor_parent;
73 if (super_class->IsTheHole()) {
74 prototype_parent = isolate->initial_object_prototype();
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)));
89 constructor_parent = super_class;
91 // TODO(arv): Should be IsConstructor.
92 Handle<Object> args[1] = {super_class};
93 THROW_NEW_ERROR_RETURN_FAILURE(
95 NewTypeError("extends_value_not_a_function", HandleVector(args, 1)));
100 isolate->factory()->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
101 map->set_prototype(*prototype_parent);
102 Handle<JSObject> prototype = isolate->factory()->NewJSObjectFromMap(map);
104 Handle<String> name_string = name->IsString()
105 ? Handle<String>::cast(name)
106 : isolate->factory()->empty_string();
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(
116 JSObject::SetOwnPropertyIgnoreAttributes(
117 ctor, isolate->factory()->prototype_string(), prototype, attribs));
119 // TODO(arv): This should not use an empty function but a function that
121 Handle<Code> code(isolate->builtins()->builtin(Builtins::kEmptyFunction));
122 ctor = isolate->factory()->NewFunction(name_string, code, prototype, true);
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));
130 if (!constructor_parent.is_null()) {
131 RETURN_FAILURE_ON_EXCEPTION(
132 isolate, JSObject::SetPrototype(ctor, constructor_parent, false));
135 JSObject::AddProperty(prototype, isolate->factory()->constructor_string(),
138 // Install private properties that are used to construct the FunctionToString.
139 RETURN_FAILURE_ON_EXCEPTION(
141 Object::SetProperty(ctor, isolate->factory()->class_script_symbol(),
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(
149 Object::SetProperty(ctor, isolate->factory()->class_end_position_symbol(),
150 handle(Smi::FromInt(end_position), isolate), STRICT));
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);
163 RETURN_FAILURE_ON_EXCEPTION(
164 isolate, JSObject::SetOwnPropertyIgnoreAttributes(
165 function, isolate->factory()->home_object_symbol(), object,
169 if (key->ToArrayIndex(&index)) {
170 RETURN_FAILURE_ON_EXCEPTION(
171 isolate, JSObject::SetOwnElement(object, index, function, STRICT));
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));
181 RETURN_FAILURE_ON_EXCEPTION(
183 JSObject::SetOwnPropertyIgnoreAttributes(object, name, function, NONE));
185 return isolate->heap()->undefined_value();
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);
197 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
198 Runtime::ToName(isolate, key));
199 RETURN_FAILURE_ON_EXCEPTION(
201 JSObject::SetOwnPropertyIgnoreAttributes(
202 getter, isolate->factory()->home_object_symbol(), object, DONT_ENUM));
204 RETURN_FAILURE_ON_EXCEPTION(
206 JSObject::DefineAccessor(object, name, getter,
207 isolate->factory()->null_value(), NONE));
208 return isolate->heap()->undefined_value();
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);
220 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
221 Runtime::ToName(isolate, key));
222 RETURN_FAILURE_ON_EXCEPTION(
224 JSObject::SetOwnPropertyIgnoreAttributes(
225 setter, isolate->factory()->home_object_symbol(), object, DONT_ENUM));
226 RETURN_FAILURE_ON_EXCEPTION(
228 JSObject::DefineAccessor(object, name, isolate->factory()->null_value(),
230 return isolate->heap()->undefined_value();
234 RUNTIME_FUNCTION(Runtime_ClassGetSourceCode) {
235 HandleScope shs(isolate);
236 DCHECK(args.length() == 1);
237 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
239 Handle<Object> script;
240 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
242 Object::GetProperty(fun, isolate->factory()->class_script_symbol()));
243 if (!script->IsScript()) {
244 return isolate->heap()->undefined_value();
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));
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));
259 if (!start_position->IsSmi() || !end_position->IsSmi() ||
260 !Handle<Script>::cast(script)->HasValidSource()) {
261 return isolate->ThrowIllegalOperation();
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());
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);
279 PrototypeIterator iter(isolate, home_object);
280 Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
281 if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
283 LookupIterator it(receiver, name, Handle<JSReceiver>::cast(proto));
284 Handle<Object> result;
285 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it));
290 static Object* LoadElementFromSuper(Isolate* isolate, Handle<Object> receiver,
291 Handle<JSObject> home_object,
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);
299 PrototypeIterator iter(isolate, home_object);
300 Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
301 if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
303 Handle<Object> result;
304 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
306 Object::GetElementWithReceiver(isolate, proto, receiver, index));
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);
318 return LoadFromSuper(isolate, receiver, home_object, name);
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);
330 if (key->ToArrayIndex(&index)) {
331 return LoadElementFromSuper(isolate, receiver, home_object, index);
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);
340 return LoadFromSuper(isolate, receiver, home_object, name);
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);
353 PrototypeIterator iter(isolate, home_object);
354 Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
355 if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
357 LookupIterator it(receiver, name, Handle<JSReceiver>::cast(proto));
358 Handle<Object> result;
359 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
361 Object::SetProperty(&it, value, strict_mode,
362 Object::CERTAINLY_NOT_STORE_FROM_KEYED,
363 Object::SUPER_PROPERTY));
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);
379 PrototypeIterator iter(isolate, home_object);
380 Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
381 if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
383 Handle<Object> result;
384 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
386 Object::SetElementWithReceiver(isolate, proto, receiver, index, value,
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);
400 return StoreToSuper(isolate, home_object, receiver, name, value, STRICT);
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);
412 return StoreToSuper(isolate, home_object, receiver, name, value, SLOPPY);
416 static Object* StoreKeyedToSuper(Isolate* isolate, Handle<JSObject> home_object,
417 Handle<Object> receiver, Handle<Object> key,
418 Handle<Object> value, StrictMode strict_mode) {
421 if (key->ToArrayIndex(&index)) {
422 return StoreElementToSuper(isolate, home_object, receiver, index, value,
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,
432 return StoreToSuper(isolate, home_object, receiver, name, value, strict_mode);
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);
444 return StoreKeyedToSuper(isolate, home_object, receiver, key, value, STRICT);
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);
456 return StoreKeyedToSuper(isolate, home_object, receiver, key, value, SLOPPY);
459 } // namespace v8::internal