Commit f5592da6 authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[parser] Track labels in the parser-base rather than parser+ast

Bug: v8:8088
Change-Id: Ie92499a43e2286e9bb1c64b0d553a515d74d5aa2
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2059989Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Reviewed-by: 's avatarSimon Zünd <szuend@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66313}
parent b9e40f7c
......@@ -1103,20 +1103,5 @@ const char* CallRuntime::debug_name() {
#endif // DEBUG
}
#define RETURN_LABELS(NodeType) \
case k##NodeType: \
return static_cast<const NodeType*>(this)->labels();
ZonePtrList<const AstRawString>* BreakableStatement::labels() const {
switch (node_type()) {
BREAKABLE_NODE_LIST(RETURN_LABELS)
ITERATION_NODE_LIST(RETURN_LABELS)
default:
UNREACHABLE();
}
}
#undef RETURN_LABELS
} // namespace internal
} // namespace v8
This diff is collapsed.
......@@ -659,15 +659,6 @@ void AstPrinter::Print(const char* format, ...) {
}
}
void AstPrinter::PrintLabels(ZonePtrList<const AstRawString>* labels) {
if (labels != nullptr) {
for (int i = 0; i < labels->length(); i++) {
PrintLiteral(labels->at(i), false);
Print(": ");
}
}
}
void AstPrinter::PrintLiteral(Literal* literal, bool quote) {
switch (literal->type()) {
case Literal::kString:
......@@ -819,16 +810,6 @@ void AstPrinter::PrintLiteralWithModeIndented(const char* info, Variable* var,
}
}
void AstPrinter::PrintLabelsIndented(ZonePtrList<const AstRawString>* labels,
const char* prefix) {
if (labels == nullptr || labels->length() == 0) return;
PrintIndented(prefix);
Print("LABELS ");
PrintLabels(labels);
Print("\n");
}
void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) {
if (node != nullptr) {
IndentedScope indent(this, s, node->position());
......@@ -902,7 +883,6 @@ void AstPrinter::VisitBlock(Block* node) {
const char* block_txt =
node->ignore_completion_value() ? "BLOCK NOCOMPLETIONS" : "BLOCK";
IndentedScope indent(this, block_txt, node->position());
PrintLabelsIndented(node->labels());
PrintStatements(node->statements());
}
......@@ -953,13 +933,11 @@ void AstPrinter::VisitIfStatement(IfStatement* node) {
void AstPrinter::VisitContinueStatement(ContinueStatement* node) {
IndentedScope indent(this, "CONTINUE", node->position());
PrintLabelsIndented(node->target()->labels());
}
void AstPrinter::VisitBreakStatement(BreakStatement* node) {
IndentedScope indent(this, "BREAK", node->position());
PrintLabelsIndented(node->target()->labels());
}
......@@ -978,7 +956,6 @@ void AstPrinter::VisitWithStatement(WithStatement* node) {
void AstPrinter::VisitSwitchStatement(SwitchStatement* node) {
IndentedScope indent(this, "SWITCH", node->position());
PrintLabelsIndented(node->labels());
PrintIndentedVisit("TAG", node->tag());
for (CaseClause* clause : *node->cases()) {
if (clause->is_default()) {
......@@ -995,8 +972,6 @@ void AstPrinter::VisitSwitchStatement(SwitchStatement* node) {
void AstPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
IndentedScope indent(this, "DO", node->position());
PrintLabelsIndented(node->labels());
PrintLabelsIndented(node->own_labels(), "OWN ");
PrintIndentedVisit("BODY", node->body());
PrintIndentedVisit("COND", node->cond());
}
......@@ -1004,8 +979,6 @@ void AstPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
void AstPrinter::VisitWhileStatement(WhileStatement* node) {
IndentedScope indent(this, "WHILE", node->position());
PrintLabelsIndented(node->labels());
PrintLabelsIndented(node->own_labels(), "OWN ");
PrintIndentedVisit("COND", node->cond());
PrintIndentedVisit("BODY", node->body());
}
......@@ -1013,8 +986,6 @@ void AstPrinter::VisitWhileStatement(WhileStatement* node) {
void AstPrinter::VisitForStatement(ForStatement* node) {
IndentedScope indent(this, "FOR", node->position());
PrintLabelsIndented(node->labels());
PrintLabelsIndented(node->own_labels(), "OWN ");
if (node->init()) PrintIndentedVisit("INIT", node->init());
if (node->cond()) PrintIndentedVisit("COND", node->cond());
PrintIndentedVisit("BODY", node->body());
......@@ -1024,8 +995,6 @@ void AstPrinter::VisitForStatement(ForStatement* node) {
void AstPrinter::VisitForInStatement(ForInStatement* node) {
IndentedScope indent(this, "FOR IN", node->position());
PrintLabelsIndented(node->labels());
PrintLabelsIndented(node->own_labels(), "OWN ");
PrintIndentedVisit("FOR", node->each());
PrintIndentedVisit("IN", node->subject());
PrintIndentedVisit("BODY", node->body());
......@@ -1034,8 +1003,6 @@ void AstPrinter::VisitForInStatement(ForInStatement* node) {
void AstPrinter::VisitForOfStatement(ForOfStatement* node) {
IndentedScope indent(this, "FOR OF", node->position());
PrintLabelsIndented(node->labels());
PrintLabelsIndented(node->own_labels(), "OWN ");
const char* for_type;
switch (node->type()) {
case IteratorType::kNormal:
......
This diff is collapsed.
......@@ -427,7 +427,6 @@ Parser::Parser(ParseInfo* info)
reusable_preparser_(nullptr),
mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly.
source_range_map_(info->source_range_map()),
target_stack_(nullptr),
total_preparse_skipped_(0),
consumed_preparse_data_(info->consumed_preparse_data()),
preparse_data_buffer_(),
......@@ -566,7 +565,6 @@ FunctionLiteral* Parser::DoParseProgram(Isolate* isolate, ParseInfo* info) {
// isolate will be nullptr.
DCHECK_EQ(parsing_on_main_thread_, isolate != nullptr);
DCHECK_NULL(scope_);
DCHECK_NULL(target_stack_);
ParsingModeScope mode(this, allow_lazy_ ? PARSE_LAZILY : PARSE_EAGERLY);
ResetFunctionLiteralId();
......@@ -681,9 +679,6 @@ FunctionLiteral* Parser::DoParseProgram(Isolate* isolate, ParseInfo* info) {
info->set_max_function_literal_id(GetLastFunctionLiteralId());
// Make sure the target stack is empty.
DCHECK_NULL(target_stack_);
if (has_error()) return nullptr;
RecordFunctionLiteralSourceRange(result);
......@@ -848,7 +843,6 @@ FunctionLiteral* Parser::DoParseFunction(Isolate* isolate, ParseInfo* info,
DCHECK_EQ(parsing_on_main_thread_, isolate != nullptr);
DCHECK_NOT_NULL(raw_name);
DCHECK_NULL(scope_);
DCHECK_NULL(target_stack_);
DCHECK(ast_value_factory());
fni_.PushEnclosingName(raw_name);
......@@ -972,8 +966,6 @@ FunctionLiteral* Parser::DoParseFunction(Isolate* isolate, ParseInfo* info,
}
}
// Make sure the target stack is empty.
DCHECK_NULL(target_stack_);
DCHECK_IMPLIES(result,
info->function_literal_id() == result->function_literal_id());
return result;
......@@ -1601,43 +1593,6 @@ Statement* Parser::DeclareNative(const AstRawString* name, int pos) {
pos);
}
void Parser::DeclareLabel(ZonePtrList<const AstRawString>** labels,
ZonePtrList<const AstRawString>** own_labels,
const AstRawString* label) {
// TODO(1240780): We don't check for redeclaration of labels during preparsing
// since keeping track of the set of active labels requires nontrivial changes
// to the way scopes are structured. However, these are probably changes we
// want to make later anyway so we should go back and fix this then.
if (ContainsLabel(*labels, label) || TargetStackContainsLabel(label)) {
ReportMessage(MessageTemplate::kLabelRedeclaration, label);
return;
}
// Add {label} to both {labels} and {own_labels}.
if (*labels == nullptr) {
DCHECK_NULL(*own_labels);
*labels = new (zone()) ZonePtrList<const AstRawString>(1, zone());
*own_labels = new (zone()) ZonePtrList<const AstRawString>(1, zone());
} else {
if (*own_labels == nullptr) {
*own_labels = new (zone()) ZonePtrList<const AstRawString>(1, zone());
}
}
(*labels)->Add(label, zone());
(*own_labels)->Add(label, zone());
}
bool Parser::ContainsLabel(ZonePtrList<const AstRawString>* labels,
const AstRawString* label) {
DCHECK_NOT_NULL(label);
if (labels != nullptr) {
for (int i = labels->length(); i-- > 0;) {
if (labels->at(i) == label) return true;
}
}
return false;
}
Block* Parser::IgnoreCompletion(Statement* statement) {
Block* block = factory()->NewBlock(1, true);
block->statements()->Add(statement, zone());
......@@ -2073,8 +2028,7 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
// explicit break target, instead handing it directly to those nodes that
// need to know about it. This should be safe because we don't run any code
// in this function that looks up break targets.
ForStatement* outer_loop =
factory()->NewForStatement(nullptr, nullptr, kNoSourcePosition);
ForStatement* outer_loop = factory()->NewForStatement(kNoSourcePosition);
outer_block->statements()->Add(outer_loop, zone());
outer_block->set_scope(scope());
......@@ -3065,40 +3019,6 @@ void Parser::InsertSloppyBlockFunctionVarBindings(DeclarationScope* scope) {
// ----------------------------------------------------------------------------
// Parser support
bool Parser::TargetStackContainsLabel(const AstRawString* label) {
for (ParserTarget* t = target_stack_; t != nullptr; t = t->previous()) {
if (ContainsLabel(t->statement()->labels(), label)) return true;
}
return false;
}
BreakableStatement* Parser::LookupBreakTarget(const AstRawString* label) {
bool anonymous = label == nullptr;
for (ParserTarget* t = target_stack_; t != nullptr; t = t->previous()) {
BreakableStatement* stat = t->statement();
if ((anonymous && stat->is_target_for_anonymous()) ||
(!anonymous && ContainsLabel(stat->labels(), label))) {
return stat;
}
}
return nullptr;
}
IterationStatement* Parser::LookupContinueTarget(const AstRawString* label) {
bool anonymous = label == nullptr;
for (ParserTarget* t = target_stack_; t != nullptr; t = t->previous()) {
IterationStatement* stat = t->statement()->AsIterationStatement();
if (stat == nullptr) continue;
DCHECK(stat->is_target_for_anonymous());
if (anonymous || ContainsLabel(stat->own_labels(), label)) {
return stat;
}
if (ContainsLabel(stat->labels(), label)) break;
}
return nullptr;
}
void Parser::HandleSourceURLComments(Isolate* isolate, Handle<Script> script) {
Handle<String> source_url = scanner_.SourceUrl(isolate);
if (!source_url.is_null()) {
......
......@@ -122,8 +122,6 @@ struct ParserTypes<Parser> {
using FuncNameInferrer = v8::internal::FuncNameInferrer;
using SourceRange = v8::internal::SourceRange;
using SourceRangeScope = v8::internal::SourceRangeScope;
using Target = ParserTarget;
using TargetScope = ParserTargetScope;
};
class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
......@@ -279,11 +277,6 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
};
ZonePtrList<const NamedImport>* ParseNamedImports(int pos);
Statement* BuildInitializationBlock(DeclarationParsingResult* parsing_result);
void DeclareLabel(ZonePtrList<const AstRawString>** labels,
ZonePtrList<const AstRawString>** own_labels,
const AstRawString* label);
bool ContainsLabel(ZonePtrList<const AstRawString>* labels,
const AstRawString* label);
Expression* RewriteReturn(Expression* return_value, int pos);
Statement* RewriteSwitchStatement(SwitchStatement* switch_statement,
Scope* scope);
......@@ -407,10 +400,6 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
Scope* declaration_scope, bool* was_added, int var_begin_pos,
int var_end_pos = kNoSourcePosition);
bool TargetStackContainsLabel(const AstRawString* label);
BreakableStatement* LookupBreakTarget(const AstRawString* label);
IterationStatement* LookupContinueTarget(const AstRawString* label);
// Factory methods.
FunctionLiteral* DefaultConstructor(const AstRawString* name, bool call_super,
int pos, int end_pos);
......@@ -727,6 +716,10 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
return arg;
}
IterationStatement* AsIterationStatement(BreakableStatement* s) {
return s->AsIterationStatement();
}
void ReportUnexpectedTokenAt(
Scanner::Location location, Token::Value token,
MessageTemplate message = MessageTemplate::kUnexpectedToken);
......@@ -750,6 +743,10 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
return subject == nullptr;
}
V8_INLINE static bool IsIterationStatement(Statement* subject) {
return subject->AsIterationStatement() != nullptr;
}
// Non-null empty string.
V8_INLINE const AstRawString* EmptyIdentifierString() const {
return ast_value_factory()->empty_string();
......@@ -1047,9 +1044,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
SourceRangeMap* source_range_map_ = nullptr;
friend class ParserTarget;
friend class ParserTargetScope;
ParserTarget* target_stack_; // for break, continue statements
ScriptCompiler::CompileOptions compile_options_;
......@@ -1072,47 +1067,6 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
int parameters_end_pos_;
};
// ----------------------------------------------------------------------------
// Target is a support class to facilitate manipulation of the
// Parser's target_stack_ (the stack of potential 'break' and
// 'continue' statement targets). Upon construction, a new target is
// added; it is removed upon destruction.
class ParserTarget {
public:
ParserTarget(ParserBase<Parser>* parser, BreakableStatement* statement)
: variable_(&parser->impl()->target_stack_),
statement_(statement),
previous_(parser->impl()->target_stack_) {
parser->impl()->target_stack_ = this;
}
~ParserTarget() { *variable_ = previous_; }
ParserTarget* previous() { return previous_; }
BreakableStatement* statement() { return statement_; }
private:
ParserTarget** variable_;
BreakableStatement* statement_;
ParserTarget* previous_;
};
class ParserTargetScope {
public:
explicit ParserTargetScope(ParserBase<Parser>* parser)
: variable_(&parser->impl()->target_stack_),
previous_(parser->impl()->target_stack_) {
parser->impl()->target_stack_ = nullptr;
}
~ParserTargetScope() { *variable_ = previous_; }
private:
ParserTarget** variable_;
ParserTarget* previous_;
};
} // namespace internal
} // namespace v8
......
......@@ -416,6 +416,10 @@ class PreParserStatement {
return PreParserStatement(kUnknownStatement);
}
static PreParserStatement Iteration() {
return PreParserStatement(kIterationStatement);
}
static PreParserStatement Null() {
return PreParserStatement(kNullStatement);
}
......@@ -450,6 +454,8 @@ class PreParserStatement {
bool IsNull() { return code_ == kNullStatement; }
bool IsIterationStatement() { return code_ == kIterationStatement; }
bool IsEmptyStatement() {
DCHECK(!IsNull());
return code_ == kEmptyStatement;
......@@ -478,6 +484,7 @@ class PreParserStatement {
kEmptyStatement,
kUnknownStatement,
kJumpStatement,
kIterationStatement,
kStringLiteralExpressionStatement,
};
......@@ -691,8 +698,7 @@ class PreParserFactory {
return PreParserBlock::Default();
}
PreParserBlock NewBlock(bool ignore_completion_value,
ZonePtrList<const AstRawString>* labels) {
PreParserBlock NewBlock(bool ignore_completion_value, bool is_breakable) {
return PreParserBlock::Default();
}
......@@ -737,20 +743,15 @@ class PreParserFactory {
return PreParserStatement::Default();
}
PreParserStatement NewDoWhileStatement(
ZonePtrList<const AstRawString>* labels,
ZonePtrList<const AstRawString>* own_labels, int pos) {
return PreParserStatement::Default();
PreParserStatement NewDoWhileStatement(int pos) {
return PreParserStatement::Iteration();
}
PreParserStatement NewWhileStatement(
ZonePtrList<const AstRawString>* labels,
ZonePtrList<const AstRawString>* own_labels, int pos) {
return PreParserStatement::Default();
PreParserStatement NewWhileStatement(int pos) {
return PreParserStatement::Iteration();
}
PreParserStatement NewSwitchStatement(ZonePtrList<const AstRawString>* labels,
const PreParserExpression& tag,
PreParserStatement NewSwitchStatement(const PreParserExpression& tag,
int pos) {
return PreParserStatement::Default();
}
......@@ -761,23 +762,17 @@ class PreParserFactory {
return PreParserStatement::Default();
}
PreParserStatement NewForStatement(
ZonePtrList<const AstRawString>* labels,
ZonePtrList<const AstRawString>* own_labels, int pos) {
return PreParserStatement::Default();
PreParserStatement NewForStatement(int pos) {
return PreParserStatement::Iteration();
}
PreParserStatement NewForEachStatement(
ForEachStatement::VisitMode visit_mode,
ZonePtrList<const AstRawString>* labels,
ZonePtrList<const AstRawString>* own_labels, int pos) {
return PreParserStatement::Default();
PreParserStatement NewForEachStatement(ForEachStatement::VisitMode visit_mode,
int pos) {
return PreParserStatement::Iteration();
}
PreParserStatement NewForOfStatement(
ZonePtrList<const AstRawString>* labels,
ZonePtrList<const AstRawString>* own_labels, int pos, IteratorType type) {
return PreParserStatement::Default();
PreParserStatement NewForOfStatement(int pos, IteratorType type) {
return PreParserStatement::Iteration();
}
PreParserExpression NewCallRuntime(
......@@ -819,17 +814,6 @@ class PreParserFormalParameters : public FormalParametersBase {
bool strict_parameter_error_ = false;
};
class PreParserTarget {
public:
PreParserTarget(ParserBase<PreParser>* preparser,
PreParserStatement statement) {}
};
class PreParserTargetScope {
public:
explicit PreParserTargetScope(ParserBase<PreParser>* preparser) {}
};
class PreParserFuncNameInferrer {
public:
explicit PreParserFuncNameInferrer(AstValueFactory* avf) {}
......@@ -904,8 +888,6 @@ struct ParserTypes<PreParser> {
using FuncNameInferrer = PreParserFuncNameInferrer;
using SourceRange = PreParserSourceRange;
using SourceRangeScope = PreParserSourceRangeScope;
using Target = PreParserTarget;
using TargetScope = PreParserTargetScope;
};
......@@ -1070,18 +1052,6 @@ class PreParser : public ParserBase<PreParser> {
const PreParserScopedStatementList* body, PreParserStatement block,
const PreParserExpression& return_value) {}
V8_INLINE void DeclareLabel(ZonePtrList<const AstRawString>** labels,
ZonePtrList<const AstRawString>** own_labels,
const AstRawString* label) {
DCHECK(!parsing_module_ || !label->IsOneByteEqualTo("await"));
}
// TODO(nikolaos): The preparser currently does not keep track of labels.
V8_INLINE bool ContainsLabel(ZonePtrList<const AstRawString>* labels,
const PreParserIdentifier& label) {
return false;
}
V8_INLINE PreParserExpression
RewriteReturn(const PreParserExpression& return_value, int pos) {
return return_value;
......@@ -1186,17 +1156,6 @@ class PreParser : public ParserBase<PreParser> {
bool IdentifierEquals(const PreParserIdentifier& identifier,
const AstRawString* other);
// TODO(nikolaos): The preparser currently does not keep track of labels
// and targets.
V8_INLINE PreParserStatement
LookupBreakTarget(const PreParserIdentifier& label) {
return PreParserStatement::Default();
}
V8_INLINE PreParserStatement
LookupContinueTarget(const PreParserIdentifier& label) {
return PreParserStatement::Default();
}
V8_INLINE PreParserStatement DeclareFunction(
const PreParserIdentifier& variable_name,
const PreParserExpression& function, VariableMode mode, VariableKind kind,
......@@ -1498,7 +1457,7 @@ class PreParser : public ParserBase<PreParser> {
V8_INLINE void ReportMessageAt(Scanner::Location source_location,
MessageTemplate message,
const PreParserIdentifier& arg) {
UNREACHABLE();
ReportMessageAt(source_location, message, arg.string_);
}
void ReportMessageAt(Scanner::Location source_location,
......@@ -1512,6 +1471,8 @@ class PreParser : public ParserBase<PreParser> {
return arg.string_;
}
PreParserStatement AsIterationStatement(PreParserStatement s) { return s; }
// "null" return type creators.
V8_INLINE static PreParserIdentifier NullIdentifier() {
return PreParserIdentifier::Null();
......@@ -1538,6 +1499,10 @@ class PreParser : public ParserBase<PreParser> {
return subject.IsNull();
}
V8_INLINE static bool IsIterationStatement(PreParserStatement subject) {
return subject.IsIterationStatement();
}
V8_INLINE PreParserIdentifier EmptyIdentifierString() const {
PreParserIdentifier result = PreParserIdentifier::Default();
result.string_ = ast_value_factory()->empty_string();
......
......@@ -146,7 +146,7 @@ void Processor::VisitBlock(Block* node) {
// returns 'undefined'. To obtain the same behavior with v8, we need
// to prevent rewriting in that case.
if (!node->ignore_completion_value()) {
BreakableScope scope(this, node->labels() != nullptr);
BreakableScope scope(this, node->is_breakable());
Process(node->statements());
}
replacement_ = node;
......
......@@ -3258,25 +3258,6 @@ TEST(FuncNameInferrerEscaped) {
}
TEST(RegressionLazyFunctionWithErrorWithArg) {
// Test only applies when lazy parsing.
if (!i::FLAG_lazy) return;
// The bug occurred when a lazy function had an error which requires a
// parameter (such as "unknown label" here). The error message was processed
// before the AstValueFactory containing the error message string was
// internalized.
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
LocalContext env;
i::FLAG_lazy = true;
CompileRun("function this_is_lazy() {\n"
" break p;\n"
"}\n"
"this_is_lazy();\n");
}
TEST(SerializationOfMaybeAssignmentFlag) {
i::Isolate* isolate = CcTest::i_isolate();
i::Factory* factory = isolate->factory();
......
getPossibleBreakpoints should not crash during lazy compilation (crbug.com/715334)
{
method : Debugger.scriptParsed
params : {
endColumn : 21
endLine : 2
executionContextId : <executionContextId>
hasSourceURL : true
hash : 124cb0278e3aa9f250651d433cdefeb5618c7202
isLiveEdit : false
isModule : false
length : 52
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url : test.js
}
}
{
method : Debugger.scriptFailedToParse
params : {
endColumn : 21
endColumn : 23
endLine : 2
executionContextId : <executionContextId>
hasSourceURL : true
hash : 124cb0278e3aa9f250651d433cdefeb5618c7202
hash : 1bce5d0c4da4d13a3ea6e6f35ea0f34705c26ba4
isModule : false
length : 52
length : 56
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
......@@ -34,7 +16,6 @@ getPossibleBreakpoints should not crash during lazy compilation (crbug.com/71533
url : test.js
}
}
One script is reported twice
{
id : <messageId>
result : {
......
......@@ -3,26 +3,16 @@
// found in the LICENSE file.
let {session, contextGroup, Protocol} = InspectorTest.start('getPossibleBreakpoints should not crash during lazy compilation (crbug.com/715334)');
contextGroup.addScript(`
function test() { continue; }
//# sourceURL=test.js`);
(async function test() {
Protocol.Debugger.enable();
let script = await Protocol.Debugger.onceScriptParsed();
InspectorTest.logMessage(script);
let scriptId = script.params.scriptId;
Protocol.Debugger.onScriptFailedToParse(msg => {
InspectorTest.logMessage(msg);
if (msg.params.scriptId !== script.params.scriptId) {
InspectorTest.log('Failed script to parse event has different scriptId');
} else {
InspectorTest.log('One script is reported twice');
}
});
let response = await Protocol.Debugger.getPossibleBreakpoints({
start: {scriptId, lineNumber: 0, columnNumber: 0}});
InspectorTest.logMessage(response);
InspectorTest.completeTest();
(async function test() {
Protocol.Debugger.enable();
Protocol.Debugger.onScriptFailedToParse(async msg => {
InspectorTest.logMessage(msg);
const response = await Protocol.Debugger.getPossibleBreakpoints({
start: {scriptId: msg.params.scriptId, lineNumber: 0, columnNumber: 0}});
InspectorTest.logMessage(response);
InspectorTest.completeTest();
});
contextGroup.addScript(`
function test() { continue; }
//# sourceURL=test.js`);
})();
......@@ -7,10 +7,7 @@
function outer() {
"use asm";
function inner() {
switch (1) {
case 0:
break foo;
}
/f(/
}
}
outer();
// Copyright 2020 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.
assertThrows("function f() { break }", SyntaxError);
assertThrows("function f() { break a }", SyntaxError);
assertThrows("function f() { continue }", SyntaxError);
assertThrows("function f() { continue a }", SyntaxError);
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