зеркало из https://github.com/mozilla/gecko-dev.git
180 строки
6.5 KiB
C++
180 строки
6.5 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* 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/. */
|
|
|
|
#include "TimeoutHandler.h"
|
|
|
|
#include "mozilla/Assertions.h"
|
|
#include "nsJSUtils.h"
|
|
|
|
namespace mozilla {
|
|
namespace dom {
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// TimeoutHandler
|
|
//-----------------------------------------------------------------------------
|
|
|
|
TimeoutHandler::TimeoutHandler(JSContext* aCx) : TimeoutHandler() {
|
|
nsJSUtils::GetCallingLocation(aCx, mFileName, &mLineNo, &mColumn);
|
|
}
|
|
|
|
bool TimeoutHandler::Call(const char* /* unused */) { return false; }
|
|
|
|
void TimeoutHandler::GetLocation(const char** aFileName, uint32_t* aLineNo,
|
|
uint32_t* aColumn) {
|
|
*aFileName = mFileName.get();
|
|
*aLineNo = mLineNo;
|
|
*aColumn = mColumn;
|
|
}
|
|
|
|
void TimeoutHandler::GetDescription(nsACString& aOutString) {
|
|
aOutString.AppendPrintf("<generic handler> (%s:%d:%d)", mFileName.get(),
|
|
mLineNo, mColumn);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// ScriptTimeoutHandler
|
|
//-----------------------------------------------------------------------------
|
|
|
|
ScriptTimeoutHandler::ScriptTimeoutHandler(JSContext* aCx,
|
|
nsIGlobalObject* aGlobal,
|
|
const nsAString& aExpression)
|
|
: TimeoutHandler(aCx), mGlobal(aGlobal), mExpr(aExpression) {}
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(ScriptTimeoutHandler)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ScriptTimeoutHandler)
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal)
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(ScriptTimeoutHandler)
|
|
if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
|
|
nsAutoCString name("ScriptTimeoutHandler");
|
|
name.AppendLiteral(" [");
|
|
name.Append(tmp->mFileName);
|
|
name.Append(':');
|
|
name.AppendInt(tmp->mLineNo);
|
|
name.Append(':');
|
|
name.AppendInt(tmp->mColumn);
|
|
name.Append(']');
|
|
cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name.get());
|
|
} else {
|
|
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(ScriptTimeoutHandler, tmp->mRefCnt.get())
|
|
}
|
|
|
|
// If we need to make TimeoutHandler CCed, don't call its Traverse method
|
|
// here, otherwise we ends up report same object twice if logging is on. See
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=1588208.
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ScriptTimeoutHandler)
|
|
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
|
NS_INTERFACE_MAP_END
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(ScriptTimeoutHandler)
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(ScriptTimeoutHandler)
|
|
|
|
void ScriptTimeoutHandler::GetDescription(nsACString& aOutString) {
|
|
if (mExpr.Length() > 15) {
|
|
aOutString.AppendPrintf(
|
|
"<string handler (truncated): \"%s...\"> (%s:%d:%d)",
|
|
NS_ConvertUTF16toUTF8(Substring(mExpr, 0, 13)).get(), mFileName.get(),
|
|
mLineNo, mColumn);
|
|
} else {
|
|
aOutString.AppendPrintf("<string handler: \"%s\"> (%s:%d:%d)",
|
|
NS_ConvertUTF16toUTF8(mExpr).get(), mFileName.get(),
|
|
mLineNo, mColumn);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// CallbackTimeoutHandler
|
|
//-----------------------------------------------------------------------------
|
|
|
|
CallbackTimeoutHandler::CallbackTimeoutHandler(
|
|
JSContext* aCx, nsIGlobalObject* aGlobal, Function* aFunction,
|
|
nsTArray<JS::Heap<JS::Value>>&& aArguments)
|
|
: TimeoutHandler(aCx), mGlobal(aGlobal), mFunction(aFunction) {
|
|
mozilla::HoldJSObjects(this);
|
|
mArgs = std::move(aArguments);
|
|
}
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_MULTI_ZONE_JSHOLDER_CLASS(CallbackTimeoutHandler)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CallbackTimeoutHandler)
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal)
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFunction)
|
|
tmp->ReleaseJSObjects();
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(CallbackTimeoutHandler)
|
|
if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
|
|
nsAutoCString name("CallbackTimeoutHandler");
|
|
JSObject* obj = tmp->mFunction->CallablePreserveColor();
|
|
JSFunction* fun =
|
|
JS_GetObjectFunction(js::UncheckedUnwrapWithoutExpose(obj));
|
|
if (fun && JS_GetFunctionId(fun)) {
|
|
JSLinearString* funId = JS_ASSERT_STRING_IS_LINEAR(JS_GetFunctionId(fun));
|
|
size_t size = 1 + JS_PutEscapedLinearString(nullptr, 0, funId, 0);
|
|
char* funIdName = new char[size];
|
|
if (funIdName) {
|
|
JS_PutEscapedLinearString(funIdName, size, funId, 0);
|
|
name.AppendLiteral(" [");
|
|
name.Append(funIdName);
|
|
delete[] funIdName;
|
|
name.Append(']');
|
|
}
|
|
}
|
|
cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name.get());
|
|
} else {
|
|
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(CallbackTimeoutHandler,
|
|
tmp->mRefCnt.get())
|
|
}
|
|
|
|
// If we need to make TimeoutHandler CCed, don't call its Traverse method
|
|
// here, otherwise we ends up report same object twice if logging is on. See
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=1588208.
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFunction)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(CallbackTimeoutHandler)
|
|
for (size_t i = 0; i < tmp->mArgs.Length(); ++i) {
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mArgs[i])
|
|
}
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CallbackTimeoutHandler)
|
|
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
|
NS_INTERFACE_MAP_END
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(CallbackTimeoutHandler)
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(CallbackTimeoutHandler)
|
|
|
|
void CallbackTimeoutHandler::ReleaseJSObjects() {
|
|
mArgs.Clear();
|
|
mozilla::DropJSObjects(this);
|
|
}
|
|
|
|
bool CallbackTimeoutHandler::Call(const char* aExecutionReason) {
|
|
IgnoredErrorResult rv;
|
|
JS::Rooted<JS::Value> ignoredVal(RootingCx());
|
|
MOZ_KnownLive(mFunction)->Call(MOZ_KnownLive(mGlobal), mArgs, &ignoredVal, rv,
|
|
aExecutionReason);
|
|
return !rv.IsUncatchableException();
|
|
}
|
|
|
|
void CallbackTimeoutHandler::MarkForCC() { mFunction->MarkForCC(); }
|
|
|
|
void CallbackTimeoutHandler::GetDescription(nsACString& aOutString) {
|
|
mFunction->GetDescription(aOutString);
|
|
}
|
|
|
|
} // namespace dom
|
|
} // namespace mozilla
|