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

Side by Side Diff: src/objects.cc

Issue 7035007: Implement get trap for proxies. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Implementing get trap for proxies. Created 9 years, 7 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 if (heap_object->IsHeapNumber()) { 127 if (heap_object->IsHeapNumber()) {
128 return HeapNumber::cast(this)->HeapNumberToBoolean(); 128 return HeapNumber::cast(this)->HeapNumberToBoolean();
129 } 129 }
130 return heap_object->GetHeap()->true_value(); 130 return heap_object->GetHeap()->true_value();
131 } 131 }
132 132
133 133
134 void Object::Lookup(String* name, LookupResult* result) { 134 void Object::Lookup(String* name, LookupResult* result) {
135 Object* holder = NULL; 135 Object* holder = NULL;
136 if (IsSmi()) { 136 if (IsSmi()) {
137 Heap* heap = Isolate::Current()->heap(); 137 Context* global_context = Isolate::Current()->context()->global_context();
138 Context* global_context = heap->isolate()->context()->global_context();
139 holder = global_context->number_function()->instance_prototype(); 138 holder = global_context->number_function()->instance_prototype();
140 } else { 139 } else {
141 HeapObject* heap_object = HeapObject::cast(this); 140 HeapObject* heap_object = HeapObject::cast(this);
142 if (heap_object->IsJSObject()) { 141 if (heap_object->IsJSObject()) {
143 return JSObject::cast(this)->Lookup(name, result); 142 return JSObject::cast(this)->Lookup(name, result);
144 } 143 }
145 Heap* heap = heap_object->GetHeap(); 144 Context* global_context = Isolate::Current()->context()->global_context();
146 if (heap_object->IsString()) { 145 if (heap_object->IsString()) {
147 Context* global_context = heap->isolate()->context()->global_context();
148 holder = global_context->string_function()->instance_prototype(); 146 holder = global_context->string_function()->instance_prototype();
149 } else if (heap_object->IsHeapNumber()) { 147 } else if (heap_object->IsHeapNumber()) {
150 Context* global_context = heap->isolate()->context()->global_context();
151 holder = global_context->number_function()->instance_prototype(); 148 holder = global_context->number_function()->instance_prototype();
152 } else if (heap_object->IsBoolean()) { 149 } else if (heap_object->IsBoolean()) {
153 Context* global_context = heap->isolate()->context()->global_context();
154 holder = global_context->boolean_function()->instance_prototype(); 150 holder = global_context->boolean_function()->instance_prototype();
151 } else if (heap_object->IsJSProxy()) {
152 return result->HandlerResult();
155 } 153 }
156 } 154 }
157 ASSERT(holder != NULL); // Cannot handle null or undefined. 155 ASSERT(holder != NULL); // Cannot handle null or undefined.
158 JSObject::cast(holder)->Lookup(name, result); 156 JSObject::cast(holder)->Lookup(name, result);
159 } 157 }
160 158
161 159
162 MaybeObject* Object::GetPropertyWithReceiver(Object* receiver, 160 MaybeObject* Object::GetPropertyWithReceiver(Object* receiver,
163 String* name, 161 String* name,
164 PropertyAttributes* attributes) { 162 PropertyAttributes* attributes) {
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 } 218 }
221 // Getter is not a function. 219 // Getter is not a function.
222 return isolate->heap()->undefined_value(); 220 return isolate->heap()->undefined_value();
223 } 221 }
224 222
225 UNREACHABLE(); 223 UNREACHABLE();
226 return NULL; 224 return NULL;
227 } 225 }
228 226
229 227
228 MaybeObject* Object::GetPropertyWithHandler(Object* receiver_raw,
229 String* name_raw,
230 Object* handler_raw) {
231 Isolate* isolate = name_raw->GetIsolate();
232 HandleScope scope;
233 Handle<Object> receiver(receiver_raw);
234 Handle<Object> name(name_raw);
235 Handle<Object> handler(handler_raw);
236
237 // Extract trap function.
238 LookupResult lookup;
239 Handle<Object> trap(v8::internal::GetProperty(handler, "get", &lookup));
240 if (!lookup.IsFound()) {
241 // Get the derived `get' property.
242 Object* derived = isolate->global_context()->builtins()->javascript_builtin(
243 Builtins::DERIVED_GET_TRAP);
244 trap = Handle<JSFunction>(JSFunction::cast(derived));
245 // Handle<String> method = isolate->factory()->LookupAsciiSymbol("get");
Kevin Millikin (Chromium) 2011/05/16 15:21:41 Is the commented-out code still needed?
rossberg 2011/05/16 15:54:37 Done.
246 // Handle<Object> args[] = { handler, method };
247 // Handle<Object> error = isolate->factory()->NewTypeError(
248 // "handler_trap_missing", HandleVector(args, ARRAY_SIZE(args)));
249 // return isolate->Throw(*error);
250 }
251
252 // to install JS objects:
253 // - add to builtins.h BUILTINS_LIST_JS
254 // - implement builtin in runtime.js
255 // - get it through isolate()->global_context()->builtins()->javascript_builti n(id)
256
257 // Call trap function.
258 Object** args[] = { receiver.location(), name.location() };
259 bool has_exception;
260 Handle<Object> result =
261 Execution::Call(trap, handler, ARRAY_SIZE(args), args, &has_exception);
262 if (has_exception) return Failure::Exception();
263
264 return *result;
265 }
266
267
230 MaybeObject* Object::GetPropertyWithDefinedGetter(Object* receiver, 268 MaybeObject* Object::GetPropertyWithDefinedGetter(Object* receiver,
231 JSFunction* getter) { 269 JSFunction* getter) {
232 HandleScope scope; 270 HandleScope scope;
233 Handle<JSFunction> fun(JSFunction::cast(getter)); 271 Handle<JSFunction> fun(JSFunction::cast(getter));
234 Handle<Object> self(receiver); 272 Handle<Object> self(receiver);
235 #ifdef ENABLE_DEBUGGER_SUPPORT 273 #ifdef ENABLE_DEBUGGER_SUPPORT
236 Debug* debug = fun->GetHeap()->isolate()->debug(); 274 Debug* debug = fun->GetHeap()->isolate()->debug();
237 // Handle stepping into a getter if step into is active. 275 // Handle stepping into a getter if step into is active.
238 if (debug->StepInActive()) { 276 if (debug->StepInActive()) {
239 debug->HandleStepIn(fun, Handle<Object>::null(), 0, false); 277 debug->HandleStepIn(fun, Handle<Object>::null(), 0, false);
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
487 MaybeObject* Object::GetProperty(Object* receiver, 525 MaybeObject* Object::GetProperty(Object* receiver,
488 LookupResult* result, 526 LookupResult* result,
489 String* name, 527 String* name,
490 PropertyAttributes* attributes) { 528 PropertyAttributes* attributes) {
491 // Make sure that the top context does not change when doing 529 // Make sure that the top context does not change when doing
492 // callbacks or interceptor calls. 530 // callbacks or interceptor calls.
493 AssertNoContextChange ncc; 531 AssertNoContextChange ncc;
494 Heap* heap = name->GetHeap(); 532 Heap* heap = name->GetHeap();
495 533
496 // Traverse the prototype chain from the current object (this) to 534 // Traverse the prototype chain from the current object (this) to
497 // the holder and check for access rights. This avoid traversing the 535 // the holder and check for access rights. This avoids traversing the
498 // objects more than once in case of interceptors, because the 536 // objects more than once in case of interceptors, because the
499 // holder will always be the interceptor holder and the search may 537 // holder will always be the interceptor holder and the search may
500 // only continue with a current object just after the interceptor 538 // only continue with a current object just after the interceptor
501 // holder in the prototype chain. 539 // holder in the prototype chain.
502 Object* last = result->IsProperty() ? result->holder() : heap->null_value(); 540 // Proxy handlers do not use the proxy's prototype, so we can skip this.
503 for (Object* current = this; true; current = current->GetPrototype()) { 541 if (!result->IsHandler()) {
504 if (current->IsAccessCheckNeeded()) { 542 Object* last = result->IsProperty() ? result->holder() : heap->null_value();
505 // Check if we're allowed to read from the current object. Note 543 ASSERT(this != this->GetPrototype());
506 // that even though we may not actually end up loading the named 544 for (Object* current = this; true; current = current->GetPrototype()) {
507 // property from the current object, we still check that we have 545 if (current->IsAccessCheckNeeded()) {
508 // access to it. 546 // Check if we're allowed to read from the current object. Note
509 JSObject* checked = JSObject::cast(current); 547 // that even though we may not actually end up loading the named
510 if (!heap->isolate()->MayNamedAccess(checked, name, v8::ACCESS_GET)) { 548 // property from the current object, we still check that we have
511 return checked->GetPropertyWithFailedAccessCheck(receiver, 549 // access to it.
512 result, 550 JSObject* checked = JSObject::cast(current);
513 name, 551 if (!heap->isolate()->MayNamedAccess(checked, name, v8::ACCESS_GET)) {
514 attributes); 552 return checked->GetPropertyWithFailedAccessCheck(receiver,
553 result,
554 name,
555 attributes);
556 }
515 } 557 }
558 // Stop traversing the chain once we reach the last object in the
559 // chain; either the holder of the result or null in case of an
560 // absent property.
561 if (current == last) break;
516 } 562 }
517 // Stop traversing the chain once we reach the last object in the
518 // chain; either the holder of the result or null in case of an
519 // absent property.
520 if (current == last) break;
521 } 563 }
522 564
523 if (!result->IsProperty()) { 565 if (!result->IsProperty()) {
524 *attributes = ABSENT; 566 *attributes = ABSENT;
525 return heap->undefined_value(); 567 return heap->undefined_value();
526 } 568 }
527 *attributes = result->GetAttributes(); 569 *attributes = result->GetAttributes();
528 Object* value; 570 Object* value;
529 JSObject* holder = result->holder(); 571 JSObject* holder = result->holder();
530 switch (result->type()) { 572 switch (result->type()) {
531 case NORMAL: 573 case NORMAL:
532 value = holder->GetNormalizedProperty(result); 574 value = holder->GetNormalizedProperty(result);
533 ASSERT(!value->IsTheHole() || result->IsReadOnly()); 575 ASSERT(!value->IsTheHole() || result->IsReadOnly());
534 return value->IsTheHole() ? heap->undefined_value() : value; 576 return value->IsTheHole() ? heap->undefined_value() : value;
535 case FIELD: 577 case FIELD:
536 value = holder->FastPropertyAt(result->GetFieldIndex()); 578 value = holder->FastPropertyAt(result->GetFieldIndex());
537 ASSERT(!value->IsTheHole() || result->IsReadOnly()); 579 ASSERT(!value->IsTheHole() || result->IsReadOnly());
538 return value->IsTheHole() ? heap->undefined_value() : value; 580 return value->IsTheHole() ? heap->undefined_value() : value;
539 case CONSTANT_FUNCTION: 581 case CONSTANT_FUNCTION:
540 return result->GetConstantFunction(); 582 return result->GetConstantFunction();
541 case CALLBACKS: 583 case CALLBACKS:
542 return GetPropertyWithCallback(receiver, 584 return GetPropertyWithCallback(receiver,
543 result->GetCallbackObject(), 585 result->GetCallbackObject(),
544 name, 586 name,
545 holder); 587 holder);
588 case HANDLER: {
589 JSProxy* proxy = JSProxy::cast(this);
590 return GetPropertyWithHandler(receiver, name, proxy->handler());
591 }
546 case INTERCEPTOR: { 592 case INTERCEPTOR: {
547 JSObject* recvr = JSObject::cast(receiver); 593 JSObject* recvr = JSObject::cast(receiver);
548 return holder->GetPropertyWithInterceptor(recvr, name, attributes); 594 return holder->GetPropertyWithInterceptor(recvr, name, attributes);
549 } 595 }
550 default: 596 case MAP_TRANSITION:
551 UNREACHABLE(); 597 case EXTERNAL_ARRAY_TRANSITION:
552 return NULL; 598 case CONSTANT_TRANSITION:
599 case NULL_DESCRIPTOR:
600 break;
553 } 601 }
602 UNREACHABLE();
603 return NULL;
554 } 604 }
555 605
556 606
557 MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) { 607 MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) {
558 Object* holder = NULL; 608 Object* holder = NULL;
559 if (IsSmi()) { 609 if (IsSmi()) {
560 Context* global_context = Isolate::Current()->context()->global_context(); 610 Context* global_context = Isolate::Current()->context()->global_context();
561 holder = global_context->number_function()->instance_prototype(); 611 holder = global_context->number_function()->instance_prototype();
562 } else { 612 } else {
563 HeapObject* heap_object = HeapObject::cast(this); 613 HeapObject* heap_object = HeapObject::cast(this);
564 614
565 if (heap_object->IsJSObject()) { 615 if (heap_object->IsJSObject()) {
566 return JSObject::cast(this)->GetElementWithReceiver(receiver, index); 616 return JSObject::cast(this)->GetElementWithReceiver(receiver, index);
567 } 617 }
568 Heap* heap = heap_object->GetHeap(); 618 Heap* heap = heap_object->GetHeap();
569 Isolate* isolate = heap->isolate(); 619 Isolate* isolate = heap->isolate();
570 620
571 Context* global_context = isolate->context()->global_context(); 621 Context* global_context = isolate->context()->global_context();
572 if (heap_object->IsString()) { 622 if (heap_object->IsString()) {
573 holder = global_context->string_function()->instance_prototype(); 623 holder = global_context->string_function()->instance_prototype();
574 } else if (heap_object->IsHeapNumber()) { 624 } else if (heap_object->IsHeapNumber()) {
575 holder = global_context->number_function()->instance_prototype(); 625 holder = global_context->number_function()->instance_prototype();
576 } else if (heap_object->IsBoolean()) { 626 } else if (heap_object->IsBoolean()) {
577 holder = global_context->boolean_function()->instance_prototype(); 627 holder = global_context->boolean_function()->instance_prototype();
628 } else if (heap_object->IsJSProxy()) {
629 return heap->undefined_value(); // For now...
578 } else { 630 } else {
579 // Undefined and null have no indexed properties. 631 // Undefined and null have no indexed properties.
580 ASSERT(heap_object->IsUndefined() || heap_object->IsNull()); 632 ASSERT(heap_object->IsUndefined() || heap_object->IsNull());
581 return heap->undefined_value(); 633 return heap->undefined_value();
582 } 634 }
583 } 635 }
584 636
585 return JSObject::cast(holder)->GetElementWithReceiver(receiver, index); 637 return JSObject::cast(holder)->GetElementWithReceiver(receiver, index);
586 } 638 }
587 639
588 640
589 Object* Object::GetPrototype() { 641 Object* Object::GetPrototype() {
590 if (IsSmi()) { 642 if (IsSmi()) {
591 Heap* heap = Isolate::Current()->heap(); 643 Heap* heap = Isolate::Current()->heap();
592 Context* context = heap->isolate()->context()->global_context(); 644 Context* context = heap->isolate()->context()->global_context();
593 return context->number_function()->instance_prototype(); 645 return context->number_function()->instance_prototype();
594 } 646 }
595 647
596 HeapObject* heap_object = HeapObject::cast(this); 648 HeapObject* heap_object = HeapObject::cast(this);
597 649
598 // The object is either a number, a string, a boolean, or a real JS object. 650 // The object is either a number, a string, a boolean,
599 if (heap_object->IsJSObject()) { 651 // a real JS object, or a Harmony proxy.
600 return JSObject::cast(this)->map()->prototype(); 652 if (heap_object->IsJSObject() || heap_object->IsJSProxy()) {
653 return heap_object->map()->prototype();
601 } 654 }
602 Heap* heap = heap_object->GetHeap(); 655 Heap* heap = heap_object->GetHeap();
603 Context* context = heap->isolate()->context()->global_context(); 656 Context* context = heap->isolate()->context()->global_context();
604 657
605 if (heap_object->IsHeapNumber()) { 658 if (heap_object->IsHeapNumber()) {
606 return context->number_function()->instance_prototype(); 659 return context->number_function()->instance_prototype();
607 } 660 }
608 if (heap_object->IsString()) { 661 if (heap_object->IsString()) {
609 return context->string_function()->instance_prototype(); 662 return context->string_function()->instance_prototype();
610 } 663 }
(...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after
1147 case JS_MESSAGE_OBJECT_TYPE: 1200 case JS_MESSAGE_OBJECT_TYPE:
1148 JSObject::BodyDescriptor::IterateBody(this, object_size, v); 1201 JSObject::BodyDescriptor::IterateBody(this, object_size, v);
1149 break; 1202 break;
1150 case JS_FUNCTION_TYPE: 1203 case JS_FUNCTION_TYPE:
1151 reinterpret_cast<JSFunction*>(this) 1204 reinterpret_cast<JSFunction*>(this)
1152 ->JSFunctionIterateBody(object_size, v); 1205 ->JSFunctionIterateBody(object_size, v);
1153 break; 1206 break;
1154 case ODDBALL_TYPE: 1207 case ODDBALL_TYPE:
1155 Oddball::BodyDescriptor::IterateBody(this, v); 1208 Oddball::BodyDescriptor::IterateBody(this, v);
1156 break; 1209 break;
1210 case JS_PROXY_TYPE:
1211 JSProxy::BodyDescriptor::IterateBody(this, v);
1212 break;
1157 case PROXY_TYPE: 1213 case PROXY_TYPE:
1158 reinterpret_cast<Proxy*>(this)->ProxyIterateBody(v); 1214 reinterpret_cast<Proxy*>(this)->ProxyIterateBody(v);
1159 break; 1215 break;
1160 case MAP_TYPE: 1216 case MAP_TYPE:
1161 Map::BodyDescriptor::IterateBody(this, v); 1217 Map::BodyDescriptor::IterateBody(this, v);
1162 break; 1218 break;
1163 case CODE_TYPE: 1219 case CODE_TYPE:
1164 reinterpret_cast<Code*>(this)->CodeIterateBody(v); 1220 reinterpret_cast<Code*>(this)->CodeIterateBody(v);
1165 break; 1221 break;
1166 case JS_GLOBAL_PROPERTY_CELL_TYPE: 1222 case JS_GLOBAL_PROPERTY_CELL_TYPE:
(...skipping 5370 matching lines...) Expand 10 before | Expand all | Expand 10 after
6537 return NULL; 6593 return NULL;
6538 } 6594 }
6539 6595
6540 6596
6541 const char* Code::PropertyType2String(PropertyType type) { 6597 const char* Code::PropertyType2String(PropertyType type) {
6542 switch (type) { 6598 switch (type) {
6543 case NORMAL: return "NORMAL"; 6599 case NORMAL: return "NORMAL";
6544 case FIELD: return "FIELD"; 6600 case FIELD: return "FIELD";
6545 case CONSTANT_FUNCTION: return "CONSTANT_FUNCTION"; 6601 case CONSTANT_FUNCTION: return "CONSTANT_FUNCTION";
6546 case CALLBACKS: return "CALLBACKS"; 6602 case CALLBACKS: return "CALLBACKS";
6603 case HANDLER: return "HANDLER";
6547 case INTERCEPTOR: return "INTERCEPTOR"; 6604 case INTERCEPTOR: return "INTERCEPTOR";
6548 case MAP_TRANSITION: return "MAP_TRANSITION"; 6605 case MAP_TRANSITION: return "MAP_TRANSITION";
6549 case EXTERNAL_ARRAY_TRANSITION: return "EXTERNAL_ARRAY_TRANSITION"; 6606 case EXTERNAL_ARRAY_TRANSITION: return "EXTERNAL_ARRAY_TRANSITION";
6550 case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION"; 6607 case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION";
6551 case NULL_DESCRIPTOR: return "NULL_DESCRIPTOR"; 6608 case NULL_DESCRIPTOR: return "NULL_DESCRIPTOR";
6552 } 6609 }
6553 UNREACHABLE(); 6610 UNREACHABLE();
6554 return NULL; 6611 return NULL;
6555 } 6612 }
6556 6613
(...skipping 3865 matching lines...) Expand 10 before | Expand all | Expand 10 after
10422 if (break_point_objects()->IsUndefined()) return 0; 10479 if (break_point_objects()->IsUndefined()) return 0;
10423 // Single beak point. 10480 // Single beak point.
10424 if (!break_point_objects()->IsFixedArray()) return 1; 10481 if (!break_point_objects()->IsFixedArray()) return 1;
10425 // Multiple break points. 10482 // Multiple break points.
10426 return FixedArray::cast(break_point_objects())->length(); 10483 return FixedArray::cast(break_point_objects())->length();
10427 } 10484 }
10428 #endif 10485 #endif
10429 10486
10430 10487
10431 } } // namespace v8::internal 10488 } } // namespace v8::internal
OLDNEW
« src/messages.js ('K') | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698