| 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 enum class RedeclarationType { kSyntaxError = 0, kTypeError = 1 }; |
| 20 |
| 21 static Object* ThrowRedeclarationError(Isolate* isolate, Handle<String> name, |
| 22 RedeclarationType redeclaration_type) { |
| 20 HandleScope scope(isolate); | 23 HandleScope scope(isolate); |
| 21 THROW_NEW_ERROR_RETURN_FAILURE( | 24 if (redeclaration_type == RedeclarationType::kSyntaxError) { |
| 22 isolate, NewTypeError(MessageTemplate::kVarRedeclaration, name)); | 25 THROW_NEW_ERROR_RETURN_FAILURE( |
| 26 isolate, NewSyntaxError(MessageTemplate::kVarRedeclaration, name)); |
| 27 } else { |
| 28 THROW_NEW_ERROR_RETURN_FAILURE( |
| 29 isolate, NewTypeError(MessageTemplate::kVarRedeclaration, name)); |
| 30 } |
| 23 } | 31 } |
| 24 | 32 |
| 25 | 33 |
| 26 RUNTIME_FUNCTION(Runtime_ThrowConstAssignError) { | 34 RUNTIME_FUNCTION(Runtime_ThrowConstAssignError) { |
| 27 HandleScope scope(isolate); | 35 HandleScope scope(isolate); |
| 28 THROW_NEW_ERROR_RETURN_FAILURE(isolate, | 36 THROW_NEW_ERROR_RETURN_FAILURE(isolate, |
| 29 NewTypeError(MessageTemplate::kConstAssign)); | 37 NewTypeError(MessageTemplate::kConstAssign)); |
| 30 } | 38 } |
| 31 | 39 |
| 32 | 40 |
| 33 // May throw a RedeclarationError. | 41 // May throw a RedeclarationError. |
| 34 static Object* DeclareGlobals(Isolate* isolate, Handle<JSGlobalObject> global, | 42 static Object* DeclareGlobals(Isolate* isolate, Handle<JSGlobalObject> global, |
| 35 Handle<String> name, Handle<Object> value, | 43 Handle<String> name, Handle<Object> value, |
| 36 PropertyAttributes attr, bool is_var, | 44 PropertyAttributes attr, bool is_var, |
| 37 bool is_function) { | 45 bool is_function, |
| 46 RedeclarationType redeclaration_type) { |
| 38 Handle<ScriptContextTable> script_contexts( | 47 Handle<ScriptContextTable> script_contexts( |
| 39 global->native_context()->script_context_table()); | 48 global->native_context()->script_context_table()); |
| 40 ScriptContextTable::LookupResult lookup; | 49 ScriptContextTable::LookupResult lookup; |
| 41 if (ScriptContextTable::Lookup(script_contexts, name, &lookup) && | 50 if (ScriptContextTable::Lookup(script_contexts, name, &lookup) && |
| 42 IsLexicalVariableMode(lookup.mode)) { | 51 IsLexicalVariableMode(lookup.mode)) { |
| 43 return ThrowRedeclarationError(isolate, name); | 52 // ES#sec-globaldeclarationinstantiation 6.a: |
| 53 // If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError |
| 54 // exception. |
| 55 return ThrowRedeclarationError(isolate, name, |
| 56 RedeclarationType::kSyntaxError); |
| 44 } | 57 } |
| 45 | 58 |
| 46 // Do the lookup own properties only, see ES5 erratum. | 59 // Do the lookup own properties only, see ES5 erratum. |
| 47 LookupIterator it(global, name, global, LookupIterator::OWN_SKIP_INTERCEPTOR); | 60 LookupIterator it(global, name, global, LookupIterator::OWN_SKIP_INTERCEPTOR); |
| 48 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); | 61 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); |
| 49 if (!maybe.IsJust()) return isolate->heap()->exception(); | 62 if (!maybe.IsJust()) return isolate->heap()->exception(); |
| 50 | 63 |
| 51 if (it.IsFound()) { | 64 if (it.IsFound()) { |
| 52 PropertyAttributes old_attributes = maybe.FromJust(); | 65 PropertyAttributes old_attributes = maybe.FromJust(); |
| 53 // The name was declared before; check for conflicting re-declarations. | 66 // The name was declared before; check for conflicting re-declarations. |
| 54 | 67 |
| 55 // Skip var re-declarations. | 68 // Skip var re-declarations. |
| 56 if (is_var) return isolate->heap()->undefined_value(); | 69 if (is_var) return isolate->heap()->undefined_value(); |
| 57 | 70 |
| 58 DCHECK(is_function); | 71 DCHECK(is_function); |
| 59 if ((old_attributes & DONT_DELETE) != 0) { | 72 if ((old_attributes & DONT_DELETE) != 0) { |
| 60 // Only allow reconfiguring globals to functions in user code (no | 73 // Only allow reconfiguring globals to functions in user code (no |
| 61 // natives, which are marked as read-only). | 74 // natives, which are marked as read-only). |
| 62 DCHECK((attr & READ_ONLY) == 0); | 75 DCHECK((attr & READ_ONLY) == 0); |
| 63 | 76 |
| 64 // Check whether we can reconfigure the existing property into a | 77 // Check whether we can reconfigure the existing property into a |
| 65 // function. | 78 // function. |
| 66 PropertyDetails old_details = it.property_details(); | 79 PropertyDetails old_details = it.property_details(); |
| 67 if (old_details.IsReadOnly() || old_details.IsDontEnum() || | 80 if (old_details.IsReadOnly() || old_details.IsDontEnum() || |
| 68 (it.state() == LookupIterator::ACCESSOR && | 81 (it.state() == LookupIterator::ACCESSOR && |
| 69 it.GetAccessors()->IsAccessorPair())) { | 82 it.GetAccessors()->IsAccessorPair())) { |
| 70 return ThrowRedeclarationError(isolate, name); | 83 // ES#sec-globaldeclarationinstantiation 5.d: |
| 84 // If hasRestrictedGlobal is true, throw a SyntaxError exception. |
| 85 // ES#sec-evaldeclarationinstantiation 8.a.iv.1.b: |
| 86 // If fnDefinable is false, throw a TypeError exception. |
| 87 return ThrowRedeclarationError(isolate, name, redeclaration_type); |
| 71 } | 88 } |
| 72 // If the existing property is not configurable, keep its attributes. Do | 89 // If the existing property is not configurable, keep its attributes. Do |
| 73 attr = old_attributes; | 90 attr = old_attributes; |
| 74 } | 91 } |
| 75 | 92 |
| 76 // If the current state is ACCESSOR, this could mean it's an AccessorInfo | 93 // If the current state is ACCESSOR, this could mean it's an AccessorInfo |
| 77 // type property. We are not allowed to call into such setters during global | 94 // type property. We are not allowed to call into such setters during global |
| 78 // function declaration since this would break e.g., onload. Meaning | 95 // function declaration since this would break e.g., onload. Meaning |
| 79 // 'function onload() {}' would invalidly register that function as the | 96 // 'function onload() {}' would invalidly register that function as the |
| 80 // onload callback. To avoid this situation, we first delete the property | 97 // onload callback. To avoid this situation, we first delete the property |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 } | 140 } |
| 124 | 141 |
| 125 // Compute the property attributes. According to ECMA-262, | 142 // Compute the property attributes. According to ECMA-262, |
| 126 // the property must be non-configurable except in eval. | 143 // the property must be non-configurable except in eval. |
| 127 bool is_native = DeclareGlobalsNativeFlag::decode(flags); | 144 bool is_native = DeclareGlobalsNativeFlag::decode(flags); |
| 128 bool is_eval = DeclareGlobalsEvalFlag::decode(flags); | 145 bool is_eval = DeclareGlobalsEvalFlag::decode(flags); |
| 129 int attr = NONE; | 146 int attr = NONE; |
| 130 if (is_function && is_native) attr |= READ_ONLY; | 147 if (is_function && is_native) attr |= READ_ONLY; |
| 131 if (!is_eval) attr |= DONT_DELETE; | 148 if (!is_eval) attr |= DONT_DELETE; |
| 132 | 149 |
| 133 Object* result = DeclareGlobals(isolate, global, name, value, | 150 // ES#sec-globaldeclarationinstantiation 5.d: |
| 134 static_cast<PropertyAttributes>(attr), | 151 // If hasRestrictedGlobal is true, throw a SyntaxError exception. |
| 135 is_var, is_function); | 152 Object* result = DeclareGlobals( |
| 153 isolate, global, name, value, static_cast<PropertyAttributes>(attr), |
| 154 is_var, is_function, RedeclarationType::kSyntaxError); |
| 136 if (isolate->has_pending_exception()) return result; | 155 if (isolate->has_pending_exception()) return result; |
| 137 }); | 156 }); |
| 138 | 157 |
| 139 return isolate->heap()->undefined_value(); | 158 return isolate->heap()->undefined_value(); |
| 140 } | 159 } |
| 141 | 160 |
| 142 | 161 |
| 143 RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) { | 162 RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) { |
| 144 HandleScope scope(isolate); | 163 HandleScope scope(isolate); |
| 145 DCHECK_EQ(3, args.length()); | 164 DCHECK_EQ(3, args.length()); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 207 bool is_var = !is_function; | 226 bool is_var = !is_function; |
| 208 DCHECK(!is_var || value->IsUndefined(isolate)); | 227 DCHECK(!is_var || value->IsUndefined(isolate)); |
| 209 | 228 |
| 210 int index; | 229 int index; |
| 211 PropertyAttributes attributes; | 230 PropertyAttributes attributes; |
| 212 BindingFlags binding_flags; | 231 BindingFlags binding_flags; |
| 213 | 232 |
| 214 // Check for a conflict with a lexically scoped variable | 233 // Check for a conflict with a lexically scoped variable |
| 215 context_arg->Lookup(name, LEXICAL_TEST, &index, &attributes, &binding_flags); | 234 context_arg->Lookup(name, LEXICAL_TEST, &index, &attributes, &binding_flags); |
| 216 if (attributes != ABSENT && binding_flags == BINDING_CHECK_INITIALIZED) { | 235 if (attributes != ABSENT && binding_flags == BINDING_CHECK_INITIALIZED) { |
| 217 return ThrowRedeclarationError(isolate, name); | 236 // ES#sec-evaldeclarationinstantiation 5.a.i.1: |
| 237 // If varEnvRec.HasLexicalDeclaration(name) is true, throw a SyntaxError |
| 238 // exception. |
| 239 // ES#sec-evaldeclarationinstantiation 5.d.ii.2.a.i: |
| 240 // Throw a SyntaxError exception. |
| 241 return ThrowRedeclarationError(isolate, name, |
| 242 RedeclarationType::kSyntaxError); |
| 218 } | 243 } |
| 219 | 244 |
| 220 Handle<Object> holder = context->Lookup(name, DONT_FOLLOW_CHAINS, &index, | 245 Handle<Object> holder = context->Lookup(name, DONT_FOLLOW_CHAINS, &index, |
| 221 &attributes, &binding_flags); | 246 &attributes, &binding_flags); |
| 222 DCHECK(!isolate->has_pending_exception()); | 247 DCHECK(!isolate->has_pending_exception()); |
| 223 | 248 |
| 224 Handle<JSObject> object; | 249 Handle<JSObject> object; |
| 225 | 250 |
| 226 if (attributes != ABSENT && holder->IsJSGlobalObject()) { | 251 if (attributes != ABSENT && holder->IsJSGlobalObject()) { |
| 252 // ES#sec-evaldeclarationinstantiation 8.a.iv.1.b: |
| 253 // If fnDefinable is false, throw a TypeError exception. |
| 227 return DeclareGlobals(isolate, Handle<JSGlobalObject>::cast(holder), name, | 254 return DeclareGlobals(isolate, Handle<JSGlobalObject>::cast(holder), name, |
| 228 value, NONE, is_var, is_function); | 255 value, NONE, is_var, is_function, |
| 256 RedeclarationType::kTypeError); |
| 229 } | 257 } |
| 230 if (context_arg->extension()->IsJSGlobalObject()) { | 258 if (context_arg->extension()->IsJSGlobalObject()) { |
| 231 Handle<JSGlobalObject> global( | 259 Handle<JSGlobalObject> global( |
| 232 JSGlobalObject::cast(context_arg->extension()), isolate); | 260 JSGlobalObject::cast(context_arg->extension()), isolate); |
| 233 return DeclareGlobals(isolate, global, name, value, NONE, is_var, | 261 return DeclareGlobals(isolate, global, name, value, NONE, is_var, |
| 234 is_function); | 262 is_function, RedeclarationType::kTypeError); |
| 235 } else if (context->IsScriptContext()) { | 263 } else if (context->IsScriptContext()) { |
| 236 DCHECK(context->global_object()->IsJSGlobalObject()); | 264 DCHECK(context->global_object()->IsJSGlobalObject()); |
| 237 Handle<JSGlobalObject> global( | 265 Handle<JSGlobalObject> global( |
| 238 JSGlobalObject::cast(context->global_object()), isolate); | 266 JSGlobalObject::cast(context->global_object()), isolate); |
| 239 return DeclareGlobals(isolate, global, name, value, NONE, is_var, | 267 return DeclareGlobals(isolate, global, name, value, NONE, is_var, |
| 240 is_function); | 268 is_function, RedeclarationType::kTypeError); |
| 241 } | 269 } |
| 242 | 270 |
| 243 if (attributes != ABSENT) { | 271 if (attributes != ABSENT) { |
| 244 DCHECK_EQ(NONE, attributes); | 272 DCHECK_EQ(NONE, attributes); |
| 245 | 273 |
| 246 // Skip var re-declarations. | 274 // Skip var re-declarations. |
| 247 if (is_var) return isolate->heap()->undefined_value(); | 275 if (is_var) return isolate->heap()->undefined_value(); |
| 248 | 276 |
| 249 DCHECK(is_function); | 277 DCHECK(is_function); |
| 250 if (index != Context::kNotFound) { | 278 if (index != Context::kNotFound) { |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 574 static Object* FindNameClash(Handle<ScopeInfo> scope_info, | 602 static Object* FindNameClash(Handle<ScopeInfo> scope_info, |
| 575 Handle<JSGlobalObject> global_object, | 603 Handle<JSGlobalObject> global_object, |
| 576 Handle<ScriptContextTable> script_context) { | 604 Handle<ScriptContextTable> script_context) { |
| 577 Isolate* isolate = scope_info->GetIsolate(); | 605 Isolate* isolate = scope_info->GetIsolate(); |
| 578 for (int var = 0; var < scope_info->ContextLocalCount(); var++) { | 606 for (int var = 0; var < scope_info->ContextLocalCount(); var++) { |
| 579 Handle<String> name(scope_info->ContextLocalName(var)); | 607 Handle<String> name(scope_info->ContextLocalName(var)); |
| 580 VariableMode mode = scope_info->ContextLocalMode(var); | 608 VariableMode mode = scope_info->ContextLocalMode(var); |
| 581 ScriptContextTable::LookupResult lookup; | 609 ScriptContextTable::LookupResult lookup; |
| 582 if (ScriptContextTable::Lookup(script_context, name, &lookup)) { | 610 if (ScriptContextTable::Lookup(script_context, name, &lookup)) { |
| 583 if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(lookup.mode)) { | 611 if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(lookup.mode)) { |
| 584 return ThrowRedeclarationError(isolate, name); | 612 // ES#sec-globaldeclarationinstantiation 5.b: |
| 613 // If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError |
| 614 // exception. |
| 615 return ThrowRedeclarationError(isolate, name, |
| 616 RedeclarationType::kSyntaxError); |
| 585 } | 617 } |
| 586 } | 618 } |
| 587 | 619 |
| 588 if (IsLexicalVariableMode(mode)) { | 620 if (IsLexicalVariableMode(mode)) { |
| 589 LookupIterator it(global_object, name, global_object, | 621 LookupIterator it(global_object, name, global_object, |
| 590 LookupIterator::OWN_SKIP_INTERCEPTOR); | 622 LookupIterator::OWN_SKIP_INTERCEPTOR); |
| 591 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); | 623 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); |
| 592 if (!maybe.IsJust()) return isolate->heap()->exception(); | 624 if (!maybe.IsJust()) return isolate->heap()->exception(); |
| 593 if ((maybe.FromJust() & DONT_DELETE) != 0) { | 625 if ((maybe.FromJust() & DONT_DELETE) != 0) { |
| 594 return ThrowRedeclarationError(isolate, name); | 626 // ES#sec-globaldeclarationinstantiation 5.a: |
| 627 // If envRec.HasVarDeclaration(name) is true, throw a SyntaxError |
| 628 // exception. |
| 629 // ES#sec-globaldeclarationinstantiation 5.d: |
| 630 // If hasRestrictedGlobal is true, throw a SyntaxError exception. |
| 631 return ThrowRedeclarationError(isolate, name, |
| 632 RedeclarationType::kSyntaxError); |
| 595 } | 633 } |
| 596 | 634 |
| 597 JSGlobalObject::InvalidatePropertyCell(global_object, name); | 635 JSGlobalObject::InvalidatePropertyCell(global_object, name); |
| 598 } | 636 } |
| 599 } | 637 } |
| 600 return isolate->heap()->undefined_value(); | 638 return isolate->heap()->undefined_value(); |
| 601 } | 639 } |
| 602 | 640 |
| 603 | 641 |
| 604 RUNTIME_FUNCTION(Runtime_NewScriptContext) { | 642 RUNTIME_FUNCTION(Runtime_NewScriptContext) { |
| (...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 990 RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Strict) { | 1028 RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Strict) { |
| 991 HandleScope scope(isolate); | 1029 HandleScope scope(isolate); |
| 992 DCHECK_EQ(2, args.length()); | 1030 DCHECK_EQ(2, args.length()); |
| 993 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); | 1031 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); |
| 994 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); | 1032 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); |
| 995 RETURN_RESULT_OR_FAILURE(isolate, StoreLookupSlot(name, value, STRICT)); | 1033 RETURN_RESULT_OR_FAILURE(isolate, StoreLookupSlot(name, value, STRICT)); |
| 996 } | 1034 } |
| 997 | 1035 |
| 998 } // namespace internal | 1036 } // namespace internal |
| 999 } // namespace v8 | 1037 } // namespace v8 |
| OLD | NEW |