| 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 |