Improve error message when using await
in DebugEvaluate
When evaluating a top-level expression while paused on a breakpoint, we don't support an await expression as top-level statement. In these cases, the error was not informative and could be improved. To do so, we now propagate the information from DebugEvaluate to ParseInfo and use the parse_info in parser-base to throw a more informative error while parsing. R=jarin@chromium.org Fixed: chromium:1132245 Change-Id: I200c5af7391258256d1d86a09cbcae326327a0d9 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3247037 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Reviewed-by: Simon Zünd <szuend@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Reviewed-by: Jaroslav Sevcik <jarin@chromium.org> Commit-Queue: Tim van der Lippe <tvanderlippe@chromium.org> Cr-Commit-Position: refs/heads/main@{#77587}
This commit is contained in:
parent
c2cdcee03f
commit
52b4aae2d9
@ -2156,7 +2156,8 @@ MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
|
||||
Handle<String> source, Handle<SharedFunctionInfo> outer_info,
|
||||
Handle<Context> context, LanguageMode language_mode,
|
||||
ParseRestriction restriction, int parameters_end_pos,
|
||||
int eval_scope_position, int eval_position) {
|
||||
int eval_scope_position, int eval_position,
|
||||
ParsingWhileDebugging parsing_while_debugging) {
|
||||
Isolate* isolate = context->GetIsolate();
|
||||
int source_length = source->length();
|
||||
isolate->counters()->total_eval_size()->Increment(source_length);
|
||||
@ -2199,6 +2200,7 @@ MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
|
||||
isolate, true, language_mode, REPLMode::kNo, ScriptType::kClassic,
|
||||
FLAG_lazy_eval);
|
||||
flags.set_is_eval(true);
|
||||
flags.set_parsing_while_debugging(parsing_while_debugging);
|
||||
DCHECK(!flags.is_module());
|
||||
flags.set_parse_restriction(restriction);
|
||||
|
||||
|
@ -131,7 +131,9 @@ class V8_EXPORT_PRIVATE Compiler : public AllStatic {
|
||||
Handle<String> source, Handle<SharedFunctionInfo> outer_info,
|
||||
Handle<Context> context, LanguageMode language_mode,
|
||||
ParseRestriction restriction, int parameters_end_pos,
|
||||
int eval_scope_position, int eval_position);
|
||||
int eval_scope_position, int eval_position,
|
||||
ParsingWhileDebugging parsing_while_debugging =
|
||||
ParsingWhileDebugging::kNo);
|
||||
|
||||
// Create a function that results from wrapping |source| in a function,
|
||||
// with |arguments| being a list of parameters for that function.
|
||||
|
@ -921,6 +921,12 @@ inline REPLMode construct_repl_mode(bool is_repl_mode) {
|
||||
return is_repl_mode ? REPLMode::kYes : REPLMode::kNo;
|
||||
}
|
||||
|
||||
// Indicates whether a script is parsed during debugging.
|
||||
enum class ParsingWhileDebugging {
|
||||
kYes,
|
||||
kNo,
|
||||
};
|
||||
|
||||
// Flag indicating whether code is built into the VM (one of the natives files).
|
||||
enum NativesFlag { NOT_NATIVES_CODE, EXTENSION_CODE, INSPECTOR_CODE };
|
||||
|
||||
|
@ -38,6 +38,9 @@ namespace internal {
|
||||
"await is only valid in async functions and the top level bodies of " \
|
||||
"modules") \
|
||||
T(AwaitNotInAsyncFunction, "await is only valid in async function") \
|
||||
T(AwaitNotInDebugEvaluate, \
|
||||
"await can not be used when evaluating code " \
|
||||
"while paused in the debugger") \
|
||||
T(AtomicsWaitNotAllowed, "Atomics.wait cannot be called in this context") \
|
||||
T(BadSortComparisonFunction, \
|
||||
"The comparison function must be either a function or undefined") \
|
||||
|
@ -183,10 +183,10 @@ MaybeHandle<Object> DebugEvaluate::Evaluate(
|
||||
Handle<JSFunction> eval_fun;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, eval_fun,
|
||||
Compiler::GetFunctionFromEval(source, outer_info, context,
|
||||
LanguageMode::kSloppy, NO_PARSE_RESTRICTION,
|
||||
kNoSourcePosition, kNoSourcePosition,
|
||||
kNoSourcePosition),
|
||||
Compiler::GetFunctionFromEval(
|
||||
source, outer_info, context, LanguageMode::kSloppy,
|
||||
NO_PARSE_RESTRICTION, kNoSourcePosition, kNoSourcePosition,
|
||||
kNoSourcePosition, ParsingWhileDebugging::kYes),
|
||||
Object);
|
||||
|
||||
Handle<Object> result;
|
||||
|
@ -26,7 +26,8 @@ UnoptimizedCompileFlags::UnoptimizedCompileFlags(Isolate* isolate,
|
||||
: flags_(0),
|
||||
script_id_(script_id),
|
||||
function_kind_(FunctionKind::kNormalFunction),
|
||||
function_syntax_kind_(FunctionSyntaxKind::kDeclaration) {
|
||||
function_syntax_kind_(FunctionSyntaxKind::kDeclaration),
|
||||
parsing_while_debugging_(ParsingWhileDebugging::kNo) {
|
||||
set_collect_type_profile(isolate->is_collecting_type_profile());
|
||||
set_coverage_enabled(!isolate->is_best_effort_code_coverage());
|
||||
set_block_coverage_enabled(isolate->is_block_code_coverage());
|
||||
|
@ -119,6 +119,15 @@ class V8_EXPORT_PRIVATE UnoptimizedCompileFlags {
|
||||
return *this;
|
||||
}
|
||||
|
||||
ParsingWhileDebugging parsing_while_debugging() const {
|
||||
return parsing_while_debugging_;
|
||||
}
|
||||
UnoptimizedCompileFlags& set_parsing_while_debugging(
|
||||
ParsingWhileDebugging value) {
|
||||
parsing_while_debugging_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
struct BitFields {
|
||||
DEFINE_BIT_FIELDS(FLAG_FIELDS)
|
||||
@ -141,6 +150,7 @@ class V8_EXPORT_PRIVATE UnoptimizedCompileFlags {
|
||||
int script_id_;
|
||||
FunctionKind function_kind_;
|
||||
FunctionSyntaxKind function_syntax_kind_;
|
||||
ParsingWhileDebugging parsing_while_debugging_;
|
||||
};
|
||||
|
||||
#undef FLAG_FIELDS
|
||||
|
@ -920,10 +920,16 @@ class ParserBase {
|
||||
}
|
||||
|
||||
if (scanner()->current_token() == Token::AWAIT && !is_async_function()) {
|
||||
ReportMessageAt(scanner()->location(),
|
||||
flags().allow_harmony_top_level_await()
|
||||
? MessageTemplate::kAwaitNotInAsyncContext
|
||||
: MessageTemplate::kAwaitNotInAsyncFunction);
|
||||
if (flags().parsing_while_debugging() == ParsingWhileDebugging::kYes) {
|
||||
ReportMessageAt(scanner()->location(),
|
||||
MessageTemplate::kAwaitNotInDebugEvaluate);
|
||||
} else if (flags().allow_harmony_top_level_await()) {
|
||||
ReportMessageAt(scanner()->location(),
|
||||
MessageTemplate::kAwaitNotInAsyncContext);
|
||||
} else {
|
||||
ReportMessageAt(scanner()->location(),
|
||||
MessageTemplate::kAwaitNotInAsyncFunction);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ bytecodes: [
|
||||
B(Mov), R(this), R(0),
|
||||
B(Mov), R(context), R(2),
|
||||
/* 48 E> */ B(CallRuntime), U16(Runtime::kAddPrivateBrand), R(0), U8(3),
|
||||
/* 53 S> */ B(Wide), B(LdaSmi), I16(284),
|
||||
/* 53 S> */ B(Wide), B(LdaSmi), I16(285),
|
||||
B(Star3),
|
||||
B(LdaConstant), U8(0),
|
||||
B(Star4),
|
||||
@ -114,7 +114,7 @@ bytecodes: [
|
||||
B(Mov), R(this), R(0),
|
||||
B(Mov), R(context), R(2),
|
||||
/* 41 E> */ B(CallRuntime), U16(Runtime::kAddPrivateBrand), R(0), U8(3),
|
||||
/* 46 S> */ B(Wide), B(LdaSmi), I16(283),
|
||||
/* 46 S> */ B(Wide), B(LdaSmi), I16(284),
|
||||
B(Star3),
|
||||
B(LdaConstant), U8(0),
|
||||
B(Star4),
|
||||
@ -145,7 +145,7 @@ bytecodes: [
|
||||
B(Mov), R(this), R(0),
|
||||
B(Mov), R(context), R(2),
|
||||
/* 48 E> */ B(CallRuntime), U16(Runtime::kAddPrivateBrand), R(0), U8(3),
|
||||
/* 53 S> */ B(Wide), B(LdaSmi), I16(284),
|
||||
/* 53 S> */ B(Wide), B(LdaSmi), I16(285),
|
||||
B(Star3),
|
||||
B(LdaConstant), U8(0),
|
||||
B(Star4),
|
||||
@ -176,7 +176,7 @@ bytecodes: [
|
||||
B(Mov), R(this), R(0),
|
||||
B(Mov), R(context), R(2),
|
||||
/* 41 E> */ B(CallRuntime), U16(Runtime::kAddPrivateBrand), R(0), U8(3),
|
||||
/* 46 S> */ B(Wide), B(LdaSmi), I16(283),
|
||||
/* 46 S> */ B(Wide), B(LdaSmi), I16(284),
|
||||
B(Star4),
|
||||
B(LdaConstant), U8(0),
|
||||
B(Star5),
|
||||
|
@ -56,7 +56,7 @@ bytecodes: [
|
||||
B(Mov), R(this), R(0),
|
||||
B(Mov), R(context), R(2),
|
||||
/* 44 E> */ B(CallRuntime), U16(Runtime::kAddPrivateBrand), R(0), U8(3),
|
||||
/* 49 S> */ B(Wide), B(LdaSmi), I16(282),
|
||||
/* 49 S> */ B(Wide), B(LdaSmi), I16(283),
|
||||
B(Star3),
|
||||
B(LdaConstant), U8(0),
|
||||
B(Star4),
|
||||
@ -88,7 +88,7 @@ bytecodes: [
|
||||
B(Mov), R(this), R(0),
|
||||
B(Mov), R(context), R(2),
|
||||
/* 44 E> */ B(CallRuntime), U16(Runtime::kAddPrivateBrand), R(0), U8(3),
|
||||
/* 49 S> */ B(Wide), B(LdaSmi), I16(282),
|
||||
/* 49 S> */ B(Wide), B(LdaSmi), I16(283),
|
||||
B(Star3),
|
||||
B(LdaConstant), U8(0),
|
||||
B(Star4),
|
||||
|
@ -24,7 +24,7 @@ bytecodes: [
|
||||
B(TestReferenceEqual), R(this),
|
||||
B(Mov), R(this), R(1),
|
||||
B(JumpIfTrue), U8(16),
|
||||
B(Wide), B(LdaSmi), I16(280),
|
||||
B(Wide), B(LdaSmi), I16(281),
|
||||
B(Star2),
|
||||
B(LdaConstant), U8(0),
|
||||
B(Star3),
|
||||
@ -55,7 +55,7 @@ frame size: 2
|
||||
parameter count: 1
|
||||
bytecode array length: 14
|
||||
bytecodes: [
|
||||
/* 56 S> */ B(Wide), B(LdaSmi), I16(282),
|
||||
/* 56 S> */ B(Wide), B(LdaSmi), I16(283),
|
||||
B(Star0),
|
||||
B(LdaConstant), U8(0),
|
||||
B(Star1),
|
||||
@ -82,7 +82,7 @@ frame size: 2
|
||||
parameter count: 1
|
||||
bytecode array length: 14
|
||||
bytecodes: [
|
||||
/* 56 S> */ B(Wide), B(LdaSmi), I16(282),
|
||||
/* 56 S> */ B(Wide), B(LdaSmi), I16(283),
|
||||
B(Star0),
|
||||
B(LdaConstant), U8(0),
|
||||
B(Star1),
|
||||
@ -121,7 +121,7 @@ bytecodes: [
|
||||
B(TestReferenceEqual), R(this),
|
||||
B(Mov), R(this), R(0),
|
||||
B(JumpIfTrue), U8(16),
|
||||
B(Wide), B(LdaSmi), I16(280),
|
||||
B(Wide), B(LdaSmi), I16(281),
|
||||
B(Star2),
|
||||
B(LdaConstant), U8(0),
|
||||
B(Star3),
|
||||
@ -143,7 +143,7 @@ bytecodes: [
|
||||
B(TestReferenceEqual), R(this),
|
||||
B(Mov), R(this), R(1),
|
||||
B(JumpIfTrue), U8(16),
|
||||
B(Wide), B(LdaSmi), I16(281),
|
||||
B(Wide), B(LdaSmi), I16(282),
|
||||
B(Star3),
|
||||
B(LdaConstant), U8(0),
|
||||
B(Star4),
|
||||
@ -158,7 +158,7 @@ bytecodes: [
|
||||
B(TestReferenceEqual), R(this),
|
||||
B(Mov), R(this), R(0),
|
||||
B(JumpIfTrue), U8(16),
|
||||
B(Wide), B(LdaSmi), I16(280),
|
||||
B(Wide), B(LdaSmi), I16(281),
|
||||
B(Star2),
|
||||
B(LdaConstant), U8(0),
|
||||
B(Star3),
|
||||
@ -188,7 +188,7 @@ frame size: 2
|
||||
parameter count: 1
|
||||
bytecode array length: 14
|
||||
bytecodes: [
|
||||
/* 60 S> */ B(Wide), B(LdaSmi), I16(284),
|
||||
/* 60 S> */ B(Wide), B(LdaSmi), I16(285),
|
||||
B(Star0),
|
||||
B(LdaConstant), U8(0),
|
||||
B(Star1),
|
||||
@ -214,7 +214,7 @@ frame size: 2
|
||||
parameter count: 1
|
||||
bytecode array length: 14
|
||||
bytecodes: [
|
||||
/* 53 S> */ B(Wide), B(LdaSmi), I16(283),
|
||||
/* 53 S> */ B(Wide), B(LdaSmi), I16(284),
|
||||
B(Star0),
|
||||
B(LdaConstant), U8(0),
|
||||
B(Star1),
|
||||
@ -240,7 +240,7 @@ frame size: 2
|
||||
parameter count: 1
|
||||
bytecode array length: 14
|
||||
bytecodes: [
|
||||
/* 60 S> */ B(Wide), B(LdaSmi), I16(284),
|
||||
/* 60 S> */ B(Wide), B(LdaSmi), I16(285),
|
||||
B(Star0),
|
||||
B(LdaConstant), U8(0),
|
||||
B(Star1),
|
||||
@ -266,7 +266,7 @@ frame size: 3
|
||||
parameter count: 1
|
||||
bytecode array length: 14
|
||||
bytecodes: [
|
||||
/* 46 S> */ B(Wide), B(LdaSmi), I16(283),
|
||||
/* 46 S> */ B(Wide), B(LdaSmi), I16(284),
|
||||
B(Star1),
|
||||
B(LdaConstant), U8(0),
|
||||
B(Star2),
|
||||
|
@ -0,0 +1,37 @@
|
||||
Test evaluating await expression on a breakpoint
|
||||
|
||||
Running test: testScopesPaused
|
||||
Evaluating await expression
|
||||
{
|
||||
exceptionDetails : {
|
||||
columnNumber : 0
|
||||
exception : {
|
||||
className : SyntaxError
|
||||
description : SyntaxError: await can not be used when evaluating code while paused in the debugger at run (<anonymous>:3:3) at <anonymous>:1:1
|
||||
objectId : 1.1.7
|
||||
subtype : error
|
||||
type : object
|
||||
}
|
||||
exceptionId : 1
|
||||
lineNumber : 0
|
||||
scriptId : 5
|
||||
text : Uncaught
|
||||
}
|
||||
result : {
|
||||
className : SyntaxError
|
||||
description : SyntaxError: await can not be used when evaluating code while paused in the debugger at run (<anonymous>:3:3) at <anonymous>:1:1
|
||||
objectId : 1.1.6
|
||||
subtype : error
|
||||
type : object
|
||||
}
|
||||
}
|
||||
Evaluating await expression in async function
|
||||
{
|
||||
result : {
|
||||
className : Promise
|
||||
description : Promise
|
||||
objectId : 1.1.8
|
||||
subtype : promise
|
||||
type : object
|
||||
}
|
||||
}
|
39
test/inspector/debugger/evaluate-with-await-on-breakpoint.js
Normal file
39
test/inspector/debugger/evaluate-with-await-on-breakpoint.js
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
let {session, contextGroup, Protocol} =
|
||||
InspectorTest.start('Test evaluating await expression on a breakpoint');
|
||||
|
||||
contextGroup.addScript(`
|
||||
async function run() {
|
||||
debugger;
|
||||
}`);
|
||||
|
||||
InspectorTest.runAsyncTestSuite([async function testScopesPaused() {
|
||||
Protocol.Debugger.enable();
|
||||
Protocol.Runtime.evaluate({expression: 'run()'});
|
||||
|
||||
let {params: {callFrames}} =
|
||||
await Protocol.Debugger.oncePaused(); // inside a.fn()
|
||||
|
||||
({result} = await Protocol.Debugger.evaluateOnCallFrame({
|
||||
expression: 'await Promise.resolve(0)',
|
||||
callFrameId: callFrames[0].callFrameId
|
||||
}));
|
||||
|
||||
InspectorTest.log('Evaluating await expression');
|
||||
InspectorTest.logObject(result);
|
||||
|
||||
({result} = await Protocol.Debugger.evaluateOnCallFrame({
|
||||
expression:
|
||||
'async function nested() { await fetch(\'http://google.com\'); } nested()',
|
||||
callFrameId: callFrames[0].callFrameId
|
||||
}));
|
||||
|
||||
InspectorTest.log('Evaluating await expression in async function');
|
||||
InspectorTest.logObject(result);
|
||||
|
||||
Protocol.Debugger.resume();
|
||||
Protocol.Debugger.disable();
|
||||
}]);
|
Loading…
Reference in New Issue
Block a user