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

Side by Side Diff: src/objects.cc

Issue 7799026: Make proxies work as prototypes. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 3 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 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 } 126 }
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 (IsJSReceiver()) {
137 holder = this;
138 } else {
137 Context* global_context = Isolate::Current()->context()->global_context(); 139 Context* global_context = Isolate::Current()->context()->global_context();
138 holder = global_context->number_function()->instance_prototype(); 140 if (IsSmi()) {
Kevin Millikin (Chromium) 2011/08/31 10:15:31 You can use IsNumber() here and remove the clause
rossberg 2011/08/31 13:28:32 Done.
139 } else { 141 holder = global_context->number_function()->instance_prototype();
140 HeapObject* heap_object = HeapObject::cast(this); 142 } else if (IsString()) {
141 if (heap_object->IsJSObject()) {
142 return JSObject::cast(this)->Lookup(name, result);
143 } else if (heap_object->IsJSProxy()) {
144 return result->HandlerResult();
145 }
146 Context* global_context = Isolate::Current()->context()->global_context();
147 if (heap_object->IsString()) {
148 holder = global_context->string_function()->instance_prototype(); 143 holder = global_context->string_function()->instance_prototype();
149 } else if (heap_object->IsHeapNumber()) { 144 } else if (IsHeapNumber()) {
150 holder = global_context->number_function()->instance_prototype(); 145 holder = global_context->number_function()->instance_prototype();
151 } else if (heap_object->IsBoolean()) { 146 } else if (IsBoolean()) {
152 holder = global_context->boolean_function()->instance_prototype(); 147 holder = global_context->boolean_function()->instance_prototype();
153 } 148 }
154 } 149 }
155 ASSERT(holder != NULL); // Cannot handle null or undefined. 150 ASSERT(holder != NULL); // Cannot handle null or undefined.
156 JSObject::cast(holder)->Lookup(name, result); 151 JSReceiver::cast(holder)->Lookup(name, result);
157 } 152 }
158 153
159 154
160 MaybeObject* Object::GetPropertyWithReceiver(Object* receiver, 155 MaybeObject* Object::GetPropertyWithReceiver(Object* receiver,
161 String* name, 156 String* name,
162 PropertyAttributes* attributes) { 157 PropertyAttributes* attributes) {
163 LookupResult result; 158 LookupResult result;
164 Lookup(name, &result); 159 Lookup(name, &result);
165 MaybeObject* value = GetProperty(receiver, &result, name, attributes); 160 MaybeObject* value = GetProperty(receiver, &result, name, attributes);
166 ASSERT(*attributes <= ABSENT); 161 ASSERT(*attributes <= ABSENT);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 } 214 }
220 // Getter is not a function. 215 // Getter is not a function.
221 return isolate->heap()->undefined_value(); 216 return isolate->heap()->undefined_value();
222 } 217 }
223 218
224 UNREACHABLE(); 219 UNREACHABLE();
225 return NULL; 220 return NULL;
226 } 221 }
227 222
228 223
229 MaybeObject* Object::GetPropertyWithHandler(Object* receiver_raw, 224 MaybeObject* JSProxy::GetPropertyWithHandler(Object* receiver_raw,
230 String* name_raw, 225 String* name_raw) {
231 Object* handler_raw) { 226 Isolate* isolate = GetIsolate();
232 Isolate* isolate = name_raw->GetIsolate();
233 HandleScope scope(isolate); 227 HandleScope scope(isolate);
234 Handle<Object> receiver(receiver_raw); 228 Handle<Object> receiver(receiver_raw);
235 Handle<Object> name(name_raw); 229 Handle<Object> name(name_raw);
236 Handle<Object> handler(handler_raw);
237 230
238 // Extract trap function. 231 Object** args[] = { receiver.location(), name.location() };
Kevin Millikin (Chromium) 2011/08/31 10:15:31 We seem to have a mix of this style and Handle<Ob
rossberg 2011/08/31 13:28:32 I agree. I fully handlified the type of CallTrap.
239 Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("get"); 232 Handle<Object> result = CallTrap(
240 Handle<Object> trap(v8::internal::GetProperty(handler, trap_name)); 233 "get", *isolate->derived_get_trap(), ARRAY_SIZE(args), args);
241 if (isolate->has_pending_exception()) return Failure::Exception(); 234 if (isolate->has_pending_exception()) return Failure::Exception();
242 if (trap->IsUndefined()) {
243 // Get the derived `get' property.
244 trap = isolate->derived_get_trap();
245 }
246
247 // Call trap function.
248 Object** args[] = { receiver.location(), name.location() };
249 bool has_exception;
250 Handle<Object> result =
251 Execution::Call(trap, handler, ARRAY_SIZE(args), args, &has_exception);
252 if (has_exception) return Failure::Exception();
253 235
254 return *result; 236 return *result;
255 } 237 }
256 238
257 239
258 MaybeObject* Object::GetPropertyWithDefinedGetter(Object* receiver, 240 MaybeObject* Object::GetPropertyWithDefinedGetter(Object* receiver,
259 JSFunction* getter) { 241 JSFunction* getter) {
260 HandleScope scope; 242 HandleScope scope;
261 Handle<JSFunction> fun(JSFunction::cast(getter)); 243 Handle<JSFunction> fun(JSFunction::cast(getter));
262 Handle<Object> self(receiver); 244 Handle<Object> self(receiver);
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
560 if (current == last) break; 542 if (current == last) break;
561 } 543 }
562 } 544 }
563 545
564 if (!result->IsProperty()) { 546 if (!result->IsProperty()) {
565 *attributes = ABSENT; 547 *attributes = ABSENT;
566 return heap->undefined_value(); 548 return heap->undefined_value();
567 } 549 }
568 *attributes = result->GetAttributes(); 550 *attributes = result->GetAttributes();
569 Object* value; 551 Object* value;
570 JSObject* holder = result->holder();
571 switch (result->type()) { 552 switch (result->type()) {
572 case NORMAL: 553 case NORMAL:
573 value = holder->GetNormalizedProperty(result); 554 value = result->holder()->GetNormalizedProperty(result);
574 ASSERT(!value->IsTheHole() || result->IsReadOnly()); 555 ASSERT(!value->IsTheHole() || result->IsReadOnly());
575 return value->IsTheHole() ? heap->undefined_value() : value; 556 return value->IsTheHole() ? heap->undefined_value() : value;
576 case FIELD: 557 case FIELD:
577 value = holder->FastPropertyAt(result->GetFieldIndex()); 558 value = result->holder()->FastPropertyAt(result->GetFieldIndex());
578 ASSERT(!value->IsTheHole() || result->IsReadOnly()); 559 ASSERT(!value->IsTheHole() || result->IsReadOnly());
579 return value->IsTheHole() ? heap->undefined_value() : value; 560 return value->IsTheHole() ? heap->undefined_value() : value;
580 case CONSTANT_FUNCTION: 561 case CONSTANT_FUNCTION:
581 return result->GetConstantFunction(); 562 return result->GetConstantFunction();
582 case CALLBACKS: 563 case CALLBACKS:
583 return GetPropertyWithCallback(receiver, 564 return GetPropertyWithCallback(receiver,
584 result->GetCallbackObject(), 565 result->GetCallbackObject(),
585 name, 566 name,
586 holder); 567 result->holder());
587 case HANDLER: { 568 case HANDLER:
588 JSProxy* proxy = JSProxy::cast(this); 569 return result->proxy()->GetPropertyWithHandler(receiver, name);
589 return GetPropertyWithHandler(receiver, name, proxy->handler());
590 }
591 case INTERCEPTOR: { 570 case INTERCEPTOR: {
592 JSObject* recvr = JSObject::cast(receiver); 571 JSObject* recvr = JSObject::cast(receiver);
593 return holder->GetPropertyWithInterceptor(recvr, name, attributes); 572 return result->holder()->GetPropertyWithInterceptor(
573 recvr, name, attributes);
594 } 574 }
595 case MAP_TRANSITION: 575 case MAP_TRANSITION:
596 case EXTERNAL_ARRAY_TRANSITION: 576 case EXTERNAL_ARRAY_TRANSITION:
597 case CONSTANT_TRANSITION: 577 case CONSTANT_TRANSITION:
598 case NULL_DESCRIPTOR: 578 case NULL_DESCRIPTOR:
599 break; 579 break;
600 } 580 }
601 UNREACHABLE(); 581 UNREACHABLE();
602 return NULL; 582 return NULL;
603 } 583 }
(...skipping 1287 matching lines...) Expand 10 before | Expand all | Expand 10 after
1891 *isolate->factory()->NewTypeError("no_setter_in_callback", 1871 *isolate->factory()->NewTypeError("no_setter_in_callback",
1892 HandleVector(args, 2))); 1872 HandleVector(args, 2)));
1893 } 1873 }
1894 } 1874 }
1895 1875
1896 UNREACHABLE(); 1876 UNREACHABLE();
1897 return NULL; 1877 return NULL;
1898 } 1878 }
1899 1879
1900 1880
1901 MaybeObject* JSObject::SetPropertyWithDefinedSetter(JSFunction* setter, 1881 MaybeObject* JSReceiver::SetPropertyWithDefinedSetter(JSFunction* setter,
1902 Object* value) { 1882 Object* value) {
Kevin Millikin (Chromium) 2011/08/31 10:15:31 Indentation is now off.
rossberg 2011/08/31 13:28:32 Done.
1903 Isolate* isolate = GetIsolate(); 1883 Isolate* isolate = GetIsolate();
1904 Handle<Object> value_handle(value, isolate); 1884 Handle<Object> value_handle(value, isolate);
1905 Handle<JSFunction> fun(JSFunction::cast(setter), isolate); 1885 Handle<JSFunction> fun(JSFunction::cast(setter), isolate);
1906 Handle<JSObject> self(this, isolate); 1886 Handle<JSReceiver> self(this, isolate);
1907 #ifdef ENABLE_DEBUGGER_SUPPORT 1887 #ifdef ENABLE_DEBUGGER_SUPPORT
1908 Debug* debug = isolate->debug(); 1888 Debug* debug = isolate->debug();
1909 // Handle stepping into a setter if step into is active. 1889 // Handle stepping into a setter if step into is active.
1910 if (debug->StepInActive()) { 1890 if (debug->StepInActive()) {
1911 debug->HandleStepIn(fun, Handle<Object>::null(), 0, false); 1891 debug->HandleStepIn(fun, Handle<Object>::null(), 0, false);
1912 } 1892 }
1913 #endif 1893 #endif
1914 bool has_pending_exception; 1894 bool has_pending_exception;
1915 Object** argv[] = { value_handle.location() }; 1895 Object** argv[] = { value_handle.location() };
1916 Execution::Call(fun, self, 1, argv, &has_pending_exception); 1896 Execution::Call(fun, self, 1, argv, &has_pending_exception);
1917 // Check for pending exception and return the result. 1897 // Check for pending exception and return the result.
1918 if (has_pending_exception) return Failure::Exception(); 1898 if (has_pending_exception) return Failure::Exception();
1919 return *value_handle; 1899 return *value_handle;
1920 } 1900 }
1921 1901
1922 1902
1923 void JSObject::LookupCallbackSetterInPrototypes(String* name, 1903 void JSObject::LookupCallbackSetterInPrototypes(String* name,
1924 LookupResult* result) { 1904 LookupResult* result) {
1925 Heap* heap = GetHeap(); 1905 Heap* heap = GetHeap();
1926 for (Object* pt = GetPrototype(); 1906 for (Object* pt = GetPrototype();
1927 pt != heap->null_value(); 1907 pt != heap->null_value();
1928 pt = pt->GetPrototype()) { 1908 pt = pt->GetPrototype()) {
1909 if (pt->IsJSProxy()) {
1910 result->HandlerResult(JSProxy::cast(pt));
Kevin Millikin (Chromium) 2011/08/31 10:15:31 I like to write return result->HandlerResult(JSPr
rossberg 2011/08/31 13:28:32 I know. :) Done.
1911 return;
1912 }
1929 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); 1913 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
1930 if (result->IsProperty()) { 1914 if (result->IsProperty()) {
1931 if (result->type() == CALLBACKS && !result->IsReadOnly()) return; 1915 if (result->type() == CALLBACKS && !result->IsReadOnly()) return;
1932 // Found non-callback or read-only callback, stop looking. 1916 // Found non-callback or read-only callback, stop looking.
1933 break; 1917 break;
1934 } 1918 }
1935 } 1919 }
1936 result->NotFound(); 1920 result->NotFound();
1937 } 1921 }
1938 1922
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
2104 return new_map; 2088 return new_map;
2105 } 2089 }
2106 2090
2107 2091
2108 void JSObject::LocalLookupRealNamedProperty(String* name, 2092 void JSObject::LocalLookupRealNamedProperty(String* name,
2109 LookupResult* result) { 2093 LookupResult* result) {
2110 if (IsJSGlobalProxy()) { 2094 if (IsJSGlobalProxy()) {
2111 Object* proto = GetPrototype(); 2095 Object* proto = GetPrototype();
2112 if (proto->IsNull()) return result->NotFound(); 2096 if (proto->IsNull()) return result->NotFound();
2113 ASSERT(proto->IsJSGlobalObject()); 2097 ASSERT(proto->IsJSGlobalObject());
2098 // A GlobalProxy's prototype should always be a proper JSObject.
2114 return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result); 2099 return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result);
2115 } 2100 }
2116 2101
2117 if (HasFastProperties()) { 2102 if (HasFastProperties()) {
2118 LookupInDescriptor(name, result); 2103 LookupInDescriptor(name, result);
2119 if (result->IsFound()) { 2104 if (result->IsFound()) {
2120 // A property, a map transition or a null descriptor was found. 2105 // A property, a map transition or a null descriptor was found.
2121 // We return all of these result types because 2106 // We return all of these result types because
2122 // LocalLookupRealNamedProperty is used when setting properties 2107 // LocalLookupRealNamedProperty is used when setting properties
2123 // where map transitions and null descriptors are handled. 2108 // where map transitions and null descriptors are handled.
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
2230 return *value_handle; 2215 return *value_handle;
2231 } 2216 }
2232 2217
2233 2218
2234 MaybeObject* JSReceiver::SetProperty(LookupResult* result, 2219 MaybeObject* JSReceiver::SetProperty(LookupResult* result,
2235 String* key, 2220 String* key,
2236 Object* value, 2221 Object* value,
2237 PropertyAttributes attributes, 2222 PropertyAttributes attributes,
2238 StrictModeFlag strict_mode) { 2223 StrictModeFlag strict_mode) {
2239 if (result->IsFound() && result->type() == HANDLER) { 2224 if (result->IsFound() && result->type() == HANDLER) {
2240 return JSProxy::cast(this)->SetPropertyWithHandler( 2225 return result->proxy()->SetPropertyWithHandler(
2241 key, value, attributes, strict_mode); 2226 key, value, attributes, strict_mode);
2242 } else { 2227 } else {
2243 return JSObject::cast(this)->SetPropertyForResult( 2228 return JSObject::cast(this)->SetPropertyForResult(
2244 result, key, value, attributes, strict_mode); 2229 result, key, value, attributes, strict_mode);
2245 } 2230 }
2246 } 2231 }
2247 2232
2248 2233
2249 bool JSProxy::HasPropertyWithHandler(String* name_raw) { 2234 bool JSProxy::HasPropertyWithHandler(String* name_raw) {
2250 Isolate* isolate = GetIsolate(); 2235 Isolate* isolate = GetIsolate();
2251 HandleScope scope(isolate); 2236 HandleScope scope(isolate);
2252 Handle<Object> receiver(this); 2237 Handle<Object> receiver(this);
2253 Handle<Object> name(name_raw); 2238 Handle<Object> name(name_raw);
2254 Handle<Object> handler(this->handler());
2255 2239
2256 // Extract trap function. 2240 Object** args[] = { name.location() };
2257 Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("has"); 2241 Handle<Object> result = CallTrap(
2258 Handle<Object> trap(v8::internal::GetProperty(handler, trap_name)); 2242 "has", *isolate->derived_has_trap(), ARRAY_SIZE(args), args);
2259 if (isolate->has_pending_exception()) return Failure::Exception(); 2243 if (isolate->has_pending_exception()) return Failure::Exception();
2260 if (trap->IsUndefined()) {
2261 trap = isolate->derived_has_trap();
2262 }
2263
2264 // Call trap function.
2265 Object** args[] = { name.location() };
2266 bool has_exception;
2267 Handle<Object> result =
2268 Execution::Call(trap, handler, ARRAY_SIZE(args), args, &has_exception);
2269 if (has_exception) return Failure::Exception();
2270 2244
2271 return result->ToBoolean()->IsTrue(); 2245 return result->ToBoolean()->IsTrue();
2272 } 2246 }
2273 2247
2274 2248
2275 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler( 2249 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler(
2276 String* name_raw, 2250 String* name_raw,
2277 Object* value_raw, 2251 Object* value_raw,
2278 PropertyAttributes attributes, 2252 PropertyAttributes attributes,
2279 StrictModeFlag strict_mode) { 2253 StrictModeFlag strict_mode) {
2280 Isolate* isolate = GetIsolate(); 2254 Isolate* isolate = GetIsolate();
2281 HandleScope scope(isolate); 2255 HandleScope scope(isolate);
2282 Handle<Object> receiver(this); 2256 Handle<Object> receiver(this);
2283 Handle<Object> name(name_raw); 2257 Handle<Object> name(name_raw);
2284 Handle<Object> value(value_raw); 2258 Handle<Object> value(value_raw);
2285 Handle<Object> handler(this->handler());
2286 2259
2287 // Extract trap function.
2288 Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("set");
2289 Handle<Object> trap(v8::internal::GetProperty(handler, trap_name));
2290 if (isolate->has_pending_exception()) return Failure::Exception();
2291 if (trap->IsUndefined()) {
2292 trap = isolate->derived_set_trap();
2293 }
2294
2295 // Call trap function.
2296 Object** args[] = { 2260 Object** args[] = {
2297 receiver.location(), name.location(), value.location() 2261 receiver.location(), name.location(), value.location()
2298 }; 2262 };
2299 bool has_exception; 2263 CallTrap("set", *isolate->derived_set_trap(), ARRAY_SIZE(args), args);
2300 Execution::Call(trap, handler, ARRAY_SIZE(args), args, &has_exception); 2264 if (isolate->has_pending_exception()) return Failure::Exception();
2301 if (has_exception) return Failure::Exception();
2302 2265
2303 return *value; 2266 return *value;
2304 } 2267 }
2305 2268
2306 2269
2307 MUST_USE_RESULT MaybeObject* JSProxy::DeletePropertyWithHandler( 2270 MUST_USE_RESULT MaybeObject* JSProxy::DeletePropertyWithHandler(
2308 String* name_raw, DeleteMode mode) { 2271 String* name_raw, DeleteMode mode) {
2309 Isolate* isolate = GetIsolate(); 2272 Isolate* isolate = GetIsolate();
2310 HandleScope scope(isolate); 2273 HandleScope scope(isolate);
2311 Handle<Object> receiver(this); 2274 Handle<Object> receiver(this);
2312 Handle<Object> name(name_raw); 2275 Handle<Object> name(name_raw);
2313 Handle<Object> handler(this->handler());
2314 2276
2315 // Extract trap function. 2277 Object** args[] = { name.location() };
2316 Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("delete"); 2278 Handle<Object> result = CallTrap("delete", NULL, ARRAY_SIZE(args), args);
2317 Handle<Object> trap(v8::internal::GetProperty(handler, trap_name));
2318 if (isolate->has_pending_exception()) return Failure::Exception(); 2279 if (isolate->has_pending_exception()) return Failure::Exception();
2319 if (trap->IsUndefined()) {
2320 Handle<Object> args[] = { handler, trap_name };
2321 Handle<Object> error = isolate->factory()->NewTypeError(
2322 "handler_trap_missing", HandleVector(args, ARRAY_SIZE(args)));
2323 isolate->Throw(*error);
2324 return Failure::Exception();
2325 }
2326
2327 // Call trap function.
2328 Object** args[] = { name.location() };
2329 bool has_exception;
2330 Handle<Object> result =
2331 Execution::Call(trap, handler, ARRAY_SIZE(args), args, &has_exception);
2332 if (has_exception) return Failure::Exception();
2333 2280
2334 Object* bool_result = result->ToBoolean(); 2281 Object* bool_result = result->ToBoolean();
2335 if (mode == STRICT_DELETION && bool_result == GetHeap()->false_value()) { 2282 if (mode == STRICT_DELETION && bool_result == GetHeap()->false_value()) {
2336 Handle<Object> args[] = { handler, trap_name }; 2283 Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("delete");
2284 Handle<Object> args[] = { Handle<Object>(handler()), trap_name };
2337 Handle<Object> error = isolate->factory()->NewTypeError( 2285 Handle<Object> error = isolate->factory()->NewTypeError(
2338 "handler_failed", HandleVector(args, ARRAY_SIZE(args))); 2286 "handler_failed", HandleVector(args, ARRAY_SIZE(args)));
2339 isolate->Throw(*error); 2287 isolate->Throw(*error);
2340 return Failure::Exception(); 2288 return Failure::Exception();
2341 } 2289 }
2342 return bool_result; 2290 return bool_result;
2343 } 2291 }
2344 2292
2345 2293
2346 MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler( 2294 MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler(
2347 JSReceiver* receiver_raw, 2295 JSReceiver* receiver_raw, String* name_raw) {
Kevin Millikin (Chromium) 2011/08/31 10:15:31 Also one parameter per line here.
rossberg 2011/08/31 13:28:32 Done.
2348 String* name_raw,
2349 bool* has_exception) {
2350 Isolate* isolate = GetIsolate(); 2296 Isolate* isolate = GetIsolate();
2351 HandleScope scope(isolate); 2297 HandleScope scope(isolate);
2352 Handle<JSReceiver> receiver(receiver_raw); 2298 Handle<JSReceiver> receiver(receiver_raw);
2353 Handle<Object> name(name_raw); 2299 Handle<Object> name(name_raw);
2354 Handle<Object> handler(this->handler());
2355 2300
2356 // Extract trap function. 2301 Object** args[] = { name.location() };
2357 Handle<String> trap_name = 2302 Handle<Object> result = CallTrap(
2358 isolate->factory()->LookupAsciiSymbol("getPropertyDescriptor"); 2303 "getPropertyDescriptor", NULL, ARRAY_SIZE(args), args);
2359 Handle<Object> trap(v8::internal::GetProperty(handler, trap_name));
2360 if (isolate->has_pending_exception()) return NONE; 2304 if (isolate->has_pending_exception()) return NONE;
2361 if (trap->IsUndefined()) {
2362 Handle<Object> args[] = { handler, trap_name };
2363 Handle<Object> error = isolate->factory()->NewTypeError(
2364 "handler_trap_missing", HandleVector(args, ARRAY_SIZE(args)));
2365 isolate->Throw(*error);
2366 *has_exception = true;
2367 return NONE;
2368 }
2369 2305
2370 // Call trap function. 2306 if (result->IsUndefined()) return ABSENT;
2371 Object** args[] = { name.location() };
2372 Handle<Object> result =
2373 Execution::Call(trap, handler, ARRAY_SIZE(args), args, has_exception);
2374 if (has_exception) return NONE;
2375 2307
2376 // TODO(rossberg): convert result to PropertyAttributes 2308 // TODO(rossberg): convert result to PropertyAttributes
2377 USE(result);
2378 return NONE; 2309 return NONE;
2379 } 2310 }
2380 2311
2381 2312
2382 void JSProxy::Fix() { 2313 void JSProxy::Fix() {
2383 Isolate* isolate = GetIsolate(); 2314 Isolate* isolate = GetIsolate();
2384 HandleScope scope(isolate); 2315 HandleScope scope(isolate);
2385 Handle<JSProxy> self(this); 2316 Handle<JSProxy> self(this);
2386 2317
2387 if (IsJSFunctionProxy()) { 2318 if (IsJSFunctionProxy()) {
2388 isolate->factory()->BecomeJSFunction(self); 2319 isolate->factory()->BecomeJSFunction(self);
2389 // Code will be set on the JavaScript side. 2320 // Code will be set on the JavaScript side.
2390 } else { 2321 } else {
2391 isolate->factory()->BecomeJSObject(self); 2322 isolate->factory()->BecomeJSObject(self);
2392 } 2323 }
2393 ASSERT(self->IsJSObject()); 2324 ASSERT(self->IsJSObject());
2394 } 2325 }
2395 2326
2396 2327
2328 MUST_USE_RESULT Handle<Object> JSProxy::CallTrap(
2329 const char* name, Object* derived, int argc, Object*** args) {
Kevin Millikin (Chromium) 2011/08/31 10:15:31 I think there's a GC hazard here. derived is a ra
rossberg 2011/08/31 13:28:32 Done.
2330 Isolate* isolate = GetIsolate();
2331 Handle<Object> handler(this->handler());
2332
2333 Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol(name);
2334 Handle<Object> trap(v8::internal::GetProperty(handler, trap_name));
2335 if (isolate->has_pending_exception()) return trap;
2336
2337 if (trap->IsUndefined()) {
2338 if (derived == NULL) {
2339 Handle<Object> args[] = { handler, trap_name };
2340 Handle<Object> error = isolate->factory()->NewTypeError(
2341 "handler_trap_missing", HandleVector(args, ARRAY_SIZE(args)));
2342 isolate->Throw(*error);
2343 return Handle<Object>();
2344 }
2345 trap = Handle<Object>(derived);
2346 }
2347
2348 bool threw = false;
2349 return Execution::Call(trap, handler, argc, args, &threw);
2350 }
2351
2397 2352
2398 MaybeObject* JSObject::SetPropertyForResult(LookupResult* result, 2353 MaybeObject* JSObject::SetPropertyForResult(LookupResult* result,
Kevin Millikin (Chromium) 2011/08/31 10:15:31 I think SetPropertyForResult needs a better name b
rossberg 2011/08/31 13:28:32 Same here. IMHO some bigger clean-up of the whole
2399 String* name, 2354 String* name,
2400 Object* value, 2355 Object* value,
2401 PropertyAttributes attributes, 2356 PropertyAttributes attributes,
2402 StrictModeFlag strict_mode) { 2357 StrictModeFlag strict_mode) {
2403 Heap* heap = GetHeap(); 2358 Heap* heap = GetHeap();
2404 // Make sure that the top context does not change when doing callbacks or 2359 // Make sure that the top context does not change when doing callbacks or
2405 // interceptor calls. 2360 // interceptor calls.
2406 AssertNoContextChange ncc; 2361 AssertNoContextChange ncc;
2407 2362
2408 // Optimization for 2-byte strings often used as keys in a decompression 2363 // Optimization for 2-byte strings often used as keys in a decompression
2409 // dictionary. We make these short keys into symbols to avoid constantly 2364 // dictionary. We make these short keys into symbols to avoid constantly
2410 // reallocating them. 2365 // reallocating them.
2411 if (!name->IsSymbol() && name->length() <= 2) { 2366 if (!name->IsSymbol() && name->length() <= 2) {
2412 Object* symbol_version; 2367 Object* symbol_version;
2413 { MaybeObject* maybe_symbol_version = heap->LookupSymbol(name); 2368 { MaybeObject* maybe_symbol_version = heap->LookupSymbol(name);
2414 if (maybe_symbol_version->ToObject(&symbol_version)) { 2369 if (maybe_symbol_version->ToObject(&symbol_version)) {
2415 name = String::cast(symbol_version); 2370 name = String::cast(symbol_version);
2416 } 2371 }
2417 } 2372 }
2418 } 2373 }
2419 2374
2420 // Check access rights if needed. 2375 // Check access rights if needed.
2421 if (IsAccessCheckNeeded() 2376 if (IsAccessCheckNeeded()) {
2422 && !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) { 2377 JSObject* object = JSObject::cast(this);
Kevin Millikin (Chromium) 2011/08/31 10:15:31 Isn't this already JSObject*?
rossberg 2011/08/31 13:28:32 Right. I had moved the method to JSReceiver, but u
2423 return SetPropertyWithFailedAccessCheck(result, 2378 if (!heap->isolate()->MayNamedAccess(object, name, v8::ACCESS_SET)) {
2424 name, 2379 return object->SetPropertyWithFailedAccessCheck(
2425 value, 2380 result, name, value, true, strict_mode);
2426 true, 2381 }
2427 strict_mode);
2428 } 2382 }
2429 2383
2430 if (IsJSGlobalProxy()) { 2384 if (IsJSGlobalProxy()) {
2431 Object* proto = GetPrototype(); 2385 Object* proto = GetPrototype();
2432 if (proto->IsNull()) return value; 2386 if (proto->IsNull()) return value;
2433 ASSERT(proto->IsJSGlobalObject()); 2387 ASSERT(proto->IsJSGlobalObject());
2434 return JSObject::cast(proto)->SetProperty( 2388 return JSObject::cast(proto)->SetPropertyForResult(
2435 result, name, value, attributes, strict_mode); 2389 result, name, value, attributes, strict_mode);
2436 } 2390 }
2437 2391
2438 if (!result->IsProperty() && !IsJSContextExtensionObject()) { 2392 if (!result->IsProperty() && !IsJSContextExtensionObject()) {
2439 // We could not find a local property so let's check whether there is an 2393 // We could not find a local property so let's check whether there is an
2440 // accessor that wants to handle the property. 2394 // accessor that wants to handle the property.
2441 LookupResult accessor_result; 2395 LookupResult accessor_result;
2442 LookupCallbackSetterInPrototypes(name, &accessor_result); 2396 LookupCallbackSetterInPrototypes(name, &accessor_result);
2443 if (accessor_result.IsProperty()) { 2397 if (accessor_result.IsFound()) {
2444 return SetPropertyWithCallback(accessor_result.GetCallbackObject(), 2398 if (accessor_result.type() == CALLBACKS) {
2445 name, 2399 return SetPropertyWithCallback(accessor_result.GetCallbackObject(),
2446 value, 2400 name,
2447 accessor_result.holder(), 2401 value,
2448 strict_mode); 2402 accessor_result.holder(),
2403 strict_mode);
2404 } else if (accessor_result.type() == HANDLER) {
2405 // There is a proxy in the prototype chain. Invoke its
2406 // getOwnPropertyDescriptor trap.
2407 Isolate* isolate = heap->isolate();
2408 Handle<JSProxy> proxy(accessor_result.proxy());
2409 Handle<Object> hname(name);
2410 Object** args[] = { hname.location() };
2411 Handle<Object> result = proxy->CallTrap(
Kevin Millikin (Chromium) 2011/08/31 10:15:31 There's also a GC hazard here. CallTrap can silen
rossberg 2011/08/31 13:28:32 Argh, of course. The good news is that the only ca
2412 "getOwnPropertyDescriptor", NULL, ARRAY_SIZE(args), args);
2413 if (isolate->has_pending_exception()) return Failure::Exception();
2414
2415 if (!result->IsUndefined()) {
2416 // The proxy handler cares about this property.
2417 // Check whether it is virtualized as an accessor.
2418 Handle<String> getter_name =
2419 isolate->factory()->LookupAsciiSymbol("get");
2420 Handle<Object> getter(
2421 v8::internal::GetProperty(result, getter_name));
2422 if (isolate->has_pending_exception()) return Failure::Exception();
2423 Handle<String> setter_name =
2424 isolate->factory()->LookupAsciiSymbol("set");
2425 Handle<Object> setter(
2426 v8::internal::GetProperty(result, setter_name));
2427 if (isolate->has_pending_exception()) return Failure::Exception();
2428
2429 if (!setter->IsUndefined()) {
2430 // We have a setter -- invoke it.
2431 if (setter->IsJSFunction()) {
2432 return proxy->SetPropertyWithDefinedSetter(
2433 JSFunction::cast(*setter), value);
2434 }
2435 Handle<Object> args[] = { setter };
2436 Handle<Object> error = isolate->factory()->NewTypeError(
2437 "setter_must_be_callable", HandleVector(args, ARRAY_SIZE(args)));
2438 return isolate->Throw(*error);
2439 } else if (!getter->IsUndefined()) {
2440 // We have a getter but no setter -- the property may not be
2441 // written. In strict mode, throw an error.
2442 if (strict_mode == kNonStrictMode) return value;
2443 Handle<Object> args[] = { hname, proxy };
2444 Handle<Object> error = isolate->factory()->NewTypeError(
2445 "no_setter_in_callback", HandleVector(args, ARRAY_SIZE(args)));
2446 return isolate->Throw(*error);
2447 }
2448 // The proxy does not define the property as an accessor.
2449 // Consequently, it has no effect on setting the receiver.
2450 // Fall through.
2451 }
2452 }
2449 } 2453 }
2450 } 2454 }
2451 if (!result->IsFound()) { 2455 if (!result->IsFound()) {
2452 // Neither properties nor transitions found. 2456 // Neither properties nor transitions found.
2453 return AddProperty(name, value, attributes, strict_mode); 2457 return AddProperty(name, value, attributes, strict_mode);
2454 } 2458 }
2455 if (result->IsReadOnly() && result->IsProperty()) { 2459 if (result->IsReadOnly() && result->IsProperty()) {
2456 if (strict_mode == kStrictMode) { 2460 if (strict_mode == kStrictMode) {
2457 HandleScope scope(heap->isolate()); 2461 HandleScope scope(heap->isolate());
2458 Handle<String> key(name); 2462 Handle<String> key(name);
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
2713 } 2717 }
2714 } 2718 }
2715 if (result->IsProperty()) { 2719 if (result->IsProperty()) {
2716 switch (result->type()) { 2720 switch (result->type()) {
2717 case NORMAL: // fall through 2721 case NORMAL: // fall through
2718 case FIELD: 2722 case FIELD:
2719 case CONSTANT_FUNCTION: 2723 case CONSTANT_FUNCTION:
2720 case CALLBACKS: 2724 case CALLBACKS:
2721 return result->GetAttributes(); 2725 return result->GetAttributes();
2722 case HANDLER: { 2726 case HANDLER: {
2723 // TODO(rossberg): propagate exceptions properly. 2727 return JSProxy::cast(result->proxy())->GetPropertyAttributeWithHandler(
2724 bool has_exception = false; 2728 receiver, name);
2725 return JSProxy::cast(this)->GetPropertyAttributeWithHandler(
2726 receiver, name, &has_exception);
2727 } 2729 }
2728 case INTERCEPTOR: 2730 case INTERCEPTOR:
2729 return result->holder()->GetPropertyAttributeWithInterceptor( 2731 return result->holder()->GetPropertyAttributeWithInterceptor(
2730 JSObject::cast(receiver), name, continue_search); 2732 JSObject::cast(receiver), name, continue_search);
2731 default: 2733 default:
2732 UNREACHABLE(); 2734 UNREACHABLE();
2733 } 2735 }
2734 } 2736 }
2735 return ABSENT; 2737 return ABSENT;
2736 } 2738 }
(...skipping 778 matching lines...) Expand 10 before | Expand all | Expand 10 after
3515 for (int i = 0; i < descs->number_of_descriptors(); i++) { 3517 for (int i = 0; i < descs->number_of_descriptors(); i++) {
3516 if (name->Equals(descs->GetKey(i)) && descs->GetType(i) == CALLBACKS) { 3518 if (name->Equals(descs->GetKey(i)) && descs->GetType(i) == CALLBACKS) {
3517 return descs->GetCallbacks(i); 3519 return descs->GetCallbacks(i);
3518 } 3520 }
3519 } 3521 }
3520 return NULL; 3522 return NULL;
3521 } 3523 }
3522 3524
3523 3525
3524 void JSReceiver::LocalLookup(String* name, LookupResult* result) { 3526 void JSReceiver::LocalLookup(String* name, LookupResult* result) {
3525 if (IsJSProxy()) {
3526 result->HandlerResult();
3527 } else {
3528 JSObject::cast(this)->LocalLookup(name, result);
3529 }
3530 }
3531
3532
3533 void JSObject::LocalLookup(String* name, LookupResult* result) {
3534 ASSERT(name->IsString()); 3527 ASSERT(name->IsString());
3535 3528
3536 Heap* heap = GetHeap(); 3529 Heap* heap = GetHeap();
3537 3530
3538 if (IsJSGlobalProxy()) { 3531 if (IsJSGlobalProxy()) {
3539 Object* proto = GetPrototype(); 3532 Object* proto = GetPrototype();
3540 if (proto->IsNull()) return result->NotFound(); 3533 if (proto->IsNull()) return result->NotFound();
3541 ASSERT(proto->IsJSGlobalObject()); 3534 ASSERT(proto->IsJSGlobalObject());
3542 return JSObject::cast(proto)->LocalLookup(name, result); 3535 return JSReceiver::cast(proto)->LocalLookup(name, result);
3536 }
3537
3538 if (IsJSProxy()) {
3539 result->HandlerResult(JSProxy::cast(this));
3540 return;
3543 } 3541 }
3544 3542
3545 // Do not use inline caching if the object is a non-global object 3543 // Do not use inline caching if the object is a non-global object
3546 // that requires access checks. 3544 // that requires access checks.
3547 if (!IsJSGlobalProxy() && IsAccessCheckNeeded()) { 3545 if (IsAccessCheckNeeded()) {
3548 result->DisallowCaching(); 3546 result->DisallowCaching();
3549 } 3547 }
3550 3548
3549 JSObject* js_object = JSObject::cast(this);
3550
3551 // Check __proto__ before interceptor. 3551 // Check __proto__ before interceptor.
3552 if (name->Equals(heap->Proto_symbol()) && !IsJSContextExtensionObject()) { 3552 if (name->Equals(heap->Proto_symbol()) && !IsJSContextExtensionObject()) {
3553 result->ConstantResult(this); 3553 result->ConstantResult(js_object);
3554 return; 3554 return;
3555 } 3555 }
3556 3556
3557 // Check for lookup interceptor except when bootstrapping. 3557 // Check for lookup interceptor except when bootstrapping.
3558 if (HasNamedInterceptor() && !heap->isolate()->bootstrapper()->IsActive()) { 3558 if (js_object->HasNamedInterceptor() &&
3559 result->InterceptorResult(this); 3559 !heap->isolate()->bootstrapper()->IsActive()) {
3560 result->InterceptorResult(js_object);
3560 return; 3561 return;
3561 } 3562 }
3562 3563
3563 LocalLookupRealNamedProperty(name, result); 3564 js_object->LocalLookupRealNamedProperty(name, result);
3564 } 3565 }
3565 3566
3566 3567
3567 void JSReceiver::Lookup(String* name, LookupResult* result) { 3568 void JSReceiver::Lookup(String* name, LookupResult* result) {
3568 // Ecma-262 3rd 8.6.2.4 3569 // Ecma-262 3rd 8.6.2.4
3569 Heap* heap = GetHeap(); 3570 Heap* heap = GetHeap();
3570 for (Object* current = this; 3571 for (Object* current = this;
3571 current != heap->null_value(); 3572 current != heap->null_value();
3572 current = JSObject::cast(current)->GetPrototype()) { 3573 current = JSObject::cast(current)->GetPrototype()) {
3573 JSObject::cast(current)->LocalLookup(name, result); 3574 JSReceiver::cast(current)->LocalLookup(name, result);
3574 if (result->IsProperty()) return; 3575 if (result->IsProperty()) return;
3575 } 3576 }
3576 result->NotFound(); 3577 result->NotFound();
3577 } 3578 }
3578 3579
3579 3580
3580 // Search object and it's prototype chain for callback properties. 3581 // Search object and it's prototype chain for callback properties.
3581 void JSObject::LookupCallback(String* name, LookupResult* result) { 3582 void JSObject::LookupCallback(String* name, LookupResult* result) {
3582 Heap* heap = GetHeap(); 3583 Heap* heap = GetHeap();
3583 for (Object* current = this; 3584 for (Object* current = this;
(...skipping 2626 matching lines...) Expand 10 before | Expand all | Expand 10 after
6210 for (int i = 0; i < descriptors->number_of_descriptors(); i++) { 6211 for (int i = 0; i < descriptors->number_of_descriptors(); i++) {
6211 if (descriptors->GetType(i) == MAP_TRANSITION || 6212 if (descriptors->GetType(i) == MAP_TRANSITION ||
6212 descriptors->GetType(i) == EXTERNAL_ARRAY_TRANSITION || 6213 descriptors->GetType(i) == EXTERNAL_ARRAY_TRANSITION ||
6213 descriptors->GetType(i) == CONSTANT_TRANSITION) { 6214 descriptors->GetType(i) == CONSTANT_TRANSITION) {
6214 // Get target. 6215 // Get target.
6215 Map* target = Map::cast(descriptors->GetValue(i)); 6216 Map* target = Map::cast(descriptors->GetValue(i));
6216 #ifdef DEBUG 6217 #ifdef DEBUG
6217 // Verify target. 6218 // Verify target.
6218 Object* source_prototype = prototype(); 6219 Object* source_prototype = prototype();
6219 Object* target_prototype = target->prototype(); 6220 Object* target_prototype = target->prototype();
6220 ASSERT(source_prototype->IsJSObject() || 6221 ASSERT(source_prototype->IsJSReceiver() ||
6221 source_prototype->IsMap() || 6222 source_prototype->IsMap() ||
6222 source_prototype->IsNull()); 6223 source_prototype->IsNull());
6223 ASSERT(target_prototype->IsJSObject() || 6224 ASSERT(target_prototype->IsJSReceiver() ||
6224 target_prototype->IsNull()); 6225 target_prototype->IsNull());
6225 ASSERT(source_prototype->IsMap() || 6226 ASSERT(source_prototype->IsMap() ||
6226 source_prototype == target_prototype); 6227 source_prototype == target_prototype);
6227 #endif 6228 #endif
6228 // Point target back to source. set_prototype() will not let us set 6229 // Point target back to source. set_prototype() will not let us set
6229 // the prototype to a map, as we do here. 6230 // the prototype to a map, as we do here.
6230 *RawField(target, kPrototypeOffset) = this; 6231 *RawField(target, kPrototypeOffset) = this;
6231 } 6232 }
6232 } 6233 }
6233 } 6234 }
(...skipping 1509 matching lines...) Expand 10 before | Expand all | Expand 10 after
7743 return heap->isolate()->Throw( 7744 return heap->isolate()->Throw(
7744 *FACTORY->NewTypeError("non_extensible_proto", 7745 *FACTORY->NewTypeError("non_extensible_proto",
7745 HandleVector<Object>(&handle, 1))); 7746 HandleVector<Object>(&handle, 1)));
7746 } 7747 }
7747 7748
7748 // Before we can set the prototype we need to be sure 7749 // Before we can set the prototype we need to be sure
7749 // prototype cycles are prevented. 7750 // prototype cycles are prevented.
7750 // It is sufficient to validate that the receiver is not in the new prototype 7751 // It is sufficient to validate that the receiver is not in the new prototype
7751 // chain. 7752 // chain.
7752 for (Object* pt = value; pt != heap->null_value(); pt = pt->GetPrototype()) { 7753 for (Object* pt = value; pt != heap->null_value(); pt = pt->GetPrototype()) {
7753 if (JSObject::cast(pt) == this) { 7754 if (JSReceiver::cast(pt) == this) {
7754 // Cycle detected. 7755 // Cycle detected.
7755 HandleScope scope(heap->isolate()); 7756 HandleScope scope(heap->isolate());
7756 return heap->isolate()->Throw( 7757 return heap->isolate()->Throw(
7757 *FACTORY->NewError("cyclic_proto", HandleVector<Object>(NULL, 0))); 7758 *FACTORY->NewError("cyclic_proto", HandleVector<Object>(NULL, 0)));
7758 } 7759 }
7759 } 7760 }
7760 7761
7761 JSReceiver* real_receiver = this; 7762 JSReceiver* real_receiver = this;
7762 7763
7763 if (skip_hidden_prototypes) { 7764 if (skip_hidden_prototypes) {
7764 // Find the first object in the chain whose prototype object is not 7765 // Find the first object in the chain whose prototype object is not
7765 // hidden and set the new prototype on that object. 7766 // hidden and set the new prototype on that object.
7766 Object* current_proto = real_receiver->GetPrototype(); 7767 Object* current_proto = real_receiver->GetPrototype();
7767 while (current_proto->IsJSObject() && 7768 while (current_proto->IsJSObject() &&
7768 JSObject::cast(current_proto)->map()->is_hidden_prototype()) { 7769 JSReceiver::cast(current_proto)->map()->is_hidden_prototype()) {
7769 real_receiver = JSObject::cast(current_proto); 7770 real_receiver = JSReceiver::cast(current_proto);
7770 current_proto = current_proto->GetPrototype(); 7771 current_proto = current_proto->GetPrototype();
7771 } 7772 }
7772 } 7773 }
7773 7774
7774 // Set the new prototype of the object. 7775 // Set the new prototype of the object.
7775 Map* map = real_receiver->map(); 7776 Map* map = real_receiver->map();
7776 7777
7777 // Nothing to do if prototype is already set. 7778 // Nothing to do if prototype is already set.
7778 if (map->prototype() == value) return value; 7779 if (map->prototype() == value) return value;
7779 7780
(...skipping 3821 matching lines...) Expand 10 before | Expand all | Expand 10 after
11601 if (break_point_objects()->IsUndefined()) return 0; 11602 if (break_point_objects()->IsUndefined()) return 0;
11602 // Single break point. 11603 // Single break point.
11603 if (!break_point_objects()->IsFixedArray()) return 1; 11604 if (!break_point_objects()->IsFixedArray()) return 1;
11604 // Multiple break points. 11605 // Multiple break points.
11605 return FixedArray::cast(break_point_objects())->length(); 11606 return FixedArray::cast(break_point_objects())->length();
11606 } 11607 }
11607 #endif 11608 #endif
11608 11609
11609 11610
11610 } } // namespace v8::internal 11611 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698