| 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 <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "src/accessors.h" | 9 #include "src/accessors.h" |
| 10 #include "src/arguments.h" | 10 #include "src/arguments.h" |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 THROW_NEW_ERROR_RETURN_FAILURE( | 37 THROW_NEW_ERROR_RETURN_FAILURE( |
| 38 isolate, NewTypeError(MessageTemplate::kVarRedeclaration, name)); | 38 isolate, NewTypeError(MessageTemplate::kVarRedeclaration, name)); |
| 39 } | 39 } |
| 40 } | 40 } |
| 41 | 41 |
| 42 | 42 |
| 43 // May throw a RedeclarationError. | 43 // May throw a RedeclarationError. |
| 44 Object* DeclareGlobal( | 44 Object* DeclareGlobal( |
| 45 Isolate* isolate, Handle<JSGlobalObject> global, Handle<String> name, | 45 Isolate* isolate, Handle<JSGlobalObject> global, Handle<String> name, |
| 46 Handle<Object> value, PropertyAttributes attr, bool is_var, | 46 Handle<Object> value, PropertyAttributes attr, bool is_var, |
| 47 bool is_function, RedeclarationType redeclaration_type, | 47 bool is_function_declaration, RedeclarationType redeclaration_type, |
| 48 Handle<TypeFeedbackVector> feedback_vector = Handle<TypeFeedbackVector>(), | 48 Handle<TypeFeedbackVector> feedback_vector = Handle<TypeFeedbackVector>(), |
| 49 FeedbackVectorSlot slot = FeedbackVectorSlot::Invalid()) { | 49 FeedbackVectorSlot slot = FeedbackVectorSlot::Invalid()) { |
| 50 Handle<ScriptContextTable> script_contexts( | 50 Handle<ScriptContextTable> script_contexts( |
| 51 global->native_context()->script_context_table()); | 51 global->native_context()->script_context_table()); |
| 52 ScriptContextTable::LookupResult lookup; | 52 ScriptContextTable::LookupResult lookup; |
| 53 if (ScriptContextTable::Lookup(script_contexts, name, &lookup) && | 53 if (ScriptContextTable::Lookup(script_contexts, name, &lookup) && |
| 54 IsLexicalVariableMode(lookup.mode)) { | 54 IsLexicalVariableMode(lookup.mode)) { |
| 55 // ES#sec-globaldeclarationinstantiation 6.a: | 55 // ES#sec-globaldeclarationinstantiation 6.a: |
| 56 // If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError | 56 // If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError |
| 57 // exception. | 57 // exception. |
| 58 return ThrowRedeclarationError(isolate, name, | 58 return ThrowRedeclarationError(isolate, name, |
| 59 RedeclarationType::kSyntaxError); | 59 RedeclarationType::kSyntaxError); |
| 60 } | 60 } |
| 61 | 61 |
| 62 // Do the lookup own properties only, see ES5 erratum. | 62 // Do the lookup own properties only, see ES5 erratum. |
| 63 LookupIterator it(global, name, global, LookupIterator::OWN_SKIP_INTERCEPTOR); | 63 LookupIterator::Configuration lookup_config( |
| 64 LookupIterator::Configuration::OWN_SKIP_INTERCEPTOR); |
| 65 if (is_function_declaration) { |
| 66 // For function declarations, use the interceptor on the declaration. For |
| 67 // non-functions, use it only on initialization. |
| 68 lookup_config = LookupIterator::Configuration::OWN; |
| 69 } |
| 70 LookupIterator it(global, name, global, lookup_config); |
| 64 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); | 71 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); |
| 65 if (!maybe.IsJust()) return isolate->heap()->exception(); | 72 if (!maybe.IsJust()) return isolate->heap()->exception(); |
| 66 | 73 |
| 67 if (it.IsFound()) { | 74 if (it.IsFound()) { |
| 68 PropertyAttributes old_attributes = maybe.FromJust(); | 75 PropertyAttributes old_attributes = maybe.FromJust(); |
| 69 // The name was declared before; check for conflicting re-declarations. | 76 // The name was declared before; check for conflicting re-declarations. |
| 70 | 77 |
| 71 // Skip var re-declarations. | 78 // Skip var re-declarations. |
| 72 if (is_var) return isolate->heap()->undefined_value(); | 79 if (is_var) return isolate->heap()->undefined_value(); |
| 73 | 80 |
| 74 DCHECK(is_function); | 81 DCHECK(is_function_declaration); |
| 75 if ((old_attributes & DONT_DELETE) != 0) { | 82 if ((old_attributes & DONT_DELETE) != 0) { |
| 76 // Only allow reconfiguring globals to functions in user code (no | 83 // Only allow reconfiguring globals to functions in user code (no |
| 77 // natives, which are marked as read-only). | 84 // natives, which are marked as read-only). |
| 78 DCHECK((attr & READ_ONLY) == 0); | 85 DCHECK((attr & READ_ONLY) == 0); |
| 79 | 86 |
| 80 // Check whether we can reconfigure the existing property into a | 87 // Check whether we can reconfigure the existing property into a |
| 81 // function. | 88 // function. |
| 82 PropertyDetails old_details = it.property_details(); | 89 PropertyDetails old_details = it.property_details(); |
| 83 if (old_details.IsReadOnly() || old_details.IsDontEnum() || | 90 if (old_details.IsReadOnly() || old_details.IsDontEnum() || |
| 84 (it.state() == LookupIterator::ACCESSOR && | 91 (it.state() == LookupIterator::ACCESSOR && |
| 85 it.GetAccessors()->IsAccessorPair())) { | 92 it.GetAccessors()->IsAccessorPair())) { |
| 86 // ES#sec-globaldeclarationinstantiation 5.d: | 93 // ECMA-262 section 15.1.11 GlobalDeclarationInstantiation 5.d: |
| 87 // If hasRestrictedGlobal is true, throw a SyntaxError exception. | 94 // If hasRestrictedGlobal is true, throw a SyntaxError exception. |
| 88 // ES#sec-evaldeclarationinstantiation 8.a.iv.1.b: | 95 // ECMA-262 section 18.2.1.3 EvalDeclarationInstantiation 8.a.iv.1.b: |
| 89 // If fnDefinable is false, throw a TypeError exception. | 96 // If fnDefinable is false, throw a TypeError exception. |
| 90 return ThrowRedeclarationError(isolate, name, redeclaration_type); | 97 return ThrowRedeclarationError(isolate, name, redeclaration_type); |
| 91 } | 98 } |
| 92 // If the existing property is not configurable, keep its attributes. Do | 99 // If the existing property is not configurable, keep its attributes. Do |
| 93 attr = old_attributes; | 100 attr = old_attributes; |
| 94 } | 101 } |
| 95 | 102 |
| 96 // If the current state is ACCESSOR, this could mean it's an AccessorInfo | 103 // If the current state is ACCESSOR, this could mean it's an AccessorInfo |
| 97 // type property. We are not allowed to call into such setters during global | 104 // type property. We are not allowed to call into such setters during global |
| 98 // function declaration since this would break e.g., onload. Meaning | 105 // function declaration since this would break e.g., onload. Meaning |
| 99 // 'function onload() {}' would invalidly register that function as the | 106 // 'function onload() {}' would invalidly register that function as the |
| 100 // onload callback. To avoid this situation, we first delete the property | 107 // onload callback. To avoid this situation, we first delete the property |
| 101 // before readding it as a regular data property below. | 108 // before readding it as a regular data property below. |
| 102 if (it.state() == LookupIterator::ACCESSOR) it.Delete(); | 109 if (it.state() == LookupIterator::ACCESSOR) it.Delete(); |
| 103 } | 110 } |
| 104 | 111 |
| 112 if (is_function_declaration) { |
| 113 it.Restart(); |
| 114 } |
| 115 |
| 105 // Define or redefine own property. | 116 // Define or redefine own property. |
| 106 RETURN_FAILURE_ON_EXCEPTION( | 117 RETURN_FAILURE_ON_EXCEPTION( |
| 107 isolate, JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, attr)); | 118 isolate, JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, attr)); |
| 108 | 119 |
| 109 if (!feedback_vector.is_null()) { | 120 if (!feedback_vector.is_null()) { |
| 110 DCHECK_EQ(*global, *it.GetHolder<Object>()); | 121 DCHECK_EQ(*global, *it.GetHolder<Object>()); |
| 111 // Preinitialize the feedback slot if the global object does not have | 122 // Preinitialize the feedback slot if the global object does not have |
| 112 // named interceptor or the interceptor is not masking. | 123 // named interceptor or the interceptor is not masking. |
| 113 if (!global->HasNamedInterceptor() || | 124 if (!global->HasNamedInterceptor() || |
| 114 global->GetNamedInterceptor()->non_masking()) { | 125 global->GetNamedInterceptor()->non_masking()) { |
| (...skipping 830 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 945 RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Strict) { | 956 RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Strict) { |
| 946 HandleScope scope(isolate); | 957 HandleScope scope(isolate); |
| 947 DCHECK_EQ(2, args.length()); | 958 DCHECK_EQ(2, args.length()); |
| 948 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); | 959 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); |
| 949 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); | 960 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); |
| 950 RETURN_RESULT_OR_FAILURE(isolate, StoreLookupSlot(name, value, STRICT)); | 961 RETURN_RESULT_OR_FAILURE(isolate, StoreLookupSlot(name, value, STRICT)); |
| 951 } | 962 } |
| 952 | 963 |
| 953 } // namespace internal | 964 } // namespace internal |
| 954 } // namespace v8 | 965 } // namespace v8 |
| OLD | NEW |