diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index 3c5cef0f1c69..02053a0b8543 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -7139,22 +7139,27 @@ nsContentUtils::GetInnerWindowID(nsIRequest* aRequest) } void -nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI, nsAString& aHost) +nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI, nsCString& aHost) { aHost.Truncate(); - nsAutoCString hostname; - nsresult rv = aURI->GetHost(hostname); + nsresult rv = aURI->GetHost(aHost); if (NS_FAILED(rv)) { // Some URIs do not have a host return; } - if (hostname.FindChar(':') != -1) { // Escape IPv6 address - MOZ_ASSERT(!hostname.Length() || - (hostname[0] !='[' && hostname[hostname.Length() - 1] != ']')); - hostname.Insert('[', 0); - hostname.Append(']'); + if (aHost.FindChar(':') != -1) { // Escape IPv6 address + MOZ_ASSERT(!aHost.Length() || + (aHost[0] !='[' && aHost[aHost.Length() - 1] != ']')); + aHost.Insert('[', 0); + aHost.Append(']'); } +} +void +nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI, nsAString& aHost) +{ + nsAutoCString hostname; + GetHostOrIPv6WithBrackets(aURI, hostname); CopyUTF8toUTF16(hostname, aHost); } diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index 10cbe7b7bf17..8ac4bdf80617 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -2282,6 +2282,7 @@ public: * otherwise it just outputs the hostname in aHost. */ static void GetHostOrIPv6WithBrackets(nsIURI* aURI, nsAString& aHost); + static void GetHostOrIPv6WithBrackets(nsIURI* aURI, nsCString& aHost); /* * Call the given callback on all remote children of the given top-level diff --git a/dom/base/test/test_url.html b/dom/base/test/test_url.html index c6c34827a247..05c93b36ba65 100644 --- a/dom/base/test/test_url.html +++ b/dom/base/test/test_url.html @@ -1,4 +1,3 @@ - @@ -117,7 +116,7 @@ { url: 'http://example.com/carrot#question%3f', base: undefined, error: false, - hash: '#question%3f' + hash: '#question?' }, { url: 'https://example.com:4443?', base: undefined, diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index dd658ce7758c..83f9da1a86bc 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -1897,6 +1897,8 @@ addExternalIface('nsIDOMCrypto', nativeType='nsIDOMCrypto', addExternalIface('nsIInputStreamCallback', nativeType='nsIInputStreamCallback', headerFile='nsIAsyncInputStream.h') addExternalIface('nsIFile', nativeType='nsIFile', notflattened=True) +addExternalIface('nsILoadGroup', nativeType='nsILoadGroup', + headerFile='nsILoadGroup.h', notflattened=True) addExternalIface('nsIMessageBroadcaster', nativeType='nsIMessageBroadcaster', headerFile='nsIMessageManager.h', notflattened=True) addExternalIface('nsISelectionListener', nativeType='nsISelectionListener') diff --git a/dom/events/test/test_bug422132.html b/dom/events/test/test_bug422132.html index 9eebacf71a60..bceeb79e8f5c 100644 --- a/dom/events/test/test_bug422132.html +++ b/dom/events/test/test_bug422132.html @@ -8,6 +8,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=422132 + @@ -25,67 +26,96 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=422132 /** Test for Bug 422132 **/ SimpleTest.waitForExplicitFinish(); -SimpleTest.requestFlakyTimeout("untriaged"); SimpleTest.waitForFocus(function() { SpecialPowers.pushPrefEnv({ "set":[["general.smoothScroll", false], ["mousewheel.min_line_scroll_amount", 1], + ["mousewheel.system_scroll_override_on_root_content.enabled", false], ["mousewheel.transaction.timeout", 100000]]}, runTests)}, window); -function hitEventLoop(aFunc, aTimes) -{ - if (--aTimes) { - setTimeout(hitEventLoop, 0, aFunc, aTimes); - } else { - setTimeout(aFunc, 20); - } -} - function runTests() { var target = document.getElementById("target"); var scrollLeft = target.scrollLeft; var scrollTop = target.scrollTop; - synthesizeWheel(target, 10, 10, - { deltaMode: WheelEvent.DOM_DELTA_PIXEL, - deltaX: 0.5, deltaY: 0.5, lineOrPageDeltaX: 0, lineOrPageDeltaY: 0 }); - hitEventLoop(function () { - is(target.scrollLeft, scrollLeft, "scrolled to right by 0.5px delta value"); - is(target.scrollTop, scrollTop, "scrolled to bottom by 0.5px delta value"); - scrollLeft = target.scrollLeft; - scrollTop = target.scrollTop; - synthesizeWheel(target, 10, 10, - { deltaMode: WheelEvent.DOM_DELTA_PIXEL, - deltaX: 0.5, deltaY: 0.5, lineOrPageDeltaX: 0, lineOrPageDeltaY: 0 }); - hitEventLoop(function () { - ok(target.scrollLeft > scrollLeft, - "not scrolled to right by 0.5px delta value with pending 0.5px delta"); - ok(target.scrollTop > scrollTop, - "not scrolled to bottom by 0.5px delta value with pending 0.5px delta"); - scrollLeft = target.scrollLeft; - scrollTop = target.scrollTop; - synthesizeWheel(target, 10, 10, - { deltaMode: WheelEvent.DOM_DELTA_LINE, - deltaX: 0.5, deltaY: 0.5, lineOrPageDeltaX: 0, lineOrPageDeltaY: 0 }); - hitEventLoop(function () { - is(target.scrollLeft, scrollLeft, "scrolled to right by 0.5 line delta value"); - is(target.scrollTop, scrollTop, "scrolled to bottom by 0.5 line delta value"); + + var tests = [ + { + prepare: function() { scrollLeft = target.scrollLeft; scrollTop = target.scrollTop; - synthesizeWheel(target, 10, 10, - { deltaMode: WheelEvent.DOM_DELTA_LINE, - deltaX: 0.5, deltaY: 0.5, lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 }); - hitEventLoop(function () { - ok(target.scrollLeft > scrollLeft, - "not scrolled to right by 0.5 line delta value with pending 0.5 line delta"); - ok(target.scrollTop > scrollTop, - "not scrolled to bottom by 0.5 line delta value with pending 0.5 line delta"); - SimpleTest.finish(); - }, 20); - }, 20); - }, 20); - }, 20); + }, + event: { + deltaMode: WheelEvent.DOM_DELTA_PIXEL, + deltaX: 0.5, + deltaY: 0.5, + lineOrPageDeltaX: 0, + lineOrPageDeltaY: 0 + }, + }, { + event: { + deltaMode: WheelEvent.DOM_DELTA_PIXEL, + deltaX: 0.5, + deltaY: 0.5, + lineOrPageDeltaX: 0, + lineOrPageDeltaY: 0 + }, + check: function() { + is(target.scrollLeft - scrollLeft, 1, + "not scrolled to right by 0.5px delta value with pending 0.5px delta"); + is(target.scrollTop - scrollTop, 1, + "not scrolled to bottom by 0.5px delta value with pending 0.5px delta"); + }, + }, { + prepare: function() { + scrollLeft = target.scrollLeft; + scrollTop = target.scrollTop; + }, + event: { + deltaMode: WheelEvent.DOM_DELTA_LINE, + deltaX: 0.5, + deltaY: 0.5, + lineOrPageDeltaX: 0, + lineOrPageDeltaY: 0 + }, + }, { + event: { + deltaMode: WheelEvent.DOM_DELTA_LINE, + deltaX: 0.5, + deltaY: 0.5, + lineOrPageDeltaX: 1, + lineOrPageDeltaY: 1 + }, + check: function() { + is(target.scrollLeft - scrollLeft, 1, + "not scrolled to right by 0.5 line delta value with pending 0.5 line delta"); + is(target.scrollTop - scrollTop, 1, + "not scrolled to bottom by 0.5 line delta value with pending 0.5 line delta"); + } + } + ]; + + var nextTest = function() { + var test = tests.shift(); + if (test.prepare) { + test.prepare(); + } + + sendWheelAndPaint(target, 10, 10, test.event, function() { + if (test.check) { + test.check(); + } + if (tests.length == 0) { + SimpleTest.finish(); + return; + } + + setTimeout(nextTest, 0); + }); + } + + nextTest(); } diff --git a/dom/html/test/test_hash_encoded.html b/dom/html/test/test_hash_encoded.html index b38c228df1c8..9b113b47a4e6 100644 --- a/dom/html/test/test_hash_encoded.html +++ b/dom/html/test/test_hash_encoded.html @@ -7,14 +7,42 @@ - - - - -
 
 
 
-
 
-
 
 
diff --git a/dom/media/IdpSandbox.jsm b/dom/media/IdpSandbox.jsm index 7c638b1003b7..95c594697b47 100644 --- a/dom/media/IdpSandbox.jsm +++ b/dom/media/IdpSandbox.jsm @@ -40,16 +40,19 @@ function ResourceLoader(res, rej) { this.data = ''; } -/** Loads the identified https:// URL. */ -ResourceLoader.load = function(uri) { +/** Loads the identified https:// URL. */ +ResourceLoader.load = function(uri, doc) { return new Promise((resolve, reject) => { let listener = new ResourceLoader(resolve, reject); let ioService = Cc['@mozilla.org/network/io-service;1'] .getService(Ci.nsIIOService); let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal(); // the '2' identifies this as a script load - let ioChannel = ioService.newChannelFromURI2(uri, null, systemPrincipal, - systemPrincipal, 0, 2); + let ioChannel = ioService.newChannelFromURI2(uri, doc, doc.nodePrincipal, + systemPrincipal, 0, + Ci.nsIContentPolicy.TYPE_SCRIPT); + + ioChannel.loadGroup = doc.documentLoadGroup.QueryInterface(Ci.nsILoadGroup); ioChannel.notificationCallbacks = new RedirectHttpsOnly(); ioChannel.asyncOpen(listener, null); }); @@ -110,12 +113,14 @@ function createLocationFromURI(uri) { * * @param domain (string) the domain of the IdP * @param protocol (string?) the protocol of the IdP [default: 'default'] + * @param doc (obj) the current document * @throws if the domain or protocol aren't valid */ -function IdpSandbox(domain, protocol) { +function IdpSandbox(domain, protocol, doc) { this.source = IdpSandbox.createIdpUri(domain, protocol || "default"); this.active = null; this.sandbox = null; + this.document = doc; } IdpSandbox.checkDomain = function(domain) { @@ -176,7 +181,7 @@ IdpSandbox.prototype = { start: function() { if (!this.active) { - this.active = ResourceLoader.load(this.source) + this.active = ResourceLoader.load(this.source, this.document) .then(result => this._createSandbox(result)); } return this.active; diff --git a/dom/media/MediaDecoder.cpp b/dom/media/MediaDecoder.cpp index b5beb546d565..6e27eaca11ff 100644 --- a/dom/media/MediaDecoder.cpp +++ b/dom/media/MediaDecoder.cpp @@ -1223,9 +1223,10 @@ void MediaDecoder::UpdateReadyStateForData() mOwner->UpdateReadyStateForData(frameStatus); } -void MediaDecoder::OnSeekResolvedInternal(bool aAtEnd, MediaDecoderEventVisibility aEventVisibility) +void MediaDecoder::OnSeekResolved(SeekResolveValue aVal) { MOZ_ASSERT(NS_IsMainThread()); + mSeekRequest.Complete(); if (mShuttingDown) return; @@ -1242,20 +1243,20 @@ void MediaDecoder::OnSeekResolvedInternal(bool aAtEnd, MediaDecoderEventVisibili seekWasAborted = true; } else { UnpinForSeek(); - fireEnded = aAtEnd; - if (aAtEnd) { + fireEnded = aVal.mAtEnd; + if (aVal.mAtEnd) { ChangeState(PLAY_STATE_ENDED); - } else if (aEventVisibility != MediaDecoderEventVisibility::Suppressed) { - ChangeState(aAtEnd ? PLAY_STATE_ENDED : mNextState); + } else if (aVal.mEventVisibility != MediaDecoderEventVisibility::Suppressed) { + ChangeState(aVal.mAtEnd ? PLAY_STATE_ENDED : mNextState); } } } - PlaybackPositionChanged(aEventVisibility); + PlaybackPositionChanged(aVal.mEventVisibility); if (mOwner) { UpdateReadyStateForData(); - if (!seekWasAborted && (aEventVisibility != MediaDecoderEventVisibility::Suppressed)) { + if (!seekWasAborted && (aVal.mEventVisibility != MediaDecoderEventVisibility::Suppressed)) { mOwner->SeekCompleted(); if (fireEnded) { mOwner->PlaybackEnded(); diff --git a/dom/media/MediaDecoder.h b/dom/media/MediaDecoder.h index 4da2f8b93918..43311fcb3565 100644 --- a/dom/media/MediaDecoder.h +++ b/dom/media/MediaDecoder.h @@ -809,21 +809,7 @@ public: void PlaybackEnded(); void OnSeekRejected() { mSeekRequest.Complete(); } - void OnSeekResolvedInternal(bool aAtEnd, MediaDecoderEventVisibility aEventVisibility); - - void OnSeekResolved(SeekResolveValue aVal) - { - mSeekRequest.Complete(); - OnSeekResolvedInternal(aVal.mAtEnd, aVal.mEventVisibility); - } - -#ifdef MOZ_AUDIO_OFFLOAD - // Temporary hack - see bug 1139206. - void SimulateSeekResolvedForAudioOffload(MediaDecoderEventVisibility aEventVisibility) - { - OnSeekResolvedInternal(false, aEventVisibility); - } -#endif + void OnSeekResolved(SeekResolveValue aVal); // Seeking has started. Inform the element on the main // thread. diff --git a/dom/media/PeerConnectionIdp.jsm b/dom/media/PeerConnectionIdp.jsm index daac5b392e4a..0248346e2113 100644 --- a/dom/media/PeerConnectionIdp.jsm +++ b/dom/media/PeerConnectionIdp.jsm @@ -56,7 +56,7 @@ PeerConnectionIdp.prototype = { } this._idp.stop(); } - this._idp = new IdpSandbox(provider, protocol); + this._idp = new IdpSandbox(provider, protocol, this._win.document); }, // start the IdP and do some error fixup diff --git a/dom/media/omx/AudioOffloadPlayer.cpp b/dom/media/omx/AudioOffloadPlayer.cpp index 3f7952b94db6..56674f085c73 100644 --- a/dom/media/omx/AudioOffloadPlayer.cpp +++ b/dom/media/omx/AudioOffloadPlayer.cpp @@ -57,13 +57,10 @@ static const uint64_t OFFLOAD_PAUSE_MAX_MSECS = 60000ll; AudioOffloadPlayer::AudioOffloadPlayer(MediaOmxCommonDecoder* aObserver) : mStarted(false), mPlaying(false), - mSeeking(false), mReachedEOS(false), - mSeekDuringPause(false), mIsElementVisible(true), mSampleRate(0), mStartPosUs(0), - mSeekTimeUs(0), mPositionTimeMediaUs(-1), mInputBuffer(nullptr), mObserver(aObserver) @@ -199,13 +196,6 @@ status_t AudioOffloadPlayer::ChangeState(MediaDecoder::PlayState aState) StartTimeUpdate(); } break; - case MediaDecoder::PLAY_STATE_SEEKING: { - int64_t seekTimeUs - = mObserver->GetSeekTime(); - SeekTo(seekTimeUs, true); - mObserver->ResetSeekTime(); - } break; - case MediaDecoder::PLAY_STATE_PAUSED: case MediaDecoder::PLAY_STATE_SHUTDOWN: // Just pause here during play state shutdown as well to stop playing @@ -278,8 +268,12 @@ status_t AudioOffloadPlayer::Play() return err; } // Seek to last play position only when there was no seek during last pause - if (!mSeeking) { - SeekTo(mPositionTimeMediaUs); + android::Mutex::Autolock autoLock(mLock); + if (!mSeekTarget.IsValid()) { + mSeekTarget = SeekTarget(mPositionTimeMediaUs, + SeekTarget::Accurate, + MediaDecoderEventVisibility::Suppressed); + DoSeek(); } } @@ -343,28 +337,36 @@ void AudioOffloadPlayer::Reset() WakeLockRelease(); } -status_t AudioOffloadPlayer::SeekTo(int64_t aTimeUs, bool aDispatchSeekEvents) +nsRefPtr AudioOffloadPlayer::Seek(SeekTarget aTarget) { MOZ_ASSERT(NS_IsMainThread()); - CHECK(mAudioSink.get()); - android::Mutex::Autolock autoLock(mLock); - AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("SeekTo ( %lld )", aTimeUs)); + mSeekPromise.RejectIfExists(true, __func__); + mSeekTarget = aTarget; + nsRefPtr p = mSeekPromise.Ensure(__func__); + DoSeek(); + return p; +} + +status_t AudioOffloadPlayer::DoSeek() +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(mSeekTarget.IsValid()); + CHECK(mAudioSink.get()); + + AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("DoSeek ( %lld )", mSeekTarget.mTime)); - mSeeking = true; mReachedEOS = false; mPositionTimeMediaUs = -1; - mSeekTimeUs = aTimeUs; - mStartPosUs = aTimeUs; - mDispatchSeekEvents = aDispatchSeekEvents; + mStartPosUs = mSeekTarget.mTime; - if (mDispatchSeekEvents) { + if (!mSeekPromise.IsEmpty()) { nsCOMPtr nsEvent = NS_NewRunnableMethodWithArg( mObserver, &MediaDecoder::SeekingStarted, - MediaDecoderEventVisibility::Observable); + mSeekTarget.mEventVisibility); NS_DispatchToCurrentThread(nsEvent); } @@ -374,21 +376,15 @@ status_t AudioOffloadPlayer::SeekTo(int64_t aTimeUs, bool aDispatchSeekEvents) mAudioSink->Start(); } else { - mSeekDuringPause = true; - if (mStarted) { mAudioSink->Flush(); } - if (mDispatchSeekEvents) { - mDispatchSeekEvents = false; + if (!mSeekPromise.IsEmpty()) { AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("Fake seek complete during pause")); - nsCOMPtr nsEvent = - NS_NewRunnableMethodWithArg( - mObserver, - &MediaDecoder::SimulateSeekResolvedForAudioOffload, - MediaDecoderEventVisibility::Observable); - NS_DispatchToCurrentThread(nsEvent); + // We do not reset mSeekTarget here. + MediaDecoder::SeekResolveValue val(mReachedEOS, mSeekTarget.mEventVisibility); + mSeekPromise.Resolve(val, __func__); } } @@ -407,8 +403,8 @@ int64_t AudioOffloadPlayer::GetMediaTimeUs() android::Mutex::Autolock autoLock(mLock); int64_t playPosition = 0; - if (mSeeking) { - return mSeekTimeUs; + if (mSeekTarget.IsValid()) { + return mSeekTarget.mTime; } if (!mStarted) { return mPositionTimeMediaUs; @@ -439,6 +435,12 @@ int64_t AudioOffloadPlayer::GetOutputPlayPositionUs_l() const void AudioOffloadPlayer::NotifyAudioEOS() { + android::Mutex::Autolock autoLock(mLock); + // We do not reset mSeekTarget here. + if (!mSeekPromise.IsEmpty()) { + MediaDecoder::SeekResolveValue val(mReachedEOS, mSeekTarget.mEventVisibility); + mSeekPromise.Resolve(val, __func__); + } nsCOMPtr nsEvent = NS_NewRunnableMethod(mObserver, &MediaDecoder::PlaybackEnded); NS_DispatchToMainThread(nsEvent); @@ -456,6 +458,15 @@ void AudioOffloadPlayer::NotifyPositionChanged() void AudioOffloadPlayer::NotifyAudioTearDown() { + // Fallback to state machine. + // state machine's seeks will be done with + // MediaDecoderEventVisibility::Suppressed. + android::Mutex::Autolock autoLock(mLock); + // We do not reset mSeekTarget here. + if (!mSeekPromise.IsEmpty()) { + MediaDecoder::SeekResolveValue val(mReachedEOS, mSeekTarget.mEventVisibility); + mSeekPromise.Resolve(val, __func__); + } nsCOMPtr nsEvent = NS_NewRunnableMethod(mObserver, &MediaOmxCommonDecoder::AudioOffloadTearDown); NS_DispatchToMainThread(nsEvent); @@ -506,27 +517,26 @@ size_t AudioOffloadPlayer::FillBuffer(void* aData, size_t aSize) size_t sizeDone = 0; size_t sizeRemaining = aSize; + int64_t seekTimeUs = -1; while (sizeRemaining > 0) { MediaSource::ReadOptions options; bool refreshSeekTime = false; - { android::Mutex::Autolock autoLock(mLock); - if (mSeeking) { - options.setSeekTo(mSeekTimeUs); + if (mSeekTarget.IsValid()) { + seekTimeUs = mSeekTarget.mTime; + options.setSeekTo(seekTimeUs); refreshSeekTime = true; if (mInputBuffer) { mInputBuffer->release(); mInputBuffer = nullptr; } - mSeeking = false; } } if (!mInputBuffer) { - status_t err; err = mSource->read(&mInputBuffer, &options); @@ -535,6 +545,9 @@ size_t AudioOffloadPlayer::FillBuffer(void* aData, size_t aSize) android::Mutex::Autolock autoLock(mLock); if (err != OK) { + if (mSeekTarget.IsValid()) { + mSeekTarget.Reset(); + } AUDIO_OFFLOAD_LOG(PR_LOG_ERROR, ("Error while reading media source %d " "Ok to receive EOS error at end", err)); if (!mReachedEOS) { @@ -564,25 +577,19 @@ size_t AudioOffloadPlayer::FillBuffer(void* aData, size_t aSize) kKeyTime, &mPositionTimeMediaUs)); } - if (refreshSeekTime) { - if (mDispatchSeekEvents && !mSeekDuringPause) { - mDispatchSeekEvents = false; + if (mSeekTarget.IsValid() && seekTimeUs == mSeekTarget.mTime) { + MOZ_ASSERT(mSeekTarget.IsValid()); + mSeekTarget.Reset(); + if (!mSeekPromise.IsEmpty()) { AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("FillBuffer posting SEEK_COMPLETE")); - nsCOMPtr nsEvent = - NS_NewRunnableMethodWithArg( - mObserver, - &MediaDecoder::SimulateSeekResolvedForAudioOffload, - MediaDecoderEventVisibility::Observable); - NS_DispatchToMainThread(nsEvent, NS_DISPATCH_NORMAL); - - } else if (mSeekDuringPause) { - // Callback is already called for seek during pause. Just reset the - // flag - AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("Not posting seek complete as its" - " already faked")); - mSeekDuringPause = false; + MediaDecoder::SeekResolveValue val(mReachedEOS, mSeekTarget.mEventVisibility); + mSeekPromise.Resolve(val, __func__); } + } else if (mSeekTarget.IsValid()) { + AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("seek is updated during unlocking mLock")); + } + if (refreshSeekTime) { NotifyPositionChanged(); // need to adjust the mStartPosUs for offload decoding since parser @@ -590,14 +597,6 @@ size_t AudioOffloadPlayer::FillBuffer(void* aData, size_t aSize) mStartPosUs = mPositionTimeMediaUs; AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("Adjust seek time to: %.2f", mStartPosUs / 1E6)); - - // clear seek time with mLock locked and once we have valid - // mPositionTimeMediaUs - // before clearing mSeekTimeUs check if a new seek request has been - // received while we were reading from the source with mLock released. - if (!mSeeking) { - mSeekTimeUs = 0; - } } } diff --git a/dom/media/omx/AudioOffloadPlayer.h b/dom/media/omx/AudioOffloadPlayer.h index aef8961c2eaf..6bfb1e63e954 100644 --- a/dom/media/omx/AudioOffloadPlayer.h +++ b/dom/media/omx/AudioOffloadPlayer.h @@ -78,25 +78,27 @@ public: ~AudioOffloadPlayer(); // Caller retains ownership of "aSource". - void SetSource(const android::sp &aSource); + virtual void SetSource(const android::sp &aSource) override; // Start the source if it's not already started and open the AudioSink to // create an offloaded audio track - status_t Start(bool aSourceAlreadyStarted = false); + virtual status_t Start(bool aSourceAlreadyStarted = false) override; - double GetMediaTimeSecs(); + virtual status_t ChangeState(MediaDecoder::PlayState aState) override; + + virtual void SetVolume(double aVolume) override; + + virtual double GetMediaTimeSecs() override; // To update progress bar when the element is visible - void SetElementVisibility(bool aIsVisible); - - status_t ChangeState(MediaDecoder::PlayState aState); - - void SetVolume(double aVolume); + virtual void SetElementVisibility(bool aIsVisible) override;; // Update ready state based on current play state. Not checking data // availability since offloading is currently done only when whole compressed // data is available - MediaDecoderOwner::NextFrameStatus GetNextFrameStatus(); + virtual MediaDecoderOwner::NextFrameStatus GetNextFrameStatus() override; + + virtual nsRefPtr Seek(SeekTarget aTarget) override; void TimeUpdate(); @@ -112,28 +114,12 @@ private: // Used only in main thread bool mPlaying; - // Set when playstate is seeking and reset when FillBUffer() acknowledged - // seeking by seeking audio source. Used in main thread and offload - // callback thread, protected by Mutex mLock - bool mSeeking; - // Once playback reached end of stream (last ~100ms), position provided by DSP // may be reset/corrupted. This bool is used to avoid that. // Used in main thread and offload callback thread, protected by Mutex // mLock bool mReachedEOS; - // Set when there is a seek request during pause. - // Used in main thread and offload callback thread, protected by Mutex - // mLock - bool mSeekDuringPause; - - // Seek can be triggered internally or by MediaDecoder. This bool is to - // to track seek triggered by MediaDecoder so that we can send back - // SeekingStarted and SeekingStopped events. - // Used in main thread and offload callback thread, protected by Mutex mLock - bool mDispatchSeekEvents; - // Set when the HTML Audio Element is visible to the user. // Used only in main thread bool mIsElementVisible; @@ -155,10 +141,15 @@ private: // mLock int64_t mStartPosUs; - // Given seek time when there is a request to seek + // The target of current seek when there is a request to seek // Used in main thread and offload callback thread, protected by Mutex // mLock - int64_t mSeekTimeUs; + SeekTarget mSeekTarget; + + // MediaPromise of current seek. + // Used in main thread and offload callback thread, protected by Mutex + // mLock + MediaPromiseHolder mSeekPromise; // Positions obtained from offlaoded tracks (DSP) // Used in main thread and offload callback thread, protected by Mutex @@ -221,15 +212,15 @@ private: bool IsSeeking(); - // Set mSeekTime to the given position and restart the sink. Actual seek - // happens in FillBuffer(). If aDispatchSeekEvents is true, send + // Set mSeekTarget to the given position and restart the sink. Actual seek + // happens in FillBuffer(). If mSeekPromise is not empty, send // SeekingStarted event always and SeekingStopped event when the play state is // paused to MediaDecoder. // When decoding and playing happens separately, if there is a seek during // pause, we can decode and keep data ready. // In case of offload player, no way to seek during pause. So just fake that // seek is done. - status_t SeekTo(int64_t aTimeUs, bool aDispatchSeekEvents = false); + status_t DoSeek(); // Start/Resume the audio sink so that callback will start being called to get // compressed data diff --git a/dom/media/omx/AudioOffloadPlayerBase.h b/dom/media/omx/AudioOffloadPlayerBase.h index b332f8b0fce8..73c6310466a7 100644 --- a/dom/media/omx/AudioOffloadPlayerBase.h +++ b/dom/media/omx/AudioOffloadPlayerBase.h @@ -66,6 +66,8 @@ public: { return MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE; } + + virtual nsRefPtr Seek(SeekTarget aTarget) = 0; }; } // namespace mozilla diff --git a/dom/media/omx/MediaOmxCommonDecoder.cpp b/dom/media/omx/MediaOmxCommonDecoder.cpp index fb37d1c53b69..12ba4072a377 100644 --- a/dom/media/omx/MediaOmxCommonDecoder.cpp +++ b/dom/media/omx/MediaOmxCommonDecoder.cpp @@ -126,8 +126,9 @@ MediaOmxCommonDecoder::ResumeStateMachine() mAudioOffloadPlayer = nullptr; int64_t timeUsecs = 0; SecondsToUsecs(mCurrentTime, timeUsecs); - mRequestedSeekTarget = SeekTarget(timeUsecs, SeekTarget::Accurate); - + mRequestedSeekTarget = SeekTarget(timeUsecs, + SeekTarget::Accurate, + MediaDecoderEventVisibility::Suppressed); mNextState = mPlayState; ChangeState(PLAY_STATE_LOADING); // exit dormant state @@ -193,10 +194,25 @@ MediaOmxCommonDecoder::ChangeState(PlayState aState) // in between MediaDecoder::ChangeState(aState); - if (mAudioOffloadPlayer) { - status_t err = mAudioOffloadPlayer->ChangeState(aState); - if (err != OK) { - ResumeStateMachine(); + if (!mAudioOffloadPlayer) { + return; + } + + status_t err = mAudioOffloadPlayer->ChangeState(aState); + if (err != OK) { + ResumeStateMachine(); + return; + } + + switch (mPlayState) { + case PLAY_STATE_SEEKING: + mSeekRequest.Begin(mAudioOffloadPlayer->Seek(mRequestedSeekTarget) + ->RefableThen(AbstractThread::MainThread(), __func__, static_cast(this), + &MediaDecoder::OnSeekResolved, &MediaDecoder::OnSeekRejected)); + mRequestedSeekTarget.Reset(); + break; + default: { + break; } } } diff --git a/dom/media/tests/mochitest/identity/idp.js b/dom/media/tests/mochitest/identity/idp.js index b4c3cc73d5dd..36c9e3d0e672 100644 --- a/dom/media/tests/mochitest/identity/idp.js +++ b/dom/media/tests/mochitest/identity/idp.js @@ -1,10 +1,10 @@ (function(global) { - "use strict"; + 'use strict'; // rather than create a million different IdP configurations and litter the // world with files all containing near-identical code, let's use the hash/URL // fragment as a way of generating instructions for the IdP - var instructions = global.location.hash.replace("#", "").split(":"); + var instructions = global.location.hash.replace('#', '').split(':'); function is(target) { return function(instruction) { return instruction === target; @@ -16,35 +16,55 @@ var path = global.location.pathname; this.protocol = path.substring(path.lastIndexOf('/') + 1) + global.location.hash; + this.id = crypto.getRandomValues(new Uint8Array(10)).join('.'); } - function borkResult(result) { - if (instructions.some(is("throw"))) { - throw new Error('Throwing!'); - } - if (instructions.some(is("fail"))) { - return Promise.reject(new Error('Failing!')); - } - if (instructions.some(is("loginerror"))) { - return Promise.reject({ - name: 'IdpLoginError', - loginUrl: 'https://example.com/log/in/here' - }); - } - if (instructions.some(is("hang"))) { - return new Promise(r => {}); - } - dump('idp: result=' + JSON.stringify(result) + '\n'); - return Promise.resolve(result); - }; - IDPJS.prototype = { + getLogin: function() { + var xhr = new XMLHttpRequest(); + xhr.open('GET', 'https://example.com/.well-known/idp-proxy/idp.sjs?' + this.id); + return new Promise(resolve => { + xhr.onload = e => resolve(xhr.status === 200); + xhr.send(); + }); + }, + checkLogin: function(result) { + return this.getLogin() + .then(loggedIn => { + if (loggedIn) { + return result; + } + return Promise.reject({ + name: 'IdpLoginError', + loginUrl: 'https://example.com/.well-known/idp-proxy/login.html#' + + this.id + }); + }); + }, + + borkResult: function(result) { + if (instructions.some(is('throw'))) { + throw new Error('Throwing!'); + } + if (instructions.some(is('fail'))) { + return Promise.reject(new Error('Failing!')); + } + if (instructions.some(is('login'))) { + return this.checkLogin(result); + } + if (instructions.some(is('hang'))) { + return new Promise(r => {}); + } + dump('idp: result=' + JSON.stringify(result) + '\n'); + return Promise.resolve(result); + }, + _selectUsername: function(usernameHint) { - var username = "someone@" + this.domain; + var username = 'someone@' + this.domain; if (usernameHint) { - var at = usernameHint.indexOf("@"); + var at = usernameHint.indexOf('@'); if (at < 0) { - username = usernameHint + "@" + this.domain; + username = usernameHint + '@' + this.domain; } else if (usernameHint.substring(at + 1) === this.domain) { username = usernameHint; } @@ -58,10 +78,10 @@ domain: this.domain, protocol: this.protocol }; - if (instructions.some(is("bad-assert"))) { + if (instructions.some(is('bad-assert'))) { idpDetails = {}; } - return borkResult({ + return this.borkResult({ idp: idpDetails, assertion: JSON.stringify({ username: this._selectUsername(usernameHint), @@ -73,17 +93,17 @@ validateAssertion: function(assertion, origin) { dump('idp: validateAssertion(' + assertion + ')\n'); var assertion = JSON.parse(assertion); - if (instructions.some(is("bad-validate"))) { + if (instructions.some(is('bad-validate'))) { assertion.contents = {}; } - return borkResult({ + return this.borkResult({ identity: assertion.username, contents: assertion.contents }); } }; - if (!instructions.some(is("not_ready"))) { + if (!instructions.some(is('not_ready'))) { dump('registering idp.js' + global.location.hash + '\n'); global.rtcIdentityProvider.register(new IDPJS()); } diff --git a/dom/media/tests/mochitest/identity/idp.sjs b/dom/media/tests/mochitest/identity/idp.sjs new file mode 100644 index 000000000000..b6313297bc2b --- /dev/null +++ b/dom/media/tests/mochitest/identity/idp.sjs @@ -0,0 +1,18 @@ +function handleRequest(request, response) { + var key = '/.well-known/idp-proxy/' + request.queryString; + dump(getState(key) + '\n'); + if (request.method === 'GET') { + if (getState(key)) { + response.setStatusLine(request.httpVersion, 200, 'OK'); + } else { + response.setStatusLine(request.httpVersion, 404, 'Not Found'); + } + } else if (request.method === 'PUT') { + setState(key, 'OK'); + response.setStatusLine(request.httpVersion, 200, 'OK'); + } else { + response.setStatusLine(request.httpVersion, 406, 'Method Not Allowed'); + } + response.setHeader('Content-Type', 'text/plain;charset=UTF-8'); + response.write('OK'); +} diff --git a/dom/media/tests/mochitest/identity/login.html b/dom/media/tests/mochitest/identity/login.html new file mode 100644 index 000000000000..eafba22f2d2e --- /dev/null +++ b/dom/media/tests/mochitest/identity/login.html @@ -0,0 +1,31 @@ + + + + Identity Provider Login + + + +
Logging in...
+ + diff --git a/dom/media/tests/mochitest/identity/mochitest.ini b/dom/media/tests/mochitest/identity/mochitest.ini index f6dc1d252e7e..f93b62623537 100644 --- a/dom/media/tests/mochitest/identity/mochitest.ini +++ b/dom/media/tests/mochitest/identity/mochitest.ini @@ -27,6 +27,11 @@ support-files = [test_setIdentityProviderWithErrors.html] [test_peerConnection_peerIdentity.html] [test_peerConnection_asymmetricIsolation.html] +[test_loginNeeded.html] +support-files = + /.well-known/idp-proxy/login.html + /.well-known/idp-proxy/idp.sjs + # Bug 950317: Hack for making a cleanup hook after finishing all WebRTC cases [../test_zmedia_cleanup.html] diff --git a/dom/media/tests/mochitest/identity/test_fingerprints.html b/dom/media/tests/mochitest/identity/test_fingerprints.html index 6c5944996b60..fd1ab95c60f4 100644 --- a/dom/media/tests/mochitest/identity/test_fingerprints.html +++ b/dom/media/tests/mochitest/identity/test_fingerprints.html @@ -12,7 +12,7 @@ function getIdentityAssertion(fpArray) { var Cu = SpecialPowers.Cu; var rtcid = Cu.import('resource://gre/modules/media/IdpSandbox.jsm'); - var sandbox = new rtcid.IdpSandbox('example.com', 'idp.js'); + var sandbox = new rtcid.IdpSandbox('example.com', 'idp.js', window.document); return sandbox.start() .then(idp => SpecialPowers.wrap(idp) .generateAssertion(JSON.stringify({ fingerprint: fpArray }), diff --git a/dom/media/tests/mochitest/identity/test_getIdentityAssertion.html b/dom/media/tests/mochitest/identity/test_getIdentityAssertion.html index 7ec4a28c8ed5..e4bfe771dc6e 100644 --- a/dom/media/tests/mochitest/identity/test_getIdentityAssertion.html +++ b/dom/media/tests/mochitest/identity/test_getIdentityAssertion.html @@ -55,11 +55,12 @@ function theTest() { }, function PC_LOCAL_IDP_LOGIN_ERROR(t) { - return getAssertion(t, '#loginerror') - .then(a => ok(false, '#loginerror should not work'), + return getAssertion(t, '#login') + .then(a => ok(false, '#login should not work'), e => { is(e.name, 'IdpLoginError', 'name is IdpLoginError'); - is(t.pcLocal._pc.idpLoginUrl, 'https://example.com/log/in/here', + is(t.pcLocal._pc.idpLoginUrl.split('#')[0], + 'https://example.com/.well-known/idp-proxy/login.html', 'got the right login URL from the IdP'); }); }, diff --git a/dom/media/tests/mochitest/identity/test_idpproxy.html b/dom/media/tests/mochitest/identity/test_idpproxy.html index cc43c188a2cb..844f38fdf73a 100644 --- a/dom/media/tests/mochitest/identity/test_idpproxy.html +++ b/dom/media/tests/mochitest/identity/test_idpproxy.html @@ -26,7 +26,7 @@ function test_domain_sandbox() { '', 12, null, diabolical, true ]; domains.forEach(function(domain) { try { - var idp = new IdpSandbox(domain); + var idp = new IdpSandbox(domain, undefined, window.document); ok(false, 'IdpSandbox allowed a bad domain: ' + domain); } catch (e) { var str = (typeof domain === 'string') ? domain : typeof domain; @@ -40,7 +40,7 @@ function test_protocol_sandbox() { '\\evil', '%5cevil', 12, true, {} ]; protos.forEach(function(proto) { try { - var idp = new IdpSandbox('example.com', proto); + var idp = new IdpSandbox('example.com', proto, window.document); ok(false, 'IdpSandbox allowed a bad protocol: ' + proto); } catch (e) { var str = (typeof proto === 'string') ? proto : typeof proto; @@ -56,7 +56,7 @@ function idpName(hash) { function makeSandbox(js) { var name = js || idpName(); info('Creating a sandbox for the protocol: ' + name); - var sandbox = new IdpSandbox('example.com', name); + var sandbox = new IdpSandbox('example.com', name, window.document); return sandbox.start().then(idp => SpecialPowers.wrap(idp)); } diff --git a/dom/media/tests/mochitest/identity/test_loginNeeded.html b/dom/media/tests/mochitest/identity/test_loginNeeded.html new file mode 100644 index 000000000000..4c95a7978e87 --- /dev/null +++ b/dom/media/tests/mochitest/identity/test_loginNeeded.html @@ -0,0 +1,71 @@ + + + + + + + +
+
+
+ + diff --git a/dom/webidl/Document.webidl b/dom/webidl/Document.webidl index d385bf73c9f1..509046f4dee3 100644 --- a/dom/webidl/Document.webidl +++ b/dom/webidl/Document.webidl @@ -10,6 +10,7 @@ interface WindowProxy; interface nsISupports; interface URI; interface nsIDocShell; +interface nsILoadGroup; enum VisibilityState { "hidden", "visible" }; @@ -354,6 +355,8 @@ partial interface Document { [ChromeOnly] readonly attribute nsIDocShell? docShell; [ChromeOnly] readonly attribute DOMString contentLanguage; + + [ChromeOnly] readonly attribute nsILoadGroup? documentLoadGroup; }; // Extension to give chrome JS the ability to determine when a document was diff --git a/dom/webidl/Navigator.webidl b/dom/webidl/Navigator.webidl index db2d86b0732a..175e75262489 100644 --- a/dom/webidl/Navigator.webidl +++ b/dom/webidl/Navigator.webidl @@ -47,6 +47,7 @@ interface NavigatorID { readonly attribute DOMString product; // constant "Gecko" // Everyone but WebKit/Blink supports this. See bug 679971. + [Exposed=Window] boolean taintEnabled(); // constant false }; diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index b16d5f2b26d6..616ef8c76cdf 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -3996,17 +3996,16 @@ WorkerPrivateParent::SetBaseURI(nsIURI* aBaseURI) mLocationInfo.mHref.Truncate(); } - if (NS_FAILED(aBaseURI->GetHost(mLocationInfo.mHostname))) { - mLocationInfo.mHostname.Truncate(); - } + mLocationInfo.mHostname.Truncate(); + nsContentUtils::GetHostOrIPv6WithBrackets(aBaseURI, mLocationInfo.mHostname); - if (NS_FAILED(aBaseURI->GetPath(mLocationInfo.mPathname))) { + nsCOMPtr url(do_QueryInterface(aBaseURI)); + if (!url || NS_FAILED(url->GetFilePath(mLocationInfo.mPathname))) { mLocationInfo.mPathname.Truncate(); } nsCString temp; - nsCOMPtr url(do_QueryInterface(aBaseURI)); if (url && NS_SUCCEEDED(url->GetQuery(temp)) && !temp.IsEmpty()) { mLocationInfo.mSearch.Assign('?'); mLocationInfo.mSearch.Append(temp); diff --git a/dom/workers/test/navigator_worker.js b/dom/workers/test/navigator_worker.js index ed2bb40e1ae9..2af41014bec2 100644 --- a/dom/workers/test/navigator_worker.js +++ b/dom/workers/test/navigator_worker.js @@ -11,7 +11,6 @@ var supportedProps = [ { name: "getDataStores", b2g: true }, "platform", "product", - "taintEnabled", "userAgent", "onLine", "language", @@ -66,9 +65,7 @@ function startTest(isB2G) { obj = { name: prop }; - if (prop === "taintEnabled") { - obj.value = navigator[prop](); - } else if (prop === "getDataStores") { + if (prop === "getDataStores") { obj.value = typeof navigator[prop]; } else { obj.value = navigator[prop]; diff --git a/dom/workers/test/test_navigator.html b/dom/workers/test/test_navigator.html index d54152778aef..2f3fc897f287 100644 --- a/dom/workers/test/test_navigator.html +++ b/dom/workers/test/test_navigator.html @@ -35,11 +35,6 @@ Tests of DOM Worker Navigator return; } - if (args.name === "taintEnabled") { - is(navigator[args.name](), args.value, args.name + "() returns false."); - return; - } - if (args.name === "getDataStores") { var type = typeof navigator[args.name]; is(type, args.value, "getDataStores() exists and it's a function."); diff --git a/dom/workers/test/urlApi_worker.js b/dom/workers/test/urlApi_worker.js index a8b88e046fa3..0fb3ae1c9eb0 100644 --- a/dom/workers/test/urlApi_worker.js +++ b/dom/workers/test/urlApi_worker.js @@ -111,7 +111,7 @@ onmessage = function() { { url: 'http://example.com/carrot#question%3f', base: undefined, error: false, - hash: '#question%3f' + hash: '#question?' }, { url: 'https://example.com:4443?', base: undefined, diff --git a/js/src/builtin/AtomicsObject.cpp b/js/src/builtin/AtomicsObject.cpp index 98a11d4d50d0..58a716fdc4fd 100644 --- a/js/src/builtin/AtomicsObject.cpp +++ b/js/src/builtin/AtomicsObject.cpp @@ -55,8 +55,8 @@ #include "prmjtime.h" +#include "asmjs/AsmJSModule.h" #include "jit/AtomicOperations.h" - #include "js/Class.h" #include "vm/GlobalObject.h" #include "vm/SharedTypedArrayObject.h" diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index 7a900b705935..d06ef3dc772e 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -1503,7 +1503,7 @@ js::testingFunc_inJit(JSContext* cx, unsigned argc, jsval* vp) { CallArgs args = CallArgsFromVp(argc, vp); - if (!IsBaselineEnabled(cx)) { + if (!jit::IsBaselineEnabled(cx)) { JSString* error = JS_NewStringCopyZ(cx, "Baseline is disabled."); if(!error) return false; @@ -1531,7 +1531,7 @@ js::testingFunc_inIon(JSContext* cx, unsigned argc, jsval* vp) { CallArgs args = CallArgsFromVp(argc, vp); - if (!IsIonEnabled(cx)) { + if (!jit::IsIonEnabled(cx)) { JSString* error = JS_NewStringCopyZ(cx, "Ion is disabled."); if (!error) return false; diff --git a/js/src/ds/IdValuePair.h b/js/src/ds/IdValuePair.h index b77c3079194d..2fa220d69303 100644 --- a/js/src/ds/IdValuePair.h +++ b/js/src/ds/IdValuePair.h @@ -7,8 +7,9 @@ #ifndef ds_IdValuePair_h #define ds_IdValuePair_h -#include "NamespaceImports.h" +#include "jsapi.h" +#include "NamespaceImports.h" #include "js/Id.h" namespace js { diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index c4f67dfc019e..bd8162c1553f 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -977,13 +977,13 @@ BytecodeEmitter::leaveNestedScope(StmtInfoBCE* stmt) if (!emit1(stmt->isBlockScope ? JSOP_DEBUGLEAVEBLOCK : JSOP_LEAVEWITH)) return false; - blockScopeList.recordEnd(blockScopeIndex, offset()); - if (stmt->isBlockScope && stmt->staticScope->as().needsClone()) { if (!emit1(JSOP_POPBLOCKSCOPE)) return false; } + blockScopeList.recordEnd(blockScopeIndex, offset()); + return true; } diff --git a/js/src/gc/Allocator.cpp b/js/src/gc/Allocator.cpp index fe38f7fab470..b3f137f4e58c 100644 --- a/js/src/gc/Allocator.cpp +++ b/js/src/gc/Allocator.cpp @@ -346,7 +346,7 @@ ArenaLists::allocateFromArena(JS::Zone* zone, AllocKind thingKind, AutoMaybeStartBackgroundAllocation& maybeStartBGAlloc) { JSRuntime* rt = zone->runtimeFromAnyThread(); - Maybe maybeLock; + mozilla::Maybe maybeLock; // See if we can proceed without taking the GC lock. if (backgroundFinalizeState[thingKind] != BFS_DONE) diff --git a/js/src/jit-test/tests/debug/Frame-environment-05.js b/js/src/jit-test/tests/debug/Frame-environment-05.js new file mode 100644 index 000000000000..98f1c9a12624 --- /dev/null +++ b/js/src/jit-test/tests/debug/Frame-environment-05.js @@ -0,0 +1,9 @@ +// Test that Debugger.Frame.prototype.environment works at all pcs of a script +// with an aliased block scope. + +var g = newGlobal(); +var dbg = new Debugger(g); +dbg.onDebuggerStatement = function (frame) { + frame.onStep = (function () { frame.environment; }); +}; +g.eval("debugger; for (let i of [1,2,3]) print(i);"); diff --git a/js/src/jit-test/tests/debug/bug1147939.js b/js/src/jit-test/tests/debug/bug1147939.js new file mode 100644 index 000000000000..a2bd2cf798de --- /dev/null +++ b/js/src/jit-test/tests/debug/bug1147939.js @@ -0,0 +1,8 @@ +// |jit-test| error: TypeError +var g = newGlobal(); +g.debuggeeGlobal = this; +g.eval("(" + function () { + dbg = new Debugger(debuggeeGlobal); + dbg.onExceptionUnwind = Map; +} + ")();"); +throw new Error("oops"); diff --git a/js/src/jit/JSONSpewer.cpp b/js/src/jit/JSONSpewer.cpp index 087cd19d6ca7..91d462f03b93 100644 --- a/js/src/jit/JSONSpewer.cpp +++ b/js/src/jit/JSONSpewer.cpp @@ -8,6 +8,7 @@ #include +#include "jit/BacktrackingAllocator.h" #include "jit/LIR.h" #include "jit/MIR.h" #include "jit/MIRGraph.h" diff --git a/js/src/jit/JitcodeMap.cpp b/js/src/jit/JitcodeMap.cpp index d37c41fe2cb3..4fbc4805503c 100644 --- a/js/src/jit/JitcodeMap.cpp +++ b/js/src/jit/JitcodeMap.cpp @@ -1532,8 +1532,8 @@ JitcodeIonTable::WriteIonTable(CompactBufferWriter& writer, JS_PUBLIC_API(JS::ProfilingFrameIterator::FrameKind) JS::GetProfilingFrameKindFromNativeAddr(JSRuntime* rt, void* addr) { - JitcodeGlobalTable* table = rt->jitRuntime()->getJitcodeGlobalTable(); - JitcodeGlobalEntry entry; + js::jit::JitcodeGlobalTable* table = rt->jitRuntime()->getJitcodeGlobalTable(); + js::jit::JitcodeGlobalEntry entry; table->lookupInfallible(addr, &entry, rt); MOZ_ASSERT(entry.isIon() || entry.isIonCache() || entry.isBaseline()); diff --git a/js/src/jit/x86-shared/Architecture-x86-shared.cpp b/js/src/jit/x86-shared/Architecture-x86-shared.cpp index 86c1a2ff2f1e..5386420b0fdf 100644 --- a/js/src/jit/x86-shared/Architecture-x86-shared.cpp +++ b/js/src/jit/x86-shared/Architecture-x86-shared.cpp @@ -9,8 +9,10 @@ # error "Wrong architecture. Only x86 and x64 should build this file!" #endif +#include "jit/RegisterSets.h" + const char* -FloatRegister::name() const { +js::jit::FloatRegister::name() const { static const char* const names[] = { #ifdef JS_CODEGEN_X64 @@ -38,8 +40,8 @@ FloatRegister::name() const { return names[size_t(code())]; } -FloatRegisterSet -FloatRegister::ReduceSetForPush(const FloatRegisterSet& s) +js::jit::FloatRegisterSet +js::jit::FloatRegister::ReduceSetForPush(const FloatRegisterSet& s) { SetType bits = s.bits(); @@ -58,7 +60,7 @@ FloatRegister::ReduceSetForPush(const FloatRegisterSet& s) } uint32_t -FloatRegister::GetPushSizeInBytes(const FloatRegisterSet& s) +js::jit::FloatRegister::GetPushSizeInBytes(const FloatRegisterSet& s) { SetType all = s.bits(); SetType float32x4Set = @@ -92,7 +94,7 @@ FloatRegister::GetPushSizeInBytes(const FloatRegisterSet& s) + count32b * sizeof(float); } uint32_t -FloatRegister::getRegisterDumpOffsetInBytes() +js::jit::FloatRegister::getRegisterDumpOffsetInBytes() { return uint32_t(encoding()) * sizeof(FloatRegisters::RegisterContent); } diff --git a/js/src/jit/x86-shared/Architecture-x86-shared.h b/js/src/jit/x86-shared/Architecture-x86-shared.h index 516acff83910..1d9966e1a302 100644 --- a/js/src/jit/x86-shared/Architecture-x86-shared.h +++ b/js/src/jit/x86-shared/Architecture-x86-shared.h @@ -11,6 +11,10 @@ # error "Unsupported architecture!" #endif +#include "mozilla/MathAlgorithms.h" + +#include + #include "jit/x86-shared/Constants-x86-shared.h" namespace js { diff --git a/js/src/jit/x86-shared/Constants-x86-shared.h b/js/src/jit/x86-shared/Constants-x86-shared.h index 8179f4644509..f3436addb8a4 100644 --- a/js/src/jit/x86-shared/Constants-x86-shared.h +++ b/js/src/jit/x86-shared/Constants-x86-shared.h @@ -7,6 +7,11 @@ #ifndef jit_x86_shared_Constants_x86_shared_h #define jit_x86_shared_Constants_x86_shared_h +#include "mozilla/ArrayUtils.h" +#include "mozilla/Assertions.h" + +#include + namespace js { namespace jit { diff --git a/js/src/jsapi-tests/testForwardSetProperty.cpp b/js/src/jsapi-tests/testForwardSetProperty.cpp index 59ad29d0f77c..04d537f990f2 100644 --- a/js/src/jsapi-tests/testForwardSetProperty.cpp +++ b/js/src/jsapi-tests/testForwardSetProperty.cpp @@ -45,7 +45,7 @@ BEGIN_TEST(testForwardSetProperty) // Non-strict setter - ObjectOpResult result; + JS::ObjectOpResult result; CHECK(JS_ForwardSetPropertyTo(cx, obj2, prop, setval, v3, result)); CHECK(result); diff --git a/js/src/jsapi-tests/testJSEvaluateScript.cpp b/js/src/jsapi-tests/testJSEvaluateScript.cpp index fb85fdb5a453..615b90c092de 100644 --- a/js/src/jsapi-tests/testJSEvaluateScript.cpp +++ b/js/src/jsapi-tests/testJSEvaluateScript.cpp @@ -4,6 +4,8 @@ #include "jsapi-tests/tests.h" +using mozilla::ArrayLength; + BEGIN_TEST(testJSEvaluateScript) { JS::RootedObject obj(cx, JS_NewPlainObject(cx)); diff --git a/js/src/jsapi-tests/tests.h b/js/src/jsapi-tests/tests.h index 7e3bef12e018..a57a0b7b218b 100644 --- a/js/src/jsapi-tests/tests.h +++ b/js/src/jsapi-tests/tests.h @@ -7,6 +7,7 @@ #ifndef jsapi_tests_tests_h #define jsapi_tests_tests_h +#include "mozilla/ArrayUtils.h" #include "mozilla/TypeTraits.h" #include diff --git a/js/src/jsexn.h b/js/src/jsexn.h index 240479cd7df5..1cdcac947e5d 100644 --- a/js/src/jsexn.h +++ b/js/src/jsexn.h @@ -125,7 +125,7 @@ class AutoClearPendingException { } ~AutoClearPendingException() { - cx->clearPendingException(); + JS_ClearPendingException(cx); } }; diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index 84be8689acbe..6adb4c895a5c 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -1753,7 +1753,13 @@ FindStartPC(JSContext* cx, const FrameIter& iter, int spindex, int skipStackHits if (spindex == JSDVG_SEARCH_STACK) { size_t index = iter.numFrameSlots(); - MOZ_ASSERT(index >= size_t(parser.stackDepthAtPC(current))); + + // The decompiler may be called from inside functions that are not + // called from script, but via the C++ API directly, such as + // Invoke. In that case, the youngest script frame may have a + // completely unrelated pc and stack depth, so we give up. + if (index < size_t(parser.stackDepthAtPC(current))) + return true; // We search from fp->sp to base to find the most recently calculated // value matching v under assumption that it is the value that caused diff --git a/js/src/jsscript.h b/js/src/jsscript.h index 712f13af5bc1..cff6eb48b94b 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -1634,6 +1634,9 @@ class JSScript : public js::gc::TenuredCell return arr->vector[index]; } + // The following 3 functions find the static scope just before the + // execution of the instruction pointed to by pc. + js::NestedScopeObject* getStaticBlockScope(jsbytecode* pc); // Returns the innermost static scope at pc if it falls within the extent diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 829b23399fc6..b48d454ebff2 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -2202,6 +2202,30 @@ TryNotes(JSContext* cx, HandleScript script, Sprinter* sp) return true; } +static bool +BlockNotes(JSContext* cx, HandleScript script, Sprinter* sp) +{ + if (!script->hasBlockScopes()) + return true; + + Sprint(sp, "\nBlock table:\n index parent start end\n"); + + BlockScopeArray* scopes = script->blockScopes(); + for (uint32_t i = 0; i < scopes->length; i++) { + const BlockScopeNote* note = &scopes->vector[i]; + if (note->index == BlockScopeNote::NoBlockScopeIndex) + Sprint(sp, "%8s ", "(none)"); + else + Sprint(sp, "%8u ", note->index); + if (note->parent == BlockScopeNote::NoBlockScopeIndex) + Sprint(sp, "%8s ", "(none)"); + else + Sprint(sp, "%8u ", note->parent); + Sprint(sp, "%8u %8u\n", note->start, note->start + note->length); + } + return true; +} + static bool DisassembleScript(JSContext* cx, HandleScript script, HandleFunction fun, bool lines, bool recursive, Sprinter* sp) @@ -2229,6 +2253,7 @@ DisassembleScript(JSContext* cx, HandleScript script, HandleFunction fun, bool l return false; SrcNotes(cx, script, sp); TryNotes(cx, script, sp); + BlockNotes(cx, script, sp); if (recursive && script->hasObjects()) { ObjectArray* objects = script->objects(); @@ -2299,6 +2324,7 @@ DisassembleToSprinter(JSContext* cx, unsigned argc, jsval* vp, Sprinter* sprinte return false; SrcNotes(cx, script, sprinter); TryNotes(cx, script, sprinter); + BlockNotes(cx, script, sprinter); } } else { for (unsigned i = 0; i < p.argc; i++) { @@ -4314,7 +4340,7 @@ SetSharedArrayBuffer(JSContext* cx, unsigned argc, Value* vp) return true; } -class SprintOptimizationTypeInfoOp : public ForEachTrackedOptimizationTypeInfoOp +class SprintOptimizationTypeInfoOp : public JS::ForEachTrackedOptimizationTypeInfoOp { Sprinter* sp; bool startedTypes_; @@ -4345,7 +4371,7 @@ class SprintOptimizationTypeInfoOp : public ForEachTrackedOptimizationTypeInfoOp Sprint(sp, "},"); } - void operator()(TrackedTypeSite site, const char* mirType) override { + void operator()(JS::TrackedTypeSite site, const char* mirType) override { if (startedTypes_) { // Clear trailing , if ((*sp)[sp->getOffset() - 1] == ',') @@ -4361,7 +4387,7 @@ class SprintOptimizationTypeInfoOp : public ForEachTrackedOptimizationTypeInfoOp } }; -class SprintOptimizationAttemptsOp : public ForEachTrackedOptimizationAttemptOp +class SprintOptimizationAttemptsOp : public JS::ForEachTrackedOptimizationAttemptOp { Sprinter* sp; @@ -4370,7 +4396,7 @@ class SprintOptimizationAttemptsOp : public ForEachTrackedOptimizationAttemptOp : sp(sp) { } - void operator()(TrackedStrategy strategy, TrackedOutcome outcome) override { + void operator()(JS::TrackedStrategy strategy, JS::TrackedOutcome outcome) override { Sprint(sp, "{\"strategy\":\"%s\",\"outcome\":\"%s\"},", TrackedStrategyString(strategy), TrackedOutcomeString(outcome)); } diff --git a/js/src/vm/ScopeObject.cpp b/js/src/vm/ScopeObject.cpp index 7f64b85ade3b..e5eed90776d3 100644 --- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -2490,6 +2490,7 @@ js::GetDebugScopeForFrame(JSContext* cx, AbstractFramePtr frame, jsbytecode* pc) assertSameCompartment(cx, frame); if (CanUseDebugScopeMaps(cx) && !DebugScopes::updateLiveScopes(cx)) return nullptr; + ScopeIter si(cx, frame, pc); return GetDebugScope(cx, si); } diff --git a/layout/generic/nsRubyBaseContainerFrame.cpp b/layout/generic/nsRubyBaseContainerFrame.cpp index 1dfad7c0545f..38be52b9ee89 100644 --- a/layout/generic/nsRubyBaseContainerFrame.cpp +++ b/layout/generic/nsRubyBaseContainerFrame.cpp @@ -382,10 +382,6 @@ nsRubyBaseContainerFrame::Reflow(nsPresContext* aPresContext, }; nscoord spanISize = ReflowSpans(reflowState); isize = std::max(isize, spanISize); - if (isize > aReflowState.AvailableISize() && - aReflowState.mLineLayout->HasOptionalBreakPosition()) { - aStatus = NS_INLINE_LINE_BREAK_BEFORE(); - } } for (uint32_t i = 0; i < rtcCount; i++) { diff --git a/layout/style/html.css b/layout/style/html.css index 422e59d13fbf..d56615882926 100644 --- a/layout/style/html.css +++ b/layout/style/html.css @@ -803,8 +803,6 @@ marquee[direction="up"], marquee[direction="down"] { } rt { display: ruby-text; - font-variant-east-asian: ruby; - text-emphasis: none; } rtc { display: ruby-text-container; @@ -813,6 +811,12 @@ marquee[direction="up"], marquee[direction="down"] { white-space: nowrap; font-size: 50%; line-height: 1; + font-variant-east-asian: ruby; + } + @supports (text-emphasis: none) { + rtc, rt { + text-emphasis: none; + } } rtc:lang(zh), rt:lang(zh) { ruby-align: center; diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index ab13addf0517..57ccc8ee227a 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -171,7 +171,7 @@ pref("dom.undo_manager.enabled", false); // Whether URL,nsLocation,Link::GetHash should be percent encoded // in setter and percent decoded in getter (old behaviour = true) -pref("dom.url.encode_decode_hash", false); +pref("dom.url.encode_decode_hash", true); // Whether to run add-on code in different compartments from browser code. This // causes a separate compartment for each (addon, global) combination, which may diff --git a/testing/web-platform/meta/url/a-element.html.ini b/testing/web-platform/meta/url/a-element.html.ini index 9ce7262da01b..d1dac0a6df3c 100644 --- a/testing/web-platform/meta/url/a-element.html.ini +++ b/testing/web-platform/meta/url/a-element.html.ini @@ -342,3 +342,17 @@ [Parsing: against ] expected: FAIL + [Parsing: against ] + expected: FAIL + + [Parsing: <#\xce\xb2> against ] + expected: FAIL + + [Parsing: against ] + expected: FAIL + + [Parsing: <#β> against ] + expected: FAIL + + [Parsing: against ] + expected: FAIL diff --git a/testing/web-platform/meta/url/a-element.xhtml.ini b/testing/web-platform/meta/url/a-element.xhtml.ini index 11424efbae47..f2353e7ef2a8 100644 --- a/testing/web-platform/meta/url/a-element.xhtml.ini +++ b/testing/web-platform/meta/url/a-element.xhtml.ini @@ -361,3 +361,17 @@ [Parsing: against ] expected: FAIL + [Parsing: against ] + expected: FAIL + + [Parsing: <#\xce\xb2> against ] + expected: FAIL + + [Parsing: against ] + expected: FAIL + + [Parsing: <#β> against ] + expected: FAIL + + [Parsing: against ] + expected: FAIL diff --git a/testing/web-platform/meta/workers/MessagePort_initial_disabled.htm.ini b/testing/web-platform/meta/workers/MessagePort_initial_disabled.htm.ini index 1718c77fbc32..b73019ab98b6 100644 --- a/testing/web-platform/meta/workers/MessagePort_initial_disabled.htm.ini +++ b/testing/web-platform/meta/workers/MessagePort_initial_disabled.htm.ini @@ -2,4 +2,5 @@ type: testharness [ MessageChannel: port message queue is initially disabled ] expected: FAIL + bug: https://bugzilla.mozilla.org/show_bug.cgi?id=952139 diff --git a/testing/web-platform/meta/workers/MessagePort_onmessage_start.htm.ini b/testing/web-platform/meta/workers/MessagePort_onmessage_start.htm.ini index 5036ad4949f1..ad6a4484ea3a 100644 --- a/testing/web-platform/meta/workers/MessagePort_onmessage_start.htm.ini +++ b/testing/web-platform/meta/workers/MessagePort_onmessage_start.htm.ini @@ -2,4 +2,5 @@ type: testharness [ MessageChannel: port.onmessage enables message queue ] expected: FAIL + bug: https://bugzilla.mozilla.org/show_bug.cgi?id=952139 diff --git a/testing/web-platform/meta/workers/WorkerLocation_hash_encoding.htm.ini b/testing/web-platform/meta/workers/WorkerLocation_hash_encoding.htm.ini new file mode 100644 index 000000000000..b5f8ce62ce3f --- /dev/null +++ b/testing/web-platform/meta/workers/WorkerLocation_hash_encoding.htm.ini @@ -0,0 +1,4 @@ +[WorkerLocation_hash_encoding.htm] + type: testharness + [ WorkerLocation.hash with url encoding string ] + expected: FAIL diff --git a/testing/web-platform/meta/workers/interfaces.worker.js.ini b/testing/web-platform/meta/workers/interfaces.worker.js.ini index 3b7db9e3e117..2a1d43ee8b53 100644 --- a/testing/web-platform/meta/workers/interfaces.worker.js.ini +++ b/testing/web-platform/meta/workers/interfaces.worker.js.ini @@ -2,6 +2,7 @@ type: testharness [WorkerGlobalScope interface: attribute onlanguagechange] expected: FAIL + bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1154779 [WorkerGlobalScope interface: operation importScripts(DOMString)] expected: FAIL @@ -29,6 +30,7 @@ [WorkerGlobalScope interface: self must inherit property "onlanguagechange" with the proper type (4)] expected: FAIL + bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1154779 [WorkerGlobalScope interface: calling importScripts(DOMString) on self with too few arguments must throw TypeError] expected: FAIL diff --git a/testing/web-platform/meta/workers/interfaces/WorkerGlobalScope/location/members.html.ini b/testing/web-platform/meta/workers/interfaces/WorkerGlobalScope/location/members.html.ini deleted file mode 100644 index d708f6da6f97..000000000000 --- a/testing/web-platform/meta/workers/interfaces/WorkerGlobalScope/location/members.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[members.html] - type: testharness - [members of WorkerLocation] - expected: FAIL - diff --git a/testing/web-platform/meta/workers/interfaces/WorkerGlobalScope/location/redirect.html.ini b/testing/web-platform/meta/workers/interfaces/WorkerGlobalScope/location/redirect.html.ini deleted file mode 100644 index 55aa2aab8ac1..000000000000 --- a/testing/web-platform/meta/workers/interfaces/WorkerGlobalScope/location/redirect.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[redirect.html] - type: testharness - [location with a worker in separate file that redirects] - expected: FAIL - diff --git a/testing/web-platform/meta/workers/interfaces/WorkerGlobalScope/location/setting-members.html.ini b/testing/web-platform/meta/workers/interfaces/WorkerGlobalScope/location/setting-members.html.ini deleted file mode 100644 index 9ee10df13e6d..000000000000 --- a/testing/web-platform/meta/workers/interfaces/WorkerGlobalScope/location/setting-members.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[setting-members.html] - type: testharness - [setting members of WorkerLocation] - expected: FAIL - diff --git a/testing/web-platform/meta/workers/interfaces/WorkerGlobalScope/location/worker-separate-file.html.ini b/testing/web-platform/meta/workers/interfaces/WorkerGlobalScope/location/worker-separate-file.html.ini deleted file mode 100644 index e1a42889a543..000000000000 --- a/testing/web-platform/meta/workers/interfaces/WorkerGlobalScope/location/worker-separate-file.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[worker-separate-file.html] - type: testharness - [location with a worker in separate file] - expected: FAIL - diff --git a/testing/web-platform/meta/workers/interfaces/WorkerUtils/navigator/007.html.ini b/testing/web-platform/meta/workers/interfaces/WorkerUtils/navigator/007.html.ini deleted file mode 100644 index da00d503cb81..000000000000 --- a/testing/web-platform/meta/workers/interfaces/WorkerUtils/navigator/007.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[007.html] - type: testharness - [readonlyness of members of Navigator] - expected: FAIL - diff --git a/testing/web-platform/meta/workers/postMessage_event_properties.htm.ini b/testing/web-platform/meta/workers/postMessage_event_properties.htm.ini index fe0d346ebfe9..f757a6627716 100644 --- a/testing/web-platform/meta/workers/postMessage_event_properties.htm.ini +++ b/testing/web-platform/meta/workers/postMessage_event_properties.htm.ini @@ -2,4 +2,5 @@ type: testharness [ postMessage(): MessageEvent properties ] expected: FAIL + bug: https://bugzilla.mozilla.org/show_bug.cgi?id=952139 diff --git a/testing/web-platform/tests/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.js b/testing/web-platform/tests/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.js index a7e8b1dba8e2..508953161913 100644 --- a/testing/web-platform/tests/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.js +++ b/testing/web-platform/tests/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.js @@ -22,10 +22,6 @@ function run_test() { assert_equals(navigator.product, "Gecko"); }, "product"); - test(function() { - assert_false(navigator.taintEnabled()); - }, "taintEnabled"); - test(function() { assert_equals(typeof navigator.userAgent, "string", "navigator.userAgent should be a string"); diff --git a/testing/web-platform/tests/workers/interfaces.idl b/testing/web-platform/tests/workers/interfaces.idl index 5bfd28835257..7b30ba563013 100644 --- a/testing/web-platform/tests/workers/interfaces.idl +++ b/testing/web-platform/tests/workers/interfaces.idl @@ -96,7 +96,6 @@ interface NavigatorID { readonly attribute DOMString appVersion; readonly attribute DOMString platform; readonly attribute DOMString product; // constant "Gecko" - boolean taintEnabled(); // constant false readonly attribute DOMString userAgent; }; diff --git a/testing/web-platform/tests/workers/interfaces/WorkerGlobalScope/location/redirect.html b/testing/web-platform/tests/workers/interfaces/WorkerGlobalScope/location/redirect.html index d939dc150da1..2fd16a4c163e 100644 --- a/testing/web-platform/tests/workers/interfaces/WorkerGlobalScope/location/redirect.html +++ b/testing/web-platform/tests/workers/interfaces/WorkerGlobalScope/location/redirect.html @@ -9,7 +9,7 @@