mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-27 02:47:31 +09:00
Merge remote-tracking branch 'origin/tracking' into custom
This commit is contained in:
commit
b0345ff809
35 changed files with 789 additions and 133 deletions
|
|
@ -80,7 +80,14 @@ DOMIntersectionObserver::Constructor(const mozilla::dom::GlobalObject& aGlobal,
|
|||
RefPtr<DOMIntersectionObserver> observer =
|
||||
new DOMIntersectionObserver(window.forget(), aCb);
|
||||
|
||||
observer->mRoot = aOptions.mRoot;
|
||||
if (!aOptions.mRoot.IsNull()) {
|
||||
if (aOptions.mRoot.Value().IsElement()) {
|
||||
observer->mRoot = aOptions.mRoot.Value().GetAsElement();
|
||||
} else {
|
||||
MOZ_ASSERT(aOptions.mRoot.Value().IsDocument());
|
||||
observer->mRoot = aOptions.mRoot.Value().GetAsDocument();
|
||||
}
|
||||
}
|
||||
|
||||
if (!observer->SetRootMargin(aOptions.mRootMargin)) {
|
||||
aRv.ThrowDOMException(NS_ERROR_DOM_SYNTAX_ERR,
|
||||
|
|
@ -258,6 +265,30 @@ EdgeInclusiveIntersection(const nsRect& aRect, const nsRect& aOtherRect)
|
|||
return Some(nsRect(left, top, right - left, bottom - top));
|
||||
}
|
||||
|
||||
// NOTE: This returns nullptr if |aDocument| is in a cross process.
|
||||
static nsIDocument* GetTopLevelDocument(const nsIDocument& aDocument) {
|
||||
nsCOMPtr<nsIPresShell> presShell = aDocument.GetShell();
|
||||
|
||||
if (presShell) {
|
||||
nsIFrame* rootFrame = presShell->GetRootScrollFrame();
|
||||
if (rootFrame) {
|
||||
nsPresContext* presContext = rootFrame->PresContext();
|
||||
while (!presContext->IsRootContentDocument()) {
|
||||
// Walk up the tree
|
||||
presContext = presContext->GetParentPresContext();
|
||||
if (!presContext) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(presContext && presContext->IsRootContentDocument()) {
|
||||
return presContext->Document();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
enum class BrowsingContextInfo {
|
||||
SimilarOriginBrowsingContext,
|
||||
DifferentOriginBrowsingContext,
|
||||
|
|
@ -267,14 +298,12 @@ enum class BrowsingContextInfo {
|
|||
void
|
||||
DOMIntersectionObserver::Update(nsIDocument* aDocument, DOMHighResTimeStamp time)
|
||||
{
|
||||
Element* root = nullptr;
|
||||
nsINode* root = mRoot;
|
||||
nsIFrame* rootFrame = nullptr;
|
||||
nsRect rootRect;
|
||||
|
||||
if (mRoot) {
|
||||
root = mRoot;
|
||||
rootFrame = root->GetPrimaryFrame();
|
||||
if (rootFrame) {
|
||||
if (mRoot && mRoot->IsElement()) {
|
||||
if ((rootFrame = mRoot->AsElement()->GetPrimaryFrame())) {
|
||||
nsRect rootRectRelativeToRootFrame;
|
||||
if (rootFrame->GetType() == nsGkAtoms::scrollFrame) {
|
||||
// rootRectRelativeToRootFrame should be the content rect of rootFrame, not including the scrollbars.
|
||||
|
|
@ -292,30 +321,18 @@ DOMIntersectionObserver::Update(nsIDocument* aDocument, DOMHighResTimeStamp time
|
|||
containingBlock);
|
||||
}
|
||||
} else {
|
||||
nsCOMPtr<nsIPresShell> presShell = aDocument->GetShell();
|
||||
if (presShell) {
|
||||
rootFrame = presShell->GetRootScrollFrame();
|
||||
if (rootFrame) {
|
||||
nsPresContext* presContext = rootFrame->PresContext();
|
||||
while (!presContext->IsRootContentDocument()) {
|
||||
// Walk up the tree
|
||||
presContext = presContext->GetParentPresContext();
|
||||
if (!presContext) {
|
||||
break;
|
||||
MOZ_ASSERT(!mRoot || mRoot->IsInUncomposedDoc());
|
||||
nsIDocument* rootDocument =
|
||||
mRoot ? mRoot->GetUncomposedDoc() : GetTopLevelDocument(*aDocument);
|
||||
if (rootDocument) {
|
||||
if (nsIPresShell* presShell = rootDocument->GetShell()) {
|
||||
rootFrame = presShell->GetRootScrollFrame();
|
||||
if (rootFrame) {
|
||||
root = rootFrame->GetContent()->AsElement();
|
||||
nsIScrollableFrame* scrollFrame = do_QueryFrame(rootFrame);
|
||||
if (scrollFrame) {
|
||||
rootRect = scrollFrame->GetScrollPortRect();
|
||||
}
|
||||
nsIFrame* rootScrollFrame = presContext->PresShell()->GetRootScrollFrame();
|
||||
if (rootScrollFrame) {
|
||||
rootFrame = rootScrollFrame;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
root = rootFrame->GetContent()->AsElement();
|
||||
nsIScrollableFrame* scrollFrame = do_QueryFrame(rootFrame);
|
||||
// If we end up with a null root frame for some reason, we'll proceed
|
||||
// with an empty root intersection rect.
|
||||
if (scrollFrame) {
|
||||
rootRect = scrollFrame->GetScrollPortRect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ public:
|
|||
return mOwner;
|
||||
}
|
||||
|
||||
Element* GetRoot() const {
|
||||
nsINode* GetRoot() const {
|
||||
return mRoot;
|
||||
}
|
||||
|
||||
|
|
@ -178,7 +178,7 @@ protected:
|
|||
nsCOMPtr<nsPIDOMWindowInner> mOwner;
|
||||
RefPtr<nsIDocument> mDocument;
|
||||
RefPtr<mozilla::dom::IntersectionCallback> mCallback;
|
||||
RefPtr<Element> mRoot;
|
||||
RefPtr<nsINode> mRoot;
|
||||
nsCSSRect mRootMargin;
|
||||
nsTArray<double> mThresholds;
|
||||
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ nsContentSink::nsContentSink()
|
|||
, mDeferredFlushTags(0)
|
||||
, mIsDocumentObserver(0)
|
||||
, mRunsToCompletion(0)
|
||||
, mIsBlockingOnload(false)
|
||||
, mDeflectedCount(0)
|
||||
, mHasPendingEvent(false)
|
||||
, mCurrentParseEndTime(0)
|
||||
|
|
@ -1539,8 +1540,14 @@ nsContentSink::DropParserAndPerfHint(void)
|
|||
FavorPerformanceHint(true, 0);
|
||||
}
|
||||
|
||||
if (!mRunsToCompletion) {
|
||||
// Call UnblockOnload only if mRunsToComletion is false and if
|
||||
// we have already started loading because it's possible that this function
|
||||
// is called (i.e. the parser is terminated) before we start loading due to
|
||||
// destroying the window inside unload event callbacks for the previous
|
||||
// document.
|
||||
if (!mRunsToCompletion && mIsBlockingOnload) {
|
||||
mDocument->UnblockOnload(true);
|
||||
mIsBlockingOnload = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1595,6 +1602,7 @@ nsContentSink::WillBuildModelImpl()
|
|||
{
|
||||
if (!mRunsToCompletion) {
|
||||
mDocument->BlockOnload();
|
||||
mIsBlockingOnload = true;
|
||||
|
||||
mBeginLoadTime = PR_IntervalToMicroseconds(PR_IntervalNow());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -304,6 +304,8 @@ protected:
|
|||
// True if this is parser is a fragment parser or an HTML DOMParser.
|
||||
// XML DOMParser leaves this to false for now!
|
||||
uint8_t mRunsToCompletion : 1;
|
||||
// True if we are blocking load event.
|
||||
bool mIsBlockingOnload : 1;
|
||||
|
||||
//
|
||||
// -- Can interrupt parsing members --
|
||||
|
|
|
|||
|
|
@ -5444,6 +5444,14 @@ nsContentUtils::AddPendingIDBTransaction(already_AddRefed<nsIRunnable> aTransact
|
|||
CycleCollectedJSContext::Get()->AddPendingIDBTransaction(Move(aTransaction));
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
nsContentUtils::IsInStableOrMetaStableState()
|
||||
{
|
||||
MOZ_ASSERT(CycleCollectedJSContext::Get(), "Must be on a script thread!");
|
||||
return CycleCollectedJSContext::Get()->IsInStableOrMetaStableState();
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function for nsContentUtils::ProcessViewportInfo.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1779,6 +1779,11 @@ public:
|
|||
*/
|
||||
static void AddPendingIDBTransaction(already_AddRefed<nsIRunnable> aTransaction);
|
||||
|
||||
/**
|
||||
* Returns true if we are doing StableState/MetastableState.
|
||||
*/
|
||||
static bool IsInStableOrMetaStableState();
|
||||
|
||||
/* Process viewport META data. This gives us information for the scale
|
||||
* and zoom of a page on mobile devices. We stick the information in
|
||||
* the document header and use it later on after rendering.
|
||||
|
|
|
|||
|
|
@ -269,6 +269,7 @@ nsRange::nsRange(nsINode* aNode)
|
|||
, mStartOffsetWasIncremented(false)
|
||||
, mEndOffsetWasIncremented(false)
|
||||
, mEnableGravitationOnElementRemoval(true)
|
||||
, mCalledByJS(false)
|
||||
#ifdef DEBUG
|
||||
, mAssertNextInsertOrAppendIndex(-1)
|
||||
, mAssertNextInsertOrAppendNode(nullptr)
|
||||
|
|
@ -997,7 +998,16 @@ nsRange::DoSetRange(nsINode* aStartN, uint32_t aStartOffset,
|
|||
// Notify any selection listeners. This has to occur last because otherwise the world
|
||||
// could be observed by a selection listener while the range was in an invalid state.
|
||||
if (mSelection) {
|
||||
mSelection->NotifySelectionListeners();
|
||||
// Our internal code should not move focus with using this instance while
|
||||
// it's calling Selection::NotifySelectionListeners() which may move focus
|
||||
// or calls selection listeners. So, let's set mCalledByJS to false here
|
||||
// since non-*JS() methods don't set it to false.
|
||||
AutoCalledByJSRestore calledByJSRestorer(*this);
|
||||
mCalledByJS = false;
|
||||
// Be aware, this range may be modified or stop being a range for selection
|
||||
// after this call. Additionally, the selection instance may have gone.
|
||||
RefPtr<Selection> selection = mSelection;
|
||||
selection->NotifySelectionListeners(calledByJSRestorer.SavedValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1224,6 +1234,14 @@ nsRange::IsValidBoundary(nsINode* aNode)
|
|||
return root;
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SetStartJS(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr)
|
||||
{
|
||||
AutoCalledByJSRestore calledByJSRestorer(*this);
|
||||
mCalledByJS = true;
|
||||
SetStart(aNode, aOffset, aErr);
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SetStart(nsINode& aNode, uint32_t aOffset, ErrorResult& aRv)
|
||||
{
|
||||
|
|
@ -1279,6 +1297,14 @@ nsRange::SetStart(nsINode* aParent, uint32_t aOffset)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SetStartBeforeJS(nsINode& aNode, ErrorResult& aErr)
|
||||
{
|
||||
AutoCalledByJSRestore calledByJSRestorer(*this);
|
||||
mCalledByJS = true;
|
||||
SetStartBefore(aNode, aErr);
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SetStartBefore(nsINode& aNode, ErrorResult& aRv)
|
||||
{
|
||||
|
|
@ -1310,6 +1336,14 @@ nsRange::SetStartBefore(nsIDOMNode* aSibling)
|
|||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SetStartAfterJS(nsINode& aNode, ErrorResult& aErr)
|
||||
{
|
||||
AutoCalledByJSRestore calledByJSRestorer(*this);
|
||||
mCalledByJS = true;
|
||||
SetStartAfter(aNode, aErr);
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SetStartAfter(nsINode& aNode, ErrorResult& aRv)
|
||||
{
|
||||
|
|
@ -1341,6 +1375,14 @@ nsRange::SetStartAfter(nsIDOMNode* aSibling)
|
|||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SetEndJS(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr)
|
||||
{
|
||||
AutoCalledByJSRestore calledByJSRestorer(*this);
|
||||
mCalledByJS = true;
|
||||
SetEnd(aNode, aOffset, aErr);
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SetEnd(nsINode& aNode, uint32_t aOffset, ErrorResult& aRv)
|
||||
{
|
||||
|
|
@ -1455,6 +1497,14 @@ nsRange::SetStartAndEnd(nsINode* aStartParent, uint32_t aStartOffset,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SetEndBeforeJS(nsINode& aNode, ErrorResult& aErr)
|
||||
{
|
||||
AutoCalledByJSRestore calledByJSRestorer(*this);
|
||||
mCalledByJS = true;
|
||||
SetEndBefore(aNode, aErr);
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SetEndBefore(nsINode& aNode, ErrorResult& aRv)
|
||||
{
|
||||
|
|
@ -1486,6 +1536,14 @@ nsRange::SetEndBefore(nsIDOMNode* aSibling)
|
|||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SetEndAfterJS(nsINode& aNode, ErrorResult& aErr)
|
||||
{
|
||||
AutoCalledByJSRestore calledByJSRestorer(*this);
|
||||
mCalledByJS = true;
|
||||
SetEndAfter(aNode, aErr);
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SetEndAfter(nsINode& aNode, ErrorResult& aRv)
|
||||
{
|
||||
|
|
@ -1532,6 +1590,14 @@ nsRange::Collapse(bool aToStart)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::CollapseJS(bool aToStart)
|
||||
{
|
||||
AutoCalledByJSRestore calledByJSRestorer(*this);
|
||||
mCalledByJS = true;
|
||||
Unused << Collapse(aToStart);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsRange::SelectNode(nsIDOMNode* aN)
|
||||
{
|
||||
|
|
@ -1543,6 +1609,14 @@ nsRange::SelectNode(nsIDOMNode* aN)
|
|||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SelectNodeJS(nsINode& aNode, ErrorResult& aErr)
|
||||
{
|
||||
AutoCalledByJSRestore calledByJSRestorer(*this);
|
||||
mCalledByJS = true;
|
||||
SelectNode(aNode, aErr);
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SelectNode(nsINode& aNode, ErrorResult& aRv)
|
||||
{
|
||||
|
|
@ -1582,6 +1656,14 @@ nsRange::SelectNodeContents(nsIDOMNode* aN)
|
|||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SelectNodeContentsJS(nsINode& aNode, ErrorResult& aErr)
|
||||
{
|
||||
AutoCalledByJSRestore calledByJSRestorer(*this);
|
||||
mCalledByJS = true;
|
||||
SelectNodeContents(aNode, aErr);
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SelectNodeContents(nsINode& aNode, ErrorResult& aRv)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "nsStubMutationObserver.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/GuardObjects.h"
|
||||
|
||||
namespace mozilla {
|
||||
class ErrorResult;
|
||||
|
|
@ -256,14 +257,20 @@ public:
|
|||
void InsertNode(nsINode& aNode, ErrorResult& aErr);
|
||||
bool IntersectsNode(nsINode& aNode, ErrorResult& aRv);
|
||||
bool IsPointInRange(nsINode& aParent, uint32_t aOffset, ErrorResult& aErr);
|
||||
void SelectNode(nsINode& aNode, ErrorResult& aErr);
|
||||
void SelectNodeContents(nsINode& aNode, ErrorResult& aErr);
|
||||
void SetEnd(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr);
|
||||
void SetEndAfter(nsINode& aNode, ErrorResult& aErr);
|
||||
void SetEndBefore(nsINode& aNode, ErrorResult& aErr);
|
||||
void SetStart(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr);
|
||||
void SetStartAfter(nsINode& aNode, ErrorResult& aErr);
|
||||
void SetStartBefore(nsINode& aNode, ErrorResult& aErr);
|
||||
|
||||
// *JS() methods are mapped to Range.*() of DOM.
|
||||
// They may move focus only when the range represents normal selection.
|
||||
// These methods shouldn't be used from internal.
|
||||
void CollapseJS(bool aToStart);
|
||||
void SelectNodeJS(nsINode& aNode, ErrorResult& aErr);
|
||||
void SelectNodeContentsJS(nsINode& aNode, ErrorResult& aErr);
|
||||
void SetEndJS(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr);
|
||||
void SetEndAfterJS(nsINode& aNode, ErrorResult& aErr);
|
||||
void SetEndBeforeJS(nsINode& aNode, ErrorResult& aErr);
|
||||
void SetStartJS(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr);
|
||||
void SetStartAfterJS(nsINode& aNode, ErrorResult& aErr);
|
||||
void SetStartBeforeJS(nsINode& aNode, ErrorResult& aErr);
|
||||
|
||||
void SurroundContents(nsINode& aNode, ErrorResult& aErr);
|
||||
already_AddRefed<DOMRect> GetBoundingClientRect(bool aClampToEdge = true,
|
||||
bool aFlushLayout = true);
|
||||
|
|
@ -272,6 +279,17 @@ public:
|
|||
void GetClientRectsAndTexts(
|
||||
mozilla::dom::ClientRectsAndTexts& aResult,
|
||||
ErrorResult& aErr);
|
||||
|
||||
// Following methods should be used for internal use instead of *JS().
|
||||
void SelectNode(nsINode& aNode, ErrorResult& aErr);
|
||||
void SelectNodeContents(nsINode& aNode, ErrorResult& aErr);
|
||||
void SetEnd(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr);
|
||||
void SetEndAfter(nsINode& aNode, ErrorResult& aErr);
|
||||
void SetEndBefore(nsINode& aNode, ErrorResult& aErr);
|
||||
void SetStart(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr);
|
||||
void SetStartAfter(nsINode& aNode, ErrorResult& aErr);
|
||||
void SetStartBefore(nsINode& aNode, ErrorResult& aErr);
|
||||
|
||||
static void GetInnerTextNoFlush(mozilla::dom::DOMString& aValue,
|
||||
mozilla::ErrorResult& aError,
|
||||
nsIContent* aStartParent,
|
||||
|
|
@ -392,6 +410,31 @@ protected:
|
|||
size_t aRangeStart,
|
||||
size_t aRangeEnd);
|
||||
|
||||
// Assume that this is guaranteed that this is held by the caller when
|
||||
// this is used. (Note that we cannot use AutoRestore for mCalledByJS
|
||||
// due to a bit field.)
|
||||
class MOZ_RAII AutoCalledByJSRestore final
|
||||
{
|
||||
private:
|
||||
nsRange& mRange;
|
||||
bool mOldValue;
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
|
||||
public:
|
||||
explicit AutoCalledByJSRestore(nsRange& aRange
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: mRange(aRange)
|
||||
, mOldValue(aRange.mCalledByJS)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
~AutoCalledByJSRestore()
|
||||
{
|
||||
mRange.mCalledByJS = mOldValue;
|
||||
}
|
||||
bool SavedValue() const { return mOldValue; }
|
||||
};
|
||||
|
||||
struct MOZ_STACK_CLASS AutoInvalidateSelection
|
||||
{
|
||||
explicit AutoInvalidateSelection(nsRange* aRange) : mRange(aRange)
|
||||
|
|
@ -428,6 +471,7 @@ protected:
|
|||
bool mStartOffsetWasIncremented : 1;
|
||||
bool mEndOffsetWasIncremented : 1;
|
||||
bool mEnableGravitationOnElementRemoval : 1;
|
||||
bool mCalledByJS : 1;
|
||||
#ifdef DEBUG
|
||||
int32_t mAssertNextInsertOrAppendIndex;
|
||||
nsINode* mAssertNextInsertOrAppendNode;
|
||||
|
|
|
|||
|
|
@ -693,6 +693,13 @@ EventDispatcher::Dispatch(nsISupports* aTarget,
|
|||
NS_ENSURE_TRUE(aEvent->mMessage || !aDOMEvent || aTargets,
|
||||
NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
|
||||
// Events shall not be fired while we are in stable state to prevent anything
|
||||
// visible from the scripts.
|
||||
// See comment in CycleCollectedJSContext::AfterProcessMicrotasks for why we allow it anyway.
|
||||
// MOZ_ASSERT(!nsContentUtils::IsInStableOrMetaStableState());
|
||||
// NS_ENSURE_TRUE(!nsContentUtils::IsInStableOrMetaStableState(),
|
||||
// NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
|
||||
#ifdef MOZ_TASK_TRACER
|
||||
{
|
||||
if (aDOMEvent) {
|
||||
|
|
|
|||
|
|
@ -3105,6 +3105,26 @@ HTMLInputElement::GetFiles()
|
|||
return mFileList;
|
||||
}
|
||||
|
||||
void
|
||||
HTMLInputElement::SetFiles(FileList* aFiles)
|
||||
{
|
||||
if (mType != NS_FORM_INPUT_FILE || !aFiles) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear |mFileList| to omit |UpdateFileList|
|
||||
if (mFileList) {
|
||||
mFileList->Clear();
|
||||
mFileList = nullptr;
|
||||
}
|
||||
|
||||
// Update |mFilesOrDirectories|
|
||||
SetFiles(aFiles, true);
|
||||
|
||||
// Update |mFileList| without copy
|
||||
mFileList = aFiles;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
HTMLInputElement::HandleNumberControlSpin(void* aData)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -474,6 +474,7 @@ public:
|
|||
// XPCOM GetForm() is OK
|
||||
|
||||
FileList* GetFiles();
|
||||
void SetFiles(FileList* aFiles);
|
||||
|
||||
// XPCOM GetFormAction() is OK
|
||||
void SetFormAction(const nsAString& aValue, ErrorResult& aRv)
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@
|
|||
#include "MediaDecoder.h"
|
||||
#include "MediaPrefs.h"
|
||||
#include "MediaResource.h"
|
||||
#include "MediaShutdownManager.h"
|
||||
|
||||
#include "nsICategoryManager.h"
|
||||
#include "nsIContentPolicy.h"
|
||||
|
|
@ -3203,6 +3204,13 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
|
|||
NotifyOwnerDocumentActivityChanged();
|
||||
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// We initialize the MediaShutdownManager as the HTMLMediaElement is always
|
||||
// constructed on the main thread, and not during stable state.
|
||||
// (MediaShutdownManager make use of nsIAsyncShutdownClient which is written
|
||||
// in JS)
|
||||
MediaShutdownManager::InitStatics();
|
||||
|
||||
mWatchManager.Watch(mDownloadSuspendedByCache, &HTMLMediaElement::UpdateReadyStateInternal);
|
||||
// Paradoxically, there is a self-edge whereby UpdateReadyStateInternal refuses
|
||||
// to run until mReadyState reaches at least HAVE_METADATA by some other means.
|
||||
|
|
|
|||
|
|
@ -264,14 +264,16 @@ void
|
|||
HTMLTrackElement::DispatchLoadResource()
|
||||
{
|
||||
if (!mLoadResourceDispatched) {
|
||||
RefPtr<Runnable> r = NewRunnableMethod(this, &HTMLTrackElement::LoadResource);
|
||||
RefPtr<WebVTTListener> listener = new WebVTTListener(this);
|
||||
RefPtr<Runnable> r = NewRunnableMethod<RefPtr<WebVTTListener>>(this,
|
||||
&HTMLTrackElement::LoadResource, std::move(listener));
|
||||
nsContentUtils::RunInStableState(r.forget());
|
||||
mLoadResourceDispatched = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HTMLTrackElement::LoadResource()
|
||||
HTMLTrackElement::LoadResource(RefPtr<WebVTTListener>&& aWebVTTListener)
|
||||
{
|
||||
mLoadResourceDispatched = false;
|
||||
|
||||
|
|
@ -317,33 +319,46 @@ HTMLTrackElement::LoadResource()
|
|||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsCOMPtr<nsILoadGroup> loadGroup = OwnerDoc()->GetDocumentLoadGroup();
|
||||
rv = NS_NewChannel(getter_AddRefs(channel),
|
||||
uri,
|
||||
static_cast<Element*>(this),
|
||||
secFlags,
|
||||
nsIContentPolicy::TYPE_INTERNAL_TRACK,
|
||||
loadGroup,
|
||||
nullptr, // aCallbacks
|
||||
nsIRequest::LOAD_NORMAL | nsIChannel::LOAD_CLASSIFY_URI);
|
||||
|
||||
NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv));
|
||||
|
||||
mListener = new WebVTTListener(this);
|
||||
mListener = std::move(aWebVTTListener);
|
||||
// This will do 6. Set the text track readiness state to loading.
|
||||
rv = mListener->LoadResource();
|
||||
NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv));
|
||||
channel->SetNotificationCallbacks(mListener);
|
||||
|
||||
LOG(LogLevel::Debug, ("opening webvtt channel"));
|
||||
rv = channel->AsyncOpen2(mListener);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
SetReadyState(TextTrackReadyState::FailedToLoad);
|
||||
nsIDocument* doc = OwnerDoc();
|
||||
if (!doc) {
|
||||
return;
|
||||
}
|
||||
|
||||
mChannel = channel;
|
||||
// 9. End the synchronous section, continuing the remaining steps in parallel.
|
||||
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
||||
[ self = RefPtr<HTMLTrackElement>(this), uri, secFlags ]() {
|
||||
if (!self->mListener) {
|
||||
// Shutdown got called, abort.
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsCOMPtr<nsILoadGroup> loadGroup = self->OwnerDoc()->GetDocumentLoadGroup();
|
||||
nsresult rv = NS_NewChannel(getter_AddRefs(channel),
|
||||
uri,
|
||||
static_cast<Element*>(self),
|
||||
secFlags,
|
||||
nsIContentPolicy::TYPE_INTERNAL_TRACK,
|
||||
loadGroup,
|
||||
nullptr, // aCallbacks
|
||||
nsIRequest::LOAD_NORMAL | nsIChannel::LOAD_CLASSIFY_URI);
|
||||
NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv));
|
||||
|
||||
channel->SetNotificationCallbacks(self->mListener);
|
||||
|
||||
LOG(LogLevel::Debug, ("opening webvtt channel"));
|
||||
rv = channel->AsyncOpen2(self->mListener);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
self->SetReadyState(TextTrackReadyState::FailedToLoad);
|
||||
return;
|
||||
}
|
||||
self->mChannel = channel;
|
||||
}));
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
|||
|
|
@ -118,9 +118,6 @@ protected:
|
|||
virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
void OnChannelRedirect(nsIChannel* aChannel, nsIChannel* aNewChannel,
|
||||
uint32_t aFlags);
|
||||
// Open a new channel to the HTMLTrackElement's src attribute and call
|
||||
// mListener's LoadResource().
|
||||
void LoadResource();
|
||||
|
||||
friend class TextTrackCue;
|
||||
friend class WebVTTListener;
|
||||
|
|
@ -134,6 +131,9 @@ protected:
|
|||
|
||||
private:
|
||||
void DispatchLoadResource();
|
||||
// Open a new channel to the HTMLTrackElement's src attribute and call
|
||||
// mListener's LoadResource().
|
||||
void LoadResource(RefPtr<WebVTTListener>&& aWebVTTListener);
|
||||
bool mLoadResourceDispatched;
|
||||
|
||||
RefPtr<WindowDestroyObserver> mWindowDestroyObserver;
|
||||
|
|
|
|||
|
|
@ -602,6 +602,17 @@ void
|
|||
TextTrackManager::TimeMarchesOn()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
CycleCollectedJSContext* context = CycleCollectedJSContext::Get();
|
||||
if (context && context->IsInStableOrMetaStableState()) {
|
||||
// FireTimeUpdate can be called while at stable state following a
|
||||
// current position change which triggered a state watcher in MediaDecoder
|
||||
// (see bug 1443429).
|
||||
// TimeMarchesOn() will modify JS attributes which is forbidden while in
|
||||
// stable state. So we dispatch a task to perform such operation later
|
||||
// instead.
|
||||
DispatchTimeMarchesOn();
|
||||
return;
|
||||
}
|
||||
WEBVTT_LOG("TimeMarchesOn");
|
||||
mTimeMarchesOnDispatched = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -453,8 +453,6 @@ MediaDecoder::MediaDecoder(MediaDecoderOwner* aOwner)
|
|||
mWatchManager.Watch(mLogicallySeeking, &MediaDecoder::SeekingChanged);
|
||||
|
||||
mWatchManager.Watch(mIsAudioDataAudible, &MediaDecoder::NotifyAudibleStateChanged);
|
||||
|
||||
MediaShutdownManager::InitStatics();
|
||||
}
|
||||
|
||||
#undef INIT_MIRROR
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "WebVTTListener.h"
|
||||
#include "mozilla/CycleCollectedJSContext.h"
|
||||
#include "mozilla/dom/TextTrackCue.h"
|
||||
#include "mozilla/dom/TextTrackRegion.h"
|
||||
#include "mozilla/dom/VTTRegionBinding.h"
|
||||
|
|
@ -34,9 +35,22 @@ LazyLogModule gTextTrackLog("TextTrack");
|
|||
|
||||
WebVTTListener::WebVTTListener(HTMLTrackElement* aElement)
|
||||
: mElement(aElement)
|
||||
, mParserWrapperError(NS_OK)
|
||||
{
|
||||
MOZ_ASSERT(mElement, "Must pass an element to the callback");
|
||||
VTT_LOG("WebVTTListener created.");
|
||||
MOZ_DIAGNOSTIC_ASSERT(
|
||||
CycleCollectedJSContext::Get() &&
|
||||
!CycleCollectedJSContext::Get()->IsInStableOrMetaStableState());
|
||||
mParserWrapper = do_CreateInstance(NS_WEBVTTPARSERWRAPPER_CONTRACTID,
|
||||
&mParserWrapperError);
|
||||
if (NS_SUCCEEDED(mParserWrapperError)) {
|
||||
nsPIDOMWindowInner* window = mElement->OwnerDoc()->GetInnerWindow();
|
||||
mParserWrapperError = mParserWrapper->LoadParser(window);
|
||||
}
|
||||
if (NS_SUCCEEDED(mParserWrapperError)) {
|
||||
mParserWrapperError = mParserWrapper->Watch(this);
|
||||
}
|
||||
}
|
||||
|
||||
WebVTTListener::~WebVTTListener()
|
||||
|
|
@ -54,16 +68,8 @@ WebVTTListener::GetInterface(const nsIID &aIID,
|
|||
nsresult
|
||||
WebVTTListener::LoadResource()
|
||||
{
|
||||
nsresult rv;
|
||||
mParserWrapper = do_CreateInstance(NS_WEBVTTPARSERWRAPPER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsPIDOMWindowInner* window = mElement->OwnerDoc()->GetInnerWindow();
|
||||
rv = mParserWrapper->LoadParser(window);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mParserWrapper->Watch(this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// Exit if we failed to create the WebVTTParserWrapper (vtt.jsm)
|
||||
NS_ENSURE_SUCCESS(mParserWrapperError, mParserWrapperError);
|
||||
|
||||
mElement->SetReadyState(TextTrackReadyState::Loading);
|
||||
return NS_OK;
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ private:
|
|||
|
||||
RefPtr<HTMLTrackElement> mElement;
|
||||
nsCOMPtr<nsIWebVTTParserWrapper> mParserWrapper;
|
||||
nsresult mParserWrapperError;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
|||
|
|
@ -59,15 +59,30 @@ public:
|
|||
switch (event) {
|
||||
case MediaStreamGraphEvent::EVENT_FINISHED:
|
||||
{
|
||||
RefPtr<SynthStreamListener> self = this;
|
||||
if (!mStarted) {
|
||||
mStarted = true;
|
||||
nsCOMPtr<nsIRunnable> startRunnable =
|
||||
NewRunnableMethod(this, &SynthStreamListener::DoNotifyStarted);
|
||||
nsCOMPtr<nsIRunnable> startRunnable = NS_NewRunnableFunction(
|
||||
[self] {
|
||||
// "start" event will be fired in DoNotifyStarted() which is
|
||||
// not allowed in stable state, so we do it asynchronously in
|
||||
// next run.
|
||||
NS_DispatchToMainThread(NewRunnableMethod(
|
||||
self,
|
||||
&SynthStreamListener::DoNotifyStarted));
|
||||
});
|
||||
aGraph->DispatchToMainThreadAfterStreamStateUpdate(startRunnable.forget());
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> endRunnable =
|
||||
NewRunnableMethod(this, &SynthStreamListener::DoNotifyFinished);
|
||||
nsCOMPtr<nsIRunnable> endRunnable = NS_NewRunnableFunction(
|
||||
[self] {
|
||||
// "end" event will be fired in DoNotifyFinished() which is
|
||||
// not allowed in stable state, so we do it asynchronously in
|
||||
// next run.
|
||||
NS_DispatchToMainThread(NewRunnableMethod(
|
||||
self,
|
||||
&SynthStreamListener::DoNotifyFinished));
|
||||
});
|
||||
aGraph->DispatchToMainThreadAfterStreamStateUpdate(endRunnable.forget());
|
||||
}
|
||||
break;
|
||||
|
|
@ -85,8 +100,16 @@ public:
|
|||
{
|
||||
if (aBlocked == MediaStreamListener::UNBLOCKED && !mStarted) {
|
||||
mStarted = true;
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
NewRunnableMethod(this, &SynthStreamListener::DoNotifyStarted);
|
||||
RefPtr<SynthStreamListener> self = this;
|
||||
nsCOMPtr<nsIRunnable> event = NS_NewRunnableFunction(
|
||||
[self] {
|
||||
// "start" event will be fired in DoNotifyStarted() which is
|
||||
// not allowed in stable state, so we do it asynchronously in
|
||||
// next run.
|
||||
NS_DispatchToMainThread(NewRunnableMethod(
|
||||
self,
|
||||
&SynthStreamListener::DoNotifyStarted));
|
||||
});
|
||||
aGraph->DispatchToMainThreadAfterStreamStateUpdate(event.forget());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ interface HTMLInputElement : HTMLElement {
|
|||
attribute boolean disabled;
|
||||
readonly attribute HTMLFormElement? form;
|
||||
[Pure]
|
||||
readonly attribute FileList? files;
|
||||
attribute FileList? files;
|
||||
[CEReactions, Pure, SetterThrows]
|
||||
attribute DOMString formAction;
|
||||
[CEReactions, Pure, SetterThrows]
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ interface IntersectionObserverEntry {
|
|||
Pref="dom.intersectionObserver.enabled"]
|
||||
interface IntersectionObserver {
|
||||
[Constant]
|
||||
readonly attribute Element? root;
|
||||
readonly attribute Node? root;
|
||||
[Constant]
|
||||
readonly attribute DOMString rootMargin;
|
||||
[Constant,Cached]
|
||||
|
|
@ -56,7 +56,7 @@ dictionary IntersectionObserverEntryInit {
|
|||
};
|
||||
|
||||
dictionary IntersectionObserverInit {
|
||||
Element? root = null;
|
||||
(Element or Document)? root = null;
|
||||
DOMString rootMargin = "0px";
|
||||
(double or sequence<double>) threshold = 0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -26,22 +26,23 @@ interface Range {
|
|||
[Throws]
|
||||
readonly attribute Node commonAncestorContainer;
|
||||
|
||||
[Throws]
|
||||
[Throws, BinaryName="setStartJS"]
|
||||
void setStart(Node refNode, unsigned long offset);
|
||||
[Throws]
|
||||
[Throws, BinaryName="setEndJS"]
|
||||
void setEnd(Node refNode, unsigned long offset);
|
||||
[Throws]
|
||||
[Throws, BinaryName="setStartBeforeJS"]
|
||||
void setStartBefore(Node refNode);
|
||||
[Throws]
|
||||
[Throws, BinaryName="setStartAfterJS"]
|
||||
void setStartAfter(Node refNode);
|
||||
[Throws]
|
||||
[Throws, BinaryName="setEndBeforeJS"]
|
||||
void setEndBefore(Node refNode);
|
||||
[Throws]
|
||||
[Throws, BinaryName="setEndAfterJS"]
|
||||
void setEndAfter(Node refNode);
|
||||
[BinaryName="collapseJS"]
|
||||
void collapse(optional boolean toStart = false);
|
||||
[Throws]
|
||||
[Throws, BinaryName="selectNodeJS"]
|
||||
void selectNode(Node refNode);
|
||||
[Throws]
|
||||
[Throws, BinaryName="selectNodeContentsJS"]
|
||||
void selectNodeContents(Node refNode);
|
||||
|
||||
const unsigned short START_TO_START = 0;
|
||||
|
|
|
|||
|
|
@ -17,17 +17,17 @@ interface Selection {
|
|||
readonly attribute unsigned long focusOffset;
|
||||
|
||||
readonly attribute boolean isCollapsed;
|
||||
[Throws]
|
||||
[Throws, BinaryName="collapseJS"]
|
||||
void collapse(Node node, unsigned long offset);
|
||||
[Throws]
|
||||
[Throws, BinaryName="collapseToStartJS"]
|
||||
void collapseToStart();
|
||||
[Throws]
|
||||
[Throws, BinaryName="collapseToEndJS"]
|
||||
void collapseToEnd();
|
||||
|
||||
[Throws]
|
||||
[Throws, BinaryName="extendJS"]
|
||||
void extend(Node node, unsigned long offset);
|
||||
|
||||
[Throws]
|
||||
[Throws, BinaryName="selectAllChildrenJS"]
|
||||
void selectAllChildren(Node node);
|
||||
[Throws]
|
||||
void deleteFromDocument();
|
||||
|
|
@ -36,7 +36,7 @@ interface Selection {
|
|||
readonly attribute DOMString type;
|
||||
[Throws]
|
||||
Range getRangeAt(unsigned long index);
|
||||
[Throws]
|
||||
[Throws, BinaryName="addRangeJS"]
|
||||
void addRange(Range range);
|
||||
[Throws]
|
||||
void removeRange(Range range);
|
||||
|
|
@ -46,7 +46,7 @@ interface Selection {
|
|||
[Throws]
|
||||
boolean containsNode(Node node, boolean allowPartialContainment);
|
||||
|
||||
[Throws]
|
||||
[Throws, BinaryName="setBaseAndExtentJS"]
|
||||
void setBaseAndExtent(Node anchorNode,
|
||||
unsigned long anchorOffset,
|
||||
Node focusNode,
|
||||
|
|
|
|||
|
|
@ -3082,6 +3082,8 @@ void
|
|||
ServiceWorkerManager::FireControllerChange(ServiceWorkerRegistrationInfo* aRegistration)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
AutoTArray<nsCOMPtr<nsIDocument>, 16> documents;
|
||||
for (auto iter = mControlledDocuments.Iter(); !iter.Done(); iter.Next()) {
|
||||
if (iter.UserData() != aRegistration) {
|
||||
continue;
|
||||
|
|
@ -3092,6 +3094,12 @@ ServiceWorkerManager::FireControllerChange(ServiceWorkerRegistrationInfo* aRegis
|
|||
continue;
|
||||
}
|
||||
|
||||
documents.AppendElement(doc);
|
||||
}
|
||||
|
||||
// Fire event after iterating mControlledDocuments is done to prevent
|
||||
// modification by reentering from the event handlers during iteration.
|
||||
for (auto& doc : documents) {
|
||||
FireControllerChangeOnDocument(doc);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ WORKER_SIMPLE_PREF("browser.dom.window.dump.enabled", DumpEnabled, DUMP)
|
|||
WORKER_SIMPLE_PREF("canvas.imagebitmap_extensions.enabled", ImageBitmapExtensionsEnabled, IMAGEBITMAP_EXTENSIONS_ENABLED)
|
||||
WORKER_SIMPLE_PREF("dom.caches.enabled", DOMCachesEnabled, DOM_CACHES)
|
||||
WORKER_SIMPLE_PREF("dom.caches.testing.enabled", DOMCachesTestingEnabled, DOM_CACHES_TESTING)
|
||||
WORKER_SIMPLE_PREF("dom.min_timeout_value", DOMMinTimeoutValue, DOM_MIN_TIMEOUT_VALUE)
|
||||
WORKER_SIMPLE_PREF("dom.performance.enable_user_timing_logging", PerformanceLoggingEnabled, PERFORMANCE_LOGGING_ENABLED)
|
||||
WORKER_SIMPLE_PREF("dom.webnotifications.enabled", DOMWorkerNotificationEnabled, DOM_WORKERNOTIFICATION)
|
||||
WORKER_SIMPLE_PREF("dom.webnotifications.serviceworker.enabled", DOMServiceWorkerNotificationEnabled, DOM_SERVICEWORKERNOTIFICATION)
|
||||
|
|
|
|||
|
|
@ -1995,13 +1995,22 @@ struct WorkerPrivate::TimeoutInfo
|
|||
mNestingLevel = kClampTimeoutNestingLevel;
|
||||
}
|
||||
|
||||
void CalculateTargetTime() {
|
||||
void CalculateTargetTime(JSContext* aCx) {
|
||||
auto target = mInterval;
|
||||
int32_t minTimeoutValue;
|
||||
|
||||
// We're on a worker thread; go through WorkerPrivate for the pref.
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
|
||||
if (workerPrivate) {
|
||||
minTimeoutValue = workerPrivate->DOMMinTimeoutValue();
|
||||
} else {
|
||||
// fall back to default 4 ms
|
||||
minTimeoutValue = 4;
|
||||
}
|
||||
|
||||
// Clamp timeout for workers, except chrome workers
|
||||
if (mNestingLevel >= kClampTimeoutNestingLevel && !mOnChromeWorker) {
|
||||
target = TimeDuration::Max(
|
||||
mInterval,
|
||||
TimeDuration::FromMilliseconds(Preferences::GetInt("dom.min_timeout_value")));
|
||||
target = TimeDuration::Max(mInterval,TimeDuration::FromMilliseconds(minTimeoutValue));
|
||||
}
|
||||
mTargetTime = TimeStamp::Now() + target;
|
||||
}
|
||||
|
|
@ -6387,7 +6396,7 @@ WorkerPrivate::RunExpiredTimeouts(JSContext* aCx)
|
|||
// Reschedule intervals.
|
||||
// Reschedule a timeout and, if needed, increase the nesting level.
|
||||
info->AccumulateNestingLevel(info->mNestingLevel);
|
||||
info->CalculateTargetTime();
|
||||
info->CalculateTargetTime(aCx);
|
||||
// Don't re-sort the list here, we'll do that at the end.
|
||||
++index;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue