[compiler] Fix double error reporting for parser errors

Remove error reporting from parsing::Parse*, since in most cases we
didn't actually want them (clear errors afterward), and there was an
issue where Compiler::Compile would try to report errors already
reported in ParseAny, which ended up triggering unreachable code.

As a drive-by, move some one-off parse exception handling in
test-parsing into a CHECKED_PARSE_PROGRAM macro which replaces all the
"necessarily positive" calls to parsing::ParseProgram.

Bug: chromium:1091656
Change-Id: I4d463ec363312aea36ab92f1322cf66a416b9888
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2237134
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68281}
This commit is contained in:
Leszek Swirski 2020-06-09 16:13:11 +02:00 committed by Commit Bot
parent 52ddf94979
commit d8c9ae5295
13 changed files with 180 additions and 101 deletions

View File

@ -1090,7 +1090,9 @@ MaybeHandle<SharedFunctionInfo> CompileToplevel(
VMState<BYTECODE_COMPILER> state(isolate);
if (parse_info->literal() == nullptr &&
!parsing::ParseProgram(parse_info, script, maybe_outer_scope_info,
isolate)) {
isolate, parsing::ReportStatisticsMode::kYes)) {
FailWithPendingException(isolate, script, parse_info,
Compiler::ClearExceptionFlag::KEEP_EXCEPTION);
return MaybeHandle<SharedFunctionInfo>();
}
// Measure how long it takes to do the compilation; only take the
@ -1456,7 +1458,7 @@ bool Compiler::CollectSourcePositions(Isolate* isolate,
// Parse and update ParseInfo with the results. Don't update parsing
// statistics since we've already parsed the code before.
if (!parsing::ParseAny(&parse_info, shared_info, isolate,
parsing::ReportErrorsAndStatisticsMode::kNo)) {
parsing::ReportStatisticsMode::kNo)) {
// Parsing failed probably as a result of stack exhaustion.
bytecode->SetSourcePositionsFailedToCollect();
return FailAndClearPendingException(isolate);
@ -1548,7 +1550,8 @@ bool Compiler::Compile(Handle<SharedFunctionInfo> shared_info,
}
// Parse and update ParseInfo with the results.
if (!parsing::ParseAny(&parse_info, shared_info, isolate)) {
if (!parsing::ParseAny(&parse_info, shared_info, isolate,
parsing::ReportStatisticsMode::kYes)) {
return FailWithPendingException(isolate, script, &parse_info, flag);
}

View File

@ -584,7 +584,12 @@ bool Shell::ExecuteString(Isolate* isolate, Local<String> source,
i::Handle<i::Script> script = parse_info.CreateScript(
i_isolate, str, i::kNullMaybeHandle, ScriptOriginOptions());
if (!i::parsing::ParseProgram(&parse_info, script, i_isolate)) {
if (!i::parsing::ParseProgram(&parse_info, script, i_isolate,
i::parsing::ReportStatisticsMode::kYes)) {
parse_info.pending_error_handler()->PrepareErrors(
i_isolate, parse_info.ast_value_factory());
parse_info.pending_error_handler()->ReportErrors(i_isolate, script);
fprintf(stderr, "Failed parsing\n");
return false;
}

View File

@ -269,8 +269,9 @@ void ScopeIterator::TryParseAndRetrieveScopes(ReparseStrategy strategy) {
const bool parse_result =
flags.is_toplevel()
? parsing::ParseProgram(info_.get(), script, maybe_outer_scope,
isolate_)
: parsing::ParseFunction(info_.get(), shared_info, isolate_);
isolate_, parsing::ReportStatisticsMode::kNo)
: parsing::ParseFunction(info_.get(), shared_info, isolate_,
parsing::ReportStatisticsMode::kNo);
if (parse_result) {
DeclarationScope* literal_scope = info_->literal()->scope();
@ -300,14 +301,13 @@ void ScopeIterator::TryParseAndRetrieveScopes(ReparseStrategy strategy) {
UnwrapEvaluationContext();
} else {
// A failed reparse indicates that the preparser has diverged from the
// parser or that the preparse data given to the initial parse has been
// faulty. We fail in debug mode but in release mode we only provide the
// information we get from the context chain but nothing about
// completely stack allocated scopes or stack allocated locals.
// Or it could be due to stack overflow.
// parser, that the preparse data given to the initial parse was faulty, or
// a stack overflow.
// TODO(leszeks): This error is pretty unexpected, so we could report the
// error in debug mode. Better to not fail in release though, in case it's
// just a stack overflow.
// Silently fail by presenting an empty context chain.
CHECK(isolate_->has_pending_exception());
isolate_->clear_pending_exception();
context_ = Handle<Context>();
}
}

View File

@ -757,7 +757,14 @@ bool ParseScript(Isolate* isolate, Handle<Script> script, ParseInfo* parse_info,
success = Compiler::CompileForLiveEdit(parse_info, script, isolate)
.ToHandle(&shared);
} else {
success = parsing::ParseProgram(parse_info, script, isolate);
success = parsing::ParseProgram(parse_info, script, isolate,
parsing::ReportStatisticsMode::kYes);
if (!success) {
// Throw the parser error.
parse_info->pending_error_handler()->PrepareErrors(
isolate, parse_info->ast_value_factory());
parse_info->pending_error_handler()->ReportErrors(isolate, script);
}
}
if (!success) {
isolate->OptionalRescheduleException(false);

View File

@ -1261,14 +1261,13 @@ Handle<String> RenderCallSite(Isolate* isolate, Handle<Object> object,
isolate, *location->shared());
UnoptimizedCompileState compile_state(isolate);
ParseInfo info(isolate, flags, &compile_state);
if (parsing::ParseAny(&info, location->shared(), isolate)) {
if (parsing::ParseAny(&info, location->shared(), isolate,
parsing::ReportStatisticsMode::kNo)) {
info.ast_value_factory()->Internalize(isolate);
CallPrinter printer(isolate, location->shared()->IsUserJavaScript());
Handle<String> str = printer.Print(info.literal(), location->start_pos());
*hint = printer.GetErrorHint();
if (str->length() > 0) return str;
} else {
isolate->clear_pending_exception();
}
}
return BuildDefaultCallSite(isolate, object);
@ -1322,7 +1321,8 @@ Object ErrorUtils::ThrowSpreadArgError(Isolate* isolate, MessageTemplate id,
isolate, *location.shared());
UnoptimizedCompileState compile_state(isolate);
ParseInfo info(isolate, flags, &compile_state);
if (parsing::ParseAny(&info, location.shared(), isolate)) {
if (parsing::ParseAny(&info, location.shared(), isolate,
parsing::ReportStatisticsMode::kNo)) {
info.ast_value_factory()->Internalize(isolate);
CallPrinter printer(isolate, location.shared()->IsUserJavaScript(),
CallPrinter::SpreadErrorInArgsHint::kErrorInArgs);
@ -1337,7 +1337,6 @@ Object ErrorUtils::ThrowSpreadArgError(Isolate* isolate, MessageTemplate id,
MessageLocation(location.script(), pos, pos + 1, location.shared());
}
} else {
isolate->clear_pending_exception();
callsite = BuildDefaultCallSite(isolate, object);
}
}
@ -1399,7 +1398,8 @@ Object ErrorUtils::ThrowLoadFromNullOrUndefined(Isolate* isolate,
isolate, *location.shared());
UnoptimizedCompileState compile_state(isolate);
ParseInfo info(isolate, flags, &compile_state);
if (parsing::ParseAny(&info, location.shared(), isolate)) {
if (parsing::ParseAny(&info, location.shared(), isolate,
parsing::ReportStatisticsMode::kNo)) {
info.ast_value_factory()->Internalize(isolate);
CallPrinter printer(isolate, location.shared()->IsUserJavaScript());
Handle<String> str = printer.Print(info.literal(), location.start_pos());
@ -1434,8 +1434,6 @@ Object ErrorUtils::ThrowLoadFromNullOrUndefined(Isolate* isolate,
}
if (str->length() > 0) callsite = str;
} else {
isolate->clear_pending_exception();
}
}

View File

@ -170,10 +170,10 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
friend class i::ArrowHeadParsingScope<ParserTypes<Parser>>;
friend bool v8::internal::parsing::ParseProgram(
ParseInfo*, Handle<Script>, MaybeHandle<ScopeInfo> maybe_outer_scope_info,
Isolate*, parsing::ReportErrorsAndStatisticsMode stats_mode);
Isolate*, parsing::ReportStatisticsMode stats_mode);
friend bool v8::internal::parsing::ParseFunction(
ParseInfo*, Handle<SharedFunctionInfo> shared_info, Isolate*,
parsing::ReportErrorsAndStatisticsMode stats_mode);
parsing::ReportStatisticsMode stats_mode);
bool AllowsLazyParsingWithoutUnresolvedVariables() const {
return !MaybeParsingArrowhead() &&

View File

@ -7,6 +7,7 @@
#include <memory>
#include "src/ast/ast.h"
#include "src/base/v8-fallthrough.h"
#include "src/execution/vm-state-inl.h"
#include "src/handles/maybe-handles.h"
#include "src/objects/objects-inl.h"
@ -24,14 +25,13 @@ namespace {
void MaybeReportErrorsAndStatistics(ParseInfo* info, Handle<Script> script,
Isolate* isolate, Parser* parser,
ReportErrorsAndStatisticsMode mode) {
if (mode == ReportErrorsAndStatisticsMode::kYes) {
if (info->literal() == nullptr) {
info->pending_error_handler()->PrepareErrors(isolate,
info->ast_value_factory());
info->pending_error_handler()->ReportErrors(isolate, script);
}
parser->UpdateStatistics(isolate, script);
ReportStatisticsMode mode) {
switch (mode) {
case ReportStatisticsMode::kYes:
parser->UpdateStatistics(isolate, script);
break;
case ReportStatisticsMode::kNo:
break;
}
}
@ -39,7 +39,7 @@ void MaybeReportErrorsAndStatistics(ParseInfo* info, Handle<Script> script,
bool ParseProgram(ParseInfo* info, Handle<Script> script,
MaybeHandle<ScopeInfo> maybe_outer_scope_info,
Isolate* isolate, ReportErrorsAndStatisticsMode mode) {
Isolate* isolate, ReportStatisticsMode mode) {
DCHECK(info->flags().is_toplevel());
DCHECK_NULL(info->literal());
@ -62,12 +62,12 @@ bool ParseProgram(ParseInfo* info, Handle<Script> script,
}
bool ParseProgram(ParseInfo* info, Handle<Script> script, Isolate* isolate,
ReportErrorsAndStatisticsMode mode) {
ReportStatisticsMode mode) {
return ParseProgram(info, script, kNullMaybeHandle, isolate, mode);
}
bool ParseFunction(ParseInfo* info, Handle<SharedFunctionInfo> shared_info,
Isolate* isolate, ReportErrorsAndStatisticsMode mode) {
Isolate* isolate, ReportStatisticsMode mode) {
DCHECK(!info->flags().is_toplevel());
DCHECK(!shared_info.is_null());
DCHECK_NULL(info->literal());
@ -93,7 +93,7 @@ bool ParseFunction(ParseInfo* info, Handle<SharedFunctionInfo> shared_info,
}
bool ParseAny(ParseInfo* info, Handle<SharedFunctionInfo> shared_info,
Isolate* isolate, ReportErrorsAndStatisticsMode mode) {
Isolate* isolate, ReportStatisticsMode mode) {
DCHECK(!shared_info.is_null());
if (info->flags().is_toplevel()) {
MaybeHandle<ScopeInfo> maybe_outer_scope_info;

View File

@ -15,36 +15,37 @@ class SharedFunctionInfo;
namespace parsing {
enum class ReportErrorsAndStatisticsMode { kYes, kNo };
enum class ReportStatisticsMode { kYes, kNo };
// Parses the top-level source code represented by the parse info and sets its
// function literal. Returns false (and deallocates any allocated AST nodes) if
// parsing failed.
V8_EXPORT_PRIVATE bool ParseProgram(
ParseInfo* info, Handle<Script> script, Isolate* isolate,
ReportErrorsAndStatisticsMode mode = ReportErrorsAndStatisticsMode::kYes);
V8_EXPORT_PRIVATE bool ParseProgram(ParseInfo* info, Handle<Script> script,
Isolate* isolate,
ReportStatisticsMode mode);
// Parses the top-level source code represented by the parse info and sets its
// function literal. Allows passing an |outer_scope| for programs that exist in
// another scope (e.g. eval). Returns false (and deallocates any allocated AST
// nodes) if parsing failed.
V8_EXPORT_PRIVATE bool ParseProgram(
ParseInfo* info, Handle<Script> script, MaybeHandle<ScopeInfo> outer_scope,
Isolate* isolate,
ReportErrorsAndStatisticsMode mode = ReportErrorsAndStatisticsMode::kYes);
V8_EXPORT_PRIVATE bool ParseProgram(ParseInfo* info, Handle<Script> script,
MaybeHandle<ScopeInfo> outer_scope,
Isolate* isolate,
ReportStatisticsMode mode);
// Like ParseProgram but for an individual function which already has a
// allocated shared function info.
V8_EXPORT_PRIVATE bool ParseFunction(
ParseInfo* info, Handle<SharedFunctionInfo> shared_info, Isolate* isolate,
ReportErrorsAndStatisticsMode mode = ReportErrorsAndStatisticsMode::kYes);
V8_EXPORT_PRIVATE bool ParseFunction(ParseInfo* info,
Handle<SharedFunctionInfo> shared_info,
Isolate* isolate,
ReportStatisticsMode mode);
// If you don't know whether info->is_toplevel() is true or not, use this method
// to dispatch to either of the above functions. Prefer to use the above methods
// whenever possible.
V8_EXPORT_PRIVATE bool ParseAny(
ParseInfo* info, Handle<SharedFunctionInfo> shared_info, Isolate* isolate,
ReportErrorsAndStatisticsMode mode = ReportErrorsAndStatisticsMode::kYes);
V8_EXPORT_PRIVATE bool ParseAny(ParseInfo* info,
Handle<SharedFunctionInfo> shared_info,
Isolate* isolate, ReportStatisticsMode mode);
} // namespace parsing
} // namespace internal

View File

@ -5,6 +5,7 @@
#include "src/parsing/pending-compilation-error-handler.h"
#include "src/ast/ast-value-factory.h"
#include "src/base/export-template.h"
#include "src/base/logging.h"
#include "src/debug/debug.h"
#include "src/execution/isolate.h"
@ -139,10 +140,13 @@ void PendingCompilationErrorHandler::PrepareErrors(
ast_value_factory->Internalize(isolate);
error_details_.Prepare(isolate);
}
template void PendingCompilationErrorHandler::PrepareErrors(
Isolate* isolate, AstValueFactory* ast_value_factory);
template void PendingCompilationErrorHandler::PrepareErrors(
OffThreadIsolate* isolate, AstValueFactory* ast_value_factory);
template EXPORT_TEMPLATE_DEFINE(
V8_EXPORT_PRIVATE) void PendingCompilationErrorHandler::
PrepareErrors(Isolate* isolate, AstValueFactory* ast_value_factory);
template EXPORT_TEMPLATE_DEFINE(
V8_EXPORT_PRIVATE) void PendingCompilationErrorHandler::
PrepareErrors(OffThreadIsolate* isolate,
AstValueFactory* ast_value_factory);
void PendingCompilationErrorHandler::ReportErrors(Isolate* isolate,
Handle<Script> script) const {

View File

@ -49,8 +49,10 @@ class PendingCompilationErrorHandler {
// Handle errors detected during parsing.
template <typename LocalIsolate>
EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
void PrepareErrors(LocalIsolate* isolate, AstValueFactory* ast_value_factory);
void ReportErrors(Isolate* isolate, Handle<Script> script) const;
V8_EXPORT_PRIVATE void ReportErrors(Isolate* isolate,
Handle<Script> script) const;
// Handle warnings detected during compilation.
template <typename LocalIsolate>
@ -139,6 +141,15 @@ class PendingCompilationErrorHandler {
DISALLOW_COPY_AND_ASSIGN(PendingCompilationErrorHandler);
};
extern template void PendingCompilationErrorHandler::PrepareErrors(
Isolate* isolate, AstValueFactory* ast_value_factory);
extern template void PendingCompilationErrorHandler::PrepareErrors(
OffThreadIsolate* isolate, AstValueFactory* ast_value_factory);
extern template void PendingCompilationErrorHandler::PrepareWarnings(
Isolate* isolate);
extern template void PendingCompilationErrorHandler::PrepareWarnings(
OffThreadIsolate* isolate);
} // namespace internal
} // namespace v8
#endif // V8_PARSING_PENDING_COMPILATION_ERROR_HANDLER_H_

View File

@ -716,7 +716,8 @@ TEST(PreParserScopeAnalysis) {
i::ParseInfo using_scope_data(isolate, flags, &using_scope_state);
using_scope_data.set_consumed_preparse_data(
i::ConsumedPreparseData::For(isolate, produced_data_on_heap));
CHECK(i::parsing::ParseFunction(&using_scope_data, shared, isolate));
CHECK(i::parsing::ParseFunction(&using_scope_data, shared, isolate,
i::parsing::ReportStatisticsMode::kYes));
// Verify that we skipped at least one function inside that scope.
i::DeclarationScope* scope_with_skipped_functions =
@ -727,7 +728,8 @@ TEST(PreParserScopeAnalysis) {
// Parse the lazy function again eagerly to produce baseline data.
i::UnoptimizedCompileState not_using_scope_state(isolate);
i::ParseInfo not_using_scope_data(isolate, flags, &not_using_scope_state);
CHECK(i::parsing::ParseFunction(&not_using_scope_data, shared, isolate));
CHECK(i::parsing::ParseFunction(&not_using_scope_data, shared, isolate,
i::parsing::ReportStatisticsMode::kYes));
// Verify that we didn't skip anything (there's no preparsed scope data,
// so we cannot skip).
@ -764,7 +766,8 @@ TEST(Regress753896) {
// We don't assert that parsing succeeded or that it failed; currently the
// error is not detected inside lazy functions, but it might be in the future.
i::parsing::ParseProgram(&info, script, isolate);
i::parsing::ParseProgram(&info, script, isolate,
i::parsing::ReportStatisticsMode::kYes);
}
TEST(ProducingAndConsumingByteData) {

View File

@ -71,6 +71,56 @@ void MockUseCounterCallback(v8::Isolate* isolate,
} // namespace
// Helpers for parsing and checking that the result has no error, implemented as
// macros to report the correct test error location.
#define FAIL_WITH_PENDING_PARSER_ERROR(info, script, isolate) \
do { \
(info)->pending_error_handler()->PrepareErrors( \
(isolate), (info)->ast_value_factory()); \
(info)->pending_error_handler()->ReportErrors((isolate), (script)); \
\
i::Handle<i::JSObject> exception_handle( \
i::JSObject::cast((isolate)->pending_exception()), (isolate)); \
i::Handle<i::String> message_string = i::Handle<i::String>::cast( \
i::JSReceiver::GetProperty((isolate), exception_handle, "message") \
.ToHandleChecked()); \
(isolate)->clear_pending_exception(); \
\
String source = String::cast((script)->source()); \
\
FATAL( \
"Parser failed on:\n" \
"\t%s\n" \
"with error:\n" \
"\t%s\n" \
"However, we expected no error.", \
source.ToCString().get(), message_string->ToCString().get()); \
} while (false)
#define CHECK_PARSE_PROGRAM(info, script, isolate) \
do { \
if (!i::parsing::ParseProgram((info), script, (isolate), \
parsing::ReportStatisticsMode::kYes)) { \
FAIL_WITH_PENDING_PARSER_ERROR((info), (script), (isolate)); \
} \
\
CHECK(!(info)->pending_error_handler()->has_pending_error()); \
CHECK_NOT_NULL((info)->literal()); \
} while (false)
#define CHECK_PARSE_FUNCTION(info, shared, isolate) \
do { \
if (!i::parsing::ParseFunction((info), (shared), (isolate), \
parsing::ReportStatisticsMode::kYes)) { \
FAIL_WITH_PENDING_PARSER_ERROR( \
(info), handle(Script::cast((shared)->script()), (isolate)), \
(isolate)); \
} \
\
CHECK(!(info)->pending_error_handler()->has_pending_error()); \
CHECK_NOT_NULL((info)->literal()); \
} while (false)
bool TokenIsAutoSemicolon(Token::Value token) {
switch (token) {
case Token::SEMICOLON:
@ -1081,7 +1131,7 @@ TEST(ScopeUsesArgumentsSuperThis) {
// The information we're checking is only produced when eager parsing.
flags.set_allow_lazy_parsing(false);
i::ParseInfo info(isolate, flags, &compile_state);
CHECK(i::parsing::ParseProgram(&info, script, isolate));
CHECK_PARSE_PROGRAM(&info, script, isolate);
i::DeclarationScope::AllocateScopeInfos(&info, isolate);
CHECK_NOT_NULL(info.literal());
@ -1147,7 +1197,7 @@ static void CheckParsesToNumber(const char* source) {
flags.set_is_toplevel(true);
i::ParseInfo info(isolate, flags, &compile_state);
CHECK(i::parsing::ParseProgram(&info, script, isolate));
CHECK_PARSE_PROGRAM(&info, script, isolate);
CHECK_EQ(1, info.scope()->declarations()->LengthForTest());
i::Declaration* decl = info.scope()->declarations()->AtForTest(0);
@ -1459,8 +1509,7 @@ TEST(ScopePositions) {
i::UnoptimizedCompileFlags::ForScriptCompile(isolate, *script);
flags.set_outer_language_mode(source_data[i].language_mode);
i::ParseInfo info(isolate, flags, &compile_state);
i::parsing::ParseProgram(&info, script, isolate);
CHECK_NOT_NULL(info.literal());
CHECK_PARSE_PROGRAM(&info, script, isolate);
// Check scope types and positions.
i::Scope* scope = info.literal()->scope();
@ -1507,7 +1556,7 @@ TEST(DiscardFunctionBody) {
i::UnoptimizedCompileFlags flags =
i::UnoptimizedCompileFlags::ForScriptCompile(isolate, *script);
i::ParseInfo info(isolate, flags, &compile_state);
i::parsing::ParseProgram(&info, script, isolate);
CHECK_PARSE_PROGRAM(&info, script, isolate);
function = info.literal();
CHECK_NOT_NULL(function);
// The rewriter will rewrite this to
@ -1645,7 +1694,14 @@ void TestParserSyncWithFlags(i::Handle<i::String> source,
i::Handle<i::Script> script =
factory->NewScriptWithId(source, compile_flags.script_id());
i::ParseInfo info(isolate, compile_flags, &compile_state);
i::parsing::ParseProgram(&info, script, isolate);
if (!i::parsing::ParseProgram(&info, script, isolate,
parsing::ReportStatisticsMode::kYes)) {
info.pending_error_handler()->PrepareErrors(isolate,
info.ast_value_factory());
info.pending_error_handler()->ReportErrors(isolate, script);
} else {
CHECK(!info.pending_error_handler()->has_pending_error());
}
function = info.literal();
}
@ -3525,7 +3581,7 @@ TEST(InnerAssignment) {
i::UnoptimizedCompileFlags flags =
i::UnoptimizedCompileFlags::ForFunctionCompile(isolate, *shared);
info = std::make_unique<i::ParseInfo>(isolate, flags, &compile_state);
CHECK(i::parsing::ParseFunction(info.get(), shared, isolate));
CHECK_PARSE_FUNCTION(info.get(), shared, isolate);
} else {
i::Handle<i::String> source =
factory->InternalizeUtf8String(program.begin());
@ -3536,9 +3592,8 @@ TEST(InnerAssignment) {
i::UnoptimizedCompileFlags::ForScriptCompile(isolate, *script);
flags.set_allow_lazy_parsing(false);
info = std::make_unique<i::ParseInfo>(isolate, flags, &compile_state);
CHECK(i::parsing::ParseProgram(info.get(), script, isolate));
CHECK_PARSE_PROGRAM(info.get(), script, isolate);
}
CHECK_NOT_NULL(info->literal());
i::Scope* scope = info->literal()->scope();
if (!lazy) {
@ -3646,8 +3701,7 @@ TEST(MaybeAssignedParameters) {
i::UnoptimizedCompileFlags::ForFunctionCompile(isolate, *shared);
flags.set_allow_lazy_parsing(allow_lazy);
info = std::make_unique<i::ParseInfo>(isolate, flags, &state);
CHECK(i::parsing::ParseFunction(info.get(), shared, isolate));
CHECK_NOT_NULL(info->literal());
CHECK_PARSE_FUNCTION(info.get(), shared, isolate);
i::Scope* scope = info->literal()->scope();
CHECK(!scope->AsDeclarationScope()->was_lazily_parsed());
@ -3687,9 +3741,8 @@ static void TestMaybeAssigned(Input input, const char* variable, bool module,
std::unique_ptr<i::ParseInfo> info =
std::make_unique<i::ParseInfo>(isolate, flags, &state);
CHECK(i::parsing::ParseProgram(info.get(), script, isolate));
CHECK_PARSE_PROGRAM(info.get(), script, isolate);
CHECK_NOT_NULL(info->literal());
i::Scope* scope = info->literal()->scope();
CHECK(!scope->AsDeclarationScope()->was_lazily_parsed());
CHECK_NULL(scope->sibling());
@ -7442,22 +7495,7 @@ TEST(BasicImportExportParsing) {
i::UnoptimizedCompileFlags::ForScriptCompile(isolate, *script);
flags.set_is_module(true);
i::ParseInfo info(isolate, flags, &compile_state);
if (!i::parsing::ParseProgram(&info, script, isolate)) {
i::Handle<i::JSObject> exception_handle(
i::JSObject::cast(isolate->pending_exception()), isolate);
i::Handle<i::String> message_string = i::Handle<i::String>::cast(
i::JSReceiver::GetProperty(isolate, exception_handle, "message")
.ToHandleChecked());
isolate->clear_pending_exception();
FATAL(
"Parser failed on:\n"
"\t%s\n"
"with error:\n"
"\t%s\n"
"However, we expected no error.",
source->ToCString().get(), message_string->ToCString().get());
}
CHECK_PARSE_PROGRAM(&info, script, isolate);
}
// And that parsing a script does not.
@ -7467,8 +7505,9 @@ TEST(BasicImportExportParsing) {
i::UnoptimizedCompileFlags flags =
i::UnoptimizedCompileFlags::ForScriptCompile(isolate, *script);
i::ParseInfo info(isolate, flags, &compile_state);
CHECK(!i::parsing::ParseProgram(&info, script, isolate));
isolate->clear_pending_exception();
CHECK(!i::parsing::ParseProgram(&info, script, isolate,
parsing::ReportStatisticsMode::kYes));
CHECK(info.pending_error_handler()->has_pending_error());
}
}
}
@ -7508,7 +7547,7 @@ TEST(NamespaceExportParsing) {
i::UnoptimizedCompileFlags::ForScriptCompile(isolate, *script);
flags.set_is_module(true);
i::ParseInfo info(isolate, flags, &compile_state);
CHECK(i::parsing::ParseProgram(&info, script, isolate));
CHECK_PARSE_PROGRAM(&info, script, isolate);
}
}
@ -7606,8 +7645,9 @@ TEST(ImportExportParsingErrors) {
i::UnoptimizedCompileFlags::ForScriptCompile(isolate, *script);
flags.set_is_module(true);
i::ParseInfo info(isolate, flags, &compile_state);
CHECK(!i::parsing::ParseProgram(&info, script, isolate));
isolate->clear_pending_exception();
CHECK(!i::parsing::ParseProgram(&info, script, isolate,
parsing::ReportStatisticsMode::kYes));
CHECK(info.pending_error_handler()->has_pending_error());
}
}
@ -7645,8 +7685,9 @@ TEST(ModuleTopLevelFunctionDecl) {
i::UnoptimizedCompileFlags::ForScriptCompile(isolate, *script);
flags.set_is_module(true);
i::ParseInfo info(isolate, flags, &compile_state);
CHECK(!i::parsing::ParseProgram(&info, script, isolate));
isolate->clear_pending_exception();
CHECK(!i::parsing::ParseProgram(&info, script, isolate,
parsing::ReportStatisticsMode::kYes));
CHECK(info.pending_error_handler()->has_pending_error());
}
}
@ -7845,7 +7886,8 @@ TEST(ModuleParsingInternals) {
i::UnoptimizedCompileFlags::ForScriptCompile(isolate, *script);
flags.set_is_module(true);
i::ParseInfo info(isolate, flags, &compile_state);
CHECK(i::parsing::ParseProgram(&info, script, isolate));
CHECK_PARSE_PROGRAM(&info, script, isolate);
i::FunctionLiteral* func = info.literal();
i::ModuleScope* module_scope = func->scope()->AsModuleScope();
i::Scope* outer_scope = module_scope->outer_scope();
@ -8089,8 +8131,8 @@ void TestLanguageMode(const char* source,
i::UnoptimizedCompileFlags flags =
i::UnoptimizedCompileFlags::ForScriptCompile(isolate, *script);
i::ParseInfo info(isolate, flags, &compile_state);
i::parsing::ParseProgram(&info, script, isolate);
CHECK_NOT_NULL(info.literal());
CHECK_PARSE_PROGRAM(&info, script, isolate);
CHECK_EQ(expected_language_mode, info.literal()->language_mode());
}
@ -10874,8 +10916,7 @@ TEST(NoPessimisticContextAllocation) {
i::UnoptimizedCompileFlags::ForScriptCompile(isolate, *script);
i::ParseInfo info(isolate, flags, &compile_state);
CHECK(i::parsing::ParseProgram(&info, script, isolate));
CHECK_NOT_NULL(info.literal());
CHECK_PARSE_PROGRAM(&info, script, isolate);
i::Scope* scope = info.literal()->scope()->inner_scope();
DCHECK_NOT_NULL(scope);
@ -11436,7 +11477,8 @@ TEST(LexicalLoopVariable) {
i::UnoptimizedCompileFlags::ForScriptCompile(isolate, *script);
flags.set_allow_lazy_parsing(false);
i::ParseInfo info(isolate, flags, &compile_state);
CHECK(i::parsing::ParseProgram(&info, script, isolate));
CHECK_PARSE_PROGRAM(&info, script, isolate);
i::DeclarationScope::AllocateScopeInfos(&info, isolate);
CHECK_NOT_NULL(info.literal());

View File

@ -85,7 +85,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
v8::internal::UnoptimizedCompileFlags::ForScriptCompile(i_isolate,
*script);
v8::internal::ParseInfo info(i_isolate, flags, &state);
if (!v8::internal::parsing::ParseProgram(&info, script, i_isolate)) {
if (!v8::internal::parsing::ParseProgram(
&info, script, i_isolate, i::parsing::ReportStatisticsMode::kYes)) {
info.pending_error_handler()->PrepareErrors(i_isolate,
info.ast_value_factory());
info.pending_error_handler()->ReportErrors(i_isolate, script);
i_isolate->OptionalRescheduleException(true);
}
isolate->RequestGarbageCollectionForTesting(