Bug 987556 Part 5 Use JS::SourceBufferHolder in nsScriptLoader. r=bz

This commit is contained in:
Ben Kelly 2014-04-25 10:11:56 -04:00
parent add3a9cc4a
commit a13edfd03a
2 changed files with 90 additions and 18 deletions

View File

@ -76,12 +76,21 @@ public:
mLoading(true),
mIsInline(true),
mHasSourceMapURL(false),
mScriptTextBuf(nullptr),
mScriptTextLength(0),
mJSVersion(aVersion),
mLineNo(1),
mCORSMode(aCORSMode)
{
}
~nsScriptLoadRequest()
{
if (mScriptTextBuf) {
js_free(mScriptTextBuf);
}
}
NS_DECL_THREADSAFE_ISUPPORTS
void FireScriptAvailable(nsresult aResult)
@ -103,7 +112,8 @@ public:
bool mIsInline; // Is the script inline or loaded?
bool mHasSourceMapURL; // Does the HTTP header have a source map url?
nsString mSourceMapURL; // Holds source map url for loaded scripts
nsString mScriptText; // Holds script for text loaded scripts
jschar* mScriptTextBuf; // Holds script text for non-inline scripts. Don't
size_t mScriptTextLength; // use nsString so we can give ownership to jsapi.
uint32_t mJSVersion;
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIPrincipal> mOriginPrincipal;
@ -851,7 +861,7 @@ nsScriptLoader::AttemptAsyncScriptParse(nsScriptLoadRequest* aRequest)
JS::CompileOptions options(cx);
FillCompileOptionsForRequest(aRequest, global, &options);
if (!JS::CanCompileOffThread(cx, options, aRequest->mScriptText.Length())) {
if (!JS::CanCompileOffThread(cx, options, aRequest->mScriptTextLength)) {
return NS_ERROR_FAILURE;
}
@ -859,7 +869,7 @@ nsScriptLoader::AttemptAsyncScriptParse(nsScriptLoadRequest* aRequest)
new NotifyOffThreadScriptLoadCompletedRunnable(aRequest, this);
if (!JS::CompileOffThread(cx, options,
aRequest->mScriptText.get(), aRequest->mScriptText.Length(),
aRequest->mScriptTextBuf, aRequest->mScriptTextLength,
OffThreadScriptLoaderCallback,
static_cast<void*>(runnable))) {
return NS_ERROR_OUT_OF_MEMORY;
@ -884,8 +894,11 @@ nsScriptLoader::ProcessRequest(nsScriptLoadRequest* aRequest, void **aOffThreadT
}
NS_ENSURE_ARG(aRequest);
nsAFlatString* script;
nsAutoString textData;
const jschar* scriptBuf = nullptr;
size_t scriptLength = 0;
JS::SourceBufferHolder::Ownership giveScriptOwnership =
JS::SourceBufferHolder::NoOwnership;
nsCOMPtr<nsIDocument> doc;
@ -897,14 +910,23 @@ nsScriptLoader::ProcessRequest(nsScriptLoadRequest* aRequest, void **aOffThreadT
// copies.
aRequest->mElement->GetScriptText(textData);
script = &textData;
scriptBuf = textData.get();
scriptLength = textData.Length();
giveScriptOwnership = JS::SourceBufferHolder::NoOwnership;
}
else {
script = &aRequest->mScriptText;
scriptBuf = aRequest->mScriptTextBuf;
scriptLength = aRequest->mScriptTextLength;
giveScriptOwnership = JS::SourceBufferHolder::GiveOwnership;
aRequest->mScriptTextBuf = nullptr;
aRequest->mScriptTextLength = 0;
doc = scriptElem->OwnerDoc();
}
JS::SourceBufferHolder srcBuf(scriptBuf, scriptLength, giveScriptOwnership);
nsCOMPtr<nsIScriptElement> oldParserInsertedScript;
uint32_t parserCreated = aRequest->mElement->GetParserCreated();
if (parserCreated) {
@ -937,7 +959,7 @@ nsScriptLoader::ProcessRequest(nsScriptLoadRequest* aRequest, void **aOffThreadT
doc->BeginEvaluatingExternalScript();
}
aRequest->mElement->BeginEvaluating();
rv = EvaluateScript(aRequest, *script, aOffThreadToken);
rv = EvaluateScript(aRequest, srcBuf, aOffThreadToken);
aRequest->mElement->EndEvaluating();
if (doc) {
doc->EndEvaluatingExternalScript();
@ -1044,7 +1066,7 @@ nsScriptLoader::FillCompileOptionsForRequest(nsScriptLoadRequest *aRequest,
nsresult
nsScriptLoader::EvaluateScript(nsScriptLoadRequest* aRequest,
const nsAFlatString& aScript,
JS::SourceBufferHolder& aSrcBuf,
void** aOffThreadToken)
{
// We need a document to evaluate scripts.
@ -1095,7 +1117,7 @@ nsScriptLoader::EvaluateScript(nsScriptLoadRequest* aRequest,
JS::CompileOptions options(entryScript.cx());
FillCompileOptionsForRequest(aRequest, global, &options);
nsresult rv = nsJSUtils::EvaluateString(entryScript.cx(), aScript, global, options,
nsresult rv = nsJSUtils::EvaluateString(entryScript.cx(), aSrcBuf, global, options,
aOffThreadToken);
// Put the old script back in case it wants to do anything else.
@ -1246,10 +1268,12 @@ DetectByteOrderMark(const unsigned char* aBytes, int32_t aLen, nsCString& oChars
/* static */ nsresult
nsScriptLoader::ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData,
uint32_t aLength, const nsAString& aHintCharset,
nsIDocument* aDocument, nsString& aString)
nsIDocument* aDocument,
jschar*& aBufOut, size_t& aLengthOut)
{
if (!aLength) {
aString.Truncate();
aBufOut = nullptr;
aLengthOut = 0;
return NS_OK;
}
@ -1302,17 +1326,40 @@ nsScriptLoader::ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData,
aLength, &unicodeLength);
NS_ENSURE_SUCCESS(rv, rv);
if (!aString.SetLength(unicodeLength, fallible_t())) {
aBufOut = static_cast<jschar*>(js_malloc(unicodeLength * sizeof(jschar)));
if (!aBufOut) {
aLengthOut = 0;
return NS_ERROR_OUT_OF_MEMORY;
}
char16_t *ustr = aString.BeginWriting();
aLengthOut = unicodeLength;
rv = unicodeDecoder->Convert(reinterpret_cast<const char*>(aData),
(int32_t *) &aLength, ustr,
(int32_t *) &aLength, aBufOut,
&unicodeLength);
MOZ_ASSERT(NS_SUCCEEDED(rv));
aString.SetLength(unicodeLength);
aLengthOut = unicodeLength;
if (NS_FAILED(rv)) {
js_free(aBufOut);
aBufOut = nullptr;
aLengthOut = 0;
}
return rv;
}
/* static */ nsresult
nsScriptLoader::ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData,
uint32_t aLength, const nsAString& aHintCharset,
nsIDocument* aDocument, nsString& aString)
{
jschar* bufOut = nullptr;
size_t lengthOut = 0;
nsresult rv = ConvertToUTF16(aChannel, aData, aLength, aHintCharset,
aDocument, bufOut, lengthOut);
aString.SetLength(lengthOut);
if (bufOut) {
memcpy(aString.BeginWriting(), bufOut, lengthOut * sizeof(jschar));
js_free(bufOut);
}
return rv;
}
@ -1426,7 +1473,7 @@ nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
hintCharset = mPreloads[i].mCharset;
}
rv = ConvertToUTF16(channel, aString, aStringLen, hintCharset, mDocument,
aRequest->mScriptText);
aRequest->mScriptTextBuf, aRequest->mScriptTextLength);
NS_ENSURE_SUCCESS(rv, rv);
}

View File

@ -21,6 +21,10 @@
class nsScriptLoadRequest;
class nsIURI;
namespace JS {
class SourceBufferHolder;
}
//////////////////////////////////////////////////////////////
// Script loader implementation
//////////////////////////////////////////////////////////////
@ -131,6 +135,27 @@ public:
}
}
/**
* Convert the given buffer to a UTF-16 string.
* @param aChannel Channel corresponding to the data. May be null.
* @param aData The data to convert
* @param aLength Length of the data
* @param aHintCharset Hint for the character set (e.g., from a charset
* attribute). May be the empty string.
* @param aDocument Document which the data is loaded for. Must not be
* null.
* @param aBufOut [out] jschar array allocated by ConvertToUTF16 and
* containing data converted to unicode. Caller must
* js_free() this data when no longer needed.
* @param aLengthOut [out] Length of array returned in aBufOut in number
* of jschars.
*/
static nsresult ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData,
uint32_t aLength,
const nsAString& aHintCharset,
nsIDocument* aDocument,
jschar*& aBufOut, size_t& aLengthOut);
/**
* Convert the given buffer to a UTF-16 string.
* @param aChannel Channel corresponding to the data. May be null.
@ -277,7 +302,7 @@ private:
void FireScriptEvaluated(nsresult aResult,
nsScriptLoadRequest* aRequest);
nsresult EvaluateScript(nsScriptLoadRequest* aRequest,
const nsAFlatString& aScript,
JS::SourceBufferHolder& aSrcBuf,
void **aOffThreadToken);
already_AddRefed<nsIScriptGlobalObject> GetScriptGlobalObject();