зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to m-c.
This commit is contained in:
Коммит
d76da7eade
|
@ -22,7 +22,8 @@ export MOZ_TELEMETRY_REPORTING=1
|
|||
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
|
||||
# DISABLED WHILE NOT ON TRY ac_add_options --enable-warnings-as-errors
|
||||
|
||||
# Use ccache
|
||||
# Use sccache
|
||||
no_sccache=
|
||||
. "$topsrcdir/build/mozconfig.cache"
|
||||
|
||||
#B2G options
|
||||
|
|
12
configure.in
12
configure.in
|
@ -7891,15 +7891,15 @@ else
|
|||
fi
|
||||
AC_SUBST(CL_INCLUDES_PREFIX)
|
||||
rm -f dummy-hello.c
|
||||
|
||||
dnl Make sure that the build system can handle non-ASCII characters
|
||||
dnl in environment variables to prevent it from breaking silently on
|
||||
dnl non-English systems.
|
||||
NONASCII=$'\241\241'
|
||||
AC_SUBST(NONASCII)
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl Make sure that the build system can handle non-ASCII characters
|
||||
dnl in environment variables to prevent it from breking silently on
|
||||
dnl non-English systems.
|
||||
NONASCII=$'\241\241'
|
||||
AC_SUBST(NONASCII)
|
||||
|
||||
dnl ========================================================
|
||||
dnl =
|
||||
dnl = Static Build Options
|
||||
|
|
|
@ -92,6 +92,7 @@ class ImageLoader;
|
|||
} // namespace css
|
||||
|
||||
namespace dom {
|
||||
class AnimationTimeline;
|
||||
class Attr;
|
||||
class CDATASection;
|
||||
class Comment;
|
||||
|
@ -1859,6 +1860,8 @@ public:
|
|||
|
||||
virtual already_AddRefed<mozilla::dom::UndoManager> GetUndoManager() = 0;
|
||||
|
||||
virtual mozilla::dom::AnimationTimeline* Timeline() = 0;
|
||||
|
||||
typedef mozilla::dom::CallbackObjectHolder<
|
||||
mozilla::dom::FrameRequestCallback,
|
||||
nsIFrameRequestCallback> FrameRequestCallbackHolder;
|
||||
|
|
|
@ -191,6 +191,7 @@
|
|||
#include "nsWrapperCacheInlines.h"
|
||||
#include "nsSandboxFlags.h"
|
||||
#include "nsIAppsService.h"
|
||||
#include "mozilla/dom/AnimationTimeline.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/DocumentFragment.h"
|
||||
#include "mozilla/dom/Event.h"
|
||||
|
@ -1961,6 +1962,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument)
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCachedEncoder)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStateObjectCached)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mUndoManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAnimationTimeline)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTemplateContentsOwner)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildrenCollection)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRegistry)
|
||||
|
@ -2030,6 +2032,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
|
|||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOriginalDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCachedEncoder)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mUndoManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mAnimationTimeline)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTemplateContentsOwner)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mChildrenCollection)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mRegistry)
|
||||
|
@ -3131,6 +3134,16 @@ nsDocument::GetUndoManager()
|
|||
return undoManager.forget();
|
||||
}
|
||||
|
||||
AnimationTimeline*
|
||||
nsDocument::Timeline()
|
||||
{
|
||||
if (!mAnimationTimeline) {
|
||||
mAnimationTimeline = new AnimationTimeline(this);
|
||||
}
|
||||
|
||||
return mAnimationTimeline;
|
||||
}
|
||||
|
||||
/* Return true if the document is in the focused top-level window, and is an
|
||||
* ancestor of the focused DOMWindow. */
|
||||
NS_IMETHODIMP
|
||||
|
@ -12130,8 +12143,9 @@ nsIDocument::WrapObject(JSContext *aCx)
|
|||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(GetInnerWindow());
|
||||
if (!win) {
|
||||
// No window, nothing else to do here
|
||||
if (!win ||
|
||||
static_cast<nsGlobalWindow*>(win.get())->IsDOMBinding()) {
|
||||
// No window or window on new DOM binding, nothing else to do here.
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
|
|
@ -770,6 +770,8 @@ public:
|
|||
|
||||
virtual already_AddRefed<mozilla::dom::UndoManager> GetUndoManager() MOZ_OVERRIDE;
|
||||
|
||||
virtual mozilla::dom::AnimationTimeline* Timeline() MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult SetSubDocumentFor(Element* aContent,
|
||||
nsIDocument* aSubDoc) MOZ_OVERRIDE;
|
||||
virtual nsIDocument* GetSubDocumentFor(nsIContent* aContent) const MOZ_OVERRIDE;
|
||||
|
@ -1635,6 +1637,8 @@ private:
|
|||
|
||||
nsRefPtr<mozilla::dom::UndoManager> mUndoManager;
|
||||
|
||||
nsRefPtr<mozilla::dom::AnimationTimeline> mAnimationTimeline;
|
||||
|
||||
enum ViewportType {
|
||||
DisplayWidthHeight,
|
||||
DisplayWidthHeightNoZoom,
|
||||
|
|
|
@ -1337,10 +1337,10 @@ WebGLContext::GetSurfaceSnapshot(bool* aPremultAlpha)
|
|||
if (!gl)
|
||||
return nullptr;
|
||||
|
||||
nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(gfxIntSize(mWidth, mHeight),
|
||||
gfxImageFormat::ARGB32,
|
||||
mWidth * 4, 0, false);
|
||||
if (surf->CairoStatus() != 0) {
|
||||
RefPtr<DataSourceSurface> surf = Factory::CreateDataSourceSurfaceWithStride(IntSize(mWidth, mHeight),
|
||||
SurfaceFormat::B8G8R8A8,
|
||||
mWidth * 4);
|
||||
if (!surf) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1348,7 +1348,7 @@ WebGLContext::GetSurfaceSnapshot(bool* aPremultAlpha)
|
|||
{
|
||||
ScopedBindFramebuffer autoFB(gl, 0);
|
||||
ClearBackbufferIfNeeded();
|
||||
ReadPixelsIntoImageSurface(gl, surf);
|
||||
ReadPixelsIntoDataSurface(gl, surf);
|
||||
}
|
||||
|
||||
if (aPremultAlpha) {
|
||||
|
@ -1359,8 +1359,7 @@ WebGLContext::GetSurfaceSnapshot(bool* aPremultAlpha)
|
|||
if (aPremultAlpha) {
|
||||
*aPremultAlpha = false;
|
||||
} else {
|
||||
gfxUtils::PremultiplyImageSurface(surf);
|
||||
surf->MarkDirty();
|
||||
gfxUtils::PremultiplyDataSurface(surf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1373,14 +1372,12 @@ WebGLContext::GetSurfaceSnapshot(bool* aPremultAlpha)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<SourceSurface> source = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(dt, surf);
|
||||
|
||||
Matrix m;
|
||||
m.Translate(0.0, mHeight);
|
||||
m.Scale(1.0, -1.0);
|
||||
dt->SetTransform(m);
|
||||
|
||||
dt->DrawSurface(source,
|
||||
dt->DrawSurface(surf,
|
||||
Rect(0, 0, mWidth, mHeight),
|
||||
Rect(0, 0, mWidth, mHeight),
|
||||
DrawSurfaceOptions(),
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "AudioNodeExternalInputStream.h"
|
||||
#include "AudioChannelFormat.h"
|
||||
#include "speex/speex_resampler.h"
|
||||
#include "mozilla/dom/MediaStreamAudioSourceNode.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
|
@ -324,7 +325,7 @@ AudioNodeExternalInputStream::ProcessInput(GraphTime aFrom, GraphTime aTo,
|
|||
|
||||
// GC stuff can result in our input stream being destroyed before this stream.
|
||||
// Handle that.
|
||||
if (mInputs.IsEmpty()) {
|
||||
if (!IsEnabled() || mInputs.IsEmpty()) {
|
||||
mLastChunks[0].SetNull(WEBAUDIO_BLOCK_SIZE);
|
||||
AdvanceOutputSegment();
|
||||
return;
|
||||
|
@ -452,4 +453,10 @@ AudioNodeExternalInputStream::ProcessInput(GraphTime aFrom, GraphTime aTo,
|
|||
AdvanceOutputSegment();
|
||||
}
|
||||
|
||||
bool
|
||||
AudioNodeExternalInputStream::IsEnabled()
|
||||
{
|
||||
return ((MediaStreamAudioSourceNodeEngine*)Engine())->IsEnabled();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "MediaStreamGraph.h"
|
||||
#include "AudioNodeStream.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
|
||||
// Forward declaration for mResamplerMap
|
||||
typedef struct SpeexResamplerState_ SpeexResamplerState;
|
||||
|
@ -94,6 +95,13 @@ private:
|
|||
*/
|
||||
size_t GetTrackMapEntry(const StreamBuffer::Track& aTrack,
|
||||
GraphTime aFrom);
|
||||
|
||||
/**
|
||||
* Determines if this is enabled or not. Disabled nodes produce silence.
|
||||
* This node becomes disabled if the document principal does not subsume the
|
||||
* DOMMediaStream principal.
|
||||
*/
|
||||
bool IsEnabled();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -250,7 +250,40 @@ DOMMediaStream::SetTrackEnabled(TrackID aTrackID, bool aEnabled)
|
|||
bool
|
||||
DOMMediaStream::CombineWithPrincipal(nsIPrincipal* aPrincipal)
|
||||
{
|
||||
return nsContentUtils::CombineResourcePrincipals(&mPrincipal, aPrincipal);
|
||||
bool changed =
|
||||
nsContentUtils::CombineResourcePrincipals(&mPrincipal, aPrincipal);
|
||||
if (changed) {
|
||||
NotifyPrincipalChanged();
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
void
|
||||
DOMMediaStream::SetPrincipal(nsIPrincipal* aPrincipal)
|
||||
{
|
||||
mPrincipal = aPrincipal;
|
||||
NotifyPrincipalChanged();
|
||||
}
|
||||
|
||||
void
|
||||
DOMMediaStream::NotifyPrincipalChanged()
|
||||
{
|
||||
for (uint32_t i = 0; i < mPrincipalChangeObservers.Length(); ++i) {
|
||||
mPrincipalChangeObservers[i]->PrincipalChanged(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DOMMediaStream::AddPrincipalChangeObserver(PrincipalChangeObserver* aObserver)
|
||||
{
|
||||
return mPrincipalChangeObservers.AppendElement(aObserver) != nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
DOMMediaStream::RemovePrincipalChangeObserver(PrincipalChangeObserver* aObserver)
|
||||
{
|
||||
return mPrincipalChangeObservers.RemoveElement(aObserver);
|
||||
}
|
||||
|
||||
MediaStreamTrack*
|
||||
|
|
|
@ -120,7 +120,19 @@ public:
|
|||
* one where the stream is accessible to script. Don't call this.
|
||||
* CombineWithPrincipal is almost certainly more appropriate.
|
||||
*/
|
||||
void SetPrincipal(nsIPrincipal* aPrincipal) { mPrincipal = aPrincipal; }
|
||||
void SetPrincipal(nsIPrincipal* aPrincipal);
|
||||
|
||||
/**
|
||||
* Used to learn about dynamic changes in principal occur.
|
||||
* Operations relating to these observers must be confined to the main thread.
|
||||
*/
|
||||
class PrincipalChangeObserver
|
||||
{
|
||||
public:
|
||||
virtual void PrincipalChanged(DOMMediaStream* aMediaStream) = 0;
|
||||
};
|
||||
bool AddPrincipalChangeObserver(PrincipalChangeObserver* aObserver);
|
||||
bool RemovePrincipalChangeObserver(PrincipalChangeObserver* aObserver);
|
||||
|
||||
/**
|
||||
* Called when this stream's MediaStreamGraph has been shut down. Normally
|
||||
|
@ -216,12 +228,6 @@ protected:
|
|||
// MediaStream is owned by the graph, but we tell it when to die, and it won't
|
||||
// die until we let it.
|
||||
MediaStream* mStream;
|
||||
// Principal identifying who may access the contents of this stream.
|
||||
// If null, this stream can be used by anyone because it has no content yet.
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
// this is used in gUM and WebRTC to identify peers that this stream
|
||||
// is allowed to be sent to
|
||||
nsAutoPtr<PeerIdentity> mPeerIdentity;
|
||||
|
||||
nsAutoTArray<nsRefPtr<MediaStreamTrack>,2> mTracks;
|
||||
nsRefPtr<StreamListener> mListener;
|
||||
|
@ -236,6 +242,17 @@ protected:
|
|||
// Indicate what track types have been added to this stream
|
||||
uint8_t mTrackTypesAvailable;
|
||||
bool mNotifiedOfMediaStreamGraphShutdown;
|
||||
|
||||
private:
|
||||
void NotifyPrincipalChanged();
|
||||
|
||||
// Principal identifying who may access the contents of this stream.
|
||||
// If null, this stream can be used by anyone because it has no content yet.
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
nsTArray<PrincipalChangeObserver*> mPrincipalChangeObservers;
|
||||
// this is used in gUM and WebRTC to identify peers that this stream
|
||||
// is allowed to be sent to
|
||||
nsAutoPtr<PeerIdentity> mPeerIdentity;
|
||||
};
|
||||
|
||||
class DOMLocalMediaStream : public DOMMediaStream,
|
||||
|
|
|
@ -1019,8 +1019,13 @@ void MediaDecoder::NotifyPrincipalChanged()
|
|||
|
||||
void MediaDecoder::NotifyBytesConsumed(int64_t aBytes, int64_t aOffset)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mShuttingDown) {
|
||||
return;
|
||||
}
|
||||
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
NS_ENSURE_TRUE_VOID(mDecoderStateMachine);
|
||||
MOZ_ASSERT(mDecoderStateMachine);
|
||||
if (mIgnoreProgressData) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -292,7 +292,7 @@ protected:
|
|||
TrackTicks aStart, TrackTicks aEnd)
|
||||
{
|
||||
MOZ_ASSERT(aStart <= aEnd, "Endpoints inverted");
|
||||
MOZ_ASSERT(aStart >= 0 && aEnd <= aSource.mDuration, "Slice out of range");
|
||||
NS_WARN_IF_FALSE(aStart >= 0 && aEnd <= aSource.mDuration, "Slice out of range");
|
||||
mDuration += aEnd - aStart;
|
||||
TrackTicks offset = 0;
|
||||
for (uint32_t i = 0; i < aSource.mChunks.Length() && offset < aEnd; ++i) {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "mozilla/dom/MediaStreamAudioSourceNodeBinding.h"
|
||||
#include "AudioNodeEngine.h"
|
||||
#include "AudioNodeExternalInputStream.h"
|
||||
#include "DOMMediaStream.h"
|
||||
#include "nsIDocument.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -37,16 +37,52 @@ MediaStreamAudioSourceNode::MediaStreamAudioSourceNode(AudioContext* aContext,
|
|||
ChannelInterpretation::Speakers),
|
||||
mInputStream(aMediaStream)
|
||||
{
|
||||
AudioNodeEngine* engine = new AudioNodeEngine(this);
|
||||
AudioNodeEngine* engine = new MediaStreamAudioSourceNodeEngine(this);
|
||||
mStream = aContext->Graph()->CreateAudioNodeExternalInputStream(engine);
|
||||
ProcessedMediaStream* outputStream = static_cast<ProcessedMediaStream*>(mStream.get());
|
||||
mInputPort = outputStream->AllocateInputPort(aMediaStream->GetStream(),
|
||||
MediaInputPort::FLAG_BLOCK_INPUT);
|
||||
mInputStream->AddConsumerToKeepAlive(this);
|
||||
|
||||
PrincipalChanged(mInputStream); // trigger enabling/disabling of the connector
|
||||
mInputStream->AddPrincipalChangeObserver(this);
|
||||
}
|
||||
|
||||
MediaStreamAudioSourceNode::~MediaStreamAudioSourceNode()
|
||||
{
|
||||
if (mInputStream) {
|
||||
mInputStream->RemovePrincipalChangeObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the principal. Note that this will be called on the main thread, but
|
||||
* changes will be enacted on the MediaStreamGraph thread. If the principal
|
||||
* change results in the document principal losing access to the stream, then
|
||||
* there needs to be other measures in place to ensure that any media that is
|
||||
* governed by the new stream principal is not available to the Media Stream
|
||||
* Graph before this change completes. Otherwise, a site could get access to
|
||||
* media that they are not authorized to receive.
|
||||
*
|
||||
* One solution is to block the altered content, call this method, then dispatch
|
||||
* another change request to the MediaStreamGraph thread that allows the content
|
||||
* under the new principal to flow. This might be unnecessary if the principal
|
||||
* change is changing to be the document principal.
|
||||
*/
|
||||
void
|
||||
MediaStreamAudioSourceNode::PrincipalChanged(DOMMediaStream* ms)
|
||||
{
|
||||
bool subsumes = false;
|
||||
nsIDocument* doc = Context()->GetParentObject()->GetExtantDoc();
|
||||
if (doc) {
|
||||
nsIPrincipal* docPrincipal = doc->NodePrincipal();
|
||||
nsIPrincipal* streamPrincipal = mInputStream->GetPrincipal();
|
||||
if (NS_FAILED(docPrincipal->Subsumes(streamPrincipal, &subsumes))) {
|
||||
subsumes = false;
|
||||
}
|
||||
}
|
||||
auto stream = static_cast<AudioNodeExternalInputStream*>(mStream.get());
|
||||
stream->SetInt32Parameter(MediaStreamAudioSourceNodeEngine::ENABLE, subsumes);
|
||||
}
|
||||
|
||||
size_t
|
||||
|
@ -83,4 +119,3 @@ MediaStreamAudioSourceNode::WrapObject(JSContext* aCx)
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,18 +8,42 @@
|
|||
#define MediaStreamAudioSourceNode_h_
|
||||
|
||||
#include "AudioNode.h"
|
||||
#include "DOMMediaStream.h"
|
||||
#include "AudioNodeEngine.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class DOMMediaStream;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class MediaStreamAudioSourceNode : public AudioNode
|
||||
class MediaStreamAudioSourceNodeEngine : public AudioNodeEngine
|
||||
{
|
||||
public:
|
||||
MediaStreamAudioSourceNodeEngine(AudioNode* aNode)
|
||||
: AudioNodeEngine(aNode), mEnabled(false) {}
|
||||
|
||||
bool IsEnabled() const { return mEnabled; }
|
||||
enum Parameters {
|
||||
ENABLE
|
||||
};
|
||||
virtual void SetInt32Parameter(uint32_t aIndex, int32_t aValue) MOZ_OVERRIDE
|
||||
{
|
||||
switch (aIndex) {
|
||||
case ENABLE:
|
||||
mEnabled = !!aValue;
|
||||
break;
|
||||
default:
|
||||
NS_ERROR("MediaStreamAudioSourceNodeEngine bad parameter index");
|
||||
}
|
||||
}
|
||||
private:
|
||||
bool mEnabled;
|
||||
};
|
||||
|
||||
class MediaStreamAudioSourceNode : public AudioNode,
|
||||
public DOMMediaStream::PrincipalChangeObserver
|
||||
{
|
||||
public:
|
||||
MediaStreamAudioSourceNode(AudioContext* aContext, DOMMediaStream* aMediaStream);
|
||||
// Define constructor out-of-line so we can forward-declare DOMMediaStream
|
||||
virtual ~MediaStreamAudioSourceNode();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
@ -39,6 +63,8 @@ public:
|
|||
virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE;
|
||||
virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE;
|
||||
|
||||
virtual void PrincipalChanged(DOMMediaStream* aMediaStream) MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
nsRefPtr<MediaInputPort> mInputPort;
|
||||
nsRefPtr<DOMMediaStream> mInputStream;
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "AnimationTimeline.h"
|
||||
#include "mozilla/dom/AnimationTimelineBinding.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsRefreshDriver.h"
|
||||
#include "nsDOMNavigationTiming.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(AnimationTimeline, mDocument)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(AnimationTimeline, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AnimationTimeline, Release)
|
||||
|
||||
JSObject*
|
||||
AnimationTimeline::WrapObject(JSContext* aCx)
|
||||
{
|
||||
return AnimationTimelineBinding::Wrap(aCx, this);
|
||||
}
|
||||
|
||||
Nullable<double>
|
||||
AnimationTimeline::GetCurrentTime() const
|
||||
{
|
||||
Nullable<double> result; // Default ctor initializes to null
|
||||
|
||||
nsIPresShell* presShell = mDocument->GetShell();
|
||||
if (!presShell)
|
||||
return result;
|
||||
|
||||
nsPresContext* presContext = presShell->GetPresContext();
|
||||
if (!presContext)
|
||||
return result;
|
||||
|
||||
nsRefPtr<nsDOMNavigationTiming> timing = mDocument->GetNavigationTiming();
|
||||
if (!timing)
|
||||
return result;
|
||||
|
||||
TimeStamp now = presContext->RefreshDriver()->MostRecentRefresh();
|
||||
result.SetValue(timing->TimeStampToDOMHighRes(now));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,46 @@
|
|||
/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_AnimationTimeline_h
|
||||
#define mozilla_dom_AnimationTimeline_h
|
||||
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "nsIDocument.h"
|
||||
|
||||
struct JSContext;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class AnimationTimeline MOZ_FINAL : public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
AnimationTimeline(nsIDocument* aDocument)
|
||||
: mDocument(aDocument)
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
}
|
||||
|
||||
virtual ~AnimationTimeline() { }
|
||||
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(AnimationTimeline)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(AnimationTimeline)
|
||||
|
||||
nsISupports* GetParentObject() const { return mDocument; }
|
||||
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
Nullable<double> GetCurrentTime() const;
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_AnimationTimeline_h
|
|
@ -0,0 +1,19 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
MOCHITEST_MANIFESTS += ['test/mochitest.ini']
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'AnimationTimeline.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
'AnimationTimeline.cpp',
|
||||
]
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
||||
FINAL_LIBRARY = 'gklayout'
|
|
@ -0,0 +1,105 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>Web Animations API: AnimationTimeline tests</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/WebIDLParser.js"></script>
|
||||
<script src="/resources/idlharness.js"></script>
|
||||
<div id="log"></div>
|
||||
<iframe src="data:text/html;charset=utf-8," width="10" height="10" id="iframe"></iframe>
|
||||
<script type="text/plain" id="AnimationTimeline-IDL">
|
||||
interface AnimationTimeline {
|
||||
readonly attribute double? currentTime;
|
||||
};
|
||||
</script>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
var idlArray;
|
||||
test(function() {
|
||||
idlArray = new IdlArray();
|
||||
idlArray.add_idls(
|
||||
document.getElementById('AnimationTimeline-IDL').textContent);
|
||||
idlArray.add_objects( { AnimationTimeline: ['document.timeline'] } );
|
||||
});
|
||||
idlArray.test();
|
||||
|
||||
test(function() {
|
||||
assert_equals(document.timeline, document.timeline,
|
||||
'document.timeline returns the same object every time');
|
||||
var iframe = document.getElementById('iframe');
|
||||
assert_not_equals(document.timeline, iframe.contentDocument.timeline,
|
||||
'document.timeline returns a different object for each document');
|
||||
assert_not_equals(iframe.contentDocument.timeline, null,
|
||||
'document.timeline on an iframe is not null');
|
||||
},
|
||||
'document.timeline identity tests',
|
||||
{
|
||||
help: 'http://dev.w3.org/fxtf/web-animations/#the-document-timeline',
|
||||
assert: [ 'Each document has a timeline called the document timeline' ],
|
||||
author: 'Brian Birtles'
|
||||
});
|
||||
|
||||
async_test(function(t) {
|
||||
assert_true(document.timeline.currentTime > 0,
|
||||
'document.timeline.currentTime is positive');
|
||||
// document.timeline.currentTime should be set even before document
|
||||
// load fires. We expect this code to be run before document load and hence
|
||||
// the above assertion is sufficient.
|
||||
// If the following assertion fails, this test needs to be redesigned.
|
||||
assert_true(document.readyState !== 'complete',
|
||||
'Test is running prior to document load');
|
||||
|
||||
// Test that the document timeline's current time is measured from
|
||||
// navigationStart.
|
||||
//
|
||||
// We can't just compare document.timeline.currentTime to
|
||||
// window.performance.now() because currentTime is only updated on a sample
|
||||
// so we use requestAnimationFrame instead.
|
||||
window.requestAnimationFrame(t.step_func(function(rafTime) {
|
||||
assert_equals(document.timeline.currentTime, rafTime,
|
||||
'document.timeline.currentTime matches' +
|
||||
' requestAnimationFrame time');
|
||||
t.done();
|
||||
}));
|
||||
},
|
||||
'document.timeline.currentTime value tests',
|
||||
{
|
||||
help: [
|
||||
'http://dev.w3.org/fxtf/web-animations/#the-global-clock',
|
||||
'http://dev.w3.org/fxtf/web-animations/#the-document-timeline'
|
||||
],
|
||||
assert: [
|
||||
'The global clock is a source of monotonically increasing time values',
|
||||
'The time values of the document timeline are calculated as a fixed' +
|
||||
' offset from the global clock',
|
||||
'the zero time corresponds to the navigationStart moment',
|
||||
'the time value of each document timeline must be equal to the time ' +
|
||||
'passed to animation frame request callbacks for that browsing context'
|
||||
],
|
||||
author: 'Brian Birtles'
|
||||
});
|
||||
|
||||
async_test(function(t) {
|
||||
var valueAtStart = document.timeline.currentTime;
|
||||
var timeAtStart = window.performance.now();
|
||||
while (window.performance.now() - timeAtStart < 100) {
|
||||
// Wait 100ms
|
||||
}
|
||||
assert_equals(document.timeline.currentTime, valueAtStart,
|
||||
'document.timeline.currentTime does not change within a script block');
|
||||
window.requestAnimationFrame(t.step_func(function() {
|
||||
assert_true(document.timeline.currentTime > valueAtStart,
|
||||
'document.timeline.currentTime increases between script blocks');
|
||||
t.done();
|
||||
}));
|
||||
},
|
||||
'document.timeline.currentTime liveness tests',
|
||||
{
|
||||
help: 'http://dev.w3.org/fxtf/web-animations/#script-execution-and-live-updates-to-the-model',
|
||||
assert: [ 'The value returned by the currentTime attribute of a' +
|
||||
' document timeline will not change within a script block' ],
|
||||
author: 'Brian Birtles'
|
||||
});
|
||||
|
||||
</script>
|
|
@ -0,0 +1 @@
|
|||
[animation-timeline/test_animation-timeline.html]
|
|
@ -1797,8 +1797,17 @@ nsWindowSH::PostCreate(nsIXPConnectWrappedNative *wrapper,
|
|||
const NativeProperties* eventTargetProperties =
|
||||
EventTargetBinding::sNativePropertyHooks->mNativeProperties.regular;
|
||||
|
||||
return DefineWebIDLBindingPropertiesOnXPCObject(cx, window, windowProperties, true) &&
|
||||
DefineWebIDLBindingPropertiesOnXPCObject(cx, window, eventTargetProperties, true) ?
|
||||
if (!DefineWebIDLBindingUnforgeablePropertiesOnXPCObject(cx, window, windowProperties) ||
|
||||
!DefineWebIDLBindingUnforgeablePropertiesOnXPCObject(cx, window, eventTargetProperties)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (!GlobalPropertiesAreOwn()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return DefineWebIDLBindingPropertiesOnXPCObject(cx, window, windowProperties) &&
|
||||
DefineWebIDLBindingPropertiesOnXPCObject(cx, window, eventTargetProperties) ?
|
||||
NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "nsIController.h"
|
||||
#include "nsScriptNameSpaceManager.h"
|
||||
#include "nsWindowMemoryReporter.h"
|
||||
#include "WindowNamedPropertiesHandler.h"
|
||||
|
||||
// Helper Classes
|
||||
#include "nsJSUtils.h"
|
||||
|
@ -1119,6 +1120,11 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
|
|||
// Initialize the PRCList (this).
|
||||
PR_INIT_CLIST(this);
|
||||
|
||||
if (Preferences::GetBool("dom.window_experimental_bindings") ||
|
||||
!aOuterWindow) {
|
||||
SetIsDOMBinding();
|
||||
}
|
||||
|
||||
if (aOuterWindow) {
|
||||
// |this| is an inner window, add this inner window to the outer
|
||||
// window list of inners.
|
||||
|
@ -1148,7 +1154,6 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
|
|||
Freeze();
|
||||
|
||||
mObserver = nullptr;
|
||||
SetIsDOMBinding();
|
||||
}
|
||||
|
||||
// We could have failed the first time through trying
|
||||
|
@ -1950,8 +1955,7 @@ nsGlobalWindow::TraceGlobalJSObject(JSTracer* aTrc)
|
|||
JSObject*
|
||||
nsGlobalWindow::OuterObject(JSContext* aCx, JS::Handle<JSObject*> aObj)
|
||||
{
|
||||
nsGlobalWindow* origWin;
|
||||
UNWRAP_OBJECT(Window, aObj, origWin);
|
||||
nsGlobalWindow* origWin = UnwrapDOMObject<nsGlobalWindow>(aObj);
|
||||
nsGlobalWindow* win = origWin->GetOuterWindowInternal();
|
||||
|
||||
if (!win) {
|
||||
|
@ -1961,6 +1965,7 @@ nsGlobalWindow::OuterObject(JSContext* aCx, JS::Handle<JSObject*> aObj)
|
|||
// null to prevent leaking an inner window to code in a different
|
||||
// window.
|
||||
NS_WARNING("nsGlobalWindow::OuterObject shouldn't fail!");
|
||||
Throw(aCx, NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1973,6 +1978,7 @@ nsGlobalWindow::OuterObject(JSContext* aCx, JS::Handle<JSObject*> aObj)
|
|||
// need to wrap here.
|
||||
if (!JS_WrapObject(aCx, &winObj)) {
|
||||
NS_WARNING("nsGlobalWindow::OuterObject shouldn't fail!");
|
||||
Throw(aCx, NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -2208,26 +2214,34 @@ CreateNativeGlobalForInner(JSContext* aCx,
|
|||
}
|
||||
}
|
||||
|
||||
nsIXPConnect* xpc = nsContentUtils::XPConnect();
|
||||
|
||||
// Determine if we need the Components object.
|
||||
bool needComponents = nsContentUtils::IsSystemPrincipal(aPrincipal) ||
|
||||
TreatAsRemoteXUL(aPrincipal);
|
||||
uint32_t flags = needComponents ? 0 : nsIXPConnect::OMIT_COMPONENTS_OBJECT;
|
||||
flags |= nsIXPConnect::DONT_FIRE_ONNEWGLOBALHOOK;
|
||||
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
nsresult rv = xpc->InitClassesWithNewWrappedGlobal(
|
||||
aCx, ToSupports(aNewInner),
|
||||
aPrincipal, flags, options, getter_AddRefs(holder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (aNewInner->IsDOMBinding()) {
|
||||
aGlobal.set(WindowBinding::Wrap(aCx, aNewInner, aNewInner, options,
|
||||
nsJSPrincipals::get(aPrincipal), false));
|
||||
if (!aGlobal || !xpc::InitGlobalObject(aCx, aGlobal, flags)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
} else {
|
||||
nsIXPConnect* xpc = nsContentUtils::XPConnect();
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
nsresult rv = xpc->InitClassesWithNewWrappedGlobal(
|
||||
aCx, ToSupports(aNewInner),
|
||||
aPrincipal, flags, options, getter_AddRefs(holder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aGlobal.set(holder->GetJSObject());
|
||||
MOZ_ASSERT(aGlobal);
|
||||
}
|
||||
|
||||
aGlobal.set(holder->GetJSObject());
|
||||
MOZ_ASSERT(aNewInner->GetWrapperPreserveColor() == aGlobal);
|
||||
|
||||
// Set the location information for the new global, so that tools like
|
||||
// about:memory may use that information
|
||||
MOZ_ASSERT(aGlobal);
|
||||
MOZ_ASSERT(aNewInner->GetWrapperPreserveColor() == aGlobal);
|
||||
xpc::SetLocationForGlobal(aGlobal, aURI);
|
||||
|
||||
return NS_OK;
|
||||
|
@ -2536,14 +2550,21 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
|||
// If we created a new inner window above, we need to do the last little bit
|
||||
// of initialization now that the dust has settled.
|
||||
if (createdInnerWindow) {
|
||||
nsIXPConnect *xpc = nsContentUtils::XPConnect();
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
|
||||
nsresult rv = xpc->GetWrappedNativeOfJSObject(cx, newInnerGlobal,
|
||||
getter_AddRefs(wrapper));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ABORT_IF_FALSE(wrapper, "bad wrapper");
|
||||
rv = wrapper->FinishInitForWrappedGlobal();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (newInnerWindow->IsDOMBinding()) {
|
||||
JS::Rooted<JSObject*> global(cx, newInnerGlobal);
|
||||
JS::Rooted<JSObject*> proto(cx);
|
||||
JS_GetPrototype(cx, global, &proto);
|
||||
WindowNamedPropertiesHandler::Install(cx, proto);
|
||||
} else {
|
||||
nsIXPConnect *xpc = nsContentUtils::XPConnect();
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
|
||||
nsresult rv = xpc->GetWrappedNativeOfJSObject(cx, newInnerGlobal,
|
||||
getter_AddRefs(wrapper));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ABORT_IF_FALSE(wrapper, "bad wrapper");
|
||||
rv = wrapper->FinishInitForWrappedGlobal();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
if (!aState) {
|
||||
|
|
|
@ -543,11 +543,23 @@ CreateInterfaceObject(JSContext* cx, JS::Handle<JSObject*> global,
|
|||
return constructor;
|
||||
}
|
||||
|
||||
bool
|
||||
DefineWebIDLBindingUnforgeablePropertiesOnXPCObject(JSContext* cx,
|
||||
JS::Handle<JSObject*> obj,
|
||||
const NativeProperties* properties)
|
||||
{
|
||||
if (properties->unforgeableAttributes &&
|
||||
!DefinePrefable(cx, obj, properties->unforgeableAttributes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DefineWebIDLBindingPropertiesOnXPCObject(JSContext* cx,
|
||||
JS::Handle<JSObject*> obj,
|
||||
const NativeProperties* properties,
|
||||
bool defineUnforgeableAttributes)
|
||||
const NativeProperties* properties)
|
||||
{
|
||||
if (properties->methods &&
|
||||
!DefinePrefable(cx, obj, properties->methods)) {
|
||||
|
@ -559,11 +571,6 @@ DefineWebIDLBindingPropertiesOnXPCObject(JSContext* cx,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (defineUnforgeableAttributes && properties->unforgeableAttributes &&
|
||||
!DefinePrefable(cx, obj, properties->unforgeableAttributes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -576,45 +583,54 @@ CreateInterfacePrototypeObject(JSContext* cx, JS::Handle<JSObject*> global,
|
|||
{
|
||||
JS::Rooted<JSObject*> ourProto(cx,
|
||||
JS_NewObjectWithUniqueType(cx, protoClass, parentProto, global));
|
||||
if (!ourProto) {
|
||||
if (!ourProto ||
|
||||
!DefineProperties(cx, ourProto, properties, chromeOnlyProperties)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ourProto;
|
||||
}
|
||||
|
||||
bool
|
||||
DefineProperties(JSContext* cx, JS::Handle<JSObject*> obj,
|
||||
const NativeProperties* properties,
|
||||
const NativeProperties* chromeOnlyProperties)
|
||||
{
|
||||
if (properties) {
|
||||
if (properties->methods &&
|
||||
!DefinePrefable(cx, ourProto, properties->methods)) {
|
||||
return nullptr;
|
||||
!DefinePrefable(cx, obj, properties->methods)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (properties->attributes &&
|
||||
!DefinePrefable(cx, ourProto, properties->attributes)) {
|
||||
return nullptr;
|
||||
!DefinePrefable(cx, obj, properties->attributes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (properties->constants &&
|
||||
!DefinePrefable(cx, ourProto, properties->constants)) {
|
||||
return nullptr;
|
||||
!DefinePrefable(cx, obj, properties->constants)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (chromeOnlyProperties) {
|
||||
if (chromeOnlyProperties->methods &&
|
||||
!DefinePrefable(cx, ourProto, chromeOnlyProperties->methods)) {
|
||||
return nullptr;
|
||||
!DefinePrefable(cx, obj, chromeOnlyProperties->methods)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (chromeOnlyProperties->attributes &&
|
||||
!DefinePrefable(cx, ourProto, chromeOnlyProperties->attributes)) {
|
||||
return nullptr;
|
||||
!DefinePrefable(cx, obj, chromeOnlyProperties->attributes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (chromeOnlyProperties->constants &&
|
||||
!DefinePrefable(cx, ourProto, chromeOnlyProperties->constants)) {
|
||||
return nullptr;
|
||||
!DefinePrefable(cx, obj, chromeOnlyProperties->constants)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return ourProto;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2181,12 +2197,15 @@ IsInCertifiedApp(JSContext* aCx, JSObject* aObj)
|
|||
Preferences::GetBool("dom.ignore_webidl_scope_checks", false);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
TraceGlobal(JSTracer* aTrc, JSObject* aObj)
|
||||
VerifyTraceProtoAndIfaceCacheCalled(JSTracer *trc, void **thingp,
|
||||
JSGCTraceKind kind)
|
||||
{
|
||||
MOZ_ASSERT(js::GetObjectClass(aObj)->flags & JSCLASS_DOM_GLOBAL);
|
||||
mozilla::dom::TraceProtoAndIfaceCache(aTrc, aObj);
|
||||
// We don't do anything here, we only want to verify that
|
||||
// TraceProtoAndIfaceCache was called.
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
FinalizeGlobal(JSFreeOp* aFreeOp, JSObject* aObj)
|
||||
|
@ -2394,5 +2413,21 @@ ConvertExceptionToPromise(JSContext* cx,
|
|||
return WrapNewBindingObject(cx, promise, rval);
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
CreateGlobalOptions<nsGlobalWindow>::TraceGlobal(JSTracer* aTrc, JSObject* aObj)
|
||||
{
|
||||
mozilla::dom::TraceProtoAndIfaceCache(aTrc, aObj);
|
||||
xpc::GetCompartmentPrivate(aObj)->scope->TraceSelf(aTrc);
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
CreateGlobalOptions<nsGlobalWindow>::PostCreateGlobal(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGlobal)
|
||||
{
|
||||
return XPCWrappedNativeScope::GetNewOrUsed(aCx, aGlobal);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -483,11 +483,35 @@ AllocateProtoAndIfaceCache(JSObject* obj, ProtoAndIfaceCache::Kind aKind)
|
|||
JS::PrivateValue(protoAndIfaceCache));
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
VerifyTraceProtoAndIfaceCacheCalled(JSTracer *trc, void **thingp,
|
||||
JSGCTraceKind kind);
|
||||
|
||||
struct VerifyTraceProtoAndIfaceCacheCalledTracer : public JSTracer
|
||||
{
|
||||
bool ok;
|
||||
|
||||
VerifyTraceProtoAndIfaceCacheCalledTracer(JSRuntime *rt)
|
||||
: JSTracer(rt, VerifyTraceProtoAndIfaceCacheCalled), ok(false)
|
||||
{}
|
||||
};
|
||||
#endif
|
||||
|
||||
inline void
|
||||
TraceProtoAndIfaceCache(JSTracer* trc, JSObject* obj)
|
||||
{
|
||||
MOZ_ASSERT(js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (trc->callback == VerifyTraceProtoAndIfaceCacheCalled) {
|
||||
// We don't do anything here, we only want to verify that
|
||||
// TraceProtoAndIfaceCache was called.
|
||||
static_cast<VerifyTraceProtoAndIfaceCacheCalledTracer*>(trc)->ok = true;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!HasProtoAndIfaceCache(obj))
|
||||
return;
|
||||
ProtoAndIfaceCache* protoAndIfaceCache = GetProtoAndIfaceCache(obj);
|
||||
|
@ -581,6 +605,24 @@ CreateInterfaceObjects(JSContext* cx, JS::Handle<JSObject*> global,
|
|||
const NativeProperties* chromeOnlyProperties,
|
||||
const char* name, bool defineOnGlobal);
|
||||
|
||||
/**
|
||||
* Define the properties (regular and chrome-only) on obj.
|
||||
*
|
||||
* obj the object to instal the properties on. This should be the interface
|
||||
* prototype object for regular interfaces and the instance object for
|
||||
* interfaces marked with Global.
|
||||
* properties contains the methods, attributes and constants to be defined on
|
||||
* objects in any compartment.
|
||||
* chromeProperties contains the methods, attributes and constants to be defined
|
||||
* on objects in chrome compartments. This must be null if the
|
||||
* interface doesn't have any ChromeOnly properties or if the
|
||||
* object is being created in non-chrome compartment.
|
||||
*/
|
||||
bool
|
||||
DefineProperties(JSContext* cx, JS::Handle<JSObject*> obj,
|
||||
const NativeProperties* properties,
|
||||
const NativeProperties* chromeOnlyProperties);
|
||||
|
||||
/*
|
||||
* Define the unforgeable attributes on an object.
|
||||
*/
|
||||
|
@ -588,11 +630,15 @@ bool
|
|||
DefineUnforgeableAttributes(JSContext* cx, JS::Handle<JSObject*> obj,
|
||||
const Prefable<const JSPropertySpec>* props);
|
||||
|
||||
bool
|
||||
DefineWebIDLBindingUnforgeablePropertiesOnXPCObject(JSContext* cx,
|
||||
JS::Handle<JSObject*> obj,
|
||||
const NativeProperties* properties);
|
||||
|
||||
bool
|
||||
DefineWebIDLBindingPropertiesOnXPCObject(JSContext* cx,
|
||||
JS::Handle<JSObject*> obj,
|
||||
const NativeProperties* properties,
|
||||
bool defineUnforgeableAttributes);
|
||||
const NativeProperties* properties);
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define HAS_MEMBER_CHECK(_name) \
|
||||
|
@ -2540,9 +2586,6 @@ IsInPrivilegedApp(JSContext* aCx, JSObject* aObj);
|
|||
bool
|
||||
IsInCertifiedApp(JSContext* aCx, JSObject* aObj);
|
||||
|
||||
void
|
||||
TraceGlobal(JSTracer* aTrc, JSObject* aObj);
|
||||
|
||||
void
|
||||
FinalizeGlobal(JSFreeOp* aFop, JSObject* aObj);
|
||||
|
||||
|
@ -2553,55 +2596,86 @@ ResolveGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj,
|
|||
bool
|
||||
EnumerateGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj);
|
||||
|
||||
template <class T, JS::Handle<JSObject*> (*ProtoGetter)(JSContext*,
|
||||
JS::Handle<JSObject*>)>
|
||||
JSObject*
|
||||
CreateGlobal(JSContext* aCx, T* aObject, nsWrapperCache* aCache,
|
||||
const JSClass* aClass, JS::CompartmentOptions& aOptions,
|
||||
JSPrincipals* aPrincipal)
|
||||
template <class T>
|
||||
struct CreateGlobalOptions
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
static MOZ_CONSTEXPR_VAR ProtoAndIfaceCache::Kind ProtoAndIfaceCacheKind =
|
||||
ProtoAndIfaceCache::NonWindowLike;
|
||||
// Intl API is broken and makes JS_InitStandardClasses fail intermittently,
|
||||
// see bug 934889.
|
||||
static MOZ_CONSTEXPR_VAR bool ForceInitStandardClassesToFalse = true;
|
||||
static void TraceGlobal(JSTracer* aTrc, JSObject* aObj)
|
||||
{
|
||||
mozilla::dom::TraceProtoAndIfaceCache(aTrc, aObj);
|
||||
}
|
||||
static bool PostCreateGlobal(JSContext* aCx, JS::Handle<JSObject*> aGlobal)
|
||||
{
|
||||
MOZ_ALWAYS_TRUE(TryPreserveWrapper(aGlobal));
|
||||
|
||||
aOptions.setTrace(TraceGlobal);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
JS::Rooted<JSObject*> global(aCx,
|
||||
JS_NewGlobalObject(aCx, aClass, aPrincipal, JS::DontFireOnNewGlobalHook,
|
||||
aOptions));
|
||||
if (!global) {
|
||||
template <>
|
||||
struct CreateGlobalOptions<nsGlobalWindow>
|
||||
{
|
||||
static MOZ_CONSTEXPR_VAR ProtoAndIfaceCache::Kind ProtoAndIfaceCacheKind =
|
||||
ProtoAndIfaceCache::WindowLike;
|
||||
static MOZ_CONSTEXPR_VAR bool ForceInitStandardClassesToFalse = false;
|
||||
static void TraceGlobal(JSTracer* aTrc, JSObject* aObj);
|
||||
static bool PostCreateGlobal(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
|
||||
};
|
||||
|
||||
template <class T, ProtoGetter GetProto>
|
||||
bool
|
||||
CreateGlobal(JSContext* aCx, T* aNative, nsWrapperCache* aCache,
|
||||
const JSClass* aClass, JS::CompartmentOptions& aOptions,
|
||||
JSPrincipals* aPrincipal, bool aInitStandardClasses,
|
||||
JS::MutableHandle<JSObject*> aGlobal)
|
||||
{
|
||||
aOptions.setTrace(CreateGlobalOptions<T>::TraceGlobal);
|
||||
|
||||
aGlobal.set(JS_NewGlobalObject(aCx, aClass, aPrincipal,
|
||||
JS::DontFireOnNewGlobalHook, aOptions));
|
||||
if (!aGlobal) {
|
||||
NS_WARNING("Failed to create global");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JSAutoCompartment ac(aCx, global);
|
||||
JSAutoCompartment ac(aCx, aGlobal);
|
||||
|
||||
dom::AllocateProtoAndIfaceCache(global, ProtoAndIfaceCache::WindowLike);
|
||||
{
|
||||
JS::AutoAssertNoGC nogc;
|
||||
|
||||
js::SetReservedSlot(global, DOM_OBJECT_SLOT, PRIVATE_TO_JSVAL(aObject));
|
||||
NS_ADDREF(aObject);
|
||||
// The setup of our global needs to be done before a GC happens.
|
||||
js::SetReservedSlot(aGlobal, DOM_OBJECT_SLOT, PRIVATE_TO_JSVAL(aNative));
|
||||
NS_ADDREF(aNative);
|
||||
|
||||
aCache->SetIsDOMBinding();
|
||||
aCache->SetWrapper(global);
|
||||
aCache->SetIsDOMBinding();
|
||||
aCache->SetWrapper(aGlobal);
|
||||
|
||||
/* Intl API is broken and makes this fail intermittently, see bug 934889.
|
||||
if (!JS_InitStandardClasses(aCx, global)) {
|
||||
dom::AllocateProtoAndIfaceCache(aGlobal,
|
||||
CreateGlobalOptions<T>::ProtoAndIfaceCacheKind);
|
||||
|
||||
if (!CreateGlobalOptions<T>::PostCreateGlobal(aCx, aGlobal)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (aInitStandardClasses &&
|
||||
!CreateGlobalOptions<T>::ForceInitStandardClassesToFalse &&
|
||||
!JS_InitStandardClasses(aCx, aGlobal)) {
|
||||
NS_WARNING("Failed to init standard classes");
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
JS::Handle<JSObject*> proto = ProtoGetter(aCx, global);
|
||||
NS_ENSURE_TRUE(proto, nullptr);
|
||||
|
||||
if (!JS_SetPrototype(aCx, global, proto)) {
|
||||
JS::Handle<JSObject*> proto = GetProto(aCx, aGlobal);
|
||||
if (!proto || !JS_SplicePrototype(aCx, aGlobal, proto)) {
|
||||
NS_WARNING("Failed to set proto");
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_TRUE(TryPreserveWrapper(global));
|
||||
|
||||
MOZ_ASSERT(UnwrapDOMObjectToISupports(global));
|
||||
|
||||
return global;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2661,6 +2735,15 @@ ConvertExceptionToPromise(JSContext* cx,
|
|||
JSObject* promiseScope,
|
||||
JS::MutableHandle<JS::Value> rval);
|
||||
|
||||
// While we wait for the outcome of spec discussions on whether properties for
|
||||
// DOM global objects live on the object or the prototype, we supply this one
|
||||
// place to switch the behaviour, so we can easily turn this off on branches.
|
||||
inline bool
|
||||
GlobalPropertiesAreOwn()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -2482,13 +2482,17 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
|||
else:
|
||||
domClass = "nullptr"
|
||||
|
||||
if self.properties.hasNonChromeOnly():
|
||||
isGlobal = self.descriptor.interface.getExtendedAttribute("Global") is not None
|
||||
if not isGlobal and self.properties.hasNonChromeOnly():
|
||||
properties = "&sNativeProperties"
|
||||
elif self.properties.hasNonChromeOnly():
|
||||
properties = "!GlobalPropertiesAreOwn() ? &sNativeProperties : nullptr"
|
||||
else:
|
||||
properties = "nullptr"
|
||||
if self.properties.hasChromeOnly():
|
||||
accessCheck = "nsContentUtils::ThreadsafeIsCallerChrome()"
|
||||
chromeProperties = accessCheck + " ? &sChromeOnlyNativeProperties : nullptr"
|
||||
if not isGlobal and self.properties.hasChromeOnly():
|
||||
chromeProperties = "nsContentUtils::ThreadsafeIsCallerChrome() ? &sChromeOnlyNativeProperties : nullptr"
|
||||
elif self.properties.hasChromeOnly():
|
||||
chromeProperties = "!GlobalPropertiesAreOwn() && nsContentUtils::ThreadsafeIsCallerChrome() ? &sChromeOnlyNativeProperties : nullptr"
|
||||
else:
|
||||
chromeProperties = "nullptr"
|
||||
|
||||
|
@ -2957,12 +2961,29 @@ class CGWrapGlobalMethod(CGAbstractMethod):
|
|||
Argument(descriptor.nativeType + '*', 'aObject'),
|
||||
Argument('nsWrapperCache*', 'aCache'),
|
||||
Argument('JS::CompartmentOptions&', 'aOptions'),
|
||||
Argument('JSPrincipals*', 'aPrincipal')]
|
||||
Argument('JSPrincipals*', 'aPrincipal'),
|
||||
Argument('bool', 'aInitStandardClasses')]
|
||||
CGAbstractMethod.__init__(self, descriptor, 'Wrap', 'JSObject*', args)
|
||||
self.descriptor = descriptor
|
||||
self.properties = properties
|
||||
|
||||
def definition_body(self):
|
||||
if self.properties.hasNonChromeOnly():
|
||||
properties = "GlobalPropertiesAreOwn() ? &sNativeProperties : nullptr"
|
||||
else:
|
||||
properties = "nullptr"
|
||||
if self.properties.hasChromeOnly():
|
||||
chromeProperties = "GlobalPropertiesAreOwn() && nsContentUtils::ThreadsafeIsCallerChrome() ? &sChromeOnlyNativeProperties : nullptr"
|
||||
else:
|
||||
chromeProperties = "nullptr"
|
||||
|
||||
if self.descriptor.workers:
|
||||
fireOnNewGlobal = """// XXXkhuey can't do this yet until workers can lazy resolve.
|
||||
// JS_FireOnNewGlobalObject(aCx, obj);
|
||||
"""
|
||||
else:
|
||||
fireOnNewGlobal = ""
|
||||
|
||||
return fill(
|
||||
"""
|
||||
${assertions}
|
||||
|
@ -2970,29 +2991,39 @@ class CGWrapGlobalMethod(CGAbstractMethod):
|
|||
"nsISupports must be on our primary inheritance chain");
|
||||
|
||||
JS::Rooted<JSObject*> obj(aCx);
|
||||
obj = CreateGlobal<${nativeType}, GetProtoObject>(aCx,
|
||||
aObject,
|
||||
aCache,
|
||||
Class.ToJSClass(),
|
||||
aOptions,
|
||||
aPrincipal);
|
||||
CreateGlobal<${nativeType}, GetProtoObject>(aCx,
|
||||
aObject,
|
||||
aCache,
|
||||
Class.ToJSClass(),
|
||||
aOptions,
|
||||
aPrincipal,
|
||||
aInitStandardClasses,
|
||||
&obj);
|
||||
if (!obj) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// obj is a new global, so has a new compartment. Enter it
|
||||
// before doing anything with it.
|
||||
JSAutoCompartment ac(aCx, obj);
|
||||
|
||||
if (!DefineProperties(aCx, obj, ${properties}, ${chromeProperties})) {
|
||||
return nullptr;
|
||||
}
|
||||
$*{unforgeable}
|
||||
|
||||
$*{slots}
|
||||
|
||||
// XXXkhuey can't do this yet until workers can lazy resolve.
|
||||
// JS_FireOnNewGlobalObject(aCx, obj);
|
||||
$*{fireOnNewGlobal}
|
||||
|
||||
return obj;
|
||||
""",
|
||||
assertions=AssertInheritanceChain(self.descriptor),
|
||||
nativeType=self.descriptor.nativeType,
|
||||
properties=properties,
|
||||
chromeProperties=chromeProperties,
|
||||
unforgeable=InitUnforgeableProperties(self.descriptor, self.properties),
|
||||
slots=InitMemberSlots(self.descriptor, True))
|
||||
slots=InitMemberSlots(self.descriptor, True),
|
||||
fireOnNewGlobal=fireOnNewGlobal)
|
||||
|
||||
|
||||
class CGUpdateMemberSlotsMethod(CGAbstractStaticMethod):
|
||||
|
|
|
@ -34,7 +34,8 @@
|
|||
}, 200);
|
||||
return function cancel() {
|
||||
if (interval) {
|
||||
ok(false, 'timed out waiting for audio check');
|
||||
ok(false, type + ' (' + successMessage + ')' +
|
||||
' failed after waiting full duration');
|
||||
clearInterval(interval);
|
||||
done();
|
||||
}
|
||||
|
@ -56,8 +57,6 @@
|
|||
analyser.getByteTimeDomainData(view);
|
||||
|
||||
var silent = check(constraintApplied, isSilence(view), 'be silence for audio');
|
||||
// TODO: silence cross origin input to webaudio, bug 966066
|
||||
silent = constraintApplied ? !silent : silent;
|
||||
return sampleCount > 0 && silent;
|
||||
}
|
||||
return periodicCheck('audio', testAudio,
|
||||
|
@ -101,7 +100,8 @@
|
|||
ctx.getImageData(0, 0, 1, 1);
|
||||
return check(constraintApplied, false, 'throw on getImageData for video');
|
||||
} catch (e) {
|
||||
return check(constraintApplied, e.name === 'SecurityError', 'get a security error');
|
||||
return check(constraintApplied, e.name === 'SecurityError',
|
||||
'get a security error: ' + e.name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -493,24 +493,70 @@ function PeerConnectionTest(options) {
|
|||
PeerConnectionTest.prototype.close = function PCT_close(onSuccess) {
|
||||
info("Closing peer connections. Connection state=" + this.connected);
|
||||
|
||||
function signalingstatechangeClose(state) {
|
||||
var self = this;
|
||||
var closeTimeout = null;
|
||||
var waitingForLocal = false;
|
||||
var waitingForRemote = false;
|
||||
var everythingClosed = false;
|
||||
|
||||
function verifyClosed() {
|
||||
if ((self.waitingForLocal || self.waitingForRemote) ||
|
||||
(self.pcLocal && (self.pcLocal.signalingState !== "closed")) ||
|
||||
(self.pcRemote && (self.pcRemote.signalingState !== "closed"))) {
|
||||
info("still waiting for closure");
|
||||
}
|
||||
else if (!everythingClosed) {
|
||||
info("No closure pending");
|
||||
if (self.pcLocal) {
|
||||
is(self.pcLocal.signalingState, "closed", "pcLocal is in 'closed' state");
|
||||
}
|
||||
if (self.pcRemote) {
|
||||
is(self.pcRemote.signalingState, "closed", "pcRemote is in 'closed' state");
|
||||
}
|
||||
clearTimeout(closeTimeout);
|
||||
self.connected = false;
|
||||
everythingClosed = true;
|
||||
onSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
function signalingstatechangeLocalClose(state) {
|
||||
info("'onsignalingstatechange' event '" + state + "' received");
|
||||
is(state, "closed", "onsignalingstatechange event is closed");
|
||||
self.waitingForLocal = false;
|
||||
verifyClosed();
|
||||
}
|
||||
|
||||
// There is no onclose event for the remote peer existent yet. So close it
|
||||
// side-by-side with the local peer.
|
||||
if (this.pcLocal) {
|
||||
this.pcLocal.onsignalingstatechange = signalingstatechangeClose;
|
||||
this.pcLocal.close();
|
||||
function signalingstatechangeRemoteClose(state) {
|
||||
info("'onsignalingstatechange' event '" + state + "' received");
|
||||
is(state, "closed", "onsignalingstatechange event is closed");
|
||||
self.waitingForRemote = false;
|
||||
verifyClosed();
|
||||
}
|
||||
if (this.pcRemote) {
|
||||
this.pcRemote.onsignalingstatechange = signalingstatechangeClose;
|
||||
this.pcRemote.close();
|
||||
}
|
||||
this.connected = false;
|
||||
|
||||
onSuccess();
|
||||
function closeEverything() {
|
||||
if ((self.pcLocal) && (self.pcLocal.signalingState !== "closed")) {
|
||||
info("Closing pcLocal");
|
||||
self.pcLocal.onsignalingstatechange = signalingstatechangeLocalClose;
|
||||
self.waitingForLocal = true;
|
||||
self.pcLocal.close();
|
||||
}
|
||||
if ((self.pcRemote) && (self.pcRemote.signalingState !== "closed")) {
|
||||
info("Closing pcRemote");
|
||||
self.pcRemote.onsignalingstatechange = signalingstatechangeRemoteClose;
|
||||
self.waitingForRemote = true;
|
||||
self.pcRemote.close();
|
||||
}
|
||||
verifyClosed();
|
||||
}
|
||||
|
||||
closeTimeout = setTimeout(function() {
|
||||
ok(false, "Closing PeerConnections timed out!");
|
||||
// it is not a success, but the show must go on
|
||||
onSuccess();
|
||||
}, 60000);
|
||||
|
||||
closeEverything();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -595,7 +641,6 @@ function PCT_setLocalDescription(peer, desc, stateExpected, onSuccess) {
|
|||
}
|
||||
|
||||
peer.onsignalingstatechange = function (state) {
|
||||
//info(peer + ": 'onsignalingstatechange' event registered, signalingState: " + peer.signalingState);
|
||||
info(peer + ": 'onsignalingstatechange' event '" + state + "' received");
|
||||
if(stateExpected === state && eventFired == false) {
|
||||
eventFired = true;
|
||||
|
|
|
@ -35,6 +35,7 @@ interfaces = [
|
|||
PARALLEL_DIRS += ['interfaces/' + i for i in interfaces]
|
||||
|
||||
PARALLEL_DIRS += [
|
||||
'animation',
|
||||
'apps',
|
||||
'base',
|
||||
'activities',
|
||||
|
|
|
@ -115,6 +115,8 @@ var interfaceNamesInGlobalScope =
|
|||
"AnalyserNode",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"AnimationEvent",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "AnimationTimeline", pref: "dom.animations-api.core.enabled"},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"Attr",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* http://dev.w3.org/fxtf/web-animations/#the-animationtimeline-interface
|
||||
*
|
||||
* Copyright © 2014 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
|
||||
* liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
[Pref="dom.animations-api.core.enabled"]
|
||||
interface AnimationTimeline {
|
||||
readonly attribute double? currentTime;
|
||||
// AnimationPlayer play (optional TimedItem? source = null);
|
||||
// sequence<AnimationPlayer> getAnimationPlayers ();
|
||||
};
|
|
@ -3,15 +3,6 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* The origin of this IDL file is:
|
||||
* http://dom.spec.whatwg.org/#interface-document
|
||||
* http://www.whatwg.org/specs/web-apps/current-work/#the-document-object
|
||||
* http://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html#api
|
||||
* http://dvcs.w3.org/hg/pointerlock/raw-file/default/index.html#extensions-to-the-document-interface
|
||||
* http://dvcs.w3.org/hg/webperf/raw-file/tip/specs/PageVisibility/Overview.html#sec-document-interface
|
||||
* http://dev.w3.org/csswg/cssom/#extensions-to-the-document-interface
|
||||
* http://dev.w3.org/csswg/cssom-view/#extensions-to-the-document-interface
|
||||
*
|
||||
* http://mxr.mozilla.org/mozilla-central/source/dom/interfaces/core/nsIDOMDocument.idl
|
||||
*/
|
||||
|
||||
|
@ -294,6 +285,12 @@ partial interface Document {
|
|||
//(Not implemented)NodeList findAll(DOMString selectors, optional (Element or sequence<Node>)? refNodes);
|
||||
};
|
||||
|
||||
// http://dev.w3.org/fxtf/web-animations/#extensions-to-the-document-interface
|
||||
partial interface Document {
|
||||
[Pref="dom.animations-api.core.enabled"]
|
||||
readonly attribute AnimationTimeline timeline;
|
||||
};
|
||||
|
||||
// Mozilla extensions of various sorts
|
||||
partial interface Document {
|
||||
// nsIDOMDocumentXBL. Wish we could make these [ChromeOnly], but
|
||||
|
|
|
@ -19,6 +19,7 @@ WEBIDL_FILES = [
|
|||
'ActivityRequestHandler.webidl',
|
||||
'AnalyserNode.webidl',
|
||||
'AnimationEvent.webidl',
|
||||
'AnimationTimeline.webidl',
|
||||
'AppInfo.webidl',
|
||||
'AppNotificationServiceOptions.webidl',
|
||||
'ArchiveReader.webidl',
|
||||
|
|
|
@ -299,7 +299,8 @@ DedicatedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx)
|
|||
|
||||
return DedicatedWorkerGlobalScopeBinding_workers::Wrap(aCx, this, this,
|
||||
options,
|
||||
GetWorkerPrincipal());
|
||||
GetWorkerPrincipal(),
|
||||
true);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -336,7 +337,8 @@ SharedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx)
|
|||
mWorkerPrivate->CopyJSCompartmentOptions(options);
|
||||
|
||||
return SharedWorkerGlobalScopeBinding_workers::Wrap(aCx, this, this, options,
|
||||
GetWorkerPrincipal());
|
||||
GetWorkerPrincipal(),
|
||||
true);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include "nsXPCOM.h"
|
||||
#include "nsSupportsPrimitives.h"
|
||||
#include "nsIComponentManager.h"
|
||||
|
||||
#include "nsCommandGroup.h"
|
||||
#include "nsIControllerCommand.h"
|
||||
#include "nsCRT.h"
|
||||
|
@ -19,31 +18,29 @@
|
|||
class nsGroupsEnumerator : public nsISimpleEnumerator
|
||||
{
|
||||
public:
|
||||
nsGroupsEnumerator(nsHashtable& inHashTable);
|
||||
virtual ~nsGroupsEnumerator();
|
||||
nsGroupsEnumerator(nsControllerCommandGroup::GroupsHashtable &inHashTable);
|
||||
virtual ~nsGroupsEnumerator();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISIMPLEENUMERATOR
|
||||
|
||||
protected:
|
||||
|
||||
static bool HashEnum(nsHashKey *aKey, void *aData, void* aClosure);
|
||||
|
||||
nsresult Initialize();
|
||||
static PLDHashOperator HashEnum(const nsACString &aKey, nsTArray<nsCString> *aData, void *aClosure);
|
||||
nsresult Initialize();
|
||||
|
||||
protected:
|
||||
|
||||
nsHashtable& mHashTable;
|
||||
int32_t mIndex;
|
||||
char ** mGroupNames; // array of pointers to char16_t* in the hash table
|
||||
bool mInitted;
|
||||
nsControllerCommandGroup::GroupsHashtable &mHashTable;
|
||||
int32_t mIndex;
|
||||
char **mGroupNames; // array of pointers to char16_t* in the hash table
|
||||
bool mInitted;
|
||||
|
||||
};
|
||||
|
||||
/* Implementation file */
|
||||
NS_IMPL_ISUPPORTS(nsGroupsEnumerator, nsISimpleEnumerator)
|
||||
|
||||
nsGroupsEnumerator::nsGroupsEnumerator(nsHashtable& inHashTable)
|
||||
nsGroupsEnumerator::nsGroupsEnumerator(nsControllerCommandGroup::GroupsHashtable &inHashTable)
|
||||
: mHashTable(inHashTable)
|
||||
, mIndex(-1)
|
||||
, mGroupNames(nullptr)
|
||||
|
@ -61,7 +58,7 @@ nsGroupsEnumerator::~nsGroupsEnumerator()
|
|||
NS_IMETHODIMP
|
||||
nsGroupsEnumerator::HasMoreElements(bool *_retval)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
|
||||
|
@ -70,7 +67,7 @@ nsGroupsEnumerator::HasMoreElements(bool *_retval)
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
*_retval = (mIndex < mHashTable.Count() - 1);
|
||||
*_retval = (mIndex < static_cast<int32_t>(mHashTable.Count()) - 1);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -78,7 +75,7 @@ nsGroupsEnumerator::HasMoreElements(bool *_retval)
|
|||
NS_IMETHODIMP
|
||||
nsGroupsEnumerator::GetNext(nsISupports **_retval)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
|
||||
|
@ -88,7 +85,7 @@ nsGroupsEnumerator::GetNext(nsISupports **_retval)
|
|||
}
|
||||
|
||||
mIndex ++;
|
||||
if (mIndex >= mHashTable.Count())
|
||||
if (mIndex >= static_cast<int32_t>(mHashTable.Count()))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
char *thisGroupName = mGroupNames[mIndex];
|
||||
|
@ -102,15 +99,13 @@ nsGroupsEnumerator::GetNext(nsISupports **_retval)
|
|||
|
||||
/* static */
|
||||
/* return false to stop */
|
||||
bool
|
||||
nsGroupsEnumerator::HashEnum(nsHashKey *aKey, void *aData, void* aClosure)
|
||||
PLDHashOperator
|
||||
nsGroupsEnumerator::HashEnum(const nsACString &aKey, nsTArray<nsCString> *aData, void *aClosure)
|
||||
{
|
||||
nsGroupsEnumerator* groupsEnum = reinterpret_cast<nsGroupsEnumerator *>(aClosure);
|
||||
nsCStringKey* stringKey = static_cast<nsCStringKey*>(aKey);
|
||||
|
||||
groupsEnum->mGroupNames[groupsEnum->mIndex] = (char*)stringKey->GetString();
|
||||
groupsEnum->mIndex ++;
|
||||
return true;
|
||||
nsGroupsEnumerator *groupsEnum = static_cast<nsGroupsEnumerator*>(aClosure);
|
||||
groupsEnum->mGroupNames[groupsEnum->mIndex] = (char*)aKey.Data();
|
||||
groupsEnum->mIndex++;
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -122,7 +117,7 @@ nsGroupsEnumerator::Initialize()
|
|||
if (!mGroupNames) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
mIndex = 0;
|
||||
mHashTable.Enumerate(HashEnum, (void*)this);
|
||||
mHashTable.EnumerateRead(HashEnum, this);
|
||||
|
||||
mIndex = -1;
|
||||
mInitted = true;
|
||||
|
@ -136,20 +131,18 @@ nsGroupsEnumerator::Initialize()
|
|||
class nsNamedGroupEnumerator : public nsISimpleEnumerator
|
||||
{
|
||||
public:
|
||||
nsNamedGroupEnumerator(nsTArray<char*>* inArray);
|
||||
virtual ~nsNamedGroupEnumerator();
|
||||
nsNamedGroupEnumerator(nsTArray<nsCString> *inArray);
|
||||
virtual ~nsNamedGroupEnumerator();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISIMPLEENUMERATOR
|
||||
|
||||
protected:
|
||||
|
||||
nsTArray<char*>* mGroupArray;
|
||||
int32_t mIndex;
|
||||
|
||||
nsTArray<nsCString> *mGroupArray;
|
||||
int32_t mIndex;
|
||||
};
|
||||
|
||||
nsNamedGroupEnumerator::nsNamedGroupEnumerator(nsTArray<char*>* inArray)
|
||||
nsNamedGroupEnumerator::nsNamedGroupEnumerator(nsTArray<nsCString> *inArray)
|
||||
: mGroupArray(inArray)
|
||||
, mIndex(-1)
|
||||
{
|
||||
|
@ -181,18 +174,17 @@ nsNamedGroupEnumerator::GetNext(nsISupports **_retval)
|
|||
if (!mGroupArray)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
mIndex ++;
|
||||
mIndex++;
|
||||
if (mIndex >= int32_t(mGroupArray->Length()))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
char16_t *thisGroupName = (char16_t*)mGroupArray->ElementAt(mIndex);
|
||||
NS_ASSERTION(thisGroupName, "Bad Element in mGroupArray");
|
||||
const nsCString& thisGroupName = mGroupArray->ElementAt(mIndex);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsISupportsString> supportsString = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
|
||||
nsCOMPtr<nsISupportsCString> supportsString = do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
supportsString->SetData(nsDependentString(thisGroupName));
|
||||
supportsString->SetData(thisGroupName);
|
||||
return CallQueryInterface(supportsString, _retval);
|
||||
}
|
||||
|
||||
|
@ -216,7 +208,7 @@ nsControllerCommandGroup::~nsControllerCommandGroup()
|
|||
void
|
||||
nsControllerCommandGroup::ClearGroupsHash()
|
||||
{
|
||||
mGroupsHash.Reset(ClearEnumerator, (void *)this);
|
||||
mGroupsHash.Clear();
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -225,24 +217,21 @@ nsControllerCommandGroup::ClearGroupsHash()
|
|||
|
||||
/* void addCommandToGroup (in DOMString aCommand, in DOMString aGroup); */
|
||||
NS_IMETHODIMP
|
||||
nsControllerCommandGroup::AddCommandToGroup(const char * aCommand, const char *aGroup)
|
||||
nsControllerCommandGroup::AddCommandToGroup(const char *aCommand, const char *aGroup)
|
||||
{
|
||||
nsCStringKey groupKey(aGroup);
|
||||
nsTArray<char*>* commandList;
|
||||
if ((commandList = (nsTArray<char*> *)mGroupsHash.Get(&groupKey)) == nullptr)
|
||||
nsDependentCString groupKey(aGroup);
|
||||
nsTArray<nsCString> *commandList;
|
||||
if ((commandList = mGroupsHash.Get(groupKey)) == nullptr)
|
||||
{
|
||||
// make this list
|
||||
commandList = new nsAutoTArray<char*, 8>;
|
||||
mGroupsHash.Put(&groupKey, (void *)commandList);
|
||||
commandList = new nsAutoTArray<nsCString, 8>;
|
||||
mGroupsHash.Put(groupKey, commandList);
|
||||
}
|
||||
// add the command to the list. Note that we're not checking for duplicates here
|
||||
char* commandString = NS_strdup(aCommand); // we store allocated char16_t* in the array
|
||||
if (!commandString) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
char** appended =
|
||||
nsCString *appended =
|
||||
#endif
|
||||
commandList->AppendElement(commandString);
|
||||
commandList->AppendElement(aCommand);
|
||||
NS_ASSERTION(appended, "Append failed");
|
||||
|
||||
return NS_OK;
|
||||
|
@ -250,43 +239,41 @@ nsControllerCommandGroup::AddCommandToGroup(const char * aCommand, const char *a
|
|||
|
||||
/* void removeCommandFromGroup (in DOMString aCommand, in DOMString aGroup); */
|
||||
NS_IMETHODIMP
|
||||
nsControllerCommandGroup::RemoveCommandFromGroup(const char * aCommand, const char * aGroup)
|
||||
nsControllerCommandGroup::RemoveCommandFromGroup(const char *aCommand, const char *aGroup)
|
||||
{
|
||||
nsCStringKey groupKey(aGroup);
|
||||
nsTArray<char*>* commandList = (nsTArray<char*> *)mGroupsHash.Get(&groupKey);
|
||||
if (!commandList) return NS_OK; // no group
|
||||
nsDependentCString groupKey(aGroup);
|
||||
nsTArray<nsCString> *commandList = mGroupsHash.Get(groupKey);
|
||||
if (!commandList) return NS_OK; // no group
|
||||
|
||||
uint32_t numEntries = commandList->Length();
|
||||
for (uint32_t i = 0; i < numEntries; i ++)
|
||||
for (uint32_t i = 0; i < numEntries; i++)
|
||||
{
|
||||
char* commandString = commandList->ElementAt(i);
|
||||
if (!nsCRT::strcmp(aCommand,commandString))
|
||||
nsCString commandString = commandList->ElementAt(i);
|
||||
if (nsDependentCString(aCommand) != commandString)
|
||||
{
|
||||
commandList->RemoveElementAt(i);
|
||||
nsMemory::Free(commandString);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* boolean isCommandInGroup (in DOMString aCommand, in DOMString aGroup); */
|
||||
NS_IMETHODIMP
|
||||
nsControllerCommandGroup::IsCommandInGroup(const char * aCommand, const char * aGroup, bool *_retval)
|
||||
nsControllerCommandGroup::IsCommandInGroup(const char *aCommand, const char *aGroup, bool *_retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
*_retval = false;
|
||||
|
||||
nsCStringKey groupKey(aGroup);
|
||||
nsTArray<char*>* commandList = (nsTArray<char*> *)mGroupsHash.Get(&groupKey);
|
||||
if (!commandList) return NS_OK; // no group
|
||||
nsDependentCString groupKey(aGroup);
|
||||
nsTArray<nsCString> *commandList = mGroupsHash.Get(groupKey);
|
||||
if (!commandList) return NS_OK; // no group
|
||||
|
||||
uint32_t numEntries = commandList->Length();
|
||||
for (uint32_t i = 0; i < numEntries; i ++)
|
||||
for (uint32_t i = 0; i < numEntries; i++)
|
||||
{
|
||||
char* commandString = commandList->ElementAt(i);
|
||||
if (!nsCRT::strcmp(aCommand,commandString))
|
||||
nsCString commandString = commandList->ElementAt(i);
|
||||
if (nsDependentCString(aCommand) != commandString)
|
||||
{
|
||||
*_retval = true;
|
||||
break;
|
||||
|
@ -299,7 +286,7 @@ nsControllerCommandGroup::IsCommandInGroup(const char * aCommand, const char * a
|
|||
NS_IMETHODIMP
|
||||
nsControllerCommandGroup::GetGroupsEnumerator(nsISimpleEnumerator **_retval)
|
||||
{
|
||||
nsGroupsEnumerator* groupsEnum = new nsGroupsEnumerator(mGroupsHash);
|
||||
nsGroupsEnumerator *groupsEnum = new nsGroupsEnumerator(mGroupsHash);
|
||||
if (!groupsEnum) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
return groupsEnum->QueryInterface(NS_GET_IID(nsISimpleEnumerator), (void **)_retval);
|
||||
|
@ -307,12 +294,12 @@ nsControllerCommandGroup::GetGroupsEnumerator(nsISimpleEnumerator **_retval)
|
|||
|
||||
/* nsISimpleEnumerator getEnumeratorForGroup (in DOMString aGroup); */
|
||||
NS_IMETHODIMP
|
||||
nsControllerCommandGroup::GetEnumeratorForGroup(const char * aGroup, nsISimpleEnumerator **_retval)
|
||||
nsControllerCommandGroup::GetEnumeratorForGroup(const char *aGroup, nsISimpleEnumerator **_retval)
|
||||
{
|
||||
nsCStringKey groupKey(aGroup);
|
||||
nsTArray<char*>* commandList = (nsTArray<char*> *)mGroupsHash.Get(&groupKey); // may be null
|
||||
nsDependentCString groupKey(aGroup);
|
||||
nsTArray<nsCString> *commandList = mGroupsHash.Get(groupKey); // may be null
|
||||
|
||||
nsNamedGroupEnumerator* theGroupEnum = new nsNamedGroupEnumerator(commandList);
|
||||
nsNamedGroupEnumerator *theGroupEnum = new nsNamedGroupEnumerator(commandList);
|
||||
if (!theGroupEnum) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
return theGroupEnum->QueryInterface(NS_GET_IID(nsISimpleEnumerator), (void **)_retval);
|
||||
|
@ -321,21 +308,3 @@ nsControllerCommandGroup::GetEnumeratorForGroup(const char * aGroup, nsISimpleEn
|
|||
#if 0
|
||||
#pragma mark -
|
||||
#endif
|
||||
|
||||
bool nsControllerCommandGroup::ClearEnumerator(nsHashKey *aKey, void *aData, void* closure)
|
||||
{
|
||||
nsTArray<char*>* commandList = (nsTArray<char*> *)aData;
|
||||
if (commandList)
|
||||
{
|
||||
uint32_t numEntries = commandList->Length();
|
||||
for (uint32_t i = 0; i < numEntries; i ++)
|
||||
{
|
||||
char* commandString = commandList->ElementAt(i);
|
||||
nsMemory::Free(commandString);
|
||||
}
|
||||
|
||||
delete commandList;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -3,15 +3,12 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
|
||||
#ifndef nsCommandGroup_h__
|
||||
#define nsCommandGroup_h__
|
||||
|
||||
#include "nsIController.h"
|
||||
|
||||
#include "nsHashtable.h"
|
||||
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
||||
// {ecd55a01-2780-11d5-a73c-ca641a6813bc}
|
||||
#define NS_CONTROLLER_COMMAND_GROUP_CID \
|
||||
|
@ -20,34 +17,24 @@
|
|||
#define NS_CONTROLLER_COMMAND_GROUP_CONTRACTID \
|
||||
"@mozilla.org/embedcomp/controller-command-group;1"
|
||||
|
||||
|
||||
class nsControllerCommandGroup : public nsIControllerCommandGroup
|
||||
{
|
||||
public:
|
||||
|
||||
nsControllerCommandGroup();
|
||||
virtual ~nsControllerCommandGroup();
|
||||
nsControllerCommandGroup();
|
||||
virtual ~nsControllerCommandGroup();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICONTROLLERCOMMANDGROUP
|
||||
|
||||
public:
|
||||
typedef nsClassHashtable<nsCStringHashKey, nsTArray<nsCString>> GroupsHashtable;
|
||||
|
||||
protected:
|
||||
|
||||
void ClearGroupsHash();
|
||||
void ClearGroupsHash();
|
||||
|
||||
protected:
|
||||
|
||||
static bool ClearEnumerator(nsHashKey *aKey, void *aData, void* closure);
|
||||
|
||||
protected:
|
||||
|
||||
nsHashtable mGroupsHash; // hash keyed on command group.
|
||||
// Entries are nsTArray<char*>
|
||||
// This could be made more space-efficient, maybe with atoms
|
||||
|
||||
GroupsHashtable mGroupsHash; // hash keyed on command group.
|
||||
// This could be made more space-efficient, maybe with atoms
|
||||
};
|
||||
|
||||
|
||||
#endif // nsCommandGroup_h__
|
||||
|
||||
|
|
|
@ -62,6 +62,15 @@ NudgeToInteger(float *aVal)
|
|||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
NudgeToInteger(float *aVal, float aErr)
|
||||
{
|
||||
float r = floorf(*aVal + 0.5f);
|
||||
if (FuzzyEqual(r, *aVal, aErr)) {
|
||||
*aVal = r;
|
||||
}
|
||||
}
|
||||
|
||||
static inline Float
|
||||
Distance(Point aA, Point aB)
|
||||
{
|
||||
|
|
|
@ -39,7 +39,7 @@ Inline documentation about TextureClient and TextureHost can be found in:
|
|||
|
||||
TextureClient is the client-side handle on a MozSurface, while TextureHost is the equivalent host-side representation. There can only be one TextureClient for a given TextureHost, and one TextureHost for a given TextureClient. Likewise, there can only be one shared object for a given TextureClient/TextureHost pair.
|
||||
|
||||
A MozSurface containing data that is shared between a client process and a host process exists in the foolowing form:
|
||||
A MozSurface containing data that is shared between a client process and a host process exists in the following form:
|
||||
|
||||
```
|
||||
.
|
||||
|
@ -88,7 +88,7 @@ A surface lets you *borrow* a DrawTarget that is only valid between Lock and Unl
|
|||
|
||||
It is invalid to hold a reference to the DrawTarget after Unlock, and a different DrawTarget may be obtained during the next Lock/Unlock interval.
|
||||
|
||||
In some cases we want to use MozSurface without Drawing into it. For instance to share video frames accross processes. Some surface types may also not be accessible through a DrawTarget (for example YCbCr surfaces).
|
||||
In some cases we want to use MozSurface without drawing into it. For instance to share video frames accross processes. Some surface types may also not be accessible through a DrawTarget (for example YCbCr surfaces).
|
||||
|
||||
bool CanExposeDrawTarget();
|
||||
|
||||
|
|
|
@ -249,8 +249,8 @@ static void CopyDataSourceSurface(DataSourceSurface* aSource,
|
|||
DataSourceSurface* aDest)
|
||||
{
|
||||
MOZ_ASSERT(aSource->GetSize() == aDest->GetSize());
|
||||
MOZ_ASSERT(aSource->GetFormat() == SurfaceFormat::R8G8B8A8 ||
|
||||
aSource->GetFormat() == SurfaceFormat::R8G8B8X8);
|
||||
MOZ_ASSERT(aSource->GetFormat() == SurfaceFormat::B8G8R8A8 ||
|
||||
aSource->GetFormat() == SurfaceFormat::B8G8R8X8);
|
||||
|
||||
uint8_t *srcRow = aSource->GetData();
|
||||
size_t srcRowBytes = aSource->GetSize().width * BytesPerPixel(aSource->GetFormat());
|
||||
|
@ -328,44 +328,40 @@ GuessAlignment(int width, int pixelSize, int rowStride)
|
|||
}
|
||||
|
||||
void
|
||||
ReadPixelsIntoImageSurface(GLContext* gl, gfxImageSurface* dest) {
|
||||
ReadPixelsIntoDataSurface(GLContext* gl, DataSourceSurface* dest) {
|
||||
gl->MakeCurrent();
|
||||
MOZ_ASSERT(dest->GetSize() != gfxIntSize(0, 0));
|
||||
MOZ_ASSERT(dest->GetSize().width != 0);
|
||||
MOZ_ASSERT(dest->GetSize().height != 0);
|
||||
|
||||
/* gfxImageFormat::ARGB32:
|
||||
* RGBA+UByte: be[RGBA], le[ABGR]
|
||||
* RGBA+UInt: be[ABGR], le[RGBA]
|
||||
* BGRA+UInt: be[ARGB], le[BGRA]
|
||||
* BGRA+UIntRev: be[BGRA], le[ARGB]
|
||||
*
|
||||
* gfxImageFormat::RGB16_565:
|
||||
* RGB+UShort: le[rrrrrggg,gggbbbbb]
|
||||
*/
|
||||
bool hasAlpha = dest->Format() == gfxImageFormat::ARGB32;
|
||||
bool hasAlpha = dest->GetFormat() == SurfaceFormat::B8G8R8A8 ||
|
||||
dest->GetFormat() == SurfaceFormat::R8G8B8A8;
|
||||
|
||||
int destPixelSize;
|
||||
GLenum destFormat;
|
||||
GLenum destType;
|
||||
|
||||
switch (dest->Format()) {
|
||||
case gfxImageFormat::RGB24: // XRGB
|
||||
case gfxImageFormat::ARGB32:
|
||||
destPixelSize = 4;
|
||||
switch (dest->GetFormat()) {
|
||||
case SurfaceFormat::B8G8R8A8:
|
||||
case SurfaceFormat::B8G8R8X8:
|
||||
// Needs host (little) endian ARGB.
|
||||
destFormat = LOCAL_GL_BGRA;
|
||||
destType = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
break;
|
||||
|
||||
case gfxImageFormat::RGB16_565:
|
||||
destPixelSize = 2;
|
||||
case SurfaceFormat::R8G8B8A8:
|
||||
case SurfaceFormat::R8G8B8X8:
|
||||
// Needs host (little) endian ABGR.
|
||||
destFormat = LOCAL_GL_RGBA;
|
||||
destType = LOCAL_GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case SurfaceFormat::R5G6B5:
|
||||
destFormat = LOCAL_GL_RGB;
|
||||
destType = LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV;
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Bad format.");
|
||||
}
|
||||
MOZ_ASSERT(dest->Width() * destPixelSize <= dest->Stride());
|
||||
destPixelSize = BytesPerPixel(dest->GetFormat());
|
||||
MOZ_ASSERT(dest->GetSize().width * destPixelSize <= dest->Stride());
|
||||
|
||||
GLenum readFormat = destFormat;
|
||||
GLenum readType = destType;
|
||||
|
@ -373,20 +369,15 @@ ReadPixelsIntoImageSurface(GLContext* gl, gfxImageSurface* dest) {
|
|||
destFormat, destType,
|
||||
readFormat, readType);
|
||||
|
||||
nsAutoPtr<gfxImageSurface> tempSurf;
|
||||
gfxImageSurface* readSurf = nullptr;
|
||||
|
||||
// Figure out alignment. We don't need to know why, we just need it
|
||||
// to be valid.
|
||||
int readAlignment = GuessAlignment(dest->Width(),
|
||||
RefPtr<DataSourceSurface> tempSurf;
|
||||
DataSourceSurface* readSurf = dest;
|
||||
int readAlignment = GuessAlignment(dest->GetSize().width,
|
||||
destPixelSize,
|
||||
dest->Stride());
|
||||
if (!readAlignment) // Couldn't calculate a valid alignment.
|
||||
if (!readAlignment) {
|
||||
needsTempSurf = true;
|
||||
|
||||
if (!needsTempSurf) {
|
||||
readSurf = dest;
|
||||
} else {
|
||||
}
|
||||
if (needsTempSurf) {
|
||||
if (gl->DebugMode()) {
|
||||
NS_WARNING("Needing intermediary surface for ReadPixels. This will be slow!");
|
||||
}
|
||||
|
@ -431,154 +422,11 @@ ReadPixelsIntoImageSurface(GLContext* gl, gfxImageSurface* dest) {
|
|||
}
|
||||
}
|
||||
|
||||
tempSurf = new gfxImageSurface(dest->GetSize(),
|
||||
SurfaceFormatToImageFormat(readFormatGFX),
|
||||
false);
|
||||
readSurf = tempSurf;
|
||||
}
|
||||
MOZ_ASSERT(readAlignment);
|
||||
|
||||
GLint currentPackAlignment = 0;
|
||||
gl->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, ¤tPackAlignment);
|
||||
|
||||
if (currentPackAlignment != readAlignment)
|
||||
gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, readAlignment);
|
||||
|
||||
GLsizei width = dest->Width();
|
||||
GLsizei height = dest->Height();
|
||||
|
||||
readSurf->Flush();
|
||||
gl->fReadPixels(0, 0,
|
||||
width, height,
|
||||
readFormat, readType,
|
||||
readSurf->Data());
|
||||
readSurf->MarkDirty();
|
||||
|
||||
if (currentPackAlignment != readAlignment)
|
||||
gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment);
|
||||
|
||||
if (readSurf != dest) {
|
||||
MOZ_ASSERT(readFormat == LOCAL_GL_RGBA);
|
||||
MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_BYTE);
|
||||
// So we just copied in RGBA in big endian, or le: 0xAABBGGRR.
|
||||
// We want 0xAARRGGBB, so swap R and B:
|
||||
dest->Flush();
|
||||
RefPtr<DataSourceSurface> readDSurf =
|
||||
Factory::CreateWrappingDataSourceSurface(readSurf->Data(),
|
||||
readSurf->Stride(),
|
||||
ToIntSize(readSurf->GetSize()),
|
||||
ImageFormatToSurfaceFormat(readSurf->Format()));
|
||||
SwapRAndBComponents(readDSurf);
|
||||
dest->MarkDirty();
|
||||
|
||||
gfxContext ctx(dest);
|
||||
ctx.SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
ctx.SetSource(readSurf);
|
||||
ctx.Paint();
|
||||
}
|
||||
|
||||
// Check if GL is giving back 1.0 alpha for
|
||||
// RGBA reads to RGBA images from no-alpha buffers.
|
||||
#ifdef XP_MACOSX
|
||||
if (gl->WorkAroundDriverBugs() &&
|
||||
gl->Vendor() == gl::GLVendor::NVIDIA &&
|
||||
dest->Format() == gfxImageFormat::ARGB32 &&
|
||||
width && height)
|
||||
{
|
||||
GLint alphaBits = 0;
|
||||
gl->fGetIntegerv(LOCAL_GL_ALPHA_BITS, &alphaBits);
|
||||
if (!alphaBits) {
|
||||
const uint32_t alphaMask = gfxPackedPixelNoPreMultiply(0xff,0,0,0);
|
||||
|
||||
MOZ_ASSERT(dest->Width() * destPixelSize == dest->Stride());
|
||||
|
||||
dest->Flush();
|
||||
uint32_t* itr = (uint32_t*)dest->Data();
|
||||
uint32_t testPixel = *itr;
|
||||
if ((testPixel & alphaMask) != alphaMask) {
|
||||
// We need to set the alpha channel to 1.0 manually.
|
||||
uint32_t* itrEnd = itr + width*height; // Stride is guaranteed to be width*4.
|
||||
|
||||
for (; itr != itrEnd; itr++) {
|
||||
*itr |= alphaMask;
|
||||
}
|
||||
}
|
||||
dest->MarkDirty();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
ReadPixelsIntoDataSurface(GLContext* gl, DataSourceSurface* dest) {
|
||||
gl->MakeCurrent();
|
||||
MOZ_ASSERT(dest->GetSize().width != 0);
|
||||
MOZ_ASSERT(dest->GetSize().height != 0);
|
||||
|
||||
bool hasAlpha = dest->GetFormat() == SurfaceFormat::B8G8R8A8 ||
|
||||
dest->GetFormat() == SurfaceFormat::R8G8B8A8;
|
||||
|
||||
int destPixelSize;
|
||||
GLenum destFormat;
|
||||
GLenum destType;
|
||||
|
||||
switch (dest->GetFormat()) {
|
||||
case SurfaceFormat::B8G8R8A8:
|
||||
case SurfaceFormat::B8G8R8X8:
|
||||
// Needs host (little) endian ARGB.
|
||||
destFormat = LOCAL_GL_BGRA;
|
||||
destType = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
break;
|
||||
case SurfaceFormat::R8G8B8A8:
|
||||
case SurfaceFormat::R8G8B8X8:
|
||||
// Needs host (little) endian ABGR.
|
||||
destFormat = LOCAL_GL_RGBA;
|
||||
destType = LOCAL_GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case SurfaceFormat::R5G6B5:
|
||||
destFormat = LOCAL_GL_RGB;
|
||||
destType = LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV;
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Bad format.");
|
||||
}
|
||||
destPixelSize = BytesPerPixel(dest->GetFormat());
|
||||
MOZ_ASSERT(dest->GetSize().width * destPixelSize <= dest->Stride());
|
||||
|
||||
GLenum readFormat = destFormat;
|
||||
GLenum readType = destType;
|
||||
bool needsTempSurf = !GetActualReadFormats(gl,
|
||||
destFormat, destType,
|
||||
readFormat, readType);
|
||||
|
||||
RefPtr<DataSourceSurface> tempSurf;
|
||||
DataSourceSurface* readSurf = nullptr;
|
||||
int readAlignment = 0;
|
||||
if (needsTempSurf) {
|
||||
if (gl->DebugMode()) {
|
||||
NS_WARNING("Needing intermediary surface for ReadPixels. This will be slow!");
|
||||
}
|
||||
SurfaceFormat readFormatGFX;
|
||||
|
||||
// If needs temp surface, readFormat is always LOCAL_GL_RGBA
|
||||
// and readType is always LOCAL_GL_UNSIGNED_BYTE
|
||||
MOZ_ASSERT(readFormat == LOCAL_GL_RGBA);
|
||||
MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_BYTE);
|
||||
readFormatGFX = hasAlpha ? SurfaceFormat::R8G8B8A8
|
||||
: SurfaceFormat::R8G8B8X8;
|
||||
readAlignment = 1;
|
||||
int32_t stride = dest->GetSize().width * BytesPerPixel(readFormatGFX);
|
||||
tempSurf = Factory::CreateDataSourceSurfaceWithStride(dest->GetSize(),
|
||||
readFormatGFX,
|
||||
stride);
|
||||
readSurf = tempSurf;
|
||||
} else {
|
||||
// Figure out alignment. We don't need to know why, we just need it
|
||||
// to be valid.
|
||||
readAlignment = GuessAlignment(dest->GetSize().width,
|
||||
destPixelSize,
|
||||
dest->Stride());
|
||||
readSurf = dest;
|
||||
}
|
||||
MOZ_ASSERT(readAlignment);
|
||||
MOZ_ASSERT(reinterpret_cast<uintptr_t>(readSurf->GetData()) % readAlignment == 0);
|
||||
|
@ -705,14 +553,6 @@ ReadBackSurface(GLContext* gl, GLuint aTexture, bool aYInvert, SurfaceFormat aFo
|
|||
return surf.forget();
|
||||
}
|
||||
|
||||
void
|
||||
ReadScreenIntoImageSurface(GLContext* gl, gfxImageSurface* dest)
|
||||
{
|
||||
ScopedBindFramebuffer autoFB(gl, 0);
|
||||
ReadPixelsIntoImageSurface(gl, dest);
|
||||
}
|
||||
|
||||
|
||||
#define CLEANUP_IF_GLERROR_OCCURRED(x) \
|
||||
if (DidGLErrorOccur(x)) { \
|
||||
isurf = nullptr; \
|
||||
|
|
|
@ -26,8 +26,6 @@ namespace gl {
|
|||
|
||||
void ReadPixelsIntoDataSurface(GLContext* aGL,
|
||||
gfx::DataSourceSurface* aSurface);
|
||||
void ReadPixelsIntoImageSurface(GLContext* aGL, gfxImageSurface* aSurface);
|
||||
void ReadScreenIntoImageSurface(GLContext* aGL, gfxImageSurface* aSurface);
|
||||
|
||||
TemporaryRef<gfx::DataSourceSurface>
|
||||
ReadBackSurface(GLContext* gl, GLuint aTexture, bool aYInvert, gfx::SurfaceFormat aFormat);
|
||||
|
|
|
@ -17,11 +17,12 @@
|
|||
#include "gfxUtils.h" // for gfxUtils
|
||||
#include "gfx2DGlue.h" // for thebes --> moz2d transition
|
||||
#include "mozilla/gfx/BaseSize.h" // for BaseSize
|
||||
#include "mozilla/gfx/Tools.h"
|
||||
#include "nsDebug.h" // for NS_ASSERTION, NS_WARNING, etc
|
||||
#include "nsISupportsImpl.h" // for gfxContext::AddRef, etc
|
||||
#include "nsRect.h" // for nsIntRect
|
||||
#include "nsSize.h" // for nsIntSize
|
||||
#include "LayerUtils.h"
|
||||
#include "gfxUtils.h"
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::gl;
|
||||
|
@ -126,7 +127,7 @@ CopyableCanvasLayer::UpdateTarget(DrawTarget* aDestTarget)
|
|||
Factory::CreateWrappingDataSourceSurface(destData, destStride, destSize, destFormat);
|
||||
mGLContext->Screen()->Readback(sharedSurf, data);
|
||||
if (needsPremult) {
|
||||
PremultiplySurface(data);
|
||||
gfxUtils::PremultiplyDataSurface(data);
|
||||
}
|
||||
aDestTarget->ReleaseBits(destData);
|
||||
return;
|
||||
|
@ -144,7 +145,7 @@ CopyableCanvasLayer::UpdateTarget(DrawTarget* aDestTarget)
|
|||
// Readback handles Flush/MarkDirty.
|
||||
mGLContext->Screen()->Readback(sharedSurf, data);
|
||||
if (needsPremult) {
|
||||
PremultiplySurface(data);
|
||||
gfxUtils::PremultiplyDataSurface(data);
|
||||
}
|
||||
resultSurf = data;
|
||||
}
|
||||
|
@ -170,7 +171,9 @@ CopyableCanvasLayer::GetTempSurface(const IntSize& aSize,
|
|||
aSize != mCachedTempSurface->GetSize() ||
|
||||
aFormat != mCachedTempSurface->GetFormat())
|
||||
{
|
||||
mCachedTempSurface = Factory::CreateDataSourceSurface(aSize, aFormat);
|
||||
// Create a surface aligned to 8 bytes since that's the highest alignment WebGL can handle.
|
||||
uint32_t stride = GetAlignedStride<8>(aSize.width * BytesPerPixel(aFormat));
|
||||
mCachedTempSurface = Factory::CreateDataSourceSurfaceWithStride(aSize, aFormat, stride);
|
||||
}
|
||||
|
||||
return mCachedTempSurface;
|
||||
|
|
|
@ -108,6 +108,8 @@ struct LayerPropertiesBase : public LayerProperties
|
|||
, mMaskLayer(nullptr)
|
||||
, mVisibleRegion(aLayer->GetVisibleRegion())
|
||||
, mInvalidRegion(aLayer->GetInvalidRegion())
|
||||
, mPostXScale(aLayer->GetPostXScale())
|
||||
, mPostYScale(aLayer->GetPostYScale())
|
||||
, mOpacity(aLayer->GetLocalOpacity())
|
||||
, mUseClipRect(!!aLayer->GetClipRect())
|
||||
{
|
||||
|
@ -142,7 +144,9 @@ struct LayerPropertiesBase : public LayerProperties
|
|||
{
|
||||
gfx3DMatrix transform;
|
||||
gfx::To3DMatrix(mLayer->GetTransform(), transform);
|
||||
bool transformChanged = !mTransform.FuzzyEqual(transform);
|
||||
bool transformChanged = !mTransform.FuzzyEqual(transform) ||
|
||||
mLayer->GetPostXScale() != mPostXScale ||
|
||||
mLayer->GetPostYScale() != mPostYScale;
|
||||
Layer* otherMask = mLayer->GetMaskLayer();
|
||||
const nsIntRect* otherClip = mLayer->GetClipRect();
|
||||
nsIntRegion result;
|
||||
|
@ -166,13 +170,6 @@ struct LayerPropertiesBase : public LayerProperties
|
|||
}
|
||||
}
|
||||
|
||||
nsIntRegion visible;
|
||||
visible.Xor(mVisibleRegion, mLayer->GetVisibleRegion());
|
||||
if (!visible.IsEmpty()) {
|
||||
aGeometryChanged = true;
|
||||
}
|
||||
AddTransformedRegion(result, visible, mTransform);
|
||||
|
||||
AddRegion(result, ComputeChangeInternal(aCallback, aGeometryChanged));
|
||||
AddTransformedRegion(result, mLayer->GetInvalidRegion(), mTransform);
|
||||
|
||||
|
@ -216,6 +213,8 @@ struct LayerPropertiesBase : public LayerProperties
|
|||
nsIntRegion mVisibleRegion;
|
||||
nsIntRegion mInvalidRegion;
|
||||
gfx3DMatrix mTransform;
|
||||
float mPostXScale;
|
||||
float mPostYScale;
|
||||
float mOpacity;
|
||||
nsIntRect mClipRect;
|
||||
bool mUseClipRect;
|
||||
|
@ -225,6 +224,8 @@ struct ContainerLayerProperties : public LayerPropertiesBase
|
|||
{
|
||||
ContainerLayerProperties(ContainerLayer* aLayer)
|
||||
: LayerPropertiesBase(aLayer)
|
||||
, mPreXScale(aLayer->GetPreXScale())
|
||||
, mPreYScale(aLayer->GetPreYScale())
|
||||
{
|
||||
for (Layer* child = aLayer->GetFirstChild(); child; child = child->GetNextSibling()) {
|
||||
mChildren.AppendElement(CloneLayerTreePropertiesInternal(child));
|
||||
|
@ -237,6 +238,21 @@ struct ContainerLayerProperties : public LayerPropertiesBase
|
|||
ContainerLayer* container = mLayer->AsContainerLayer();
|
||||
nsIntRegion result;
|
||||
|
||||
if (mPreXScale != container->GetPreXScale() ||
|
||||
mPreYScale != container->GetPreYScale()) {
|
||||
aGeometryChanged = true;
|
||||
result = OldTransformedBounds();
|
||||
AddRegion(result, NewTransformedBounds());
|
||||
|
||||
// If we don't have to generate invalidations separately for child
|
||||
// layers then we can just stop here since we've already invalidated the entire
|
||||
// old and new bounds.
|
||||
if (!aCallback) {
|
||||
ClearInvalidations(mLayer);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// A low frame rate is especially visible to users when scrolling, so we
|
||||
// particularly want to avoid unnecessary invalidation at that time. For us
|
||||
// here, that means avoiding unnecessary invalidation of child items when
|
||||
|
@ -312,6 +328,8 @@ struct ContainerLayerProperties : public LayerPropertiesBase
|
|||
|
||||
// The old list of children:
|
||||
nsAutoTArray<nsAutoPtr<LayerPropertiesBase>,1> mChildren;
|
||||
float mPreXScale;
|
||||
float mPreYScale;
|
||||
};
|
||||
|
||||
struct ColorLayerProperties : public LayerPropertiesBase
|
||||
|
|
|
@ -1,101 +0,0 @@
|
|||
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "LayerUtils.h"
|
||||
#include "PremultiplyTables.h"
|
||||
#include "mozilla/Endian.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
static inline const uint8_t PremultiplyValue(uint8_t a, uint8_t v) {
|
||||
return PremultiplyTable[a*256+v];
|
||||
}
|
||||
|
||||
static inline const uint8_t UnpremultiplyValue(uint8_t a, uint8_t v) {
|
||||
return UnpremultiplyTable[a*256+v];
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static bool IsLittleEndian()
|
||||
{
|
||||
// Violate strict aliasing, because violating strict aliasing is how
|
||||
// we always pack and unpack between uint32_t and uint8_t[].
|
||||
uint16_t testShort;
|
||||
static const uint8_t testBytes[2] = { 0xAA, 0xBB };
|
||||
memcpy(&testShort, testBytes, sizeof(testBytes));
|
||||
return testShort == 0xBBAA;
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
#ifdef MOZ_LITTLE_ENDIAN
|
||||
#define ASSERT_ENDIAN() MOZ_ASSERT(IsLittleEndian(), "Defined as little endian, but actually big!")
|
||||
#else
|
||||
#define ASSERT_ENDIAN() MOZ_ASSERT(!IsLittleEndian(), "Defined as big endian, but actually little!")
|
||||
#endif
|
||||
|
||||
void
|
||||
PremultiplySurface(DataSourceSurface* srcSurface,
|
||||
DataSourceSurface* destSurface)
|
||||
{
|
||||
if (!destSurface)
|
||||
destSurface = srcSurface;
|
||||
|
||||
IntSize srcSize = srcSurface->GetSize();
|
||||
MOZ_ASSERT(srcSurface->GetFormat() == destSurface->GetFormat() &&
|
||||
srcSize.width == destSurface->GetSize().width &&
|
||||
srcSize.height == destSurface->GetSize().height &&
|
||||
srcSurface->Stride() == destSurface->Stride(),
|
||||
"Source and destination surfaces don't have identical characteristics");
|
||||
|
||||
MOZ_ASSERT(srcSurface->Stride() == srcSize.width * 4,
|
||||
"Source surface stride isn't tightly packed");
|
||||
|
||||
// Only premultiply ARGB32
|
||||
if (srcSurface->GetFormat() != SurfaceFormat::B8G8R8A8) {
|
||||
if (destSurface != srcSurface) {
|
||||
memcpy(destSurface->GetData(), srcSurface->GetData(),
|
||||
srcSurface->Stride() * srcSize.height);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t *src = srcSurface->GetData();
|
||||
uint8_t *dst = destSurface->GetData();
|
||||
|
||||
// Assert that our endian define is correct.
|
||||
ASSERT_ENDIAN();
|
||||
|
||||
uint32_t dim = srcSize.width * srcSize.height;
|
||||
for (uint32_t i = 0; i < dim; ++i) {
|
||||
#ifdef MOZ_LITTLE_ENDIAN
|
||||
uint8_t b = *src++;
|
||||
uint8_t g = *src++;
|
||||
uint8_t r = *src++;
|
||||
uint8_t a = *src++;
|
||||
|
||||
*dst++ = PremultiplyValue(a, b);
|
||||
*dst++ = PremultiplyValue(a, g);
|
||||
*dst++ = PremultiplyValue(a, r);
|
||||
*dst++ = a;
|
||||
#else
|
||||
uint8_t a = *src++;
|
||||
uint8_t r = *src++;
|
||||
uint8_t g = *src++;
|
||||
uint8_t b = *src++;
|
||||
|
||||
*dst++ = a;
|
||||
*dst++ = PremultiplyValue(a, r);
|
||||
*dst++ = PremultiplyValue(a, g);
|
||||
*dst++ = PremultiplyValue(a, b);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MOZILLA_LAYERS_LAYERUTILS_H_
|
||||
#define MOZILLA_LAYERS_LAYERUTILS_H_
|
||||
|
||||
#include "mozilla/gfx/2D.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
void
|
||||
PremultiplySurface(gfx::DataSourceSurface* srcSurface,
|
||||
gfx::DataSourceSurface* destSurface = nullptr);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* MOZILLA_LAYERS_LAYERUTILS_H_ */
|
|
@ -70,9 +70,10 @@ CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
|
|||
if (mTextureFlags & TextureFlags::NEEDS_Y_FLIP) {
|
||||
flags |= TextureFlags::NEEDS_Y_FLIP;
|
||||
}
|
||||
mBuffer = CreateBufferTextureClient(gfx::ImageFormatToSurfaceFormat(format),
|
||||
flags,
|
||||
gfxPlatform::GetPlatform()->GetPreferredCanvasBackend());
|
||||
mBuffer = CreateTextureClientForDrawing(gfx::ImageFormatToSurfaceFormat(format),
|
||||
flags,
|
||||
gfxPlatform::GetPlatform()->GetPreferredCanvasBackend(),
|
||||
aSize);
|
||||
MOZ_ASSERT(mBuffer->CanExposeDrawTarget());
|
||||
mBuffer->AllocateForSurface(aSize);
|
||||
|
||||
|
|
|
@ -124,6 +124,10 @@ ImageHost::Composite(EffectChain& aEffectChain,
|
|||
} else {
|
||||
effect->mTextureCoords = Rect(0, 0, 1, 1);
|
||||
}
|
||||
if (mFrontBuffer->GetFlags() & TextureFlags::NEEDS_Y_FLIP) {
|
||||
effect->mTextureCoords.y = effect->mTextureCoords.YMost();
|
||||
effect->mTextureCoords.height = -effect->mTextureCoords.height;
|
||||
}
|
||||
GetCompositor()->DrawQuad(rect, aClipRect, aEffectChain,
|
||||
aOpacity, aTransform);
|
||||
GetCompositor()->DrawDiagnostics(DiagnosticFlags::IMAGE | DiagnosticFlags::BIGIMAGE,
|
||||
|
|
|
@ -294,7 +294,6 @@ UNIFIED_SOURCES += [
|
|||
'LayerScope.cpp',
|
||||
'LayersLogging.cpp',
|
||||
'LayerSorter.cpp',
|
||||
'LayerUtils.cpp',
|
||||
'opengl/CompositingRenderTargetOGL.cpp',
|
||||
'opengl/CompositorOGL.cpp',
|
||||
'opengl/OGLShaderProgram.cpp',
|
||||
|
|
|
@ -880,3 +880,24 @@ void gfx3DMatrix::NudgeToIntegers(void)
|
|||
NudgeToInteger(&_43);
|
||||
NudgeToInteger(&_44);
|
||||
}
|
||||
|
||||
void gfx3DMatrix::NudgeToIntegersFixedEpsilon(void)
|
||||
{
|
||||
static const float error = 1e-5;
|
||||
NudgeToInteger(&_11, error);
|
||||
NudgeToInteger(&_12, error);
|
||||
NudgeToInteger(&_13, error);
|
||||
NudgeToInteger(&_14, error);
|
||||
NudgeToInteger(&_21, error);
|
||||
NudgeToInteger(&_22, error);
|
||||
NudgeToInteger(&_23, error);
|
||||
NudgeToInteger(&_24, error);
|
||||
NudgeToInteger(&_31, error);
|
||||
NudgeToInteger(&_32, error);
|
||||
NudgeToInteger(&_33, error);
|
||||
NudgeToInteger(&_34, error);
|
||||
NudgeToInteger(&_41, error);
|
||||
NudgeToInteger(&_42, error);
|
||||
NudgeToInteger(&_43, error);
|
||||
NudgeToInteger(&_44, error);
|
||||
}
|
||||
|
|
|
@ -344,6 +344,7 @@ public:
|
|||
gfxFloat Determinant() const;
|
||||
|
||||
void NudgeToIntegers(void);
|
||||
void NudgeToIntegersFixedEpsilon();
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -3489,11 +3489,6 @@ public:
|
|||
return mFonts.Length();
|
||||
}
|
||||
|
||||
bool Equals(const gfxFontGroup& other) const {
|
||||
return mFamilies.Equals(other.mFamilies) &&
|
||||
mStyle.Equals(other.mStyle);
|
||||
}
|
||||
|
||||
const gfxFontStyle *GetStyle() const { return &mStyle; }
|
||||
|
||||
virtual gfxFontGroup *Copy(const gfxFontStyle *aStyle);
|
||||
|
|
|
@ -423,22 +423,6 @@ gfxPlatformFontList::PreloadNamesList()
|
|||
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatformFontList::SetFixedPitch(const nsAString& aFamilyName)
|
||||
{
|
||||
gfxFontFamily *family = FindFamily(aFamilyName);
|
||||
if (!family) return;
|
||||
|
||||
family->FindStyleVariations();
|
||||
nsTArray<nsRefPtr<gfxFontEntry> >& fontlist = family->GetFontList();
|
||||
|
||||
uint32_t i, numFonts = fontlist.Length();
|
||||
|
||||
for (i = 0; i < numFonts; i++) {
|
||||
fontlist[i]->mFixedPitch = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatformFontList::LoadBadUnderlineList()
|
||||
{
|
||||
|
|
|
@ -264,9 +264,6 @@ protected:
|
|||
// load the bad underline blacklist from pref.
|
||||
void LoadBadUnderlineList();
|
||||
|
||||
// explicitly set fixed-pitch flag for all faces
|
||||
void SetFixedPitch(const nsAString& aFamilyName);
|
||||
|
||||
void GenerateFontListKey(const nsAString& aKeyName, nsAString& aResult);
|
||||
|
||||
static PLDHashOperator
|
||||
|
|
|
@ -36,34 +36,24 @@ static const uint8_t UnpremultiplyValue(uint8_t a, uint8_t v) {
|
|||
}
|
||||
|
||||
void
|
||||
gfxUtils::PremultiplyImageSurface(gfxImageSurface *aSourceSurface,
|
||||
gfxImageSurface *aDestSurface)
|
||||
gfxUtils::PremultiplyDataSurface(DataSourceSurface *aSurface)
|
||||
{
|
||||
if (!aDestSurface)
|
||||
aDestSurface = aSourceSurface;
|
||||
|
||||
MOZ_ASSERT(aSourceSurface->Format() == aDestSurface->Format() &&
|
||||
aSourceSurface->Width() == aDestSurface->Width() &&
|
||||
aSourceSurface->Height() == aDestSurface->Height() &&
|
||||
aSourceSurface->Stride() == aDestSurface->Stride(),
|
||||
"Source and destination surfaces don't have identical characteristics");
|
||||
|
||||
MOZ_ASSERT(aSourceSurface->Stride() == aSourceSurface->Width() * 4,
|
||||
"Source surface stride isn't tightly packed");
|
||||
|
||||
// Only premultiply ARGB32
|
||||
if (aSourceSurface->Format() != gfxImageFormat::ARGB32) {
|
||||
if (aDestSurface != aSourceSurface) {
|
||||
memcpy(aDestSurface->Data(), aSourceSurface->Data(),
|
||||
aSourceSurface->Stride() * aSourceSurface->Height());
|
||||
}
|
||||
if (aSurface->GetFormat() != SurfaceFormat::B8G8R8A8) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t *src = aSourceSurface->Data();
|
||||
uint8_t *dst = aDestSurface->Data();
|
||||
DataSourceSurface::MappedSurface map;
|
||||
if (!aSurface->Map(DataSourceSurface::MapType::READ_WRITE, &map)) {
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(map.mStride == aSurface->GetSize().width * 4,
|
||||
"Source surface stride isn't tightly packed");
|
||||
|
||||
uint32_t dim = aSourceSurface->Width() * aSourceSurface->Height();
|
||||
uint8_t *src = map.mData;
|
||||
uint8_t *dst = map.mData;
|
||||
|
||||
uint32_t dim = aSurface->GetSize().width * aSurface->GetSize().height;
|
||||
for (uint32_t i = 0; i < dim; ++i) {
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
uint8_t b = *src++;
|
||||
|
@ -87,59 +77,8 @@ gfxUtils::PremultiplyImageSurface(gfxImageSurface *aSourceSurface,
|
|||
*dst++ = PremultiplyValue(a, b);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxUtils::UnpremultiplyImageSurface(gfxImageSurface *aSourceSurface,
|
||||
gfxImageSurface *aDestSurface)
|
||||
{
|
||||
if (!aDestSurface)
|
||||
aDestSurface = aSourceSurface;
|
||||
|
||||
MOZ_ASSERT(aSourceSurface->Format() == aDestSurface->Format() &&
|
||||
aSourceSurface->Width() == aDestSurface->Width() &&
|
||||
aSourceSurface->Height() == aDestSurface->Height(),
|
||||
"Source and destination surfaces don't have identical characteristics");
|
||||
|
||||
// Only premultiply ARGB32
|
||||
if (aSourceSurface->Format() != gfxImageFormat::ARGB32) {
|
||||
if (aDestSurface != aSourceSurface) {
|
||||
aDestSurface->CopyFrom(aSourceSurface);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t *src = aSourceSurface->Data();
|
||||
uint8_t *dst = aDestSurface->Data();
|
||||
|
||||
for (int32_t i = 0; i < aSourceSurface->Height(); ++i) {
|
||||
uint8_t *srcRow = src + (i * aSourceSurface->Stride());
|
||||
uint8_t *dstRow = dst + (i * aDestSurface->Stride());
|
||||
|
||||
for (int32_t j = 0; j < aSourceSurface->Width(); ++j) {
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
uint8_t b = *srcRow++;
|
||||
uint8_t g = *srcRow++;
|
||||
uint8_t r = *srcRow++;
|
||||
uint8_t a = *srcRow++;
|
||||
|
||||
*dstRow++ = UnpremultiplyValue(a, b);
|
||||
*dstRow++ = UnpremultiplyValue(a, g);
|
||||
*dstRow++ = UnpremultiplyValue(a, r);
|
||||
*dstRow++ = a;
|
||||
#else
|
||||
uint8_t a = *srcRow++;
|
||||
uint8_t r = *srcRow++;
|
||||
uint8_t g = *srcRow++;
|
||||
uint8_t b = *srcRow++;
|
||||
|
||||
*dstRow++ = a;
|
||||
*dstRow++ = UnpremultiplyValue(a, r);
|
||||
*dstRow++ = UnpremultiplyValue(a, g);
|
||||
*dstRow++ = UnpremultiplyValue(a, b);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
aSurface->Unmap();
|
||||
}
|
||||
|
||||
TemporaryRef<DataSourceSurface>
|
||||
|
|
|
@ -40,10 +40,7 @@ public:
|
|||
* If the source is not gfxImageFormat::ARGB32, no operation is performed. If
|
||||
* aDestSurface is given, the data is copied over.
|
||||
*/
|
||||
static void PremultiplyImageSurface(gfxImageSurface *aSourceSurface,
|
||||
gfxImageSurface *aDestSurface = nullptr);
|
||||
static void UnpremultiplyImageSurface(gfxImageSurface *aSurface,
|
||||
gfxImageSurface *aDestSurface = nullptr);
|
||||
static void PremultiplyDataSurface(DataSourceSurface *aSurface);
|
||||
static mozilla::TemporaryRef<DataSourceSurface> UnpremultiplyDataSurface(DataSourceSurface* aSurface);
|
||||
|
||||
static void ConvertBGRAtoRGBA(gfxImageSurface *aSourceSurface,
|
||||
|
|
|
@ -188,12 +188,12 @@ nsresult nsDateTimeFormatMac::FormatTMTime(nsILocale* locale,
|
|||
CFSTR("h"), CFSTR("H"),
|
||||
CFRangeMake(0, CFStringGetLength(newFormat)),
|
||||
0);
|
||||
NS_ASSERTION(replaceCount == 1, "Unexpected number of \"h\" occurrences");
|
||||
NS_ASSERTION(replaceCount <= 2, "Unexpected number of \"h\" occurrences");
|
||||
replaceCount = CFStringFindAndReplace(newFormat,
|
||||
CFSTR("a"), CFSTR(""),
|
||||
CFRangeMake(0, CFStringGetLength(newFormat)),
|
||||
0);
|
||||
NS_ASSERTION(replaceCount == 1, "Unexpected number of \"a\" occurrences");
|
||||
NS_ASSERTION(replaceCount <= 1, "Unexpected number of \"a\" occurrences");
|
||||
CFDateFormatterSetFormat(formatter, newFormat);
|
||||
CFRelease(newFormat); // note we don't own oldFormat
|
||||
}
|
||||
|
|
|
@ -1048,7 +1048,7 @@ InitClass(JSContext *cx, Handle<GlobalObject*> global, const Class *clasp, JSPro
|
|||
return nullptr;
|
||||
proto->setPrivate(nullptr);
|
||||
|
||||
Rooted<JSFunction*> ctor(cx, global->createConstructor(cx, construct, ClassName(key, cx), 0));
|
||||
Rooted<JSFunction*> ctor(cx, global->createConstructor(cx, construct, ClassName(key, cx), 1));
|
||||
if (!ctor ||
|
||||
!LinkConstructorAndPrototype(cx, ctor, proto) ||
|
||||
!DefinePropertiesAndBrand(cx, proto, properties, methods) ||
|
||||
|
|
|
@ -3675,15 +3675,15 @@ else
|
|||
fi
|
||||
AC_SUBST(CL_INCLUDES_PREFIX)
|
||||
rm -f dummy-hello.c
|
||||
|
||||
dnl Make sure that the build system can handle non-ASCII characters
|
||||
dnl in environment variables to prevent it from breaking silently on
|
||||
dnl non-English systems.
|
||||
NONASCII=$'\241\241'
|
||||
AC_SUBST(NONASCII)
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl Make sure that the build system can handle non-ASCII characters
|
||||
dnl in environment variables to prevent it from breking silently on
|
||||
dnl non-English systems.
|
||||
NONASCII=$'\241\241'
|
||||
AC_SUBST(NONASCII)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Disable -fstrict-aliasing with GCC 4.4 and earlier.
|
||||
dnl = See bugs 821502 and 832623.
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
|
||||
var count = 0;
|
||||
|
||||
function Parent() {
|
||||
// Scanning "this" properties here with Object.keys() solved the bug in my case
|
||||
//Object.keys(this);
|
||||
|
||||
this.log('Parent ctor');
|
||||
this.meth1();
|
||||
this.log('data3 before : ' + this.data3);
|
||||
this.meth2();
|
||||
// Added properties lost in ChildA
|
||||
this.log('data3 after : ' + this.data3);
|
||||
this.log('');
|
||||
|
||||
if (count++)
|
||||
assertEq(this.data3, 'z');
|
||||
}
|
||||
Parent.prototype.meth1 = function () {
|
||||
this.log('Parent.meth1()');
|
||||
};
|
||||
Parent.prototype.meth2 = function () {
|
||||
this.log('Parent.meth2()');
|
||||
// Requirement for the bug : Parent.meth2() needs to add data
|
||||
this.data4 = 'x';
|
||||
};
|
||||
Parent.prototype.log = function (data) {
|
||||
print(data);
|
||||
}
|
||||
|
||||
// Intermediate constructor to instantiate children prototype without executing Parent constructor code
|
||||
function ParentEmptyCtor() { }
|
||||
ParentEmptyCtor.prototype = Parent.prototype;
|
||||
|
||||
function ChildA() {
|
||||
this.log('ChildA ctor');
|
||||
Parent.call(this);
|
||||
}
|
||||
ChildA.prototype = new ParentEmptyCtor();
|
||||
// Using Object.create() instead solves the bug
|
||||
//ChildA.prototype = Object.create(ParentEmptyCtor.prototype);
|
||||
ChildA.prototype.constructor = ChildA;
|
||||
ChildA.prototype.meth1 = function () {
|
||||
this.log('ChildA.meth1()');
|
||||
this.data3 = 'z';
|
||||
};
|
||||
ChildA.prototype.meth2 = function () {
|
||||
this.log('ChildA.meth2()');
|
||||
};
|
||||
|
||||
function ChildB() {
|
||||
this.log('ChildB ctor');
|
||||
Parent.call(this);
|
||||
}
|
||||
ChildB.prototype = new ParentEmptyCtor();
|
||||
//ChildB.prototype = Object.create(ParentEmptyCtor.prototype);
|
||||
ChildB.prototype.constructor = ChildB;
|
||||
|
||||
function demo() {
|
||||
// Requirement for the bug : ChildB needs to be instantiated before ChildA
|
||||
new ChildB();
|
||||
new ChildA();
|
||||
}
|
||||
demo();
|
|
@ -9,7 +9,7 @@ assertEq(desc.writable, true);
|
|||
|
||||
assertEq(typeof Map, 'function');
|
||||
assertEq(Object.keys(Map).length, 0);
|
||||
assertEq(Map.length, 0);
|
||||
assertEq(Map.length, 1);
|
||||
assertEq(Map.name, "Map");
|
||||
|
||||
assertEq(Object.getPrototypeOf(Map.prototype), Object.prototype);
|
||||
|
|
|
@ -9,7 +9,7 @@ assertEq(desc.writable, true);
|
|||
|
||||
assertEq(typeof Set, 'function');
|
||||
assertEq(Object.keys(Set).length, 0);
|
||||
assertEq(Set.length, 0);
|
||||
assertEq(Set.length, 1);
|
||||
assertEq(Set.name, "Set");
|
||||
|
||||
assertEq(Object.getPrototypeOf(Set.prototype), Object.prototype);
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
// WeakMap surfaces
|
||||
|
||||
var desc = Object.getOwnPropertyDescriptor(this, "WeakMap");
|
||||
assertEq(desc.enumerable, false);
|
||||
assertEq(desc.configurable, true);
|
||||
assertEq(desc.writable, true);
|
||||
|
||||
assertEq(typeof WeakMap, 'function');
|
||||
assertEq(Object.keys(WeakMap).length, 0);
|
||||
assertEq(WeakMap.length, 1);
|
||||
assertEq(WeakMap.name, "WeakMap");
|
||||
|
||||
assertEq(Object.getPrototypeOf(WeakMap.prototype), Object.prototype);
|
||||
assertEq(Object.prototype.toString.call(WeakMap.prototype), "[object WeakMap]");
|
||||
assertEq(Object.prototype.toString.call(new WeakMap), "[object WeakMap]");
|
||||
assertEq(Object.prototype.toString.call(WeakMap()), "[object WeakMap]");
|
||||
assertEq(Object.keys(WeakMap.prototype).join(), "");
|
||||
assertEq(WeakMap.prototype.constructor, WeakMap);
|
||||
|
||||
function checkMethod(name, arity) {
|
||||
var desc = Object.getOwnPropertyDescriptor(WeakMap.prototype, name);
|
||||
assertEq(desc.enumerable, false);
|
||||
assertEq(desc.configurable, true);
|
||||
assertEq(desc.writable, true);
|
||||
assertEq(typeof desc.value, 'function');
|
||||
assertEq(desc.value.name, name);
|
||||
assertEq(desc.value.length, arity);
|
||||
}
|
||||
|
||||
// XXX: WeakMap#get implementation has an undocumented 2nd argument
|
||||
//checkMethod("get", 1);
|
||||
checkMethod("has", 1);
|
||||
checkMethod("set", 2);
|
||||
checkMethod("delete", 1);
|
||||
checkMethod("clear", 0);
|
|
@ -2147,14 +2147,10 @@ AnalyzePoppedThis(JSContext *cx, types::TypeObject *type,
|
|||
JS_ASSERT(!baseobj->inDictionaryMode());
|
||||
|
||||
Vector<MResumePoint *> callerResumePoints(cx);
|
||||
MBasicBlock *block = ins->block();
|
||||
for (MResumePoint *rp = block->callerResumePoint();
|
||||
for (MResumePoint *rp = ins->block()->callerResumePoint();
|
||||
rp;
|
||||
block = rp->block(), rp = block->callerResumePoint())
|
||||
rp = rp->block()->callerResumePoint())
|
||||
{
|
||||
JSScript *script = rp->block()->info().script();
|
||||
if (!types::AddClearDefiniteFunctionUsesInScript(cx, type, script, block->info().script()))
|
||||
return true;
|
||||
if (!callerResumePoints.append(rp))
|
||||
return false;
|
||||
}
|
||||
|
@ -2373,7 +2369,24 @@ jit::AnalyzeNewScriptProperties(JSContext *cx, JSFunction *fun,
|
|||
return false;
|
||||
}
|
||||
if (!handled)
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (baseobj->slotSpan() != 0) {
|
||||
// We found some definite properties, but their correctness is still
|
||||
// contingent on the correct frames being inlined. Add constraints to
|
||||
// invalidate the definite properties if additional functions could be
|
||||
// called at the inline frame sites.
|
||||
Vector<MBasicBlock *> exitBlocks(cx);
|
||||
for (MBasicBlockIterator block(graph.begin()); block != graph.end(); block++) {
|
||||
if (MResumePoint *rp = block->callerResumePoint()) {
|
||||
if (block->numPredecessors() == 1 && block->getPredecessor(0) == rp->block()) {
|
||||
JSScript *script = rp->block()->info().script();
|
||||
if (!types::AddClearDefiniteFunctionUsesInScript(cx, type, script, block->info().script()))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -4193,6 +4193,11 @@ IonBuilder::selectInliningTargets(ObjectVector &targets, CallInfo &callInfo, Boo
|
|||
if (!choiceSet.reserve(targets.length()))
|
||||
return false;
|
||||
|
||||
// Don't inline polymorphic sites during the definite properties analysis.
|
||||
// AddClearDefiniteFunctionUsesInScript depends on this for correctness.
|
||||
if (info().executionMode() == DefinitePropertiesAnalysis && targets.length() > 1)
|
||||
return true;
|
||||
|
||||
for (size_t i = 0; i < targets.length(); i++) {
|
||||
JSFunction *target = &targets[i]->as<JSFunction>();
|
||||
bool inlineable;
|
||||
|
|
|
@ -23,6 +23,3 @@ JSAPI_TESTS_AUTOLOAD := jsapi-tests-gdb.py.in
|
|||
JSAPI_TESTS_AUTOLOAD_FLAGS := -Dtopsrcdir=$(abspath $(srcdir)/..)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
check::
|
||||
$(wildcard $(RUN_TEST_PROGRAM)) $(DIST)/bin/jsapi-tests$(BIN_SUFFIX)
|
||||
|
|
|
@ -3360,7 +3360,9 @@ types::AddClearDefiniteFunctionUsesInScript(JSContext *cx, TypeObject *type,
|
|||
// |script|, and add constraints to ensure that if the type sets' contents
|
||||
// change then the definite properties are cleared from the type.
|
||||
// This ensures that the inlining performed when the definite properties
|
||||
// analysis was done is stable.
|
||||
// analysis was done is stable. We only need to look at type sets which
|
||||
// contain a single object, as IonBuilder does not inline polymorphic sites
|
||||
// during the definite properties analysis.
|
||||
|
||||
TypeObjectKey *calleeKey = Type::ObjectType(calleeScript->functionNonDelazifying()).objectKey();
|
||||
|
||||
|
|
|
@ -500,7 +500,7 @@ js_InitWeakMapClass(JSContext *cx, HandleObject obj)
|
|||
return nullptr;
|
||||
|
||||
RootedFunction ctor(cx, global->createConstructor(cx, WeakMap_construct,
|
||||
cx->names().WeakMap, 0));
|
||||
cx->names().WeakMap, 1));
|
||||
if (!ctor)
|
||||
return nullptr;
|
||||
|
||||
|
|
|
@ -3501,14 +3501,15 @@ Parent(JSContext *cx, unsigned argc, jsval *vp)
|
|||
}
|
||||
|
||||
Rooted<JSObject*> parent(cx, JS_GetParent(&v.toObject()));
|
||||
args.rval().setObjectOrNull(parent);
|
||||
|
||||
/* Outerize if necessary. Embrace the ugliness! */
|
||||
/* Outerize if necessary. */
|
||||
if (parent) {
|
||||
if (js::ObjectOp op = parent->getClass()->ext.outerObject)
|
||||
args.rval().setObjectOrNull(op(cx, parent));
|
||||
parent = GetOuterObject(cx, parent);
|
||||
if (!parent)
|
||||
return false;
|
||||
}
|
||||
|
||||
args.rval().setObjectOrNull(parent);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -582,13 +582,15 @@ TraceLogger::startEvent(uint32_t id)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!tree.ensureSpaceBeforeAdd()) {
|
||||
if (!tree.hasSpaceForAdd()){
|
||||
uint64_t start = rdtsc() - traceLoggers.startupTime;
|
||||
if (!flush()) {
|
||||
fprintf(stderr, "TraceLogging: Couldn't write the data to disk.\n");
|
||||
enabled = false;
|
||||
failed = true;
|
||||
return;
|
||||
if (!tree.ensureSpaceBeforeAdd()) {
|
||||
if (!flush()) {
|
||||
fprintf(stderr, "TraceLogging: Couldn't write the data to disk.\n");
|
||||
enabled = false;
|
||||
failed = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Log the time it took to flush the events as being from the
|
||||
|
|
|
@ -203,9 +203,15 @@ class ContinuousSpace {
|
|||
return data()[currentId()];
|
||||
}
|
||||
|
||||
bool ensureSpaceBeforeAdd(uint32_t count = 1) {
|
||||
bool hasSpaceForAdd(uint32_t count = 1) {
|
||||
if (next_ + count <= capacity_)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ensureSpaceBeforeAdd(uint32_t count = 1) {
|
||||
if (hasSpaceForAdd(count))
|
||||
return true;
|
||||
|
||||
uint32_t nCapacity = capacity_ * 2;
|
||||
if (next_ + count > nCapacity)
|
||||
|
|
|
@ -143,11 +143,11 @@ xpc_qsDefineQuickStubs(JSContext *cx, JSObject *protoArg, unsigned flags,
|
|||
|
||||
if (entry->newBindingProperties) {
|
||||
if (entry->newBindingProperties->regular) {
|
||||
mozilla::dom::DefineWebIDLBindingPropertiesOnXPCObject(cx, proto, entry->newBindingProperties->regular, false);
|
||||
mozilla::dom::DefineWebIDLBindingPropertiesOnXPCObject(cx, proto, entry->newBindingProperties->regular);
|
||||
}
|
||||
if (entry->newBindingProperties->chromeOnly &&
|
||||
xpc::AccessCheck::isChrome(js::GetContextCompartment(cx))) {
|
||||
mozilla::dom::DefineWebIDLBindingPropertiesOnXPCObject(cx, proto, entry->newBindingProperties->chromeOnly, false);
|
||||
mozilla::dom::DefineWebIDLBindingPropertiesOnXPCObject(cx, proto, entry->newBindingProperties->chromeOnly);
|
||||
}
|
||||
}
|
||||
// Next.
|
||||
|
|
|
@ -78,8 +78,10 @@ XPCWrappedNativeScope::XPCWrappedNativeScope(JSContext *cx,
|
|||
// add ourselves to the scopes list
|
||||
{
|
||||
MOZ_ASSERT(aGlobal);
|
||||
MOZ_ASSERT(js::GetObjectClass(aGlobal)->flags & (JSCLASS_PRIVATE_IS_NSISUPPORTS |
|
||||
JSCLASS_HAS_PRIVATE));
|
||||
DebugOnly<const js::Class*> clasp = js::GetObjectClass(aGlobal);
|
||||
MOZ_ASSERT(clasp->flags & (JSCLASS_PRIVATE_IS_NSISUPPORTS |
|
||||
JSCLASS_HAS_PRIVATE) ||
|
||||
mozilla::dom::IsDOMClass(clasp));
|
||||
#ifdef DEBUG
|
||||
for (XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext)
|
||||
MOZ_ASSERT(aGlobal != cur->GetGlobalJSObjectPreserveColor(), "dup object");
|
||||
|
|
|
@ -328,36 +328,9 @@ nsXPConnect::InitClasses(JSContext * aJSContext, JSObject * aGlobalJSObj)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static void
|
||||
VerifyTraceXPCGlobalCalled(JSTracer *trc, void **thingp, JSGCTraceKind kind)
|
||||
{
|
||||
// We don't do anything here, we only want to verify that TraceXPCGlobal
|
||||
// was called.
|
||||
}
|
||||
|
||||
struct VerifyTraceXPCGlobalCalledTracer : public JSTracer
|
||||
{
|
||||
bool ok;
|
||||
|
||||
VerifyTraceXPCGlobalCalledTracer(JSRuntime *rt)
|
||||
: JSTracer(rt, VerifyTraceXPCGlobalCalled), ok(false)
|
||||
{}
|
||||
};
|
||||
#endif
|
||||
|
||||
void
|
||||
TraceXPCGlobal(JSTracer *trc, JSObject *obj)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (trc->callback == VerifyTraceXPCGlobalCalled) {
|
||||
// We don't do anything here, we only want to verify that TraceXPCGlobal
|
||||
// was called.
|
||||
reinterpret_cast<VerifyTraceXPCGlobalCalledTracer*>(trc)->ok = true;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL)
|
||||
mozilla::dom::TraceProtoAndIfaceCache(trc, obj);
|
||||
}
|
||||
|
@ -388,7 +361,7 @@ CreateGlobalObject(JSContext *cx, const JSClass *clasp, nsIPrincipal *principal,
|
|||
// more complicated. Manual inspection shows that they do the right thing.
|
||||
if (!((const js::Class*)clasp)->ext.isWrappedNative)
|
||||
{
|
||||
VerifyTraceXPCGlobalCalledTracer trc(JS_GetRuntime(cx));
|
||||
VerifyTraceProtoAndIfaceCacheCalledTracer trc(JS_GetRuntime(cx));
|
||||
JS_TraceChildren(&trc, global, JSTRACE_OBJECT);
|
||||
MOZ_ASSERT(trc.ok, "Trace hook on global needs to call TraceXPCGlobal for XPConnect compartments.");
|
||||
}
|
||||
|
|
|
@ -3399,6 +3399,8 @@ JSObject *
|
|||
CreateGlobalObject(JSContext *cx, const JSClass *clasp, nsIPrincipal *principal,
|
||||
JS::CompartmentOptions& aOptions);
|
||||
|
||||
// InitGlobalObject enters the compartment of aGlobal, so it doesn't matter what
|
||||
// compartment aJSContext is in.
|
||||
bool
|
||||
InitGlobalObject(JSContext* aJSContext, JS::Handle<JSObject*> aGlobal,
|
||||
uint32_t aFlags);
|
||||
|
|
|
@ -275,13 +275,15 @@ DisplayItemClip::RemoveRoundedCorners()
|
|||
mRoundedClipRects.Clear();
|
||||
}
|
||||
|
||||
// Computes the difference between aR1 and aR2, limited to aBounds.
|
||||
static void
|
||||
AccumulateRectDifference(const nsRect& aR1, const nsRect& aR2, nsRegion* aOut)
|
||||
AccumulateRectDifference(const nsRect& aR1, const nsRect& aR2, const nsRect& aBounds, nsRegion* aOut)
|
||||
{
|
||||
if (aR1.IsEqualInterior(aR2))
|
||||
return;
|
||||
nsRegion r;
|
||||
r.Xor(aR1, aR2);
|
||||
r.And(r, aBounds);
|
||||
aOut->Or(*aOut, r);
|
||||
}
|
||||
|
||||
|
@ -299,8 +301,8 @@ DisplayItemClip::AddOffsetAndComputeDifference(const nsPoint& aOffset,
|
|||
return;
|
||||
}
|
||||
if (mHaveClipRect) {
|
||||
AccumulateRectDifference((mClipRect + aOffset).Intersect(aBounds),
|
||||
aOther.mClipRect.Intersect(aOtherBounds),
|
||||
AccumulateRectDifference(mClipRect + aOffset, aOther.mClipRect,
|
||||
aBounds.Union(aOtherBounds),
|
||||
aDifference);
|
||||
}
|
||||
for (uint32_t i = 0; i < mRoundedClipRects.Length(); ++i) {
|
||||
|
|
|
@ -1472,6 +1472,11 @@ ContainerState::CreateOrRecycleThebesLayer(const nsIFrame* aAnimatedGeometryRoot
|
|||
if (!FuzzyEqual(data->mXScale, mParameters.mXScale, 0.00001f) ||
|
||||
!FuzzyEqual(data->mYScale, mParameters.mYScale, 0.00001f) ||
|
||||
data->mAppUnitsPerDevPixel != mAppUnitsPerDevPixel) {
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
|
||||
printf_stderr("Recycled layer %p changed scale\n", layer.get());
|
||||
}
|
||||
#endif
|
||||
InvalidateEntireThebesLayer(layer, aAnimatedGeometryRoot);
|
||||
#ifndef MOZ_ANDROID_OMTC
|
||||
didResetScrollPositionForLayerPixelAlignment = true;
|
||||
|
@ -3107,7 +3112,9 @@ ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder,
|
|||
// Set any matrix entries close to integers to be those exact integers.
|
||||
// This protects against floating-point inaccuracies causing problems
|
||||
// in the checks below.
|
||||
transform.NudgeToIntegers();
|
||||
// We use the fixed epsilon version here because we don't want the nudging
|
||||
// to depend on the scroll position.
|
||||
transform.NudgeToIntegersFixedEpsilon();
|
||||
}
|
||||
gfxMatrix transform2d;
|
||||
if (aContainerFrame &&
|
||||
|
|
|
@ -4511,7 +4511,7 @@ nsDisplayTransform::GetResultingTransformMatrix(const FrameTransformProperties&
|
|||
nsIFrame** aOutAncestor)
|
||||
{
|
||||
return GetResultingTransformMatrixInternal(aProperties, aOrigin, aAppUnitsPerPixel,
|
||||
aBoundsOverride, aOutAncestor);
|
||||
aBoundsOverride, aOutAncestor, false);
|
||||
}
|
||||
|
||||
gfx3DMatrix
|
||||
|
@ -4519,14 +4519,16 @@ nsDisplayTransform::GetResultingTransformMatrix(const nsIFrame* aFrame,
|
|||
const nsPoint& aOrigin,
|
||||
float aAppUnitsPerPixel,
|
||||
const nsRect* aBoundsOverride,
|
||||
nsIFrame** aOutAncestor)
|
||||
nsIFrame** aOutAncestor,
|
||||
bool aOffsetByOrigin)
|
||||
{
|
||||
FrameTransformProperties props(aFrame,
|
||||
aAppUnitsPerPixel,
|
||||
aBoundsOverride);
|
||||
|
||||
return GetResultingTransformMatrixInternal(props, aOrigin, aAppUnitsPerPixel,
|
||||
aBoundsOverride, aOutAncestor);
|
||||
return GetResultingTransformMatrixInternal(props, aOrigin, aAppUnitsPerPixel,
|
||||
aBoundsOverride, aOutAncestor,
|
||||
aOffsetByOrigin);
|
||||
}
|
||||
|
||||
gfx3DMatrix
|
||||
|
@ -4534,7 +4536,8 @@ nsDisplayTransform::GetResultingTransformMatrixInternal(const FrameTransformProp
|
|||
const nsPoint& aOrigin,
|
||||
float aAppUnitsPerPixel,
|
||||
const nsRect* aBoundsOverride,
|
||||
nsIFrame** aOutAncestor)
|
||||
nsIFrame** aOutAncestor,
|
||||
bool aOffsetByOrigin)
|
||||
{
|
||||
const nsIFrame *frame = aProperties.mFrame;
|
||||
|
||||
|
@ -4542,14 +4545,6 @@ nsDisplayTransform::GetResultingTransformMatrixInternal(const FrameTransformProp
|
|||
*aOutAncestor = nsLayoutUtils::GetCrossDocParentFrame(frame);
|
||||
}
|
||||
|
||||
/* Account for the -moz-transform-origin property by translating the
|
||||
* coordinate space to the new origin.
|
||||
*/
|
||||
gfxPoint3D newOrigin =
|
||||
gfxPoint3D(NSAppUnitsToFloatPixels(aOrigin.x, aAppUnitsPerPixel),
|
||||
NSAppUnitsToFloatPixels(aOrigin.y, aAppUnitsPerPixel),
|
||||
0.0f);
|
||||
|
||||
/* Get the underlying transform matrix. This requires us to get the
|
||||
* bounds of the frame.
|
||||
*/
|
||||
|
@ -4598,28 +4593,51 @@ nsDisplayTransform::GetResultingTransformMatrixInternal(const FrameTransformProp
|
|||
result = result * nsLayoutUtils::ChangeMatrixBasis(aProperties.mToPerspectiveOrigin - aProperties.mToTransformOrigin, perspective);
|
||||
}
|
||||
|
||||
gfxPoint3D rounded(hasSVGTransforms ? newOrigin.x : NS_round(newOrigin.x),
|
||||
hasSVGTransforms ? newOrigin.y : NS_round(newOrigin.y),
|
||||
0);
|
||||
/* Account for the -moz-transform-origin property by translating the
|
||||
* coordinate space to the new origin.
|
||||
*/
|
||||
gfxPoint3D newOrigin =
|
||||
gfxPoint3D(NSAppUnitsToFloatPixels(aOrigin.x, aAppUnitsPerPixel),
|
||||
NSAppUnitsToFloatPixels(aOrigin.y, aAppUnitsPerPixel),
|
||||
0.0f);
|
||||
gfxPoint3D roundedOrigin(hasSVGTransforms ? newOrigin.x : NS_round(newOrigin.x),
|
||||
hasSVGTransforms ? newOrigin.y : NS_round(newOrigin.y),
|
||||
0);
|
||||
gfxPoint3D offsetBetweenOrigins = roundedOrigin + aProperties.mToTransformOrigin;
|
||||
|
||||
if (frame && frame->Preserves3D()) {
|
||||
// Include the transform set on our parent
|
||||
NS_ASSERTION(frame->GetParent() &&
|
||||
frame->GetParent()->IsTransformed() &&
|
||||
frame->GetParent()->Preserves3DChildren(),
|
||||
"Preserve3D mismatch!");
|
||||
FrameTransformProperties props(frame->GetParent(),
|
||||
aAppUnitsPerPixel,
|
||||
nullptr);
|
||||
gfx3DMatrix parent =
|
||||
GetResultingTransformMatrixInternal(props,
|
||||
aOrigin - frame->GetPosition(),
|
||||
aAppUnitsPerPixel, nullptr, aOutAncestor);
|
||||
return nsLayoutUtils::ChangeMatrixBasis(rounded + aProperties.mToTransformOrigin, result) * parent;
|
||||
// Include the transform set on our parent
|
||||
NS_ASSERTION(frame->GetParent() &&
|
||||
frame->GetParent()->IsTransformed() &&
|
||||
frame->GetParent()->Preserves3DChildren(),
|
||||
"Preserve3D mismatch!");
|
||||
FrameTransformProperties props(frame->GetParent(),
|
||||
aAppUnitsPerPixel,
|
||||
nullptr);
|
||||
gfx3DMatrix parent =
|
||||
GetResultingTransformMatrixInternal(props,
|
||||
aOrigin - frame->GetPosition(),
|
||||
aAppUnitsPerPixel, nullptr,
|
||||
aOutAncestor, false);
|
||||
|
||||
result = nsLayoutUtils::ChangeMatrixBasis(offsetBetweenOrigins, result) * parent;
|
||||
if (aOffsetByOrigin) {
|
||||
result.Translate(roundedOrigin);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return nsLayoutUtils::ChangeMatrixBasis
|
||||
(rounded + aProperties.mToTransformOrigin, result);
|
||||
if (aOffsetByOrigin) {
|
||||
// We can fold the final translation by roundedOrigin into the first matrix
|
||||
// basis change translation. This is more stable against variation due to
|
||||
// insufficient floating point precision than reversing the translation
|
||||
// afterwards.
|
||||
result.Translate(-aProperties.mToTransformOrigin);
|
||||
result.TranslatePost(offsetBetweenOrigins);
|
||||
} else {
|
||||
result = nsLayoutUtils::ChangeMatrixBasis(offsetBetweenOrigins, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -4726,19 +4744,17 @@ nsDisplayTransform::GetTransform()
|
|||
mTransform = mTransformGetter(mFrame, scale);
|
||||
mTransform = nsLayoutUtils::ChangeMatrixBasis(newOrigin, mTransform);
|
||||
} else {
|
||||
mTransform =
|
||||
GetResultingTransformMatrix(mFrame, ToReferenceFrame(), scale);
|
||||
|
||||
/**
|
||||
* Shift the coorindates to be relative to our reference frame instead of relative to this frame.
|
||||
* When we have preserve-3d, our reference frame is already guaranteed to be an ancestor of the
|
||||
* preserve-3d chain, so we only need to do this once.
|
||||
* Passing true as the final argument means that we want to shift the
|
||||
* coordinates to be relative to our reference frame instead of relative
|
||||
* to this frame.
|
||||
* When we have preserve-3d, our reference frame is already guaranteed
|
||||
* to be an ancestor of the preserve-3d chain, so we only need to do
|
||||
* this once.
|
||||
*/
|
||||
bool hasSVGTransforms = mFrame->IsSVGTransformed();
|
||||
gfxPoint3D rounded(hasSVGTransforms ? newOrigin.x : NS_round(newOrigin.x),
|
||||
hasSVGTransforms ? newOrigin.y : NS_round(newOrigin.y),
|
||||
0);
|
||||
mTransform.Translate(rounded);
|
||||
mTransform =
|
||||
GetResultingTransformMatrix(mFrame, ToReferenceFrame(), scale,
|
||||
nullptr, nullptr, true);
|
||||
}
|
||||
}
|
||||
return mTransform;
|
||||
|
|
|
@ -3345,12 +3345,15 @@ public:
|
|||
* for the frame's bounding rectangle. Otherwise, it will use the
|
||||
* value of aBoundsOverride. This is mostly for internal use and in
|
||||
* most cases you will not need to specify a value.
|
||||
* @param aOffsetByOrigin If true, the resulting matrix will be translated
|
||||
* by aOrigin. This translation is applied *before* the CSS transform.
|
||||
*/
|
||||
static gfx3DMatrix GetResultingTransformMatrix(const nsIFrame* aFrame,
|
||||
const nsPoint& aOrigin,
|
||||
float aAppUnitsPerPixel,
|
||||
const nsRect* aBoundsOverride = nullptr,
|
||||
nsIFrame** aOutAncestor = nullptr);
|
||||
nsIFrame** aOutAncestor = nullptr,
|
||||
bool aOffsetByOrigin = false);
|
||||
static gfx3DMatrix GetResultingTransformMatrix(const FrameTransformProperties& aProperties,
|
||||
const nsPoint& aOrigin,
|
||||
float aAppUnitsPerPixel,
|
||||
|
@ -3372,7 +3375,8 @@ private:
|
|||
const nsPoint& aOrigin,
|
||||
float aAppUnitsPerPixel,
|
||||
const nsRect* aBoundsOverride,
|
||||
nsIFrame** aOutAncestor);
|
||||
nsIFrame** aOutAncestor,
|
||||
bool aOffsetByOrigin);
|
||||
|
||||
nsDisplayWrapList mStoredList;
|
||||
gfx3DMatrix mTransform;
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
li::-moz-list-bullet {
|
||||
direction: rtl;
|
||||
margin-right: 1em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
Body
|
||||
<ul>
|
||||
<li>list item</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
|
@ -528,5 +528,6 @@ test-pref(layout.css.sticky.enabled,true) load 949932.html
|
|||
load 973701-1.xhtml
|
||||
load 973701-2.xhtml
|
||||
load 986899.html
|
||||
load 1001233.html
|
||||
load 1001258-1.html
|
||||
load outline-on-frameset.xhtml
|
||||
|
|
|
@ -6832,18 +6832,26 @@ nsBlockFrame::ReflowBullet(nsIFrame* aBulletFrame,
|
|||
// in the current writing mode. Then we subtract out the start
|
||||
// border/padding and the bullet's width and margin to offset the position.
|
||||
WritingMode wm = rs.GetWritingMode();
|
||||
LogicalRect logicalFAS(wm, floatAvailSpace, floatAvailSpace.XMost());
|
||||
nscoord containerWidth = floatAvailSpace.XMost();
|
||||
LogicalRect logicalFAS(wm, floatAvailSpace, containerWidth);
|
||||
// Get the bullet's margin, converted to our writing mode so that we can
|
||||
// combine it with other logical values here.
|
||||
WritingMode bulletWM = reflowState.GetWritingMode();
|
||||
LogicalMargin bulletMargin =
|
||||
reflowState.ComputedLogicalMargin().ConvertTo(wm, bulletWM);
|
||||
nscoord iStart = logicalFAS.IStart(wm) -
|
||||
rs.ComputedLogicalBorderPadding().IStart(wm)
|
||||
- reflowState.ComputedLogicalMargin().IEnd(wm) - aMetrics.ISize();
|
||||
rs.ComputedLogicalBorderPadding().IStart(wm) -
|
||||
bulletMargin.IEnd(wm) -
|
||||
aMetrics.ISize();
|
||||
|
||||
// Approximate the bullets position; vertical alignment will provide
|
||||
// the final vertical location.
|
||||
// the final vertical location. We pass our writing-mode here, because
|
||||
// it may be different from the bullet frame's mode.
|
||||
nscoord bStart = logicalFAS.BStart(wm);
|
||||
aBulletFrame->SetRect(LogicalRect(wm, LogicalPoint(wm, iStart, bStart),
|
||||
LogicalSize(wm, aMetrics.ISize(),
|
||||
aMetrics.BSize())),
|
||||
floatAvailSpace.XMost());
|
||||
aBulletFrame->SetRect(wm, LogicalRect(wm, LogicalPoint(wm, iStart, bStart),
|
||||
LogicalSize(wm, aMetrics.ISize(),
|
||||
aMetrics.BSize())),
|
||||
containerWidth);
|
||||
aBulletFrame->DidReflow(aState.mPresContext, &aState.mReflowState,
|
||||
nsDidReflowStatus::FINISHED);
|
||||
}
|
||||
|
|
|
@ -1878,7 +1878,7 @@ void ScrollFrameHelper::MarkInactive()
|
|||
return;
|
||||
|
||||
mScrollingActive = false;
|
||||
mOuter->InvalidateFrameSubtree();
|
||||
mOuter->SchedulePaint();
|
||||
}
|
||||
|
||||
void ScrollFrameHelper::MarkActive()
|
||||
|
|
|
@ -1796,7 +1796,7 @@ fails == 942017.html 942017-ref.html # bug 942017
|
|||
== 950436-1.html 950436-1-ref.html
|
||||
== 957770-1.svg 957770-1-ref.svg
|
||||
== 960277-1.html 960277-1-ref.html
|
||||
pref(layout.css.overflow-clip-box.enabled,true) fuzzy(50,10) == 966992-1.html 966992-1-ref.html
|
||||
pref(layout.css.overflow-clip-box.enabled,true) fuzzy(50,31) == 966992-1.html 966992-1-ref.html
|
||||
skip-if(Android) == 966510-1.html 966510-1-ref.html # scrollable elements other than the root probably won't work well on android until bug 776030 is fixed
|
||||
skip-if(Android) == 966510-2.html 966510-2-ref.html # same as above
|
||||
== 978911-1.svg 978911-1-ref.svg
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" class="reftest-wait">
|
||||
<meta charset="utf-8">
|
||||
<title>Scrolling the horizontal bar away shouldn't invalidate the green rectangle</title>
|
||||
|
||||
<style>
|
||||
|
||||
.wrapper {
|
||||
transform: translateY(1px);
|
||||
}
|
||||
|
||||
.content {
|
||||
box-sizing: border-box;
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.first {
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.second {
|
||||
margin-left: auto;
|
||||
width: 20px;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.reftest-no-paint {
|
||||
margin: -150px 100px 0;
|
||||
height: 100px;
|
||||
border-color: lime;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 50px;
|
||||
height: 3000px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div class="wrapper">
|
||||
<div class="first content"></div>
|
||||
<div class="second content"></div>
|
||||
</div>
|
||||
|
||||
<div class="reftest-no-paint content"></div>
|
||||
|
||||
<script>
|
||||
|
||||
function doTest() {
|
||||
document.documentElement.scrollTop = 100;
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
document.addEventListener("MozReftestInvalidate", doTest, false);
|
||||
|
||||
</script>
|
|
@ -0,0 +1,58 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" class="reftest-wait">
|
||||
<meta charset="utf-8">
|
||||
<title>Scrolling the horizontal bar away shouldn't invalidate the green rectangle</title>
|
||||
|
||||
<style>
|
||||
|
||||
.wrapper {
|
||||
transform: translateY(1px);
|
||||
}
|
||||
|
||||
.content {
|
||||
box-sizing: border-box;
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.first {
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.second {
|
||||
margin-left: auto;
|
||||
width: 20px;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.reftest-no-paint {
|
||||
margin: -150px 100px 0;
|
||||
height: 100px;
|
||||
border-color: lime;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 50px;
|
||||
height: 3000px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div class="wrapper">
|
||||
<div class="wrapper">
|
||||
<div class="first content"></div>
|
||||
<div class="second content"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="reftest-no-paint content"></div>
|
||||
|
||||
<script>
|
||||
|
||||
function doTest() {
|
||||
document.documentElement.scrollTop = 100;
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
document.addEventListener("MozReftestInvalidate", doTest, false);
|
||||
|
||||
</script>
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" class="reftest-wait">
|
||||
<meta charset="utf-8">
|
||||
<title>Different epsilons in NudeToInteger and FuzzyEqual cause invalidations</title>
|
||||
|
||||
<body>
|
||||
|
||||
<svg viewBox="0 0 700 3000" width="700px" height="3000px">
|
||||
<g transform="translate(0, -220.999756)">
|
||||
<rect x="100" y="400" height="50" width="50" fill="grey" class="reftest-no-paint"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
<script>
|
||||
|
||||
var scrollPositions = [0, 50];
|
||||
if (location.search.contains("reverse")) {
|
||||
scrollPositions.reverse();
|
||||
}
|
||||
document.documentElement.scrollTop = scrollPositions[0];
|
||||
|
||||
function doTest() {
|
||||
document.documentElement.scrollTop = scrollPositions[1];
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
document.addEventListener("MozReftestInvalidate", doTest, false);
|
||||
|
||||
</script>
|
|
@ -40,3 +40,9 @@ pref(layout.animated-image-layers.enabled,true) == test-animated-image-layers-ba
|
|||
== filter-userspace-offset.svg?offsetContainer=rect&filter=matrix-fillPaint-userSpace-at100 filter-userspace-offset.svg
|
||||
== scroll-inactive-layers.html scroll-inactive-layers.html
|
||||
== scroll-inactive-layers-2.html scroll-inactive-layers-2.html
|
||||
!= inactive-layertree-visible-region-1.html about:blank
|
||||
!= inactive-layertree-visible-region-2.html about:blank
|
||||
!= transform-floating-point-invalidation.html about:blank
|
||||
!= transform-floating-point-invalidation.html?reverse about:blank
|
||||
!= nudge-to-integer-invalidation.html about:blank
|
||||
!= nudge-to-integer-invalidation.html?reverse about:blank
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" class="reftest-wait">
|
||||
<meta charset="utf-8">
|
||||
<title>Scrolling shouldn't invalidate the rect</title>
|
||||
|
||||
<body>
|
||||
|
||||
<svg width="824" height="1375" viewBox="0 0 660 1100">
|
||||
<rect x="100" y="600" width="120" height="120" fill="#EEE"
|
||||
transform="matrix(0,0.969665,-2.0321494,0,1828.58132,65.718239)"
|
||||
class="reftest-no-paint"/>
|
||||
</svg>
|
||||
|
||||
<script>
|
||||
|
||||
var scrollPositions = [81, 82];
|
||||
if (location.search.contains("reverse")) {
|
||||
scrollPositions.reverse();
|
||||
}
|
||||
document.documentElement.scrollTop = scrollPositions[0];
|
||||
|
||||
function doTest() {
|
||||
document.documentElement.scrollTop = scrollPositions[1];
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
document.addEventListener("MozReftestInvalidate", doTest, false);
|
||||
|
||||
</script>
|
|
@ -1470,6 +1470,18 @@ PeerConnectionImpl::SetDtlsConnected(bool aPrivacyRequested)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
void
|
||||
PeerConnectionImpl::PrincipalChanged(DOMMediaStream* aMediaStream) {
|
||||
nsIDocument* doc = GetWindow()->GetExtantDoc();
|
||||
if (doc) {
|
||||
mMedia->UpdateSinkIdentity_m(doc->NodePrincipal(), mPeerIdentity);
|
||||
} else {
|
||||
CSFLogInfo(logTag, "Can't update sink principal; document gone");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
PeerConnectionImpl::AddStream(DOMMediaStream &aMediaStream,
|
||||
const MediaConstraintsInternal& aConstraints)
|
||||
|
@ -1511,6 +1523,8 @@ PeerConnectionImpl::AddStream(DOMMediaStream &aMediaStream,
|
|||
return res;
|
||||
}
|
||||
|
||||
aMediaStream.AddPrincipalChangeObserver(this);
|
||||
|
||||
// TODO(ekr@rtfm.com): these integers should be the track IDs
|
||||
if (hints & DOMMediaStream::HINT_CONTENTS_AUDIO) {
|
||||
cc_media_constraints_t* cc_constraints = aConstraints.build();
|
||||
|
@ -1539,6 +1553,8 @@ PeerConnectionImpl::RemoveStream(DOMMediaStream& aMediaStream) {
|
|||
if (NS_FAILED(res))
|
||||
return res;
|
||||
|
||||
aMediaStream.RemovePrincipalChangeObserver(this);
|
||||
|
||||
uint32_t hints = aMediaStream.GetHintContents();
|
||||
|
||||
if (hints & DOMMediaStream::HINT_CONTENTS_AUDIO) {
|
||||
|
@ -1751,6 +1767,12 @@ PeerConnectionImpl::ShutdownMedia()
|
|||
return;
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
// before we destroy references to local streams, detach from them
|
||||
for(uint32_t i = 0; i < media()->LocalStreamsLength(); ++i) {
|
||||
LocalSourceStreamInfo *info = media()->GetLocalStream(i);
|
||||
info->GetMediaStream()->RemovePrincipalChangeObserver(this);
|
||||
}
|
||||
|
||||
// End of call to be recorded in Telemetry
|
||||
if (!mStartTime.IsNull()){
|
||||
TimeDuration timeDelta = TimeStamp::Now() - mStartTime;
|
||||
|
|
|
@ -38,6 +38,9 @@
|
|||
#include "mozilla/dom/RTCStatsReportBinding.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "mozilla/PeerIdentity.h"
|
||||
#ifndef USE_FAKE_MEDIA_STREAMS
|
||||
#include "DOMMediaStream.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace test {
|
||||
|
@ -197,6 +200,7 @@ class PeerConnectionImpl MOZ_FINAL : public nsISupports,
|
|||
#ifdef MOZILLA_INTERNAL_API
|
||||
public mozilla::DataChannelConnection::DataConnectionListener,
|
||||
public nsNSSShutDownObject,
|
||||
public DOMMediaStream::PrincipalChangeObserver,
|
||||
#endif
|
||||
public sigslot::has_slots<>
|
||||
{
|
||||
|
@ -552,6 +556,10 @@ public:
|
|||
RTCStatsQuery *query);
|
||||
|
||||
static nsresult ExecuteStatsQuery_s(RTCStatsQuery *query);
|
||||
|
||||
// for monitoring changes in stream ownership
|
||||
// PeerConnectionMedia can't do it because it doesn't know about principals
|
||||
virtual void PrincipalChanged(DOMMediaStream* aMediaStream) MOZ_OVERRIDE;
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
|
|
@ -244,6 +244,14 @@ public:
|
|||
|
||||
void SetTrackEnabled(mozilla::TrackID aTrackID, bool aEnabled) {}
|
||||
|
||||
class PrincipalChangeObserver
|
||||
{
|
||||
public:
|
||||
virtual void PrincipalChanged(Fake_DOMMediaStream* aMediaStream) = 0;
|
||||
};
|
||||
void AddPrincipalChangeObserver(void* ignoredObserver) {}
|
||||
void RemovePrincipalChangeObserver(void* ignoredObserver) {}
|
||||
|
||||
private:
|
||||
nsRefPtr<Fake_MediaStream> mMediaStream;
|
||||
|
||||
|
|
|
@ -31,6 +31,15 @@ add_task(function test_AndroidLog() {
|
|||
do_check_eq(48, AndroidLog.w.bind(null, "AndroidLogTest")("This is a warning message."));
|
||||
do_check_eq(47, AndroidLog.e.bind(null, "AndroidLogTest")("This is an error message."));
|
||||
|
||||
// Ensure the functions work when the tag length is greater than the maximum
|
||||
// tag length.
|
||||
let tag = "X".repeat(AndroidLog.MAX_TAG_LENGTH + 1);
|
||||
do_check_eq(AndroidLog.MAX_TAG_LENGTH + 54, AndroidLog.v(tag, "This is a verbose message with a too-long tag."));
|
||||
do_check_eq(AndroidLog.MAX_TAG_LENGTH + 52, AndroidLog.d(tag, "This is a debug message with a too-long tag."));
|
||||
do_check_eq(AndroidLog.MAX_TAG_LENGTH + 52, AndroidLog.i(tag, "This is an info message with a too-long tag."));
|
||||
do_check_eq(AndroidLog.MAX_TAG_LENGTH + 54, AndroidLog.w(tag, "This is a warning message with a too-long tag."));
|
||||
do_check_eq(AndroidLog.MAX_TAG_LENGTH + 53, AndroidLog.e(tag, "This is an error message with a too-long tag."));
|
||||
|
||||
// We should also ensure that the module is accessible from a ChromeWorker,
|
||||
// but there doesn't seem to be a way to load a ChromeWorker from this test.
|
||||
});
|
||||
|
|
|
@ -29,7 +29,8 @@
|
|||
* debug("This is a debug message.");
|
||||
*
|
||||
* Note: the module automatically prepends "Gecko" to the tag you specify,
|
||||
* since all tags used by Fennec code should start with that string.
|
||||
* since all tags used by Fennec code should start with that string; and it
|
||||
* truncates tags longer than MAX_TAG_LENGTH characters (not including "Gecko").
|
||||
*/
|
||||
|
||||
if (typeof Components != "undefined") {
|
||||
|
@ -45,6 +46,12 @@ const ANDROID_LOG_INFO = 4;
|
|||
const ANDROID_LOG_WARN = 5;
|
||||
const ANDROID_LOG_ERROR = 6;
|
||||
|
||||
// android.util.Log.isLoggable throws IllegalArgumentException if a tag length
|
||||
// exceeds 23 characters, and we prepend five characters ("Gecko") to every tag,
|
||||
// so we truncate tags exceeding 18 characters (although __android_log_write
|
||||
// itself and other android.util.Log methods don't seem to mind longer tags).
|
||||
const MAX_TAG_LENGTH = 18;
|
||||
|
||||
let liblog = ctypes.open("liblog.so"); // /system/lib/liblog.so
|
||||
let __android_log_write = liblog.declare("__android_log_write",
|
||||
ctypes.default_abi,
|
||||
|
@ -54,11 +61,12 @@ let __android_log_write = liblog.declare("__android_log_write",
|
|||
ctypes.char.ptr); // message
|
||||
|
||||
let AndroidLog = {
|
||||
v: (tag, msg) => __android_log_write(ANDROID_LOG_VERBOSE, "Gecko" + tag, msg),
|
||||
d: (tag, msg) => __android_log_write(ANDROID_LOG_DEBUG, "Gecko" + tag, msg),
|
||||
i: (tag, msg) => __android_log_write(ANDROID_LOG_INFO, "Gecko" + tag, msg),
|
||||
w: (tag, msg) => __android_log_write(ANDROID_LOG_WARN, "Gecko" + tag, msg),
|
||||
e: (tag, msg) => __android_log_write(ANDROID_LOG_ERROR, "Gecko" + tag, msg),
|
||||
MAX_TAG_LENGTH: MAX_TAG_LENGTH,
|
||||
v: (tag, msg) => __android_log_write(ANDROID_LOG_VERBOSE, "Gecko" + tag.substring(0, MAX_TAG_LENGTH), msg),
|
||||
d: (tag, msg) => __android_log_write(ANDROID_LOG_DEBUG, "Gecko" + tag.substring(0, MAX_TAG_LENGTH), msg),
|
||||
i: (tag, msg) => __android_log_write(ANDROID_LOG_INFO, "Gecko" + tag.substring(0, MAX_TAG_LENGTH), msg),
|
||||
w: (tag, msg) => __android_log_write(ANDROID_LOG_WARN, "Gecko" + tag.substring(0, MAX_TAG_LENGTH), msg),
|
||||
e: (tag, msg) => __android_log_write(ANDROID_LOG_ERROR, "Gecko" + tag.substring(0, MAX_TAG_LENGTH), msg),
|
||||
};
|
||||
|
||||
if (typeof Components == "undefined") {
|
||||
|
|
|
@ -760,6 +760,8 @@ pref("dom.webapps.useCurrentProfile", false);
|
|||
|
||||
pref("dom.cycle_collector.incremental", true);
|
||||
|
||||
pref("dom.window_experimental_bindings", false);
|
||||
|
||||
// Parsing perf prefs. For now just mimic what the old code did.
|
||||
#ifndef XP_WIN
|
||||
pref("content.sink.pending_event_mode", 0);
|
||||
|
@ -1940,6 +1942,13 @@ pref("layout.display-list.dump", false);
|
|||
// heavily loaded.
|
||||
pref("layout.frame_rate.precise", false);
|
||||
|
||||
// Is support for the Web Animations API enabled?
|
||||
#ifdef RELEASE_BUILD
|
||||
pref("dom.animations-api.core.enabled", false);
|
||||
#else
|
||||
pref("dom.animations-api.core.enabled", true);
|
||||
#endif
|
||||
|
||||
// pref to permit users to make verified SOAP calls by default
|
||||
pref("capability.policy.default.SOAPCall.invokeVerifySourceHeader", "allAccess");
|
||||
|
||||
|
|
|
@ -74,10 +74,9 @@ nsTemporaryFileInputStream::ReadSegments(nsWriteSegmentFun writer,
|
|||
nsresult rv = writer(this, closure, buf,
|
||||
count - remainBufCount, bufCount, &write_result);
|
||||
remainBufCount -= bufCount;
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
NS_ASSERTION(write_result <= bufCount,
|
||||
"writer should not write more than we asked it to write");
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ASSERTION(write_result <= bufCount,
|
||||
"writer should not write more than we asked it to write");
|
||||
mStartPos += bufCount;
|
||||
}
|
||||
*result = count;
|
||||
|
|
|
@ -626,7 +626,6 @@ nsHttpConnectionMgr::ReportSpdyConnection(nsHttpConnection *conn,
|
|||
if (!ent->mCoalescingKey.IsEmpty()) {
|
||||
mSpdyPreferredHash.Put(ent->mCoalescingKey, ent);
|
||||
ent->mSpdyPreferred = true;
|
||||
preferred = ent;
|
||||
}
|
||||
} else if ((preferred != ent) &&
|
||||
(joinedConnection = GetSpdyPreferredEnt(ent)) &&
|
||||
|
|
|
@ -715,7 +715,9 @@ DataChannelConnection::SctpDtlsOutput(void *addr, void *buffer, size_t length,
|
|||
} else {
|
||||
unsigned char *data = new unsigned char[length];
|
||||
memcpy(data, buffer, length);
|
||||
res = -1;
|
||||
// Commented out since we have to Dispatch SendPacket to avoid deadlock"
|
||||
// res = -1;
|
||||
|
||||
// XXX It might be worthwhile to add an assertion against the thread
|
||||
// somehow getting into the DataChannel/SCTP code again, as
|
||||
// DISPATCH_SYNC is not fully blocking. This may be tricky, as it
|
||||
|
|
|
@ -3171,7 +3171,6 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
|
|||
uint32_t vrf_id;
|
||||
|
||||
lport = 0;
|
||||
error = 0;
|
||||
bindall = 1;
|
||||
inp = (struct sctp_inpcb *)so->so_pcb;
|
||||
#if defined(INET) || (defined(INET6) && defined(__APPLE__)) || defined(__FreeBSD__) || defined(__APPLE__)
|
||||
|
|
|
@ -206,7 +206,6 @@ sctp_sha1_update(struct sctp_sha1_context *ctx, const unsigned char *ptr, unsign
|
|||
ptr, number_left);
|
||||
ctx->how_many_in_block += number_left;
|
||||
ctx->running_total += number_left;
|
||||
number_left = 0;
|
||||
break;
|
||||
} else {
|
||||
/* block is now full, process it */
|
||||
|
|
|
@ -2782,7 +2782,6 @@ sctp_userspace_ip_output(int *result, struct mbuf *o_pak,
|
|||
int use_udp_tunneling;
|
||||
|
||||
*result = 0;
|
||||
send_count = 0;
|
||||
|
||||
m = SCTP_HEADER_TO_CHAIN(o_pak);
|
||||
m_orig = m;
|
||||
|
@ -2938,7 +2937,6 @@ void sctp_userspace_ip6_output(int *result, struct mbuf *o_pak,
|
|||
int use_udp_tunneling;
|
||||
|
||||
*result = 0;
|
||||
send_count = 0;
|
||||
|
||||
m = SCTP_HEADER_TO_CHAIN(o_pak);
|
||||
m_orig = m;
|
||||
|
|
|
@ -132,16 +132,10 @@ index_guess(const xtd_seq_num_t *local,
|
|||
uint32_t local_roc = (uint32_t)(*local >> 16);
|
||||
uint16_t local_seq = (uint16_t) *local;
|
||||
#endif
|
||||
#ifdef NO_64BIT_MATH
|
||||
uint32_t guess_roc = ((high32(*guess) << 16) |
|
||||
(low32(*guess) >> 16));
|
||||
uint16_t guess_seq = (uint16_t) (low32(*guess));
|
||||
#else
|
||||
uint32_t guess_roc = (uint32_t)(*guess >> 16);
|
||||
uint16_t guess_seq = (uint16_t) *guess;
|
||||
#endif
|
||||
uint32_t guess_roc;
|
||||
uint16_t guess_seq;
|
||||
int difference;
|
||||
|
||||
|
||||
if (local_seq < seq_num_median) {
|
||||
if (s - local_seq > seq_num_median) {
|
||||
guess_roc = local_roc - 1;
|
||||
|
@ -160,7 +154,7 @@ index_guess(const xtd_seq_num_t *local,
|
|||
}
|
||||
}
|
||||
guess_seq = s;
|
||||
|
||||
|
||||
/* Note: guess_roc is 32 bits, so this generates a 48-bit result! */
|
||||
#ifdef NO_64BIT_MATH
|
||||
*guess = make64(guess_roc >> 16,
|
||||
|
|
|
@ -166,7 +166,6 @@ srtp_stream_init_from_ekt(srtp_stream_t stream,
|
|||
err_status_t err;
|
||||
const uint8_t *master_key;
|
||||
srtp_policy_t srtp_policy;
|
||||
unsigned master_key_len;
|
||||
uint32_t roc;
|
||||
|
||||
/*
|
||||
|
@ -178,7 +177,6 @@ srtp_stream_init_from_ekt(srtp_stream_t stream,
|
|||
|
||||
if (stream->ekt->data->ekt_cipher_type != EKT_CIPHER_AES_128_ECB)
|
||||
return err_status_bad_param;
|
||||
master_key_len = 16;
|
||||
|
||||
/* decrypt the Encrypted Master Key field */
|
||||
master_key = srtcp_packet_get_emk_location(srtcp_hdr, pkt_octet_len);
|
||||
|
|
|
@ -319,6 +319,11 @@ function _getBinaryUtil(binaryUtilName) {
|
|||
utilBin.append("bin");
|
||||
utilBin.append(binaryUtilName + (gIsWindows ? ".exe" : ""));
|
||||
}
|
||||
// But maybe we're on Android or B2G, where binaries are in /data/local/xpcb.
|
||||
if (!utilBin.exists()) {
|
||||
utilBin.initWithPath("/data/local/xpcb/");
|
||||
utilBin.append(binaryUtilName);
|
||||
}
|
||||
do_check_true(utilBin.exists());
|
||||
return utilBin;
|
||||
}
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче