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 "src/accessors.h" 8 #include "src/arguments.h" 9 #include "src/ast/scopeinfo.h" 10 #include "src/ast/scopes.h" 11 #include "src/deoptimizer.h" 12 #include "src/frames-inl.h" 13 #include "src/isolate-inl.h" 14 #include "src/messages.h" 15 16 namespace v8 { 17 namespace internal { 18 19 static Object* ThrowRedeclarationError(Isolate* isolate, Handle<String> name) { 20 HandleScope scope(isolate); 21 THROW_NEW_ERROR_RETURN_FAILURE( 22 isolate, NewTypeError(MessageTemplate::kVarRedeclaration, name)); 23 } 24 25 26 RUNTIME_FUNCTION(Runtime_ThrowConstAssignError) { 27 HandleScope scope(isolate); 28 THROW_NEW_ERROR_RETURN_FAILURE(isolate, 29 NewTypeError(MessageTemplate::kConstAssign)); 30 } 31 32 33 // May throw a RedeclarationError. 34 static Object* DeclareGlobals(Isolate* isolate, Handle<JSGlobalObject> global, 35 Handle<String> name, Handle<Object> value, 36 PropertyAttributes attr, bool is_var, 37 bool is_const, bool is_function) { 38 Handle<ScriptContextTable> script_contexts( 39 global->native_context()->script_context_table()); 40 ScriptContextTable::LookupResult lookup; 41 if (ScriptContextTable::Lookup(script_contexts, name, &lookup) && 42 IsLexicalVariableMode(lookup.mode)) { 43 return ThrowRedeclarationError(isolate, name); 44 } 45 46 // Do the lookup own properties only, see ES5 erratum. 47 LookupIterator it(global, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR); 48 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); 49 if (!maybe.IsJust()) return isolate->heap()->exception(); 50 51 if (it.IsFound()) { 52 PropertyAttributes old_attributes = maybe.FromJust(); 53 // The name was declared before; check for conflicting re-declarations. 54 if (is_const) return ThrowRedeclarationError(isolate, name); 55 56 // Skip var re-declarations. 57 if (is_var) return isolate->heap()->undefined_value(); 58 59 DCHECK(is_function); 60 if ((old_attributes & DONT_DELETE) != 0) { 61 // Only allow reconfiguring globals to functions in user code (no 62 // natives, which are marked as read-only). 63 DCHECK((attr & READ_ONLY) == 0); 64 65 // Check whether we can reconfigure the existing property into a 66 // function. 67 PropertyDetails old_details = it.property_details(); 68 // TODO(verwaest): ACCESSOR_CONSTANT invalidly includes 69 // ExecutableAccessInfo, 70 // which are actually data properties, not accessor properties. 71 if (old_details.IsReadOnly() || old_details.IsDontEnum() || 72 old_details.type() == ACCESSOR_CONSTANT) { 73 return ThrowRedeclarationError(isolate, name); 74 } 75 // If the existing property is not configurable, keep its attributes. Do 76 attr = old_attributes; 77 } 78 } 79 80 // Define or redefine own property. 81 RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes( 82 global, name, value, attr)); 83 84 return isolate->heap()->undefined_value(); 85 } 86 87 88 RUNTIME_FUNCTION(Runtime_DeclareGlobals) { 89 HandleScope scope(isolate); 90 DCHECK_EQ(2, args.length()); 91 Handle<JSGlobalObject> global(isolate->global_object()); 92 Handle<Context> context(isolate->context()); 93 94 CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 0); 95 CONVERT_SMI_ARG_CHECKED(flags, 1); 96 97 // Traverse the name/value pairs and set the properties. 98 int length = pairs->length(); 99 for (int i = 0; i < length; i += 2) { 100 HandleScope scope(isolate); 101 Handle<String> name(String::cast(pairs->get(i))); 102 Handle<Object> initial_value(pairs->get(i + 1), isolate); 103 104 // We have to declare a global const property. To capture we only 105 // assign to it when evaluating the assignment for "const x = 106 // <expr>" the initial value is the hole. 107 bool is_var = initial_value->IsUndefined(); 108 bool is_const = initial_value->IsTheHole(); 109 bool is_function = initial_value->IsSharedFunctionInfo(); 110 DCHECK_EQ(1, 111 BoolToInt(is_var) + BoolToInt(is_const) + BoolToInt(is_function)); 112 113 Handle<Object> value; 114 if (is_function) { 115 // Copy the function and update its context. Use it as value. 116 Handle<SharedFunctionInfo> shared = 117 Handle<SharedFunctionInfo>::cast(initial_value); 118 Handle<JSFunction> function = 119 isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context, 120 TENURED); 121 value = function; 122 } else { 123 value = isolate->factory()->undefined_value(); 124 } 125 126 // Compute the property attributes. According to ECMA-262, 127 // the property must be non-configurable except in eval. 128 bool is_native = DeclareGlobalsNativeFlag::decode(flags); 129 bool is_eval = DeclareGlobalsEvalFlag::decode(flags); 130 int attr = NONE; 131 if (is_const) attr |= READ_ONLY; 132 if (is_function && is_native) attr |= READ_ONLY; 133 if (!is_const && !is_eval) attr |= DONT_DELETE; 134 135 Object* result = DeclareGlobals(isolate, global, name, value, 136 static_cast<PropertyAttributes>(attr), 137 is_var, is_const, is_function); 138 if (isolate->has_pending_exception()) return result; 139 } 140 141 return isolate->heap()->undefined_value(); 142 } 143 144 145 RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) { 146 HandleScope scope(isolate); 147 // args[0] == name 148 // args[1] == language_mode 149 // args[2] == value (optional) 150 151 // Determine if we need to assign to the variable if it already 152 // exists (based on the number of arguments). 153 RUNTIME_ASSERT(args.length() == 3); 154 155 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); 156 CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 1); 157 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); 158 159 Handle<JSGlobalObject> global(isolate->context()->global_object()); 160 Handle<Object> result; 161 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 162 isolate, result, Object::SetProperty(global, name, value, language_mode)); 163 return *result; 164 } 165 166 167 RUNTIME_FUNCTION(Runtime_InitializeConstGlobal) { 168 HandleScope handle_scope(isolate); 169 // All constants are declared with an initial value. The name 170 // of the constant is the first argument and the initial value 171 // is the second. 172 RUNTIME_ASSERT(args.length() == 2); 173 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); 174 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); 175 176 Handle<JSGlobalObject> global = isolate->global_object(); 177 178 // Lookup the property as own on the global object. 179 LookupIterator it(global, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR); 180 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); 181 DCHECK(maybe.IsJust()); 182 PropertyAttributes old_attributes = maybe.FromJust(); 183 184 PropertyAttributes attr = 185 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY); 186 // Set the value if the property is either missing, or the property attributes 187 // allow setting the value without invoking an accessor. 188 if (it.IsFound()) { 189 // Ignore if we can't reconfigure the value. 190 if ((old_attributes & DONT_DELETE) != 0) { 191 if ((old_attributes & READ_ONLY) != 0 || 192 it.state() == LookupIterator::ACCESSOR) { 193 return *value; 194 } 195 attr = static_cast<PropertyAttributes>(old_attributes | READ_ONLY); 196 } 197 } 198 199 RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes( 200 global, name, value, attr)); 201 202 return *value; 203 } 204 205 206 namespace { 207 208 Object* DeclareLookupSlot(Isolate* isolate, Handle<String> name, 209 Handle<Object> initial_value, 210 PropertyAttributes attr) { 211 // Declarations are always made in a function, eval or script context, or 212 // a declaration block scope. 213 // In the case of eval code, the context passed is the context of the caller, 214 // which may be some nested context and not the declaration context. 215 Handle<Context> context_arg(isolate->context(), isolate); 216 Handle<Context> context(context_arg->declaration_context(), isolate); 217 218 // TODO(verwaest): Unify the encoding indicating "var" with DeclareGlobals. 219 bool is_var = *initial_value == NULL; 220 bool is_const = initial_value->IsTheHole(); 221 bool is_function = initial_value->IsJSFunction(); 222 DCHECK_EQ(1, 223 BoolToInt(is_var) + BoolToInt(is_const) + BoolToInt(is_function)); 224 225 int index; 226 PropertyAttributes attributes; 227 BindingFlags binding_flags; 228 229 if ((attr & EVAL_DECLARED) != 0) { 230 // Check for a conflict with a lexically scoped variable 231 context_arg->Lookup(name, LEXICAL_TEST, &index, &attributes, 232 &binding_flags); 233 if (attributes != ABSENT && 234 (binding_flags == MUTABLE_CHECK_INITIALIZED || 235 binding_flags == IMMUTABLE_CHECK_INITIALIZED || 236 binding_flags == IMMUTABLE_CHECK_INITIALIZED_HARMONY)) { 237 return ThrowRedeclarationError(isolate, name); 238 } 239 attr = static_cast<PropertyAttributes>(attr & ~EVAL_DECLARED); 240 } 241 242 Handle<Object> holder = context->Lookup(name, DONT_FOLLOW_CHAINS, &index, 243 &attributes, &binding_flags); 244 if (holder.is_null()) { 245 // In case of JSProxy, an exception might have been thrown. 246 if (isolate->has_pending_exception()) return isolate->heap()->exception(); 247 } 248 249 Handle<JSObject> object; 250 Handle<Object> value = 251 is_function ? initial_value 252 : Handle<Object>::cast(isolate->factory()->undefined_value()); 253 254 // TODO(verwaest): This case should probably not be covered by this function, 255 // but by DeclareGlobals instead. 256 if (attributes != ABSENT && holder->IsJSGlobalObject()) { 257 return DeclareGlobals(isolate, Handle<JSGlobalObject>::cast(holder), name, 258 value, attr, is_var, is_const, is_function); 259 } 260 if (context_arg->extension()->IsJSGlobalObject()) { 261 Handle<JSGlobalObject> global( 262 JSGlobalObject::cast(context_arg->extension()), isolate); 263 return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const, 264 is_function); 265 } else if (context->IsScriptContext()) { 266 DCHECK(context->global_object()->IsJSGlobalObject()); 267 Handle<JSGlobalObject> global( 268 JSGlobalObject::cast(context->global_object()), isolate); 269 return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const, 270 is_function); 271 } 272 273 if (attributes != ABSENT) { 274 // The name was declared before; check for conflicting re-declarations. 275 if (is_const || (attributes & READ_ONLY) != 0) { 276 return ThrowRedeclarationError(isolate, name); 277 } 278 279 // Skip var re-declarations. 280 if (is_var) return isolate->heap()->undefined_value(); 281 282 DCHECK(is_function); 283 if (index != Context::kNotFound) { 284 DCHECK(holder.is_identical_to(context)); 285 context->set(index, *initial_value); 286 return isolate->heap()->undefined_value(); 287 } 288 289 object = Handle<JSObject>::cast(holder); 290 291 } else if (context->has_extension()) { 292 // Sloppy varblock contexts might not have an extension object yet, 293 // in which case their extension is a ScopeInfo. 294 if (context->extension()->IsScopeInfo()) { 295 DCHECK(context->IsBlockContext()); 296 object = isolate->factory()->NewJSObject( 297 isolate->context_extension_function()); 298 Handle<HeapObject> extension = 299 isolate->factory()->NewSloppyBlockWithEvalContextExtension( 300 handle(context->scope_info()), object); 301 context->set_extension(*extension); 302 } else { 303 object = handle(context->extension_object(), isolate); 304 } 305 DCHECK(object->IsJSContextExtensionObject() || object->IsJSGlobalObject()); 306 } else { 307 DCHECK(context->IsFunctionContext()); 308 object = 309 isolate->factory()->NewJSObject(isolate->context_extension_function()); 310 context->set_extension(*object); 311 } 312 313 RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes( 314 object, name, value, attr)); 315 316 return isolate->heap()->undefined_value(); 317 } 318 319 } // namespace 320 321 322 RUNTIME_FUNCTION(Runtime_DeclareLookupSlot) { 323 HandleScope scope(isolate); 324 DCHECK_EQ(3, args.length()); 325 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); 326 CONVERT_ARG_HANDLE_CHECKED(Object, initial_value, 1); 327 CONVERT_ARG_HANDLE_CHECKED(Smi, property_attributes, 2); 328 329 PropertyAttributes attributes = 330 static_cast<PropertyAttributes>(property_attributes->value()); 331 return DeclareLookupSlot(isolate, name, initial_value, attributes); 332 } 333 334 335 RUNTIME_FUNCTION(Runtime_InitializeLegacyConstLookupSlot) { 336 HandleScope scope(isolate); 337 DCHECK(args.length() == 3); 338 339 CONVERT_ARG_HANDLE_CHECKED(Object, value, 0); 340 DCHECK(!value->IsTheHole()); 341 // Initializations are always done in a function or native context. 342 CONVERT_ARG_HANDLE_CHECKED(Context, context_arg, 1); 343 Handle<Context> context(context_arg->declaration_context()); 344 CONVERT_ARG_HANDLE_CHECKED(String, name, 2); 345 346 int index; 347 PropertyAttributes attributes; 348 ContextLookupFlags flags = DONT_FOLLOW_CHAINS; 349 BindingFlags binding_flags; 350 Handle<Object> holder = 351 context->Lookup(name, flags, &index, &attributes, &binding_flags); 352 if (holder.is_null()) { 353 // In case of JSProxy, an exception might have been thrown. 354 if (isolate->has_pending_exception()) return isolate->heap()->exception(); 355 } 356 357 if (index != Context::kNotFound) { 358 DCHECK(holder->IsContext()); 359 // Property was found in a context. Perform the assignment if the constant 360 // was uninitialized. 361 Handle<Context> context = Handle<Context>::cast(holder); 362 DCHECK((attributes & READ_ONLY) != 0); 363 if (context->get(index)->IsTheHole()) context->set(index, *value); 364 return *value; 365 } 366 367 PropertyAttributes attr = 368 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY); 369 370 // Strict mode handling not needed (legacy const is disallowed in strict 371 // mode). 372 373 // The declared const was configurable, and may have been deleted in the 374 // meanwhile. If so, re-introduce the variable in the context extension. 375 if (attributes == ABSENT) { 376 Handle<Context> declaration_context(context_arg->declaration_context()); 377 if (declaration_context->IsScriptContext()) { 378 holder = handle(declaration_context->global_object(), isolate); 379 } else { 380 holder = handle(declaration_context->extension_object(), isolate); 381 DCHECK(!holder.is_null()); 382 } 383 CHECK(holder->IsJSObject()); 384 } else { 385 // For JSContextExtensionObjects, the initializer can be run multiple times 386 // if in a for loop: for (var i = 0; i < 2; i++) { const x = i; }. Only the 387 // first assignment should go through. For JSGlobalObjects, additionally any 388 // code can run in between that modifies the declared property. 389 DCHECK(holder->IsJSGlobalObject() || holder->IsJSContextExtensionObject()); 390 391 LookupIterator it(holder, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR); 392 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); 393 if (!maybe.IsJust()) return isolate->heap()->exception(); 394 PropertyAttributes old_attributes = maybe.FromJust(); 395 396 // Ignore if we can't reconfigure the value. 397 if ((old_attributes & DONT_DELETE) != 0) { 398 if ((old_attributes & READ_ONLY) != 0 || 399 it.state() == LookupIterator::ACCESSOR) { 400 return *value; 401 } 402 attr = static_cast<PropertyAttributes>(old_attributes | READ_ONLY); 403 } 404 } 405 406 RETURN_FAILURE_ON_EXCEPTION( 407 isolate, JSObject::SetOwnPropertyIgnoreAttributes( 408 Handle<JSObject>::cast(holder), name, value, attr)); 409 410 return *value; 411 } 412 413 414 namespace { 415 416 // Find the arguments of the JavaScript function invocation that called 417 // into C++ code. Collect these in a newly allocated array of handles (possibly 418 // prefixed by a number of empty handles). 419 base::SmartArrayPointer<Handle<Object>> GetCallerArguments(Isolate* isolate, 420 int prefix_argc, 421 int* total_argc) { 422 // Find frame containing arguments passed to the caller. 423 JavaScriptFrameIterator it(isolate); 424 JavaScriptFrame* frame = it.frame(); 425 List<JSFunction*> functions(2); 426 frame->GetFunctions(&functions); 427 if (functions.length() > 1) { 428 int inlined_jsframe_index = functions.length() - 1; 429 TranslatedState translated_values(frame); 430 translated_values.Prepare(false, frame->fp()); 431 432 int argument_count = 0; 433 TranslatedFrame* translated_frame = 434 translated_values.GetArgumentsInfoFromJSFrameIndex( 435 inlined_jsframe_index, &argument_count); 436 TranslatedFrame::iterator iter = translated_frame->begin(); 437 438 // Skip the function. 439 iter++; 440 441 // Skip the receiver. 442 iter++; 443 argument_count--; 444 445 *total_argc = prefix_argc + argument_count; 446 base::SmartArrayPointer<Handle<Object>> param_data( 447 NewArray<Handle<Object>>(*total_argc)); 448 bool should_deoptimize = false; 449 for (int i = 0; i < argument_count; i++) { 450 should_deoptimize = should_deoptimize || iter->IsMaterializedObject(); 451 Handle<Object> value = iter->GetValue(); 452 param_data[prefix_argc + i] = value; 453 iter++; 454 } 455 456 if (should_deoptimize) { 457 translated_values.StoreMaterializedValuesAndDeopt(); 458 } 459 460 return param_data; 461 } else { 462 it.AdvanceToArgumentsFrame(); 463 frame = it.frame(); 464 int args_count = frame->ComputeParametersCount(); 465 466 *total_argc = prefix_argc + args_count; 467 base::SmartArrayPointer<Handle<Object>> param_data( 468 NewArray<Handle<Object>>(*total_argc)); 469 for (int i = 0; i < args_count; i++) { 470 Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate); 471 param_data[prefix_argc + i] = val; 472 } 473 return param_data; 474 } 475 } 476 477 478 template <typename T> 479 Handle<JSObject> NewSloppyArguments(Isolate* isolate, Handle<JSFunction> callee, 480 T parameters, int argument_count) { 481 CHECK(!IsSubclassConstructor(callee->shared()->kind())); 482 DCHECK(callee->shared()->has_simple_parameters()); 483 Handle<JSObject> result = 484 isolate->factory()->NewArgumentsObject(callee, argument_count); 485 486 // Allocate the elements if needed. 487 int parameter_count = callee->shared()->internal_formal_parameter_count(); 488 if (argument_count > 0) { 489 if (parameter_count > 0) { 490 int mapped_count = Min(argument_count, parameter_count); 491 Handle<FixedArray> parameter_map = 492 isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED); 493 parameter_map->set_map(isolate->heap()->sloppy_arguments_elements_map()); 494 result->set_map(isolate->native_context()->fast_aliased_arguments_map()); 495 result->set_elements(*parameter_map); 496 497 // Store the context and the arguments array at the beginning of the 498 // parameter map. 499 Handle<Context> context(isolate->context()); 500 Handle<FixedArray> arguments = 501 isolate->factory()->NewFixedArray(argument_count, NOT_TENURED); 502 parameter_map->set(0, *context); 503 parameter_map->set(1, *arguments); 504 505 // Loop over the actual parameters backwards. 506 int index = argument_count - 1; 507 while (index >= mapped_count) { 508 // These go directly in the arguments array and have no 509 // corresponding slot in the parameter map. 510 arguments->set(index, parameters[index]); 511 --index; 512 } 513 514 Handle<ScopeInfo> scope_info(callee->shared()->scope_info()); 515 while (index >= 0) { 516 // Detect duplicate names to the right in the parameter list. 517 Handle<String> name(scope_info->ParameterName(index)); 518 int context_local_count = scope_info->ContextLocalCount(); 519 bool duplicate = false; 520 for (int j = index + 1; j < parameter_count; ++j) { 521 if (scope_info->ParameterName(j) == *name) { 522 duplicate = true; 523 break; 524 } 525 } 526 527 if (duplicate) { 528 // This goes directly in the arguments array with a hole in the 529 // parameter map. 530 arguments->set(index, parameters[index]); 531 parameter_map->set_the_hole(index + 2); 532 } else { 533 // The context index goes in the parameter map with a hole in the 534 // arguments array. 535 int context_index = -1; 536 for (int j = 0; j < context_local_count; ++j) { 537 if (scope_info->ContextLocalName(j) == *name) { 538 context_index = j; 539 break; 540 } 541 } 542 543 DCHECK(context_index >= 0); 544 arguments->set_the_hole(index); 545 parameter_map->set( 546 index + 2, 547 Smi::FromInt(Context::MIN_CONTEXT_SLOTS + context_index)); 548 } 549 550 --index; 551 } 552 } else { 553 // If there is no aliasing, the arguments object elements are not 554 // special in any way. 555 Handle<FixedArray> elements = 556 isolate->factory()->NewFixedArray(argument_count, NOT_TENURED); 557 result->set_elements(*elements); 558 for (int i = 0; i < argument_count; ++i) { 559 elements->set(i, parameters[i]); 560 } 561 } 562 } 563 return result; 564 } 565 566 567 template <typename T> 568 Handle<JSObject> NewStrictArguments(Isolate* isolate, Handle<JSFunction> callee, 569 T parameters, int argument_count) { 570 Handle<JSObject> result = 571 isolate->factory()->NewArgumentsObject(callee, argument_count); 572 573 if (argument_count > 0) { 574 Handle<FixedArray> array = 575 isolate->factory()->NewUninitializedFixedArray(argument_count); 576 DisallowHeapAllocation no_gc; 577 WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc); 578 for (int i = 0; i < argument_count; i++) { 579 array->set(i, parameters[i], mode); 580 } 581 result->set_elements(*array); 582 } 583 return result; 584 } 585 586 587 template <typename T> 588 Handle<JSObject> NewRestArguments(Isolate* isolate, Handle<JSFunction> callee, 589 T parameters, int argument_count, 590 int start_index) { 591 int num_elements = std::max(0, argument_count - start_index); 592 Handle<JSObject> result = isolate->factory()->NewJSArray( 593 FAST_ELEMENTS, num_elements, num_elements, Strength::WEAK, 594 DONT_INITIALIZE_ARRAY_ELEMENTS); 595 { 596 DisallowHeapAllocation no_gc; 597 FixedArray* elements = FixedArray::cast(result->elements()); 598 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); 599 for (int i = 0; i < num_elements; i++) { 600 elements->set(i, parameters[i + start_index], mode); 601 } 602 } 603 return result; 604 } 605 606 607 class HandleArguments BASE_EMBEDDED { 608 public: 609 explicit HandleArguments(Handle<Object>* array) : array_(array) {} 610 Object* operator[](int index) { return *array_[index]; } 611 612 private: 613 Handle<Object>* array_; 614 }; 615 616 617 class ParameterArguments BASE_EMBEDDED { 618 public: 619 explicit ParameterArguments(Object** parameters) : parameters_(parameters) {} 620 Object*& operator[](int index) { return *(parameters_ - index - 1); } 621 622 private: 623 Object** parameters_; 624 }; 625 626 } // namespace 627 628 629 RUNTIME_FUNCTION(Runtime_NewSloppyArguments_Generic) { 630 HandleScope scope(isolate); 631 DCHECK(args.length() == 1); 632 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0); 633 // This generic runtime function can also be used when the caller has been 634 // inlined, we use the slow but accurate {GetCallerArguments}. 635 int argument_count = 0; 636 base::SmartArrayPointer<Handle<Object>> arguments = 637 GetCallerArguments(isolate, 0, &argument_count); 638 HandleArguments argument_getter(arguments.get()); 639 return *NewSloppyArguments(isolate, callee, argument_getter, argument_count); 640 } 641 642 643 RUNTIME_FUNCTION(Runtime_NewStrictArguments_Generic) { 644 HandleScope scope(isolate); 645 DCHECK(args.length() == 1); 646 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0); 647 // This generic runtime function can also be used when the caller has been 648 // inlined, we use the slow but accurate {GetCallerArguments}. 649 int argument_count = 0; 650 base::SmartArrayPointer<Handle<Object>> arguments = 651 GetCallerArguments(isolate, 0, &argument_count); 652 HandleArguments argument_getter(arguments.get()); 653 return *NewStrictArguments(isolate, callee, argument_getter, argument_count); 654 } 655 656 657 RUNTIME_FUNCTION(Runtime_NewRestArguments_Generic) { 658 HandleScope scope(isolate); 659 DCHECK(args.length() == 2); 660 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0) 661 CONVERT_SMI_ARG_CHECKED(start_index, 1); 662 // This generic runtime function can also be used when the caller has been 663 // inlined, we use the slow but accurate {GetCallerArguments}. 664 int argument_count = 0; 665 base::SmartArrayPointer<Handle<Object>> arguments = 666 GetCallerArguments(isolate, 0, &argument_count); 667 HandleArguments argument_getter(arguments.get()); 668 return *NewRestArguments(isolate, callee, argument_getter, argument_count, 669 start_index); 670 } 671 672 673 RUNTIME_FUNCTION(Runtime_NewSloppyArguments) { 674 HandleScope scope(isolate); 675 DCHECK(args.length() == 3); 676 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0); 677 Object** parameters = reinterpret_cast<Object**>(args[1]); 678 CONVERT_SMI_ARG_CHECKED(argument_count, 2); 679 #ifdef DEBUG 680 // This runtime function does not materialize the correct arguments when the 681 // caller has been inlined, better make sure we are not hitting that case. 682 JavaScriptFrameIterator it(isolate); 683 DCHECK(!it.frame()->HasInlinedFrames()); 684 #endif // DEBUG 685 ParameterArguments argument_getter(parameters); 686 return *NewSloppyArguments(isolate, callee, argument_getter, argument_count); 687 } 688 689 690 RUNTIME_FUNCTION(Runtime_NewStrictArguments) { 691 HandleScope scope(isolate); 692 DCHECK(args.length() == 3); 693 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0) 694 Object** parameters = reinterpret_cast<Object**>(args[1]); 695 CONVERT_SMI_ARG_CHECKED(argument_count, 2); 696 #ifdef DEBUG 697 // This runtime function does not materialize the correct arguments when the 698 // caller has been inlined, better make sure we are not hitting that case. 699 JavaScriptFrameIterator it(isolate); 700 DCHECK(!it.frame()->HasInlinedFrames()); 701 #endif // DEBUG 702 ParameterArguments argument_getter(parameters); 703 return *NewStrictArguments(isolate, callee, argument_getter, argument_count); 704 } 705 706 707 RUNTIME_FUNCTION(Runtime_NewRestParam) { 708 HandleScope scope(isolate); 709 DCHECK(args.length() == 3); 710 CONVERT_SMI_ARG_CHECKED(num_params, 0); 711 Object** parameters = reinterpret_cast<Object**>(args[1]); 712 CONVERT_SMI_ARG_CHECKED(rest_index, 2); 713 #ifdef DEBUG 714 // This runtime function does not materialize the correct arguments when the 715 // caller has been inlined, better make sure we are not hitting that case. 716 JavaScriptFrameIterator it(isolate); 717 DCHECK(!it.frame()->HasInlinedFrames()); 718 #endif // DEBUG 719 Handle<JSFunction> callee; 720 ParameterArguments argument_getter(parameters); 721 return *NewRestArguments(isolate, callee, argument_getter, num_params, 722 rest_index); 723 } 724 725 726 RUNTIME_FUNCTION(Runtime_NewClosure) { 727 HandleScope scope(isolate); 728 DCHECK_EQ(1, args.length()); 729 CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0); 730 Handle<Context> context(isolate->context(), isolate); 731 return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context, 732 NOT_TENURED); 733 } 734 735 736 RUNTIME_FUNCTION(Runtime_NewClosure_Tenured) { 737 HandleScope scope(isolate); 738 DCHECK_EQ(1, args.length()); 739 CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0); 740 Handle<Context> context(isolate->context(), isolate); 741 // The caller ensures that we pretenure closures that are assigned 742 // directly to properties. 743 return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context, 744 TENURED); 745 } 746 747 static Object* FindNameClash(Handle<ScopeInfo> scope_info, 748 Handle<JSGlobalObject> global_object, 749 Handle<ScriptContextTable> script_context) { 750 Isolate* isolate = scope_info->GetIsolate(); 751 for (int var = 0; var < scope_info->ContextLocalCount(); var++) { 752 Handle<String> name(scope_info->ContextLocalName(var)); 753 VariableMode mode = scope_info->ContextLocalMode(var); 754 ScriptContextTable::LookupResult lookup; 755 if (ScriptContextTable::Lookup(script_context, name, &lookup)) { 756 if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(lookup.mode)) { 757 return ThrowRedeclarationError(isolate, name); 758 } 759 } 760 761 if (IsLexicalVariableMode(mode)) { 762 LookupIterator it(global_object, name, 763 LookupIterator::HIDDEN_SKIP_INTERCEPTOR); 764 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); 765 if (!maybe.IsJust()) return isolate->heap()->exception(); 766 if ((maybe.FromJust() & DONT_DELETE) != 0) { 767 return ThrowRedeclarationError(isolate, name); 768 } 769 770 JSGlobalObject::InvalidatePropertyCell(global_object, name); 771 } 772 } 773 return isolate->heap()->undefined_value(); 774 } 775 776 777 RUNTIME_FUNCTION(Runtime_NewScriptContext) { 778 HandleScope scope(isolate); 779 DCHECK(args.length() == 2); 780 781 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); 782 CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1); 783 Handle<JSGlobalObject> global_object(function->context()->global_object()); 784 Handle<Context> native_context(global_object->native_context()); 785 Handle<ScriptContextTable> script_context_table( 786 native_context->script_context_table()); 787 788 Object* name_clash_result = 789 FindNameClash(scope_info, global_object, script_context_table); 790 if (isolate->has_pending_exception()) return name_clash_result; 791 792 // Script contexts have a canonical empty function as their closure, not the 793 // anonymous closure containing the global code. See 794 // FullCodeGenerator::PushFunctionArgumentForContextAllocation. 795 Handle<JSFunction> closure( 796 function->shared()->IsBuiltin() ? *function : native_context->closure()); 797 Handle<Context> result = 798 isolate->factory()->NewScriptContext(closure, scope_info); 799 800 result->InitializeGlobalSlots(); 801 802 DCHECK(function->context() == isolate->context()); 803 DCHECK(*global_object == result->global_object()); 804 805 Handle<ScriptContextTable> new_script_context_table = 806 ScriptContextTable::Extend(script_context_table, result); 807 native_context->set_script_context_table(*new_script_context_table); 808 return *result; 809 } 810 811 812 RUNTIME_FUNCTION(Runtime_NewFunctionContext) { 813 HandleScope scope(isolate); 814 DCHECK(args.length() == 1); 815 816 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); 817 818 DCHECK(function->context() == isolate->context()); 819 int length = function->shared()->scope_info()->ContextLength(); 820 return *isolate->factory()->NewFunctionContext(length, function); 821 } 822 823 824 RUNTIME_FUNCTION(Runtime_PushWithContext) { 825 HandleScope scope(isolate); 826 DCHECK_EQ(2, args.length()); 827 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, extension_object, 0); 828 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1); 829 Handle<Context> current(isolate->context()); 830 Handle<Context> context = 831 isolate->factory()->NewWithContext(function, current, extension_object); 832 isolate->set_context(*context); 833 return *context; 834 } 835 836 837 RUNTIME_FUNCTION(Runtime_PushCatchContext) { 838 HandleScope scope(isolate); 839 DCHECK_EQ(3, args.length()); 840 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); 841 CONVERT_ARG_HANDLE_CHECKED(Object, thrown_object, 1); 842 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 2); 843 Handle<Context> current(isolate->context()); 844 Handle<Context> context = isolate->factory()->NewCatchContext( 845 function, current, name, thrown_object); 846 isolate->set_context(*context); 847 return *context; 848 } 849 850 851 RUNTIME_FUNCTION(Runtime_PushBlockContext) { 852 HandleScope scope(isolate); 853 DCHECK_EQ(2, args.length()); 854 CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 0); 855 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1); 856 Handle<Context> current(isolate->context()); 857 Handle<Context> context = 858 isolate->factory()->NewBlockContext(function, current, scope_info); 859 isolate->set_context(*context); 860 return *context; 861 } 862 863 864 RUNTIME_FUNCTION(Runtime_IsJSModule) { 865 SealHandleScope shs(isolate); 866 DCHECK(args.length() == 1); 867 CONVERT_ARG_CHECKED(Object, obj, 0); 868 return isolate->heap()->ToBoolean(obj->IsJSModule()); 869 } 870 871 872 RUNTIME_FUNCTION(Runtime_PushModuleContext) { 873 SealHandleScope shs(isolate); 874 DCHECK(args.length() == 2); 875 CONVERT_SMI_ARG_CHECKED(index, 0); 876 877 if (!args[1]->IsScopeInfo()) { 878 // Module already initialized. Find hosting context and retrieve context. 879 Context* host = Context::cast(isolate->context())->script_context(); 880 Context* context = Context::cast(host->get(index)); 881 DCHECK(context->previous() == isolate->context()); 882 isolate->set_context(context); 883 return context; 884 } 885 886 CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1); 887 888 // Allocate module context. 889 HandleScope scope(isolate); 890 Factory* factory = isolate->factory(); 891 Handle<Context> context = factory->NewModuleContext(scope_info); 892 Handle<JSModule> module = factory->NewJSModule(context, scope_info); 893 context->set_module(*module); 894 Context* previous = isolate->context(); 895 context->set_previous(previous); 896 context->set_closure(previous->closure()); 897 context->set_native_context(previous->native_context()); 898 isolate->set_context(*context); 899 900 // Find hosting scope and initialize internal variable holding module there. 901 previous->script_context()->set(index, *context); 902 903 return *context; 904 } 905 906 907 RUNTIME_FUNCTION(Runtime_DeclareModules) { 908 HandleScope scope(isolate); 909 DCHECK(args.length() == 1); 910 CONVERT_ARG_HANDLE_CHECKED(FixedArray, descriptions, 0); 911 Context* host_context = isolate->context(); 912 913 for (int i = 0; i < descriptions->length(); ++i) { 914 Handle<ModuleInfo> description(ModuleInfo::cast(descriptions->get(i))); 915 int host_index = description->host_index(); 916 Handle<Context> context(Context::cast(host_context->get(host_index))); 917 Handle<JSModule> module(context->module()); 918 919 for (int j = 0; j < description->length(); ++j) { 920 Handle<String> name(description->name(j)); 921 VariableMode mode = description->mode(j); 922 int index = description->index(j); 923 switch (mode) { 924 case VAR: 925 case LET: 926 case CONST: 927 case CONST_LEGACY: 928 case IMPORT: { 929 PropertyAttributes attr = 930 IsImmutableVariableMode(mode) ? FROZEN : SEALED; 931 Handle<AccessorInfo> info = 932 Accessors::MakeModuleExport(name, index, attr); 933 Handle<Object> result = 934 JSObject::SetAccessor(module, info).ToHandleChecked(); 935 DCHECK(!result->IsUndefined()); 936 USE(result); 937 break; 938 } 939 case TEMPORARY: 940 case DYNAMIC: 941 case DYNAMIC_GLOBAL: 942 case DYNAMIC_LOCAL: 943 UNREACHABLE(); 944 } 945 } 946 947 if (JSObject::PreventExtensions(module, Object::THROW_ON_ERROR) 948 .IsNothing()) { 949 DCHECK(false); 950 } 951 } 952 953 DCHECK(!isolate->has_pending_exception()); 954 return isolate->heap()->undefined_value(); 955 } 956 957 958 RUNTIME_FUNCTION(Runtime_DeleteLookupSlot) { 959 HandleScope scope(isolate); 960 DCHECK(args.length() == 2); 961 962 CONVERT_ARG_HANDLE_CHECKED(Context, context, 0); 963 CONVERT_ARG_HANDLE_CHECKED(String, name, 1); 964 965 int index; 966 PropertyAttributes attributes; 967 ContextLookupFlags flags = FOLLOW_CHAINS; 968 BindingFlags binding_flags; 969 Handle<Object> holder = 970 context->Lookup(name, flags, &index, &attributes, &binding_flags); 971 972 // If the slot was not found the result is true. 973 if (holder.is_null()) { 974 // In case of JSProxy, an exception might have been thrown. 975 if (isolate->has_pending_exception()) return isolate->heap()->exception(); 976 return isolate->heap()->true_value(); 977 } 978 979 // If the slot was found in a context, it should be DONT_DELETE. 980 if (holder->IsContext()) { 981 return isolate->heap()->false_value(); 982 } 983 984 // The slot was found in a JSReceiver, either a context extension object, 985 // the global object, or the subject of a with. Try to delete it 986 // (respecting DONT_DELETE). 987 Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder); 988 Maybe<bool> result = JSReceiver::DeleteProperty(object, name); 989 MAYBE_RETURN(result, isolate->heap()->exception()); 990 return isolate->heap()->ToBoolean(result.FromJust()); 991 } 992 993 994 static Object* ComputeReceiverForNonGlobal(Isolate* isolate, JSObject* holder) { 995 DCHECK(!holder->IsJSGlobalObject()); 996 997 // If the holder isn't a context extension object, we just return it 998 // as the receiver. This allows arguments objects to be used as 999 // receivers, but only if they are put in the context scope chain 1000 // explicitly via a with-statement. 1001 if (holder->map()->instance_type() != JS_CONTEXT_EXTENSION_OBJECT_TYPE) { 1002 return holder; 1003 } 1004 // Fall back to using the global object as the implicit receiver if 1005 // the property turns out to be a local variable allocated in a 1006 // context extension object - introduced via eval. 1007 return isolate->heap()->undefined_value(); 1008 } 1009 1010 1011 static ObjectPair LoadLookupSlotHelper(Arguments args, Isolate* isolate, 1012 bool throw_error) { 1013 HandleScope scope(isolate); 1014 DCHECK_EQ(2, args.length()); 1015 1016 if (!args[0]->IsContext() || !args[1]->IsString()) { 1017 return MakePair(isolate->ThrowIllegalOperation(), NULL); 1018 } 1019 Handle<Context> context = args.at<Context>(0); 1020 Handle<String> name = args.at<String>(1); 1021 1022 int index; 1023 PropertyAttributes attributes; 1024 ContextLookupFlags flags = FOLLOW_CHAINS; 1025 BindingFlags binding_flags; 1026 Handle<Object> holder = 1027 context->Lookup(name, flags, &index, &attributes, &binding_flags); 1028 if (isolate->has_pending_exception()) { 1029 return MakePair(isolate->heap()->exception(), NULL); 1030 } 1031 1032 if (index != Context::kNotFound) { 1033 DCHECK(holder->IsContext()); 1034 // If the "property" we were looking for is a local variable, the 1035 // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3. 1036 Handle<Object> receiver = isolate->factory()->undefined_value(); 1037 Object* value = Context::cast(*holder)->get(index); 1038 // Check for uninitialized bindings. 1039 switch (binding_flags) { 1040 case MUTABLE_CHECK_INITIALIZED: 1041 case IMMUTABLE_CHECK_INITIALIZED_HARMONY: 1042 if (value->IsTheHole()) { 1043 Handle<Object> error = isolate->factory()->NewReferenceError( 1044 MessageTemplate::kNotDefined, name); 1045 isolate->Throw(*error); 1046 return MakePair(isolate->heap()->exception(), NULL); 1047 } 1048 // FALLTHROUGH 1049 case MUTABLE_IS_INITIALIZED: 1050 case IMMUTABLE_IS_INITIALIZED: 1051 case IMMUTABLE_IS_INITIALIZED_HARMONY: 1052 DCHECK(!value->IsTheHole()); 1053 return MakePair(value, *receiver); 1054 case IMMUTABLE_CHECK_INITIALIZED: 1055 if (value->IsTheHole()) { 1056 DCHECK((attributes & READ_ONLY) != 0); 1057 value = isolate->heap()->undefined_value(); 1058 } 1059 return MakePair(value, *receiver); 1060 case MISSING_BINDING: 1061 UNREACHABLE(); 1062 return MakePair(NULL, NULL); 1063 } 1064 } 1065 1066 // Otherwise, if the slot was found the holder is a context extension 1067 // object, subject of a with, or a global object. We read the named 1068 // property from it. 1069 if (!holder.is_null()) { 1070 Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder); 1071 // GetProperty below can cause GC. 1072 Handle<Object> receiver_handle( 1073 object->IsJSGlobalObject() 1074 ? Object::cast(isolate->heap()->undefined_value()) 1075 : object->IsJSProxy() ? static_cast<Object*>(*object) 1076 : ComputeReceiverForNonGlobal( 1077 isolate, JSObject::cast(*object)), 1078 isolate); 1079 1080 // No need to unhole the value here. This is taken care of by the 1081 // GetProperty function. 1082 Handle<Object> value; 1083 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 1084 isolate, value, Object::GetProperty(object, name), 1085 MakePair(isolate->heap()->exception(), NULL)); 1086 return MakePair(*value, *receiver_handle); 1087 } 1088 1089 if (throw_error) { 1090 // The property doesn't exist - throw exception. 1091 Handle<Object> error = isolate->factory()->NewReferenceError( 1092 MessageTemplate::kNotDefined, name); 1093 isolate->Throw(*error); 1094 return MakePair(isolate->heap()->exception(), NULL); 1095 } else { 1096 // The property doesn't exist - return undefined. 1097 return MakePair(isolate->heap()->undefined_value(), 1098 isolate->heap()->undefined_value()); 1099 } 1100 } 1101 1102 1103 RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadLookupSlot) { 1104 return LoadLookupSlotHelper(args, isolate, true); 1105 } 1106 1107 1108 RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadLookupSlotNoReferenceError) { 1109 return LoadLookupSlotHelper(args, isolate, false); 1110 } 1111 1112 1113 RUNTIME_FUNCTION(Runtime_StoreLookupSlot) { 1114 HandleScope scope(isolate); 1115 DCHECK(args.length() == 4); 1116 1117 CONVERT_ARG_HANDLE_CHECKED(Object, value, 0); 1118 CONVERT_ARG_HANDLE_CHECKED(Context, context, 1); 1119 CONVERT_ARG_HANDLE_CHECKED(String, name, 2); 1120 CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 3); 1121 1122 int index; 1123 PropertyAttributes attributes; 1124 ContextLookupFlags flags = FOLLOW_CHAINS; 1125 BindingFlags binding_flags; 1126 Handle<Object> holder = 1127 context->Lookup(name, flags, &index, &attributes, &binding_flags); 1128 if (holder.is_null()) { 1129 // In case of JSProxy, an exception might have been thrown. 1130 if (isolate->has_pending_exception()) return isolate->heap()->exception(); 1131 } 1132 1133 // The property was found in a context slot. 1134 if (index != Context::kNotFound) { 1135 if ((binding_flags == MUTABLE_CHECK_INITIALIZED || 1136 binding_flags == IMMUTABLE_CHECK_INITIALIZED_HARMONY) && 1137 Handle<Context>::cast(holder)->is_the_hole(index)) { 1138 THROW_NEW_ERROR_RETURN_FAILURE( 1139 isolate, NewReferenceError(MessageTemplate::kNotDefined, name)); 1140 } 1141 if ((attributes & READ_ONLY) == 0) { 1142 Handle<Context>::cast(holder)->set(index, *value); 1143 } else if (is_strict(language_mode)) { 1144 // Setting read only property in strict mode. 1145 THROW_NEW_ERROR_RETURN_FAILURE( 1146 isolate, NewTypeError(MessageTemplate::kStrictCannotAssign, name)); 1147 } 1148 return *value; 1149 } 1150 1151 // Slow case: The property is not in a context slot. It is either in a 1152 // context extension object, a property of the subject of a with, or a 1153 // property of the global object. 1154 Handle<JSReceiver> object; 1155 if (attributes != ABSENT) { 1156 // The property exists on the holder. 1157 object = Handle<JSReceiver>::cast(holder); 1158 } else if (is_strict(language_mode)) { 1159 // If absent in strict mode: throw. 1160 THROW_NEW_ERROR_RETURN_FAILURE( 1161 isolate, NewReferenceError(MessageTemplate::kNotDefined, name)); 1162 } else { 1163 // If absent in sloppy mode: add the property to the global object. 1164 object = Handle<JSReceiver>(context->global_object()); 1165 } 1166 1167 RETURN_FAILURE_ON_EXCEPTION( 1168 isolate, Object::SetProperty(object, name, value, language_mode)); 1169 1170 return *value; 1171 } 1172 1173 1174 RUNTIME_FUNCTION(Runtime_ArgumentsLength) { 1175 HandleScope scope(isolate); 1176 DCHECK(args.length() == 0); 1177 int argument_count = 0; 1178 GetCallerArguments(isolate, 0, &argument_count); 1179 return Smi::FromInt(argument_count); 1180 } 1181 1182 1183 RUNTIME_FUNCTION(Runtime_Arguments) { 1184 HandleScope scope(isolate); 1185 DCHECK(args.length() == 1); 1186 CONVERT_ARG_HANDLE_CHECKED(Object, raw_key, 0); 1187 1188 // Determine the actual arguments passed to the function. 1189 int argument_count_signed = 0; 1190 base::SmartArrayPointer<Handle<Object>> arguments = 1191 GetCallerArguments(isolate, 0, &argument_count_signed); 1192 const uint32_t argument_count = argument_count_signed; 1193 1194 // Try to convert the key to an index. If successful and within 1195 // index return the the argument from the frame. 1196 uint32_t index = 0; 1197 if (raw_key->ToArrayIndex(&index) && index < argument_count) { 1198 return *arguments[index]; 1199 } 1200 1201 if (raw_key->IsSymbol()) { 1202 Handle<Symbol> symbol = Handle<Symbol>::cast(raw_key); 1203 if (Name::Equals(symbol, isolate->factory()->iterator_symbol())) { 1204 return isolate->native_context()->array_values_iterator(); 1205 } 1206 // Lookup in the initial Object.prototype object. 1207 Handle<Object> result; 1208 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1209 isolate, result, 1210 Object::GetProperty(isolate->initial_object_prototype(), 1211 Handle<Symbol>::cast(raw_key))); 1212 return *result; 1213 } 1214 1215 // Convert the key to a string. 1216 Handle<Object> converted; 1217 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, converted, 1218 Object::ToString(isolate, raw_key)); 1219 Handle<String> key = Handle<String>::cast(converted); 1220 1221 // Try to convert the string key into an array index. 1222 if (key->AsArrayIndex(&index)) { 1223 if (index < argument_count) { 1224 return *arguments[index]; 1225 } else { 1226 Handle<Object> initial_prototype(isolate->initial_object_prototype()); 1227 Handle<Object> result; 1228 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1229 isolate, result, 1230 Object::GetElement(isolate, initial_prototype, index)); 1231 return *result; 1232 } 1233 } 1234 1235 // Handle special arguments properties. 1236 if (String::Equals(isolate->factory()->length_string(), key)) { 1237 return Smi::FromInt(argument_count); 1238 } 1239 if (String::Equals(isolate->factory()->callee_string(), key)) { 1240 JavaScriptFrameIterator it(isolate); 1241 JSFunction* function = it.frame()->function(); 1242 if (is_strict(function->shared()->language_mode())) { 1243 THROW_NEW_ERROR_RETURN_FAILURE( 1244 isolate, NewTypeError(MessageTemplate::kStrictPoisonPill)); 1245 } 1246 return function; 1247 } 1248 1249 // Lookup in the initial Object.prototype object. 1250 Handle<Object> result; 1251 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1252 isolate, result, 1253 Object::GetProperty(isolate->initial_object_prototype(), key)); 1254 return *result; 1255 } 1256 } // namespace internal 1257 } // namespace v8 1258