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