Commit 85c2c8d8 authored by littledan's avatar littledan Committed by Commit bot

Revert of change most cases of variable redeclaration from TypeError to...

Revert of change most cases of variable redeclaration from TypeError to SyntaxError (patchset #8 id:140001 of https://codereview.chromium.org/2048703002/ )

Reason for revert:
This is going to break the LayoutTest inspector-protocol/console/console-let-const-with-api.html as seen in https://build.chromium.org/p/tryserver.v8/builders/v8_linux_blink_rel/builds/2247 . Please run this test manually, using instructions at https://www.chromium.org/developers/testing/webkit-layout-tests , and fix on the Chrome side if needed before resubmitting this patch.

Original issue's description:
> change most cases of variable redeclaration from TypeError to SyntaxError.
>
> Code like `let a; eval("var a;");` should throw a SyntaxError, not a TypeError
> (this caused a test262 failure.). However, the code `eval("function NaN() {}");`
> should actually throw a TypeError. This patch changes most cases of
> redeclaration errors from TypeError to SyntaxError. See the test
> mjsunit/regress/redeclaration-error-types for a thorough analysis with spec
> references.
>
> The relevant sections of the spec are ES#sec-globaldeclarationinstantiation and
> ES#sec-evaldeclarationinstantiation
>
> BUG=v8:4955
> LOG=y
>
> Committed: https://crrev.com/2b787561763d0f7e8dab698652715a742cf78291
> Cr-Commit-Position: refs/heads/master@{#36940}

TBR=adamk@chromium.org,jwolfe@igalia.com
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=v8:4955

Review-Url: https://codereview.chromium.org/2064793002
Cr-Commit-Position: refs/heads/master@{#36941}
parent 2b787561
......@@ -16,18 +16,10 @@
namespace v8 {
namespace internal {
enum class RedeclarationType { kSyntaxError = 0, kTypeError = 1 };
static Object* ThrowRedeclarationError(Isolate* isolate, Handle<String> name,
RedeclarationType redeclaration_type) {
static Object* ThrowRedeclarationError(Isolate* isolate, Handle<String> name) {
HandleScope scope(isolate);
if (redeclaration_type == RedeclarationType::kSyntaxError) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewSyntaxError(MessageTemplate::kVarRedeclaration, name));
} else {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kVarRedeclaration, name));
}
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kVarRedeclaration, name));
}
......@@ -42,18 +34,13 @@ RUNTIME_FUNCTION(Runtime_ThrowConstAssignError) {
static Object* DeclareGlobals(Isolate* isolate, Handle<JSGlobalObject> global,
Handle<String> name, Handle<Object> value,
PropertyAttributes attr, bool is_var,
bool is_function,
RedeclarationType redeclaration_type) {
bool is_function) {
Handle<ScriptContextTable> script_contexts(
global->native_context()->script_context_table());
ScriptContextTable::LookupResult lookup;
if (ScriptContextTable::Lookup(script_contexts, name, &lookup) &&
IsLexicalVariableMode(lookup.mode)) {
// ES#sec-globaldeclarationinstantiation 6.a:
// If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
// exception.
return ThrowRedeclarationError(isolate, name,
RedeclarationType::kSyntaxError);
return ThrowRedeclarationError(isolate, name);
}
// Do the lookup own properties only, see ES5 erratum.
......@@ -80,11 +67,7 @@ static Object* DeclareGlobals(Isolate* isolate, Handle<JSGlobalObject> global,
if (old_details.IsReadOnly() || old_details.IsDontEnum() ||
(it.state() == LookupIterator::ACCESSOR &&
it.GetAccessors()->IsAccessorPair())) {
// 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_type);
return ThrowRedeclarationError(isolate, name);
}
// If the existing property is not configurable, keep its attributes. Do
attr = old_attributes;
......@@ -147,11 +130,9 @@ RUNTIME_FUNCTION(Runtime_DeclareGlobals) {
if (is_function && is_native) attr |= READ_ONLY;
if (!is_eval) attr |= DONT_DELETE;
// 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_function, RedeclarationType::kSyntaxError);
Object* result = DeclareGlobals(isolate, global, name, value,
static_cast<PropertyAttributes>(attr),
is_var, is_function);
if (isolate->has_pending_exception()) return result;
});
......@@ -234,13 +215,7 @@ 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) {
// ES#sec-evaldeclarationinstantiation 5.a.i.1:
// If varEnvRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
// exception.
// ES#sec-evaldeclarationinstantiation 5.d.ii.2.a.i:
// Throw a SyntaxError exception.
return ThrowRedeclarationError(isolate, name,
RedeclarationType::kSyntaxError);
return ThrowRedeclarationError(isolate, name);
}
attr = static_cast<PropertyAttributes>(attr & ~EVAL_DECLARED);
}
......@@ -260,30 +235,26 @@ 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_function,
RedeclarationType::kTypeError);
value, attr, is_var, is_function);
}
if (context_arg->extension()->IsJSGlobalObject()) {
Handle<JSGlobalObject> global(
JSGlobalObject::cast(context_arg->extension()), isolate);
return DeclareGlobals(isolate, global, name, value, attr, is_var,
is_function, RedeclarationType::kTypeError);
is_function);
} 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_function, RedeclarationType::kTypeError);
is_function);
}
if (attributes != ABSENT) {
// The name was declared before; check for conflicting re-declarations.
if ((attributes & READ_ONLY) != 0) {
return ThrowRedeclarationError(isolate, name,
RedeclarationType::kSyntaxError);
return ThrowRedeclarationError(isolate, name);
}
// Skip var re-declarations.
......@@ -622,11 +593,7 @@ static Object* FindNameClash(Handle<ScopeInfo> scope_info,
ScriptContextTable::LookupResult lookup;
if (ScriptContextTable::Lookup(script_context, name, &lookup)) {
if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(lookup.mode)) {
// ES#sec-globaldeclarationinstantiation 5.b:
// If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
// exception.
return ThrowRedeclarationError(isolate, name,
RedeclarationType::kSyntaxError);
return ThrowRedeclarationError(isolate, name);
}
}
......@@ -636,13 +603,7 @@ 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) {
// ES#sec-globaldeclarationinstantiation 5.a:
// If envRec.HasVarDeclaration(name) is true, throw a SyntaxError
// exception.
// ES#sec-globaldeclarationinstantiation 5.d:
// If hasRestrictedGlobal is true, throw a SyntaxError exception.
return ThrowRedeclarationError(isolate, name,
RedeclarationType::kSyntaxError);
return ThrowRedeclarationError(isolate, name);
}
JSGlobalObject::InvalidatePropertyCell(global_object, name);
......
......@@ -8,13 +8,13 @@
assertThrows(function() {
let x = 1;
eval('var x');
}, SyntaxError);
}, TypeError);
// If the eval is in its own block scope, throws
assertThrows(function() {
let y = 1;
{ eval('var y'); }
}, SyntaxError);
}, TypeError);
// If the let is in its own block scope, with the eval, throws
assertThrows(function() {
......@@ -22,7 +22,7 @@ assertThrows(function() {
let x = 1;
eval('var x');
}
}, SyntaxError);
}, TypeError);
// Legal if the let is no longer visible
assertDoesNotThrow(function() {
......@@ -37,13 +37,13 @@ assertDoesNotThrow(function() {
assertThrows(function() {
const x = 1;
eval('var x');
}, SyntaxError);
}, TypeError);
// If the eval is in its own block scope, throws
assertThrows(function() {
const y = 1;
{ eval('var y'); }
}, SyntaxError);
}, TypeError);
// If the const is in its own block scope, with the eval, throws
assertThrows(function() {
......@@ -51,7 +51,7 @@ assertThrows(function() {
const x = 1;
eval('var x');
}
}, SyntaxError);
}, TypeError);
// Legal if the const is no longer visible
assertDoesNotThrow(function() {
......
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function doTest(scripts, expectedError) {
var realm = Realm.create();
for (var i = 0; i < scripts.length - 1; i++) {
Realm.eval(realm, scripts[i]);
}
assertThrows(function() {
Realm.eval(realm, scripts[scripts.length - 1]);
}, Realm.eval(realm, expectedError));
Realm.dispose(realm);
}
var tests = [
{
// ES#sec-globaldeclarationinstantiation 5.a:
// If envRec.HasVarDeclaration(name) is true, throw a SyntaxError
// exception.
scripts: [
"var a;",
"let a;",
],
expectedError: "SyntaxError",
},
{
// ES#sec-globaldeclarationinstantiation 6.a:
// If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
// exception.
scripts: [
"let a;",
"var a;",
],
expectedError: "SyntaxError",
},
{
// ES#sec-globaldeclarationinstantiation 5.b:
// If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
// exception.
scripts: [
"let a;",
"let a;",
],
expectedError: "SyntaxError",
},
{
// ES#sec-evaldeclarationinstantiation 5.a.i.1:
// If varEnvRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
// exception.
scripts: [
'let a; eval("var a;");',
],
expectedError: "SyntaxError",
},
{
// ES#sec-evaldeclarationinstantiation 5.a.i.1:
// If varEnvRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
// exception.
scripts: [
'let a; eval("function a() {}");',
],
expectedError: "SyntaxError",
},
{
// ES#sec-evaldeclarationinstantiation 5.d.ii.2.a.i:
// Throw a SyntaxError exception.
scripts: [
'(function() { let a; eval("var a;"); })();',
],
expectedError: "SyntaxError",
},
{
// ES#sec-evaldeclarationinstantiation 5.d.ii.2.a.i:
// Throw a SyntaxError exception.
scripts: [
'(function() { let a; eval("function a() {}"); })();',
],
expectedError: "SyntaxError",
},
{
// ES#sec-globaldeclarationinstantiation 5.d:
// If hasRestrictedGlobal is true, throw a SyntaxError exception.
scripts: [
'let NaN;',
],
expectedError: "SyntaxError",
},
{
// ES#sec-globaldeclarationinstantiation 5.d:
// If hasRestrictedGlobal is true, throw a SyntaxError exception.
scripts: [
'function NaN() {}',
],
expectedError: "SyntaxError",
},
{
// ES#sec-evaldeclarationinstantiation 8.a.iv.1.b:
// If fnDefinable is false, throw a TypeError exception.
scripts: [
'eval("function NaN() {}");',
],
expectedError: "TypeError",
},
{
// ES#sec-evaldeclarationinstantiation 8.a.iv.1.b:
// If fnDefinable is false, throw a TypeError exception.
scripts: [
`
let a;
try {
eval("function a() {}");
} catch (e) {}
eval("function NaN() {}");
`,
],
expectedError: "TypeError",
},
{
// ES#sec-evaldeclarationinstantiation 8.a.iv.1.b:
// If fnDefinable is false, throw a TypeError exception.
scripts: [
`
eval("
function f() {
function b() {
(0, eval)('function NaN() {}');
}
b();
}
f();
");
`.replace(/"/g, '`'),
],
expectedError: "TypeError",
},
];
tests.forEach(function(test) {
doTest(test.scripts, test.expectedError);
});
......@@ -263,6 +263,11 @@
'language/eval-code/indirect/non-definable-function-with-function': [FAIL],
'language/eval-code/indirect/non-definable-function-with-variable': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=4955
'language/eval-code/direct/var-env-global-lex-non-strict': [FAIL],
'language/eval-code/direct/var-env-lower-lex-non-strict': [FAIL],
'language/eval-code/indirect/var-env-global-lex-non-strict': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=4124
'built-ins/Simd/*': [SKIP],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment