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