Commit 2f66cb22 authored by Suraj Sharma's avatar Suraj Sharma Committed by Commit Bot

[inspector] Improve uninitialized binding error message

The program:

    foo;
    let foo = 5;

…now produces:

    ReferenceError: Cannot access 'foo' before initialization

…instead of:

    ReferenceError: foo is not defined

Bug: v8:6513, v8:6951
Change-Id: I6c372626734570d5abeb1d0196b814dde02b9e3e
Reviewed-on: https://chromium-review.googlesource.com/c/1441151Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarSathya Gunasekaran <gsathya@chromium.org>
Reviewed-by: 's avatarMathias Bynens <mathias@chromium.org>
Commit-Queue: Suraj Sharma <surshar@microsoft.com>
Commit-Queue: Mathias Bynens <mathias@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59307}
parent 4e07bfb0
......@@ -2168,7 +2168,7 @@ void BytecodeGraphBuilder::BuildHoleCheckAndThrow(
bytecode_iterator().current_offset()));
Node* node;
const Operator* op = javascript()->CallRuntime(runtime_id);
if (runtime_id == Runtime::kThrowReferenceError) {
if (runtime_id == Runtime::kThrowAccessedUninitializedVariable) {
DCHECK_NOT_NULL(name);
node = NewNode(op, name);
} else {
......@@ -2190,7 +2190,8 @@ void BytecodeGraphBuilder::VisitThrowReferenceErrorIfHole() {
jsgraph()->TheHoleConstant());
Node* name = jsgraph()->Constant(
handle(bytecode_iterator().GetConstantForIndexOperand(0), isolate()));
BuildHoleCheckAndThrow(check_for_hole, Runtime::kThrowReferenceError, name);
BuildHoleCheckAndThrow(check_for_hole,
Runtime::kThrowAccessedUninitializedVariable, name);
}
void BytecodeGraphBuilder::VisitThrowSuperNotCalledIfHole() {
......
......@@ -2958,7 +2958,8 @@ IGNITION_HANDLER(ThrowReferenceErrorIfHole, InterpreterAssembler) {
BIND(&throw_error);
{
Node* name = LoadConstantPoolEntryAtOperandIndex(0);
CallRuntime(Runtime::kThrowReferenceError, GetContext(), name);
CallRuntime(Runtime::kThrowAccessedUninitializedVariable, GetContext(),
name);
// We shouldn't ever return from a throw.
Abort(AbortReason::kUnexpectedReturnFromThrow);
Unreachable();
......
......@@ -292,6 +292,7 @@ namespace internal {
/* ReferenceError */ \
T(NotDefined, "% is not defined") \
T(SuperAlreadyCalled, "Super constructor may only be called once") \
T(AccessedUninitializedVariable, "Cannot access '%' before initialization") \
T(UnsupportedSuper, "Unsupported reference to 'super'") \
/* RangeError */ \
T(BigIntDivZero, "Division by zero") \
......
......@@ -157,6 +157,15 @@ RUNTIME_FUNCTION(Runtime_ThrowReferenceError) {
isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
}
RUNTIME_FUNCTION(Runtime_ThrowAccessedUninitializedVariable) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
THROW_NEW_ERROR_RETURN_FAILURE(
isolate,
NewReferenceError(MessageTemplate::kAccessedUninitializedVariable, name));
}
RUNTIME_FUNCTION(Runtime_NewTypeError) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
......
......@@ -124,6 +124,7 @@ bool Runtime::NeedsExactContext(FunctionId id) {
case Runtime::kThrowNotConstructor:
case Runtime::kThrowRangeError:
case Runtime::kThrowReferenceError:
case Runtime::kThrowAccessedUninitializedVariable:
case Runtime::kThrowStackOverflow:
case Runtime::kThrowStaticPrototypeError:
case Runtime::kThrowSuperAlreadyCalledError:
......@@ -163,6 +164,7 @@ bool Runtime::IsNonReturning(FunctionId id) {
case Runtime::kThrowNotConstructor:
case Runtime::kThrowRangeError:
case Runtime::kThrowReferenceError:
case Runtime::kThrowAccessedUninitializedVariable:
case Runtime::kThrowStackOverflow:
case Runtime::kThrowSymbolAsyncIteratorInvalid:
case Runtime::kThrowTypeError:
......
......@@ -242,6 +242,7 @@ namespace internal {
F(ThrowPatternAssignmentNonCoercible, 0, 1) \
F(ThrowRangeError, -1 /* >= 1 */, 1) \
F(ThrowReferenceError, 1, 1) \
F(ThrowAccessedUninitializedVariable, 1, 1) \
F(ThrowStackOverflow, 0, 1) \
F(ThrowSymbolAsyncIteratorInvalid, 0, 1) \
F(ThrowSymbolIteratorInvalid, 0, 1) \
......
......@@ -2891,7 +2891,7 @@ TEST(BytecodeGraphBuilderIllegalConstDeclaration) {
ExpectedSnippet<0, const char*> illegal_const_decl[] = {
{"const x = x = 10 + 3; return x;",
{"Uncaught ReferenceError: x is not defined"}},
{"Uncaught ReferenceError: Cannot access 'x' before initialization"}},
{"const x = 10; x = 20; return x;",
{"Uncaught TypeError: Assignment to constant variable."}},
{"const x = 10; { x = 20; } return x;",
......@@ -2899,7 +2899,7 @@ TEST(BytecodeGraphBuilderIllegalConstDeclaration) {
{"const x = 10; eval('x = 20;'); return x;",
{"Uncaught TypeError: Assignment to constant variable."}},
{"let x = x + 10; return x;",
{"Uncaught ReferenceError: x is not defined"}},
{"Uncaught ReferenceError: Cannot access 'x' before initialization"}},
{"'use strict'; (function f1() { f1 = 123; })() ",
{"Uncaught TypeError: Assignment to constant variable."}},
};
......
......@@ -4944,7 +4944,7 @@ TEST(InterpreterIllegalConstDeclaration) {
std::pair<const char*, const char*> const_decl[] = {
{"const x = x = 10 + 3; return x;",
"Uncaught ReferenceError: x is not defined"},
"Uncaught ReferenceError: Cannot access 'x' before initialization"},
{"const x = 10; x = 20; return x;",
"Uncaught TypeError: Assignment to constant variable."},
{"const x = 10; { x = 20; } return x;",
......@@ -4952,7 +4952,7 @@ TEST(InterpreterIllegalConstDeclaration) {
{"const x = 10; eval('x = 20;'); return x;",
"Uncaught TypeError: Assignment to constant variable."},
{"let x = x + 10; return x;",
"Uncaught ReferenceError: x is not defined"},
"Uncaught ReferenceError: Cannot access 'x' before initialization"},
{"'use strict'; (function f1() { f1 = 123; })() ",
"Uncaught TypeError: Assignment to constant variable."},
};
......
*%(basename)s:7: ReferenceError: a is not defined
*%(basename)s:7: ReferenceError: Cannot access 'a' before initialization
((a=-a) => { })();
^
ReferenceError: a is not defined
ReferenceError: Cannot access 'a' before initialization
at *%(basename)s:7:6
at *%(basename)s:7:16
*%(basename)s:7: ReferenceError: a is not defined
*%(basename)s:7: ReferenceError: Cannot access 'a' before initialization
(function(a=+a) { })();
^
ReferenceError: a is not defined
ReferenceError: Cannot access 'a' before initialization
at *%(basename)s:7:14
at *%(basename)s:7:21
......@@ -108,8 +108,8 @@ PASS 'use strict'; var VarA = class A { constructor() {} }; var VarB = class B e
Class statement binding in other circumstances
PASS var result = A; result threw exception ReferenceError: A is not defined.
PASS 'use strict'; var result = A; result threw exception ReferenceError: A is not defined.
PASS var result = A; class A {}; result threw exception ReferenceError: A is not defined.
PASS 'use strict'; var result = A; class A {}; result threw exception ReferenceError: A is not defined.
PASS var result = A; class A {}; result threw exception ReferenceError: Cannot access 'A' before initialization.
PASS 'use strict'; var result = A; class A {}; result threw exception ReferenceError: Cannot access 'A' before initialization.
PASS class A { constructor() { A = 1; } }; new A threw exception TypeError: Assignment to constant variable..
PASS 'use strict'; class A { constructor() { A = 1; } }; new A threw exception TypeError: Assignment to constant variable..
PASS class A { constructor() { } }; A = 1; A is 1
......
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