Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(81)

Side by Side Diff: src/objects.cc

Issue 906463002: add support for all can read interceptors (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <sstream> 5 #include <sstream>
6 6
7 #include "src/v8.h" 7 #include "src/v8.h"
8 8
9 #include "src/accessors.h" 9 #include "src/accessors.h"
10 #include "src/allocation-site-scopes.h" 10 #include "src/allocation-site-scopes.h"
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after
426 426
427 Handle<Object> argv[] = { value }; 427 Handle<Object> argv[] = { value };
428 RETURN_ON_EXCEPTION(isolate, Execution::Call(isolate, setter, receiver, 428 RETURN_ON_EXCEPTION(isolate, Execution::Call(isolate, setter, receiver,
429 arraysize(argv), argv, true), 429 arraysize(argv), argv, true),
430 Object); 430 Object);
431 return value; 431 return value;
432 } 432 }
433 433
434 434
435 static bool FindAllCanReadHolder(LookupIterator* it) { 435 static bool FindAllCanReadHolder(LookupIterator* it) {
436 for (; it->IsFound(); it->Next()) { 436 // Skip current iteration, it's in state ACCESS_CHECK or INTERCEPTOR, both of
437 // which have already been checked.
438 DCHECK(it->state() == LookupIterator::ACCESS_CHECK ||
439 it->state() == LookupIterator::INTERCEPTOR);
440 for (it->Next(); it->IsFound(); it->Next()) {
437 if (it->state() == LookupIterator::ACCESSOR) { 441 if (it->state() == LookupIterator::ACCESSOR) {
438 Handle<Object> accessors = it->GetAccessors(); 442 auto accessors = it->GetAccessors();
439 if (accessors->IsAccessorInfo()) { 443 if (accessors->IsAccessorInfo()) {
440 if (AccessorInfo::cast(*accessors)->all_can_read()) return true; 444 if (AccessorInfo::cast(*accessors)->all_can_read()) return true;
441 } 445 }
446 } else if (it->state() == LookupIterator::INTERCEPTOR) {
447 auto holder = it->GetHolder<JSObject>();
448 if (holder->GetNamedInterceptor()->all_can_read()) return true;
442 } 449 }
443 } 450 }
444 return false; 451 return false;
445 } 452 }
446 453
447 454
448 MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck( 455 MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
449 LookupIterator* it) { 456 LookupIterator* it) {
450 Handle<JSObject> checked = it->GetHolder<JSObject>(); 457 Handle<JSObject> checked = it->GetHolder<JSObject>();
451 if (FindAllCanReadHolder(it)) { 458 while (FindAllCanReadHolder(it)) {
452 return GetPropertyWithAccessor(it->GetReceiver(), it->name(), 459 if (it->state() == LookupIterator::ACCESSOR) {
453 it->GetHolder<JSObject>(), 460 return GetPropertyWithAccessor(it->GetReceiver(), it->name(),
454 it->GetAccessors()); 461 it->GetHolder<JSObject>(),
462 it->GetAccessors());
463 }
464 DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
465 auto receiver = Handle<JSObject>::cast(it->GetReceiver());
466 auto result = GetPropertyWithInterceptor(it->GetHolder<JSObject>(),
467 receiver, it->name());
468 if (it->isolate()->has_scheduled_exception()) break;
469 if (!result.is_null()) return result;
455 } 470 }
456 it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_GET); 471 it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_GET);
457 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object); 472 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
458 return it->factory()->undefined_value(); 473 return it->factory()->undefined_value();
459 } 474 }
460 475
461 476
462 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck( 477 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck(
463 LookupIterator* it) { 478 LookupIterator* it) {
464 Handle<JSObject> checked = it->GetHolder<JSObject>(); 479 Handle<JSObject> checked = it->GetHolder<JSObject>();
465 if (FindAllCanReadHolder(it)) 480 while (FindAllCanReadHolder(it)) {
466 return maybe(it->property_details().attributes()); 481 if (it->state() == LookupIterator::ACCESSOR) {
482 return maybe(it->property_details().attributes());
483 }
484 DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
485 auto result = GetPropertyAttributesWithInterceptor(
486 it->GetHolder<JSObject>(), it->GetReceiver(), it->name());
487 if (it->isolate()->has_scheduled_exception()) break;
488 if (result.has_value && result.value != ABSENT) return result;
489 }
467 it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_HAS); 490 it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_HAS);
468 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), 491 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(),
469 Maybe<PropertyAttributes>()); 492 Maybe<PropertyAttributes>());
470 return maybe(ABSENT); 493 return maybe(ABSENT);
471 } 494 }
472 495
473 496
474 static bool FindAllCanWriteHolder(LookupIterator* it) { 497 static bool FindAllCanWriteHolder(LookupIterator* it) {
475 for (; it->IsFound(); it->Next()) { 498 for (; it->IsFound(); it->Next()) {
476 if (it->state() == LookupIterator::ACCESSOR) { 499 if (it->state() == LookupIterator::ACCESSOR) {
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
543 PropertyCell::cast(property_dictionary->ValueAt(entry))); 566 PropertyCell::cast(property_dictionary->ValueAt(entry)));
544 PropertyCell::SetValueInferType(cell, value); 567 PropertyCell::SetValueInferType(cell, value);
545 // Please note we have to update the property details. 568 // Please note we have to update the property details.
546 property_dictionary->DetailsAtPut(entry, details); 569 property_dictionary->DetailsAtPut(entry, details);
547 } else { 570 } else {
548 property_dictionary->SetEntry(entry, name, value, details); 571 property_dictionary->SetEntry(entry, name, value, details);
549 } 572 }
550 } 573 }
551 574
552 575
576 static MaybeHandle<JSObject> FindIndexedAllCanReadHolder(
577 Isolate* isolate, Handle<JSObject> js_object,
578 PrototypeIterator::WhereToStart where_to_start) {
579 for (PrototypeIterator iter(isolate, js_object, where_to_start);
580 !iter.IsAtEnd(); iter.Advance()) {
581 auto curr = PrototypeIterator::GetCurrent(iter);
582 if (!curr->IsJSObject()) break;
583 auto obj = Handle<JSObject>::cast(curr);
584 if (!obj->HasIndexedInterceptor()) continue;
585 if (obj->GetIndexedInterceptor()->all_can_read()) return obj;
586 }
587 return MaybeHandle<JSObject>();
588 }
589
590
591 MaybeHandle<Object> JSObject::GetElementWithFailedAccessCheck(
592 Isolate* isolate, Handle<JSObject> object, Handle<Object> receiver,
593 uint32_t index) {
594 Handle<JSObject> holder = object;
595 PrototypeIterator::WhereToStart where_to_start =
596 PrototypeIterator::START_AT_RECEIVER;
597 while (true) {
598 auto all_can_read_holder =
599 FindIndexedAllCanReadHolder(isolate, holder, where_to_start);
600 if (!all_can_read_holder.ToHandle(&holder)) break;
601 auto result =
602 JSObject::GetElementWithInterceptor(holder, receiver, index, false);
603 if (isolate->has_scheduled_exception()) break;
604 if (!result.is_null()) return result;
605 where_to_start = PrototypeIterator::START_AT_PROTOTYPE;
606 }
607 isolate->ReportFailedAccessCheck(object, v8::ACCESS_GET);
608 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
609 return isolate->factory()->undefined_value();
610 }
611
612
613 Maybe<PropertyAttributes> JSObject::GetElementAttributesWithFailedAccessCheck(
614 Isolate* isolate, Handle<JSObject> object, Handle<Object> receiver,
615 uint32_t index) {
616 Handle<JSObject> holder = object;
617 PrototypeIterator::WhereToStart where_to_start =
618 PrototypeIterator::START_AT_RECEIVER;
619 while (true) {
620 auto all_can_read_holder =
621 FindIndexedAllCanReadHolder(isolate, holder, where_to_start);
622 if (!all_can_read_holder.ToHandle(&holder)) break;
623 auto result =
624 JSObject::GetElementAttributeFromInterceptor(object, receiver, index);
625 if (isolate->has_scheduled_exception()) break;
626 if (result.has_value && result.value != ABSENT) return result;
627 where_to_start = PrototypeIterator::START_AT_PROTOTYPE;
628 }
629 isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
630 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<PropertyAttributes>());
631 return maybe(ABSENT);
632 }
633
634
553 MaybeHandle<Object> Object::GetElementWithReceiver(Isolate* isolate, 635 MaybeHandle<Object> Object::GetElementWithReceiver(Isolate* isolate,
554 Handle<Object> object, 636 Handle<Object> object,
555 Handle<Object> receiver, 637 Handle<Object> receiver,
556 uint32_t index) { 638 uint32_t index) {
557 if (object->IsUndefined()) { 639 if (object->IsUndefined()) {
558 // TODO(verwaest): Why is this check here? 640 // TODO(verwaest): Why is this check here?
559 UNREACHABLE(); 641 UNREACHABLE();
560 return isolate->factory()->undefined_value(); 642 return isolate->factory()->undefined_value();
561 } 643 }
562 644
(...skipping 12 matching lines...) Expand all
575 657
576 // Inline the case for JSObjects. Doing so significantly improves the 658 // Inline the case for JSObjects. Doing so significantly improves the
577 // performance of fetching elements where checking the prototype chain is 659 // performance of fetching elements where checking the prototype chain is
578 // necessary. 660 // necessary.
579 Handle<JSObject> js_object = 661 Handle<JSObject> js_object =
580 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); 662 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
581 663
582 // Check access rights if needed. 664 // Check access rights if needed.
583 if (js_object->IsAccessCheckNeeded()) { 665 if (js_object->IsAccessCheckNeeded()) {
584 if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_GET)) { 666 if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_GET)) {
585 isolate->ReportFailedAccessCheck(js_object, v8::ACCESS_GET); 667 return JSObject::GetElementWithFailedAccessCheck(isolate, js_object,
586 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); 668 receiver, index);
587 return isolate->factory()->undefined_value();
588 } 669 }
589 } 670 }
590 671
591 if (js_object->HasIndexedInterceptor()) { 672 if (js_object->HasIndexedInterceptor()) {
592 return JSObject::GetElementWithInterceptor(js_object, receiver, index); 673 return JSObject::GetElementWithInterceptor(js_object, receiver, index,
674 true);
593 } 675 }
594 676
595 if (js_object->elements() != isolate->heap()->empty_fixed_array()) { 677 if (js_object->elements() != isolate->heap()->empty_fixed_array()) {
596 Handle<Object> result; 678 Handle<Object> result;
597 ASSIGN_RETURN_ON_EXCEPTION( 679 ASSIGN_RETURN_ON_EXCEPTION(
598 isolate, result, 680 isolate, result,
599 js_object->GetElementsAccessor()->Get(receiver, js_object, index), 681 js_object->GetElementsAccessor()->Get(receiver, js_object, index),
600 Object); 682 Object);
601 if (!result->IsTheHole()) return result; 683 if (!result->IsTheHole()) return result;
602 } 684 }
(...skipping 3402 matching lines...) Expand 10 before | Expand all | Expand 10 after
4005 4087
4006 4088
4007 Maybe<PropertyAttributes> JSObject::GetElementAttributeWithReceiver( 4089 Maybe<PropertyAttributes> JSObject::GetElementAttributeWithReceiver(
4008 Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index, 4090 Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index,
4009 bool check_prototype) { 4091 bool check_prototype) {
4010 Isolate* isolate = object->GetIsolate(); 4092 Isolate* isolate = object->GetIsolate();
4011 4093
4012 // Check access rights if needed. 4094 // Check access rights if needed.
4013 if (object->IsAccessCheckNeeded()) { 4095 if (object->IsAccessCheckNeeded()) {
4014 if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_HAS)) { 4096 if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_HAS)) {
4015 isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS); 4097 return GetElementAttributesWithFailedAccessCheck(isolate, object,
4016 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<PropertyAttributes>()); 4098 receiver, index);
4017 return maybe(ABSENT);
4018 } 4099 }
4019 } 4100 }
4020 4101
4021 if (object->IsJSGlobalProxy()) { 4102 if (object->IsJSGlobalProxy()) {
4022 PrototypeIterator iter(isolate, object); 4103 PrototypeIterator iter(isolate, object);
4023 if (iter.IsAtEnd()) return maybe(ABSENT); 4104 if (iter.IsAtEnd()) return maybe(ABSENT);
4024 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); 4105 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
4025 return JSObject::GetElementAttributeWithReceiver( 4106 return JSObject::GetElementAttributeWithReceiver(
4026 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), receiver, 4107 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), receiver,
4027 index, check_prototype); 4108 index, check_prototype);
(...skipping 9229 matching lines...) Expand 10 before | Expand all | Expand 10 after
13257 MaybeHandle<Object> JSArray::ReadOnlyLengthError(Handle<JSArray> array) { 13338 MaybeHandle<Object> JSArray::ReadOnlyLengthError(Handle<JSArray> array) {
13258 Isolate* isolate = array->GetIsolate(); 13339 Isolate* isolate = array->GetIsolate();
13259 Handle<Name> length = isolate->factory()->length_string(); 13340 Handle<Name> length = isolate->factory()->length_string();
13260 Handle<Object> args[2] = { length, array }; 13341 Handle<Object> args[2] = { length, array };
13261 THROW_NEW_ERROR(isolate, NewTypeError("strict_read_only_property", 13342 THROW_NEW_ERROR(isolate, NewTypeError("strict_read_only_property",
13262 HandleVector(args, arraysize(args))), 13343 HandleVector(args, arraysize(args))),
13263 Object); 13344 Object);
13264 } 13345 }
13265 13346
13266 13347
13267 MaybeHandle<Object> JSObject::GetElementWithInterceptor( 13348 MaybeHandle<Object> JSObject::GetElementWithInterceptor(Handle<JSObject> object,
13268 Handle<JSObject> object, 13349 Handle<Object> receiver,
13269 Handle<Object> receiver, 13350 uint32_t index,
13270 uint32_t index) { 13351 bool check_prototype) {
13271 Isolate* isolate = object->GetIsolate(); 13352 Isolate* isolate = object->GetIsolate();
13272 13353
13273 // Make sure that the top context does not change when doing 13354 // Make sure that the top context does not change when doing
13274 // callbacks or interceptor calls. 13355 // callbacks or interceptor calls.
13275 AssertNoContextChange ncc(isolate); 13356 AssertNoContextChange ncc(isolate);
13276 13357
13277 Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor(), isolate); 13358 Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor(), isolate);
13278 if (!interceptor->getter()->IsUndefined()) { 13359 if (!interceptor->getter()->IsUndefined()) {
13279 v8::IndexedPropertyGetterCallback getter = 13360 v8::IndexedPropertyGetterCallback getter =
13280 v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter()); 13361 v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
13281 LOG(isolate, 13362 LOG(isolate,
13282 ApiIndexedPropertyAccess("interceptor-indexed-get", *object, index)); 13363 ApiIndexedPropertyAccess("interceptor-indexed-get", *object, index));
13283 PropertyCallbackArguments 13364 PropertyCallbackArguments
13284 args(isolate, interceptor->data(), *receiver, *object); 13365 args(isolate, interceptor->data(), *receiver, *object);
13285 v8::Handle<v8::Value> result = args.Call(getter, index); 13366 v8::Handle<v8::Value> result = args.Call(getter, index);
13286 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); 13367 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
13287 if (!result.IsEmpty()) { 13368 if (!result.IsEmpty()) {
13288 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); 13369 Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
13289 result_internal->VerifyApiCallResultType(); 13370 result_internal->VerifyApiCallResultType();
13290 // Rebox handle before return. 13371 // Rebox handle before return.
13291 return handle(*result_internal, isolate); 13372 return handle(*result_internal, isolate);
13292 } 13373 }
13293 } 13374 }
13294 13375
13376 if (!check_prototype) return MaybeHandle<Object>();
13377
13295 ElementsAccessor* handler = object->GetElementsAccessor(); 13378 ElementsAccessor* handler = object->GetElementsAccessor();
13296 Handle<Object> result; 13379 Handle<Object> result;
13297 ASSIGN_RETURN_ON_EXCEPTION( 13380 ASSIGN_RETURN_ON_EXCEPTION(
13298 isolate, result, handler->Get(receiver, object, index), 13381 isolate, result, handler->Get(receiver, object, index),
13299 Object); 13382 Object);
13300 if (!result->IsTheHole()) return result; 13383 if (!result->IsTheHole()) return result;
13301 13384
13302 PrototypeIterator iter(isolate, object); 13385 PrototypeIterator iter(isolate, object);
13303 if (iter.IsAtEnd()) return isolate->factory()->undefined_value(); 13386 if (iter.IsAtEnd()) return isolate->factory()->undefined_value();
13304 return Object::GetElementWithReceiver( 13387 return Object::GetElementWithReceiver(
(...skipping 3572 matching lines...) Expand 10 before | Expand all | Expand 10 after
16877 Handle<DependentCode> codes = 16960 Handle<DependentCode> codes =
16878 DependentCode::Insert(handle(cell->dependent_code(), info->isolate()), 16961 DependentCode::Insert(handle(cell->dependent_code(), info->isolate()),
16879 DependentCode::kPropertyCellChangedGroup, 16962 DependentCode::kPropertyCellChangedGroup,
16880 info->object_wrapper()); 16963 info->object_wrapper());
16881 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); 16964 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes);
16882 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( 16965 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add(
16883 cell, info->zone()); 16966 cell, info->zone());
16884 } 16967 }
16885 16968
16886 } } // namespace v8::internal 16969 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698