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

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

Powered by Google App Engine
This is Rietveld 408576698