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

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: incorporating comments into code 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 struct RedeclarationError {
adamk 2016/06/09 15:08:42 You can use 'enum class' to get the same thing wit
20 enum Type { kSyntaxError = 0, kTypeError = 1 };
21 };
22
23 static Object* ThrowRedeclarationError(
24 Isolate* isolate, Handle<String> name,
25 RedeclarationError::Type redeclaration_error_type) {
20 HandleScope scope(isolate); 26 HandleScope scope(isolate);
21 THROW_NEW_ERROR_RETURN_FAILURE( 27 if (redeclaration_error_type == RedeclarationError::kSyntaxError) {
22 isolate, NewTypeError(MessageTemplate::kVarRedeclaration, name)); 28 THROW_NEW_ERROR_RETURN_FAILURE(
29 isolate, NewSyntaxError(MessageTemplate::kVarRedeclaration, name));
30 } else {
31 THROW_NEW_ERROR_RETURN_FAILURE(
32 isolate, NewTypeError(MessageTemplate::kVarRedeclaration, name));
33 }
23 } 34 }
24 35
25 36
26 RUNTIME_FUNCTION(Runtime_ThrowConstAssignError) { 37 RUNTIME_FUNCTION(Runtime_ThrowConstAssignError) {
27 HandleScope scope(isolate); 38 HandleScope scope(isolate);
28 THROW_NEW_ERROR_RETURN_FAILURE(isolate, 39 THROW_NEW_ERROR_RETURN_FAILURE(isolate,
29 NewTypeError(MessageTemplate::kConstAssign)); 40 NewTypeError(MessageTemplate::kConstAssign));
30 } 41 }
31 42
32 43
33 // May throw a RedeclarationError. 44 // May throw a RedeclarationError.
34 static Object* DeclareGlobals(Isolate* isolate, Handle<JSGlobalObject> global, 45 static Object* DeclareGlobals(
35 Handle<String> name, Handle<Object> value, 46 Isolate* isolate, Handle<JSGlobalObject> global, Handle<String> name,
36 PropertyAttributes attr, bool is_var, 47 Handle<Object> value, PropertyAttributes attr, bool is_var, bool is_const,
37 bool is_const, bool is_function) { 48 bool is_function, RedeclarationError::Type redeclaration_error_type) {
38 Handle<ScriptContextTable> script_contexts( 49 Handle<ScriptContextTable> script_contexts(
39 global->native_context()->script_context_table()); 50 global->native_context()->script_context_table());
40 ScriptContextTable::LookupResult lookup; 51 ScriptContextTable::LookupResult lookup;
41 if (ScriptContextTable::Lookup(script_contexts, name, &lookup) && 52 if (ScriptContextTable::Lookup(script_contexts, name, &lookup) &&
42 IsLexicalVariableMode(lookup.mode)) { 53 IsLexicalVariableMode(lookup.mode)) {
43 return ThrowRedeclarationError(isolate, name); 54 // ES#sec-globaldeclarationinstantiation 6.a:
55 // If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
56 // exception.
57 return ThrowRedeclarationError(isolate, name,
58 RedeclarationError::kSyntaxError);
44 } 59 }
45 60
46 // Do the lookup own properties only, see ES5 erratum. 61 // Do the lookup own properties only, see ES5 erratum.
47 LookupIterator it(global, name, global, LookupIterator::OWN_SKIP_INTERCEPTOR); 62 LookupIterator it(global, name, global, LookupIterator::OWN_SKIP_INTERCEPTOR);
48 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); 63 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
49 if (!maybe.IsJust()) return isolate->heap()->exception(); 64 if (!maybe.IsJust()) return isolate->heap()->exception();
50 65
51 if (it.IsFound()) { 66 if (it.IsFound()) {
52 PropertyAttributes old_attributes = maybe.FromJust(); 67 PropertyAttributes old_attributes = maybe.FromJust();
53 // The name was declared before; check for conflicting re-declarations. 68 // The name was declared before; check for conflicting re-declarations.
54 if (is_const) return ThrowRedeclarationError(isolate, name); 69 if (is_const) {
adamk 2016/06/09 15:08:42 Did you say this code is unreachable?
70 return ThrowRedeclarationError(isolate, name,
71 RedeclarationError::kSyntaxError);
72 }
55 73
56 // Skip var re-declarations. 74 // Skip var re-declarations.
57 if (is_var) return isolate->heap()->undefined_value(); 75 if (is_var) return isolate->heap()->undefined_value();
58 76
59 DCHECK(is_function); 77 DCHECK(is_function);
60 if ((old_attributes & DONT_DELETE) != 0) { 78 if ((old_attributes & DONT_DELETE) != 0) {
61 // Only allow reconfiguring globals to functions in user code (no 79 // Only allow reconfiguring globals to functions in user code (no
62 // natives, which are marked as read-only). 80 // natives, which are marked as read-only).
63 DCHECK((attr & READ_ONLY) == 0); 81 DCHECK((attr & READ_ONLY) == 0);
64 82
65 // Check whether we can reconfigure the existing property into a 83 // Check whether we can reconfigure the existing property into a
66 // function. 84 // function.
67 PropertyDetails old_details = it.property_details(); 85 PropertyDetails old_details = it.property_details();
68 if (old_details.IsReadOnly() || old_details.IsDontEnum() || 86 if (old_details.IsReadOnly() || old_details.IsDontEnum() ||
69 (it.state() == LookupIterator::ACCESSOR && 87 (it.state() == LookupIterator::ACCESSOR &&
70 it.GetAccessors()->IsAccessorPair())) { 88 it.GetAccessors()->IsAccessorPair())) {
71 return ThrowRedeclarationError(isolate, name); 89 // ES#sec-globaldeclarationinstantiation 5.d:
90 // If hasRestrictedGlobal is true, throw a SyntaxError exception.
91 // ES#sec-evaldeclarationinstantiation 8.a.iv.1.b:
92 // If fnDefinable is false, throw a TypeError exception.
93 return ThrowRedeclarationError(isolate, name, redeclaration_error_type);
72 } 94 }
73 // If the existing property is not configurable, keep its attributes. Do 95 // If the existing property is not configurable, keep its attributes. Do
74 attr = old_attributes; 96 attr = old_attributes;
75 } 97 }
76 98
77 // If the current state is ACCESSOR, this could mean it's an AccessorInfo 99 // If the current state is ACCESSOR, this could mean it's an AccessorInfo
78 // type property. We are not allowed to call into such setters during global 100 // type property. We are not allowed to call into such setters during global
79 // function declaration since this would break e.g., onload. Meaning 101 // function declaration since this would break e.g., onload. Meaning
80 // 'function onload() {}' would invalidly register that function as the 102 // 'function onload() {}' would invalidly register that function as the
81 // onload callback. To avoid this situation, we first delete the property 103 // onload callback. To avoid this situation, we first delete the property
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 152
131 // Compute the property attributes. According to ECMA-262, 153 // Compute the property attributes. According to ECMA-262,
132 // the property must be non-configurable except in eval. 154 // the property must be non-configurable except in eval.
133 bool is_native = DeclareGlobalsNativeFlag::decode(flags); 155 bool is_native = DeclareGlobalsNativeFlag::decode(flags);
134 bool is_eval = DeclareGlobalsEvalFlag::decode(flags); 156 bool is_eval = DeclareGlobalsEvalFlag::decode(flags);
135 int attr = NONE; 157 int attr = NONE;
136 if (is_const) attr |= READ_ONLY; 158 if (is_const) attr |= READ_ONLY;
137 if (is_function && is_native) attr |= READ_ONLY; 159 if (is_function && is_native) attr |= READ_ONLY;
138 if (!is_const && !is_eval) attr |= DONT_DELETE; 160 if (!is_const && !is_eval) attr |= DONT_DELETE;
139 161
140 Object* result = DeclareGlobals(isolate, global, name, value, 162 // ES#sec-globaldeclarationinstantiation 5.d:
141 static_cast<PropertyAttributes>(attr), 163 // If hasRestrictedGlobal is true, throw a SyntaxError exception.
142 is_var, is_const, is_function); 164 Object* result = DeclareGlobals(
165 isolate, global, name, value, static_cast<PropertyAttributes>(attr),
166 is_var, is_const, is_function, RedeclarationError::kSyntaxError);
143 if (isolate->has_pending_exception()) return result; 167 if (isolate->has_pending_exception()) return result;
144 }); 168 });
145 169
146 return isolate->heap()->undefined_value(); 170 return isolate->heap()->undefined_value();
147 } 171 }
148 172
149 173
150 RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) { 174 RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) {
151 HandleScope scope(isolate); 175 HandleScope scope(isolate);
152 // args[0] == name 176 // args[0] == name
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 251
228 int index; 252 int index;
229 PropertyAttributes attributes; 253 PropertyAttributes attributes;
230 BindingFlags binding_flags; 254 BindingFlags binding_flags;
231 255
232 if ((attr & EVAL_DECLARED) != 0) { 256 if ((attr & EVAL_DECLARED) != 0) {
233 // Check for a conflict with a lexically scoped variable 257 // Check for a conflict with a lexically scoped variable
234 context_arg->Lookup(name, LEXICAL_TEST, &index, &attributes, 258 context_arg->Lookup(name, LEXICAL_TEST, &index, &attributes,
235 &binding_flags); 259 &binding_flags);
236 if (attributes != ABSENT && binding_flags == BINDING_CHECK_INITIALIZED) { 260 if (attributes != ABSENT && binding_flags == BINDING_CHECK_INITIALIZED) {
237 return ThrowRedeclarationError(isolate, name); 261 return ThrowRedeclarationError(isolate, name,
adamk 2016/06/09 15:08:42 Why no comment here?
jwolfe 2016/06/09 17:05:23 Oops. Missed a spot. I've got a comment prepared a
262 RedeclarationError::kSyntaxError);
238 } 263 }
239 attr = static_cast<PropertyAttributes>(attr & ~EVAL_DECLARED); 264 attr = static_cast<PropertyAttributes>(attr & ~EVAL_DECLARED);
240 } 265 }
241 266
242 Handle<Object> holder = context->Lookup(name, DONT_FOLLOW_CHAINS, &index, 267 Handle<Object> holder = context->Lookup(name, DONT_FOLLOW_CHAINS, &index,
243 &attributes, &binding_flags); 268 &attributes, &binding_flags);
244 if (holder.is_null()) { 269 if (holder.is_null()) {
245 // In case of JSProxy, an exception might have been thrown. 270 // In case of JSProxy, an exception might have been thrown.
246 if (isolate->has_pending_exception()) return isolate->heap()->exception(); 271 if (isolate->has_pending_exception()) return isolate->heap()->exception();
247 } 272 }
248 273
249 Handle<JSObject> object; 274 Handle<JSObject> object;
250 Handle<Object> value = 275 Handle<Object> value =
251 is_function ? initial_value 276 is_function ? initial_value
252 : Handle<Object>::cast(isolate->factory()->undefined_value()); 277 : Handle<Object>::cast(isolate->factory()->undefined_value());
253 278
254 // TODO(verwaest): This case should probably not be covered by this function, 279 // TODO(verwaest): This case should probably not be covered by this function,
255 // but by DeclareGlobals instead. 280 // but by DeclareGlobals instead.
256 if (attributes != ABSENT && holder->IsJSGlobalObject()) { 281 if (attributes != ABSENT && holder->IsJSGlobalObject()) {
282 // ES#sec-evaldeclarationinstantiation 8.a.iv.1.b:
283 // If fnDefinable is false, throw a TypeError exception.
257 return DeclareGlobals(isolate, Handle<JSGlobalObject>::cast(holder), name, 284 return DeclareGlobals(isolate, Handle<JSGlobalObject>::cast(holder), name,
258 value, attr, is_var, is_const, is_function); 285 value, attr, is_var, is_const, is_function,
286 RedeclarationError::kTypeError);
259 } 287 }
260 if (context_arg->extension()->IsJSGlobalObject()) { 288 if (context_arg->extension()->IsJSGlobalObject()) {
261 Handle<JSGlobalObject> global( 289 Handle<JSGlobalObject> global(
262 JSGlobalObject::cast(context_arg->extension()), isolate); 290 JSGlobalObject::cast(context_arg->extension()), isolate);
263 return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const, 291 return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const,
264 is_function); 292 is_function, RedeclarationError::kTypeError);
265 } else if (context->IsScriptContext()) { 293 } else if (context->IsScriptContext()) {
266 DCHECK(context->global_object()->IsJSGlobalObject()); 294 DCHECK(context->global_object()->IsJSGlobalObject());
267 Handle<JSGlobalObject> global( 295 Handle<JSGlobalObject> global(
268 JSGlobalObject::cast(context->global_object()), isolate); 296 JSGlobalObject::cast(context->global_object()), isolate);
269 return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const, 297 return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const,
270 is_function); 298 is_function, RedeclarationError::kTypeError);
271 } 299 }
272 300
273 if (attributes != ABSENT) { 301 if (attributes != ABSENT) {
274 // The name was declared before; check for conflicting re-declarations. 302 // The name was declared before; check for conflicting re-declarations.
275 if (is_const || (attributes & READ_ONLY) != 0) { 303 if (is_const || (attributes & READ_ONLY) != 0) {
adamk 2016/06/09 15:08:42 Was this also unreachable?
276 return ThrowRedeclarationError(isolate, name); 304 return ThrowRedeclarationError(isolate, name,
305 RedeclarationError::kSyntaxError);
277 } 306 }
278 307
279 // Skip var re-declarations. 308 // Skip var re-declarations.
280 if (is_var) return isolate->heap()->undefined_value(); 309 if (is_var) return isolate->heap()->undefined_value();
281 310
282 DCHECK(is_function); 311 DCHECK(is_function);
283 if (index != Context::kNotFound) { 312 if (index != Context::kNotFound) {
284 DCHECK(holder.is_identical_to(context)); 313 DCHECK(holder.is_identical_to(context));
285 context->set(index, *initial_value); 314 context->set(index, *initial_value);
286 return isolate->heap()->undefined_value(); 315 return isolate->heap()->undefined_value();
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after
605 static Object* FindNameClash(Handle<ScopeInfo> scope_info, 634 static Object* FindNameClash(Handle<ScopeInfo> scope_info,
606 Handle<JSGlobalObject> global_object, 635 Handle<JSGlobalObject> global_object,
607 Handle<ScriptContextTable> script_context) { 636 Handle<ScriptContextTable> script_context) {
608 Isolate* isolate = scope_info->GetIsolate(); 637 Isolate* isolate = scope_info->GetIsolate();
609 for (int var = 0; var < scope_info->ContextLocalCount(); var++) { 638 for (int var = 0; var < scope_info->ContextLocalCount(); var++) {
610 Handle<String> name(scope_info->ContextLocalName(var)); 639 Handle<String> name(scope_info->ContextLocalName(var));
611 VariableMode mode = scope_info->ContextLocalMode(var); 640 VariableMode mode = scope_info->ContextLocalMode(var);
612 ScriptContextTable::LookupResult lookup; 641 ScriptContextTable::LookupResult lookup;
613 if (ScriptContextTable::Lookup(script_context, name, &lookup)) { 642 if (ScriptContextTable::Lookup(script_context, name, &lookup)) {
614 if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(lookup.mode)) { 643 if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(lookup.mode)) {
615 return ThrowRedeclarationError(isolate, name); 644 // ES#sec-globaldeclarationinstantiation 5.b:
645 // If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
adamk 2016/06/09 15:08:42 I also see this line in EvalDeclarationInstantiati
jwolfe 2016/06/09 17:05:23 I don't believe this code runs for eval. This code
646 // exception.
647 return ThrowRedeclarationError(isolate, name,
648 RedeclarationError::kSyntaxError);
616 } 649 }
617 } 650 }
618 651
619 if (IsLexicalVariableMode(mode)) { 652 if (IsLexicalVariableMode(mode)) {
620 LookupIterator it(global_object, name, global_object, 653 LookupIterator it(global_object, name, global_object,
621 LookupIterator::OWN_SKIP_INTERCEPTOR); 654 LookupIterator::OWN_SKIP_INTERCEPTOR);
622 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); 655 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
623 if (!maybe.IsJust()) return isolate->heap()->exception(); 656 if (!maybe.IsJust()) return isolate->heap()->exception();
624 if ((maybe.FromJust() & DONT_DELETE) != 0) { 657 if ((maybe.FromJust() & DONT_DELETE) != 0) {
625 return ThrowRedeclarationError(isolate, name); 658 // ES#sec-globaldeclarationinstantiation 5.a:
659 // If envRec.HasVarDeclaration(name) is true, throw a SyntaxError
660 // exception.
661 return ThrowRedeclarationError(isolate, name,
662 RedeclarationError::kSyntaxError);
626 } 663 }
627 664
628 JSGlobalObject::InvalidatePropertyCell(global_object, name); 665 JSGlobalObject::InvalidatePropertyCell(global_object, name);
629 } 666 }
630 } 667 }
631 return isolate->heap()->undefined_value(); 668 return isolate->heap()->undefined_value();
632 } 669 }
633 670
634 671
635 RUNTIME_FUNCTION(Runtime_NewScriptContext) { 672 RUNTIME_FUNCTION(Runtime_NewScriptContext) {
(...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after
1021 RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Strict) { 1058 RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Strict) {
1022 HandleScope scope(isolate); 1059 HandleScope scope(isolate);
1023 DCHECK_EQ(2, args.length()); 1060 DCHECK_EQ(2, args.length());
1024 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); 1061 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
1025 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); 1062 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
1026 RETURN_RESULT_OR_FAILURE(isolate, StoreLookupSlot(name, value, STRICT)); 1063 RETURN_RESULT_OR_FAILURE(isolate, StoreLookupSlot(name, value, STRICT));
1027 } 1064 }
1028 1065
1029 } // namespace internal 1066 } // namespace internal
1030 } // namespace v8 1067 } // 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