1 // Copyright 2012 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/accessors.h" 6 7 #include "src/api.h" 8 #include "src/contexts.h" 9 #include "src/deoptimizer.h" 10 #include "src/execution.h" 11 #include "src/factory.h" 12 #include "src/frames-inl.h" 13 #include "src/isolate-inl.h" 14 #include "src/list-inl.h" 15 #include "src/messages.h" 16 #include "src/property-details.h" 17 #include "src/prototype.h" 18 19 namespace v8 { 20 namespace internal { 21 22 23 Handle<AccessorInfo> Accessors::MakeAccessor( 24 Isolate* isolate, 25 Handle<Name> name, 26 AccessorNameGetterCallback getter, 27 AccessorNameSetterCallback setter, 28 PropertyAttributes attributes) { 29 Factory* factory = isolate->factory(); 30 Handle<ExecutableAccessorInfo> info = factory->NewExecutableAccessorInfo(); 31 info->set_property_attributes(attributes); 32 info->set_all_can_read(false); 33 info->set_all_can_write(false); 34 info->set_is_special_data_property(true); 35 info->set_name(*name); 36 Handle<Object> get = v8::FromCData(isolate, getter); 37 Handle<Object> set = v8::FromCData(isolate, setter); 38 info->set_getter(*get); 39 info->set_setter(*set); 40 return info; 41 } 42 43 44 Handle<ExecutableAccessorInfo> Accessors::CloneAccessor( 45 Isolate* isolate, 46 Handle<ExecutableAccessorInfo> accessor) { 47 Factory* factory = isolate->factory(); 48 Handle<ExecutableAccessorInfo> info = factory->NewExecutableAccessorInfo(); 49 info->set_name(accessor->name()); 50 info->set_flag(accessor->flag()); 51 info->set_expected_receiver_type(accessor->expected_receiver_type()); 52 info->set_getter(accessor->getter()); 53 info->set_setter(accessor->setter()); 54 info->set_data(accessor->data()); 55 return info; 56 } 57 58 59 static V8_INLINE bool CheckForName(Handle<Name> name, 60 Handle<String> property_name, 61 int offset, 62 int* object_offset) { 63 if (Name::Equals(name, property_name)) { 64 *object_offset = offset; 65 return true; 66 } 67 return false; 68 } 69 70 71 // Returns true for properties that are accessors to object fields. 72 // If true, *object_offset contains offset of object field. 73 bool Accessors::IsJSObjectFieldAccessor(Handle<Map> map, Handle<Name> name, 74 int* object_offset) { 75 Isolate* isolate = name->GetIsolate(); 76 77 switch (map->instance_type()) { 78 case JS_ARRAY_TYPE: 79 return 80 CheckForName(name, isolate->factory()->length_string(), 81 JSArray::kLengthOffset, object_offset); 82 case JS_ARRAY_BUFFER_TYPE: 83 return CheckForName(name, isolate->factory()->byte_length_string(), 84 JSArrayBuffer::kByteLengthOffset, object_offset); 85 default: 86 if (map->instance_type() < FIRST_NONSTRING_TYPE) { 87 return CheckForName(name, isolate->factory()->length_string(), 88 String::kLengthOffset, object_offset); 89 } 90 91 return false; 92 } 93 } 94 95 96 bool Accessors::IsJSArrayBufferViewFieldAccessor(Handle<Map> map, 97 Handle<Name> name, 98 int* object_offset) { 99 Isolate* isolate = name->GetIsolate(); 100 101 switch (map->instance_type()) { 102 case JS_TYPED_ARRAY_TYPE: { 103 if (!CheckForName(name, isolate->factory()->length_string(), 104 JSTypedArray::kLengthOffset, object_offset) && 105 !CheckForName(name, isolate->factory()->byte_length_string(), 106 JSTypedArray::kByteLengthOffset, object_offset) && 107 !CheckForName(name, isolate->factory()->byte_offset_string(), 108 JSTypedArray::kByteOffsetOffset, object_offset)) { 109 return false; 110 } 111 112 if (map->is_dictionary_map()) return false; 113 114 // Check if the property is overridden on the instance. 115 DescriptorArray* descriptors = map->instance_descriptors(); 116 int descriptor = descriptors->SearchWithCache(*name, *map); 117 if (descriptor != DescriptorArray::kNotFound) return false; 118 119 Handle<Object> proto = Handle<Object>(map->prototype(), isolate); 120 if (!proto->IsJSReceiver()) return false; 121 122 // Check if the property is defined in the prototype chain. 123 LookupIterator it(proto, name); 124 if (!it.IsFound()) return false; 125 126 Object* original_proto = 127 JSFunction::cast(map->GetConstructor())->prototype(); 128 129 // Property is not configurable. It is enough to verify that 130 // the holder is the same. 131 return *it.GetHolder<Object>() == original_proto; 132 } 133 case JS_DATA_VIEW_TYPE: 134 return CheckForName(name, isolate->factory()->byte_length_string(), 135 JSDataView::kByteLengthOffset, object_offset) || 136 CheckForName(name, isolate->factory()->byte_offset_string(), 137 JSDataView::kByteOffsetOffset, object_offset); 138 default: 139 return false; 140 } 141 } 142 143 144 // 145 // Accessors::ArgumentsIterator 146 // 147 148 149 void Accessors::ArgumentsIteratorGetter( 150 v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) { 151 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 152 DisallowHeapAllocation no_allocation; 153 HandleScope scope(isolate); 154 Object* result = isolate->native_context()->array_values_iterator(); 155 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate))); 156 } 157 158 159 void Accessors::ArgumentsIteratorSetter( 160 v8::Local<v8::Name> name, v8::Local<v8::Value> val, 161 const v8::PropertyCallbackInfo<void>& info) { 162 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 163 HandleScope scope(isolate); 164 Handle<JSObject> object_handle = 165 Handle<JSObject>::cast(Utils::OpenHandle(*info.This())); 166 Handle<Object> value_handle = Utils::OpenHandle(*val); 167 Handle<Name> name_handle = Utils::OpenHandle(*name); 168 169 if (JSObject::DefinePropertyOrElementIgnoreAttributes( 170 object_handle, name_handle, value_handle, NONE) 171 .is_null()) { 172 isolate->OptionalRescheduleException(false); 173 } 174 } 175 176 177 Handle<AccessorInfo> Accessors::ArgumentsIteratorInfo( 178 Isolate* isolate, PropertyAttributes attributes) { 179 Handle<Name> name = isolate->factory()->iterator_symbol(); 180 return MakeAccessor(isolate, name, &ArgumentsIteratorGetter, 181 &ArgumentsIteratorSetter, attributes); 182 } 183 184 185 // 186 // Accessors::ArrayLength 187 // 188 189 190 void Accessors::ArrayLengthGetter( 191 v8::Local<v8::Name> name, 192 const v8::PropertyCallbackInfo<v8::Value>& info) { 193 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 194 DisallowHeapAllocation no_allocation; 195 HandleScope scope(isolate); 196 JSArray* holder = JSArray::cast(*Utils::OpenHandle(*info.Holder())); 197 Object* result = holder->length(); 198 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate))); 199 } 200 201 202 void Accessors::ArrayLengthSetter( 203 v8::Local<v8::Name> name, 204 v8::Local<v8::Value> val, 205 const v8::PropertyCallbackInfo<void>& info) { 206 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 207 HandleScope scope(isolate); 208 209 Handle<JSReceiver> object = Utils::OpenHandle(*info.This()); 210 Handle<JSArray> array = Handle<JSArray>::cast(object); 211 Handle<Object> length_obj = Utils::OpenHandle(*val); 212 213 uint32_t length = 0; 214 if (!JSArray::AnythingToArrayLength(isolate, length_obj, &length)) { 215 isolate->OptionalRescheduleException(false); 216 return; 217 } 218 219 if (JSArray::ObservableSetLength(array, length).is_null()) { 220 isolate->OptionalRescheduleException(false); 221 } 222 } 223 224 225 Handle<AccessorInfo> Accessors::ArrayLengthInfo( 226 Isolate* isolate, PropertyAttributes attributes) { 227 return MakeAccessor(isolate, 228 isolate->factory()->length_string(), 229 &ArrayLengthGetter, 230 &ArrayLengthSetter, 231 attributes); 232 } 233 234 235 // 236 // Accessors::StringLength 237 // 238 239 void Accessors::StringLengthGetter( 240 v8::Local<v8::Name> name, 241 const v8::PropertyCallbackInfo<v8::Value>& info) { 242 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 243 DisallowHeapAllocation no_allocation; 244 HandleScope scope(isolate); 245 246 // We have a slight impedance mismatch between the external API and the way we 247 // use callbacks internally: Externally, callbacks can only be used with 248 // v8::Object, but internally we have callbacks on entities which are higher 249 // in the hierarchy, in this case for String values. 250 251 Object* value = *Utils::OpenHandle(*v8::Local<v8::Value>(info.This())); 252 if (!value->IsString()) { 253 // Not a string value. That means that we either got a String wrapper or 254 // a Value with a String wrapper in its prototype chain. 255 value = JSValue::cast(*Utils::OpenHandle(*info.Holder()))->value(); 256 } 257 Object* result = Smi::FromInt(String::cast(value)->length()); 258 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate))); 259 } 260 261 262 void Accessors::StringLengthSetter( 263 v8::Local<v8::Name> name, 264 v8::Local<v8::Value> value, 265 const v8::PropertyCallbackInfo<void>& info) { 266 UNREACHABLE(); 267 } 268 269 270 Handle<AccessorInfo> Accessors::StringLengthInfo( 271 Isolate* isolate, PropertyAttributes attributes) { 272 return MakeAccessor(isolate, 273 isolate->factory()->length_string(), 274 &StringLengthGetter, 275 &StringLengthSetter, 276 attributes); 277 } 278 279 280 // 281 // Accessors::ScriptColumnOffset 282 // 283 284 285 void Accessors::ScriptColumnOffsetGetter( 286 v8::Local<v8::Name> name, 287 const v8::PropertyCallbackInfo<v8::Value>& info) { 288 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 289 DisallowHeapAllocation no_allocation; 290 HandleScope scope(isolate); 291 Object* object = *Utils::OpenHandle(*info.This()); 292 Object* res = Smi::FromInt( 293 Script::cast(JSValue::cast(object)->value())->column_offset()); 294 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate))); 295 } 296 297 298 void Accessors::ScriptColumnOffsetSetter( 299 v8::Local<v8::Name> name, 300 v8::Local<v8::Value> value, 301 const v8::PropertyCallbackInfo<void>& info) { 302 UNREACHABLE(); 303 } 304 305 306 Handle<AccessorInfo> Accessors::ScriptColumnOffsetInfo( 307 Isolate* isolate, PropertyAttributes attributes) { 308 Handle<String> name(isolate->factory()->InternalizeOneByteString( 309 STATIC_CHAR_VECTOR("column_offset"))); 310 return MakeAccessor(isolate, 311 name, 312 &ScriptColumnOffsetGetter, 313 &ScriptColumnOffsetSetter, 314 attributes); 315 } 316 317 318 // 319 // Accessors::ScriptId 320 // 321 322 323 void Accessors::ScriptIdGetter( 324 v8::Local<v8::Name> name, 325 const v8::PropertyCallbackInfo<v8::Value>& info) { 326 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 327 DisallowHeapAllocation no_allocation; 328 HandleScope scope(isolate); 329 Object* object = *Utils::OpenHandle(*info.This()); 330 Object* id = Smi::FromInt(Script::cast(JSValue::cast(object)->value())->id()); 331 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(id, isolate))); 332 } 333 334 335 void Accessors::ScriptIdSetter( 336 v8::Local<v8::Name> name, 337 v8::Local<v8::Value> value, 338 const v8::PropertyCallbackInfo<void>& info) { 339 UNREACHABLE(); 340 } 341 342 343 Handle<AccessorInfo> Accessors::ScriptIdInfo( 344 Isolate* isolate, PropertyAttributes attributes) { 345 Handle<String> name( 346 isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("id"))); 347 return MakeAccessor(isolate, 348 name, 349 &ScriptIdGetter, 350 &ScriptIdSetter, 351 attributes); 352 } 353 354 355 // 356 // Accessors::ScriptName 357 // 358 359 360 void Accessors::ScriptNameGetter( 361 v8::Local<v8::Name> name, 362 const v8::PropertyCallbackInfo<v8::Value>& info) { 363 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 364 DisallowHeapAllocation no_allocation; 365 HandleScope scope(isolate); 366 Object* object = *Utils::OpenHandle(*info.This()); 367 Object* source = Script::cast(JSValue::cast(object)->value())->name(); 368 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(source, isolate))); 369 } 370 371 372 void Accessors::ScriptNameSetter( 373 v8::Local<v8::Name> name, 374 v8::Local<v8::Value> value, 375 const v8::PropertyCallbackInfo<void>& info) { 376 UNREACHABLE(); 377 } 378 379 380 Handle<AccessorInfo> Accessors::ScriptNameInfo( 381 Isolate* isolate, PropertyAttributes attributes) { 382 return MakeAccessor(isolate, 383 isolate->factory()->name_string(), 384 &ScriptNameGetter, 385 &ScriptNameSetter, 386 attributes); 387 } 388 389 390 // 391 // Accessors::ScriptSource 392 // 393 394 395 void Accessors::ScriptSourceGetter( 396 v8::Local<v8::Name> name, 397 const v8::PropertyCallbackInfo<v8::Value>& info) { 398 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 399 DisallowHeapAllocation no_allocation; 400 HandleScope scope(isolate); 401 Object* object = *Utils::OpenHandle(*info.This()); 402 Object* source = Script::cast(JSValue::cast(object)->value())->source(); 403 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(source, isolate))); 404 } 405 406 407 void Accessors::ScriptSourceSetter( 408 v8::Local<v8::Name> name, 409 v8::Local<v8::Value> value, 410 const v8::PropertyCallbackInfo<void>& info) { 411 UNREACHABLE(); 412 } 413 414 415 Handle<AccessorInfo> Accessors::ScriptSourceInfo( 416 Isolate* isolate, PropertyAttributes attributes) { 417 return MakeAccessor(isolate, 418 isolate->factory()->source_string(), 419 &ScriptSourceGetter, 420 &ScriptSourceSetter, 421 attributes); 422 } 423 424 425 // 426 // Accessors::ScriptLineOffset 427 // 428 429 430 void Accessors::ScriptLineOffsetGetter( 431 v8::Local<v8::Name> name, 432 const v8::PropertyCallbackInfo<v8::Value>& info) { 433 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 434 DisallowHeapAllocation no_allocation; 435 HandleScope scope(isolate); 436 Object* object = *Utils::OpenHandle(*info.This()); 437 Object* res = 438 Smi::FromInt(Script::cast(JSValue::cast(object)->value())->line_offset()); 439 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate))); 440 } 441 442 443 void Accessors::ScriptLineOffsetSetter( 444 v8::Local<v8::Name> name, 445 v8::Local<v8::Value> value, 446 const v8::PropertyCallbackInfo<void>& info) { 447 UNREACHABLE(); 448 } 449 450 451 Handle<AccessorInfo> Accessors::ScriptLineOffsetInfo( 452 Isolate* isolate, PropertyAttributes attributes) { 453 Handle<String> name(isolate->factory()->InternalizeOneByteString( 454 STATIC_CHAR_VECTOR("line_offset"))); 455 return MakeAccessor(isolate, 456 name, 457 &ScriptLineOffsetGetter, 458 &ScriptLineOffsetSetter, 459 attributes); 460 } 461 462 463 // 464 // Accessors::ScriptType 465 // 466 467 468 void Accessors::ScriptTypeGetter( 469 v8::Local<v8::Name> name, 470 const v8::PropertyCallbackInfo<v8::Value>& info) { 471 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 472 DisallowHeapAllocation no_allocation; 473 HandleScope scope(isolate); 474 Object* object = *Utils::OpenHandle(*info.This()); 475 Object* res = 476 Smi::FromInt(Script::cast(JSValue::cast(object)->value())->type()); 477 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate))); 478 } 479 480 481 void Accessors::ScriptTypeSetter( 482 v8::Local<v8::Name> name, 483 v8::Local<v8::Value> value, 484 const v8::PropertyCallbackInfo<void>& info) { 485 UNREACHABLE(); 486 } 487 488 489 Handle<AccessorInfo> Accessors::ScriptTypeInfo( 490 Isolate* isolate, PropertyAttributes attributes) { 491 Handle<String> name( 492 isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("type"))); 493 return MakeAccessor(isolate, 494 name, 495 &ScriptTypeGetter, 496 &ScriptTypeSetter, 497 attributes); 498 } 499 500 501 // 502 // Accessors::ScriptCompilationType 503 // 504 505 506 void Accessors::ScriptCompilationTypeGetter( 507 v8::Local<v8::Name> name, 508 const v8::PropertyCallbackInfo<v8::Value>& info) { 509 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 510 DisallowHeapAllocation no_allocation; 511 HandleScope scope(isolate); 512 Object* object = *Utils::OpenHandle(*info.This()); 513 Object* res = Smi::FromInt( 514 Script::cast(JSValue::cast(object)->value())->compilation_type()); 515 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate))); 516 } 517 518 519 void Accessors::ScriptCompilationTypeSetter( 520 v8::Local<v8::Name> name, 521 v8::Local<v8::Value> value, 522 const v8::PropertyCallbackInfo<void>& info) { 523 UNREACHABLE(); 524 } 525 526 527 Handle<AccessorInfo> Accessors::ScriptCompilationTypeInfo( 528 Isolate* isolate, PropertyAttributes attributes) { 529 Handle<String> name(isolate->factory()->InternalizeOneByteString( 530 STATIC_CHAR_VECTOR("compilation_type"))); 531 return MakeAccessor(isolate, 532 name, 533 &ScriptCompilationTypeGetter, 534 &ScriptCompilationTypeSetter, 535 attributes); 536 } 537 538 539 // 540 // Accessors::ScriptGetLineEnds 541 // 542 543 544 void Accessors::ScriptLineEndsGetter( 545 v8::Local<v8::Name> name, 546 const v8::PropertyCallbackInfo<v8::Value>& info) { 547 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 548 HandleScope scope(isolate); 549 Handle<Object> object = Utils::OpenHandle(*info.This()); 550 Handle<Script> script( 551 Script::cast(Handle<JSValue>::cast(object)->value()), isolate); 552 Script::InitLineEnds(script); 553 DCHECK(script->line_ends()->IsFixedArray()); 554 Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends())); 555 // We do not want anyone to modify this array from JS. 556 DCHECK(*line_ends == isolate->heap()->empty_fixed_array() || 557 line_ends->map() == isolate->heap()->fixed_cow_array_map()); 558 Handle<JSArray> js_array = 559 isolate->factory()->NewJSArrayWithElements(line_ends); 560 info.GetReturnValue().Set(Utils::ToLocal(js_array)); 561 } 562 563 564 void Accessors::ScriptLineEndsSetter( 565 v8::Local<v8::Name> name, 566 v8::Local<v8::Value> value, 567 const v8::PropertyCallbackInfo<void>& info) { 568 UNREACHABLE(); 569 } 570 571 572 Handle<AccessorInfo> Accessors::ScriptLineEndsInfo( 573 Isolate* isolate, PropertyAttributes attributes) { 574 Handle<String> name(isolate->factory()->InternalizeOneByteString( 575 STATIC_CHAR_VECTOR("line_ends"))); 576 return MakeAccessor(isolate, 577 name, 578 &ScriptLineEndsGetter, 579 &ScriptLineEndsSetter, 580 attributes); 581 } 582 583 584 // 585 // Accessors::ScriptSourceUrl 586 // 587 588 589 void Accessors::ScriptSourceUrlGetter( 590 v8::Local<v8::Name> name, 591 const v8::PropertyCallbackInfo<v8::Value>& info) { 592 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 593 DisallowHeapAllocation no_allocation; 594 HandleScope scope(isolate); 595 Object* object = *Utils::OpenHandle(*info.This()); 596 Object* url = Script::cast(JSValue::cast(object)->value())->source_url(); 597 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(url, isolate))); 598 } 599 600 601 void Accessors::ScriptSourceUrlSetter( 602 v8::Local<v8::Name> name, 603 v8::Local<v8::Value> value, 604 const v8::PropertyCallbackInfo<void>& info) { 605 UNREACHABLE(); 606 } 607 608 609 Handle<AccessorInfo> Accessors::ScriptSourceUrlInfo( 610 Isolate* isolate, PropertyAttributes attributes) { 611 return MakeAccessor(isolate, 612 isolate->factory()->source_url_string(), 613 &ScriptSourceUrlGetter, 614 &ScriptSourceUrlSetter, 615 attributes); 616 } 617 618 619 // 620 // Accessors::ScriptSourceMappingUrl 621 // 622 623 624 void Accessors::ScriptSourceMappingUrlGetter( 625 v8::Local<v8::Name> name, 626 const v8::PropertyCallbackInfo<v8::Value>& info) { 627 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 628 DisallowHeapAllocation no_allocation; 629 HandleScope scope(isolate); 630 Object* object = *Utils::OpenHandle(*info.This()); 631 Object* url = 632 Script::cast(JSValue::cast(object)->value())->source_mapping_url(); 633 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(url, isolate))); 634 } 635 636 637 void Accessors::ScriptSourceMappingUrlSetter( 638 v8::Local<v8::Name> name, 639 v8::Local<v8::Value> value, 640 const v8::PropertyCallbackInfo<void>& info) { 641 UNREACHABLE(); 642 } 643 644 645 Handle<AccessorInfo> Accessors::ScriptSourceMappingUrlInfo( 646 Isolate* isolate, PropertyAttributes attributes) { 647 return MakeAccessor(isolate, 648 isolate->factory()->source_mapping_url_string(), 649 &ScriptSourceMappingUrlGetter, 650 &ScriptSourceMappingUrlSetter, 651 attributes); 652 } 653 654 655 // 656 // Accessors::ScriptIsEmbedderDebugScript 657 // 658 659 660 void Accessors::ScriptIsEmbedderDebugScriptGetter( 661 v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) { 662 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 663 DisallowHeapAllocation no_allocation; 664 HandleScope scope(isolate); 665 Object* object = *Utils::OpenHandle(*info.This()); 666 bool is_embedder_debug_script = Script::cast(JSValue::cast(object)->value()) 667 ->origin_options() 668 .IsEmbedderDebugScript(); 669 Object* res = *isolate->factory()->ToBoolean(is_embedder_debug_script); 670 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate))); 671 } 672 673 674 void Accessors::ScriptIsEmbedderDebugScriptSetter( 675 v8::Local<v8::Name> name, v8::Local<v8::Value> value, 676 const v8::PropertyCallbackInfo<void>& info) { 677 UNREACHABLE(); 678 } 679 680 681 Handle<AccessorInfo> Accessors::ScriptIsEmbedderDebugScriptInfo( 682 Isolate* isolate, PropertyAttributes attributes) { 683 Handle<String> name(isolate->factory()->InternalizeOneByteString( 684 STATIC_CHAR_VECTOR("is_debugger_script"))); 685 return MakeAccessor(isolate, name, &ScriptIsEmbedderDebugScriptGetter, 686 &ScriptIsEmbedderDebugScriptSetter, attributes); 687 } 688 689 690 // 691 // Accessors::ScriptGetContextData 692 // 693 694 695 void Accessors::ScriptContextDataGetter( 696 v8::Local<v8::Name> name, 697 const v8::PropertyCallbackInfo<v8::Value>& info) { 698 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 699 DisallowHeapAllocation no_allocation; 700 HandleScope scope(isolate); 701 Object* object = *Utils::OpenHandle(*info.This()); 702 Object* res = Script::cast(JSValue::cast(object)->value())->context_data(); 703 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate))); 704 } 705 706 707 void Accessors::ScriptContextDataSetter( 708 v8::Local<v8::Name> name, 709 v8::Local<v8::Value> value, 710 const v8::PropertyCallbackInfo<void>& info) { 711 UNREACHABLE(); 712 } 713 714 715 Handle<AccessorInfo> Accessors::ScriptContextDataInfo( 716 Isolate* isolate, PropertyAttributes attributes) { 717 Handle<String> name(isolate->factory()->InternalizeOneByteString( 718 STATIC_CHAR_VECTOR("context_data"))); 719 return MakeAccessor(isolate, 720 name, 721 &ScriptContextDataGetter, 722 &ScriptContextDataSetter, 723 attributes); 724 } 725 726 727 // 728 // Accessors::ScriptGetEvalFromScript 729 // 730 731 732 void Accessors::ScriptEvalFromScriptGetter( 733 v8::Local<v8::Name> name, 734 const v8::PropertyCallbackInfo<v8::Value>& info) { 735 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 736 HandleScope scope(isolate); 737 Handle<Object> object = Utils::OpenHandle(*info.This()); 738 Handle<Script> script( 739 Script::cast(Handle<JSValue>::cast(object)->value()), isolate); 740 Handle<Object> result = isolate->factory()->undefined_value(); 741 if (!script->eval_from_shared()->IsUndefined()) { 742 Handle<SharedFunctionInfo> eval_from_shared( 743 SharedFunctionInfo::cast(script->eval_from_shared())); 744 if (eval_from_shared->script()->IsScript()) { 745 Handle<Script> eval_from_script(Script::cast(eval_from_shared->script())); 746 result = Script::GetWrapper(eval_from_script); 747 } 748 } 749 750 info.GetReturnValue().Set(Utils::ToLocal(result)); 751 } 752 753 754 void Accessors::ScriptEvalFromScriptSetter( 755 v8::Local<v8::Name> name, 756 v8::Local<v8::Value> value, 757 const v8::PropertyCallbackInfo<void>& info) { 758 UNREACHABLE(); 759 } 760 761 762 Handle<AccessorInfo> Accessors::ScriptEvalFromScriptInfo( 763 Isolate* isolate, PropertyAttributes attributes) { 764 Handle<String> name(isolate->factory()->InternalizeOneByteString( 765 STATIC_CHAR_VECTOR("eval_from_script"))); 766 return MakeAccessor(isolate, 767 name, 768 &ScriptEvalFromScriptGetter, 769 &ScriptEvalFromScriptSetter, 770 attributes); 771 } 772 773 774 // 775 // Accessors::ScriptGetEvalFromScriptPosition 776 // 777 778 779 void Accessors::ScriptEvalFromScriptPositionGetter( 780 v8::Local<v8::Name> name, 781 const v8::PropertyCallbackInfo<v8::Value>& info) { 782 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 783 HandleScope scope(isolate); 784 Handle<Object> object = Utils::OpenHandle(*info.This()); 785 Handle<Script> script( 786 Script::cast(Handle<JSValue>::cast(object)->value()), isolate); 787 Handle<Object> result = isolate->factory()->undefined_value(); 788 if (script->compilation_type() == Script::COMPILATION_TYPE_EVAL) { 789 Handle<Code> code(SharedFunctionInfo::cast( 790 script->eval_from_shared())->code()); 791 result = Handle<Object>(Smi::FromInt(code->SourcePosition( 792 code->instruction_start() + 793 script->eval_from_instructions_offset())), 794 isolate); 795 } 796 info.GetReturnValue().Set(Utils::ToLocal(result)); 797 } 798 799 800 void Accessors::ScriptEvalFromScriptPositionSetter( 801 v8::Local<v8::Name> name, 802 v8::Local<v8::Value> value, 803 const v8::PropertyCallbackInfo<void>& info) { 804 UNREACHABLE(); 805 } 806 807 808 Handle<AccessorInfo> Accessors::ScriptEvalFromScriptPositionInfo( 809 Isolate* isolate, PropertyAttributes attributes) { 810 Handle<String> name(isolate->factory()->InternalizeOneByteString( 811 STATIC_CHAR_VECTOR("eval_from_script_position"))); 812 return MakeAccessor(isolate, 813 name, 814 &ScriptEvalFromScriptPositionGetter, 815 &ScriptEvalFromScriptPositionSetter, 816 attributes); 817 } 818 819 820 // 821 // Accessors::ScriptGetEvalFromFunctionName 822 // 823 824 825 void Accessors::ScriptEvalFromFunctionNameGetter( 826 v8::Local<v8::Name> name, 827 const v8::PropertyCallbackInfo<v8::Value>& info) { 828 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 829 HandleScope scope(isolate); 830 Handle<Object> object = Utils::OpenHandle(*info.This()); 831 Handle<Script> script( 832 Script::cast(Handle<JSValue>::cast(object)->value()), isolate); 833 Handle<Object> result; 834 Handle<SharedFunctionInfo> shared( 835 SharedFunctionInfo::cast(script->eval_from_shared())); 836 // Find the name of the function calling eval. 837 if (!shared->name()->IsUndefined()) { 838 result = Handle<Object>(shared->name(), isolate); 839 } else { 840 result = Handle<Object>(shared->inferred_name(), isolate); 841 } 842 info.GetReturnValue().Set(Utils::ToLocal(result)); 843 } 844 845 846 void Accessors::ScriptEvalFromFunctionNameSetter( 847 v8::Local<v8::Name> name, 848 v8::Local<v8::Value> value, 849 const v8::PropertyCallbackInfo<void>& info) { 850 UNREACHABLE(); 851 } 852 853 854 Handle<AccessorInfo> Accessors::ScriptEvalFromFunctionNameInfo( 855 Isolate* isolate, PropertyAttributes attributes) { 856 Handle<String> name(isolate->factory()->InternalizeOneByteString( 857 STATIC_CHAR_VECTOR("eval_from_function_name"))); 858 return MakeAccessor(isolate, 859 name, 860 &ScriptEvalFromFunctionNameGetter, 861 &ScriptEvalFromFunctionNameSetter, 862 attributes); 863 } 864 865 866 // 867 // Accessors::FunctionPrototype 868 // 869 870 static Handle<Object> GetFunctionPrototype(Isolate* isolate, 871 Handle<JSFunction> function) { 872 if (!function->has_prototype()) { 873 Handle<Object> proto = isolate->factory()->NewFunctionPrototype(function); 874 JSFunction::SetPrototype(function, proto); 875 } 876 return Handle<Object>(function->prototype(), isolate); 877 } 878 879 880 MUST_USE_RESULT static MaybeHandle<Object> SetFunctionPrototype( 881 Isolate* isolate, Handle<JSFunction> function, Handle<Object> value) { 882 Handle<Object> old_value; 883 bool is_observed = function->map()->is_observed(); 884 if (is_observed) { 885 if (function->has_prototype()) 886 old_value = handle(function->prototype(), isolate); 887 else 888 old_value = isolate->factory()->NewFunctionPrototype(function); 889 } 890 891 JSFunction::SetPrototype(function, value); 892 DCHECK(function->prototype() == *value); 893 894 if (is_observed && !old_value->SameValue(*value)) { 895 MaybeHandle<Object> result = JSObject::EnqueueChangeRecord( 896 function, "update", isolate->factory()->prototype_string(), old_value); 897 if (result.is_null()) return MaybeHandle<Object>(); 898 } 899 900 return function; 901 } 902 903 904 MaybeHandle<Object> Accessors::FunctionSetPrototype(Handle<JSFunction> function, 905 Handle<Object> prototype) { 906 DCHECK(function->IsConstructor()); 907 Isolate* isolate = function->GetIsolate(); 908 return SetFunctionPrototype(isolate, function, prototype); 909 } 910 911 912 void Accessors::FunctionPrototypeGetter( 913 v8::Local<v8::Name> name, 914 const v8::PropertyCallbackInfo<v8::Value>& info) { 915 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 916 HandleScope scope(isolate); 917 Handle<JSFunction> function = 918 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder())); 919 Handle<Object> result = GetFunctionPrototype(isolate, function); 920 info.GetReturnValue().Set(Utils::ToLocal(result)); 921 } 922 923 924 void Accessors::FunctionPrototypeSetter( 925 v8::Local<v8::Name> name, 926 v8::Local<v8::Value> val, 927 const v8::PropertyCallbackInfo<void>& info) { 928 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 929 HandleScope scope(isolate); 930 Handle<Object> value = Utils::OpenHandle(*val); 931 Handle<JSFunction> object = 932 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder())); 933 if (SetFunctionPrototype(isolate, object, value).is_null()) { 934 isolate->OptionalRescheduleException(false); 935 } 936 } 937 938 939 Handle<AccessorInfo> Accessors::FunctionPrototypeInfo( 940 Isolate* isolate, PropertyAttributes attributes) { 941 return MakeAccessor(isolate, 942 isolate->factory()->prototype_string(), 943 &FunctionPrototypeGetter, 944 &FunctionPrototypeSetter, 945 attributes); 946 } 947 948 949 // 950 // Accessors::FunctionLength 951 // 952 953 954 void Accessors::FunctionLengthGetter( 955 v8::Local<v8::Name> name, 956 const v8::PropertyCallbackInfo<v8::Value>& info) { 957 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 958 HandleScope scope(isolate); 959 Handle<JSFunction> function = 960 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder())); 961 962 int length = 0; 963 if (function->shared()->is_compiled()) { 964 length = function->shared()->length(); 965 } else { 966 // If the function isn't compiled yet, the length is not computed 967 // correctly yet. Compile it now and return the right length. 968 if (Compiler::Compile(function, KEEP_EXCEPTION)) { 969 length = function->shared()->length(); 970 } 971 if (isolate->has_pending_exception()) { 972 isolate->OptionalRescheduleException(false); 973 } 974 } 975 Handle<Object> result(Smi::FromInt(length), isolate); 976 info.GetReturnValue().Set(Utils::ToLocal(result)); 977 } 978 979 980 MUST_USE_RESULT static MaybeHandle<Object> ReplaceAccessorWithDataProperty( 981 Isolate* isolate, Handle<JSObject> object, Handle<Name> name, 982 Handle<Object> value, bool is_observed, Handle<Object> old_value) { 983 LookupIterator it(object, name); 984 CHECK_EQ(LookupIterator::ACCESSOR, it.state()); 985 DCHECK(it.HolderIsReceiverOrHiddenPrototype()); 986 it.ReconfigureDataProperty(value, it.property_details().attributes()); 987 988 if (is_observed && !old_value->SameValue(*value)) { 989 return JSObject::EnqueueChangeRecord(object, "update", name, old_value); 990 } 991 992 return value; 993 } 994 995 996 MUST_USE_RESULT static MaybeHandle<Object> SetFunctionLength( 997 Isolate* isolate, Handle<JSFunction> function, Handle<Object> value) { 998 Handle<Object> old_value; 999 bool is_observed = function->map()->is_observed(); 1000 if (is_observed) { 1001 old_value = handle(Smi::FromInt(function->shared()->length()), isolate); 1002 } 1003 1004 return ReplaceAccessorWithDataProperty(isolate, function, 1005 isolate->factory()->length_string(), 1006 value, is_observed, old_value); 1007 } 1008 1009 1010 void Accessors::FunctionLengthSetter( 1011 v8::Local<v8::Name> name, 1012 v8::Local<v8::Value> val, 1013 const v8::PropertyCallbackInfo<void>& info) { 1014 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 1015 HandleScope scope(isolate); 1016 Handle<Object> value = Utils::OpenHandle(*val); 1017 1018 Handle<JSFunction> object = 1019 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder())); 1020 if (SetFunctionLength(isolate, object, value).is_null()) { 1021 isolate->OptionalRescheduleException(false); 1022 } 1023 } 1024 1025 1026 Handle<AccessorInfo> Accessors::FunctionLengthInfo( 1027 Isolate* isolate, PropertyAttributes attributes) { 1028 return MakeAccessor(isolate, 1029 isolate->factory()->length_string(), 1030 &FunctionLengthGetter, 1031 &FunctionLengthSetter, 1032 attributes); 1033 } 1034 1035 1036 // 1037 // Accessors::FunctionName 1038 // 1039 1040 1041 void Accessors::FunctionNameGetter( 1042 v8::Local<v8::Name> name, 1043 const v8::PropertyCallbackInfo<v8::Value>& info) { 1044 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 1045 HandleScope scope(isolate); 1046 Handle<JSFunction> function = 1047 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder())); 1048 Handle<Object> result; 1049 if (function->shared()->name_should_print_as_anonymous()) { 1050 result = isolate->factory()->anonymous_string(); 1051 } else { 1052 result = handle(function->shared()->name(), isolate); 1053 } 1054 info.GetReturnValue().Set(Utils::ToLocal(result)); 1055 } 1056 1057 1058 MUST_USE_RESULT static MaybeHandle<Object> SetFunctionName( 1059 Isolate* isolate, Handle<JSFunction> function, Handle<Object> value) { 1060 Handle<Object> old_value; 1061 bool is_observed = function->map()->is_observed(); 1062 if (is_observed) { 1063 old_value = handle(function->shared()->name(), isolate); 1064 } 1065 1066 return ReplaceAccessorWithDataProperty(isolate, function, 1067 isolate->factory()->name_string(), 1068 value, is_observed, old_value); 1069 } 1070 1071 1072 void Accessors::FunctionNameSetter( 1073 v8::Local<v8::Name> name, 1074 v8::Local<v8::Value> val, 1075 const v8::PropertyCallbackInfo<void>& info) { 1076 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 1077 HandleScope scope(isolate); 1078 Handle<Object> value = Utils::OpenHandle(*val); 1079 1080 Handle<JSFunction> object = 1081 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder())); 1082 if (SetFunctionName(isolate, object, value).is_null()) { 1083 isolate->OptionalRescheduleException(false); 1084 } 1085 } 1086 1087 1088 Handle<AccessorInfo> Accessors::FunctionNameInfo( 1089 Isolate* isolate, PropertyAttributes attributes) { 1090 return MakeAccessor(isolate, 1091 isolate->factory()->name_string(), 1092 &FunctionNameGetter, 1093 &FunctionNameSetter, 1094 attributes); 1095 } 1096 1097 1098 // 1099 // Accessors::FunctionArguments 1100 // 1101 1102 1103 static Handle<Object> ArgumentsForInlinedFunction( 1104 JavaScriptFrame* frame, 1105 Handle<JSFunction> inlined_function, 1106 int inlined_frame_index) { 1107 Isolate* isolate = inlined_function->GetIsolate(); 1108 Factory* factory = isolate->factory(); 1109 1110 TranslatedState translated_values(frame); 1111 translated_values.Prepare(false, frame->fp()); 1112 1113 int argument_count = 0; 1114 TranslatedFrame* translated_frame = 1115 translated_values.GetArgumentsInfoFromJSFrameIndex(inlined_frame_index, 1116 &argument_count); 1117 TranslatedFrame::iterator iter = translated_frame->begin(); 1118 1119 // Skip the function. 1120 iter++; 1121 1122 // Skip the receiver. 1123 iter++; 1124 argument_count--; 1125 1126 Handle<JSObject> arguments = 1127 factory->NewArgumentsObject(inlined_function, argument_count); 1128 Handle<FixedArray> array = factory->NewFixedArray(argument_count); 1129 bool should_deoptimize = false; 1130 for (int i = 0; i < argument_count; ++i) { 1131 // If we materialize any object, we should deopt because we might alias 1132 // an object that was eliminated by escape analysis. 1133 should_deoptimize = should_deoptimize || iter->IsMaterializedObject(); 1134 Handle<Object> value = iter->GetValue(); 1135 array->set(i, *value); 1136 iter++; 1137 } 1138 arguments->set_elements(*array); 1139 1140 if (should_deoptimize) { 1141 translated_values.StoreMaterializedValuesAndDeopt(); 1142 } 1143 1144 // Return the freshly allocated arguments object. 1145 return arguments; 1146 } 1147 1148 1149 static int FindFunctionInFrame(JavaScriptFrame* frame, 1150 Handle<JSFunction> function) { 1151 DisallowHeapAllocation no_allocation; 1152 List<JSFunction*> functions(2); 1153 frame->GetFunctions(&functions); 1154 for (int i = functions.length() - 1; i >= 0; i--) { 1155 if (functions[i] == *function) return i; 1156 } 1157 return -1; 1158 } 1159 1160 1161 Handle<Object> GetFunctionArguments(Isolate* isolate, 1162 Handle<JSFunction> function) { 1163 if (function->shared()->native()) return isolate->factory()->null_value(); 1164 1165 // Find the top invocation of the function by traversing frames. 1166 for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) { 1167 JavaScriptFrame* frame = it.frame(); 1168 int function_index = FindFunctionInFrame(frame, function); 1169 if (function_index < 0) continue; 1170 1171 if (function_index > 0) { 1172 // The function in question was inlined. Inlined functions have the 1173 // correct number of arguments and no allocated arguments object, so 1174 // we can construct a fresh one by interpreting the function's 1175 // deoptimization input data. 1176 return ArgumentsForInlinedFunction(frame, function, function_index); 1177 } 1178 1179 // Find the frame that holds the actual arguments passed to the function. 1180 it.AdvanceToArgumentsFrame(); 1181 frame = it.frame(); 1182 1183 // Get the number of arguments and construct an arguments object 1184 // mirror for the right frame. 1185 const int length = frame->ComputeParametersCount(); 1186 Handle<JSObject> arguments = isolate->factory()->NewArgumentsObject( 1187 function, length); 1188 Handle<FixedArray> array = isolate->factory()->NewFixedArray(length); 1189 1190 // Copy the parameters to the arguments object. 1191 DCHECK(array->length() == length); 1192 for (int i = 0; i < length; i++) array->set(i, frame->GetParameter(i)); 1193 arguments->set_elements(*array); 1194 1195 // Return the freshly allocated arguments object. 1196 return arguments; 1197 } 1198 1199 // No frame corresponding to the given function found. Return null. 1200 return isolate->factory()->null_value(); 1201 } 1202 1203 1204 Handle<Object> Accessors::FunctionGetArguments(Handle<JSFunction> function) { 1205 return GetFunctionArguments(function->GetIsolate(), function); 1206 } 1207 1208 1209 void Accessors::FunctionArgumentsGetter( 1210 v8::Local<v8::Name> name, 1211 const v8::PropertyCallbackInfo<v8::Value>& info) { 1212 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 1213 HandleScope scope(isolate); 1214 Handle<JSFunction> function = 1215 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder())); 1216 Handle<Object> result = GetFunctionArguments(isolate, function); 1217 info.GetReturnValue().Set(Utils::ToLocal(result)); 1218 } 1219 1220 1221 void Accessors::FunctionArgumentsSetter( 1222 v8::Local<v8::Name> name, 1223 v8::Local<v8::Value> val, 1224 const v8::PropertyCallbackInfo<void>& info) { 1225 // Function arguments is non writable, non configurable. 1226 UNREACHABLE(); 1227 } 1228 1229 1230 Handle<AccessorInfo> Accessors::FunctionArgumentsInfo( 1231 Isolate* isolate, PropertyAttributes attributes) { 1232 return MakeAccessor(isolate, 1233 isolate->factory()->arguments_string(), 1234 &FunctionArgumentsGetter, 1235 &FunctionArgumentsSetter, 1236 attributes); 1237 } 1238 1239 1240 // 1241 // Accessors::FunctionCaller 1242 // 1243 1244 1245 static inline bool AllowAccessToFunction(Context* current_context, 1246 JSFunction* function) { 1247 return current_context->HasSameSecurityTokenAs(function->context()); 1248 } 1249 1250 1251 class FrameFunctionIterator { 1252 public: 1253 FrameFunctionIterator(Isolate* isolate, const DisallowHeapAllocation& promise) 1254 : isolate_(isolate), 1255 frame_iterator_(isolate), 1256 functions_(2), 1257 index_(0) { 1258 GetFunctions(); 1259 } 1260 JSFunction* next() { 1261 while (true) { 1262 if (functions_.length() == 0) return NULL; 1263 JSFunction* next_function = functions_[index_]; 1264 index_--; 1265 if (index_ < 0) { 1266 GetFunctions(); 1267 } 1268 // Skip functions from other origins. 1269 if (!AllowAccessToFunction(isolate_->context(), next_function)) continue; 1270 return next_function; 1271 } 1272 } 1273 1274 // Iterate through functions until the first occurence of 'function'. 1275 // Returns true if 'function' is found, and false if the iterator ends 1276 // without finding it. 1277 bool Find(JSFunction* function) { 1278 JSFunction* next_function; 1279 do { 1280 next_function = next(); 1281 if (next_function == function) return true; 1282 } while (next_function != NULL); 1283 return false; 1284 } 1285 1286 private: 1287 void GetFunctions() { 1288 functions_.Rewind(0); 1289 if (frame_iterator_.done()) return; 1290 JavaScriptFrame* frame = frame_iterator_.frame(); 1291 frame->GetFunctions(&functions_); 1292 DCHECK(functions_.length() > 0); 1293 frame_iterator_.Advance(); 1294 index_ = functions_.length() - 1; 1295 } 1296 Isolate* isolate_; 1297 JavaScriptFrameIterator frame_iterator_; 1298 List<JSFunction*> functions_; 1299 int index_; 1300 }; 1301 1302 1303 MaybeHandle<JSFunction> FindCaller(Isolate* isolate, 1304 Handle<JSFunction> function) { 1305 DisallowHeapAllocation no_allocation; 1306 FrameFunctionIterator it(isolate, no_allocation); 1307 if (function->shared()->native()) { 1308 return MaybeHandle<JSFunction>(); 1309 } 1310 // Find the function from the frames. 1311 if (!it.Find(*function)) { 1312 // No frame corresponding to the given function found. Return null. 1313 return MaybeHandle<JSFunction>(); 1314 } 1315 // Find previously called non-toplevel function. 1316 JSFunction* caller; 1317 do { 1318 caller = it.next(); 1319 if (caller == NULL) return MaybeHandle<JSFunction>(); 1320 } while (caller->shared()->is_toplevel()); 1321 1322 // If caller is a built-in function and caller's caller is also built-in, 1323 // use that instead. 1324 JSFunction* potential_caller = caller; 1325 while (potential_caller != NULL && potential_caller->shared()->IsBuiltin()) { 1326 caller = potential_caller; 1327 potential_caller = it.next(); 1328 } 1329 if (!caller->shared()->native() && potential_caller != NULL) { 1330 caller = potential_caller; 1331 } 1332 // Censor if the caller is not a sloppy mode function. 1333 // Change from ES5, which used to throw, see: 1334 // https://bugs.ecmascript.org/show_bug.cgi?id=310 1335 if (is_strict(caller->shared()->language_mode())) { 1336 return MaybeHandle<JSFunction>(); 1337 } 1338 // Don't return caller from another security context. 1339 if (!AllowAccessToFunction(isolate->context(), caller)) { 1340 return MaybeHandle<JSFunction>(); 1341 } 1342 return Handle<JSFunction>(caller); 1343 } 1344 1345 1346 void Accessors::FunctionCallerGetter( 1347 v8::Local<v8::Name> name, 1348 const v8::PropertyCallbackInfo<v8::Value>& info) { 1349 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 1350 HandleScope scope(isolate); 1351 Handle<JSFunction> function = 1352 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder())); 1353 Handle<Object> result; 1354 MaybeHandle<JSFunction> maybe_caller; 1355 maybe_caller = FindCaller(isolate, function); 1356 Handle<JSFunction> caller; 1357 if (maybe_caller.ToHandle(&caller)) { 1358 result = caller; 1359 } else { 1360 result = isolate->factory()->null_value(); 1361 } 1362 info.GetReturnValue().Set(Utils::ToLocal(result)); 1363 } 1364 1365 1366 void Accessors::FunctionCallerSetter( 1367 v8::Local<v8::Name> name, 1368 v8::Local<v8::Value> val, 1369 const v8::PropertyCallbackInfo<void>& info) { 1370 // Function caller is non writable, non configurable. 1371 UNREACHABLE(); 1372 } 1373 1374 1375 Handle<AccessorInfo> Accessors::FunctionCallerInfo( 1376 Isolate* isolate, PropertyAttributes attributes) { 1377 return MakeAccessor(isolate, 1378 isolate->factory()->caller_string(), 1379 &FunctionCallerGetter, 1380 &FunctionCallerSetter, 1381 attributes); 1382 } 1383 1384 1385 // 1386 // Accessors::MakeModuleExport 1387 // 1388 1389 static void ModuleGetExport( 1390 v8::Local<v8::String> property, 1391 const v8::PropertyCallbackInfo<v8::Value>& info) { 1392 JSModule* instance = JSModule::cast(*v8::Utils::OpenHandle(*info.Holder())); 1393 Context* context = Context::cast(instance->context()); 1394 DCHECK(context->IsModuleContext()); 1395 Isolate* isolate = instance->GetIsolate(); 1396 int slot = info.Data() 1397 ->Int32Value(info.GetIsolate()->GetCurrentContext()) 1398 .FromMaybe(-1); 1399 if (slot < 0 || slot >= context->length()) { 1400 Handle<String> name = v8::Utils::OpenHandle(*property); 1401 1402 Handle<Object> exception = isolate->factory()->NewReferenceError( 1403 MessageTemplate::kNotDefined, name); 1404 isolate->ScheduleThrow(*exception); 1405 return; 1406 } 1407 Object* value = context->get(slot); 1408 if (value->IsTheHole()) { 1409 Handle<String> name = v8::Utils::OpenHandle(*property); 1410 1411 Handle<Object> exception = isolate->factory()->NewReferenceError( 1412 MessageTemplate::kNotDefined, name); 1413 isolate->ScheduleThrow(*exception); 1414 return; 1415 } 1416 info.GetReturnValue().Set(v8::Utils::ToLocal(Handle<Object>(value, isolate))); 1417 } 1418 1419 1420 static void ModuleSetExport( 1421 v8::Local<v8::String> property, 1422 v8::Local<v8::Value> value, 1423 const v8::PropertyCallbackInfo<v8::Value>& info) { 1424 JSModule* instance = JSModule::cast(*v8::Utils::OpenHandle(*info.Holder())); 1425 Context* context = Context::cast(instance->context()); 1426 DCHECK(context->IsModuleContext()); 1427 Isolate* isolate = instance->GetIsolate(); 1428 int slot = info.Data() 1429 ->Int32Value(info.GetIsolate()->GetCurrentContext()) 1430 .FromMaybe(-1); 1431 if (slot < 0 || slot >= context->length()) { 1432 Handle<String> name = v8::Utils::OpenHandle(*property); 1433 Handle<Object> exception = isolate->factory()->NewReferenceError( 1434 MessageTemplate::kNotDefined, name); 1435 isolate->ScheduleThrow(*exception); 1436 return; 1437 } 1438 Object* old_value = context->get(slot); 1439 if (old_value->IsTheHole()) { 1440 Handle<String> name = v8::Utils::OpenHandle(*property); 1441 Handle<Object> exception = isolate->factory()->NewReferenceError( 1442 MessageTemplate::kNotDefined, name); 1443 isolate->ScheduleThrow(*exception); 1444 return; 1445 } 1446 context->set(slot, *v8::Utils::OpenHandle(*value)); 1447 } 1448 1449 1450 Handle<AccessorInfo> Accessors::MakeModuleExport( 1451 Handle<String> name, 1452 int index, 1453 PropertyAttributes attributes) { 1454 Isolate* isolate = name->GetIsolate(); 1455 Factory* factory = isolate->factory(); 1456 Handle<ExecutableAccessorInfo> info = factory->NewExecutableAccessorInfo(); 1457 info->set_property_attributes(attributes); 1458 info->set_all_can_read(true); 1459 info->set_all_can_write(true); 1460 info->set_name(*name); 1461 info->set_data(Smi::FromInt(index)); 1462 Handle<Object> getter = v8::FromCData(isolate, &ModuleGetExport); 1463 Handle<Object> setter = v8::FromCData(isolate, &ModuleSetExport); 1464 info->set_getter(*getter); 1465 if (!(attributes & ReadOnly)) info->set_setter(*setter); 1466 return info; 1467 } 1468 1469 1470 } // namespace internal 1471 } // namespace v8 1472