| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/runtime/runtime-utils.h" | 5 #include "src/runtime/runtime-utils.h" |
| 6 | 6 |
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/arguments.h" | 8 #include "src/arguments.h" |
| 9 #include "src/ast/scopeinfo.h" | 9 #include "src/ast/scopeinfo.h" |
| 10 #include "src/ast/scopes.h" | 10 #include "src/ast/scopes.h" |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 HandleScope scope(isolate); | 27 HandleScope scope(isolate); |
| 28 THROW_NEW_ERROR_RETURN_FAILURE(isolate, | 28 THROW_NEW_ERROR_RETURN_FAILURE(isolate, |
| 29 NewTypeError(MessageTemplate::kConstAssign)); | 29 NewTypeError(MessageTemplate::kConstAssign)); |
| 30 } | 30 } |
| 31 | 31 |
| 32 | 32 |
| 33 // May throw a RedeclarationError. | 33 // May throw a RedeclarationError. |
| 34 static Object* DeclareGlobals(Isolate* isolate, Handle<JSGlobalObject> global, | 34 static Object* DeclareGlobals(Isolate* isolate, Handle<JSGlobalObject> global, |
| 35 Handle<String> name, Handle<Object> value, | 35 Handle<String> name, Handle<Object> value, |
| 36 PropertyAttributes attr, bool is_var, | 36 PropertyAttributes attr, bool is_var, |
| 37 bool is_const, bool is_function) { | 37 bool is_function) { |
| 38 Handle<ScriptContextTable> script_contexts( | 38 Handle<ScriptContextTable> script_contexts( |
| 39 global->native_context()->script_context_table()); | 39 global->native_context()->script_context_table()); |
| 40 ScriptContextTable::LookupResult lookup; | 40 ScriptContextTable::LookupResult lookup; |
| 41 if (ScriptContextTable::Lookup(script_contexts, name, &lookup) && | 41 if (ScriptContextTable::Lookup(script_contexts, name, &lookup) && |
| 42 IsLexicalVariableMode(lookup.mode)) { | 42 IsLexicalVariableMode(lookup.mode)) { |
| 43 return ThrowRedeclarationError(isolate, name); | 43 return ThrowRedeclarationError(isolate, name); |
| 44 } | 44 } |
| 45 | 45 |
| 46 // Do the lookup own properties only, see ES5 erratum. | 46 // Do the lookup own properties only, see ES5 erratum. |
| 47 LookupIterator it(global, name, global, LookupIterator::OWN_SKIP_INTERCEPTOR); | 47 LookupIterator it(global, name, global, LookupIterator::OWN_SKIP_INTERCEPTOR); |
| 48 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); | 48 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); |
| 49 if (!maybe.IsJust()) return isolate->heap()->exception(); | 49 if (!maybe.IsJust()) return isolate->heap()->exception(); |
| 50 | 50 |
| 51 if (it.IsFound()) { | 51 if (it.IsFound()) { |
| 52 PropertyAttributes old_attributes = maybe.FromJust(); | 52 PropertyAttributes old_attributes = maybe.FromJust(); |
| 53 // The name was declared before; check for conflicting re-declarations. | 53 // The name was declared before; check for conflicting re-declarations. |
| 54 if (is_const) return ThrowRedeclarationError(isolate, name); | |
| 55 | 54 |
| 56 // Skip var re-declarations. | 55 // Skip var re-declarations. |
| 57 if (is_var) return isolate->heap()->undefined_value(); | 56 if (is_var) return isolate->heap()->undefined_value(); |
| 58 | 57 |
| 59 DCHECK(is_function); | 58 DCHECK(is_function); |
| 60 if ((old_attributes & DONT_DELETE) != 0) { | 59 if ((old_attributes & DONT_DELETE) != 0) { |
| 61 // Only allow reconfiguring globals to functions in user code (no | 60 // Only allow reconfiguring globals to functions in user code (no |
| 62 // natives, which are marked as read-only). | 61 // natives, which are marked as read-only). |
| 63 DCHECK((attr & READ_ONLY) == 0); | 62 DCHECK((attr & READ_ONLY) == 0); |
| 64 | 63 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 | 98 |
| 100 CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 0); | 99 CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 0); |
| 101 CONVERT_SMI_ARG_CHECKED(flags, 1); | 100 CONVERT_SMI_ARG_CHECKED(flags, 1); |
| 102 | 101 |
| 103 // Traverse the name/value pairs and set the properties. | 102 // Traverse the name/value pairs and set the properties. |
| 104 int length = pairs->length(); | 103 int length = pairs->length(); |
| 105 FOR_WITH_HANDLE_SCOPE(isolate, int, i = 0, i, i < length, i += 2, { | 104 FOR_WITH_HANDLE_SCOPE(isolate, int, i = 0, i, i < length, i += 2, { |
| 106 Handle<String> name(String::cast(pairs->get(i))); | 105 Handle<String> name(String::cast(pairs->get(i))); |
| 107 Handle<Object> initial_value(pairs->get(i + 1), isolate); | 106 Handle<Object> initial_value(pairs->get(i + 1), isolate); |
| 108 | 107 |
| 109 // We have to declare a global const property. To capture we only | |
| 110 // assign to it when evaluating the assignment for "const x = | |
| 111 // <expr>" the initial value is the hole. | |
| 112 bool is_var = initial_value->IsUndefined(isolate); | 108 bool is_var = initial_value->IsUndefined(isolate); |
| 113 bool is_const = initial_value->IsTheHole(isolate); | |
| 114 bool is_function = initial_value->IsSharedFunctionInfo(); | 109 bool is_function = initial_value->IsSharedFunctionInfo(); |
| 115 DCHECK_EQ(1, | 110 DCHECK_EQ(1, BoolToInt(is_var) + BoolToInt(is_function)); |
| 116 BoolToInt(is_var) + BoolToInt(is_const) + BoolToInt(is_function)); | |
| 117 | 111 |
| 118 Handle<Object> value; | 112 Handle<Object> value; |
| 119 if (is_function) { | 113 if (is_function) { |
| 120 // Copy the function and update its context. Use it as value. | 114 // Copy the function and update its context. Use it as value. |
| 121 Handle<SharedFunctionInfo> shared = | 115 Handle<SharedFunctionInfo> shared = |
| 122 Handle<SharedFunctionInfo>::cast(initial_value); | 116 Handle<SharedFunctionInfo>::cast(initial_value); |
| 123 Handle<JSFunction> function = | 117 Handle<JSFunction> function = |
| 124 isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context, | 118 isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context, |
| 125 TENURED); | 119 TENURED); |
| 126 value = function; | 120 value = function; |
| 127 } else { | 121 } else { |
| 128 value = isolate->factory()->undefined_value(); | 122 value = isolate->factory()->undefined_value(); |
| 129 } | 123 } |
| 130 | 124 |
| 131 // Compute the property attributes. According to ECMA-262, | 125 // Compute the property attributes. According to ECMA-262, |
| 132 // the property must be non-configurable except in eval. | 126 // the property must be non-configurable except in eval. |
| 133 bool is_native = DeclareGlobalsNativeFlag::decode(flags); | 127 bool is_native = DeclareGlobalsNativeFlag::decode(flags); |
| 134 bool is_eval = DeclareGlobalsEvalFlag::decode(flags); | 128 bool is_eval = DeclareGlobalsEvalFlag::decode(flags); |
| 135 int attr = NONE; | 129 int attr = NONE; |
| 136 if (is_const) attr |= READ_ONLY; | |
| 137 if (is_function && is_native) attr |= READ_ONLY; | 130 if (is_function && is_native) attr |= READ_ONLY; |
| 138 if (!is_const && !is_eval) attr |= DONT_DELETE; | 131 if (!is_eval) attr |= DONT_DELETE; |
| 139 | 132 |
| 140 Object* result = DeclareGlobals(isolate, global, name, value, | 133 Object* result = DeclareGlobals(isolate, global, name, value, |
| 141 static_cast<PropertyAttributes>(attr), | 134 static_cast<PropertyAttributes>(attr), |
| 142 is_var, is_const, is_function); | 135 is_var, is_function); |
| 143 if (isolate->has_pending_exception()) return result; | 136 if (isolate->has_pending_exception()) return result; |
| 144 }); | 137 }); |
| 145 | 138 |
| 146 return isolate->heap()->undefined_value(); | 139 return isolate->heap()->undefined_value(); |
| 147 } | 140 } |
| 148 | 141 |
| 149 | 142 |
| 150 RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) { | 143 RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) { |
| 151 HandleScope scope(isolate); | 144 HandleScope scope(isolate); |
| 152 DCHECK_EQ(3, args.length()); | 145 DCHECK_EQ(3, args.length()); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 203 PropertyAttributes attr) { | 196 PropertyAttributes attr) { |
| 204 // Declarations are always made in a function, eval or script context, or | 197 // Declarations are always made in a function, eval or script context, or |
| 205 // a declaration block scope. | 198 // a declaration block scope. |
| 206 // In the case of eval code, the context passed is the context of the caller, | 199 // In the case of eval code, the context passed is the context of the caller, |
| 207 // which may be some nested context and not the declaration context. | 200 // which may be some nested context and not the declaration context. |
| 208 Handle<Context> context_arg(isolate->context(), isolate); | 201 Handle<Context> context_arg(isolate->context(), isolate); |
| 209 Handle<Context> context(context_arg->declaration_context(), isolate); | 202 Handle<Context> context(context_arg->declaration_context(), isolate); |
| 210 | 203 |
| 211 // TODO(verwaest): Unify the encoding indicating "var" with DeclareGlobals. | 204 // TODO(verwaest): Unify the encoding indicating "var" with DeclareGlobals. |
| 212 bool is_var = *initial_value == NULL; | 205 bool is_var = *initial_value == NULL; |
| 213 bool is_const = initial_value->IsTheHole(isolate); | |
| 214 bool is_function = initial_value->IsJSFunction(); | 206 bool is_function = initial_value->IsJSFunction(); |
| 215 DCHECK_EQ(1, | 207 DCHECK_EQ(1, BoolToInt(is_var) + BoolToInt(is_function)); |
| 216 BoolToInt(is_var) + BoolToInt(is_const) + BoolToInt(is_function)); | |
| 217 | 208 |
| 218 int index; | 209 int index; |
| 219 PropertyAttributes attributes; | 210 PropertyAttributes attributes; |
| 220 BindingFlags binding_flags; | 211 BindingFlags binding_flags; |
| 221 | 212 |
| 222 if ((attr & EVAL_DECLARED) != 0) { | 213 if ((attr & EVAL_DECLARED) != 0) { |
| 223 // Check for a conflict with a lexically scoped variable | 214 // Check for a conflict with a lexically scoped variable |
| 224 context_arg->Lookup(name, LEXICAL_TEST, &index, &attributes, | 215 context_arg->Lookup(name, LEXICAL_TEST, &index, &attributes, |
| 225 &binding_flags); | 216 &binding_flags); |
| 226 if (attributes != ABSENT && binding_flags == BINDING_CHECK_INITIALIZED) { | 217 if (attributes != ABSENT && binding_flags == BINDING_CHECK_INITIALIZED) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 238 | 229 |
| 239 Handle<JSObject> object; | 230 Handle<JSObject> object; |
| 240 Handle<Object> value = | 231 Handle<Object> value = |
| 241 is_function ? initial_value | 232 is_function ? initial_value |
| 242 : Handle<Object>::cast(isolate->factory()->undefined_value()); | 233 : Handle<Object>::cast(isolate->factory()->undefined_value()); |
| 243 | 234 |
| 244 // TODO(verwaest): This case should probably not be covered by this function, | 235 // TODO(verwaest): This case should probably not be covered by this function, |
| 245 // but by DeclareGlobals instead. | 236 // but by DeclareGlobals instead. |
| 246 if (attributes != ABSENT && holder->IsJSGlobalObject()) { | 237 if (attributes != ABSENT && holder->IsJSGlobalObject()) { |
| 247 return DeclareGlobals(isolate, Handle<JSGlobalObject>::cast(holder), name, | 238 return DeclareGlobals(isolate, Handle<JSGlobalObject>::cast(holder), name, |
| 248 value, attr, is_var, is_const, is_function); | 239 value, attr, is_var, is_function); |
| 249 } | 240 } |
| 250 if (context_arg->extension()->IsJSGlobalObject()) { | 241 if (context_arg->extension()->IsJSGlobalObject()) { |
| 251 Handle<JSGlobalObject> global( | 242 Handle<JSGlobalObject> global( |
| 252 JSGlobalObject::cast(context_arg->extension()), isolate); | 243 JSGlobalObject::cast(context_arg->extension()), isolate); |
| 253 return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const, | 244 return DeclareGlobals(isolate, global, name, value, attr, is_var, |
| 254 is_function); | 245 is_function); |
| 255 } else if (context->IsScriptContext()) { | 246 } else if (context->IsScriptContext()) { |
| 256 DCHECK(context->global_object()->IsJSGlobalObject()); | 247 DCHECK(context->global_object()->IsJSGlobalObject()); |
| 257 Handle<JSGlobalObject> global( | 248 Handle<JSGlobalObject> global( |
| 258 JSGlobalObject::cast(context->global_object()), isolate); | 249 JSGlobalObject::cast(context->global_object()), isolate); |
| 259 return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const, | 250 return DeclareGlobals(isolate, global, name, value, attr, is_var, |
| 260 is_function); | 251 is_function); |
| 261 } | 252 } |
| 262 | 253 |
| 263 if (attributes != ABSENT) { | 254 if (attributes != ABSENT) { |
| 264 // The name was declared before; check for conflicting re-declarations. | 255 // The name was declared before; check for conflicting re-declarations. |
| 265 if (is_const || (attributes & READ_ONLY) != 0) { | 256 if ((attributes & READ_ONLY) != 0) { |
| 266 return ThrowRedeclarationError(isolate, name); | 257 return ThrowRedeclarationError(isolate, name); |
| 267 } | 258 } |
| 268 | 259 |
| 269 // Skip var re-declarations. | 260 // Skip var re-declarations. |
| 270 if (is_var) return isolate->heap()->undefined_value(); | 261 if (is_var) return isolate->heap()->undefined_value(); |
| 271 | 262 |
| 272 DCHECK(is_function); | 263 DCHECK(is_function); |
| 273 if (index != Context::kNotFound) { | 264 if (index != Context::kNotFound) { |
| 274 DCHECK(holder.is_identical_to(context)); | 265 DCHECK(holder.is_identical_to(context)); |
| 275 context->set(index, *initial_value); | 266 context->set(index, *initial_value); |
| (...skipping 735 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1011 RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Strict) { | 1002 RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Strict) { |
| 1012 HandleScope scope(isolate); | 1003 HandleScope scope(isolate); |
| 1013 DCHECK_EQ(2, args.length()); | 1004 DCHECK_EQ(2, args.length()); |
| 1014 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); | 1005 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); |
| 1015 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); | 1006 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); |
| 1016 RETURN_RESULT_OR_FAILURE(isolate, StoreLookupSlot(name, value, STRICT)); | 1007 RETURN_RESULT_OR_FAILURE(isolate, StoreLookupSlot(name, value, STRICT)); |
| 1017 } | 1008 } |
| 1018 | 1009 |
| 1019 } // namespace internal | 1010 } // namespace internal |
| 1020 } // namespace v8 | 1011 } // namespace v8 |
| OLD | NEW |