Chromium Code Reviews| Index: src/runtime/runtime-scopes.cc |
| diff --git a/src/runtime/runtime-scopes.cc b/src/runtime/runtime-scopes.cc |
| index e36fd842149b28e22ee2fe3477dcba5c3e0d666d..1424bff61f60976e87d3339c185705c8ea536633 100644 |
| --- a/src/runtime/runtime-scopes.cc |
| +++ b/src/runtime/runtime-scopes.cc |
| @@ -16,10 +16,21 @@ |
| namespace v8 { |
| namespace internal { |
| -static Object* ThrowRedeclarationError(Isolate* isolate, Handle<String> name) { |
| +struct RedeclarationError { |
|
adamk
2016/06/09 15:08:42
You can use 'enum class' to get the same thing wit
|
| + enum Type { kSyntaxError = 0, kTypeError = 1 }; |
| +}; |
| + |
| +static Object* ThrowRedeclarationError( |
| + Isolate* isolate, Handle<String> name, |
| + RedeclarationError::Type redeclaration_error_type) { |
| HandleScope scope(isolate); |
| - THROW_NEW_ERROR_RETURN_FAILURE( |
| - isolate, NewTypeError(MessageTemplate::kVarRedeclaration, name)); |
| + if (redeclaration_error_type == RedeclarationError::kSyntaxError) { |
| + THROW_NEW_ERROR_RETURN_FAILURE( |
| + isolate, NewSyntaxError(MessageTemplate::kVarRedeclaration, name)); |
| + } else { |
| + THROW_NEW_ERROR_RETURN_FAILURE( |
| + isolate, NewTypeError(MessageTemplate::kVarRedeclaration, name)); |
| + } |
| } |
| @@ -31,16 +42,20 @@ RUNTIME_FUNCTION(Runtime_ThrowConstAssignError) { |
| // May throw a RedeclarationError. |
| -static Object* DeclareGlobals(Isolate* isolate, Handle<JSGlobalObject> global, |
| - Handle<String> name, Handle<Object> value, |
| - PropertyAttributes attr, bool is_var, |
| - bool is_const, bool is_function) { |
| +static Object* DeclareGlobals( |
| + Isolate* isolate, Handle<JSGlobalObject> global, Handle<String> name, |
| + Handle<Object> value, PropertyAttributes attr, bool is_var, bool is_const, |
| + bool is_function, RedeclarationError::Type redeclaration_error_type) { |
| Handle<ScriptContextTable> script_contexts( |
| global->native_context()->script_context_table()); |
| ScriptContextTable::LookupResult lookup; |
| if (ScriptContextTable::Lookup(script_contexts, name, &lookup) && |
| IsLexicalVariableMode(lookup.mode)) { |
| - return ThrowRedeclarationError(isolate, name); |
| + // ES#sec-globaldeclarationinstantiation 6.a: |
| + // If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError |
| + // exception. |
| + return ThrowRedeclarationError(isolate, name, |
| + RedeclarationError::kSyntaxError); |
| } |
| // Do the lookup own properties only, see ES5 erratum. |
| @@ -51,7 +66,10 @@ static Object* DeclareGlobals(Isolate* isolate, Handle<JSGlobalObject> global, |
| if (it.IsFound()) { |
| PropertyAttributes old_attributes = maybe.FromJust(); |
| // The name was declared before; check for conflicting re-declarations. |
| - if (is_const) return ThrowRedeclarationError(isolate, name); |
| + if (is_const) { |
|
adamk
2016/06/09 15:08:42
Did you say this code is unreachable?
|
| + return ThrowRedeclarationError(isolate, name, |
| + RedeclarationError::kSyntaxError); |
| + } |
| // Skip var re-declarations. |
| if (is_var) return isolate->heap()->undefined_value(); |
| @@ -68,7 +86,11 @@ static Object* DeclareGlobals(Isolate* isolate, Handle<JSGlobalObject> global, |
| if (old_details.IsReadOnly() || old_details.IsDontEnum() || |
| (it.state() == LookupIterator::ACCESSOR && |
| it.GetAccessors()->IsAccessorPair())) { |
| - return ThrowRedeclarationError(isolate, name); |
| + // ES#sec-globaldeclarationinstantiation 5.d: |
| + // If hasRestrictedGlobal is true, throw a SyntaxError exception. |
| + // ES#sec-evaldeclarationinstantiation 8.a.iv.1.b: |
| + // If fnDefinable is false, throw a TypeError exception. |
| + return ThrowRedeclarationError(isolate, name, redeclaration_error_type); |
| } |
| // If the existing property is not configurable, keep its attributes. Do |
| attr = old_attributes; |
| @@ -137,9 +159,11 @@ RUNTIME_FUNCTION(Runtime_DeclareGlobals) { |
| if (is_function && is_native) attr |= READ_ONLY; |
| if (!is_const && !is_eval) attr |= DONT_DELETE; |
| - Object* result = DeclareGlobals(isolate, global, name, value, |
| - static_cast<PropertyAttributes>(attr), |
| - is_var, is_const, is_function); |
| + // ES#sec-globaldeclarationinstantiation 5.d: |
| + // If hasRestrictedGlobal is true, throw a SyntaxError exception. |
| + Object* result = DeclareGlobals( |
| + isolate, global, name, value, static_cast<PropertyAttributes>(attr), |
| + is_var, is_const, is_function, RedeclarationError::kSyntaxError); |
| if (isolate->has_pending_exception()) return result; |
| }); |
| @@ -234,7 +258,8 @@ Object* DeclareLookupSlot(Isolate* isolate, Handle<String> name, |
| context_arg->Lookup(name, LEXICAL_TEST, &index, &attributes, |
| &binding_flags); |
| if (attributes != ABSENT && binding_flags == BINDING_CHECK_INITIALIZED) { |
| - return ThrowRedeclarationError(isolate, name); |
| + 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
|
| + RedeclarationError::kSyntaxError); |
| } |
| attr = static_cast<PropertyAttributes>(attr & ~EVAL_DECLARED); |
| } |
| @@ -254,26 +279,30 @@ Object* DeclareLookupSlot(Isolate* isolate, Handle<String> name, |
| // TODO(verwaest): This case should probably not be covered by this function, |
| // but by DeclareGlobals instead. |
| if (attributes != ABSENT && holder->IsJSGlobalObject()) { |
| + // ES#sec-evaldeclarationinstantiation 8.a.iv.1.b: |
| + // If fnDefinable is false, throw a TypeError exception. |
| return DeclareGlobals(isolate, Handle<JSGlobalObject>::cast(holder), name, |
| - value, attr, is_var, is_const, is_function); |
| + value, attr, is_var, is_const, is_function, |
| + RedeclarationError::kTypeError); |
| } |
| if (context_arg->extension()->IsJSGlobalObject()) { |
| Handle<JSGlobalObject> global( |
| JSGlobalObject::cast(context_arg->extension()), isolate); |
| return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const, |
| - is_function); |
| + is_function, RedeclarationError::kTypeError); |
| } else if (context->IsScriptContext()) { |
| DCHECK(context->global_object()->IsJSGlobalObject()); |
| Handle<JSGlobalObject> global( |
| JSGlobalObject::cast(context->global_object()), isolate); |
| return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const, |
| - is_function); |
| + is_function, RedeclarationError::kTypeError); |
| } |
| if (attributes != ABSENT) { |
| // The name was declared before; check for conflicting re-declarations. |
| if (is_const || (attributes & READ_ONLY) != 0) { |
|
adamk
2016/06/09 15:08:42
Was this also unreachable?
|
| - return ThrowRedeclarationError(isolate, name); |
| + return ThrowRedeclarationError(isolate, name, |
| + RedeclarationError::kSyntaxError); |
| } |
| // Skip var re-declarations. |
| @@ -612,7 +641,11 @@ static Object* FindNameClash(Handle<ScopeInfo> scope_info, |
| ScriptContextTable::LookupResult lookup; |
| if (ScriptContextTable::Lookup(script_context, name, &lookup)) { |
| if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(lookup.mode)) { |
| - return ThrowRedeclarationError(isolate, name); |
| + // ES#sec-globaldeclarationinstantiation 5.b: |
| + // 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
|
| + // exception. |
| + return ThrowRedeclarationError(isolate, name, |
| + RedeclarationError::kSyntaxError); |
| } |
| } |
| @@ -622,7 +655,11 @@ static Object* FindNameClash(Handle<ScopeInfo> scope_info, |
| Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); |
| if (!maybe.IsJust()) return isolate->heap()->exception(); |
| if ((maybe.FromJust() & DONT_DELETE) != 0) { |
| - return ThrowRedeclarationError(isolate, name); |
| + // ES#sec-globaldeclarationinstantiation 5.a: |
| + // If envRec.HasVarDeclaration(name) is true, throw a SyntaxError |
| + // exception. |
| + return ThrowRedeclarationError(isolate, name, |
| + RedeclarationError::kSyntaxError); |
| } |
| JSGlobalObject::InvalidatePropertyCell(global_object, name); |