Chromium Code Reviews| 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" |
| 11 #include "src/deoptimizer.h" | 11 #include "src/deoptimizer.h" |
| 12 #include "src/frames-inl.h" | 12 #include "src/frames-inl.h" |
| 13 #include "src/isolate-inl.h" | 13 #include "src/isolate-inl.h" |
| 14 #include "src/messages.h" | 14 #include "src/messages.h" |
| 15 | 15 |
| 16 namespace v8 { | 16 namespace v8 { |
| 17 namespace internal { | 17 namespace internal { |
| 18 | 18 |
| 19 static Object* ThrowRedeclarationError(Isolate* isolate, Handle<String> name) { | 19 struct RedeclarationError { |
|
adamk
2016/06/09 15:08:42
You can use 'enum class' to get the same thing wit
| |
| 20 enum Type { kSyntaxError = 0, kTypeError = 1 }; | |
| 21 }; | |
| 22 | |
| 23 static Object* ThrowRedeclarationError( | |
| 24 Isolate* isolate, Handle<String> name, | |
| 25 RedeclarationError::Type redeclaration_error_type) { | |
| 20 HandleScope scope(isolate); | 26 HandleScope scope(isolate); |
| 21 THROW_NEW_ERROR_RETURN_FAILURE( | 27 if (redeclaration_error_type == RedeclarationError::kSyntaxError) { |
| 22 isolate, NewTypeError(MessageTemplate::kVarRedeclaration, name)); | 28 THROW_NEW_ERROR_RETURN_FAILURE( |
| 29 isolate, NewSyntaxError(MessageTemplate::kVarRedeclaration, name)); | |
| 30 } else { | |
| 31 THROW_NEW_ERROR_RETURN_FAILURE( | |
| 32 isolate, NewTypeError(MessageTemplate::kVarRedeclaration, name)); | |
| 33 } | |
| 23 } | 34 } |
| 24 | 35 |
| 25 | 36 |
| 26 RUNTIME_FUNCTION(Runtime_ThrowConstAssignError) { | 37 RUNTIME_FUNCTION(Runtime_ThrowConstAssignError) { |
| 27 HandleScope scope(isolate); | 38 HandleScope scope(isolate); |
| 28 THROW_NEW_ERROR_RETURN_FAILURE(isolate, | 39 THROW_NEW_ERROR_RETURN_FAILURE(isolate, |
| 29 NewTypeError(MessageTemplate::kConstAssign)); | 40 NewTypeError(MessageTemplate::kConstAssign)); |
| 30 } | 41 } |
| 31 | 42 |
| 32 | 43 |
| 33 // May throw a RedeclarationError. | 44 // May throw a RedeclarationError. |
| 34 static Object* DeclareGlobals(Isolate* isolate, Handle<JSGlobalObject> global, | 45 static Object* DeclareGlobals( |
| 35 Handle<String> name, Handle<Object> value, | 46 Isolate* isolate, Handle<JSGlobalObject> global, Handle<String> name, |
| 36 PropertyAttributes attr, bool is_var, | 47 Handle<Object> value, PropertyAttributes attr, bool is_var, bool is_const, |
| 37 bool is_const, bool is_function) { | 48 bool is_function, RedeclarationError::Type redeclaration_error_type) { |
| 38 Handle<ScriptContextTable> script_contexts( | 49 Handle<ScriptContextTable> script_contexts( |
| 39 global->native_context()->script_context_table()); | 50 global->native_context()->script_context_table()); |
| 40 ScriptContextTable::LookupResult lookup; | 51 ScriptContextTable::LookupResult lookup; |
| 41 if (ScriptContextTable::Lookup(script_contexts, name, &lookup) && | 52 if (ScriptContextTable::Lookup(script_contexts, name, &lookup) && |
| 42 IsLexicalVariableMode(lookup.mode)) { | 53 IsLexicalVariableMode(lookup.mode)) { |
| 43 return ThrowRedeclarationError(isolate, name); | 54 // ES#sec-globaldeclarationinstantiation 6.a: |
| 55 // If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError | |
| 56 // exception. | |
| 57 return ThrowRedeclarationError(isolate, name, | |
| 58 RedeclarationError::kSyntaxError); | |
| 44 } | 59 } |
| 45 | 60 |
| 46 // Do the lookup own properties only, see ES5 erratum. | 61 // Do the lookup own properties only, see ES5 erratum. |
| 47 LookupIterator it(global, name, global, LookupIterator::OWN_SKIP_INTERCEPTOR); | 62 LookupIterator it(global, name, global, LookupIterator::OWN_SKIP_INTERCEPTOR); |
| 48 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); | 63 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); |
| 49 if (!maybe.IsJust()) return isolate->heap()->exception(); | 64 if (!maybe.IsJust()) return isolate->heap()->exception(); |
| 50 | 65 |
| 51 if (it.IsFound()) { | 66 if (it.IsFound()) { |
| 52 PropertyAttributes old_attributes = maybe.FromJust(); | 67 PropertyAttributes old_attributes = maybe.FromJust(); |
| 53 // The name was declared before; check for conflicting re-declarations. | 68 // The name was declared before; check for conflicting re-declarations. |
| 54 if (is_const) return ThrowRedeclarationError(isolate, name); | 69 if (is_const) { |
|
adamk
2016/06/09 15:08:42
Did you say this code is unreachable?
| |
| 70 return ThrowRedeclarationError(isolate, name, | |
| 71 RedeclarationError::kSyntaxError); | |
| 72 } | |
| 55 | 73 |
| 56 // Skip var re-declarations. | 74 // Skip var re-declarations. |
| 57 if (is_var) return isolate->heap()->undefined_value(); | 75 if (is_var) return isolate->heap()->undefined_value(); |
| 58 | 76 |
| 59 DCHECK(is_function); | 77 DCHECK(is_function); |
| 60 if ((old_attributes & DONT_DELETE) != 0) { | 78 if ((old_attributes & DONT_DELETE) != 0) { |
| 61 // Only allow reconfiguring globals to functions in user code (no | 79 // Only allow reconfiguring globals to functions in user code (no |
| 62 // natives, which are marked as read-only). | 80 // natives, which are marked as read-only). |
| 63 DCHECK((attr & READ_ONLY) == 0); | 81 DCHECK((attr & READ_ONLY) == 0); |
| 64 | 82 |
| 65 // Check whether we can reconfigure the existing property into a | 83 // Check whether we can reconfigure the existing property into a |
| 66 // function. | 84 // function. |
| 67 PropertyDetails old_details = it.property_details(); | 85 PropertyDetails old_details = it.property_details(); |
| 68 if (old_details.IsReadOnly() || old_details.IsDontEnum() || | 86 if (old_details.IsReadOnly() || old_details.IsDontEnum() || |
| 69 (it.state() == LookupIterator::ACCESSOR && | 87 (it.state() == LookupIterator::ACCESSOR && |
| 70 it.GetAccessors()->IsAccessorPair())) { | 88 it.GetAccessors()->IsAccessorPair())) { |
| 71 return ThrowRedeclarationError(isolate, name); | 89 // ES#sec-globaldeclarationinstantiation 5.d: |
| 90 // If hasRestrictedGlobal is true, throw a SyntaxError exception. | |
| 91 // ES#sec-evaldeclarationinstantiation 8.a.iv.1.b: | |
| 92 // If fnDefinable is false, throw a TypeError exception. | |
| 93 return ThrowRedeclarationError(isolate, name, redeclaration_error_type); | |
| 72 } | 94 } |
| 73 // If the existing property is not configurable, keep its attributes. Do | 95 // If the existing property is not configurable, keep its attributes. Do |
| 74 attr = old_attributes; | 96 attr = old_attributes; |
| 75 } | 97 } |
| 76 | 98 |
| 77 // If the current state is ACCESSOR, this could mean it's an AccessorInfo | 99 // If the current state is ACCESSOR, this could mean it's an AccessorInfo |
| 78 // type property. We are not allowed to call into such setters during global | 100 // type property. We are not allowed to call into such setters during global |
| 79 // function declaration since this would break e.g., onload. Meaning | 101 // function declaration since this would break e.g., onload. Meaning |
| 80 // 'function onload() {}' would invalidly register that function as the | 102 // 'function onload() {}' would invalidly register that function as the |
| 81 // onload callback. To avoid this situation, we first delete the property | 103 // onload callback. To avoid this situation, we first delete the property |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 130 | 152 |
| 131 // Compute the property attributes. According to ECMA-262, | 153 // Compute the property attributes. According to ECMA-262, |
| 132 // the property must be non-configurable except in eval. | 154 // the property must be non-configurable except in eval. |
| 133 bool is_native = DeclareGlobalsNativeFlag::decode(flags); | 155 bool is_native = DeclareGlobalsNativeFlag::decode(flags); |
| 134 bool is_eval = DeclareGlobalsEvalFlag::decode(flags); | 156 bool is_eval = DeclareGlobalsEvalFlag::decode(flags); |
| 135 int attr = NONE; | 157 int attr = NONE; |
| 136 if (is_const) attr |= READ_ONLY; | 158 if (is_const) attr |= READ_ONLY; |
| 137 if (is_function && is_native) attr |= READ_ONLY; | 159 if (is_function && is_native) attr |= READ_ONLY; |
| 138 if (!is_const && !is_eval) attr |= DONT_DELETE; | 160 if (!is_const && !is_eval) attr |= DONT_DELETE; |
| 139 | 161 |
| 140 Object* result = DeclareGlobals(isolate, global, name, value, | 162 // ES#sec-globaldeclarationinstantiation 5.d: |
| 141 static_cast<PropertyAttributes>(attr), | 163 // If hasRestrictedGlobal is true, throw a SyntaxError exception. |
| 142 is_var, is_const, is_function); | 164 Object* result = DeclareGlobals( |
| 165 isolate, global, name, value, static_cast<PropertyAttributes>(attr), | |
| 166 is_var, is_const, is_function, RedeclarationError::kSyntaxError); | |
| 143 if (isolate->has_pending_exception()) return result; | 167 if (isolate->has_pending_exception()) return result; |
| 144 }); | 168 }); |
| 145 | 169 |
| 146 return isolate->heap()->undefined_value(); | 170 return isolate->heap()->undefined_value(); |
| 147 } | 171 } |
| 148 | 172 |
| 149 | 173 |
| 150 RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) { | 174 RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) { |
| 151 HandleScope scope(isolate); | 175 HandleScope scope(isolate); |
| 152 // args[0] == name | 176 // args[0] == name |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 227 | 251 |
| 228 int index; | 252 int index; |
| 229 PropertyAttributes attributes; | 253 PropertyAttributes attributes; |
| 230 BindingFlags binding_flags; | 254 BindingFlags binding_flags; |
| 231 | 255 |
| 232 if ((attr & EVAL_DECLARED) != 0) { | 256 if ((attr & EVAL_DECLARED) != 0) { |
| 233 // Check for a conflict with a lexically scoped variable | 257 // Check for a conflict with a lexically scoped variable |
| 234 context_arg->Lookup(name, LEXICAL_TEST, &index, &attributes, | 258 context_arg->Lookup(name, LEXICAL_TEST, &index, &attributes, |
| 235 &binding_flags); | 259 &binding_flags); |
| 236 if (attributes != ABSENT && binding_flags == BINDING_CHECK_INITIALIZED) { | 260 if (attributes != ABSENT && binding_flags == BINDING_CHECK_INITIALIZED) { |
| 237 return ThrowRedeclarationError(isolate, name); | 261 return ThrowRedeclarationError(isolate, name, |
|
adamk
2016/06/09 15:08:42
Why no comment here?
jwolfe
2016/06/09 17:05:23
Oops. Missed a spot. I've got a comment prepared a
| |
| 262 RedeclarationError::kSyntaxError); | |
| 238 } | 263 } |
| 239 attr = static_cast<PropertyAttributes>(attr & ~EVAL_DECLARED); | 264 attr = static_cast<PropertyAttributes>(attr & ~EVAL_DECLARED); |
| 240 } | 265 } |
| 241 | 266 |
| 242 Handle<Object> holder = context->Lookup(name, DONT_FOLLOW_CHAINS, &index, | 267 Handle<Object> holder = context->Lookup(name, DONT_FOLLOW_CHAINS, &index, |
| 243 &attributes, &binding_flags); | 268 &attributes, &binding_flags); |
| 244 if (holder.is_null()) { | 269 if (holder.is_null()) { |
| 245 // In case of JSProxy, an exception might have been thrown. | 270 // In case of JSProxy, an exception might have been thrown. |
| 246 if (isolate->has_pending_exception()) return isolate->heap()->exception(); | 271 if (isolate->has_pending_exception()) return isolate->heap()->exception(); |
| 247 } | 272 } |
| 248 | 273 |
| 249 Handle<JSObject> object; | 274 Handle<JSObject> object; |
| 250 Handle<Object> value = | 275 Handle<Object> value = |
| 251 is_function ? initial_value | 276 is_function ? initial_value |
| 252 : Handle<Object>::cast(isolate->factory()->undefined_value()); | 277 : Handle<Object>::cast(isolate->factory()->undefined_value()); |
| 253 | 278 |
| 254 // TODO(verwaest): This case should probably not be covered by this function, | 279 // TODO(verwaest): This case should probably not be covered by this function, |
| 255 // but by DeclareGlobals instead. | 280 // but by DeclareGlobals instead. |
| 256 if (attributes != ABSENT && holder->IsJSGlobalObject()) { | 281 if (attributes != ABSENT && holder->IsJSGlobalObject()) { |
| 282 // ES#sec-evaldeclarationinstantiation 8.a.iv.1.b: | |
| 283 // If fnDefinable is false, throw a TypeError exception. | |
| 257 return DeclareGlobals(isolate, Handle<JSGlobalObject>::cast(holder), name, | 284 return DeclareGlobals(isolate, Handle<JSGlobalObject>::cast(holder), name, |
| 258 value, attr, is_var, is_const, is_function); | 285 value, attr, is_var, is_const, is_function, |
| 286 RedeclarationError::kTypeError); | |
| 259 } | 287 } |
| 260 if (context_arg->extension()->IsJSGlobalObject()) { | 288 if (context_arg->extension()->IsJSGlobalObject()) { |
| 261 Handle<JSGlobalObject> global( | 289 Handle<JSGlobalObject> global( |
| 262 JSGlobalObject::cast(context_arg->extension()), isolate); | 290 JSGlobalObject::cast(context_arg->extension()), isolate); |
| 263 return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const, | 291 return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const, |
| 264 is_function); | 292 is_function, RedeclarationError::kTypeError); |
| 265 } else if (context->IsScriptContext()) { | 293 } else if (context->IsScriptContext()) { |
| 266 DCHECK(context->global_object()->IsJSGlobalObject()); | 294 DCHECK(context->global_object()->IsJSGlobalObject()); |
| 267 Handle<JSGlobalObject> global( | 295 Handle<JSGlobalObject> global( |
| 268 JSGlobalObject::cast(context->global_object()), isolate); | 296 JSGlobalObject::cast(context->global_object()), isolate); |
| 269 return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const, | 297 return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const, |
| 270 is_function); | 298 is_function, RedeclarationError::kTypeError); |
| 271 } | 299 } |
| 272 | 300 |
| 273 if (attributes != ABSENT) { | 301 if (attributes != ABSENT) { |
| 274 // The name was declared before; check for conflicting re-declarations. | 302 // The name was declared before; check for conflicting re-declarations. |
| 275 if (is_const || (attributes & READ_ONLY) != 0) { | 303 if (is_const || (attributes & READ_ONLY) != 0) { |
|
adamk
2016/06/09 15:08:42
Was this also unreachable?
| |
| 276 return ThrowRedeclarationError(isolate, name); | 304 return ThrowRedeclarationError(isolate, name, |
| 305 RedeclarationError::kSyntaxError); | |
| 277 } | 306 } |
| 278 | 307 |
| 279 // Skip var re-declarations. | 308 // Skip var re-declarations. |
| 280 if (is_var) return isolate->heap()->undefined_value(); | 309 if (is_var) return isolate->heap()->undefined_value(); |
| 281 | 310 |
| 282 DCHECK(is_function); | 311 DCHECK(is_function); |
| 283 if (index != Context::kNotFound) { | 312 if (index != Context::kNotFound) { |
| 284 DCHECK(holder.is_identical_to(context)); | 313 DCHECK(holder.is_identical_to(context)); |
| 285 context->set(index, *initial_value); | 314 context->set(index, *initial_value); |
| 286 return isolate->heap()->undefined_value(); | 315 return isolate->heap()->undefined_value(); |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 605 static Object* FindNameClash(Handle<ScopeInfo> scope_info, | 634 static Object* FindNameClash(Handle<ScopeInfo> scope_info, |
| 606 Handle<JSGlobalObject> global_object, | 635 Handle<JSGlobalObject> global_object, |
| 607 Handle<ScriptContextTable> script_context) { | 636 Handle<ScriptContextTable> script_context) { |
| 608 Isolate* isolate = scope_info->GetIsolate(); | 637 Isolate* isolate = scope_info->GetIsolate(); |
| 609 for (int var = 0; var < scope_info->ContextLocalCount(); var++) { | 638 for (int var = 0; var < scope_info->ContextLocalCount(); var++) { |
| 610 Handle<String> name(scope_info->ContextLocalName(var)); | 639 Handle<String> name(scope_info->ContextLocalName(var)); |
| 611 VariableMode mode = scope_info->ContextLocalMode(var); | 640 VariableMode mode = scope_info->ContextLocalMode(var); |
| 612 ScriptContextTable::LookupResult lookup; | 641 ScriptContextTable::LookupResult lookup; |
| 613 if (ScriptContextTable::Lookup(script_context, name, &lookup)) { | 642 if (ScriptContextTable::Lookup(script_context, name, &lookup)) { |
| 614 if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(lookup.mode)) { | 643 if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(lookup.mode)) { |
| 615 return ThrowRedeclarationError(isolate, name); | 644 // ES#sec-globaldeclarationinstantiation 5.b: |
| 645 // If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError | |
|
adamk
2016/06/09 15:08:42
I also see this line in EvalDeclarationInstantiati
jwolfe
2016/06/09 17:05:23
I don't believe this code runs for eval. This code
| |
| 646 // exception. | |
| 647 return ThrowRedeclarationError(isolate, name, | |
| 648 RedeclarationError::kSyntaxError); | |
| 616 } | 649 } |
| 617 } | 650 } |
| 618 | 651 |
| 619 if (IsLexicalVariableMode(mode)) { | 652 if (IsLexicalVariableMode(mode)) { |
| 620 LookupIterator it(global_object, name, global_object, | 653 LookupIterator it(global_object, name, global_object, |
| 621 LookupIterator::OWN_SKIP_INTERCEPTOR); | 654 LookupIterator::OWN_SKIP_INTERCEPTOR); |
| 622 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); | 655 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); |
| 623 if (!maybe.IsJust()) return isolate->heap()->exception(); | 656 if (!maybe.IsJust()) return isolate->heap()->exception(); |
| 624 if ((maybe.FromJust() & DONT_DELETE) != 0) { | 657 if ((maybe.FromJust() & DONT_DELETE) != 0) { |
| 625 return ThrowRedeclarationError(isolate, name); | 658 // ES#sec-globaldeclarationinstantiation 5.a: |
| 659 // If envRec.HasVarDeclaration(name) is true, throw a SyntaxError | |
| 660 // exception. | |
| 661 return ThrowRedeclarationError(isolate, name, | |
| 662 RedeclarationError::kSyntaxError); | |
| 626 } | 663 } |
| 627 | 664 |
| 628 JSGlobalObject::InvalidatePropertyCell(global_object, name); | 665 JSGlobalObject::InvalidatePropertyCell(global_object, name); |
| 629 } | 666 } |
| 630 } | 667 } |
| 631 return isolate->heap()->undefined_value(); | 668 return isolate->heap()->undefined_value(); |
| 632 } | 669 } |
| 633 | 670 |
| 634 | 671 |
| 635 RUNTIME_FUNCTION(Runtime_NewScriptContext) { | 672 RUNTIME_FUNCTION(Runtime_NewScriptContext) { |
| (...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1021 RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Strict) { | 1058 RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Strict) { |
| 1022 HandleScope scope(isolate); | 1059 HandleScope scope(isolate); |
| 1023 DCHECK_EQ(2, args.length()); | 1060 DCHECK_EQ(2, args.length()); |
| 1024 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); | 1061 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); |
| 1025 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); | 1062 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); |
| 1026 RETURN_RESULT_OR_FAILURE(isolate, StoreLookupSlot(name, value, STRICT)); | 1063 RETURN_RESULT_OR_FAILURE(isolate, StoreLookupSlot(name, value, STRICT)); |
| 1027 } | 1064 } |
| 1028 | 1065 |
| 1029 } // namespace internal | 1066 } // namespace internal |
| 1030 } // namespace v8 | 1067 } // namespace v8 |
| OLD | NEW |