This commit is contained in:
Andrea Marchesini 2015-10-15 14:06:55 +02:00
parent c965ad64a0
commit ef38daea39
5 changed files with 83 additions and 36 deletions

View File

@ -316,7 +316,8 @@ private:
void
ShutdownScriptLoader(JSContext* aCx,
WorkerPrivate* aWorkerPrivate,
bool aResult);
bool aResult,
bool aMutedError);
};
class CacheScriptLoader;
@ -499,6 +500,7 @@ class ScriptLoaderRunnable final : public WorkerFeature,
WorkerScriptType mWorkerScriptType;
bool mCanceled;
bool mCanceledMainThread;
ErrorResult& mRv;
public:
NS_DECL_THREADSAFE_ISUPPORTS
@ -507,10 +509,11 @@ public:
nsIEventTarget* aSyncLoopTarget,
nsTArray<ScriptLoadInfo>& aLoadInfos,
bool aIsMainScript,
WorkerScriptType aWorkerScriptType)
WorkerScriptType aWorkerScriptType,
ErrorResult& aRv)
: mWorkerPrivate(aWorkerPrivate), mSyncLoopTarget(aSyncLoopTarget),
mIsMainScript(aIsMainScript), mWorkerScriptType(aWorkerScriptType),
mCanceled(false), mCanceledMainThread(false)
mCanceled(false), mCanceledMainThread(false), mRv(aRv)
{
aWorkerPrivate->AssertIsOnWorkerThread();
MOZ_ASSERT(aSyncLoopTarget);
@ -969,7 +972,7 @@ private:
principal = parentWorker->GetPrincipal();
}
aLoadInfo.mMutedErrorFlag.emplace(principal->Subsumes(channelPrincipal));
aLoadInfo.mMutedErrorFlag.emplace(!principal->Subsumes(channelPrincipal));
// Make sure we're not seeing the result of a 404 or something by checking
// the 'requestSucceeded' attribute on the http channel.
@ -1121,7 +1124,7 @@ private:
principal = parentWorker->GetPrincipal();
}
loadInfo.mMutedErrorFlag.emplace(principal->Subsumes(responsePrincipal));
loadInfo.mMutedErrorFlag.emplace(!principal->Subsumes(responsePrincipal));
// May be null.
nsIDocument* parentDoc = mWorkerPrivate->GetDocument();
@ -1769,14 +1772,16 @@ ScriptExecutorRunnable::PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
if (mLastIndex == loadInfos.Length() - 1) {
// All done. If anything failed then return false.
bool result = true;
bool mutedError = false;
for (uint32_t index = 0; index < loadInfos.Length(); index++) {
if (!loadInfos[index].mExecutionResult) {
mutedError = loadInfos[index].mMutedErrorFlag.valueOr(true);
result = false;
break;
}
}
ShutdownScriptLoader(aCx, aWorkerPrivate, result);
ShutdownScriptLoader(aCx, aWorkerPrivate, result, mutedError);
}
}
@ -1784,7 +1789,8 @@ NS_IMETHODIMP
ScriptExecutorRunnable::Cancel()
{
if (mLastIndex == mScriptLoader.mLoadInfos.Length() - 1) {
ShutdownScriptLoader(mWorkerPrivate->GetJSContext(), mWorkerPrivate, false);
ShutdownScriptLoader(mWorkerPrivate->GetJSContext(), mWorkerPrivate,
false, false);
}
return MainThreadWorkerSyncRunnable::Cancel();
}
@ -1792,7 +1798,8 @@ ScriptExecutorRunnable::Cancel()
void
ScriptExecutorRunnable::ShutdownScriptLoader(JSContext* aCx,
WorkerPrivate* aWorkerPrivate,
bool aResult)
bool aResult,
bool aMutedError)
{
MOZ_ASSERT(mLastIndex == mScriptLoader.mLoadInfos.Length() - 1);
@ -1800,14 +1807,25 @@ ScriptExecutorRunnable::ShutdownScriptLoader(JSContext* aCx,
aWorkerPrivate->SetLoadingWorkerScript(false);
}
if (!aResult) {
// If this error has to be muted, we have to clear the pending exception,
// if any, and use the ErrorResult object to throw a new exception.
if (aMutedError && JS_IsExceptionPending(aCx)) {
JS_ClearPendingException(aCx);
mScriptLoader.mRv.Throw(NS_ERROR_FAILURE);
} else {
mScriptLoader.mRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
}
}
aWorkerPrivate->RemoveFeature(aCx, &mScriptLoader);
aWorkerPrivate->StopSyncLoop(mSyncLoopTarget, aResult);
}
bool
void
LoadAllScripts(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
nsTArray<ScriptLoadInfo>& aLoadInfos, bool aIsMainScript,
WorkerScriptType aWorkerScriptType)
WorkerScriptType aWorkerScriptType, ErrorResult& aRv)
{
aWorkerPrivate->AssertIsOnWorkerThread();
NS_ASSERTION(!aLoadInfos.IsEmpty(), "Bad arguments!");
@ -1816,22 +1834,25 @@ LoadAllScripts(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
nsRefPtr<ScriptLoaderRunnable> loader =
new ScriptLoaderRunnable(aWorkerPrivate, syncLoop.EventTarget(),
aLoadInfos, aIsMainScript, aWorkerScriptType);
aLoadInfos, aIsMainScript, aWorkerScriptType,
aRv);
NS_ASSERTION(aLoadInfos.IsEmpty(), "Should have swapped!");
if (!aWorkerPrivate->AddFeature(aCx, loader)) {
return false;
aRv.Throw(NS_ERROR_FAILURE);
return;
}
if (NS_FAILED(NS_DispatchToMainThread(loader))) {
NS_ERROR("Failed to dispatch!");
aWorkerPrivate->RemoveFeature(aCx, loader);
return false;
aRv.Throw(NS_ERROR_FAILURE);
return;
}
return syncLoop.Run();
syncLoop.Run();
}
} /* anonymous namespace */
@ -1913,9 +1934,10 @@ void ReportLoadError(JSContext* aCx, nsresult aLoadResult)
}
}
bool
void
LoadMainScript(JSContext* aCx, const nsAString& aScriptURL,
WorkerScriptType aWorkerScriptType)
WorkerScriptType aWorkerScriptType,
ErrorResult& aRv)
{
WorkerPrivate* worker = GetWorkerPrivateFromContext(aCx);
NS_ASSERTION(worker, "This should never be null!");
@ -1925,7 +1947,7 @@ LoadMainScript(JSContext* aCx, const nsAString& aScriptURL,
ScriptLoadInfo* info = loadInfos.AppendElement();
info->mURL = aScriptURL;
return LoadAllScripts(aCx, worker, loadInfos, true, aWorkerScriptType);
LoadAllScripts(aCx, worker, loadInfos, true, aWorkerScriptType, aRv);
}
void
@ -1951,10 +1973,7 @@ Load(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
loadInfos[index].mURL = aScriptURLs[index];
}
if (!LoadAllScripts(aCx, aWorkerPrivate, loadInfos, false, aWorkerScriptType)) {
// LoadAllScripts can fail if we're shutting down.
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
}
LoadAllScripts(aCx, aWorkerPrivate, loadInfos, false, aWorkerScriptType, aRv);
}
} // namespace scriptloader

View File

@ -49,8 +49,9 @@ ChannelFromScriptURLWorkerThread(JSContext* aCx,
void ReportLoadError(JSContext* aCx, nsresult aLoadResult);
bool LoadMainScript(JSContext* aCx, const nsAString& aScriptURL,
WorkerScriptType aWorkerScriptType);
void LoadMainScript(JSContext* aCx, const nsAString& aScriptURL,
WorkerScriptType aWorkerScriptType,
ErrorResult& aRv);
void Load(JSContext* aCx,
WorkerPrivate* aWorkerPrivate,

View File

@ -491,7 +491,9 @@ private:
virtual bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
{
if (!scriptloader::LoadMainScript(aCx, mScriptURL, WorkerScript)) {
ErrorResult rv;
scriptloader::LoadMainScript(aCx, mScriptURL, WorkerScript, rv);
if (NS_WARN_IF(rv.Failed())) {
return false;
}
@ -524,8 +526,14 @@ private:
JS::Rooted<JSObject*> global(aCx, globalScope->GetWrapper());
ErrorResult rv;
JSAutoCompartment ac(aCx, global);
return scriptloader::LoadMainScript(aCx, mScriptURL, DebuggerScript);
scriptloader::LoadMainScript(aCx, mScriptURL, DebuggerScript, rv);
if (NS_WARN_IF(rv.Failed())) {
return false;
}
return true;
}
};
@ -842,6 +850,7 @@ class ReportErrorRunnable final : public WorkerRunnable
uint32_t mFlags;
uint32_t mErrorNumber;
JSExnType mExnType;
bool mMutedError;
public:
// aWorkerPrivate is the worker thread we're on (or the main thread, if null)
@ -853,12 +862,12 @@ public:
const nsString& aMessage, const nsString& aFilename,
const nsString& aLine, uint32_t aLineNumber,
uint32_t aColumnNumber, uint32_t aFlags,
uint32_t aErrorNumber, JSExnType aExnType, uint64_t aInnerWindowId)
uint32_t aErrorNumber, JSExnType aExnType,
bool aMutedError, uint64_t aInnerWindowId)
{
if (aWorkerPrivate) {
aWorkerPrivate->AssertIsOnWorkerThread();
}
else {
} else {
AssertIsOnMainThread();
}
@ -879,9 +888,15 @@ public:
if (!JSREPORT_IS_WARNING(aFlags)) {
// First fire an ErrorEvent at the worker.
RootedDictionary<ErrorEventInit> init(aCx);
init.mMessage = aMessage;
init.mFilename = aFilename;
init.mLineno = aLineNumber;
if (aMutedError) {
init.mMessage.AssignLiteral("Script error.");
} else {
init.mMessage = aMessage;
init.mFilename = aFilename;
init.mLineno = aLineNumber;
}
init.mCancelable = true;
init.mBubbles = false;
@ -958,7 +973,7 @@ public:
nsRefPtr<ReportErrorRunnable> runnable =
new ReportErrorRunnable(aWorkerPrivate, aMessage, aFilename, aLine,
aLineNumber, aColumnNumber, aFlags,
aErrorNumber, aExnType);
aErrorNumber, aExnType, aMutedError);
return runnable->Dispatch(aCx);
}
@ -973,11 +988,11 @@ private:
const nsString& aFilename, const nsString& aLine,
uint32_t aLineNumber, uint32_t aColumnNumber,
uint32_t aFlags, uint32_t aErrorNumber,
JSExnType aExnType)
JSExnType aExnType, bool aMutedError)
: WorkerRunnable(aWorkerPrivate, ParentThreadUnchangedBusyCount),
mMessage(aMessage), mFilename(aFilename), mLine(aLine),
mLineNumber(aLineNumber), mColumnNumber(aColumnNumber), mFlags(aFlags),
mErrorNumber(aErrorNumber), mExnType(aExnType)
mErrorNumber(aErrorNumber), mExnType(aExnType), mMutedError(aMutedError)
{ }
virtual void
@ -1051,7 +1066,7 @@ private:
return ReportError(aCx, parent, fireAtScope, aWorkerPrivate, mMessage,
mFilename, mLine, mLineNumber, mColumnNumber, mFlags,
mErrorNumber, mExnType, innerWindowId);
mErrorNumber, mExnType, mMutedError, innerWindowId);
}
};
@ -5708,6 +5723,7 @@ WorkerPrivate::ReportError(JSContext* aCx, const char* aMessage,
nsString message, filename, line;
uint32_t lineNumber, columnNumber, flags, errorNumber;
JSExnType exnType = JSEXN_ERR;
bool mutedError = aReport && aReport->isMuted;
if (aReport) {
// ErrorEvent objects don't have a |name| field the way ES |Error| objects
@ -5752,7 +5768,8 @@ WorkerPrivate::ReportError(JSContext* aCx, const char* aMessage,
if (!ReportErrorRunnable::ReportError(aCx, this, fireAtScope, nullptr, message,
filename, line, lineNumber,
columnNumber, flags, errorNumber, exnType, 0)) {
columnNumber, flags, errorNumber, exnType,
mutedError, 0)) {
JS_ReportPendingException(aCx);
}

View File

@ -0,0 +1,4 @@
[004.html]
type: testharness
[importScripts broken script]
expected: FAIL

View File

@ -0,0 +1,6 @@
[006.html]
type: testharness
expected: ERROR
[importScripts uncaught exception]
expected: TIMEOUT