mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:18:48 +00:00
8f529f64f5
- Bug 932865 - Add ThreadHangStats for collecting background hang telemetry; r=vladan (2f08a076b)
- Bug 932865 - Add way for telemetry to iterate over active threads; r=froydnj (535615d3d)
- Bug 1128768: Part 3 - Update BHR to allow for hang annotations; r=vladan (0b880a667)
- Bug 935092 - Add ThreadStackHelper to get a thread's pesudo-stack; r=BenWa (1422cfe4d)
- Bug 942488 - Don't report pseudo-stacks without SPS profiler. r=nchen (e160a7a08)
- Bug 946817 - Don't assert mPseudoStack on B2G. r=BenWa (9f846df3b)
- Bug 951431 - Don't get stacks during profiler runs on Linux; r=BenWa (15036e907)
- Bug 978262 - Ignore duplicate frames when getting BHR stack. r=froydnj (964721b1b)
- Bug 985155 - Add signal trampoline on ARM Linux to work around kernel bug. r=snorp (cb8a7846c)
- Bug 995730 - Convert xpcom/threads/ to Gecko style. r=froydnj (fe150404e)
- Bug 1013326 - Distinguish chrome and content scripts in pseudostack; r=snorp (81273c977)
- Bug 1023461 - Remove temporary stack buffer in ThreadStackHelper; r=snorp (cf5a717c2)
- Bug 1023461 - Record filename and line number for chrome JS entries; r=snorp (10c89808f)
- Bug 1022456 - Fix modelines in xpcom/{base,glue,io,string,threads}/. (48dbc0416)
- Bug 1016441 - Switch to using real-time signal in ThreadStackHelper; (2c5f818be)
- Bug 1016629 - b. Use RAII class to assign mStackToFill; r=snorp (769eae130)
- Bug 1016629 - c. Add define for ThreadStackHelper pseudostack support; r=snorp (67def0d2f)
- Bug 1016629 - d. Add and implement GetNativeStack method in ThreadStackHelper; r=snorp r=jseward (46c52f2be)
- Bug 1016629 - e. Implement platform-specific code for filling in context; r=snorp r=jseward (e6a66858b)
- Bug 1016629 - g. Avoid ASan flag when copying stack; r=snorp (0159628b5)
- Bug 1045176 - Unbreak build on non-SPS platforms after bug 1016629. (f1d60d838)
- Bug 1047123 - ThreadStackHelper should use UniquePtr<uint8_t[]>, not ScopedDeleteArray. r=jchen (0e4af313c)
- Bug 1049161 - Fix ThreadStackHelper thread handle permissions on Windows; r=snorp (c05172b1c)
- Bug 1050185 - Make ThreadStackHelper::FillThreadContext Valgrind-friendly. r=nchen (368725774)
- Bug 1050440 - Remove repeated js::RunScript frames in ThreadStackHelper (2a79600b3)
- Bug 1046841 - Fix more style violations in previously touched .cpp files in xpcom/. r=froydnj (02afe2493)
- Bug 1069694 - Remove or move around functions in OldDebugAPI. r=shu (177197302)
- Bug 1069694 - Remove OldDebugAPI from the browser. r=shu (b8c917d42)
- Bug 1100911 - For MacOS builds running on Valgrind, make ThreadStackHelper::GetStack be a no-op. r=nchen. (d99c02e16)
- Bug 1091758 - Report full paths for most chrome scripts; r=snorp (2b72e7878)
- Bug 1109291 - Include better paths for hanging chrome scripts in profile extensions directory; r=snorp r=bsmedberg (1997b9532)
- Bug 1113416 - Don't read stack labels inside hang monitor sighandler; r=nfroyd r=snorp (9688f6069)
- bug 1146027 - more final r=froydnj (7b0f295e5)
- Bug 1164090 - Check for Windows path separator in BHR file name; r=snorp (f014b4d78)
- Bug 1169034 - include <cstdlib> in ThreadStackHelper.cpp to declare correct overload for std::abs; r=jseward (874d4447e)
- Bug 1182996 - Fix and add missing namespace comments. rs=ehsan (054fc00b2)
- Bug 932865 - Collect thread hang stats in BackgroundHangMonitor; (ac80c8e9f)
- minor anticipated fixes to get it compiling (2bd701d15)
358 lines
9.2 KiB
C++
358 lines
9.2 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
/* diagnostic reporting for CSS style sheet parser */
|
|
|
|
#include "mozilla/css/ErrorReporter.h"
|
|
|
|
#include "mozilla/CSSStyleSheet.h"
|
|
#include "mozilla/css/Loader.h"
|
|
#include "mozilla/Preferences.h"
|
|
#include "mozilla/Services.h"
|
|
#include "nsCSSScanner.h"
|
|
#include "nsIConsoleService.h"
|
|
#include "nsIDocument.h"
|
|
#include "nsIFactory.h"
|
|
#include "nsIScriptError.h"
|
|
#include "nsIStringBundle.h"
|
|
#include "nsServiceManagerUtils.h"
|
|
#include "nsStyleUtil.h"
|
|
#include "nsThreadUtils.h"
|
|
|
|
#ifdef CSS_REPORT_PARSE_ERRORS
|
|
|
|
using namespace mozilla;
|
|
|
|
namespace {
|
|
class ShortTermURISpecCache : public nsRunnable {
|
|
public:
|
|
ShortTermURISpecCache() : mPending(false) {}
|
|
|
|
nsString const& GetSpec(nsIURI* aURI) {
|
|
if (mURI != aURI) {
|
|
mURI = aURI;
|
|
|
|
nsAutoCString cSpec;
|
|
mURI->GetSpec(cSpec);
|
|
CopyUTF8toUTF16(cSpec, mSpec);
|
|
}
|
|
return mSpec;
|
|
}
|
|
|
|
bool IsInUse() const { return mURI != nullptr; }
|
|
bool IsPending() const { return mPending; }
|
|
void SetPending() { mPending = true; }
|
|
|
|
// When invoked as a runnable, zap the cache.
|
|
NS_IMETHOD Run() {
|
|
mURI = nullptr;
|
|
mSpec.Truncate();
|
|
mPending = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
private:
|
|
nsCOMPtr<nsIURI> mURI;
|
|
nsString mSpec;
|
|
bool mPending;
|
|
};
|
|
|
|
} // namespace
|
|
|
|
static bool sReportErrors;
|
|
static nsIConsoleService *sConsoleService;
|
|
static nsIFactory *sScriptErrorFactory;
|
|
static nsIStringBundle *sStringBundle;
|
|
static ShortTermURISpecCache *sSpecCache;
|
|
|
|
#define CSS_ERRORS_PREF "layout.css.report_errors"
|
|
|
|
static bool
|
|
InitGlobals()
|
|
{
|
|
MOZ_ASSERT(!sConsoleService && !sScriptErrorFactory && !sStringBundle,
|
|
"should not have been called");
|
|
|
|
if (NS_FAILED(Preferences::AddBoolVarCache(&sReportErrors, CSS_ERRORS_PREF,
|
|
true))) {
|
|
return false;
|
|
}
|
|
|
|
nsCOMPtr<nsIConsoleService> cs = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
|
|
if (!cs) {
|
|
return false;
|
|
}
|
|
|
|
nsCOMPtr<nsIFactory> sf = do_GetClassObject(NS_SCRIPTERROR_CONTRACTID);
|
|
if (!sf) {
|
|
return false;
|
|
}
|
|
|
|
nsCOMPtr<nsIStringBundleService> sbs = services::GetStringBundleService();
|
|
if (!sbs) {
|
|
return false;
|
|
}
|
|
|
|
nsCOMPtr<nsIStringBundle> sb;
|
|
nsresult rv = sbs->CreateBundle("chrome://global/locale/css.properties",
|
|
getter_AddRefs(sb));
|
|
if (NS_FAILED(rv) || !sb) {
|
|
return false;
|
|
}
|
|
|
|
cs.forget(&sConsoleService);
|
|
sf.forget(&sScriptErrorFactory);
|
|
sb.forget(&sStringBundle);
|
|
|
|
return true;
|
|
}
|
|
|
|
static inline bool
|
|
ShouldReportErrors()
|
|
{
|
|
if (!sConsoleService) {
|
|
if (!InitGlobals()) {
|
|
return false;
|
|
}
|
|
}
|
|
return sReportErrors;
|
|
}
|
|
|
|
namespace mozilla {
|
|
namespace css {
|
|
|
|
/* static */ void
|
|
ErrorReporter::ReleaseGlobals()
|
|
{
|
|
NS_IF_RELEASE(sConsoleService);
|
|
NS_IF_RELEASE(sScriptErrorFactory);
|
|
NS_IF_RELEASE(sStringBundle);
|
|
NS_IF_RELEASE(sSpecCache);
|
|
}
|
|
|
|
ErrorReporter::ErrorReporter(const nsCSSScanner& aScanner,
|
|
const CSSStyleSheet* aSheet,
|
|
const Loader* aLoader,
|
|
nsIURI* aURI)
|
|
: mScanner(&aScanner), mSheet(aSheet), mLoader(aLoader), mURI(aURI),
|
|
mInnerWindowID(0), mErrorLineNumber(0), mPrevErrorLineNumber(0),
|
|
mErrorColNumber(0)
|
|
{
|
|
}
|
|
|
|
ErrorReporter::~ErrorReporter()
|
|
{
|
|
// Schedule deferred cleanup for cached data. We want to strike a
|
|
// balance between performance and memory usage, so we only allow
|
|
// short-term caching.
|
|
if (sSpecCache && sSpecCache->IsInUse() && !sSpecCache->IsPending()) {
|
|
if (NS_FAILED(NS_DispatchToCurrentThread(sSpecCache))) {
|
|
// Peform the "deferred" cleanup immediately if the dispatch fails.
|
|
sSpecCache->Run();
|
|
} else {
|
|
sSpecCache->SetPending();
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
ErrorReporter::OutputError()
|
|
{
|
|
if (mError.IsEmpty()) {
|
|
return;
|
|
}
|
|
if (!ShouldReportErrors()) {
|
|
ClearError();
|
|
return;
|
|
}
|
|
|
|
if (mInnerWindowID == 0 && (mSheet || mLoader)) {
|
|
if (mSheet) {
|
|
mInnerWindowID = mSheet->FindOwningWindowInnerID();
|
|
}
|
|
if (mInnerWindowID == 0 && mLoader) {
|
|
nsIDocument* doc = mLoader->GetDocument();
|
|
if (doc) {
|
|
mInnerWindowID = doc->InnerWindowID();
|
|
}
|
|
}
|
|
// don't attempt this again, even if we failed
|
|
mSheet = nullptr;
|
|
mLoader = nullptr;
|
|
}
|
|
|
|
if (mFileName.IsEmpty()) {
|
|
if (mURI) {
|
|
if (!sSpecCache) {
|
|
sSpecCache = new ShortTermURISpecCache;
|
|
NS_ADDREF(sSpecCache);
|
|
}
|
|
mFileName = sSpecCache->GetSpec(mURI);
|
|
mURI = nullptr;
|
|
} else {
|
|
mFileName.AssignLiteral("from DOM");
|
|
}
|
|
}
|
|
|
|
nsresult rv;
|
|
nsCOMPtr<nsIScriptError> errorObject =
|
|
do_CreateInstance(sScriptErrorFactory, &rv);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
rv = errorObject->InitWithWindowID(mError,
|
|
mFileName,
|
|
mErrorLine,
|
|
mErrorLineNumber,
|
|
mErrorColNumber,
|
|
nsIScriptError::warningFlag,
|
|
"CSS Parser",
|
|
mInnerWindowID);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
sConsoleService->LogMessage(errorObject);
|
|
}
|
|
}
|
|
|
|
ClearError();
|
|
}
|
|
|
|
void
|
|
ErrorReporter::OutputError(uint32_t aLineNumber, uint32_t aLineOffset)
|
|
{
|
|
mErrorLineNumber = aLineNumber;
|
|
mErrorColNumber = aLineOffset;
|
|
OutputError();
|
|
}
|
|
|
|
void
|
|
ErrorReporter::ClearError()
|
|
{
|
|
mError.Truncate();
|
|
}
|
|
|
|
void
|
|
ErrorReporter::AddToError(const nsString &aErrorText)
|
|
{
|
|
if (!ShouldReportErrors()) return;
|
|
|
|
if (mError.IsEmpty()) {
|
|
mError = aErrorText;
|
|
mErrorLineNumber = mScanner->GetLineNumber();
|
|
mErrorColNumber = mScanner->GetColumnNumber();
|
|
// Retrieve the error line once per line, and reuse the same nsString
|
|
// for all errors on that line. That causes the text of the line to
|
|
// be shared among all the nsIScriptError objects.
|
|
if (mErrorLine.IsEmpty() || mErrorLineNumber != mPrevErrorLineNumber) {
|
|
mErrorLine = mScanner->GetCurrentLine();
|
|
mPrevErrorLineNumber = mErrorLineNumber;
|
|
}
|
|
} else {
|
|
mError.AppendLiteral(" ");
|
|
mError.Append(aErrorText);
|
|
}
|
|
}
|
|
|
|
void
|
|
ErrorReporter::ReportUnexpected(const char *aMessage)
|
|
{
|
|
if (!ShouldReportErrors()) return;
|
|
|
|
nsAutoString str;
|
|
sStringBundle->GetStringFromName(NS_ConvertASCIItoUTF16(aMessage).get(),
|
|
getter_Copies(str));
|
|
AddToError(str);
|
|
}
|
|
|
|
void
|
|
ErrorReporter::ReportUnexpected(const char *aMessage,
|
|
const nsString &aParam)
|
|
{
|
|
if (!ShouldReportErrors()) return;
|
|
|
|
nsAutoString qparam;
|
|
nsStyleUtil::AppendEscapedCSSIdent(aParam, qparam);
|
|
const char16_t *params[1] = { qparam.get() };
|
|
|
|
nsAutoString str;
|
|
sStringBundle->FormatStringFromName(NS_ConvertASCIItoUTF16(aMessage).get(),
|
|
params, ArrayLength(params),
|
|
getter_Copies(str));
|
|
AddToError(str);
|
|
}
|
|
|
|
void
|
|
ErrorReporter::ReportUnexpected(const char *aMessage,
|
|
const nsCSSToken &aToken)
|
|
{
|
|
if (!ShouldReportErrors()) return;
|
|
|
|
nsAutoString tokenString;
|
|
aToken.AppendToString(tokenString);
|
|
const char16_t *params[1] = { tokenString.get() };
|
|
|
|
nsAutoString str;
|
|
sStringBundle->FormatStringFromName(NS_ConvertASCIItoUTF16(aMessage).get(),
|
|
params, ArrayLength(params),
|
|
getter_Copies(str));
|
|
AddToError(str);
|
|
}
|
|
|
|
void
|
|
ErrorReporter::ReportUnexpected(const char *aMessage,
|
|
const nsCSSToken &aToken,
|
|
char16_t aChar)
|
|
{
|
|
if (!ShouldReportErrors()) return;
|
|
|
|
nsAutoString tokenString;
|
|
aToken.AppendToString(tokenString);
|
|
const char16_t charStr[2] = { aChar, 0 };
|
|
const char16_t *params[2] = { tokenString.get(), charStr };
|
|
|
|
nsAutoString str;
|
|
sStringBundle->FormatStringFromName(NS_ConvertASCIItoUTF16(aMessage).get(),
|
|
params, ArrayLength(params),
|
|
getter_Copies(str));
|
|
AddToError(str);
|
|
}
|
|
|
|
void
|
|
ErrorReporter::ReportUnexpectedEOF(const char *aMessage)
|
|
{
|
|
if (!ShouldReportErrors()) return;
|
|
|
|
nsAutoString innerStr;
|
|
sStringBundle->GetStringFromName(NS_ConvertASCIItoUTF16(aMessage).get(),
|
|
getter_Copies(innerStr));
|
|
const char16_t *params[1] = { innerStr.get() };
|
|
|
|
nsAutoString str;
|
|
sStringBundle->FormatStringFromName(MOZ_UTF16("PEUnexpEOF2"),
|
|
params, ArrayLength(params),
|
|
getter_Copies(str));
|
|
AddToError(str);
|
|
}
|
|
|
|
void
|
|
ErrorReporter::ReportUnexpectedEOF(char16_t aExpected)
|
|
{
|
|
if (!ShouldReportErrors()) return;
|
|
|
|
const char16_t expectedStr[] = {
|
|
char16_t('\''), aExpected, char16_t('\''), char16_t(0)
|
|
};
|
|
const char16_t *params[1] = { expectedStr };
|
|
|
|
nsAutoString str;
|
|
sStringBundle->FormatStringFromName(MOZ_UTF16("PEUnexpEOF2"),
|
|
params, ArrayLength(params),
|
|
getter_Copies(str));
|
|
AddToError(str);
|
|
}
|
|
|
|
} // namespace css
|
|
} // namespace mozilla
|
|
|
|
#endif
|