| 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 1131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1142 Handle<Object> type_handle = | 1142 Handle<Object> type_handle = |
| 1143 isolate->factory()->NewStringFromAscii(CStrVector(type)); | 1143 isolate->factory()->NewStringFromAscii(CStrVector(type)); |
| 1144 Handle<Object> args[2] = { type_handle, name }; | 1144 Handle<Object> args[2] = { type_handle, name }; |
| 1145 Handle<Object> error = | 1145 Handle<Object> error = |
| 1146 isolate->factory()->NewTypeError("redeclaration", HandleVector(args, 2)); | 1146 isolate->factory()->NewTypeError("redeclaration", HandleVector(args, 2)); |
| 1147 return isolate->Throw(*error); | 1147 return isolate->Throw(*error); |
| 1148 } | 1148 } |
| 1149 | 1149 |
| 1150 | 1150 |
| 1151 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { | 1151 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { |
| 1152 ASSERT(args.length() == 4); | 1152 ASSERT(args.length() == 3); |
| 1153 HandleScope scope(isolate); | 1153 HandleScope scope(isolate); |
| 1154 Handle<GlobalObject> global = Handle<GlobalObject>( | 1154 Handle<GlobalObject> global = Handle<GlobalObject>( |
| 1155 isolate->context()->global()); | 1155 isolate->context()->global()); |
| 1156 | 1156 |
| 1157 Handle<Context> context = args.at<Context>(0); | 1157 Handle<Context> context = args.at<Context>(0); |
| 1158 CONVERT_ARG_CHECKED(FixedArray, pairs, 1); | 1158 CONVERT_ARG_CHECKED(FixedArray, pairs, 1); |
| 1159 bool is_eval = args.smi_at(2) == 1; | 1159 CONVERT_SMI_ARG_CHECKED(flags, 2); |
| 1160 StrictModeFlag strict_mode = static_cast<StrictModeFlag>(args.smi_at(3)); | |
| 1161 ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode); | |
| 1162 | |
| 1163 // Compute the property attributes. According to ECMA-262, section | |
| 1164 // 13, page 71, the property must be read-only and | |
| 1165 // non-deletable. However, neither SpiderMonkey nor KJS creates the | |
| 1166 // property as read-only, so we don't either. | |
| 1167 PropertyAttributes base = is_eval ? NONE : DONT_DELETE; | |
| 1168 | 1160 |
| 1169 // Traverse the name/value pairs and set the properties. | 1161 // Traverse the name/value pairs and set the properties. |
| 1170 int length = pairs->length(); | 1162 int length = pairs->length(); |
| 1171 for (int i = 0; i < length; i += 2) { | 1163 for (int i = 0; i < length; i += 2) { |
| 1172 HandleScope scope(isolate); | 1164 HandleScope scope(isolate); |
| 1173 Handle<String> name(String::cast(pairs->get(i))); | 1165 Handle<String> name(String::cast(pairs->get(i))); |
| 1174 Handle<Object> value(pairs->get(i + 1), isolate); | 1166 Handle<Object> value(pairs->get(i + 1), isolate); |
| 1175 | 1167 |
| 1176 // We have to declare a global const property. To capture we only | 1168 // We have to declare a global const property. To capture we only |
| 1177 // assign to it when evaluating the assignment for "const x = | 1169 // assign to it when evaluating the assignment for "const x = |
| 1178 // <expr>" the initial value is the hole. | 1170 // <expr>" the initial value is the hole. |
| 1179 bool is_const_property = value->IsTheHole(); | 1171 bool is_const_property = value->IsTheHole(); |
| 1180 | 1172 bool is_function_declaration = false; |
| 1181 if (value->IsUndefined() || is_const_property) { | 1173 if (value->IsUndefined() || is_const_property) { |
| 1182 // Lookup the property in the global object, and don't set the | 1174 // Lookup the property in the global object, and don't set the |
| 1183 // value of the variable if the property is already there. | 1175 // value of the variable if the property is already there. |
| 1184 LookupResult lookup; | 1176 LookupResult lookup; |
| 1185 global->Lookup(*name, &lookup); | 1177 global->Lookup(*name, &lookup); |
| 1186 if (lookup.IsProperty()) { | 1178 if (lookup.IsProperty()) { |
| 1187 // Determine if the property is local by comparing the holder | 1179 // Determine if the property is local by comparing the holder |
| 1188 // against the global object. The information will be used to | 1180 // against the global object. The information will be used to |
| 1189 // avoid throwing re-declaration errors when declaring | 1181 // avoid throwing re-declaration errors when declaring |
| 1190 // variables or constants that exist in the prototype chain. | 1182 // variables or constants that exist in the prototype chain. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1219 if (is_local && (is_read_only || is_const_property)) { | 1211 if (is_local && (is_read_only || is_const_property)) { |
| 1220 const char* type = (is_read_only) ? "const" : "var"; | 1212 const char* type = (is_read_only) ? "const" : "var"; |
| 1221 return ThrowRedeclarationError(isolate, type, name); | 1213 return ThrowRedeclarationError(isolate, type, name); |
| 1222 } | 1214 } |
| 1223 // The property already exists without conflicting: Go to | 1215 // The property already exists without conflicting: Go to |
| 1224 // the next declaration. | 1216 // the next declaration. |
| 1225 continue; | 1217 continue; |
| 1226 } | 1218 } |
| 1227 } | 1219 } |
| 1228 } else { | 1220 } else { |
| 1221 is_function_declaration = true; |
| 1229 // Copy the function and update its context. Use it as value. | 1222 // Copy the function and update its context. Use it as value. |
| 1230 Handle<SharedFunctionInfo> shared = | 1223 Handle<SharedFunctionInfo> shared = |
| 1231 Handle<SharedFunctionInfo>::cast(value); | 1224 Handle<SharedFunctionInfo>::cast(value); |
| 1232 Handle<JSFunction> function = | 1225 Handle<JSFunction> function = |
| 1233 isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, | 1226 isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, |
| 1234 context, | 1227 context, |
| 1235 TENURED); | 1228 TENURED); |
| 1236 value = function; | 1229 value = function; |
| 1237 } | 1230 } |
| 1238 | 1231 |
| 1239 LookupResult lookup; | 1232 LookupResult lookup; |
| 1240 global->LocalLookup(*name, &lookup); | 1233 global->LocalLookup(*name, &lookup); |
| 1241 | 1234 |
| 1242 PropertyAttributes attributes = is_const_property | |
| 1243 ? static_cast<PropertyAttributes>(base | READ_ONLY) | |
| 1244 : base; | |
| 1245 | |
| 1246 // There's a local property that we need to overwrite because | 1235 // There's a local property that we need to overwrite because |
| 1247 // we're either declaring a function or there's an interceptor | 1236 // we're either declaring a function or there's an interceptor |
| 1248 // that claims the property is absent. | 1237 // that claims the property is absent. |
| 1249 // | 1238 // |
| 1250 // Check for conflicting re-declarations. We cannot have | 1239 // Check for conflicting re-declarations. We cannot have |
| 1251 // conflicting types in case of intercepted properties because | 1240 // conflicting types in case of intercepted properties because |
| 1252 // they are absent. | 1241 // they are absent. |
| 1253 if (lookup.IsProperty() && | 1242 if (lookup.IsProperty() && |
| 1254 (lookup.type() != INTERCEPTOR) && | 1243 (lookup.type() != INTERCEPTOR) && |
| 1255 (lookup.IsReadOnly() || is_const_property)) { | 1244 (lookup.IsReadOnly() || is_const_property)) { |
| 1256 const char* type = (lookup.IsReadOnly()) ? "const" : "var"; | 1245 const char* type = (lookup.IsReadOnly()) ? "const" : "var"; |
| 1257 return ThrowRedeclarationError(isolate, type, name); | 1246 return ThrowRedeclarationError(isolate, type, name); |
| 1258 } | 1247 } |
| 1259 | 1248 |
| 1249 // Compute the property attributes. According to ECMA-262, section |
| 1250 // 13, page 71, the property must be read-only and |
| 1251 // non-deletable. However, neither SpiderMonkey nor KJS creates the |
| 1252 // property as read-only, so we don't either. |
| 1253 int attr = NONE; |
| 1254 if ((flags & kDeclareGlobalsEvalFlag) == 0) { |
| 1255 attr |= DONT_DELETE; |
| 1256 } |
| 1257 bool is_native = (flags & kDeclareGlobalsNativeFlag) != 0; |
| 1258 if (is_const_property || (is_native && is_function_declaration)) { |
| 1259 attr |= READ_ONLY; |
| 1260 } |
| 1261 |
| 1260 // Safari does not allow the invocation of callback setters for | 1262 // Safari does not allow the invocation of callback setters for |
| 1261 // function declarations. To mimic this behavior, we do not allow | 1263 // function declarations. To mimic this behavior, we do not allow |
| 1262 // the invocation of setters for function values. This makes a | 1264 // the invocation of setters for function values. This makes a |
| 1263 // difference for global functions with the same names as event | 1265 // difference for global functions with the same names as event |
| 1264 // handlers such as "function onload() {}". Firefox does call the | 1266 // handlers such as "function onload() {}". Firefox does call the |
| 1265 // onload setter in those case and Safari does not. We follow | 1267 // onload setter in those case and Safari does not. We follow |
| 1266 // Safari for compatibility. | 1268 // Safari for compatibility. |
| 1267 if (value->IsJSFunction()) { | 1269 if (value->IsJSFunction()) { |
| 1268 // Do not change DONT_DELETE to false from true. | 1270 // Do not change DONT_DELETE to false from true. |
| 1269 if (lookup.IsProperty() && (lookup.type() != INTERCEPTOR)) { | 1271 if (lookup.IsProperty() && (lookup.type() != INTERCEPTOR)) { |
| 1270 attributes = static_cast<PropertyAttributes>( | 1272 attr |= lookup.GetAttributes() & DONT_DELETE; |
| 1271 attributes | (lookup.GetAttributes() & DONT_DELETE)); | |
| 1272 } | 1273 } |
| 1274 PropertyAttributes attributes = static_cast<PropertyAttributes>(attr); |
| 1275 |
| 1273 RETURN_IF_EMPTY_HANDLE(isolate, | 1276 RETURN_IF_EMPTY_HANDLE(isolate, |
| 1274 SetLocalPropertyIgnoreAttributes(global, | 1277 SetLocalPropertyIgnoreAttributes(global, |
| 1275 name, | 1278 name, |
| 1276 value, | 1279 value, |
| 1277 attributes)); | 1280 attributes)); |
| 1278 } else { | 1281 } else { |
| 1282 StrictModeFlag strict_mode = |
| 1283 ((flags & kDeclareGlobalsStrictModeFlag) != 0) ? kStrictMode |
| 1284 : kNonStrictMode; |
| 1279 RETURN_IF_EMPTY_HANDLE(isolate, | 1285 RETURN_IF_EMPTY_HANDLE(isolate, |
| 1280 SetProperty(global, | 1286 SetProperty(global, |
| 1281 name, | 1287 name, |
| 1282 value, | 1288 value, |
| 1283 attributes, | 1289 static_cast<PropertyAttributes>(attr), |
| 1284 strict_mode)); | 1290 strict_mode)); |
| 1285 } | 1291 } |
| 1286 } | 1292 } |
| 1287 | 1293 |
| 1288 ASSERT(!isolate->has_pending_exception()); | 1294 ASSERT(!isolate->has_pending_exception()); |
| 1289 return isolate->heap()->undefined_value(); | 1295 return isolate->heap()->undefined_value(); |
| 1290 } | 1296 } |
| 1291 | 1297 |
| 1292 | 1298 |
| 1293 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) { | 1299 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) { |
| (...skipping 11693 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12987 } else { | 12993 } else { |
| 12988 // Handle last resort GC and make sure to allow future allocations | 12994 // Handle last resort GC and make sure to allow future allocations |
| 12989 // to grow the heap without causing GCs (if possible). | 12995 // to grow the heap without causing GCs (if possible). |
| 12990 isolate->counters()->gc_last_resort_from_js()->Increment(); | 12996 isolate->counters()->gc_last_resort_from_js()->Increment(); |
| 12991 isolate->heap()->CollectAllGarbage(false); | 12997 isolate->heap()->CollectAllGarbage(false); |
| 12992 } | 12998 } |
| 12993 } | 12999 } |
| 12994 | 13000 |
| 12995 | 13001 |
| 12996 } } // namespace v8::internal | 13002 } } // namespace v8::internal |
| OLD | NEW |