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 |