mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 786108 - Cache UTF-16 version of URI to prevent repeated conversions in the CSS scanner, and free the cache after a short time. r=bz
This commit is contained in:
parent
803b082135
commit
ed479625af
22
layout/style/crashtests/786108-1.html
Normal file
22
layout/style/crashtests/786108-1.html
Normal file
@ -0,0 +1,22 @@
|
||||
<html>
|
||||
<head></head>
|
||||
<body></body>
|
||||
<script type="text/javascript">
|
||||
// Detect severe performance and memory issues when large amounts of errors
|
||||
// are reported from CSS embedded in a file with a long data URI. Addressed
|
||||
// by 786108; should finish quickly with that patch and run for a very long
|
||||
// time otherwise.
|
||||
|
||||
var img = new Array;
|
||||
img.push('<img src="data:image/svg+xml,');
|
||||
img.push(encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300px" height="300px">'));
|
||||
|
||||
for (var i = 0 ; i < 10000 ; i++)
|
||||
img.push(encodeURIComponent('<circle cx="0" cy="0" r="1" style="xxx-invalid-property: 0;"/>'));
|
||||
|
||||
img.push(encodeURIComponent('</svg>'));
|
||||
img.push('">');
|
||||
|
||||
document.getElementsByTagName('body')[0].innerHTML = img.join('');
|
||||
</script>
|
||||
</html>
|
23
layout/style/crashtests/786108-2.html
Normal file
23
layout/style/crashtests/786108-2.html
Normal file
@ -0,0 +1,23 @@
|
||||
<html>
|
||||
<head></head>
|
||||
<body></body>
|
||||
<script type="text/javascript">
|
||||
// Detect severe performance and memory issues when large amounts of errors
|
||||
// are reported from CSS embedded in a file with a long data URI. Addressed
|
||||
// by 786108; should finish quickly with that patch and run for a very long
|
||||
// time otherwise. This version is designed for slow / memory constrained
|
||||
// platforms like Android.
|
||||
|
||||
var img = new Array;
|
||||
img.push('<img src="data:image/svg+xml,');
|
||||
img.push(encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300px" height="300px">'));
|
||||
|
||||
for (var i = 0 ; i < 2500 ; i++)
|
||||
img.push(encodeURIComponent('<circle cx="0" cy="0" r="1" style="xxx-invalid-property: 0;"/>'));
|
||||
|
||||
img.push(encodeURIComponent('</svg>'));
|
||||
img.push('">');
|
||||
|
||||
document.getElementsByTagName('body')[0].innerHTML = img.join('');
|
||||
</script>
|
||||
</html>
|
@ -77,4 +77,6 @@ load 696188-1.html
|
||||
load 700116.html
|
||||
load 729126-1.html
|
||||
load 729126-2.html
|
||||
skip-if(Android||browserIsRemote) load 786108-1.html # Bug 795534
|
||||
skip-if(browserIsRemote) load 786108-2.html # Bug 795534
|
||||
load 788836.html
|
||||
|
@ -249,6 +249,29 @@ nsCSSToken::AppendToString(nsString& aBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
class DeferredCleanupRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
DeferredCleanupRunnable(nsCSSScanner* aToClean)
|
||||
: mToClean(aToClean)
|
||||
{}
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
if (mToClean) {
|
||||
mToClean->PerformDeferredCleanup();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void Revoke() {
|
||||
mToClean = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
nsCSSScanner* mToClean;
|
||||
};
|
||||
|
||||
nsCSSScanner::nsCSSScanner()
|
||||
: mReadPointer(nullptr)
|
||||
, mSVGMode(false)
|
||||
@ -271,13 +294,24 @@ nsCSSScanner::nsCSSScanner()
|
||||
nsCSSScanner::~nsCSSScanner()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsCSSScanner);
|
||||
Close();
|
||||
Reset();
|
||||
if (mLocalPushback != mPushback) {
|
||||
delete [] mPushback;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CSS_REPORT_PARSE_ERRORS
|
||||
void
|
||||
nsCSSScanner::PerformDeferredCleanup()
|
||||
{
|
||||
// Clean up all short term caches.
|
||||
mCachedURI = nullptr;
|
||||
mCachedFileName.Truncate();
|
||||
|
||||
// Release our DeferredCleanupRunnable.
|
||||
mDeferredCleaner.Forget();
|
||||
}
|
||||
|
||||
#define CSS_ERRORS_PREF "layout.css.report_errors"
|
||||
|
||||
static int
|
||||
@ -331,17 +365,13 @@ nsCSSScanner::Init(const nsAString& aBuffer,
|
||||
mCount = aBuffer.Length();
|
||||
|
||||
#ifdef CSS_REPORT_PARSE_ERRORS
|
||||
// If aURI is the same as mURI, no need to reget mFileName -- it
|
||||
// shouldn't have changed.
|
||||
if (aURI != mURI) {
|
||||
mURI = aURI;
|
||||
if (aURI) {
|
||||
aURI->GetSpec(mFileName);
|
||||
} else {
|
||||
mFileName.Adopt(NS_strdup("from DOM"));
|
||||
}
|
||||
// If aURI is different from mCachedURI, invalidate the filename cache.
|
||||
if (aURI != mCachedURI) {
|
||||
mCachedURI = aURI;
|
||||
mCachedFileName.Truncate();
|
||||
}
|
||||
#endif // CSS_REPORT_PARSE_ERRORS
|
||||
|
||||
mLineNumber = aLineNumber;
|
||||
|
||||
// Reset variables that we use to keep track of our progress through the input
|
||||
@ -406,8 +436,19 @@ nsCSSScanner::OutputError()
|
||||
do_CreateInstance(gScriptErrorFactory, &rv);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Update the cached filename if needed.
|
||||
if (mCachedFileName.IsEmpty()) {
|
||||
if (mCachedURI) {
|
||||
nsAutoCString cFileName;
|
||||
mCachedURI->GetSpec(cFileName);
|
||||
CopyUTF8toUTF16(cFileName, mCachedFileName);
|
||||
} else {
|
||||
mCachedFileName.AssignLiteral("from DOM");
|
||||
}
|
||||
}
|
||||
|
||||
rv = errorObject->InitWithWindowID(mError,
|
||||
NS_ConvertUTF8toUTF16(mFileName),
|
||||
mCachedFileName,
|
||||
EmptyString(),
|
||||
mErrorLineNumber,
|
||||
mErrorColNumber,
|
||||
@ -554,19 +595,37 @@ nsCSSScanner::ReportUnexpectedTokenParams(nsCSSToken& tok,
|
||||
|
||||
void
|
||||
nsCSSScanner::Close()
|
||||
{
|
||||
Reset();
|
||||
|
||||
// Schedule deferred cleanup for cached data. We want to strike a balance
|
||||
// between performance and memory usage, so we only allow short-term caching.
|
||||
#ifdef CSS_REPORT_PARSE_ERRORS
|
||||
if (!mDeferredCleaner.IsPending()) {
|
||||
mDeferredCleaner = new DeferredCleanupRunnable(this);
|
||||
if (NS_FAILED(NS_DispatchToCurrentThread(mDeferredCleaner.get()))) {
|
||||
// Peform the "deferred" cleanup immediately if the dispatch fails.
|
||||
// This will also have the effect of clearing mDeferredCleaner.
|
||||
nsCSSScanner::PerformDeferredCleanup();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
nsCSSScanner::Reset()
|
||||
{
|
||||
mReadPointer = nullptr;
|
||||
|
||||
// Clean things up so we don't hold on to memory if our parser gets recycled.
|
||||
#ifdef CSS_REPORT_PARSE_ERRORS
|
||||
mFileName.Truncate();
|
||||
mURI = nullptr;
|
||||
mError.Truncate();
|
||||
mInnerWindowID = 0;
|
||||
mWindowIDCached = false;
|
||||
mSheet = nullptr;
|
||||
mLoader = nullptr;
|
||||
#endif
|
||||
|
||||
if (mPushback != mLocalPushback) {
|
||||
delete [] mPushback;
|
||||
mPushback = mLocalPushback;
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
// for #ifdef CSS_REPORT_PARSE_ERRORS
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsThreadUtils.h"
|
||||
class nsIURI;
|
||||
|
||||
// Token types
|
||||
@ -91,6 +92,8 @@ struct nsCSSToken {
|
||||
void AppendToString(nsString& aBuffer);
|
||||
};
|
||||
|
||||
class DeferredCleanupRunnable;
|
||||
|
||||
// CSS Scanner API. Used to tokenize an input stream using the CSS
|
||||
// forward compatible tokenization rules. This implementation is
|
||||
// private to this package and is only used internally by the css
|
||||
@ -120,6 +123,9 @@ class nsCSSScanner {
|
||||
}
|
||||
|
||||
#ifdef CSS_REPORT_PARSE_ERRORS
|
||||
// Clean up any reclaimable cached resources.
|
||||
void PerformDeferredCleanup();
|
||||
|
||||
void AddToError(const nsSubstring& aErrorText);
|
||||
void OutputError();
|
||||
void ClearError();
|
||||
@ -128,6 +134,8 @@ class nsCSSScanner {
|
||||
void ReportUnexpected(const char* aMessage);
|
||||
|
||||
private:
|
||||
void Reset();
|
||||
|
||||
void ReportUnexpectedParams(const char* aMessage,
|
||||
const PRUnichar** aParams,
|
||||
uint32_t aParamsLength);
|
||||
@ -211,8 +219,9 @@ protected:
|
||||
uint32_t mRecordStartOffset;
|
||||
|
||||
#ifdef CSS_REPORT_PARSE_ERRORS
|
||||
nsXPIDLCString mFileName;
|
||||
nsCOMPtr<nsIURI> mURI; // Cached so we know to not refetch mFileName
|
||||
nsRevocableEventPtr<DeferredCleanupRunnable> mDeferredCleaner;
|
||||
nsCOMPtr<nsIURI> mCachedURI; // Used to invalidate the cached filename.
|
||||
nsString mCachedFileName;
|
||||
uint32_t mErrorLineNumber, mColNumber, mErrorColNumber;
|
||||
nsFixedString mError;
|
||||
PRUnichar mErrorBuf[200];
|
||||
|
Loading…
Reference in New Issue
Block a user