Merge remote-tracking branch 'origin/tracking' into custom

This commit is contained in:
roytam1 2024-01-18 10:17:09 +08:00
commit b0345ff809
35 changed files with 789 additions and 133 deletions

View file

@ -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();
}
}
}

View file

@ -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;

View file

@ -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());
}

View file

@ -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 --

View file

@ -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.
*

View file

@ -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.

View file

@ -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)
{

View file

@ -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;

View file

@ -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) {

View file

@ -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)
{

View file

@ -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)

View file

@ -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.

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -453,8 +453,6 @@ MediaDecoder::MediaDecoder(MediaDecoderOwner* aOwner)
mWatchManager.Watch(mLogicallySeeking, &MediaDecoder::SeekingChanged);
mWatchManager.Watch(mIsAudioDataAudible, &MediaDecoder::NotifyAudibleStateChanged);
MediaShutdownManager::InitStatics();
}
#undef INIT_MIRROR

View file

@ -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;

View file

@ -57,6 +57,7 @@ private:
RefPtr<HTMLTrackElement> mElement;
nsCOMPtr<nsIWebVTTParserWrapper> mParserWrapper;
nsresult mParserWrapperError;
};
} // namespace dom

View file

@ -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());
}
}

View file

@ -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]

View file

@ -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;
};

View file

@ -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;

View file

@ -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,

View file

@ -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);
}
}

View file

@ -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)

View file

@ -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;
}