OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |