From 81c8e5b514ce567c9375022ab4c3b6c92eb3a91b Mon Sep 17 00:00:00 2001 From: Tooru Fujisawa Date: Wed, 28 Sep 2022 07:40:18 +0000 Subject: [PATCH] Bug 1786494 - Part 11: Add AutoReportFrontendContext and use it in CompilationAndEvaluation.cpp. r=bthrall The frontend error is converted into the runtime error in AutoReportFrontendContext destructor, and it can GC. If the function's return value is GC thing, AutoReportFrontendContext destructor must be called before the return statement, and thus AutoReportFrontendContext must be put into a block, and the return value must be stored into `JS::Rooted` outside of the block. Differential Revision: https://phabricator.services.mozilla.com/D157451 --- js/src/vm/CompilationAndEvaluation.cpp | 21 +++++++++++++-------- js/src/vm/ErrorContext.h | 19 +++++++++++++++++++ 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/js/src/vm/CompilationAndEvaluation.cpp b/js/src/vm/CompilationAndEvaluation.cpp index 336dae93168f..fec237b0b6fa 100644 --- a/js/src/vm/CompilationAndEvaluation.cpp +++ b/js/src/vm/CompilationAndEvaluation.cpp @@ -32,7 +32,7 @@ #include "util/CompleteFile.h" // js::FileContents, js::ReadCompleteFile #include "util/StringBuffer.h" // js::StringBuffer #include "vm/EnvironmentObject.h" // js::CreateNonSyntacticEnvironmentChain -#include "vm/ErrorContext.h" // js::MainThreadErrorContext +#include "vm/ErrorContext.h" // js::AutoReportFrontendContext #include "vm/Interpreter.h" // js::Execute #include "vm/JSContext.h" // JSContext @@ -67,9 +67,14 @@ static JSScript* CompileSourceBuffer(JSContext* cx, AssertHeapIsIdle(); CHECK_THREAD(cx); - MainThreadErrorContext ec(cx); - return frontend::CompileGlobalScript( - cx, &ec, cx->stackLimitForCurrentPrincipal(), options, srcBuf, scopeKind); + JS::Rooted script(cx); + { + AutoReportFrontendContext ec(cx); + script = frontend::CompileGlobalScript(cx, &ec, + cx->stackLimitForCurrentPrincipal(), + options, srcBuf, scopeKind); + } + return script; } JSScript* JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options, @@ -100,7 +105,7 @@ JS_PUBLIC_API bool JS::StartIncrementalEncoding(JSContext* cx, return false; } - MainThreadErrorContext ec(cx); + AutoReportFrontendContext ec(cx); if (!initial->steal(&ec, std::move(stencil))) { return false; } @@ -165,7 +170,8 @@ JS_PUBLIC_API bool JS_Utf8BufferIsCompilableUnit(JSContext* cx, using frontend::ParseGoal; using frontend::Parser; - MainThreadErrorContext ec(cx); + AutoReportFrontendContext ec(cx, + AutoReportFrontendContext::Warning::Suppress); CompileOptions options(cx); Rooted input(cx, frontend::CompilationInput(options)); @@ -180,7 +186,6 @@ JS_PUBLIC_API bool JS_Utf8BufferIsCompilableUnit(JSContext* cx, return false; } - JS::AutoSuppressWarningReporter suppressWarnings(cx); Parser parser( cx, &ec, cx->stackLimitForCurrentPrincipal(), options, chars.get(), length, @@ -515,7 +520,7 @@ static bool EvaluateSourceBuffer(JSContext* cx, ScopeKind scopeKind, options.setNonSyntacticScope(scopeKind == ScopeKind::NonSyntactic); options.setIsRunOnce(true); - MainThreadErrorContext ec(cx); + AutoReportFrontendContext ec(cx); RootedScript script(cx, frontend::CompileGlobalScript( cx, &ec, cx->stackLimitForCurrentPrincipal(), options, srcBuf, scopeKind)); diff --git a/js/src/vm/ErrorContext.h b/js/src/vm/ErrorContext.h index 7d75af8d3863..56f57e72af75 100644 --- a/js/src/vm/ErrorContext.h +++ b/js/src/vm/ErrorContext.h @@ -123,6 +123,7 @@ class OffThreadErrorContext : public ErrorContext { private: js::OffThreadFrontendErrors errors_; + protected: // (optional) Current JSContext to support main-thread-specific // handling for error reporting, GC, and memory allocation. // @@ -184,6 +185,24 @@ class OffThreadErrorContext : public ErrorContext { void addPendingOutOfMemory(); }; +// Automatically report any pending exception when leaving the scope. +class MOZ_STACK_CLASS AutoReportFrontendContext : public OffThreadErrorContext { + // The target JSContext to report the errors to. + JSContext* cx_; + + Warning warning_; + + public: + explicit AutoReportFrontendContext(JSContext* cx, + Warning warning = Warning::Report) + : OffThreadErrorContext(), cx_(cx), warning_(warning) { + setCurrentJSContext(cx_); + MOZ_ASSERT(cx_ == maybeCx_); + } + + ~AutoReportFrontendContext() { convertToRuntimeError(cx_, warning_); } +}; + } // namespace js #endif /* vm_ErrorContext_h */