Chromium Code Reviews

Side by Side Diff: src/runtime.cc

Issue 6576024: (early draft) Strict mode - throw exception on assignment to read only property. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | | Annotate | Revision Log
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 142 matching lines...)
153 // an array. 153 // an array.
154 if (attributes != NONE) continue; 154 if (attributes != NONE) continue;
155 Object* value = 155 Object* value =
156 copy->GetProperty(key_string, &attributes)->ToObjectUnchecked(); 156 copy->GetProperty(key_string, &attributes)->ToObjectUnchecked();
157 if (value->IsJSObject()) { 157 if (value->IsJSObject()) {
158 JSObject* js_object = JSObject::cast(value); 158 JSObject* js_object = JSObject::cast(value);
159 { MaybeObject* maybe_result = DeepCopyBoilerplate(js_object); 159 { MaybeObject* maybe_result = DeepCopyBoilerplate(js_object);
160 if (!maybe_result->ToObject(&result)) return maybe_result; 160 if (!maybe_result->ToObject(&result)) return maybe_result;
161 } 161 }
162 { MaybeObject* maybe_result = 162 { MaybeObject* maybe_result =
163 copy->SetProperty(key_string, result, NONE); 163 // Creating object copy for literals. No strict mode needed.
164 copy->SetProperty(key_string, result, NONE, kNonStrictMode);
164 if (!maybe_result->ToObject(&result)) return maybe_result; 165 if (!maybe_result->ToObject(&result)) return maybe_result;
165 } 166 }
166 } 167 }
167 } 168 }
168 } 169 }
169 170
170 // Deep copy local elements. 171 // Deep copy local elements.
171 // Pixel elements cannot be created using an object literal. 172 // Pixel elements cannot be created using an object literal.
172 ASSERT(!copy->HasPixelElements() && !copy->HasExternalArrayElements()); 173 ASSERT(!copy->HasPixelElements() && !copy->HasExternalArrayElements());
173 switch (copy->GetElementsKind()) { 174 switch (copy->GetElementsKind()) {
(...skipping 365 matching lines...)
539 // Create a catch context extension object. 540 // Create a catch context extension object.
540 JSFunction* constructor = 541 JSFunction* constructor =
541 Top::context()->global_context()->context_extension_function(); 542 Top::context()->global_context()->context_extension_function();
542 Object* object; 543 Object* object;
543 { MaybeObject* maybe_object = Heap::AllocateJSObject(constructor); 544 { MaybeObject* maybe_object = Heap::AllocateJSObject(constructor);
544 if (!maybe_object->ToObject(&object)) return maybe_object; 545 if (!maybe_object->ToObject(&object)) return maybe_object;
545 } 546 }
546 // Assign the exception value to the catch variable and make sure 547 // Assign the exception value to the catch variable and make sure
547 // that the catch variable is DontDelete. 548 // that the catch variable is DontDelete.
548 { MaybeObject* maybe_value = 549 { MaybeObject* maybe_value =
549 JSObject::cast(object)->SetProperty(key, value, DONT_DELETE); 550 // Passing non-strict per Ecma-262 5th Ed. 12.14. Catch, bullet #4.
551 JSObject::cast(object)->SetProperty(
552 key, value, DONT_DELETE, kNonStrictMode);
550 if (!maybe_value->ToObject(&value)) return maybe_value; 553 if (!maybe_value->ToObject(&value)) return maybe_value;
551 } 554 }
552 return object; 555 return object;
553 } 556 }
554 557
555 558
556 static MaybeObject* Runtime_ClassOf(Arguments args) { 559 static MaybeObject* Runtime_ClassOf(Arguments args) {
557 NoHandleAllocation ha; 560 NoHandleAllocation ha;
558 ASSERT(args.length() == 1); 561 ASSERT(args.length() == 1);
559 Object* obj = args[0]; 562 Object* obj = args[0];
(...skipping 542 matching lines...)
1102 // difference for global functions with the same names as event 1105 // difference for global functions with the same names as event
1103 // handlers such as "function onload() {}". Firefox does call the 1106 // handlers such as "function onload() {}". Firefox does call the
1104 // onload setter in those case and Safari does not. We follow 1107 // onload setter in those case and Safari does not. We follow
1105 // Safari for compatibility. 1108 // Safari for compatibility.
1106 if (value->IsJSFunction()) { 1109 if (value->IsJSFunction()) {
1107 RETURN_IF_EMPTY_HANDLE(SetLocalPropertyIgnoreAttributes(global, 1110 RETURN_IF_EMPTY_HANDLE(SetLocalPropertyIgnoreAttributes(global,
1108 name, 1111 name,
1109 value, 1112 value,
1110 attributes)); 1113 attributes));
1111 } else { 1114 } else {
1112 RETURN_IF_EMPTY_HANDLE(SetProperty(global, name, value, attributes)); 1115 // TODO(mmaly): Runtime_DeclareGlobals. Do we need strict?
1116 RETURN_IF_EMPTY_HANDLE(SetProperty(global,
1117 name,
1118 value,
1119 attributes,
1120 kNonStrictMode));
1113 } 1121 }
1114 } 1122 }
1115 1123
1116 ASSERT(!Top::has_pending_exception()); 1124 ASSERT(!Top::has_pending_exception());
1117 return Heap::undefined_value(); 1125 return Heap::undefined_value();
1118 } 1126 }
1119 1127
1120 1128
1121 static MaybeObject* Runtime_DeclareContextSlot(Arguments args) { 1129 static MaybeObject* Runtime_DeclareContextSlot(Arguments args) {
1122 HandleScope scope; 1130 HandleScope scope;
(...skipping 40 matching lines...)
1163 } else { 1171 } else {
1164 // The holder is an arguments object. 1172 // The holder is an arguments object.
1165 Handle<JSObject> arguments(Handle<JSObject>::cast(holder)); 1173 Handle<JSObject> arguments(Handle<JSObject>::cast(holder));
1166 Handle<Object> result = SetElement(arguments, index, initial_value); 1174 Handle<Object> result = SetElement(arguments, index, initial_value);
1167 if (result.is_null()) return Failure::Exception(); 1175 if (result.is_null()) return Failure::Exception();
1168 } 1176 }
1169 } else { 1177 } else {
1170 // Slow case: The property is not in the FixedArray part of the context. 1178 // Slow case: The property is not in the FixedArray part of the context.
1171 Handle<JSObject> context_ext = Handle<JSObject>::cast(holder); 1179 Handle<JSObject> context_ext = Handle<JSObject>::cast(holder);
1172 RETURN_IF_EMPTY_HANDLE( 1180 RETURN_IF_EMPTY_HANDLE(
1173 SetProperty(context_ext, name, initial_value, mode)); 1181 // TODO(mmaly): Runtime_DeclareContextSlot. Need strict?
1182 SetProperty(context_ext, name, initial_value,
1183 mode, kNonStrictMode));
1174 } 1184 }
1175 } 1185 }
1176 1186
1177 } else { 1187 } else {
1178 // The property is not in the function context. It needs to be 1188 // The property is not in the function context. It needs to be
1179 // "declared" in the function context's extension context, or in the 1189 // "declared" in the function context's extension context, or in the
1180 // global context. 1190 // global context.
1181 Handle<JSObject> context_ext; 1191 Handle<JSObject> context_ext;
1182 if (context->has_extension()) { 1192 if (context->has_extension()) {
1183 // The function context's extension context exists - use it. 1193 // The function context's extension context exists - use it.
(...skipping 20 matching lines...)
1204 // SetProperty and no setters are invoked for those since they are 1214 // SetProperty and no setters are invoked for those since they are
1205 // not real JSObjects. 1215 // not real JSObjects.
1206 if (initial_value->IsTheHole() && 1216 if (initial_value->IsTheHole() &&
1207 !context_ext->IsJSContextExtensionObject()) { 1217 !context_ext->IsJSContextExtensionObject()) {
1208 LookupResult lookup; 1218 LookupResult lookup;
1209 context_ext->Lookup(*name, &lookup); 1219 context_ext->Lookup(*name, &lookup);
1210 if (lookup.IsProperty() && (lookup.type() == CALLBACKS)) { 1220 if (lookup.IsProperty() && (lookup.type() == CALLBACKS)) {
1211 return ThrowRedeclarationError("const", name); 1221 return ThrowRedeclarationError("const", name);
1212 } 1222 }
1213 } 1223 }
1214 RETURN_IF_EMPTY_HANDLE(SetProperty(context_ext, name, value, mode)); 1224 // TODO(mmaly): Runtime_DeclareContextSlot. Need strict?
1225 RETURN_IF_EMPTY_HANDLE(SetProperty(context_ext, name, value, mode,
1226 kNonStrictMode));
1215 } 1227 }
1216 1228
1217 return Heap::undefined_value(); 1229 return Heap::undefined_value();
1218 } 1230 }
1219 1231
1220 1232
1221 static MaybeObject* Runtime_InitializeVarGlobal(Arguments args) { 1233 static MaybeObject* Runtime_InitializeVarGlobal(Arguments args) {
1222 NoHandleAllocation nha; 1234 NoHandleAllocation nha;
1223 1235
1224 // Determine if we need to assign to the variable if it already 1236 // Determine if we need to assign to the variable if it already
(...skipping 52 matching lines...)
1277 } 1289 }
1278 1290
1279 if (found && !assign) { 1291 if (found && !assign) {
1280 // The global property is there and we're not assigning any value 1292 // The global property is there and we're not assigning any value
1281 // to it. Just return. 1293 // to it. Just return.
1282 return Heap::undefined_value(); 1294 return Heap::undefined_value();
1283 } 1295 }
1284 1296
1285 // Assign the value (or undefined) to the property. 1297 // Assign the value (or undefined) to the property.
1286 Object* value = (assign) ? args[1] : Heap::undefined_value(); 1298 Object* value = (assign) ? args[1] : Heap::undefined_value();
1287 return real_holder->SetProperty(&lookup, *name, value, attributes); 1299 // TODO(mmaly): Runtime_InitializeVarGlobal. pass strict mode through?
1300 return real_holder->SetProperty(&lookup, *name, value, attributes,
1301 kNonStrictMode);
1288 } 1302 }
1289 1303
1290 Object* proto = real_holder->GetPrototype(); 1304 Object* proto = real_holder->GetPrototype();
1291 if (!proto->IsJSObject()) 1305 if (!proto->IsJSObject())
1292 break; 1306 break;
1293 1307
1294 if (!JSObject::cast(proto)->map()->is_hidden_prototype()) 1308 if (!JSObject::cast(proto)->map()->is_hidden_prototype())
1295 break; 1309 break;
1296 1310
1297 real_holder = JSObject::cast(proto); 1311 real_holder = JSObject::cast(proto);
1298 } 1312 }
1299 1313
1300 global = Top::context()->global(); 1314 global = Top::context()->global();
1301 if (assign) return global->SetProperty(*name, args[1], attributes); 1315 if (assign) {
1316 // TODO(mmaly): Runtime_InitializeVarGlobal. pass strict mode through?
1317 return global->SetProperty(*name, args[1], attributes, kNonStrictMode);
1318 }
1302 return Heap::undefined_value(); 1319 return Heap::undefined_value();
1303 } 1320 }
1304 1321
1305 1322
1306 static MaybeObject* Runtime_InitializeConstGlobal(Arguments args) { 1323 static MaybeObject* Runtime_InitializeConstGlobal(Arguments args) {
1307 // All constants are declared with an initial value. The name 1324 // All constants are declared with an initial value. The name
1308 // of the constant is the first argument and the initial value 1325 // of the constant is the first argument and the initial value
1309 // is the second. 1326 // is the second.
1310 RUNTIME_ASSERT(args.length() == 2); 1327 RUNTIME_ASSERT(args.length() == 2);
1311 CONVERT_ARG_CHECKED(String, name, 0); 1328 CONVERT_ARG_CHECKED(String, name, 0);
(...skipping 38 matching lines...)
1350 1367
1351 // Restore global object from context (in case of GC) and continue 1368 // Restore global object from context (in case of GC) and continue
1352 // with setting the value because the property is either absent or 1369 // with setting the value because the property is either absent or
1353 // read-only. We also have to do redo the lookup. 1370 // read-only. We also have to do redo the lookup.
1354 HandleScope handle_scope; 1371 HandleScope handle_scope;
1355 Handle<GlobalObject> global(Top::context()->global()); 1372 Handle<GlobalObject> global(Top::context()->global());
1356 1373
1357 // BUG 1213575: Handle the case where we have to set a read-only 1374 // BUG 1213575: Handle the case where we have to set a read-only
1358 // property through an interceptor and only do it if it's 1375 // property through an interceptor and only do it if it's
1359 // uninitialized, e.g. the hole. Nirk... 1376 // uninitialized, e.g. the hole. Nirk...
1360 RETURN_IF_EMPTY_HANDLE(SetProperty(global, name, value, attributes)); 1377 // Passing non-strict mode because the property is writable.
1378 RETURN_IF_EMPTY_HANDLE(SetProperty(global,
1379 name,
1380 value,
1381 attributes,
1382 kNonStrictMode));
1361 return *value; 1383 return *value;
1362 } 1384 }
1363 1385
1364 // Set the value, but only we're assigning the initial value to a 1386 // Set the value, but only we're assigning the initial value to a
1365 // constant. For now, we determine this by checking if the 1387 // constant. For now, we determine this by checking if the
1366 // current value is the hole. 1388 // current value is the hole.
1367 PropertyType type = lookup.type(); 1389 PropertyType type = lookup.type();
1368 if (type == FIELD) { 1390 if (type == FIELD) {
1369 FixedArray* properties = global->properties(); 1391 FixedArray* properties = global->properties();
1370 int index = lookup.GetFieldIndex(); 1392 int index = lookup.GetFieldIndex();
1371 if (properties->get(index)->IsTheHole()) { 1393 if (properties->get(index)->IsTheHole()) {
1372 properties->set(index, *value); 1394 properties->set(index, *value);
1373 } 1395 }
1396 // TODO(mmaly): Runtime_InitializeConstGlobal. throw in strict mode?
1374 } else if (type == NORMAL) { 1397 } else if (type == NORMAL) {
1375 if (global->GetNormalizedProperty(&lookup)->IsTheHole()) { 1398 if (global->GetNormalizedProperty(&lookup)->IsTheHole()) {
1376 global->SetNormalizedProperty(&lookup, *value); 1399 global->SetNormalizedProperty(&lookup, *value);
1377 } 1400 }
1401 // TODO(mmaly): Runtime_InitializeConstGlobal. throw in strict mode?
1378 } else { 1402 } else {
1379 // Ignore re-initialization of constants that have already been 1403 // Ignore re-initialization of constants that have already been
1380 // assigned a function value. 1404 // assigned a function value.
1381 ASSERT(lookup.IsReadOnly() && type == CONSTANT_FUNCTION); 1405 ASSERT(lookup.IsReadOnly() && type == CONSTANT_FUNCTION);
1406 // TODO(mmaly): Runtime_InitializeConstGlobal. throw in strict mode?
1382 } 1407 }
1383 1408
1384 // Use the set value as the result of the operation. 1409 // Use the set value as the result of the operation.
1385 return *value; 1410 return *value;
1386 } 1411 }
1387 1412
1388 1413
1389 static MaybeObject* Runtime_InitializeConstContextSlot(Arguments args) { 1414 static MaybeObject* Runtime_InitializeConstContextSlot(Arguments args) {
1390 HandleScope scope; 1415 HandleScope scope;
1391 ASSERT(args.length() == 3); 1416 ASSERT(args.length() == 3);
(...skipping 40 matching lines...)
1432 Handle<JSObject> arguments(Handle<JSObject>::cast(holder)); 1457 Handle<JSObject> arguments(Handle<JSObject>::cast(holder));
1433 SetElement(arguments, index, value); 1458 SetElement(arguments, index, value);
1434 } 1459 }
1435 return *value; 1460 return *value;
1436 } 1461 }
1437 1462
1438 // The property could not be found, we introduce it in the global 1463 // The property could not be found, we introduce it in the global
1439 // context. 1464 // context.
1440 if (attributes == ABSENT) { 1465 if (attributes == ABSENT) {
1441 Handle<JSObject> global = Handle<JSObject>(Top::context()->global()); 1466 Handle<JSObject> global = Handle<JSObject>(Top::context()->global());
1442 RETURN_IF_EMPTY_HANDLE(SetProperty(global, name, value, NONE)); 1467 // TODO(mmaly): Runtime_InitializeConstContextSlot. Probably needs strict.
1468 // (introduces variable in global context) unless this is only called
1469 // from with which is disabled in strict mode.
1470 RETURN_IF_EMPTY_HANDLE(SetProperty(global, name, value, NONE, kNonStrictMode ));
1443 return *value; 1471 return *value;
1444 } 1472 }
1445 1473
1446 // The property was present in a context extension object. 1474 // The property was present in a context extension object.
1447 Handle<JSObject> context_ext = Handle<JSObject>::cast(holder); 1475 Handle<JSObject> context_ext = Handle<JSObject>::cast(holder);
1448 1476
1449 if (*context_ext == context->extension()) { 1477 if (*context_ext == context->extension()) {
1450 // This is the property that was introduced by the const 1478 // This is the property that was introduced by the const
1451 // declaration. Set it if it hasn't been set before. NOTE: We 1479 // declaration. Set it if it hasn't been set before. NOTE: We
1452 // cannot use GetProperty() to get the current value as it 1480 // cannot use GetProperty() to get the current value as it
(...skipping 16 matching lines...)
1469 } 1497 }
1470 } else { 1498 } else {
1471 // We should not reach here. Any real, named property should be 1499 // We should not reach here. Any real, named property should be
1472 // either a field or a dictionary slot. 1500 // either a field or a dictionary slot.
1473 UNREACHABLE(); 1501 UNREACHABLE();
1474 } 1502 }
1475 } else { 1503 } else {
1476 // The property was found in a different context extension object. 1504 // The property was found in a different context extension object.
1477 // Set it if it is not a read-only property. 1505 // Set it if it is not a read-only property.
1478 if ((attributes & READ_ONLY) == 0) { 1506 if ((attributes & READ_ONLY) == 0) {
1507 // TODO(mmaly): Runtime_InitializeConstContextSlot. Probably should throw
1508 // if strict mode and r/o property. Unless this is only called from
1509 // with which is disabled in strict mode.
1479 RETURN_IF_EMPTY_HANDLE( 1510 RETURN_IF_EMPTY_HANDLE(
1480 SetProperty(context_ext, name, value, attributes)); 1511 SetProperty(context_ext, name, value, attributes, kNonStrictMode));
1481 } 1512 }
1482 } 1513 }
1483 1514
1484 return *value; 1515 return *value;
1485 } 1516 }
1486 1517
1487 1518
1488 static MaybeObject* Runtime_OptimizeObjectForAddingMultipleProperties( 1519 static MaybeObject* Runtime_OptimizeObjectForAddingMultipleProperties(
1489 Arguments args) { 1520 Arguments args) {
1490 HandleScope scope; 1521 HandleScope scope;
(...skipping 145 matching lines...)
1636 const char* name, 1667 const char* name,
1637 Builtins::Name builtin_name) { 1668 Builtins::Name builtin_name) {
1638 Handle<String> key = Factory::LookupAsciiSymbol(name); 1669 Handle<String> key = Factory::LookupAsciiSymbol(name);
1639 Handle<Code> code(Builtins::builtin(builtin_name)); 1670 Handle<Code> code(Builtins::builtin(builtin_name));
1640 Handle<JSFunction> optimized = Factory::NewFunction(key, 1671 Handle<JSFunction> optimized = Factory::NewFunction(key,
1641 JS_OBJECT_TYPE, 1672 JS_OBJECT_TYPE,
1642 JSObject::kHeaderSize, 1673 JSObject::kHeaderSize,
1643 code, 1674 code,
1644 false); 1675 false);
1645 optimized->shared()->DontAdaptArguments(); 1676 optimized->shared()->DontAdaptArguments();
1646 SetProperty(holder, key, optimized, NONE); 1677 // No need for strict mode here. Called from SetupArray (array.js).
1678 SetProperty(holder, key, optimized, NONE, kNonStrictMode);
1647 return optimized; 1679 return optimized;
1648 } 1680 }
1649 1681
1650 1682
1651 static MaybeObject* Runtime_SpecialArrayFunctions(Arguments args) { 1683 static MaybeObject* Runtime_SpecialArrayFunctions(Arguments args) {
1652 HandleScope scope; 1684 HandleScope scope;
1653 ASSERT(args.length() == 1); 1685 ASSERT(args.length() == 1);
1654 CONVERT_ARG_CHECKED(JSObject, holder, 0); 1686 CONVERT_ARG_CHECKED(JSObject, holder, 0);
1655 1687
1656 InstallBuiltin(holder, "pop", Builtins::ArrayPop); 1688 InstallBuiltin(holder, "pop", Builtins::ArrayPop);
(...skipping 2075 matching lines...)
3732 attr); 3764 attr);
3733 } 3765 }
3734 3766
3735 return Runtime::ForceSetObjectProperty(js_object, name, obj_value, attr); 3767 return Runtime::ForceSetObjectProperty(js_object, name, obj_value, attr);
3736 } 3768 }
3737 3769
3738 3770
3739 MaybeObject* Runtime::SetObjectProperty(Handle<Object> object, 3771 MaybeObject* Runtime::SetObjectProperty(Handle<Object> object,
3740 Handle<Object> key, 3772 Handle<Object> key,
3741 Handle<Object> value, 3773 Handle<Object> value,
3742 PropertyAttributes attr) { 3774 PropertyAttributes attr,
3775 StrictModeFlag strict) {
3743 HandleScope scope; 3776 HandleScope scope;
3744 3777
3745 if (object->IsUndefined() || object->IsNull()) { 3778 if (object->IsUndefined() || object->IsNull()) {
3746 Handle<Object> args[2] = { key, object }; 3779 Handle<Object> args[2] = { key, object };
3747 Handle<Object> error = 3780 Handle<Object> error =
3748 Factory::NewTypeError("non_object_property_store", 3781 Factory::NewTypeError("non_object_property_store",
3749 HandleVector(args, 2)); 3782 HandleVector(args, 2));
3750 return Top::Throw(*error); 3783 return Top::Throw(*error);
3751 } 3784 }
3752 3785
3753 // If the object isn't a JavaScript object, we ignore the store. 3786 // If the object isn't a JavaScript object, we ignore the store.
3754 if (!object->IsJSObject()) return *value; 3787 if (!object->IsJSObject()) return *value;
3755 3788
3756 Handle<JSObject> js_object = Handle<JSObject>::cast(object); 3789 Handle<JSObject> js_object = Handle<JSObject>::cast(object);
3757 3790
3758 // Check if the given key is an array index. 3791 // Check if the given key is an array index.
3759 uint32_t index; 3792 uint32_t index;
3760 if (key->ToArrayIndex(&index)) { 3793 if (key->ToArrayIndex(&index)) {
3761 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters 3794 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
3762 // of a string using [] notation. We need to support this too in 3795 // of a string using [] notation. We need to support this too in
3763 // JavaScript. 3796 // JavaScript.
3764 // In the case of a String object we just need to redirect the assignment to 3797 // In the case of a String object we just need to redirect the assignment to
3765 // the underlying string if the index is in range. Since the underlying 3798 // the underlying string if the index is in range. Since the underlying
3766 // string does nothing with the assignment then we can ignore such 3799 // string does nothing with the assignment then we can ignore such
3767 // assignments. 3800 // assignments.
3768 if (js_object->IsStringObjectWithCharacterAt(index)) { 3801 if (js_object->IsStringObjectWithCharacterAt(index)) {
3769 return *value; 3802 return *value;
3770 } 3803 }
3771 3804
3805 // TODO(mmaly): SetElement strict mode.
Martin Maly 2011/02/24 06:33:34 The big todo. SetElement currently does no strict
3772 Handle<Object> result = SetElement(js_object, index, value); 3806 Handle<Object> result = SetElement(js_object, index, value);
3773 if (result.is_null()) return Failure::Exception(); 3807 if (result.is_null()) return Failure::Exception();
3774 return *value; 3808 return *value;
3775 } 3809 }
3776 3810
3777 if (key->IsString()) { 3811 if (key->IsString()) {
3778 Handle<Object> result; 3812 Handle<Object> result;
3779 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { 3813 if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
3780 result = SetElement(js_object, index, value); 3814 result = SetElement(js_object, index, value);
3781 } else { 3815 } else {
3782 Handle<String> key_string = Handle<String>::cast(key); 3816 Handle<String> key_string = Handle<String>::cast(key);
3783 key_string->TryFlatten(); 3817 key_string->TryFlatten();
3784 result = SetProperty(js_object, key_string, value, attr); 3818 result = SetProperty(js_object, key_string, value, attr, strict);
3785 } 3819 }
3786 if (result.is_null()) return Failure::Exception(); 3820 if (result.is_null()) return Failure::Exception();
3787 return *value; 3821 return *value;
3788 } 3822 }
3789 3823
3790 // Call-back into JavaScript to convert the key to a string. 3824 // Call-back into JavaScript to convert the key to a string.
3791 bool has_pending_exception = false; 3825 bool has_pending_exception = false;
3792 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); 3826 Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
3793 if (has_pending_exception) return Failure::Exception(); 3827 if (has_pending_exception) return Failure::Exception();
3794 Handle<String> name = Handle<String>::cast(converted); 3828 Handle<String> name = Handle<String>::cast(converted);
3795 3829
3796 if (name->AsArrayIndex(&index)) { 3830 if (name->AsArrayIndex(&index)) {
3831 // TODO(mmaly): Strict mode handling in SetElement.
3797 return js_object->SetElement(index, *value); 3832 return js_object->SetElement(index, *value);
3798 } else { 3833 } else {
3799 return js_object->SetProperty(*name, *value, attr); 3834 return js_object->SetProperty(*name, *value, attr, strict);
3800 } 3835 }
3801 } 3836 }
3802 3837
3803 3838
3804 MaybeObject* Runtime::ForceSetObjectProperty(Handle<JSObject> js_object, 3839 MaybeObject* Runtime::ForceSetObjectProperty(Handle<JSObject> js_object,
3805 Handle<Object> key, 3840 Handle<Object> key,
3806 Handle<Object> value, 3841 Handle<Object> value,
3807 PropertyAttributes attr) { 3842 PropertyAttributes attr) {
3808 HandleScope scope; 3843 HandleScope scope;
3809 3844
(...skipping 71 matching lines...)
3881 key_string = Handle<String>::cast(converted); 3916 key_string = Handle<String>::cast(converted);
3882 } 3917 }
3883 3918
3884 key_string->TryFlatten(); 3919 key_string->TryFlatten();
3885 return js_object->DeleteProperty(*key_string, JSObject::FORCE_DELETION); 3920 return js_object->DeleteProperty(*key_string, JSObject::FORCE_DELETION);
3886 } 3921 }
3887 3922
3888 3923
3889 static MaybeObject* Runtime_SetProperty(Arguments args) { 3924 static MaybeObject* Runtime_SetProperty(Arguments args) {
3890 NoHandleAllocation ha; 3925 NoHandleAllocation ha;
3891 RUNTIME_ASSERT(args.length() == 3 || args.length() == 4); 3926 RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
3892 3927
3893 Handle<Object> object = args.at<Object>(0); 3928 Handle<Object> object = args.at<Object>(0);
3894 Handle<Object> key = args.at<Object>(1); 3929 Handle<Object> key = args.at<Object>(1);
3895 Handle<Object> value = args.at<Object>(2); 3930 Handle<Object> value = args.at<Object>(2);
3931 CONVERT_SMI_CHECKED(unchecked_attributes, args[3]);
3932 RUNTIME_ASSERT(
3933 (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
3934 // Compute attributes.
3935 PropertyAttributes attributes =
3936 static_cast<PropertyAttributes>(unchecked_attributes);
3896 3937
3897 // Compute attributes. 3938 StrictModeFlag strict = kNonStrictMode;
3898 PropertyAttributes attributes = NONE; 3939 if (args.length() == 5) {
3899 if (args.length() == 4) { 3940 CONVERT_SMI_CHECKED(strict_unchecked, args[4]);
3900 CONVERT_CHECKED(Smi, value_obj, args[3]); 3941 RUNTIME_ASSERT(strict_unchecked == kStrictMode ||
3901 int unchecked_value = value_obj->value(); 3942 strict_unchecked == kNonStrictMode);
3902 // Only attribute bits should be set. 3943 strict = static_cast<StrictModeFlag>(strict_unchecked);
3903 RUNTIME_ASSERT(
3904 (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
3905 attributes = static_cast<PropertyAttributes>(unchecked_value);
3906 } 3944 }
3907 return Runtime::SetObjectProperty(object, key, value, attributes); 3945
3946 return Runtime::SetObjectProperty(object, key, value, attributes, strict);
3908 } 3947 }
3909 3948
3910 3949
3911 // Set a local property, even if it is READ_ONLY. If the property does not 3950 // Set a local property, even if it is READ_ONLY. If the property does not
3912 // exist, it will be added with attributes NONE. 3951 // exist, it will be added with attributes NONE.
3913 static MaybeObject* Runtime_IgnoreAttributesAndSetProperty(Arguments args) { 3952 static MaybeObject* Runtime_IgnoreAttributesAndSetProperty(Arguments args) {
3914 NoHandleAllocation ha; 3953 NoHandleAllocation ha;
3915 RUNTIME_ASSERT(args.length() == 3 || args.length() == 4); 3954 RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
3916 CONVERT_CHECKED(JSObject, object, args[0]); 3955 CONVERT_CHECKED(JSObject, object, args[0]);
3917 CONVERT_CHECKED(String, name, args[1]); 3956 CONVERT_CHECKED(String, name, args[1]);
(...skipping 3557 matching lines...)
7475 } 7514 }
7476 7515
7477 7516
7478 static ObjectPair Runtime_LoadContextSlotNoReferenceError(Arguments args) { 7517 static ObjectPair Runtime_LoadContextSlotNoReferenceError(Arguments args) {
7479 return LoadContextSlotHelper(args, false); 7518 return LoadContextSlotHelper(args, false);
7480 } 7519 }
7481 7520
7482 7521
7483 static MaybeObject* Runtime_StoreContextSlot(Arguments args) { 7522 static MaybeObject* Runtime_StoreContextSlot(Arguments args) {
7484 HandleScope scope; 7523 HandleScope scope;
7485 ASSERT(args.length() == 3); 7524 ASSERT(args.length() == 4);
7486 7525
7487 Handle<Object> value(args[0]); 7526 Handle<Object> value(args[0]);
7488 CONVERT_ARG_CHECKED(Context, context, 1); 7527 CONVERT_ARG_CHECKED(Context, context, 1);
7489 CONVERT_ARG_CHECKED(String, name, 2); 7528 CONVERT_ARG_CHECKED(String, name, 2);
7529 CONVERT_SMI_CHECKED(strict_unchecked, args[3]);
7530 RUNTIME_ASSERT(strict_unchecked == kStrictMode ||
7531 strict_unchecked == kNonStrictMode);
7532 StrictModeFlag strict = static_cast<StrictModeFlag>(strict_unchecked);
7533
7490 7534
7491 int index; 7535 int index;
7492 PropertyAttributes attributes; 7536 PropertyAttributes attributes;
7493 ContextLookupFlags flags = FOLLOW_CHAINS; 7537 ContextLookupFlags flags = FOLLOW_CHAINS;
7494 Handle<Object> holder = context->Lookup(name, flags, &index, &attributes); 7538 Handle<Object> holder = context->Lookup(name, flags, &index, &attributes);
7495 7539
7496 if (index >= 0) { 7540 if (index >= 0) {
7497 if (holder->IsContext()) { 7541 if (holder->IsContext()) {
7498 // Ignore if read_only variable. 7542 // Ignore if read_only variable.
7499 if ((attributes & READ_ONLY) == 0) { 7543 if ((attributes & READ_ONLY) == 0) {
(...skipping 23 matching lines...)
7523 // The property was not found. It needs to be stored in the global context. 7567 // The property was not found. It needs to be stored in the global context.
7524 ASSERT(attributes == ABSENT); 7568 ASSERT(attributes == ABSENT);
7525 attributes = NONE; 7569 attributes = NONE;
7526 context_ext = Handle<JSObject>(Top::context()->global()); 7570 context_ext = Handle<JSObject>(Top::context()->global());
7527 } 7571 }
7528 7572
7529 // Set the property, but ignore if read_only variable on the context 7573 // Set the property, but ignore if read_only variable on the context
7530 // extension object itself. 7574 // extension object itself.
7531 if ((attributes & READ_ONLY) == 0 || 7575 if ((attributes & READ_ONLY) == 0 ||
7532 (context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) { 7576 (context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) {
7533 RETURN_IF_EMPTY_HANDLE(SetProperty(context_ext, name, value, NONE)); 7577 RETURN_IF_EMPTY_HANDLE(SetProperty(context_ext, name, value, NONE, strict));
7578 } else if (strict == kStrictMode && (attributes & READ_ONLY) != 0) {
7579 // Setting read only property in strict mode.
7580 Handle<Object> error =
7581 Factory::NewTypeError("strict_cannot_assign", HandleVector(&name, 1));
7582 return Top::Throw(*error);
7534 } 7583 }
7535 return *value; 7584 return *value;
7536 } 7585 }
7537 7586
7538 7587
7539 static MaybeObject* Runtime_Throw(Arguments args) { 7588 static MaybeObject* Runtime_Throw(Arguments args) {
7540 HandleScope scope; 7589 HandleScope scope;
7541 ASSERT(args.length() == 1); 7590 ASSERT(args.length() == 1);
7542 7591
7543 return Top::Throw(args[0]); 7592 return Top::Throw(args[0]);
(...skipping 1641 matching lines...)
9185 i < scope_info.number_of_context_slots(); 9234 i < scope_info.number_of_context_slots();
9186 i++) { 9235 i++) {
9187 int context_index = serialized_scope_info->ContextSlotIndex( 9236 int context_index = serialized_scope_info->ContextSlotIndex(
9188 *scope_info.context_slot_name(i), NULL); 9237 *scope_info.context_slot_name(i), NULL);
9189 9238
9190 // Don't include the arguments shadow (.arguments) context variable. 9239 // Don't include the arguments shadow (.arguments) context variable.
9191 if (*scope_info.context_slot_name(i) != Heap::arguments_shadow_symbol()) { 9240 if (*scope_info.context_slot_name(i) != Heap::arguments_shadow_symbol()) {
9192 RETURN_IF_EMPTY_HANDLE_VALUE( 9241 RETURN_IF_EMPTY_HANDLE_VALUE(
9193 SetProperty(scope_object, 9242 SetProperty(scope_object,
9194 scope_info.context_slot_name(i), 9243 scope_info.context_slot_name(i),
9195 Handle<Object>(context->get(context_index)), NONE), 9244 Handle<Object>(context->get(context_index)),
9245 NONE,
9246 kNonStrictMode),
9196 false); 9247 false);
9197 } 9248 }
9198 } 9249 }
9199 9250
9200 return true; 9251 return true;
9201 } 9252 }
9202 9253
9203 9254
9204 // Create a plain JSObject which materializes the local scope for the specified 9255 // Create a plain JSObject which materializes the local scope for the specified
9205 // frame. 9256 // frame.
9206 static Handle<JSObject> MaterializeLocalScope(JavaScriptFrame* frame) { 9257 static Handle<JSObject> MaterializeLocalScope(JavaScriptFrame* frame) {
9207 Handle<JSFunction> function(JSFunction::cast(frame->function())); 9258 Handle<JSFunction> function(JSFunction::cast(frame->function()));
9208 Handle<SharedFunctionInfo> shared(function->shared()); 9259 Handle<SharedFunctionInfo> shared(function->shared());
9209 Handle<SerializedScopeInfo> serialized_scope_info(shared->scope_info()); 9260 Handle<SerializedScopeInfo> serialized_scope_info(shared->scope_info());
9210 ScopeInfo<> scope_info(*serialized_scope_info); 9261 ScopeInfo<> scope_info(*serialized_scope_info);
9211 9262
9212 // Allocate and initialize a JSObject with all the arguments, stack locals 9263 // Allocate and initialize a JSObject with all the arguments, stack locals
9213 // heap locals and extension properties of the debugged function. 9264 // heap locals and extension properties of the debugged function.
9214 Handle<JSObject> local_scope = Factory::NewJSObject(Top::object_function()); 9265 Handle<JSObject> local_scope = Factory::NewJSObject(Top::object_function());
9215 9266
9216 // First fill all parameters. 9267 // First fill all parameters.
9217 for (int i = 0; i < scope_info.number_of_parameters(); ++i) { 9268 for (int i = 0; i < scope_info.number_of_parameters(); ++i) {
9218 RETURN_IF_EMPTY_HANDLE_VALUE( 9269 RETURN_IF_EMPTY_HANDLE_VALUE(
9219 SetProperty(local_scope, 9270 SetProperty(local_scope,
9220 scope_info.parameter_name(i), 9271 scope_info.parameter_name(i),
9221 Handle<Object>(frame->GetParameter(i)), NONE), 9272 Handle<Object>(frame->GetParameter(i)),
9273 NONE,
9274 kNonStrictMode),
9222 Handle<JSObject>()); 9275 Handle<JSObject>());
9223 } 9276 }
9224 9277
9225 // Second fill all stack locals. 9278 // Second fill all stack locals.
9226 for (int i = 0; i < scope_info.number_of_stack_slots(); i++) { 9279 for (int i = 0; i < scope_info.number_of_stack_slots(); i++) {
9227 RETURN_IF_EMPTY_HANDLE_VALUE( 9280 RETURN_IF_EMPTY_HANDLE_VALUE(
9228 SetProperty(local_scope, 9281 SetProperty(local_scope,
9229 scope_info.stack_slot_name(i), 9282 scope_info.stack_slot_name(i),
9230 Handle<Object>(frame->GetExpression(i)), NONE), 9283 Handle<Object>(frame->GetExpression(i)),
9284 NONE,
9285 kNonStrictMode),
9231 Handle<JSObject>()); 9286 Handle<JSObject>());
9232 } 9287 }
9233 9288
9234 // Third fill all context locals. 9289 // Third fill all context locals.
9235 Handle<Context> frame_context(Context::cast(frame->context())); 9290 Handle<Context> frame_context(Context::cast(frame->context()));
9236 Handle<Context> function_context(frame_context->fcontext()); 9291 Handle<Context> function_context(frame_context->fcontext());
9237 if (!CopyContextLocalsToScopeObject(serialized_scope_info, scope_info, 9292 if (!CopyContextLocalsToScopeObject(serialized_scope_info, scope_info,
9238 function_context, local_scope)) { 9293 function_context, local_scope)) {
9239 return Handle<JSObject>(); 9294 return Handle<JSObject>();
9240 } 9295 }
9241 9296
9242 // Finally copy any properties from the function context extension. This will 9297 // Finally copy any properties from the function context extension. This will
9243 // be variables introduced by eval. 9298 // be variables introduced by eval.
9244 if (function_context->closure() == *function) { 9299 if (function_context->closure() == *function) {
9245 if (function_context->has_extension() && 9300 if (function_context->has_extension() &&
9246 !function_context->IsGlobalContext()) { 9301 !function_context->IsGlobalContext()) {
9247 Handle<JSObject> ext(JSObject::cast(function_context->extension())); 9302 Handle<JSObject> ext(JSObject::cast(function_context->extension()));
9248 Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS); 9303 Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS);
9249 for (int i = 0; i < keys->length(); i++) { 9304 for (int i = 0; i < keys->length(); i++) {
9250 // Names of variables introduced by eval are strings. 9305 // Names of variables introduced by eval are strings.
9251 ASSERT(keys->get(i)->IsString()); 9306 ASSERT(keys->get(i)->IsString());
9252 Handle<String> key(String::cast(keys->get(i))); 9307 Handle<String> key(String::cast(keys->get(i)));
9253 RETURN_IF_EMPTY_HANDLE_VALUE( 9308 RETURN_IF_EMPTY_HANDLE_VALUE(
9254 SetProperty(local_scope, key, GetProperty(ext, key), NONE), 9309 SetProperty(local_scope,
9310 key,
9311 GetProperty(ext, key),
9312 NONE,
9313 kNonStrictMode),
9255 Handle<JSObject>()); 9314 Handle<JSObject>());
9256 } 9315 }
9257 } 9316 }
9258 } 9317 }
9259 return local_scope; 9318 return local_scope;
9260 } 9319 }
9261 9320
9262 9321
9263 // Create a plain JSObject which materializes the closure content for the 9322 // Create a plain JSObject which materializes the closure content for the
9264 // context. 9323 // context.
(...skipping 17 matching lines...)
9282 // object. 9341 // object.
9283 Handle<JSObject> arguments_shadow( 9342 Handle<JSObject> arguments_shadow(
9284 JSObject::cast(context->get(arguments_shadow_index))); 9343 JSObject::cast(context->get(arguments_shadow_index)));
9285 for (int i = 0; i < scope_info.number_of_parameters(); ++i) { 9344 for (int i = 0; i < scope_info.number_of_parameters(); ++i) {
9286 // We don't expect exception-throwing getters on the arguments shadow. 9345 // We don't expect exception-throwing getters on the arguments shadow.
9287 Object* element = arguments_shadow->GetElement(i)->ToObjectUnchecked(); 9346 Object* element = arguments_shadow->GetElement(i)->ToObjectUnchecked();
9288 RETURN_IF_EMPTY_HANDLE_VALUE( 9347 RETURN_IF_EMPTY_HANDLE_VALUE(
9289 SetProperty(closure_scope, 9348 SetProperty(closure_scope,
9290 scope_info.parameter_name(i), 9349 scope_info.parameter_name(i),
9291 Handle<Object>(element), 9350 Handle<Object>(element),
9292 NONE), 9351 NONE,
9352 kNonStrictMode),
9293 Handle<JSObject>()); 9353 Handle<JSObject>());
9294 } 9354 }
9295 } 9355 }
9296 9356
9297 // Fill all context locals to the context extension. 9357 // Fill all context locals to the context extension.
9298 if (!CopyContextLocalsToScopeObject(serialized_scope_info, scope_info, 9358 if (!CopyContextLocalsToScopeObject(serialized_scope_info, scope_info,
9299 context, closure_scope)) { 9359 context, closure_scope)) {
9300 return Handle<JSObject>(); 9360 return Handle<JSObject>();
9301 } 9361 }
9302 9362
9303 // Finally copy any properties from the function context extension. This will 9363 // Finally copy any properties from the function context extension. This will
9304 // be variables introduced by eval. 9364 // be variables introduced by eval.
9305 if (context->has_extension()) { 9365 if (context->has_extension()) {
9306 Handle<JSObject> ext(JSObject::cast(context->extension())); 9366 Handle<JSObject> ext(JSObject::cast(context->extension()));
9307 Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS); 9367 Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS);
9308 for (int i = 0; i < keys->length(); i++) { 9368 for (int i = 0; i < keys->length(); i++) {
9309 // Names of variables introduced by eval are strings. 9369 // Names of variables introduced by eval are strings.
9310 ASSERT(keys->get(i)->IsString()); 9370 ASSERT(keys->get(i)->IsString());
9311 Handle<String> key(String::cast(keys->get(i))); 9371 Handle<String> key(String::cast(keys->get(i)));
9312 RETURN_IF_EMPTY_HANDLE_VALUE( 9372 RETURN_IF_EMPTY_HANDLE_VALUE(
9313 SetProperty(closure_scope, key, GetProperty(ext, key), NONE), 9373 SetProperty(closure_scope, key, GetProperty(ext, key), NONE, kNonStric tMode),
9314 Handle<JSObject>()); 9374 Handle<JSObject>());
9315 } 9375 }
9316 } 9376 }
9317 9377
9318 return closure_scope; 9378 return closure_scope;
9319 } 9379 }
9320 9380
9321 9381
9322 // Iterate over the actual scopes visible from a stack frame. All scopes are 9382 // Iterate over the actual scopes visible from a stack frame. All scopes are
9323 // backed by an actual context except the local scope, which is inserted 9383 // backed by an actual context except the local scope, which is inserted
(...skipping 1897 matching lines...)
11221 } else { 11281 } else {
11222 // Handle last resort GC and make sure to allow future allocations 11282 // Handle last resort GC and make sure to allow future allocations
11223 // to grow the heap without causing GCs (if possible). 11283 // to grow the heap without causing GCs (if possible).
11224 Counters::gc_last_resort_from_js.Increment(); 11284 Counters::gc_last_resort_from_js.Increment();
11225 Heap::CollectAllGarbage(false); 11285 Heap::CollectAllGarbage(false);
11226 } 11286 }
11227 } 11287 }
11228 11288
11229 11289
11230 } } // namespace v8::internal 11290 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine