mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 1160890
, r=smaug
This commit is contained in:
parent
c965ad64a0
commit
ef38daea39
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,4 @@
|
||||
[004.html]
|
||||
type: testharness
|
||||
[importScripts broken script]
|
||||
expected: FAIL
|
@ -0,0 +1,6 @@
|
||||
[006.html]
|
||||
type: testharness
|
||||
expected: ERROR
|
||||
[importScripts uncaught exception]
|
||||
expected: TIMEOUT
|
||||
|
Loading…
Reference in New Issue
Block a user