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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
208 | 227 |
209 int index; | 228 int index; |
210 PropertyAttributes attributes; | 229 PropertyAttributes attributes; |
211 BindingFlags binding_flags; | 230 BindingFlags binding_flags; |
212 | 231 |
213 if ((attr & EVAL_DECLARED) != 0) { | 232 if ((attr & EVAL_DECLARED) != 0) { |
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, | 234 context_arg->Lookup(name, LEXICAL_TEST, &index, &attributes, |
216 &binding_flags); | 235 &binding_flags); |
217 if (attributes != ABSENT && binding_flags == BINDING_CHECK_INITIALIZED) { | 236 if (attributes != ABSENT && binding_flags == BINDING_CHECK_INITIALIZED) { |
218 return ThrowRedeclarationError(isolate, name); | 237 // ES#sec-evaldeclarationinstantiation 5.a.i.1: |
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); | |
219 } | 244 } |
220 attr = static_cast<PropertyAttributes>(attr & ~EVAL_DECLARED); | 245 attr = static_cast<PropertyAttributes>(attr & ~EVAL_DECLARED); |
221 } | 246 } |
222 | 247 |
223 Handle<Object> holder = context->Lookup(name, DONT_FOLLOW_CHAINS, &index, | 248 Handle<Object> holder = context->Lookup(name, DONT_FOLLOW_CHAINS, &index, |
224 &attributes, &binding_flags); | 249 &attributes, &binding_flags); |
225 if (holder.is_null()) { | 250 if (holder.is_null()) { |
226 // In case of JSProxy, an exception might have been thrown. | 251 // In case of JSProxy, an exception might have been thrown. |
227 if (isolate->has_pending_exception()) return isolate->heap()->exception(); | 252 if (isolate->has_pending_exception()) return isolate->heap()->exception(); |
228 } | 253 } |
229 | 254 |
230 Handle<JSObject> object; | 255 Handle<JSObject> object; |
231 Handle<Object> value = | 256 Handle<Object> value = |
232 is_function ? initial_value | 257 is_function ? initial_value |
233 : Handle<Object>::cast(isolate->factory()->undefined_value()); | 258 : Handle<Object>::cast(isolate->factory()->undefined_value()); |
234 | 259 |
235 // TODO(verwaest): This case should probably not be covered by this function, | 260 // TODO(verwaest): This case should probably not be covered by this function, |
236 // but by DeclareGlobals instead. | 261 // but by DeclareGlobals instead. |
237 if (attributes != ABSENT && holder->IsJSGlobalObject()) { | 262 if (attributes != ABSENT && holder->IsJSGlobalObject()) { |
263 // ES#sec-evaldeclarationinstantiation 8.a.iv.1.b: | |
264 // If fnDefinable is false, throw a TypeError exception. | |
238 return DeclareGlobals(isolate, Handle<JSGlobalObject>::cast(holder), name, | 265 return DeclareGlobals(isolate, Handle<JSGlobalObject>::cast(holder), name, |
239 value, attr, is_var, is_function); | 266 value, attr, is_var, is_function, |
267 RedeclarationType::kTypeError); | |
240 } | 268 } |
241 if (context_arg->extension()->IsJSGlobalObject()) { | 269 if (context_arg->extension()->IsJSGlobalObject()) { |
242 Handle<JSGlobalObject> global( | 270 Handle<JSGlobalObject> global( |
243 JSGlobalObject::cast(context_arg->extension()), isolate); | 271 JSGlobalObject::cast(context_arg->extension()), isolate); |
244 return DeclareGlobals(isolate, global, name, value, attr, is_var, | 272 return DeclareGlobals(isolate, global, name, value, attr, is_var, |
245 is_function); | 273 is_function, RedeclarationType::kTypeError); |
246 } else if (context->IsScriptContext()) { | 274 } else if (context->IsScriptContext()) { |
247 DCHECK(context->global_object()->IsJSGlobalObject()); | 275 DCHECK(context->global_object()->IsJSGlobalObject()); |
248 Handle<JSGlobalObject> global( | 276 Handle<JSGlobalObject> global( |
249 JSGlobalObject::cast(context->global_object()), isolate); | 277 JSGlobalObject::cast(context->global_object()), isolate); |
250 return DeclareGlobals(isolate, global, name, value, attr, is_var, | 278 return DeclareGlobals(isolate, global, name, value, attr, is_var, |
251 is_function); | 279 is_function, RedeclarationType::kTypeError); |
252 } | 280 } |
253 | 281 |
254 if (attributes != ABSENT) { | 282 if (attributes != ABSENT) { |
255 // The name was declared before; check for conflicting re-declarations. | 283 // The name was declared before; check for conflicting re-declarations. |
256 if ((attributes & READ_ONLY) != 0) { | 284 if ((attributes & READ_ONLY) != 0) { |
257 return ThrowRedeclarationError(isolate, name); | 285 return ThrowRedeclarationError(isolate, name, |
286 RedeclarationType::kSyntaxError); | |
jwolfe
2016/06/10 20:36:05
this branch seems unreachable.
adamk
2016/06/13 12:44:27
I'm working on a CL to remove this code, I agree t
| |
258 } | 287 } |
259 | 288 |
260 // Skip var re-declarations. | 289 // Skip var re-declarations. |
261 if (is_var) return isolate->heap()->undefined_value(); | 290 if (is_var) return isolate->heap()->undefined_value(); |
262 | 291 |
263 DCHECK(is_function); | 292 DCHECK(is_function); |
264 if (index != Context::kNotFound) { | 293 if (index != Context::kNotFound) { |
265 DCHECK(holder.is_identical_to(context)); | 294 DCHECK(holder.is_identical_to(context)); |
266 context->set(index, *initial_value); | 295 context->set(index, *initial_value); |
267 return isolate->heap()->undefined_value(); | 296 return isolate->heap()->undefined_value(); |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
586 static Object* FindNameClash(Handle<ScopeInfo> scope_info, | 615 static Object* FindNameClash(Handle<ScopeInfo> scope_info, |
587 Handle<JSGlobalObject> global_object, | 616 Handle<JSGlobalObject> global_object, |
588 Handle<ScriptContextTable> script_context) { | 617 Handle<ScriptContextTable> script_context) { |
589 Isolate* isolate = scope_info->GetIsolate(); | 618 Isolate* isolate = scope_info->GetIsolate(); |
590 for (int var = 0; var < scope_info->ContextLocalCount(); var++) { | 619 for (int var = 0; var < scope_info->ContextLocalCount(); var++) { |
591 Handle<String> name(scope_info->ContextLocalName(var)); | 620 Handle<String> name(scope_info->ContextLocalName(var)); |
592 VariableMode mode = scope_info->ContextLocalMode(var); | 621 VariableMode mode = scope_info->ContextLocalMode(var); |
593 ScriptContextTable::LookupResult lookup; | 622 ScriptContextTable::LookupResult lookup; |
594 if (ScriptContextTable::Lookup(script_context, name, &lookup)) { | 623 if (ScriptContextTable::Lookup(script_context, name, &lookup)) { |
595 if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(lookup.mode)) { | 624 if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(lookup.mode)) { |
596 return ThrowRedeclarationError(isolate, name); | 625 // ES#sec-globaldeclarationinstantiation 5.b: |
626 // If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError | |
627 // exception. | |
628 return ThrowRedeclarationError(isolate, name, | |
629 RedeclarationType::kSyntaxError); | |
597 } | 630 } |
598 } | 631 } |
599 | 632 |
600 if (IsLexicalVariableMode(mode)) { | 633 if (IsLexicalVariableMode(mode)) { |
601 LookupIterator it(global_object, name, global_object, | 634 LookupIterator it(global_object, name, global_object, |
602 LookupIterator::OWN_SKIP_INTERCEPTOR); | 635 LookupIterator::OWN_SKIP_INTERCEPTOR); |
603 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); | 636 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); |
604 if (!maybe.IsJust()) return isolate->heap()->exception(); | 637 if (!maybe.IsJust()) return isolate->heap()->exception(); |
605 if ((maybe.FromJust() & DONT_DELETE) != 0) { | 638 if ((maybe.FromJust() & DONT_DELETE) != 0) { |
606 return ThrowRedeclarationError(isolate, name); | 639 // ES#sec-globaldeclarationinstantiation 5.a: |
640 // If envRec.HasVarDeclaration(name) is true, throw a SyntaxError | |
641 // exception. | |
642 return ThrowRedeclarationError(isolate, name, | |
643 RedeclarationType::kSyntaxError); | |
607 } | 644 } |
608 | 645 |
609 JSGlobalObject::InvalidatePropertyCell(global_object, name); | 646 JSGlobalObject::InvalidatePropertyCell(global_object, name); |
610 } | 647 } |
611 } | 648 } |
612 return isolate->heap()->undefined_value(); | 649 return isolate->heap()->undefined_value(); |
613 } | 650 } |
614 | 651 |
615 | 652 |
616 RUNTIME_FUNCTION(Runtime_NewScriptContext) { | 653 RUNTIME_FUNCTION(Runtime_NewScriptContext) { |
(...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1002 RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Strict) { | 1039 RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Strict) { |
1003 HandleScope scope(isolate); | 1040 HandleScope scope(isolate); |
1004 DCHECK_EQ(2, args.length()); | 1041 DCHECK_EQ(2, args.length()); |
1005 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); | 1042 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); |
1006 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); | 1043 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); |
1007 RETURN_RESULT_OR_FAILURE(isolate, StoreLookupSlot(name, value, STRICT)); | 1044 RETURN_RESULT_OR_FAILURE(isolate, StoreLookupSlot(name, value, STRICT)); |
1008 } | 1045 } |
1009 | 1046 |
1010 } // namespace internal | 1047 } // namespace internal |
1011 } // namespace v8 | 1048 } // namespace v8 |
OLD | NEW |