Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(250)

Side by Side Diff: src/runtime/runtime-scopes.cc

Issue 2048703002: change most cases of variable redeclaration from TypeError to SyntaxError (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebase Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | test/mjsunit/es6/block-eval-var-over-let.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | test/mjsunit/es6/block-eval-var-over-let.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698