Merge inbound to central, a=merge

MozReview-Commit-ID: 87zaFE5GN5Y
This commit is contained in:
Wes Kocher 2016-04-11 16:02:30 -07:00
Родитель e7e4a7abbf 364386e3cf
Коммит 4db4931366
82 изменённых файлов: 6812 добавлений и 4825 удалений

Просмотреть файл

@ -219,7 +219,7 @@ EventTree::Process()
AccHideEvent* hideEvent = downcast_accEvent(mtEvent);
if (hideEvent->NeedsShutdown()) {
mContainer->Document()->ShutdownChildrenInSubtree(hideEvent->mAccessible);
mtEvent->GetDocAccessible()->ShutdownChildrenInSubtree(mtEvent->mAccessible);
}
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -111,9 +111,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.11.0"
#define SQLITE_VERSION_NUMBER 3011000
#define SQLITE_SOURCE_ID "2016-02-15 17:29:24 3d862f207e3adc00f78066799ac5a8c282430a5f"
#define SQLITE_VERSION "3.12.1"
#define SQLITE_VERSION_NUMBER 3012001
#define SQLITE_SOURCE_ID "2016-04-08 15:09:49 fe7d3b75fe1bde41511b323925af8ae1b910bc4d"
/*
** CAPI3REF: Run-Time Library Version Numbers
@ -1228,7 +1228,7 @@ struct sqlite3_vfs {
const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName);
/*
** The methods above are in versions 1 through 3 of the sqlite_vfs object.
** New fields may be appended in figure versions. The iVersion
** New fields may be appended in future versions. The iVersion
** value will increment whenever this happens.
*/
};
@ -1820,6 +1820,20 @@ struct sqlite3_mem_methods {
** is enabled (using the [PRAGMA threads] command) and the amount of content
** to be sorted exceeds the page size times the minimum of the
** [PRAGMA cache_size] setting and this value.
**
** [[SQLITE_CONFIG_STMTJRNL_SPILL]]
** <dt>SQLITE_CONFIG_STMTJRNL_SPILL
** <dd>^The SQLITE_CONFIG_STMTJRNL_SPILL option takes a single parameter which
** becomes the [statement journal] spill-to-disk threshold.
** [Statement journals] are held in memory until their size (in bytes)
** exceeds this threshold, at which point they are written to disk.
** Or if the threshold is -1, statement journals are always held
** exclusively in memory.
** Since many statement journals never become large, setting the spill
** threshold to a value such as 64KiB can greatly reduce the amount of
** I/O required to support statement rollback.
** The default value for this setting is controlled by the
** [SQLITE_STMTJRNL_SPILL] compile-time option.
** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
@ -1847,6 +1861,7 @@ struct sqlite3_mem_methods {
#define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */
#define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */
#define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */
#define SQLITE_CONFIG_STMTJRNL_SPILL 26 /* int nByte */
/*
** CAPI3REF: Database Connection Configuration Options
@ -1904,11 +1919,25 @@ struct sqlite3_mem_methods {
** following this call. The second parameter may be a NULL pointer, in
** which case the trigger setting is not reported back. </dd>
**
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
** <dd> ^This option is used to enable or disable the two-argument
** version of the [fts3_tokenizer()] function which is part of the
** [FTS3] full-text search engine extension.
** There should be two additional arguments.
** The first argument is an integer which is 0 to disable fts3_tokenizer() or
** positive to enable fts3_tokenizer() or negative to leave the setting
** unchanged.
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether fts3_tokenizer is disabled or enabled
** following this call. The second parameter may be a NULL pointer, in
** which case the new setting is not reported back. </dd>
**
** </dl>
*/
#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */
#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */
/*
@ -7489,7 +7518,7 @@ SQLITE_API void SQLITE_CDECL sqlite3_log(int iErrCode, const char *zFormat, ...)
** previously registered write-ahead log callback. ^Note that the
** [sqlite3_wal_autocheckpoint()] interface and the
** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will
** those overwrite any prior [sqlite3_wal_hook()] settings.
** overwrite any prior [sqlite3_wal_hook()] settings.
*/
SQLITE_API void *SQLITE_STDCALL sqlite3_wal_hook(
sqlite3*,
@ -7886,6 +7915,18 @@ SQLITE_API void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
*/
SQLITE_API int SQLITE_STDCALL sqlite3_db_cacheflush(sqlite3*);
/*
** CAPI3REF: Low-level system error code
**
** ^Attempt to return the underlying operating system error code or error
** number that caused the most reason I/O error or failure to open a file.
** The return value is OS-dependent. For example, on unix systems, after
** [sqlite3_open_v2()] returns [SQLITE_CANTOPEN], this interface could be
** called to get back the underlying "errno" that caused the problem, such
** as ENOSPC, EAUTH, EISDIR, and so forth.
*/
SQLITE_API int SQLITE_STDCALL sqlite3_system_errno(sqlite3*);
/*
** CAPI3REF: Database Snapshot
** KEYWORDS: {snapshot}
@ -7954,7 +7995,11 @@ SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_snapshot_get(
** the first operation, apart from other sqlite3_snapshot_open() calls,
** following the [BEGIN] that starts a new read transaction.
** ^A [snapshot] will fail to open if it has been overwritten by a
** [checkpoint].
** [checkpoint].
** ^A [snapshot] will fail to open if the database connection D has not
** previously completed at least one read operation against the database
** file. (Hint: Run "[PRAGMA application_id]" against a newly opened
** database connection in order to make it ready to use snapshots.)
**
** The [sqlite3_snapshot_open()] interface is only available when the
** SQLITE_ENABLE_SNAPSHOT compile-time option is used.

Просмотреть файл

@ -221,6 +221,21 @@ EffectCompositor::PostRestyleForThrottledAnimations()
}
}
void
EffectCompositor::UpdateEffectProperties(nsStyleContext* aStyleContext,
dom::Element* aElement,
CSSPseudoElementType aPseudoType)
{
EffectSet* effectSet = EffectSet::GetEffectSet(aElement, aPseudoType);
if (!effectSet) {
return;
}
for (KeyframeEffectReadOnly* effect : *effectSet) {
effect->UpdateProperties(aStyleContext);
}
}
void
EffectCompositor::MaybeUpdateAnimationRule(dom::Element* aElement,
CSSPseudoElementType aPseudoType,

Просмотреть файл

@ -111,6 +111,14 @@ public:
// posted because updates on the main thread are throttled.
void PostRestyleForThrottledAnimations();
// Called when the style context on the specified (pseudo-) element might
// have changed so that any context-sensitive values stored within
// animation effects (e.g. em-based endpoints used in keyframe effects)
// can be re-resolved to computed values.
void UpdateEffectProperties(nsStyleContext* aStyleContext,
dom::Element* aElement,
CSSPseudoElementType aPseudoType);
// Updates the animation rule stored on the EffectSet for the
// specified (pseudo-)element for cascade level |aLevel|.
// If the animation rule is not marked as needing an update,

Просмотреть файл

@ -457,6 +457,46 @@ KeyframeEffectReadOnly::SetAnimation(Animation* aAnimation)
NotifyAnimationTimingUpdated();
}
static bool
KeyframesEqualIgnoringComputedOffsets(const nsTArray<Keyframe>& aLhs,
const nsTArray<Keyframe>& aRhs)
{
if (aLhs.Length() != aRhs.Length()) {
return false;
}
for (size_t i = 0, len = aLhs.Length(); i < len; ++i) {
const Keyframe& a = aLhs[i];
const Keyframe& b = aRhs[i];
if (a.mOffset != b.mOffset ||
a.mTimingFunction != b.mTimingFunction ||
a.mPropertyValues != b.mPropertyValues) {
return false;
}
}
return true;
}
void
KeyframeEffectReadOnly::SetFrames(nsTArray<Keyframe>&& aFrames,
nsStyleContext* aStyleContext)
{
if (KeyframesEqualIgnoringComputedOffsets(aFrames, mFrames)) {
return;
}
mFrames = Move(aFrames);
KeyframeUtils::ApplyDistributeSpacing(mFrames);
if (mAnimation && mAnimation->IsRelevant()) {
nsNodeUtils::AnimationChanged(mAnimation);
}
if (aStyleContext) {
UpdateProperties(aStyleContext);
}
}
const AnimationProperty*
KeyframeEffectReadOnly::GetAnimationOfProperty(nsCSSProperty aProperty) const
{
@ -486,17 +526,25 @@ KeyframeEffectReadOnly::HasAnimationOfProperties(
return false;
}
bool
KeyframeEffectReadOnly::UpdateProperties(
const InfallibleTArray<AnimationProperty>& aProperties)
void
KeyframeEffectReadOnly::UpdateProperties(nsStyleContext* aStyleContext)
{
// AnimationProperty::operator== does not compare mWinsInCascade and
// mIsRunningOnCompositor, we don't need to update anything here because
// we want to preserve
if (mProperties == aProperties) {
return false;
MOZ_ASSERT(aStyleContext);
nsTArray<AnimationProperty> properties;
if (mTarget) {
properties =
KeyframeUtils::GetAnimationPropertiesFromKeyframes(aStyleContext,
mTarget,
mPseudoType,
mFrames);
}
if (mProperties == properties) {
return;
}
// Preserve the state of mWinsInCascade and mIsRunningOnCompositor flags.
nsCSSPropertySet winningInCascadeProperties;
nsCSSPropertySet runningOnCompositorProperties;
@ -509,7 +557,7 @@ KeyframeEffectReadOnly::UpdateProperties(
}
}
mProperties = aProperties;
mProperties = Move(properties);
for (AnimationProperty& property : mProperties) {
property.mWinsInCascade =
@ -518,6 +566,13 @@ KeyframeEffectReadOnly::UpdateProperties(
runningOnCompositorProperties.HasProperty(property.mProperty);
}
if (mTarget) {
EffectSet* effectSet = EffectSet::GetEffectSet(mTarget, mPseudoType);
if (effectSet) {
effectSet->MarkCascadeNeedsUpdate();
}
}
if (mAnimation) {
nsPresContext* presContext = GetPresContext();
if (presContext) {
@ -527,8 +582,6 @@ KeyframeEffectReadOnly::UpdateProperties(
mAnimation->CascadeLevel());
}
}
return true;
}
void
@ -711,17 +764,15 @@ KeyframeEffectReadOnly::ConstructKeyframeEffect(
pseudoType = target.GetAsCSSPseudoElement().GetType();
}
if (!targetElement->GetComposedDoc()) {
aRv.Throw(NS_ERROR_DOM_ANIM_TARGET_NOT_IN_DOC_ERR);
return nullptr;
}
nsTArray<Keyframe> keyframes =
KeyframeUtils::GetKeyframesFromObject(aGlobal.Context(), aFrames, aRv);
if (aRv.Failed()) {
return nullptr;
}
KeyframeUtils::ApplyDistributeSpacing(keyframes);
RefPtr<KeyframeEffectType> effect =
new KeyframeEffectType(targetElement->OwnerDoc(), targetElement,
pseudoType, timingParams);
RefPtr<nsStyleContext> styleContext;
nsIPresShell* shell = doc->GetShell();
@ -733,20 +784,8 @@ KeyframeEffectReadOnly::ConstructKeyframeEffect(
nsComputedDOMStyle::GetStyleContextForElement(targetElement, pseudo,
shell);
}
effect->SetFrames(Move(keyframes), styleContext);
nsTArray<AnimationProperty> animationProperties;
if (styleContext) {
animationProperties =
KeyframeUtils::GetAnimationPropertiesFromKeyframes(styleContext,
targetElement,
pseudoType,
keyframes);
}
RefPtr<KeyframeEffectType> effect =
new KeyframeEffectType(targetElement->OwnerDoc(), targetElement,
pseudoType, timingParams);
effect->mProperties = Move(animationProperties);
return effect.forget();
}
@ -820,81 +859,6 @@ struct KeyframeValue
StyleAnimationValue mValue;
};
/**
* Represents a relative position for a value in a keyframe animation.
*/
enum class ValuePosition
{
First, // value at 0 used for reverse filling
Left, // value coming in to a given offset
Right, // value coming out from a given offset
Last // value at 1 used for forward filling
};
/**
* A single value in a keyframe animation, used by GetFrames to produce a
* minimal set of keyframe objects.
*/
struct OrderedKeyframeValueEntry : KeyframeValue
{
float mOffset;
const Maybe<ComputedTimingFunction>* mTimingFunction;
ValuePosition mPosition;
bool SameKeyframe(const OrderedKeyframeValueEntry& aOther) const
{
return mOffset == aOther.mOffset &&
!!mTimingFunction == !!aOther.mTimingFunction &&
(!mTimingFunction || *mTimingFunction == *aOther.mTimingFunction) &&
mPosition == aOther.mPosition;
}
struct ForKeyframeGenerationComparator
{
static bool Equals(const OrderedKeyframeValueEntry& aLhs,
const OrderedKeyframeValueEntry& aRhs)
{
return aLhs.SameKeyframe(aRhs) &&
aLhs.mProperty == aRhs.mProperty;
}
static bool LessThan(const OrderedKeyframeValueEntry& aLhs,
const OrderedKeyframeValueEntry& aRhs)
{
// First, sort by offset.
if (aLhs.mOffset != aRhs.mOffset) {
return aLhs.mOffset < aRhs.mOffset;
}
// Second, by position.
if (aLhs.mPosition != aRhs.mPosition) {
return aLhs.mPosition < aRhs.mPosition;
}
// Third, by easing.
if (aLhs.mTimingFunction) {
if (aRhs.mTimingFunction) {
int32_t order =
ComputedTimingFunction::Compare(*aLhs.mTimingFunction,
*aRhs.mTimingFunction);
if (order != 0) {
return order < 0;
}
} else {
return true;
}
} else {
if (aRhs.mTimingFunction) {
return false;
}
}
// Last, by property IDL name.
return nsCSSProps::PropertyIDLNameSortPosition(aLhs.mProperty) <
nsCSSProps::PropertyIDLNameSortPosition(aRhs.mProperty);
}
};
};
/* static */ already_AddRefed<KeyframeEffectReadOnly>
KeyframeEffectReadOnly::Constructor(
const GlobalObject& aGlobal,
@ -1026,67 +990,25 @@ KeyframeEffectReadOnly::GetFrames(JSContext*& aCx,
nsTArray<JSObject*>& aResult,
ErrorResult& aRv)
{
nsTArray<OrderedKeyframeValueEntry> entries;
MOZ_ASSERT(aResult.IsEmpty());
MOZ_ASSERT(!aRv.Failed());
for (const AnimationProperty& property : mProperties) {
for (size_t i = 0, n = property.mSegments.Length(); i < n; i++) {
const AnimationPropertySegment& segment = property.mSegments[i];
// We append the mFromValue for each segment. If the mToValue
// differs from the following segment's mFromValue, or if we're on
// the last segment, then we append the mToValue as well.
//
// Each value is annotated with whether it is a "first", "left", "right",
// or "last" value. "left" and "right" values represent the value coming
// in to and out of a given offset, in the middle of an animation. For
// most segments, the mToValue is the "left" and the following segment's
// mFromValue is the "right". The "first" and "last" values are the
// additional values assigned to offset 0 or 1 for reverse and forward
// filling. These annotations are used to ensure multiple values for a
// given property are sorted correctly and that we do not merge Keyframes
// with different values for the same offset.
OrderedKeyframeValueEntry* entry = entries.AppendElement();
entry->mProperty = property.mProperty;
entry->mValue = segment.mFromValue;
entry->mOffset = segment.mFromKey;
entry->mTimingFunction = &segment.mTimingFunction;
entry->mPosition =
segment.mFromKey == segment.mToKey && segment.mFromKey == 0.0f ?
ValuePosition::First :
ValuePosition::Right;
if (i == n - 1 ||
segment.mToValue != property.mSegments[i + 1].mFromValue) {
entry = entries.AppendElement();
entry->mProperty = property.mProperty;
entry->mValue = segment.mToValue;
entry->mOffset = segment.mToKey;
entry->mTimingFunction = segment.mToKey == 1.0f ?
nullptr : &segment.mTimingFunction;
entry->mPosition =
segment.mFromKey == segment.mToKey && segment.mToKey == 1.0f ?
ValuePosition::Last :
ValuePosition::Left;
}
}
if (!aResult.SetCapacity(mFrames.Length(), mozilla::fallible)) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return;
}
entries.Sort(OrderedKeyframeValueEntry::ForKeyframeGenerationComparator());
for (size_t i = 0, n = entries.Length(); i < n; ) {
OrderedKeyframeValueEntry* entry = &entries[i];
OrderedKeyframeValueEntry* previousEntry = nullptr;
// Create a JS object with the BaseComputedKeyframe dictionary members.
for (const Keyframe& keyframe : mFrames) {
// Set up a dictionary object for the explicit members
BaseComputedKeyframe keyframeDict;
keyframeDict.mOffset.SetValue(entry->mOffset);
keyframeDict.mComputedOffset.Construct(entry->mOffset);
if (entry->mTimingFunction && entry->mTimingFunction->isSome()) {
// If null, leave easing as its default "linear".
keyframeDict.mEasing.Truncate();
entry->mTimingFunction->value().AppendToString(keyframeDict.mEasing);
if (keyframe.mOffset) {
keyframeDict.mOffset.SetValue(keyframe.mOffset.value());
}
keyframeDict.mComputedOffset.Construct(keyframe.mComputedOffset);
if (keyframe.mTimingFunction) {
keyframeDict.mEasing.Truncate();
keyframe.mTimingFunction.ref().AppendToString(keyframeDict.mEasing);
} // else if null, leave easing as its default "linear".
JS::Rooted<JS::Value> keyframeJSValue(aCx);
if (!ToJSValue(aCx, keyframeDict, &keyframeJSValue)) {
@ -1094,27 +1016,33 @@ KeyframeEffectReadOnly::GetFrames(JSContext*& aCx,
return;
}
JS::Rooted<JSObject*> keyframe(aCx, &keyframeJSValue.toObject());
do {
const char* name = nsCSSProps::PropertyIDLName(entry->mProperty);
nsString stringValue;
StyleAnimationValue::UncomputeValue(entry->mProperty,
entry->mValue,
stringValue);
JS::Rooted<JSObject*> keyframeObject(aCx, &keyframeJSValue.toObject());
for (const PropertyValuePair& propertyValue : keyframe.mPropertyValues) {
const char* name = nsCSSProps::PropertyIDLName(propertyValue.mProperty);
// nsCSSValue::AppendToString does not accept shorthands properties but
// works with token stream values if we pass eCSSProperty_UNKNOWN as
// the property.
nsCSSProperty propertyForSerializing =
nsCSSProps::IsShorthand(propertyValue.mProperty)
? eCSSProperty_UNKNOWN
: propertyValue.mProperty;
nsAutoString stringValue;
propertyValue.mValue.AppendToString(
propertyForSerializing, stringValue, nsCSSValue::eNormalized);
JS::Rooted<JS::Value> value(aCx);
if (!ToJSValue(aCx, stringValue, &value) ||
!JS_DefineProperty(aCx, keyframe, name, value, JSPROP_ENUMERATE)) {
!JS_DefineProperty(aCx, keyframeObject, name, value,
JSPROP_ENUMERATE)) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
if (++i == n) {
break;
}
previousEntry = entry;
entry = &entries[i];
} while (entry->SameKeyframe(*previousEntry));
}
aResult.AppendElement(keyframe);
aResult.AppendElement(keyframeObject);
}
}

Просмотреть файл

@ -63,6 +63,11 @@ struct PropertyValuePair
// property values, we store the specified property value as a token stream
// (string).
nsCSSValue mValue;
bool operator==(const PropertyValuePair& aOther) const {
return mProperty == aOther.mProperty &&
mValue == aOther.mValue;
}
};
/**
@ -83,12 +88,20 @@ struct PropertyValuePair
struct Keyframe
{
Keyframe() = default;
Keyframe(const Keyframe& aOther) = default;
Keyframe(Keyframe&& aOther)
: mOffset(aOther.mOffset)
, mComputedOffset(aOther.mComputedOffset)
, mTimingFunction(Move(aOther.mTimingFunction))
, mPropertyValues(Move(aOther.mPropertyValues))
{
*this = Move(aOther);
}
Keyframe& operator=(const Keyframe& aOther) = default;
Keyframe& operator=(Keyframe&& aOther)
{
mOffset = aOther.mOffset;
mComputedOffset = aOther.mComputedOffset;
mTimingFunction = Move(aOther.mTimingFunction);
mPropertyValues = Move(aOther.mPropertyValues);
return *this;
}
Maybe<double> mOffset;
@ -274,6 +287,7 @@ public:
void SetAnimation(Animation* aAnimation);
Animation* GetAnimation() const { return mAnimation; }
void SetFrames(nsTArray<Keyframe>&& aFrames, nsStyleContext* aStyleContext);
const AnimationProperty*
GetAnimationOfProperty(nsCSSProperty aProperty) const;
bool HasAnimationOfProperty(nsCSSProperty aProperty) const {
@ -287,12 +301,10 @@ public:
InfallibleTArray<AnimationProperty>& Properties() {
return mProperties;
}
// Updates the set of properties using the supplied list whilst preserving
// the mWinsInCascade and mIsRunningOnCompositor state of any matching
// properties.
// Returns true if we updated anything in the properties.
bool UpdateProperties(
const InfallibleTArray<AnimationProperty>& aProperties);
// Update |mProperties| by recalculating from |mFrames| using |aStyleContext|
// to resolve specified values.
void UpdateProperties(nsStyleContext* aStyleContext);
// Updates |aStyleRule| with the animation values produced by this
// AnimationEffect for the current time except any properties already
@ -363,7 +375,11 @@ protected:
OwningNonNull<AnimationEffectTimingReadOnly> mTiming;
CSSPseudoElementType mPseudoType;
InfallibleTArray<AnimationProperty> mProperties;
// The specified keyframes.
nsTArray<Keyframe> mFrames;
// A set of per-property value arrays, derived from |mFrames|.
nsTArray<AnimationProperty> mProperties;
// The computed progress last time we composed the style rule. This is
// used to detect when the progress is not changing (e.g. due to a step

Просмотреть файл

@ -467,6 +467,9 @@ KeyframeUtils::GetAnimationPropertiesFromKeyframes(
CSSPseudoElementType aPseudoType,
const nsTArray<Keyframe>& aFrames)
{
MOZ_ASSERT(aStyleContext);
MOZ_ASSERT(aElement);
nsTArray<KeyframeValueEntry> entries;
for (const Keyframe& frame : aFrames) {

Просмотреть файл

@ -15,8 +15,8 @@
}
@keyframes anim-only-non-animatable {
from { display: none; }
to { display: inline; }
from { animation-duration: 3s; }
to { animation-duration: 5s; }
}
@keyframes anim-simple {
@ -59,6 +59,13 @@
50% { color: blue; }
}
@keyframes anim-partially-omit-to {
from { margin-top: 50px;
margin-bottom: 100px; }
to { margin-top: 150px !important; /* ignored */
margin-bottom: 200px; }
}
@keyframes anim-different-props {
from { color: black; margin-top: 8px; }
25% { color: blue; }
@ -100,6 +107,27 @@
50% { margin-bottom: 10px; animation-timing-function: step-end; }
to { margin-top: 20px; margin-right: 20px; margin-bottom: 20px; }
}
@keyframes anim-overriding {
from { padding-top: 50px }
50%, from { padding-top: 30px } /* wins: 0% */
75%, 85%, 50% { padding-top: 20px } /* wins: 75%, 50% */
100%, 85% { padding-top: 70px } /* wins: 100% */
85.1% { padding-top: 60px } /* wins: 85.1% */
85% { padding-top: 30px } /* wins: 85% */
}
@keyframes anim-filter {
to { filter: blur(5px) sepia(60%) saturate(30%); }
}
@keyframes anim-text-shadow {
to { text-shadow: none; }
}
@keyframes anim-background-size {
to { background-size: 50%, 6px, contain }
}
</style>
<body>
<script>
@ -114,7 +142,12 @@ function assert_frames_equal(a, b, name) {
Object.keys(b).sort().toString(),
"properties on " + name);
for (var p in a) {
assert_equals(a[p], b[p], "value for '" + p + "' on " + name);
if (p === 'offset' || p === 'computedOffset') {
assert_approx_equals(a[p], b[p], 0.00001,
"value for '" + p + "' on " + name);
} else {
assert_equals(a[p], b[p], "value for '" + p + "' on " + name);
}
}
}
@ -142,7 +175,6 @@ const kTimingFunctionValues = [
test(function(t) {
var div = addDiv(t);
var frames;
div.style.animation = 'anim-empty 100s';
assert_equals(getFrames(div).length, 0,
@ -173,10 +205,8 @@ test(function(t) {
assert_equals(frames.length, 2, "number of frames");
var expected = [
{ offset: 0, computedOffset: 0, easing: "ease",
color: "rgb(0, 0, 0)" },
{ offset: 1, computedOffset: 1, easing: "linear",
color: "rgb(255, 255, 255)" },
{ offset: 0, computedOffset: 0, easing: "ease", color: "black" },
{ offset: 1, computedOffset: 1, easing: "ease", color: "white" },
];
for (var i = 0; i < frames.length; i++) {
@ -195,7 +225,7 @@ test(function(t) {
assert_equals(frames.length, 3, "number of frames");
for (var i = 0; i < frames.length; i++) {
assert_equals(frames[i].easing, i == frames.length - 1 ? "linear" : easing,
assert_equals(frames[i].easing, easing,
"value for 'easing' on ComputedKeyframe #" + i);
}
});
@ -214,7 +244,7 @@ test(function(t) {
"value of 'easing' on ComputedKeyframe #0");
assert_equals(frames[1].easing, "ease-in-out",
"value of 'easing' on ComputedKeyframe #1");
assert_equals(frames[2].easing, "linear",
assert_equals(frames[2].easing, "step-end",
"value of 'easing' on ComputedKeyframe #2");
}, 'KeyframeEffectReadOnly.getFrames() returns frames with expected easing ' +
'values, when the easing is specified on each keyframe');
@ -230,7 +260,7 @@ test(function(t) {
"value of 'easing' on ComputedKeyframe #0");
assert_equals(frames[1].easing, "step-start",
"value of 'easing' on ComputedKeyframe #1");
assert_equals(frames[2].easing, "linear",
assert_equals(frames[2].easing, "step-start",
"value of 'easing' on ComputedKeyframe #2");
}, 'KeyframeEffectReadOnly.getFrames() returns frames with expected easing ' +
'values, when the easing is specified on some keyframes');
@ -245,11 +275,11 @@ test(function(t) {
var expected = [
{ offset: 0, computedOffset: 0, easing: "ease",
marginTop: "8px", marginRight: "8px",
marginBottom: "8px", marginLeft: "8px" },
{ offset: 1, computedOffset: 1, easing: "linear",
marginTop: "16px", marginRight: "16px",
marginBottom: "16px", marginLeft: "16px" },
marginBottom: "8px", marginLeft: "8px",
marginRight: "8px", marginTop: "8px" },
{ offset: 1, computedOffset: 1, easing: "ease",
marginBottom: "16px", marginLeft: "16px",
marginRight: "16px", marginTop: "16px" },
];
for (var i = 0; i < frames.length; i++) {
@ -268,9 +298,8 @@ test(function(t) {
assert_equals(frames.length, 2, "number of frames");
var expected = [
{ offset: 0, computedOffset: 0, easing: "ease",
color: "rgb(0, 0, 255)" },
{ offset: 1, computedOffset: 1, easing: "linear",
{ offset: 0, computedOffset: 0, easing: "ease", color: "blue" },
{ offset: 1, computedOffset: 1, easing: "ease",
color: "rgb(255, 255, 255)" },
];
@ -292,8 +321,7 @@ test(function(t) {
var expected = [
{ offset: 0, computedOffset: 0, easing: "ease",
color: "rgb(255, 255, 255)" },
{ offset: 1, computedOffset: 1, easing: "linear",
color: "rgb(0, 0, 255)" },
{ offset: 1, computedOffset: 1, easing: "ease", color: "blue" },
];
for (var i = 0; i < frames.length; i++) {
@ -312,11 +340,10 @@ test(function(t) {
assert_equals(frames.length, 3, "number of frames");
var expected = [
{ offset: 0, computedOffset: 0, easing: "ease",
{ offset: 0, computedOffset: 0, easing: "ease",
color: "rgb(255, 255, 255)" },
{ offset: 0.5, computedOffset: 0.5, easing: "ease",
color: "rgb(0, 0, 255)" },
{ offset: 1, computedOffset: 1, easing: "linear",
{ offset: 0.5, computedOffset: 0.5, easing: "ease", color: "blue" },
{ offset: 1, computedOffset: 1, easing: "ease",
color: "rgb(255, 255, 255)" },
];
@ -326,6 +353,29 @@ test(function(t) {
}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for an ' +
'animation with no 0% or 100% keyframe but with a 50% keyframe');
test(function(t) {
var div = addDiv(t);
div.style.animation = 'anim-partially-omit-to 100s';
div.style.marginTop = '250px';
var frames = getFrames(div);
assert_equals(frames.length, 2, "number of frames");
var expected = [
{ offset: 0, computedOffset: 0, easing: "ease",
marginTop: '50px', marginBottom: '100px' },
{ offset: 1, computedOffset: 1, easing: "ease",
marginTop: '250px', marginBottom: '200px' },
];
for (var i = 0; i < frames.length; i++) {
assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
}
}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for an ' +
'animation with a partially complete 100% keyframe (because the ' +
'!important rule is ignored)');
test(function(t) {
var div = addDiv(t);
@ -336,13 +386,13 @@ test(function(t) {
var expected = [
{ offset: 0, computedOffset: 0, easing: "ease",
color: "rgb(0, 0, 0)", marginTop: "8px" },
color: "black", marginTop: "8px" },
{ offset: 0.25, computedOffset: 0.25, easing: "ease",
color: "rgb(0, 0, 255)" },
color: "blue" },
{ offset: 0.75, computedOffset: 0.75, easing: "ease",
marginTop: "12px" },
{ offset: 1, computedOffset: 1, easing: "linear",
color: "rgb(255, 255, 255)", marginTop: "16px" },
{ offset: 1, computedOffset: 1, easing: "ease",
color: "white", marginTop: "16px" },
];
for (var i = 0; i < frames.length; i++) {
@ -362,13 +412,13 @@ test(function(t) {
var expected = [
{ offset: 0, computedOffset: 0, easing: "linear",
color: "rgb(0, 0, 0)", marginTop: "8px" },
color: "black", marginTop: "8px" },
{ offset: 0.25, computedOffset: 0.25, easing: "step-end",
color: "rgb(0, 0, 255)" },
color: "blue" },
{ offset: 0.75, computedOffset: 0.75, easing: "ease-in",
marginTop: "12px" },
{ offset: 1, computedOffset: 1, easing: "linear",
color: "rgb(255, 255, 255)", marginTop: "16px" },
{ offset: 1, computedOffset: 1, easing: "ease",
color: "white", marginTop: "16px" },
];
for (var i = 0; i < frames.length; i++) {
@ -388,9 +438,9 @@ test(function(t) {
var expected = [
{ offset: 0, computedOffset: 0, easing: "ease",
color: "rgb(0, 0, 0)", marginTop: "8px" },
{ offset: 1, computedOffset: 1, easing: "linear",
color: "rgb(255, 255, 255)", marginTop: "16px" },
color: "black", marginTop: "8px" },
{ offset: 1, computedOffset: 1, easing: "ease",
color: "white", marginTop: "16px" },
];
for (var i = 0; i < frames.length; i++) {
@ -409,12 +459,12 @@ test(function(t) {
assert_equals(frames.length, 3, "number of frames");
var expected = [
{ offset: 0, computedOffset: 0, easing: "step-end",
color: "black", fontSize: "16px" },
{ offset: 0, computedOffset: 0, easing: "linear",
marginTop: "8px", paddingLeft: "2px" },
{ offset: 0, computedOffset: 0, easing: "step-end",
color: "rgb(0, 0, 0)", fontSize: "16px" },
{ offset: 1, computedOffset: 1, easing: "linear",
color: "rgb(255, 255, 255)", fontSize: "32px", marginTop: "16px",
{ offset: 1, computedOffset: 1, easing: "ease",
color: "white", fontSize: "32px", marginTop: "16px",
paddingLeft: "4px" },
];
@ -434,15 +484,15 @@ test(function(t) {
assert_equals(frames.length, 5, "number of frames");
var expected = [
{ offset: 0, computedOffset: 0, easing: "steps(1, end)",
marginTop: "0px" },
{ offset: 0, computedOffset: 0, easing: "step-end",
marginRight: "0px" },
{ offset: 0, computedOffset: 0, easing: "steps(1)",
marginBottom: "0px" },
{ offset: 0, computedOffset: 0, easing: "steps(1, end)",
marginTop: "0px" },
{ offset: 0.5, computedOffset: 0.5, easing: "step-end",
marginTop: "10px", marginRight: "10px", marginBottom: "10px" },
{ offset: 1, computedOffset: 1, easing: "linear",
{ offset: 1, computedOffset: 1, easing: "ease",
marginTop: "20px", marginRight: "20px", marginBottom: "20px" },
];
@ -453,6 +503,122 @@ test(function(t) {
'animation with multiple keyframes for the same time and with ' +
'different but equivalent easing functions');
test(function(t) {
var div = addDiv(t);
div.style.animation = 'anim-overriding 100s';
var frames = getFrames(div);
assert_equals(frames.length, 6, "number of frames");
var expected = [
{ offset: 0, computedOffset: 0, easing: "ease",
paddingTop: "30px" },
{ offset: 0.5, computedOffset: 0.5, easing: "ease",
paddingTop: "20px" },
{ offset: 0.75, computedOffset: 0.75, easing: "ease",
paddingTop: "20px" },
{ offset: 0.85, computedOffset: 0.85, easing: "ease",
paddingTop: "30px" },
{ offset: 0.851, computedOffset: 0.851, easing: "ease",
paddingTop: "60px" },
{ offset: 1, computedOffset: 1, easing: "ease",
paddingTop: "70px" },
];
for (var i = 0; i < frames.length; i++) {
assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
}
}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for ' +
'overlapping keyframes');
// Gecko-specific test case: We are specifically concerned here that the
// computed value for filter, "none", is correctly represented.
test(function(t) {
var div = addDiv(t);
div.style.animation = 'anim-filter 100s';
var frames = getFrames(div);
assert_equals(frames.length, 2, "number of frames");
var expected = [
{ offset: 0, computedOffset: 0, easing: "ease",
filter: "none" },
{ offset: 1, computedOffset: 1, easing: "ease",
filter: "blur(5px) sepia(60%) saturate(30%)" },
];
for (var i = 0; i < frames.length; i++) {
assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
}
}, 'KeyframeEffectReadOnly.getFrames() returns expected values for ' +
'animations with filter properties and missing keyframes');
// Gecko-specific test case: We are specifically concerned here that the
// computed value for text-shadow and a "none" specified on a keyframe
// are correctly represented.
test(function(t) {
var div = addDiv(t);
div.style.textShadow = '1px 1px 2px black, 0 0 16px blue, 0 0 3.2px blue';
div.style.animation = 'anim-text-shadow 100s';
var frames = getFrames(div);
assert_equals(frames.length, 2, "number of frames");
var expected = [
{ offset: 0, computedOffset: 0, easing: "ease",
textShadow: "1px 1px 2px 0px rgb(0, 0, 0),"
+ " 0px 0px 16px 0px rgb(0, 0, 255),"
+ " 0px 0px 3.2px 0px rgb(0, 0, 255)" },
{ offset: 1, computedOffset: 1, easing: "ease", textShadow: "none" },
];
for (var i = 0; i < frames.length; i++) {
assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
}
}, 'KeyframeEffectReadOnly.getFrames() returns expected values for ' +
'animations with text-shadow properties and missing keyframes');
// Gecko-specific test case: We are specifically concerned here that the
// initial value for background-size and the specified list are correctly
// represented.
test(function(t) {
var div = addDiv(t);
div.style.animation = 'anim-background-size 100s';
var frames = getFrames(div);
assert_equals(frames.length, 2, "number of frames");
var expected = [
{ offset: 0, computedOffset: 0, easing: "ease",
backgroundSize: "auto auto" },
{ offset: 1, computedOffset: 1, easing: "ease",
backgroundSize: "50% auto, 6px auto, contain" },
];
for (var i = 0; i < frames.length; i++) {
assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
}
// Test inheriting a background-size value
expected[0].backgroundSize = div.style.backgroundSize =
"30px auto, 40% auto, auto auto";
frames = getFrames(div);
for (var i = 0; i < frames.length; i++) {
assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i
+ " after updating current style");
}
}, 'KeyframeEffectReadOnly.getFrames() returns expected values for ' +
'animations with background-size properties and missing keyframes');
done();
</script>
</body>

Просмотреть файл

@ -22,6 +22,8 @@ namespace dom {
class GlobalObject;
class DOMMatrix;
class DOMPoint;
struct DOMPointInit;
class DOMMatrixReadOnly : public nsWrapperCache
{

Просмотреть файл

@ -18,10 +18,13 @@
#include "mozilla/dom/StructuredCloneTags.h"
#include "mozilla/dom/UnionConversions.h"
#include "mozilla/EventDispatcher.h"
#include "nsContentUtils.h"
#include "nsGlobalWindow.h"
#include "nsIPresShell.h"
#include "nsIPrincipal.h"
#include "nsIScriptError.h"
#include "nsPresContext.h"
#include "nsQueryObject.h"
namespace mozilla {
namespace dom {

Просмотреть файл

@ -14,6 +14,7 @@
#include "nsThreadUtils.h"
class nsGlobalWindow;
class nsIDocument;
class nsIPrincipal;
namespace mozilla {

Просмотреть файл

@ -8,8 +8,10 @@
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/WebKitCSSMatrixBinding.h"
#include "mozilla/Preferences.h"
#include "nsCSSParser.h"
#include "nsStyleTransformMatrix.h"
#include "RuleNodeCacheConditions.h"
namespace mozilla {
namespace dom {

Просмотреть файл

@ -119,7 +119,6 @@ DOM4_MSG_DEF(BtAuthRejectedError, "Authentication rejected", NS_ERROR_DOM_BLUET
DOM4_MSG_DEF(NotSupportedError, "Animation to or from an underlying value is not yet supported.", NS_ERROR_DOM_ANIM_MISSING_PROPS_ERR)
DOM4_MSG_DEF(NotSupportedError, "Animation with no target is not yet supported.", NS_ERROR_DOM_ANIM_NO_TARGET_ERR)
DOM4_MSG_DEF(NotSupportedError, "Animation with a target not bound to a document is not yet supported.", NS_ERROR_DOM_ANIM_TARGET_NOT_IN_DOC_ERR)
/* common global codes (from nsError.h) */

Просмотреть файл

@ -3132,7 +3132,8 @@ nsContentUtils::IsImageInCache(nsIURI* aURI, nsIDocument* aDocument)
// static
nsresult
nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,
nsContentUtils::LoadImage(nsIURI* aURI, nsINode* aContext,
nsIDocument* aLoadingDocument,
nsIPrincipal* aLoadingPrincipal, nsIURI* aReferrer,
net::ReferrerPolicy aReferrerPolicy,
imgINotificationObserver* aObserver, int32_t aLoadFlags,
@ -3141,6 +3142,7 @@ nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,
uint32_t aContentPolicyType)
{
NS_PRECONDITION(aURI, "Must have a URI");
NS_PRECONDITION(aContext, "Must have a context");
NS_PRECONDITION(aLoadingDocument, "Must have a document");
NS_PRECONDITION(aLoadingPrincipal, "Must have a principal");
NS_PRECONDITION(aRequest, "Null out param");
@ -3170,6 +3172,7 @@ nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,
aLoadingPrincipal, /* loading principal */
loadGroup, /* loadgroup */
aObserver, /* imgINotificationObserver */
aContext, /* loading context */
aLoadingDocument, /* uniquification key */
aLoadFlags, /* load flags */
nullptr, /* cache key */

Просмотреть файл

@ -679,6 +679,8 @@ public:
* keep a mutable version around should pass in a clone.
*
* @param aURI uri of the image to be loaded
* @param aContext element of document where the result of this request
* will be used.
* @param aLoadingDocument the document we belong to
* @param aLoadingPrincipal the principal doing the load
* @param aReferrer the referrer URI
@ -691,6 +693,7 @@ public:
* @return the imgIRequest for the image load
*/
static nsresult LoadImage(nsIURI* aURI,
nsINode* aContext,
nsIDocument* aLoadingDocument,
nsIPrincipal* aLoadingPrincipal,
nsIURI* aReferrer,

Просмотреть файл

@ -9823,6 +9823,7 @@ nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr,
RefPtr<imgRequestProxy> request;
nsresult rv =
nsContentUtils::LoadImage(uri,
static_cast<nsINode*>(this),
this,
NodePrincipal(),
mDocumentURI, // uri of document used as referrer

Просмотреть файл

@ -871,7 +871,11 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
RefPtr<imgRequestProxy>& req = PrepareNextRequest(aImageLoadType);
nsCOMPtr<nsIContent> content =
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
nsresult rv = nsContentUtils::LoadImage(aNewURI, aDocument,
nsCOMPtr<nsINode> thisNode =
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
nsresult rv = nsContentUtils::LoadImage(aNewURI,
thisNode,
aDocument,
aDocument->NodePrincipal(),
aDocument->GetDocumentURI(),
referrerPolicy,

Просмотреть файл

@ -79,6 +79,7 @@ void AudioInputCubeb::UpdateDeviceList()
(devices->device[i]->state == CUBEB_DEVICE_STATE_ENABLED ||
devices->device[i]->state == CUBEB_DEVICE_STATE_UNPLUGGED ||
(devices->device[i]->state == CUBEB_DEVICE_STATE_DISABLED &&
devices->device[i]->friendly_name &&
strcmp(devices->device[i]->friendly_name, "Sine source at 440 Hz") == 0)))
{
auto j = mDeviceNames->IndexOf(devices->device[i]->device_id);

Просмотреть файл

@ -196,6 +196,7 @@ PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface,
, mHasPainted(false)
, mSurfaceDifferenceRect(0,0,0,0)
, mDestroyed(false)
, mStackDepth(0)
{
memset(&mWindow, 0, sizeof(mWindow));
mWindow.type = NPWindowTypeWindow;
@ -383,6 +384,7 @@ PluginInstanceChild::NPN_GetValue(NPNVariable aVar,
{
PLUGIN_LOG_DEBUG(("%s (aVar=%i)", FULLFUNCTION, (int) aVar));
AssertPluginThread();
AutoStackHelper guard(this);
switch(aVar) {
@ -591,6 +593,8 @@ PluginInstanceChild::NPN_SetValue(NPPVariable aVar, void* aValue)
AssertPluginThread();
AutoStackHelper guard(this);
switch (aVar) {
case NPPVpluginWindowBool: {
NPError rv;
@ -695,6 +699,7 @@ PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginWantsAllNetworkStreams(
bool* wantsAllStreams, NPError* rv)
{
AssertPluginThread();
AutoStackHelper guard(this);
uint32_t value = 0;
if (!mPluginIface->getvalue) {
@ -713,6 +718,7 @@ PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginNeedsXEmbed(
bool* needs, NPError* rv)
{
AssertPluginThread();
AutoStackHelper guard(this);
#ifdef MOZ_X11
// The documentation on the types for many variables in NP(N|P)_GetValue
@ -747,6 +753,7 @@ PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginScriptableNPObject(
NPError* aResult)
{
AssertPluginThread();
AutoStackHelper guard(this);
NPObject* object = nullptr;
NPError result = NPERR_GENERIC_ERROR;
@ -784,6 +791,7 @@ PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginNativeAccessibleAtkPlugId(
NPError* aResult)
{
AssertPluginThread();
AutoStackHelper guard(this);
#if MOZ_ACCESSIBILITY_ATK
@ -856,6 +864,7 @@ PluginInstanceChild::AnswerNPP_HandleEvent(const NPRemoteEvent& event,
{
PLUGIN_LOG_DEBUG_FUNCTION;
AssertPluginThread();
AutoStackHelper guard(this);
#if defined(MOZ_X11) && defined(DEBUG)
if (GraphicsExpose == event.event.type)
@ -938,6 +947,7 @@ PluginInstanceChild::AnswerNPP_HandleEvent_Shmem(const NPRemoteEvent& event,
{
PLUGIN_LOG_DEBUG_FUNCTION;
AssertPluginThread();
AutoStackHelper guard(this);
PaintTracker pt;
@ -1042,6 +1052,7 @@ PluginInstanceChild::AnswerNPP_HandleEvent_IOSurface(const NPRemoteEvent& event,
{
PLUGIN_LOG_DEBUG_FUNCTION;
AssertPluginThread();
AutoStackHelper guard(this);
PaintTracker pt;
@ -1237,6 +1248,7 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow)
NS_ASSERTION(!mLayersRendering && !mPendingPluginCall,
"Shouldn't be receiving NPP_SetWindow with layer rendering");
AssertPluginThread();
AutoStackHelper guard(this);
#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
NS_ASSERTION(mWsInfo.display, "We should have a valid display!");
@ -2490,6 +2502,7 @@ PluginInstanceChild::DoNPP_NewStream(BrowserStreamChild* actor,
uint16_t* stype)
{
AssertPluginThread();
AutoStackHelper guard(this);
NPError rv = actor->StreamConstructed(mimeType, seekable, stype);
return rv;
}
@ -2708,6 +2721,7 @@ PluginInstanceChild::NPN_NewStream(NPMIMEType aMIMEType, const char* aWindow,
NPStream** aStream)
{
AssertPluginThread();
AutoStackHelper guard(this);
PluginStreamChild* ps = new PluginStreamChild();
@ -2790,6 +2804,7 @@ PluginInstanceChild::NPN_InitAsyncSurface(NPSize *size, NPImageFormat format,
void *initData, NPAsyncSurface *surface)
{
AssertPluginThread();
AutoStackHelper guard(this);
if (!IsUsingDirectDrawing()) {
return NPERR_INVALID_PARAM;
@ -3007,6 +3022,7 @@ PluginInstanceChild::RecvAsyncSetWindow(const gfxSurfaceType& aSurfaceType,
{
AssertPluginThread();
AutoStackHelper guard(this);
NS_ASSERTION(!aWindow.window, "Remote window should be null.");
if (mCurrentAsyncSetWindowTask) {
@ -4261,6 +4277,9 @@ PluginInstanceChild::Destroy()
if (mDestroyed) {
return;
}
if (mStackDepth != 0) {
NS_RUNTIMEABORT("Destroying plugin instance on the stack.");
}
mDestroyed = true;
#if defined(OS_WIN)

Просмотреть файл

@ -660,6 +660,25 @@ private:
// Has this instance been destroyed, either by ActorDestroy or NPP_Destroy?
bool mDestroyed;
// A counter is incremented by AutoStackHelper to indicate that there is an
// active plugin call which should be preventing shutdown.
public:
class AutoStackHelper {
public:
explicit AutoStackHelper(PluginInstanceChild* instance)
: mInstance(instance)
{
++mInstance->mStackDepth;
}
~AutoStackHelper() {
--mInstance->mStackDepth;
}
private:
PluginInstanceChild *const mInstance;
};
private:
int32_t mStackDepth;
};
} // namespace plugins

Просмотреть файл

@ -338,6 +338,8 @@ PluginScriptableObjectChild::ScriptableGetProperty(NPObject* aObject,
NS_ASSERTION(actor, "This shouldn't ever be null!");
NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
PluginInstanceChild::AutoStackHelper guard(actor->mInstance);
Variant result;
bool success;
actor->CallGetParentProperty(FromNPIdentifier(aName),
@ -707,6 +709,7 @@ bool
PluginScriptableObjectChild::AnswerInvalidate()
{
AssertPluginThread();
PluginInstanceChild::AutoStackHelper guard(mInstance);
if (mInvalidated) {
return true;
@ -731,6 +734,7 @@ PluginScriptableObjectChild::AnswerHasMethod(const PluginIdentifier& aId,
bool* aHasMethod)
{
AssertPluginThread();
PluginInstanceChild::AutoStackHelper guard(mInstance);
if (mInvalidated) {
NS_WARNING("Calling AnswerHasMethod with an invalidated object!");
@ -758,6 +762,7 @@ PluginScriptableObjectChild::AnswerInvoke(const PluginIdentifier& aId,
bool* aSuccess)
{
AssertPluginThread();
PluginInstanceChild::AutoStackHelper guard(mInstance);
if (mInvalidated) {
NS_WARNING("Calling AnswerInvoke with an invalidated object!");
@ -828,6 +833,7 @@ PluginScriptableObjectChild::AnswerInvokeDefault(InfallibleTArray<Variant>&& aAr
bool* aSuccess)
{
AssertPluginThread();
PluginInstanceChild::AutoStackHelper guard(mInstance);
if (mInvalidated) {
NS_WARNING("Calling AnswerInvokeDefault with an invalidated object!");
@ -896,6 +902,7 @@ PluginScriptableObjectChild::AnswerHasProperty(const PluginIdentifier& aId,
bool* aHasProperty)
{
AssertPluginThread();
PluginInstanceChild::AutoStackHelper guard(mInstance);
if (mInvalidated) {
NS_WARNING("Calling AnswerHasProperty with an invalidated object!");
@ -924,6 +931,7 @@ PluginScriptableObjectChild::AnswerGetChildProperty(const PluginIdentifier& aId,
bool* aSuccess)
{
AssertPluginThread();
PluginInstanceChild::AutoStackHelper guard(mInstance);
*aHasProperty = *aHasMethod = *aSuccess = false;
*aResult = void_t();
@ -972,6 +980,7 @@ PluginScriptableObjectChild::AnswerSetProperty(const PluginIdentifier& aId,
bool* aSuccess)
{
AssertPluginThread();
PluginInstanceChild::AutoStackHelper guard(mInstance);
if (mInvalidated) {
NS_WARNING("Calling AnswerSetProperty with an invalidated object!");
@ -1010,6 +1019,7 @@ PluginScriptableObjectChild::AnswerRemoveProperty(const PluginIdentifier& aId,
bool* aSuccess)
{
AssertPluginThread();
PluginInstanceChild::AutoStackHelper guard(mInstance);
if (mInvalidated) {
NS_WARNING("Calling AnswerRemoveProperty with an invalidated object!");
@ -1040,6 +1050,7 @@ PluginScriptableObjectChild::AnswerEnumerate(InfallibleTArray<PluginIdentifier>*
bool* aSuccess)
{
AssertPluginThread();
PluginInstanceChild::AutoStackHelper guard(mInstance);
if (mInvalidated) {
NS_WARNING("Calling AnswerEnumerate with an invalidated object!");
@ -1079,6 +1090,7 @@ PluginScriptableObjectChild::AnswerConstruct(InfallibleTArray<Variant>&& aArgs,
bool* aSuccess)
{
AssertPluginThread();
PluginInstanceChild::AutoStackHelper guard(mInstance);
if (mInvalidated) {
NS_WARNING("Calling AnswerConstruct with an invalidated object!");
@ -1165,6 +1177,8 @@ bool
PluginScriptableObjectChild::Evaluate(NPString* aScript,
NPVariant* aResult)
{
PluginInstanceChild::AutoStackHelper guard(mInstance);
nsDependentCString script("");
if (aScript->UTF8Characters && aScript->UTF8Length) {
script.Rebind(aScript->UTF8Characters, aScript->UTF8Length);

Просмотреть файл

@ -611,6 +611,8 @@ Promise::Then(JSContext* aCx,
JS::MutableHandle<JS::Value> aRetval,
ErrorResult& aRv)
{
NS_ASSERT_OWNINGTHREAD(Promise);
// Let's hope this does the right thing with Xrays... Ensure everything is
// just in the caller compartment; that ought to do the trick. In theory we
// should consider aCalleeGlobal, but in practice our only caller is
@ -692,6 +694,8 @@ void
Promise::MaybeResolve(JSContext* aCx,
JS::Handle<JS::Value> aValue)
{
NS_ASSERT_OWNINGTHREAD(Promise);
JS::Rooted<JSObject*> p(aCx, PromiseObj());
if (!JS::ResolvePromise(aCx, p, aValue)) {
// Now what? There's nothing sane to do here.
@ -703,6 +707,8 @@ void
Promise::MaybeReject(JSContext* aCx,
JS::Handle<JS::Value> aValue)
{
NS_ASSERT_OWNINGTHREAD(Promise);
JS::Rooted<JSObject*> p(aCx, PromiseObj());
if (!JS::RejectPromise(aCx, p, aValue)) {
// Now what? There's nothing sane to do here.
@ -772,6 +778,8 @@ CreateNativeHandlerFunction(JSContext* aCx, JS::Handle<JSObject*> aHolder,
void
Promise::AppendNativeHandler(PromiseNativeHandler* aRunnable)
{
NS_ASSERT_OWNINGTHREAD(Promise);
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(mGlobal))) {
// Our API doesn't allow us to return a useful error. Not like this should
@ -891,6 +899,8 @@ void
Promise::MaybeResolve(JSContext* aCx,
JS::Handle<JS::Value> aValue)
{
NS_ASSERT_OWNINGTHREAD(Promise);
MaybeResolveInternal(aCx, aValue);
}
@ -898,6 +908,8 @@ void
Promise::MaybeReject(JSContext* aCx,
JS::Handle<JS::Value> aValue)
{
NS_ASSERT_OWNINGTHREAD(Promise);
MaybeRejectInternal(aCx, aValue);
}
@ -905,12 +917,16 @@ Promise::MaybeReject(JSContext* aCx,
void
Promise::MaybeReject(const RefPtr<MediaStreamError>& aArg) {
NS_ASSERT_OWNINGTHREAD(Promise);
MaybeSomething(aArg, &Promise::MaybeReject);
}
void
Promise::MaybeRejectWithNull()
{
NS_ASSERT_OWNINGTHREAD(Promise);
MaybeSomething(JS::NullHandleValue, &Promise::MaybeReject);
}
@ -1624,6 +1640,8 @@ Promise::Then(JSContext* aCx, JS::Handle<JSObject*> aCalleeGlobal,
AnyCallback* aResolveCallback, AnyCallback* aRejectCallback,
JS::MutableHandle<JS::Value> aRetval, ErrorResult& aRv)
{
NS_ASSERT_OWNINGTHREAD(Promise);
// Implements
// http://www.ecma-international.org/ecma-262/6.0/#sec-promise.prototype.then
@ -1760,6 +1778,8 @@ Promise::Catch(JSContext* aCx, AnyCallback* aRejectCallback,
JS::MutableHandle<JS::Value> aRetval,
ErrorResult& aRv)
{
NS_ASSERT_OWNINGTHREAD(Promise);
// Implements
// http://www.ecma-international.org/ecma-262/6.0/#sec-promise.prototype.catch
@ -2411,6 +2431,8 @@ Promise::PromiseSpecies(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
void
Promise::AppendNativeHandler(PromiseNativeHandler* aRunnable)
{
NS_ASSERT_OWNINGTHREAD(Promise);
RefPtr<PromiseCallback> resolveCb =
new NativePromiseCallback(aRunnable, Resolved);
@ -2478,6 +2500,8 @@ Promise::AppendCallbacks(PromiseCallback* aResolveCallback,
void
Promise::MaybeReportRejected()
{
NS_ASSERT_OWNINGTHREAD(Promise);
if (mState != Rejected || mHadRejectCallback || mResult.isUndefined()) {
return;
}
@ -2531,6 +2555,8 @@ void
Promise::MaybeResolveInternal(JSContext* aCx,
JS::Handle<JS::Value> aValue)
{
NS_ASSERT_OWNINGTHREAD(Promise);
if (mResolvePending) {
return;
}
@ -2542,6 +2568,8 @@ void
Promise::MaybeRejectInternal(JSContext* aCx,
JS::Handle<JS::Value> aValue)
{
NS_ASSERT_OWNINGTHREAD(Promise);
if (mResolvePending) {
return;
}
@ -2552,6 +2580,8 @@ Promise::MaybeRejectInternal(JSContext* aCx,
void
Promise::HandleException(JSContext* aCx)
{
NS_ASSERT_OWNINGTHREAD(Promise);
JS::Rooted<JS::Value> exn(aCx);
if (JS_GetPendingException(aCx, &exn)) {
JS_ClearPendingException(aCx);
@ -2563,6 +2593,8 @@ void
Promise::ResolveInternal(JSContext* aCx,
JS::Handle<JS::Value> aValue)
{
NS_ASSERT_OWNINGTHREAD(Promise);
CycleCollectedJSRuntime* runtime = CycleCollectedJSRuntime::Get();
mResolvePending = true;
@ -2618,6 +2650,8 @@ void
Promise::RejectInternal(JSContext* aCx,
JS::Handle<JS::Value> aValue)
{
NS_ASSERT_OWNINGTHREAD(Promise);
mResolvePending = true;
MaybeSettle(aValue, Rejected);
@ -2629,6 +2663,8 @@ Promise::Settle(JS::Handle<JS::Value> aValue, PromiseState aState)
MOZ_ASSERT(mGlobal,
"We really should have a global here. Except we sometimes don't "
"in the wild for some odd reason");
NS_ASSERT_OWNINGTHREAD(Promise);
if (!mGlobal || mGlobal->IsDying()) {
return;
}
@ -2690,6 +2726,8 @@ void
Promise::MaybeSettle(JS::Handle<JS::Value> aValue,
PromiseState aState)
{
NS_ASSERT_OWNINGTHREAD(Promise);
// Promise.all() or Promise.race() implementations will repeatedly call
// Resolve/RejectInternal rather than using the Maybe... forms. Stop SetState
// from asserting.
@ -2703,6 +2741,8 @@ Promise::MaybeSettle(JS::Handle<JS::Value> aValue,
void
Promise::TriggerPromiseReactions()
{
NS_ASSERT_OWNINGTHREAD(Promise);
CycleCollectedJSRuntime* runtime = CycleCollectedJSRuntime::Get();
nsTArray<RefPtr<PromiseCallback>> callbacks;
@ -2722,6 +2762,8 @@ Promise::TriggerPromiseReactions()
void
Promise::RemoveFeature()
{
NS_ASSERT_OWNINGTHREAD(Promise);
if (mFeature) {
workers::WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(worker);
@ -2743,6 +2785,8 @@ PromiseReportRejectFeature::Notify(workers::Status aStatus)
bool
Promise::CaptureStack(JSContext* aCx, JS::Heap<JSObject*>& aTarget)
{
NS_ASSERT_OWNINGTHREAD(Promise);
JS::Rooted<JSObject*> stack(aCx);
if (!JS::CaptureCurrentStack(aCx, &stack)) {
return false;
@ -2754,6 +2798,8 @@ Promise::CaptureStack(JSContext* aCx, JS::Heap<JSObject*>& aTarget)
void
Promise::GetDependentPromises(nsTArray<RefPtr<Promise>>& aPromises)
{
NS_ASSERT_OWNINGTHREAD(Promise);
// We want to return promises that correspond to then() calls, Promise.all()
// calls, and Promise.race() calls.
//

Просмотреть файл

@ -13,7 +13,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=840388
<script>
// For tests that require setTimeout, set the maximum polling time to 100 x 100ms = 10 seconds.
var MAX_COUNT = 100;
var MAX_COUNT = 50;
var TIMEOUT_INTERVAL = 100;
var counter = 0;

Просмотреть файл

@ -21,7 +21,12 @@
case "insecurePage_navigate_grandchild":
document.getElementById("content").innerHTML =
'<a href="http://example.com/tests/dom/security/test/mixedcontentblocker/file_frameNavigation_innermost.html?insecurePage_navigate_grandchild_response" id="link">Testing\<\/a>';
document.getElementById("link").click();
// If we don't reflow before clicking the link, the test will fail intermittently. The reason is still unknown. We'll track this issue in bug 1259715.
requestAnimationFrame(function() {
setTimeout(function() {
document.getElementById("link").click();
}, 0);
});
break;
case "insecurePage_navigate_grandchild_response":

Просмотреть файл

@ -20,4 +20,4 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' #TIME
[test_bug803225.html]
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT, SSL_REQUIRED # Bug 1141029 Mulet parity with B2G Desktop for TC
[test_frameNavigation.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' || (os == 'mac' || os == 'win') #TIMED_OUT, SSL_REQUIRED, OSX/Win: Bug 1241634
skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT, SSL_REQUIRED

Просмотреть файл

@ -122,7 +122,7 @@ nsXBLResourceLoader::LoadResources(bool* aResult)
// Passing nullptr for pretty much everything -- cause we don't care!
// XXX: initialDocumentURI is nullptr!
RefPtr<imgRequestProxy> req;
nsContentUtils::LoadImage(url, doc, docPrincipal, docURL,
nsContentUtils::LoadImage(url, doc, doc, docPrincipal, docURL,
doc->GetReferrerPolicy(), nullptr,
nsIRequest::LOAD_BACKGROUND, EmptyString(),
getter_AddRefs(req));

Просмотреть файл

@ -301,7 +301,7 @@ nsContextMenuInfo::GetBackgroundImageRequestInternal(nsIDOMNode* aDOMNode,
return il->LoadImage(bgUri, nullptr, nullptr,
doc->GetReferrerPolicy(), principal, nullptr,
nullptr, nullptr, nsIRequest::LOAD_NORMAL,
nullptr, nullptr, nullptr, nsIRequest::LOAD_NORMAL,
nullptr, nsIContentPolicy::TYPE_INTERNAL_IMAGE,
EmptyString(), aRequest);
}

Просмотреть файл

@ -58,7 +58,7 @@ AxisPhysicsMSDModel::Acceleration(const State &aState)
double
AxisPhysicsMSDModel::GetDestination()
AxisPhysicsMSDModel::GetDestination() const
{
return mDestination;
}

Просмотреть файл

@ -27,7 +27,7 @@ public:
/**
* Gets the raw destination of this axis at this moment.
*/
double GetDestination();
double GetDestination() const;
/**
* Sets the raw destination of this axis at this moment.

Просмотреть файл

@ -18,6 +18,7 @@ namespace mozilla {
namespace layers {
class WheelScrollAnimation;
class SmoothScrollAnimation;
class AsyncPanZoomAnimation {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncPanZoomAnimation)
@ -52,6 +53,9 @@ public:
virtual WheelScrollAnimation* AsWheelScrollAnimation() {
return nullptr;
}
virtual SmoothScrollAnimation* AsSmoothScrollAnimation() {
return nullptr;
}
virtual bool WantsRepaints() {
return true;

Просмотреть файл

@ -742,7 +742,7 @@ public:
* frame. Returns true if the smooth scroll should be advanced by one frame,
* or false if the smooth scroll has ended.
*/
bool DoSample(FrameMetrics& aFrameMetrics, const TimeDuration& aDelta) {
bool DoSample(FrameMetrics& aFrameMetrics, const TimeDuration& aDelta) override {
nsPoint oneParentLayerPixel =
CSSPoint::ToAppUnits(ParentLayerPoint(1, 1) / aFrameMetrics.GetZoom());
if (mXAxisModel.IsFinished(oneParentLayerPixel.x) &&
@ -839,6 +839,15 @@ public:
mYAxisModel.SetDestination(static_cast<int32_t>(aNewDestination.y));
}
CSSPoint GetDestination() const {
return CSSPoint::FromAppUnits(
nsPoint(mXAxisModel.GetDestination(), mYAxisModel.GetDestination()));
}
SmoothScrollAnimation* AsSmoothScrollAnimation() override {
return this;
}
private:
AsyncPanZoomController& mApzc;
AxisPhysicsMSDModel mXAxisModel, mYAxisModel;
@ -1827,13 +1836,16 @@ nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEve
mozilla::Telemetry::Accumulate(mozilla::Telemetry::SCROLL_INPUT_METHODS,
(uint32_t) ScrollInputMethodForWheelDeltaType(aEvent.mDeltaType));
// Wheel events from "clicky" mouse wheels trigger scroll snapping to the
// next snap point. Check for this, and adjust the delta to take into
// account the snap point.
bool scrollSnapping = MaybeAdjustDeltaForScrollSnapping(delta, aEvent);
switch (aEvent.mScrollMode) {
case ScrollWheelInput::SCROLLMODE_INSTANT: {
// Wheel events from "clicky" mouse wheels trigger scroll snapping to the
// next snap point. Check for this, and adjust the delta to take into
// account the snap point.
CSSPoint startPosition = mFrameMetrics.GetScrollOffset();
MaybeAdjustDeltaForScrollSnapping(aEvent, delta, startPosition);
ScreenPoint distance = ToScreenCoordinates(
ParentLayerPoint(fabs(delta.x), fabs(delta.y)), aEvent.mLocalOrigin);
@ -1863,33 +1875,43 @@ nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEve
// update it.
ReentrantMonitorAutoEnter lock(mMonitor);
if (scrollSnapping) {
// If we're scroll snapping use a smooth scroll animation to get
// Perform scroll snapping if appropriate.
CSSPoint startPosition = mFrameMetrics.GetScrollOffset();
// If we're already in a wheel scroll or smooth scroll animation,
// the delta is applied to its destination, not to the current
// scroll position. Take this into account when finding a snap point.
if (mState == WHEEL_SCROLL) {
startPosition = mAnimation->AsWheelScrollAnimation()->GetDestination();
} else if (mState == SMOOTH_SCROLL) {
startPosition = mAnimation->AsSmoothScrollAnimation()->GetDestination();
}
if (MaybeAdjustDeltaForScrollSnapping(aEvent, delta, startPosition)) {
// If we're scroll snapping, use a smooth scroll animation to get
// the desired physics. Note that SmoothScrollTo() will re-use an
// existing smooth scroll animation if there is one.
CSSPoint snapPoint = mFrameMetrics.GetScrollOffset() + (delta / mFrameMetrics.GetZoom());
SmoothScrollTo(snapPoint);
} else {
// Otherwise, use a wheel scroll animation, also reusing one if possible.
if (mState != WHEEL_SCROLL) {
CancelAnimation();
SetState(WHEEL_SCROLL);
nsPoint initialPosition = CSSPoint::ToAppUnits(mFrameMetrics.GetScrollOffset());
StartAnimation(new WheelScrollAnimation(
*this, initialPosition, aEvent.mDeltaType));
}
nsPoint deltaInAppUnits =
CSSPoint::ToAppUnits(delta / mFrameMetrics.GetZoom());
// Cast velocity from ParentLayerPoints/ms to CSSPoints/ms then convert to
// appunits/second
nsPoint velocity =
CSSPoint::ToAppUnits(CSSPoint(mX.GetVelocity(), mY.GetVelocity())) * 1000.0f;
WheelScrollAnimation* animation = mAnimation->AsWheelScrollAnimation();
animation->Update(aEvent.mTimeStamp, deltaInAppUnits, nsSize(velocity.x, velocity.y));
SmoothScrollTo(startPosition);
break;
}
// Otherwise, use a wheel scroll animation, also reusing one if possible.
if (mState != WHEEL_SCROLL) {
CancelAnimation();
SetState(WHEEL_SCROLL);
nsPoint initialPosition = CSSPoint::ToAppUnits(mFrameMetrics.GetScrollOffset());
StartAnimation(new WheelScrollAnimation(
*this, initialPosition, aEvent.mDeltaType));
}
nsPoint deltaInAppUnits =
CSSPoint::ToAppUnits(delta / mFrameMetrics.GetZoom());
// Cast velocity from ParentLayerPoints/ms to CSSPoints/ms then convert to
// appunits/second
nsPoint velocity =
CSSPoint::ToAppUnits(CSSPoint(mX.GetVelocity(), mY.GetVelocity())) * 1000.0f;
WheelScrollAnimation* animation = mAnimation->AsWheelScrollAnimation();
animation->Update(aEvent.mTimeStamp, deltaInAppUnits, nsSize(velocity.x, velocity.y));
break;
}
}
@ -4027,7 +4049,9 @@ void AsyncPanZoomController::ScrollSnapToDestination() {
}
bool AsyncPanZoomController::MaybeAdjustDeltaForScrollSnapping(
ParentLayerPoint& aDelta, const ScrollWheelInput& aEvent)
const ScrollWheelInput& aEvent,
ParentLayerPoint& aDelta,
CSSPoint& aStartPosition)
{
// Don't scroll snap for pixel scrolls. This matches the main thread
// behaviour in EventStateManager::DoScrollText().
@ -4036,15 +4060,15 @@ bool AsyncPanZoomController::MaybeAdjustDeltaForScrollSnapping(
}
ReentrantMonitorAutoEnter lock(mMonitor);
CSSPoint scrollOffset = mFrameMetrics.GetScrollOffset();
CSSToParentLayerScale2D zoom = mFrameMetrics.GetZoom();
CSSPoint destination = mFrameMetrics.CalculateScrollRange().ClampPoint(
scrollOffset + (aDelta / zoom));
aStartPosition + (aDelta / zoom));
nsIScrollableFrame::ScrollUnit unit =
ScrollWheelInput::ScrollUnitForDeltaType(aEvent.mDeltaType);
if (Maybe<CSSPoint> snapPoint = FindSnapPointNear(destination, unit)) {
aDelta = (*snapPoint - scrollOffset) * zoom;
aDelta = (*snapPoint - aStartPosition) * zoom;
aStartPosition = *snapPoint;
return true;
}
return false;

Просмотреть файл

@ -1155,9 +1155,13 @@ private:
// If |aEvent| should trigger scroll snapping, adjust |aDelta| to reflect
// the snapping (that is, make it a delta that will take us to the desired
// snap point). Returns true iff. the delta was so adjusted.
bool MaybeAdjustDeltaForScrollSnapping(ParentLayerPoint& aDelta,
const ScrollWheelInput& aEvent);
// snap point). The delta is interpreted as being relative to
// |aStartPosition|, and if a target snap point is found, |aStartPosition|
// is also updated, to the value of the snap point.
// Returns true iff. a target snap point was found.
bool MaybeAdjustDeltaForScrollSnapping(const ScrollWheelInput& aEvent,
ParentLayerPoint& aDelta,
CSSPoint& aStartPosition);
// Snap to a snap position nearby the current scroll position, if appropriate.
void ScrollSnap();

Просмотреть файл

@ -32,6 +32,10 @@ public:
return this;
}
CSSPoint GetDestination() const {
return CSSPoint::FromAppUnits(mFinalDestination);
}
private:
void InitPreferences(TimeStamp aTime);

Просмотреть файл

@ -783,6 +783,8 @@ CompositorBridgeParent::RecvWillClose()
if (mCompositor) {
mCompositor->DetachWidget();
mCompositor->Destroy();
mCompositor = nullptr;
}
return true;

Просмотреть файл

@ -11,7 +11,6 @@
#include "nsHostObjectProtocolHandler.h"
#include "nsString.h"
#include "mozilla/dom/workers/ServiceWorkerManager.h"
#include "nsIDOMDocument.h"
#include "nsIDocument.h"
#include "nsPrintfCString.h"
@ -46,7 +45,7 @@ BlobSerial(ImageURL* aURI)
return Nothing();
}
ImageCacheKey::ImageCacheKey(nsIURI* aURI, nsIDOMDocument* aDocument)
ImageCacheKey::ImageCacheKey(nsIURI* aURI, nsIDocument* aDocument)
: mURI(new ImageURL(aURI))
, mControlledDocument(GetControlledDocumentToken(aDocument))
, mIsChrome(URISchemeIs(mURI, "chrome"))
@ -60,7 +59,7 @@ ImageCacheKey::ImageCacheKey(nsIURI* aURI, nsIDOMDocument* aDocument)
mHash = ComputeHash(mURI, mBlobSerial, mControlledDocument);
}
ImageCacheKey::ImageCacheKey(ImageURL* aURI, nsIDOMDocument* aDocument)
ImageCacheKey::ImageCacheKey(ImageURL* aURI, nsIDocument* aDocument)
: mURI(aURI)
, mControlledDocument(GetControlledDocumentToken(aDocument))
, mIsChrome(URISchemeIs(mURI, "chrome"))
@ -141,7 +140,7 @@ ImageCacheKey::ComputeHash(ImageURL* aURI,
}
/* static */ void*
ImageCacheKey::GetControlledDocumentToken(nsIDOMDocument* aDocument)
ImageCacheKey::GetControlledDocumentToken(nsIDocument* aDocument)
{
// For non-controlled documents, we just return null. For controlled
// documents, we cast the pointer into a void* to avoid dereferencing
@ -149,11 +148,10 @@ ImageCacheKey::GetControlledDocumentToken(nsIDOMDocument* aDocument)
void* pointer = nullptr;
using dom::workers::ServiceWorkerManager;
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDocument);
if (doc && swm) {
if (aDocument && swm) {
ErrorResult rv;
if (swm->IsControlled(doc, rv)) {
pointer = doc;
if (swm->IsControlled(aDocument, rv)) {
pointer = aDocument;
}
}
return pointer;

Просмотреть файл

@ -12,7 +12,7 @@
#include "mozilla/Maybe.h"
class nsIDOMDocument;
class nsIDocument;
class nsIURI;
namespace mozilla {
@ -31,8 +31,8 @@ class ImageURL;
class ImageCacheKey final
{
public:
ImageCacheKey(nsIURI* aURI, nsIDOMDocument* aDocument);
ImageCacheKey(ImageURL* aURI, nsIDOMDocument* aDocument);
ImageCacheKey(nsIURI* aURI, nsIDocument* aDocument);
ImageCacheKey(ImageURL* aURI, nsIDocument* aDocument);
ImageCacheKey(const ImageCacheKey& aOther);
ImageCacheKey(ImageCacheKey&& aOther);
@ -54,7 +54,7 @@ private:
static uint32_t ComputeHash(ImageURL* aURI,
const Maybe<uint64_t>& aBlobSerial,
void* aControlledDocument);
static void* GetControlledDocumentToken(nsIDOMDocument* aDocument);
static void* GetControlledDocumentToken(nsIDocument* aDocument);
RefPtr<ImageURL> mURI;
Maybe<uint64_t> mBlobSerial;

Просмотреть файл

@ -1329,11 +1329,12 @@ imgLoader::ClearCache(bool chrome)
NS_IMETHODIMP
imgLoader::FindEntryProperties(nsIURI* uri,
nsIDOMDocument* doc,
nsIDOMDocument* aDOMDoc,
nsIProperties** _retval)
{
*_retval = nullptr;
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDOMDoc);
ImageCacheKey key(uri, doc);
imgCacheTable& cache = GetCache(key);
@ -1991,6 +1992,8 @@ imgLoader::LoadImageXPCOM(nsIURI* aURI,
}
imgRequestProxy* proxy;
ReferrerPolicy refpol = ReferrerPolicyFromString(aReferrerPolicy);
nsCOMPtr<nsINode> node = do_QueryInterface(aCX);
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aCX);
nsresult rv = LoadImage(aURI,
aInitialDocumentURI,
aReferrerURI,
@ -1998,7 +2001,8 @@ imgLoader::LoadImageXPCOM(nsIURI* aURI,
aLoadingPrincipal,
aLoadGroup,
aObserver,
aCX,
node,
doc,
aLoadFlags,
aCacheKey,
aContentPolicyType,
@ -2016,7 +2020,8 @@ imgLoader::LoadImage(nsIURI* aURI,
nsIPrincipal* aLoadingPrincipal,
nsILoadGroup* aLoadGroup,
imgINotificationObserver* aObserver,
nsISupports* aCX,
nsINode *aContext,
nsIDocument* aLoadingDocument,
nsLoadFlags aLoadFlags,
nsISupports* aCacheKey,
nsContentPolicyType aContentPolicyType,
@ -2095,13 +2100,12 @@ imgLoader::LoadImage(nsIURI* aURI,
// XXX For now ignore aCacheKey. We will need it in the future
// for correctly dealing with image load requests that are a result
// of post data.
nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(aCX);
ImageCacheKey key(aURI, doc);
ImageCacheKey key(aURI, aLoadingDocument);
imgCacheTable& cache = GetCache(key);
if (cache.Get(key, getter_AddRefs(entry)) && entry) {
if (ValidateEntry(entry, aURI, aInitialDocumentURI, aReferrerURI,
aReferrerPolicy, aLoadGroup, aObserver, aCX,
aReferrerPolicy, aLoadGroup, aObserver, aLoadingDocument,
requestFlags, aContentPolicyType, true, _retval,
aLoadingPrincipal, corsmode)) {
request = entry->GetRequest();
@ -2152,7 +2156,7 @@ imgLoader::LoadImage(nsIURI* aURI,
requestFlags,
aContentPolicyType,
aLoadingPrincipal,
aCX);
aContext);
if (NS_FAILED(rv)) {
return NS_ERROR_FAILURE;
}
@ -2170,7 +2174,7 @@ imgLoader::LoadImage(nsIURI* aURI,
nsCOMPtr<nsILoadGroup> channelLoadGroup;
newChannel->GetLoadGroup(getter_AddRefs(channelLoadGroup));
request->Init(aURI, aURI, /* aHadInsecureRedirect = */ false,
channelLoadGroup, newChannel, entry, aCX,
channelLoadGroup, newChannel, entry, aLoadingDocument,
aLoadingPrincipal, corsmode, aReferrerPolicy);
// Add the initiator type for this image load
@ -2242,7 +2246,7 @@ imgLoader::LoadImage(nsIURI* aURI,
// URL maps to the same image on a page) if we load the same image in a
// different tab (see bug 528003), because its load id will get re-set, and
// that'll cause us to validate over the network.
request->SetLoadId(aCX);
request->SetLoadId(aLoadingDocument);
LOG_MSG(gImgLog, "imgLoader::LoadImage", "creating proxy request.");
rv = CreateNewProxyForRequest(request, aLoadGroup, aObserver,
@ -2320,7 +2324,7 @@ imgLoader::LoadImageWithChannel(nsIChannel* channel,
nsCOMPtr<nsIURI> uri;
channel->GetURI(getter_AddRefs(uri));
nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(aCX);
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aCX);
ImageCacheKey key(uri, doc);
nsLoadFlags requestFlags = nsIRequest::LOAD_NORMAL;

Просмотреть файл

@ -277,7 +277,8 @@ public:
nsIPrincipal* aLoadingPrincipal,
nsILoadGroup* aLoadGroup,
imgINotificationObserver* aObserver,
nsISupports* aCX,
nsINode* aContext,
nsIDocument* aLoadingDocument,
nsLoadFlags aLoadFlags,
nsISupports* aCacheKey,
nsContentPolicyType aContentPolicyType,

Просмотреть файл

@ -32,6 +32,7 @@ if os_posix and not CONFIG['MOZ_SYSTEM_LIBEVENT']:
DEFINES['HAVE_CONFIG_H'] = True
LOCAL_INCLUDES += sorted([
'libevent',
'libevent/compat',
'libevent/include',
'libevent/' + libevent_include_suffix,
])

Просмотреть файл

@ -8162,7 +8162,7 @@ EstablishPreconditions(ExclusiveContext* cx, AsmJSParser& parser)
switch (parser.options().asmJSOption) {
case AsmJSOption::Disabled:
return Warn(parser, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by javascript.options.asmjs in about:config");
return Warn(parser, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by 'asmjs' runtime option");
case AsmJSOption::DisabledByDebugger:
return Warn(parser, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by debugger");
case AsmJSOption::Enabled:

Просмотреть файл

@ -935,10 +935,10 @@ js::RegExpMatcher(JSContext* cx, unsigned argc, Value* vp)
*/
bool
js::RegExpMatcherRaw(JSContext* cx, HandleObject regexp, HandleString input,
uint32_t lastIndex, bool sticky,
int32_t lastIndex, bool sticky,
MatchPairs* maybeMatches, MutableHandleValue output)
{
MOZ_ASSERT(lastIndex <= INT32_MAX);
MOZ_ASSERT(lastIndex >= 0);
// The MatchPairs will always be passed in, but RegExp execution was
// successful only if the pairs have actually been filled in.
@ -1016,7 +1016,7 @@ js::RegExpSearcherRaw(JSContext* cx, HandleObject regexp, HandleString input,
int32_t lastIndex, bool sticky,
MatchPairs* maybeMatches, int32_t* result)
{
MOZ_ASSERT(lastIndex <= INT32_MAX);
MOZ_ASSERT(lastIndex >= 0);
// The MatchPairs will always be passed in, but RegExp execution was
// successful only if the pairs have actually been filled in.
@ -1087,9 +1087,9 @@ js::RegExpTester(JSContext* cx, unsigned argc, Value* vp)
*/
bool
js::RegExpTesterRaw(JSContext* cx, HandleObject regexp, HandleString input,
uint32_t lastIndex, bool sticky, int32_t* endIndex)
int32_t lastIndex, bool sticky, int32_t* endIndex)
{
MOZ_ASSERT(lastIndex <= INT32_MAX);
MOZ_ASSERT(lastIndex >= 0);
size_t endIndexTmp = 0;
RegExpRunStatus status = ExecuteRegExp(cx, regexp, input, lastIndex, sticky,

Просмотреть файл

@ -45,7 +45,7 @@ RegExpMatcher(JSContext* cx, unsigned argc, Value* vp);
extern bool
RegExpMatcherRaw(JSContext* cx, HandleObject regexp, HandleString input,
uint32_t lastIndex, bool sticky,
int32_t lastIndex, bool sticky,
MatchPairs* maybeMatches, MutableHandleValue output);
extern bool
@ -61,7 +61,7 @@ RegExpTester(JSContext* cx, unsigned argc, Value* vp);
extern bool
RegExpTesterRaw(JSContext* cx, HandleObject regexp, HandleString input,
uint32_t lastIndex, bool sticky, int32_t* endIndex);
int32_t lastIndex, bool sticky, int32_t* endIndex);
/*
* The following functions are for use by self-hosted code.

Просмотреть файл

@ -1038,7 +1038,7 @@ class GCRuntime
size_t maxMallocBytes;
// An incrementing id used to assign unique ids to cells that require one.
mozilla::Atomic<uint64_t, mozilla::SequentiallyConsistent> nextCellUniqueId_;
mozilla::Atomic<uint64_t, mozilla::ReleaseAcquire> nextCellUniqueId_;
/*
* Number of the committed arenas in all GC chunks including empty chunks.

Просмотреть файл

@ -20,6 +20,6 @@ runOffThreadScript();
var msg = getLastWarning().message;
assertEq(msg === "asm.js type error: Disabled by debugger" ||
msg === "asm.js type error: Disabled by lack of a JIT compiler" ||
msg === "asm.js type error: Disabled by javascript.options.asmjs in about:config" ||
msg === "asm.js type error: Disabled by 'asmjs' runtime option" ||
msg === "asm.js type error: Disabled by lack of compiler support",
true);

Просмотреть файл

@ -1754,7 +1754,7 @@ class OutOfLineRegExpMatcher : public OutOfLineCodeBase<CodeGenerator>
};
typedef bool (*RegExpMatcherRawFn)(JSContext* cx, HandleObject regexp, HandleString input,
uint32_t lastIndex, bool sticky,
int32_t lastIndex, bool sticky,
MatchPairs* pairs, MutableHandleValue output);
static const VMFunction RegExpMatcherRawInfo = FunctionInfo<RegExpMatcherRawFn>(RegExpMatcherRaw);
@ -2073,7 +2073,7 @@ class OutOfLineRegExpTester : public OutOfLineCodeBase<CodeGenerator>
};
typedef bool (*RegExpTesterRawFn)(JSContext* cx, HandleObject regexp, HandleString input,
uint32_t lastIndex, bool sticky, int32_t* result);
int32_t lastIndex, bool sticky, int32_t* result);
static const VMFunction RegExpTesterRawInfo = FunctionInfo<RegExpTesterRawFn>(RegExpTesterRaw);
void

Просмотреть файл

@ -1,13 +1,13 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=370436
https://bugzilla.mozilla.org/show_bug.cgi?id=370436
-->
<head>
<title>Test for Bug 370436</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<title>Test for Bug 370436</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
</head>
<body>
@ -18,66 +18,66 @@ const Ci = Components.interfaces;
function expandStringOffsetToWord(data, offset)
{
if (data == undefined) return "";
if (data == undefined) return "";
var m1 = data.substr(0, offset).match(/\w+$/) || "";
var m2 = data.substr(offset).match(/^\w+/) || "";
return m1 + m2;
var m1 = data.substr(0, offset).match(/\w+$/) || "";
var m2 = data.substr(offset).match(/^\w+/) || "";
return m1 + m2;
}
function onContextMenu(e)
{
var node = e.rangeParent;
var offset = e.rangeOffset;
var utils = window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
is(utils.getClassName(node), "Text", "Shouldn't have SOWs in chrome");
var node = e.rangeParent;
var offset = e.rangeOffset;
var utils = window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
is(utils.getClassName(node), "Text", "Shouldn't have SOWs in chrome");
var word = expandStringOffsetToWord(node.data, offset);
words.push(word);
var word = expandStringOffsetToWord(node.data, offset);
words.push(word);
}
function startTest()
{
ta = document.getElementById('blah');
ta.focus();
ta.selectionStart = ta.selectionEnd = ta.value.length;
ta = document.getElementById('blah');
ta.focus();
ta.selectionStart = ta.selectionEnd = ta.value.length;
// Note: This test, intentionally or by accident, relies on sending button '0'
// with contextMenu, which triggers some key-equiv stuff in
// PresShell::AdjustContextMenuKeyEvent.
var mouseParams = { type: 'contextmenu', button: 0 };
/* Put cursor at start and middle of "sheep" */
synthesizeKey("VK_UP", {})
synthesizeMouse(ta, 0, 0, mouseParams);
synthesizeKey("VK_RIGHT", {})
synthesizeMouse(ta, 0, 0, mouseParams);
synthesizeKey("VK_RIGHT", {})
synthesizeMouse(ta, 0, 0, mouseParams);
/* Put cursor at start and middle of "sheep" */
synthesizeKey("VK_UP", {})
synthesizeMouse(ta, 0, 0, mouseParams);
synthesizeKey("VK_RIGHT", {})
synthesizeMouse(ta, 0, 0, mouseParams);
synthesizeKey("VK_RIGHT", {})
synthesizeMouse(ta, 0, 0, mouseParams);
/* Put cursor at the end of "hello" */
synthesizeKey("VK_UP", {})
synthesizeMouse(ta, 0, 0, mouseParams);
synthesizeKey("VK_RIGHT", {})
synthesizeKey("VK_RIGHT", {})
synthesizeKey("VK_RIGHT", {})
synthesizeMouse(ta, 0, 0, mouseParams);
synthesizeKey("VK_RIGHT", {})
synthesizeMouse(ta, 0, 0, mouseParams);
/* Put cursor at the end of "hello" */
synthesizeKey("VK_UP", {})
synthesizeMouse(ta, 0, 0, mouseParams);
synthesizeKey("VK_RIGHT", {})
synthesizeKey("VK_RIGHT", {})
synthesizeKey("VK_RIGHT", {})
synthesizeMouse(ta, 0, 0, mouseParams);
synthesizeKey("VK_RIGHT", {})
synthesizeMouse(ta, 0, 0, mouseParams);
/* Put cursor on "welcome" */
synthesizeKey("VK_UP", {})
synthesizeMouse(ta, 0, 0, mouseParams);
/* Put cursor on "welcome" */
synthesizeKey("VK_UP", {})
synthesizeMouse(ta, 0, 0, mouseParams);
is(words.pop(), "welcome", "Word 1 selected correctly");
is(words.pop(), "world" , "Word 2 selected correctly");
is(words.pop(), "hello" , "Word 3 selected correctly");
is(words.pop(), "hello" , "Word 4 selected correctly");
is(words.pop(), "sheep" , "Word 5 selected correctly");
is(words.pop(), "sheep" , "Word 6 selected correctly");
is(words.pop(), "sheep" , "Word 7 selected correctly");
is(words.pop(), "welcome", "Word 1 selected correctly");
is(words.pop(), "world" , "Word 2 selected correctly");
is(words.pop(), "hello" , "Word 3 selected correctly");
is(words.pop(), "hello" , "Word 4 selected correctly");
is(words.pop(), "sheep" , "Word 5 selected correctly");
is(words.pop(), "sheep" , "Word 6 selected correctly");
is(words.pop(), "sheep" , "Word 7 selected correctly");
SimpleTest.finish();
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish()
@ -94,4 +94,3 @@ sheep
</textarea>
</body>
</html>

Просмотреть файл

@ -2172,6 +2172,7 @@ nsImageFrame::LoadIcon(const nsAString& aSpec,
nullptr, /* principal (not relevant for icons) */
loadGroup,
gIconLoad,
nullptr, /* No context */
nullptr, /* Not associated with any particular document */
loadFlags,
nullptr,

Просмотреть файл

@ -263,7 +263,8 @@ ImageLoader::LoadImage(nsIURI* aURI, nsIPrincipal* aOriginPrincipal,
}
RefPtr<imgRequestProxy> request;
nsContentUtils::LoadImage(aURI, mDocument, aOriginPrincipal, aReferrer,
nsContentUtils::LoadImage(aURI, mDocument, mDocument,
aOriginPrincipal, aReferrer,
mDocument->GetReferrerPolicy(),
nullptr, nsIRequest::LOAD_NORMAL,
NS_LITERAL_STRING("css"),

Просмотреть файл

@ -2862,8 +2862,14 @@ StyleAnimationValue::UncomputeValue(nsCSSProperty aProperty,
case eUnit_Shadow:
case eUnit_Filter:
case eUnit_BackgroundPosition:
aSpecifiedValue.
SetDependentListValue(aComputedValue.GetCSSValueListValue());
{
nsCSSValueList* computedList = aComputedValue.GetCSSValueListValue();
if (computedList) {
aSpecifiedValue.SetDependentListValue(computedList);
} else {
aSpecifiedValue.SetNoneValue();
}
}
break;
case eUnit_Transform:
aSpecifiedValue.
@ -2879,6 +2885,41 @@ StyleAnimationValue::UncomputeValue(nsCSSProperty aProperty,
return true;
}
bool
StyleAnimationValue::UncomputeValue(nsCSSProperty aProperty,
StyleAnimationValue&& aComputedValue,
nsCSSValue& aSpecifiedValue)
{
Unit unit = aComputedValue.GetUnit();
switch (unit) {
case eUnit_Dasharray:
case eUnit_Shadow:
case eUnit_Filter:
case eUnit_BackgroundPosition:
{
UniquePtr<nsCSSValueList> computedList =
aComputedValue.TakeCSSValueListValue();
if (computedList) {
aSpecifiedValue.AdoptListValue(computedList.release());
} else {
aSpecifiedValue.SetNoneValue();
}
}
break;
case eUnit_CSSValuePairList:
{
UniquePtr<nsCSSValuePairList> computedList =
aComputedValue.TakeCSSValuePairListValue();
MOZ_ASSERT(computedList, "Pair list should never be null");
aSpecifiedValue.AdoptPairListValue(computedList.release());
}
break;
default:
return UncomputeValue(aProperty, aComputedValue, aSpecifiedValue);
}
return true;
}
bool
StyleAnimationValue::UncomputeValue(nsCSSProperty aProperty,
const StyleAnimationValue& aComputedValue,

Просмотреть файл

@ -9,6 +9,7 @@
#define mozilla_StyleAnimationValue_h_
#include "mozilla/gfx/MatrixFwd.h"
#include "mozilla/UniquePtr.h"
#include "nsStringFwd.h"
#include "nsStringBuffer.h"
#include "nsCoord.h"
@ -197,10 +198,14 @@ public:
/**
* Creates a specified value for the given computed value.
*
* The first overload fills in an nsCSSValue object; the second
* produces a string. The nsCSSValue result may depend on objects
* owned by the |aComputedValue| object, so users of that variant
* The first two overloads fill in an nsCSSValue object; the third
* produces a string. For the overload that takes a const
* StyleAnimationValue& reference, the nsCSSValue result may depend on
* objects owned by the |aComputedValue| object, so users of that variant
* must keep |aComputedValue| alive longer than |aSpecifiedValue|.
* The overload that takes an rvalue StyleAnimationValue reference
* transfers ownership for some resources such that the |aComputedValue|
* does not depend on the lifetime of |aSpecifiedValue|.
*
* @param aProperty The property whose value we're uncomputing.
* @param aComputedValue The computed value to be converted.
@ -210,6 +215,9 @@ public:
static bool UncomputeValue(nsCSSProperty aProperty,
const StyleAnimationValue& aComputedValue,
nsCSSValue& aSpecifiedValue);
static bool UncomputeValue(nsCSSProperty aProperty,
StyleAnimationValue&& aComputedValue,
nsCSSValue& aSpecifiedValue);
static bool UncomputeValue(nsCSSProperty aProperty,
const StyleAnimationValue& aComputedValue,
nsAString& aSpecifiedValue);
@ -366,6 +374,19 @@ public:
/// @return the scale for this value, calculated with reference to @aForFrame.
gfxSize GetScaleValue(const nsIFrame* aForFrame) const;
UniquePtr<nsCSSValueList> TakeCSSValueListValue() {
nsCSSValueList* list = GetCSSValueListValue();
mValue.mCSSValueList = nullptr;
mUnit = eUnit_Null;
return UniquePtr<nsCSSValueList>(list);
}
UniquePtr<nsCSSValuePairList> TakeCSSValuePairListValue() {
nsCSSValuePairList* list = GetCSSValuePairListValue();
mValue.mCSSValuePairList = nullptr;
mUnit = eUnit_Null;
return UniquePtr<nsCSSValuePairList>(list);
}
explicit StyleAnimationValue(Unit aUnit = eUnit_Null) : mUnit(aUnit) {
NS_ASSERTION(aUnit == eUnit_Null || aUnit == eUnit_Normal ||
aUnit == eUnit_Auto || aUnit == eUnit_None,

Просмотреть файл

@ -23,6 +23,7 @@
#include "nsIFrame.h"
#include "nsIDocument.h"
#include "nsDOMMutationObserver.h"
#include <algorithm> // std::stable_sort
#include <math.h>
using namespace mozilla;
@ -332,8 +333,9 @@ static void
UpdateOldAnimationPropertiesWithNew(
CSSAnimation& aOld,
TimingParams& aNewTiming,
InfallibleTArray<AnimationProperty>& aNewProperties,
bool aNewIsStylePaused)
nsTArray<Keyframe>& aNewFrames,
bool aNewIsStylePaused,
nsStyleContext* aStyleContext)
{
bool animationChanged = false;
@ -344,8 +346,7 @@ UpdateOldAnimationPropertiesWithNew(
animationChanged =
oldEffect->SpecifiedTiming() != aNewTiming;
oldEffect->SetSpecifiedTiming(aNewTiming);
animationChanged |=
oldEffect->UpdateProperties(aNewProperties);
oldEffect->SetFrames(Move(aNewFrames), aStyleContext);
}
// Handle changes in play state. If the animation is idle, however,
@ -479,21 +480,6 @@ nsAnimationManager::StopAnimationsForElement(
collection->Destroy();
}
struct KeyframeData {
float mKey;
uint32_t mIndex; // store original order since sort algorithm is not stable
nsCSSKeyframeRule *mRule;
};
struct KeyframeDataComparator {
bool Equals(const KeyframeData& A, const KeyframeData& B) const {
return A.mKey == B.mKey && A.mIndex == B.mIndex;
}
bool LessThan(const KeyframeData& A, const KeyframeData& B) const {
return A.mKey < B.mKey || (A.mKey == B.mKey && A.mIndex < B.mIndex);
}
};
class ResolvedStyleCache {
public:
ResolvedStyleCache() : mCache() {}
@ -562,17 +548,31 @@ public:
const nsCSSKeyframesRule* aRule);
private:
void BuildAnimationProperties(nsPresContext* aPresContext,
const StyleAnimation& aSrc,
const nsCSSKeyframesRule* aRule,
InfallibleTArray<AnimationProperty>& aResult);
bool BuildSegment(InfallibleTArray<mozilla::AnimationPropertySegment>&
aSegments,
nsCSSProperty aProperty,
const mozilla::StyleAnimation& aAnimation,
float aFromKey, nsStyleContext* aFromContext,
mozilla::css::Declaration* aFromDeclaration,
float aToKey, nsStyleContext* aToContext);
nsTArray<Keyframe> BuildAnimationFrames(nsPresContext* aPresContext,
const StyleAnimation& aSrc,
const nsCSSKeyframesRule* aRule);
Maybe<ComputedTimingFunction> GetKeyframeTimingFunction(
nsPresContext* aPresContext,
nsCSSKeyframeRule* aKeyframeRule,
const Maybe<ComputedTimingFunction>& aInheritedTimingFunction);
nsTArray<PropertyValuePair> GetKeyframePropertyValues(
nsPresContext* aPresContext,
nsCSSKeyframeRule* aKeyframeRule,
nsCSSCompressedDataBlock* aDataBlock,
nsCSSPropertySet& aAnimatedProperties);
void FillInMissingKeyframeValues(
nsPresContext* aPresContext,
nsCSSPropertySet aAnimatedProperties,
nsCSSPropertySet aPropertiesSetAtStart,
nsCSSPropertySet aPropertiesSetAtEnd,
const Maybe<ComputedTimingFunction>& aInheritedTimingFunction,
nsTArray<Keyframe>& aKeyframes);
void AppendProperty(nsPresContext* aPresContext,
nsCSSProperty aProperty,
nsTArray<PropertyValuePair>& aPropertyValues);
void GetComputedValue(nsPresContext* aPresContext,
nsCSSProperty aProperty,
nsCSSValue& aResult);
static TimingParams TimingParamsFrom(
const StyleAnimation& aStyleAnimation)
@ -599,6 +599,9 @@ private:
nsAnimationManager::CSSAnimationCollection* mCollection;
};
static Maybe<ComputedTimingFunction>
ConvertTimingFunction(const nsTimingFunction& aTimingFunction);
already_AddRefed<CSSAnimation>
CSSAnimationBuilder::Build(nsPresContext* aPresContext,
const StyleAnimation& aSrc,
@ -609,8 +612,8 @@ CSSAnimationBuilder::Build(nsPresContext* aPresContext,
TimingParams timing = TimingParamsFrom(aSrc);
InfallibleTArray<AnimationProperty> animationProperties;
BuildAnimationProperties(aPresContext, aSrc, aRule, animationProperties);
nsTArray<Keyframe> keyframes =
BuildAnimationFrames(aPresContext, aSrc, aRule);
bool isStylePaused =
aSrc.GetPlayState() == NS_STYLE_ANIMATION_PLAY_STATE_PAUSED;
@ -631,8 +634,9 @@ CSSAnimationBuilder::Build(nsPresContext* aPresContext,
// In order to honor what the spec said, we'd copy more data over.
UpdateOldAnimationPropertiesWithNew(*oldAnim,
timing,
animationProperties,
isStylePaused);
keyframes,
isStylePaused,
mStyleContext);
return oldAnim.forget();
}
@ -640,7 +644,7 @@ CSSAnimationBuilder::Build(nsPresContext* aPresContext,
new KeyframeEffectReadOnly(aPresContext->Document(), mTarget,
mStyleContext->GetPseudoType(), timing);
effect->Properties() = Move(animationProperties);
effect->SetFrames(Move(keyframes), mStyleContext);
RefPtr<CSSAnimation> animation =
new CSSAnimation(aPresContext->Document()->GetScopeObject(),
@ -667,214 +671,388 @@ CSSAnimationBuilder::Build(nsPresContext* aPresContext,
return animation.forget();
}
void
CSSAnimationBuilder::BuildAnimationProperties(
nsPresContext* aPresContext,
const StyleAnimation& aSrc,
const nsCSSKeyframesRule* aRule,
InfallibleTArray<AnimationProperty>& aResult)
nsTArray<Keyframe>
CSSAnimationBuilder::BuildAnimationFrames(nsPresContext* aPresContext,
const StyleAnimation& aSrc,
const nsCSSKeyframesRule* aRule)
{
// While current drafts of css3-animations say that later keyframes
// with the same key entirely replace earlier ones (no cascading),
// this is a bad idea and contradictory to the rest of CSS. So
// we're going to keep all the keyframes for each key and then do
// the replacement on a per-property basis rather than a per-rule
// basis, just like everything else in CSS.
// Ideally we'd like to build up a set of Keyframe objects that more-or-less
// reflects the keyframes as-specified in the @keyframes rule(s). However,
// that proves to be difficult because the way CSS declarations are processed
// differs from how we are able to represent keyframes as JavaScript objects.
//
// For example, in CSS the following rules differ in meaning:
//
// { margin: 10px; margin-left: 20px }
// { margin-left: 20px; margin: 10px }
//
// However, in JavaScript, since the order in which object properties are
// enumerated is not defined, Web Animations defines that shorthands are
// applied first and longhands are layered on top regardless of the order
// in which they are specified. As a result, we would need to represent the
// above as:
//
// { margin: '10px', marginLeft: '20px' }
// { margin: '10px' }
//
// Similarly, redundant declarations are permitted by CSS but not in
// JavaScript. As such,
//
// { margin-left: 20px; margin-left: 30px }
//
// would be represented as:
//
// { marginLeft: '30px' }
//
// In effect, we would need to manually apply the rules for CSS declaration
// processing in order to maintain the closest possibly mapping
// to the source and even then, the mapping would be unclear in some
// cases. Furthermore, @keyframes are defined to cascade so any
// correspondance to the source would be further obscured once we represent
// the result as a single array.
//
// Until there is specified behavior for preserving shorthands we simply
// expand all shorthands, apply regular declaration processing, then go and
// pick up the last value specified for each property at each offset.
AutoTArray<KeyframeData, 16> sortedKeyframes;
// FIXME: There is a pending spec change to make multiple @keyframes
// rules with the same name cascade but we don't support that yet.
for (uint32_t ruleIdx = 0, ruleEnd = aRule->StyleRuleCount();
Maybe<ComputedTimingFunction> inheritedTimingFunction =
ConvertTimingFunction(aSrc.GetTimingFunction());
// First, make up Keyframe objects for each rule
nsTArray<Keyframe> keyframes;
nsCSSPropertySet animatedProperties;
for (auto ruleIdx = 0, ruleEnd = aRule->StyleRuleCount();
ruleIdx != ruleEnd; ++ruleIdx) {
css::Rule* cssRule = aRule->GetStyleRuleAt(ruleIdx);
MOZ_ASSERT(cssRule, "must have rule");
MOZ_ASSERT(cssRule->GetType() == css::Rule::KEYFRAME_RULE,
"must be keyframe rule");
nsCSSKeyframeRule *kfRule = static_cast<nsCSSKeyframeRule*>(cssRule);
"must be keyframe rule");
nsCSSKeyframeRule* keyframeRule = static_cast<nsCSSKeyframeRule*>(cssRule);
nsCSSCompressedDataBlock* dataBlock =
keyframeRule->Declaration()->GetNormalBlock();
const nsTArray<float> &keys = kfRule->GetKeys();
for (uint32_t keyIdx = 0, keyEnd = keys.Length();
keyIdx != keyEnd; ++keyIdx) {
float key = keys[keyIdx];
// FIXME (spec): The spec doesn't say what to do with
// out-of-range keyframes. We'll ignore them.
if (0.0f <= key && key <= 1.0f) {
KeyframeData *data = sortedKeyframes.AppendElement();
data->mKey = key;
data->mIndex = ruleIdx;
data->mRule = kfRule;
const nsTArray<float>& keys = keyframeRule->GetKeys();
for (float key : keys) {
if (key < 0.0f || key > 1.0f) {
continue;
}
Keyframe keyframe;
keyframe.mOffset.emplace(key);
keyframe.mTimingFunction =
GetKeyframeTimingFunction(aPresContext, keyframeRule,
inheritedTimingFunction);
keyframe.mPropertyValues =
GetKeyframePropertyValues(aPresContext, keyframeRule, dataBlock,
animatedProperties);
keyframes.AppendElement(Move(keyframe));
}
}
sortedKeyframes.Sort(KeyframeDataComparator());
// Next, stable sort by offset
std::stable_sort(keyframes.begin(), keyframes.end(),
[](const Keyframe& a, const Keyframe& b)
{
return a.mOffset < b.mOffset;
});
if (sortedKeyframes.Length() == 0) {
// no segments
return;
}
// Then walk backwards through the keyframes and drop overridden properties.
nsCSSPropertySet propertiesSetAtCurrentOffset;
nsCSSPropertySet propertiesSetAtStart;
nsCSSPropertySet propertiesSetAtEnd;
double currentOffset = -1.0;
for (size_t keyframeIdx = keyframes.Length();
keyframeIdx > 0;
--keyframeIdx) {
Keyframe& keyframe = keyframes[keyframeIdx - 1];
MOZ_ASSERT(keyframe.mOffset, "Should have filled in the offset");
// Record the properties that are present in any keyframe rules we
// are using.
nsCSSPropertySet properties;
if (keyframe.mOffset.value() != currentOffset) {
propertiesSetAtCurrentOffset.Empty();
currentOffset = keyframe.mOffset.value();
}
for (uint32_t kfIdx = 0, kfEnd = sortedKeyframes.Length();
kfIdx != kfEnd; ++kfIdx) {
css::Declaration *decl = sortedKeyframes[kfIdx].mRule->Declaration();
for (uint32_t propIdx = 0, propEnd = decl->Count();
propIdx != propEnd; ++propIdx) {
nsCSSProperty prop = decl->GetPropertyAt(propIdx);
if (prop != eCSSPropertyExtra_variable) {
// CSS Variables are not animatable
properties.AddProperty(prop);
// Get the set of properties from this keyframe that have not
// already been set at this offset.
nsTArray<PropertyValuePair> uniquePropertyValues;
uniquePropertyValues.SetCapacity(keyframe.mPropertyValues.Length());
for (const PropertyValuePair& pair : keyframe.mPropertyValues) {
if (!propertiesSetAtCurrentOffset.HasProperty(pair.mProperty)) {
uniquePropertyValues.AppendElement(pair);
propertiesSetAtCurrentOffset.AddProperty(pair.mProperty);
if (currentOffset == 0.0) {
propertiesSetAtStart.AddProperty(pair.mProperty);
} else if (currentOffset == 1.0) {
propertiesSetAtEnd.AddProperty(pair.mProperty);
}
}
}
// If we have a keyframe at the same offset with the same timing
// function we should merge our (unique) values into it.
// Otherwise, we should update the existing keyframe with only the
// unique properties.
//
// Bug 1216843: We should also match composite modes here.
Keyframe* existingKeyframe = nullptr;
// Don't bother searching for an existing keyframe if we don't
// have anything to contribute to it.
if (!uniquePropertyValues.IsEmpty()) {
for (size_t i = keyframeIdx; i < keyframes.Length(); i++) {
Keyframe& kf = keyframes[i];
if (kf.mOffset.value() != currentOffset) {
break;
}
if (kf.mTimingFunction == keyframe.mTimingFunction) {
existingKeyframe = &kf;
break;
}
}
}
if (existingKeyframe) {
existingKeyframe->
mPropertyValues.AppendElements(Move(uniquePropertyValues));
keyframe.mPropertyValues.Clear();
} else {
keyframe.mPropertyValues.SwapElements(uniquePropertyValues);
}
// Check for a now-empty keyframe
if (keyframe.mPropertyValues.IsEmpty()) {
keyframes.RemoveElementAt(keyframeIdx - 1);
// existingKeyframe might dangle now
}
}
// Finally, we need to look for any animated properties that have an
// implicit 'to' or 'from' value and fill in the appropriate keyframe
// with the current computed style.
FillInMissingKeyframeValues(aPresContext, animatedProperties,
propertiesSetAtStart, propertiesSetAtEnd,
inheritedTimingFunction, keyframes);
return keyframes;
}
Maybe<ComputedTimingFunction>
CSSAnimationBuilder::GetKeyframeTimingFunction(
nsPresContext* aPresContext,
nsCSSKeyframeRule* aKeyframeRule,
const Maybe<ComputedTimingFunction>& aInheritedTimingFunction)
{
Maybe<ComputedTimingFunction> result;
if (aKeyframeRule->Declaration() &&
aKeyframeRule->Declaration()->HasProperty(
eCSSProperty_animation_timing_function)) {
RefPtr<nsStyleContext> keyframeRuleContext =
mResolvedStyles.Get(aPresContext, mStyleContext,
aKeyframeRule->Declaration());
const nsTimingFunction& tf = keyframeRuleContext->StyleDisplay()->
mAnimations[0].GetTimingFunction();
result = ConvertTimingFunction(tf);
} else {
result = aInheritedTimingFunction;
}
return result;
}
static Maybe<ComputedTimingFunction>
ConvertTimingFunction(const nsTimingFunction& aTimingFunction)
{
Maybe<ComputedTimingFunction> result;
if (aTimingFunction.mType != nsTimingFunction::Type::Linear) {
result.emplace();
result->Init(aTimingFunction);
}
return result;
}
nsTArray<PropertyValuePair>
CSSAnimationBuilder::GetKeyframePropertyValues(
nsPresContext* aPresContext,
nsCSSKeyframeRule* aKeyframeRule,
nsCSSCompressedDataBlock* aDataBlock,
nsCSSPropertySet& aAnimatedProperties)
{
nsTArray<PropertyValuePair> result;
for (nsCSSProperty prop = nsCSSProperty(0);
prop < eCSSProperty_COUNT_no_shorthands;
prop = nsCSSProperty(prop + 1)) {
if (!properties.HasProperty(prop) ||
nsCSSProps::kAnimTypeTable[prop] == eStyleAnimType_None) {
if (nsCSSProps::kAnimTypeTable[prop] == eStyleAnimType_None ||
!aKeyframeRule->Declaration()->HasNonImportantValueFor(prop)) {
continue;
}
// Build a list of the keyframes to use for this property. This
// means we need every keyframe with the property in it, except
// for those keyframes where a later keyframe with the *same key*
// also has the property.
AutoTArray<uint32_t, 16> keyframesWithProperty;
float lastKey = 100.0f; // an invalid key
for (uint32_t kfIdx = 0, kfEnd = sortedKeyframes.Length();
kfIdx != kfEnd; ++kfIdx) {
KeyframeData &kf = sortedKeyframes[kfIdx];
if (!kf.mRule->Declaration()->HasProperty(prop)) {
continue;
}
if (kf.mKey == lastKey) {
// Replace previous occurrence of same key.
keyframesWithProperty[keyframesWithProperty.Length() - 1] = kfIdx;
} else {
keyframesWithProperty.AppendElement(kfIdx);
}
lastKey = kf.mKey;
PropertyValuePair pair;
pair.mProperty = prop;
pair.mValue = *aDataBlock->ValueFor(prop);
MOZ_ASSERT(pair.mValue.GetUnit() != eCSSUnit_Null,
"Not expecting to read invalid properties");
result.AppendElement(Move(pair));
aAnimatedProperties.AddProperty(prop);
}
return result;
}
// Utility function to walk through |aIter| to find the Keyframe with
// matching offset and timing function but stopping as soon as the offset
// differs from |aOffset| (i.e. it assumes a sorted iterator).
//
// If a matching Keyframe is found,
// Returns true and sets |aIndex| to the index of the matching Keyframe
// within |aIter|.
//
// If no matching Keyframe is found,
// Returns false and sets |aIndex| to the index in the iterator of the
// first Keyframe with an offset differing to |aOffset| or, if the end
// of the iterator is reached, sets |aIndex| to the index after the last
// Keyframe.
template <class IterType>
static bool
FindMatchingKeyframe(
IterType&& aIter,
double aOffset,
const Maybe<ComputedTimingFunction>& aTimingFunctionToMatch,
size_t& aIndex)
{
aIndex = 0;
for (Keyframe& keyframe : aIter) {
if (keyframe.mOffset.value() != aOffset) {
break;
}
if (keyframe.mTimingFunction == aTimingFunctionToMatch) {
return true;
}
++aIndex;
}
return false;
}
void
CSSAnimationBuilder::FillInMissingKeyframeValues(
nsPresContext* aPresContext,
nsCSSPropertySet aAnimatedProperties,
nsCSSPropertySet aPropertiesSetAtStart,
nsCSSPropertySet aPropertiesSetAtEnd,
const Maybe<ComputedTimingFunction>& aInheritedTimingFunction,
nsTArray<Keyframe>& aKeyframes)
{
static const size_t kNotSet = static_cast<size_t>(-1);
// Find/create the keyframe to add start values to
size_t startKeyframeIndex = kNotSet;
if (!aAnimatedProperties.Equals(aPropertiesSetAtStart) &&
!FindMatchingKeyframe(aKeyframes, 0.0, aInheritedTimingFunction,
startKeyframeIndex)) {
Keyframe newKeyframe;
newKeyframe.mOffset.emplace(0.0);
newKeyframe.mTimingFunction = aInheritedTimingFunction;
aKeyframes.InsertElementAt(startKeyframeIndex, Move(newKeyframe));
}
// Find/create the keyframe to add end values to
size_t endKeyframeIndex = kNotSet;
if (!aAnimatedProperties.Equals(aPropertiesSetAtEnd)) {
if (!FindMatchingKeyframe(Reversed(aKeyframes), 1.0,
aInheritedTimingFunction, endKeyframeIndex)) {
Keyframe newKeyframe;
newKeyframe.mOffset.emplace(1.0);
newKeyframe.mTimingFunction = aInheritedTimingFunction;
aKeyframes.AppendElement(Move(newKeyframe));
endKeyframeIndex = aKeyframes.Length() - 1;
} else {
// endKeyframeIndex is currently a count from the end of the array
// so we need to reverse it.
endKeyframeIndex = aKeyframes.Length() - 1 - endKeyframeIndex;
}
}
if (startKeyframeIndex == kNotSet && endKeyframeIndex == kNotSet) {
return;
}
// Now that we have finished manipulating aKeyframes, it is safe to
// take pointers to its elements.
Keyframe* startKeyframe = startKeyframeIndex == kNotSet
? nullptr : &aKeyframes[startKeyframeIndex];
Keyframe* endKeyframe = endKeyframeIndex == kNotSet
? nullptr : &aKeyframes[endKeyframeIndex];
// Iterate through all properties and fill-in missing values
for (nsCSSProperty prop = nsCSSProperty(0);
prop < eCSSProperty_COUNT_no_shorthands;
prop = nsCSSProperty(prop + 1)) {
if (!aAnimatedProperties.HasProperty(prop)) {
continue;
}
AnimationProperty &propData = *aResult.AppendElement();
propData.mProperty = prop;
KeyframeData *fromKeyframe = nullptr;
RefPtr<nsStyleContext> fromContext;
bool interpolated = true;
for (uint32_t wpIdx = 0, wpEnd = keyframesWithProperty.Length();
wpIdx != wpEnd; ++wpIdx) {
uint32_t kfIdx = keyframesWithProperty[wpIdx];
KeyframeData &toKeyframe = sortedKeyframes[kfIdx];
RefPtr<nsStyleContext> toContext =
mResolvedStyles.Get(aPresContext, mStyleContext,
toKeyframe.mRule->Declaration());
if (fromKeyframe) {
interpolated = interpolated &&
BuildSegment(propData.mSegments, prop, aSrc,
fromKeyframe->mKey, fromContext,
fromKeyframe->mRule->Declaration(),
toKeyframe.mKey, toContext);
} else {
if (toKeyframe.mKey != 0.0f) {
// There's no data for this property at 0%, so use the
// cascaded value above us.
if (!mStyleWithoutAnimation) {
MOZ_ASSERT(aPresContext->StyleSet()->IsGecko(),
"ServoStyleSet should not use nsAnimationManager for "
"animations");
mStyleWithoutAnimation = aPresContext->StyleSet()->AsGecko()->
ResolveStyleWithoutAnimation(mTarget, mStyleContext,
eRestyle_AllHintsWithAnimations);
}
interpolated = interpolated &&
BuildSegment(propData.mSegments, prop, aSrc,
0.0f, mStyleWithoutAnimation, nullptr,
toKeyframe.mKey, toContext);
}
}
fromContext = toContext;
fromKeyframe = &toKeyframe;
if (startKeyframe && !aPropertiesSetAtStart.HasProperty(prop)) {
AppendProperty(aPresContext, prop, startKeyframe->mPropertyValues);
}
if (fromKeyframe->mKey != 1.0f) {
// There's no data for this property at 100%, so use the
// cascaded value above us.
if (!mStyleWithoutAnimation) {
MOZ_ASSERT(aPresContext->StyleSet()->IsGecko(),
"ServoStyleSet should not use nsAnimationManager for "
"animations");
mStyleWithoutAnimation = aPresContext->StyleSet()->AsGecko()->
ResolveStyleWithoutAnimation(mTarget, mStyleContext,
eRestyle_AllHintsWithAnimations);
}
interpolated = interpolated &&
BuildSegment(propData.mSegments, prop, aSrc,
fromKeyframe->mKey, fromContext,
fromKeyframe->mRule->Declaration(),
1.0f, mStyleWithoutAnimation);
}
// If we failed to build any segments due to inability to
// interpolate, remove the property from the animation. (It's not
// clear if this is the right thing to do -- we could run some of
// the segments, but it's really not clear whether we should skip
// values (which?) or skip segments, so best to skip the whole
// thing for now.)
if (!interpolated) {
aResult.RemoveElementAt(aResult.Length() - 1);
if (endKeyframe && !aPropertiesSetAtEnd.HasProperty(prop)) {
AppendProperty(aPresContext, prop, endKeyframe->mPropertyValues);
}
}
}
bool
CSSAnimationBuilder::BuildSegment(InfallibleTArray<AnimationPropertySegment>&
aSegments,
nsCSSProperty aProperty,
const StyleAnimation& aAnimation,
float aFromKey, nsStyleContext* aFromContext,
mozilla::css::Declaration* aFromDeclaration,
float aToKey, nsStyleContext* aToContext)
void
CSSAnimationBuilder::AppendProperty(
nsPresContext* aPresContext,
nsCSSProperty aProperty,
nsTArray<PropertyValuePair>& aPropertyValues)
{
StyleAnimationValue fromValue, toValue, dummyValue;
if (!CommonAnimationManager<CSSAnimation>::ExtractComputedValueForTransition(
aProperty, aFromContext, fromValue) ||
!CommonAnimationManager<CSSAnimation>::ExtractComputedValueForTransition(
aProperty, aToContext, toValue) ||
// Check that we can interpolate between these values
// (If this is ever a performance problem, we could add a
// CanInterpolate method, but it seems fine for now.)
!StyleAnimationValue::Interpolate(aProperty, fromValue, toValue,
0.5, dummyValue)) {
return false;
PropertyValuePair propertyValue;
propertyValue.mProperty = aProperty;
GetComputedValue(aPresContext, aProperty, propertyValue.mValue);
aPropertyValues.AppendElement(Move(propertyValue));
}
void
CSSAnimationBuilder::GetComputedValue(nsPresContext* aPresContext,
nsCSSProperty aProperty,
nsCSSValue& aResult)
{
StyleAnimationValue computedValue;
if (!mStyleWithoutAnimation) {
MOZ_ASSERT(aPresContext->StyleSet()->IsGecko(),
"ServoStyleSet should not use nsAnimationManager for "
"animations");
mStyleWithoutAnimation = aPresContext->StyleSet()->AsGecko()->
ResolveStyleWithoutAnimation(mTarget, mStyleContext,
eRestyle_AllHintsWithAnimations);
}
AnimationPropertySegment &segment = *aSegments.AppendElement();
segment.mFromValue = fromValue;
segment.mToValue = toValue;
segment.mFromKey = aFromKey;
segment.mToKey = aToKey;
const nsTimingFunction *tf;
if (aFromDeclaration &&
aFromDeclaration->HasProperty(eCSSProperty_animation_timing_function)) {
tf = &aFromContext->StyleDisplay()->mAnimations[0].GetTimingFunction();
} else {
tf = &aAnimation.GetTimingFunction();
}
if (tf->mType != nsTimingFunction::Type::Linear) {
ComputedTimingFunction computedTimingFunction;
computedTimingFunction.Init(*tf);
segment.mTimingFunction = Some(computedTimingFunction);
if (CommonAnimationManager<CSSAnimation>::ExtractComputedValueForTransition(
aProperty, mStyleWithoutAnimation, computedValue) &&
StyleAnimationValue::UncomputeValue(
aProperty, Move(computedValue), aResult)) {
// If we hit this assertion or the MOZ_ASSERT_UNREACHABLE below, it
// probably means we are fetching a value from the computed style that
// we don't know how to represent as a StyleAnimationValue.
MOZ_ASSERT(aResult.GetUnit() != eCSSUnit_Null,
"Got null computed value");
return;
}
return true;
MOZ_ASSERT_UNREACHABLE("Failed to get computed value");
aResult.Reset();
}
void

Просмотреть файл

@ -621,6 +621,21 @@ void nsCSSValue::SetDependentListValue(nsCSSValueList* aList)
}
}
void
nsCSSValue::AdoptListValue(nsCSSValueList*&& aValue)
{
// We have to copy the first element since for owned lists the first
// element should be an nsCSSValueList_heap object.
SetListValue();
// FIXME: If nsCSSValue gets a swap method or move assignment operator,
// we should use that here to avoid allocating an extra value.
mValue.mList->mValue = aValue->mValue;
mValue.mList->mNext = aValue->mNext;
aValue->mNext = nullptr;
delete aValue;
aValue = nullptr;
}
nsCSSValuePairList* nsCSSValue::SetPairListValue()
{
Reset();
@ -639,6 +654,22 @@ void nsCSSValue::SetDependentPairListValue(nsCSSValuePairList* aList)
}
}
void
nsCSSValue::AdoptPairListValue(nsCSSValuePairList*&& aValue)
{
// We have to copy the first element since for owned pair lists the first
// element should be an nsCSSValuePairList_heap object.
SetPairListValue();
// FIXME: If nsCSSValue gets a swap method or move assignment operator,
// we should use that here to avoid allocating extra values.
mValue.mPairList->mXValue = aValue->mXValue;
mValue.mPairList->mYValue = aValue->mYValue;
mValue.mPairList->mNext = aValue->mNext;
aValue->mNext = nullptr;
delete aValue;
aValue = nullptr;
}
void nsCSSValue::SetAutoValue()
{
Reset();

Просмотреть файл

@ -718,6 +718,10 @@ public:
nsCSSValueList* SetListValue();
nsCSSValuePairList* SetPairListValue();
// These take ownership of the passed-in resource.
void AdoptListValue(nsCSSValueList*&& aValue);
void AdoptPairListValue(nsCSSValuePairList*&& aValue);
void StartImageLoad(nsIDocument* aDocument) const; // Only pretend const
// Initializes as a function value with the specified function id.
@ -991,7 +995,7 @@ nsCSSValue::GetListValue()
if (mUnit == eCSSUnit_List)
return mValue.mList;
else {
MOZ_ASSERT(mUnit == eCSSUnit_ListDep, "not a pairlist value");
MOZ_ASSERT(mUnit == eCSSUnit_ListDep, "not a list value");
return mValue.mListDependent;
}
}
@ -1002,7 +1006,7 @@ nsCSSValue::GetListValue() const
if (mUnit == eCSSUnit_List)
return mValue.mList;
else {
MOZ_ASSERT(mUnit == eCSSUnit_ListDep, "not a pairlist value");
MOZ_ASSERT(mUnit == eCSSUnit_ListDep, "not a list value");
return mValue.mListDependent;
}
}

Просмотреть файл

@ -979,6 +979,8 @@ nsStyleSet::GetContext(nsStyleContext* aParentContext,
// Update CSS animations in case the animation-name has just changed.
PresContext()->AnimationManager()->UpdateAnimations(result,
aElementForAnimation);
PresContext()->EffectCompositor()->UpdateEffectProperties(
result, aElementForAnimation, result->GetPseudoType());
animRule = PresContext()->EffectCompositor()->
GetAnimationRule(aElementForAnimation,

Просмотреть файл

@ -63,13 +63,11 @@ ElementPropertyTransition::CurrentValuePortion() const
MOZ_ASSERT(!computedTiming.mProgress.IsNull(),
"Got a null progress for a fill mode of 'both'");
MOZ_ASSERT(mProperties.Length() == 1,
"Should have one animation property for a transition");
MOZ_ASSERT(mProperties[0].mSegments.Length() == 1,
"Animation property should have one segment for a transition");
return ComputedTimingFunction::GetPortion(
mProperties[0].mSegments[0].mTimingFunction,
computedTiming.mProgress.Value(), computedTiming.mBeforeFlag);
MOZ_ASSERT(mFrames.Length() == 2,
"Should have two animation frames for a transition");
return ComputedTimingFunction::GetPortion(mFrames[0].mTimingFunction,
computedTiming.mProgress.Value(),
computedTiming.mBeforeFlag);
}
////////////////////////// CSSTransition ////////////////////////////
@ -178,6 +176,17 @@ CSSTransition::TransitionProperty() const
return effect->AsTransition()->TransitionProperty();
}
StyleAnimationValue
CSSTransition::ToValue() const
{
// FIXME: Once we support replacing/removing the effect (bug 1049975)
// the following assertion will no longer hold.
dom::KeyframeEffectReadOnly* effect = GetEffect();
MOZ_ASSERT(effect && effect->AsTransition(),
"Transition should have a transition effect");
return effect->AsTransition()->ToValue();
}
bool
CSSTransition::HasLowerCompositeOrderThan(const CSSTransition& aOther) const
{
@ -426,24 +435,18 @@ nsTransitionManager::StyleContextChanged(dom::Element *aElement,
do {
--i;
CSSTransition* anim = animations[i];
dom::KeyframeEffectReadOnly* effect = anim->GetEffect();
MOZ_ASSERT(effect && effect->Properties().Length() == 1,
"Should have one animation property for a transition");
MOZ_ASSERT(effect && effect->Properties()[0].mSegments.Length() == 1,
"Animation property should have one segment for a transition");
const AnimationProperty& prop = effect->Properties()[0];
const AnimationPropertySegment& segment = prop.mSegments[0];
// properties no longer in 'transition-property'
if ((checkProperties &&
!allTransitionProperties.HasProperty(prop.mProperty)) ||
!allTransitionProperties.HasProperty(anim->TransitionProperty())) ||
// properties whose computed values changed but for which we
// did not start a new transition (because delay and
// duration are both zero, or because the new value is not
// interpolable); a new transition would have segment.mToValue
// interpolable); a new transition would have anim->ToValue()
// matching currentValue
!ExtractComputedValueForTransition(prop.mProperty, afterChangeStyle,
!ExtractComputedValueForTransition(anim->TransitionProperty(),
afterChangeStyle,
currentValue) ||
currentValue != segment.mToValue) {
currentValue != anim->ToValue()) {
// stop the transition
if (anim->HasCurrentEffect()) {
EffectSet* effectSet = EffectSet::GetEffectSet(aElement, pseudoType);
@ -667,19 +670,9 @@ nsTransitionManager::ConsiderStartingTransition(
aNewStyleContext->GetPseudoType(), timing,
startForReversingTest, reversePortion);
AnimationProperty& prop = *pt->Properties().AppendElement();
prop.mProperty = aProperty;
AnimationPropertySegment& segment = *prop.mSegments.AppendElement();
segment.mFromValue = startValue;
segment.mToValue = endValue;
segment.mFromKey = 0;
segment.mToKey = 1;
if (tf.mType != nsTimingFunction::Type::Linear) {
ComputedTimingFunction computedTimingFunction;
computedTimingFunction.Init(tf);
segment.mTimingFunction = Some(computedTimingFunction);
}
pt->SetFrames(GetTransitionKeyframes(aNewStyleContext, aProperty,
Move(startValue), Move(endValue), tf),
aNewStyleContext);
MOZ_ASSERT(mPresContext->RestyleManager()->IsGecko(),
"ServoRestyleManager should not use nsTransitionManager "
@ -747,6 +740,43 @@ nsTransitionManager::ConsiderStartingTransition(
aWhichStarted->AddProperty(aProperty);
}
static Keyframe&
AppendKeyframe(double aOffset, nsCSSProperty aProperty,
StyleAnimationValue&& aValue, nsTArray<Keyframe>& aKeyframes)
{
Keyframe& frame = *aKeyframes.AppendElement();
frame.mOffset.emplace(aOffset);
PropertyValuePair& pv = *frame.mPropertyValues.AppendElement();
pv.mProperty = aProperty;
DebugOnly<bool> uncomputeResult =
StyleAnimationValue::UncomputeValue(aProperty, Move(aValue), pv.mValue);
MOZ_ASSERT(uncomputeResult,
"Unable to get specified value from computed value");
return frame;
}
nsTArray<Keyframe>
nsTransitionManager::GetTransitionKeyframes(
nsStyleContext* aStyleContext,
nsCSSProperty aProperty,
StyleAnimationValue&& aStartValue,
StyleAnimationValue&& aEndValue,
const nsTimingFunction& aTimingFunction)
{
nsTArray<Keyframe> keyframes(2);
Keyframe& fromFrame = AppendKeyframe(0.0, aProperty, Move(aStartValue),
keyframes);
if (aTimingFunction.mType != nsTimingFunction::Type::Linear) {
fromFrame.mTimingFunction.emplace();
fromFrame.mTimingFunction->Init(aTimingFunction);
}
AppendKeyframe(1.0, aProperty, Move(aEndValue), keyframes);
return keyframes;
}
void
nsTransitionManager::PruneCompletedTransitions(mozilla::dom::Element* aElement,
CSSPseudoElementType aPseudoType,
@ -775,20 +805,13 @@ nsTransitionManager::PruneCompletedTransitions(mozilla::dom::Element* aElement,
continue;
}
dom::KeyframeEffectReadOnly* effect = anim->GetEffect();
MOZ_ASSERT(effect->Properties().Length() == 1,
"Should have one animation property for a transition");
MOZ_ASSERT(effect->Properties()[0].mSegments.Length() == 1,
"Animation property should have one segment for a transition");
const AnimationProperty& prop = effect->Properties()[0];
const AnimationPropertySegment& segment = prop.mSegments[0];
// Since effect is a finished transition, we know it didn't
// influence style.
StyleAnimationValue currentValue;
if (!ExtractComputedValueForTransition(prop.mProperty, aNewStyleContext,
if (!ExtractComputedValueForTransition(anim->TransitionProperty(),
aNewStyleContext,
currentValue) ||
currentValue != segment.mToValue) {
currentValue != anim->ToValue()) {
anim->CancelFromStyle();
animations.RemoveElementAt(i);
}

Просмотреть файл

@ -23,6 +23,7 @@ class nsCSSPropertySet;
namespace mozilla {
enum class CSSPseudoElementType : uint8_t;
struct Keyframe;
struct StyleTransition;
} // namespace mozilla
@ -147,6 +148,7 @@ public:
void Tick() override;
nsCSSProperty TransitionProperty() const;
StyleAnimationValue ToValue() const;
bool HasLowerCompositeOrderThan(const CSSTransition& aOther) const;
EffectCompositor::CascadeLevel CascadeLevel() const override
@ -355,6 +357,13 @@ protected:
bool* aStartedAny,
nsCSSPropertySet* aWhichStarted);
nsTArray<mozilla::Keyframe> GetTransitionKeyframes(
nsStyleContext* aStyleContext,
nsCSSProperty aProperty,
mozilla::StyleAnimationValue&& aStartValue,
mozilla::StyleAnimationValue&& aEndValue,
const nsTimingFunction& aTimingFunction);
bool mInAnimationOnlyStyleUpdate;
mozilla::DelayedEventDispatcher<mozilla::TransitionEventInfo>

Просмотреть файл

@ -50,7 +50,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=435442
25% { margin-top: 100px }
}
@keyframes kf4 {
to, from { display: inline; margin-top: 37px }
to, from { border-collapse: collapse; margin-top: 37px }
}
@keyframes kf_cascade1 {
from { padding-top: 50px }
@ -566,23 +566,23 @@ done_div();
// we still override the value when two consecutive keyframes have
// the same value.
new_div("animation: kf4 ease 10s");
is(cs.display, "block",
is(cs.borderCollapse, "separate",
"non-animatable properties should be ignored (linear, 0s)");
is(cs.marginTop, "37px",
"animatable properties should still apply (linear, 0s)");
advance_clock(1000);
is(cs.display, "block",
is(cs.borderCollapse, "separate",
"non-animatable properties should be ignored (linear, 1s)");
is(cs.marginTop, "37px",
"animatable properties should still apply (linear, 1s)");
done_div();
new_div("animation: kf4 step-start 10s");
is(cs.display, "block",
is(cs.borderCollapse, "separate",
"non-animatable properties should be ignored (step-start, 0s)");
is(cs.marginTop, "37px",
"animatable properties should still apply (step-start, 0s)");
advance_clock(1000);
is(cs.display, "block",
is(cs.borderCollapse, "separate",
"non-animatable properties should be ignored (step-start, 1s)");
is(cs.marginTop, "37px",
"animatable properties should still apply (step-start, 1s)");

Просмотреть файл

@ -61,7 +61,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=964646
25% { transform: translate(100px) }
}
@keyframes kf4 {
to, from { display: inline; transform: translate(37px) }
to, from { border-collapse: collapse; transform: translate(37px) }
}
@keyframes kf_cascade1 {
from { transform: translate(50px) }
@ -637,12 +637,12 @@ addAsyncAnimTest(function *() {
new_div("animation: kf4 ease 10s");
yield waitForPaintsFlushed();
var cs = window.getComputedStyle(gDiv);
is(cs.display, "block",
is(cs.borderCollapse, "separate",
"non-animatable properties should be ignored (linear, 0s)");
omta_is("transform", { tx: 37 }, RunningOn.Compositor,
"animatable properties should still apply (linear, 0s)");
advance_clock(1000);
is(cs.display, "block",
is(cs.borderCollapse, "separate",
"non-animatable properties should be ignored (linear, 1s)");
omta_is("transform", { tx: 37 }, RunningOn.Compositor,
"animatable properties should still apply (linear, 1s)");
@ -650,12 +650,12 @@ addAsyncAnimTest(function *() {
new_div("animation: kf4 step-start 10s");
yield waitForPaintsFlushed();
cs = window.getComputedStyle(gDiv);
is(cs.display, "block",
is(cs.borderCollapse, "separate",
"non-animatable properties should be ignored (step-start, 0s)");
omta_is("transform", { tx: 37 }, RunningOn.Compositor,
"animatable properties should still apply (step-start, 0s)");
advance_clock(1000);
is(cs.display, "block",
is(cs.borderCollapse, "separate",
"non-animatable properties should be ignored (step-start, 1s)");
omta_is("transform", { tx: 37 }, RunningOn.Compositor,
"animatable properties should still apply (step-start, 1s)");

Просмотреть файл

@ -236,7 +236,7 @@ nsImageBoxFrame::UpdateImage()
if (uri && nsContentUtils::CanLoadImage(uri, mContent, doc,
mContent->NodePrincipal())) {
nsContentUtils::LoadImage(uri, doc, mContent->NodePrincipal(),
nsContentUtils::LoadImage(uri, mContent, doc, mContent->NodePrincipal(),
doc->GetDocumentURI(), doc->GetReferrerPolicy(),
mListener, mLoadFlags,
EmptyString(), getter_AddRefs(mImageRequest));

Просмотреть файл

@ -2191,6 +2191,7 @@ nsTreeBodyFrame::GetImage(int32_t aRowIndex, nsTreeColumn* aCol, bool aUseContex
if (nsContentUtils::CanLoadImage(srcURI, mContent, doc,
mContent->NodePrincipal())) {
nsresult rv = nsContentUtils::LoadImage(srcURI,
mContent,
doc,
mContent->NodePrincipal(),
doc->GetDocumentURI(),

Просмотреть файл

@ -40,7 +40,7 @@ public class testBookmarklets extends BaseTest {
public boolean isSatisfied() {
return mSolo.searchButton("OK", true) && mSolo.searchText(expected, true);
}
}, 3000);
}, 10000);
mAsserter.is(alerted, true, "Alert was shown for bookmarklet");
}
}

Просмотреть файл

@ -45,4 +45,4 @@ TrackingUriBlocked=The resource at "%1$S" was blocked because tracking protectio
APIDeprecationWarning=Warning: '%1$S' deprecated, please use '%2$S'
# LOCALIZATION NOTE (nsICookieManagerRemoveDeprecated): don't localize nsICookieManager.remove() and originAttributes.
nsICookieManagerRemoveDeprecated="'nsICookieManager.remove()' is changed. Update your code and pass the correct originAttributes. Read more on MDN: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsICookieManager'
nsICookieManagerRemoveDeprecated=“nsICookieManager.remove()” is changed. Update your code and pass the correct originAttributes. Read more on MDN: https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsICookieManager

Просмотреть файл

@ -71,7 +71,7 @@ GNOMEUI_VERSION=2.2.0
GCONF_VERSION=1.2.1
STARTUP_NOTIFICATION_VERSION=0.8
DBUS_VERSION=0.60
SQLITE_VERSION=3.11.0
SQLITE_VERSION=3.12.1
FONTCONFIG_VERSION=2.7.0
MSMANIFEST_TOOL=

Просмотреть файл

@ -14,7 +14,13 @@ nsHtml5Atom::nsHtml5Atom(const nsAString& aString)
if (buf) {
mString = static_cast<char16_t*>(buf->Data());
} else {
buf = nsStringBuffer::Alloc((mLength + 1) * sizeof(char16_t));
const size_t size = (mLength + 1) * sizeof(char16_t);
buf = nsStringBuffer::Alloc(size);
if (MOZ_UNLIKELY(!buf)) {
// We OOM because atom allocations should be small and it's hard to
// handle them more gracefully in a constructor.
NS_ABORT_OOM(size);
}
mString = static_cast<char16_t*>(buf->Data());
CopyUnicodeTo(aString, 0, mString, mLength);
mString[mLength] = char16_t(0);

Просмотреть файл

@ -140,11 +140,8 @@ class CommandAction(argparse.Action):
subcommand = None
# If there are sub-commands, parse the intent out immediately.
if handler.subcommand_handlers:
if not args:
self._handle_subcommand_main_help(parser, handler)
sys.exit(0)
elif len(args) == 1 and args[0] in ('help', '--help'):
if handler.subcommand_handlers and args:
if len(args) == 1 and args[0] in ('help', '--help'):
self._handle_subcommand_main_help(parser, handler)
sys.exit(0)
# mach <command> help <subcommand>

Просмотреть файл

@ -0,0 +1,135 @@
[DEFAULT]
subsuite = media
[../tests/dom/media/tests/mochitest/test_dataChannel_basicAudio.html]
[../tests/dom/media/tests/mochitest/test_dataChannel_basicAudioVideoCombined.html]
[../tests/dom/media/tests/mochitest/test_dataChannel_basicAudioVideo.html]
[../tests/dom/media/tests/mochitest/test_dataChannel_basicAudioVideoNoBundle.html]
[../tests/dom/media/tests/mochitest/test_dataChannel_basicDataOnly.html]
[../tests/dom/media/tests/mochitest/test_dataChannel_basicVideo.html]
[../tests/dom/media/tests/mochitest/test_dataChannel_bug1013809.html]
[../tests/dom/media/tests/mochitest/test_dataChannel_noOffer.html]
[../tests/dom/media/tests/mochitest/test_enumerateDevices.html]
[../tests/dom/media/tests/mochitest/test_getUserMedia_addTrackRemoveTrack.html]
[../tests/dom/media/tests/mochitest/test_getUserMedia_audioCapture.html]
skip-if = true # timeout
[../tests/dom/media/tests/mochitest/test_getUserMedia_basicAudio.html]
[../tests/dom/media/tests/mochitest/test_getUserMedia_basicScreenshare.html]
skip-if = true # OverConstrained error
[../tests/dom/media/tests/mochitest/test_getUserMedia_basicTabshare.html]
[../tests/dom/media/tests/mochitest/test_getUserMedia_basicVideoAudio.html]
[../tests/dom/media/tests/mochitest/test_getUserMedia_basicVideo.html]
[../tests/dom/media/tests/mochitest/test_getUserMedia_basicVideo_playAfterLoadedmetadata.html]
[../tests/dom/media/tests/mochitest/test_getUserMedia_basicWindowshare.html]
skip-if = true # OverConstrained error
[../tests/dom/media/tests/mochitest/test_getUserMedia_bug1223696.html]
[../tests/dom/media/tests/mochitest/test_getUserMedia_callbacks.html]
[../tests/dom/media/tests/mochitest/test_getUserMedia_constraints.html]
[../tests/dom/media/tests/mochitest/test_getUserMedia_gumWithinGum.html]
[../tests/dom/media/tests/mochitest/test_getUserMedia_loadedmetadata.html]
[../tests/dom/media/tests/mochitest/test_getUserMedia_mediaStreamConstructors.html]
[../tests/dom/media/tests/mochitest/test_getUserMedia_peerIdentity.html]
[../tests/dom/media/tests/mochitest/test_getUserMedia_playAudioTwice.html]
[../tests/dom/media/tests/mochitest/test_getUserMedia_playVideoAudioTwice.html]
[../tests/dom/media/tests/mochitest/test_getUserMedia_playVideoTwice.html]
[../tests/dom/media/tests/mochitest/test_getUserMedia_spinEventLoop.html]
[../tests/dom/media/tests/mochitest/test_getUserMedia_stopAudioStream.html]
[../tests/dom/media/tests/mochitest/test_getUserMedia_stopAudioStreamWithFollowupAudio.html]
[../tests/dom/media/tests/mochitest/test_getUserMedia_stopVideoAudioStream.html]
[../tests/dom/media/tests/mochitest/test_getUserMedia_stopVideoAudioStreamWithFollowupVideoAudio.html]
[../tests/dom/media/tests/mochitest/test_getUserMedia_stopVideoStream.html]
[../tests/dom/media/tests/mochitest/test_getUserMedia_stopVideoStreamWithFollowupVideo.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_addDataChannel.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_addDataChannelNoBundle.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_addIceCandidate.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_addSecondAudioStream.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_addSecondAudioStreamNoBundle.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_addSecondVideoStream.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_addSecondVideoStreamNoBundle.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_addTrack.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_answererAddSecondAudioStream.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_basicAudioDynamicPtMissingRtpmap.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_basicAudio.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_basicAudioPcmaPcmuOnly.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_basicAudioRequireEOC.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_basicAudioVideoCombined.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_basicAudioVideo.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_basicAudioVideoNoBundle.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_basicAudioVideoNoBundleNoRtcpMux.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_basicAudioVideoNoRtcpMux.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_basicH264Video.html]
skip-if = true # H.264 should be present in the SDP offer - didn't expect -1, but got it, many other failures
[../tests/dom/media/tests/mochitest/test_peerConnection_basicScreenshare.html]
skip-if = true # OverConstrained error
[../tests/dom/media/tests/mochitest/test_peerConnection_basicVideo.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_basicWindowshare.html]
skip-if = true # H.264 should be present in the SDP offer - didn't expect -1, but got it
[../tests/dom/media/tests/mochitest/test_peerConnection_bug1013809.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_bug1042791.html]
skip-if = true # H.264 should be present in the SDP offer - didn't expect -1, but got it
[../tests/dom/media/tests/mochitest/test_peerConnection_bug1064223.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_bug1227781.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_bug822674.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_bug825703.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_bug827843.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_bug834153.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_callbacks.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_capturedVideo.html]
skip-if = true # application crashed [@ mozilla::layers::GLImage::GetAsSourceSurface] on Android < 6
[../tests/dom/media/tests/mochitest/test_peerConnection_captureStream_canvas_2d.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_captureStream_canvas_webgl.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_certificates.html]
skip-if = true # timeout
[../tests/dom/media/tests/mochitest/test_peerConnection_closeDuringIce.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_close.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_errorCallbacks.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_forwarding_basicAudioVideoCombined.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_iceFailure.html]
skip-if = true # timeout
[../tests/dom/media/tests/mochitest/test_peerConnection_localReofferRollback.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_localRollback.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_multiple_captureStream_canvas_2d.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_noTrickleAnswer.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_noTrickleOfferAnswer.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_noTrickleOffer.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveAudio.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideoAudio.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideo.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_promiseSendOnly.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_relayOnly.html]
skip-if = true # timeout
[../tests/dom/media/tests/mochitest/test_peerConnection_remoteReofferRollback.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_remoteRollback.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_removeAudioTrack.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_removeThenAddAudioTrack.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_removeThenAddAudioTrackNoBundle.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_removeThenAddVideoTrack.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_removeThenAddVideoTrackNoBundle.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_removeVideoTrack.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_replaceTrack.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_replaceVideoThenRenegotiate.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_scaleResolution.html]
skip-if = true # timeout
[../tests/dom/media/tests/mochitest/test_peerConnection_setLocalAnswerInHaveLocalOffer.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_setLocalAnswerInStable.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_setLocalOfferInHaveRemoteOffer.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_setParameters.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_setRemoteAnswerInHaveRemoteOffer.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_setRemoteAnswerInStable.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_setRemoteOfferInHaveLocalOffer.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_simulcastOffer.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_syncSetDescription.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_throwInCallbacks.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_toJSON.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_trackDisabling.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_twoAudioStreams.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_twoAudioTracksInOneStream.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_twoAudioVideoStreamsCombined.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_twoAudioVideoStreams.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_twoVideoStreams.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_twoVideoTracksInOneStream.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_verifyAudioAfterRenegotiation.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_verifyVideoAfterRenegotiation.html]
[../tests/dom/media/tests/mochitest/test_peerConnection_webAudio.html]
[../tests/dom/media/tests/mochitest/test_selftest.html]
[../tests/dom/media/tests/mochitest/test_zmedia_cleanup.html]

Просмотреть файл

@ -6,5 +6,6 @@
TEST_HARNESS_FILES.testing.mochitest.manifests += [
'autophone-media.ini',
'autophone-webrtc.ini',
'emulator-jb.ini',
]

Просмотреть файл

@ -28389,10 +28389,18 @@
"path": "web-animations/animatable/animate.html",
"url": "/web-animations/animatable/animate.html"
},
{
"path": "web-animations/animation-effect-timing/delay.html",
"url": "/web-animations/animation-effect-timing/delay.html"
},
{
"path": "web-animations/animation-effect-timing/direction.html",
"url": "/web-animations/animation-effect-timing/direction.html"
},
{
"path": "web-animations/animation-model/keyframes/effect-value-context.html",
"url": "/web-animations/animation-model/keyframes/effect-value-context.html"
},
{
"path": "web-animations/animation-effect-timing/duration.html",
"url": "/web-animations/animation-effect-timing/duration.html"

Просмотреть файл

@ -0,0 +1,6 @@
[effect-value-context.html]
type: testharness
[Effect values reflect changes to font-size when computed style is not immediately flushed]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1254424

Просмотреть файл

@ -1,10 +1,10 @@
[constructor.html]
type: testharness
[composite values are parsed correctly when passed to the KeyframeEffectReadOnly constructor in PropertyIndexedKeyframes]
[composite values are parsed correctly when passed to the KeyframeEffectReadOnly constructor in property-indexed keyframes]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1216843
[composite values are parsed correctly when passed to the KeyframeEffectReadOnly constructor in Keyframe]
[composite values are parsed correctly when passed to the KeyframeEffectReadOnly constructor in regular keyframes]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1216843
@ -12,55 +12,55 @@
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1216843
[a KeyframeEffectReadOnly can be constructed with a Keyframe sequence with different composite values, but the same composite value for a given offset]
[a KeyframeEffectReadOnly can be constructed with a keyframe sequence with different composite values, but the same composite value for a given offset]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1216843
[a KeyframeEffectReadOnly can be constructed with a one property one value PropertyIndexedKeyframes specification]
[a KeyframeEffectReadOnly can be constructed with a one property one value property-indexed keyframes specification]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1216844
[a KeyframeEffectReadOnly constructed with a one property one value PropertyIndexedKeyframes specification roundtrips]
[a KeyframeEffectReadOnly constructed with a one property one value property-indexed keyframes specification roundtrips]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1216844
[a KeyframeEffectReadOnly can be constructed with a one property one non-array value PropertyIndexedKeyframes specification]
[a KeyframeEffectReadOnly can be constructed with a one property one non-array value property-indexed keyframes specification]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1216844
[a KeyframeEffectReadOnly constructed with a one property one non-array value PropertyIndexedKeyframes specification roundtrips]
[a KeyframeEffectReadOnly constructed with a one property one non-array value property-indexed keyframes specification roundtrips]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1216844
[a KeyframeEffectReadOnly can be constructed with a one property two value PropertyIndexedKeyframes specification where the first value is invalid]
[a KeyframeEffectReadOnly can be constructed with a one property two value property-indexed keyframes specification where the first value is invalid]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1216844
[a KeyframeEffectReadOnly constructed with a one property two value PropertyIndexedKeyframes specification where the first value is invalid roundtrips]
[a KeyframeEffectReadOnly constructed with a one property two value property-indexed keyframes specification where the first value is invalid roundtrips]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1216844
[a KeyframeEffectReadOnly can be constructed with a one property two value PropertyIndexedKeyframes specification where the second value is invalid]
[a KeyframeEffectReadOnly can be constructed with a one property two value property-indexed keyframes specification where the second value is invalid]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1216844
[a KeyframeEffectReadOnly constructed with a one property two value PropertyIndexedKeyframes specification where the second value is invalid roundtrips]
[a KeyframeEffectReadOnly constructed with a one property two value property-indexed keyframes specification where the second value is invalid roundtrips]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1216844
[a KeyframeEffectReadOnly can be constructed with a two property PropertyIndexedKeyframes specification where one property is missing from the first Keyframe]
[a KeyframeEffectReadOnly can be constructed with a two property property-indexed keyframes specification where one property is missing from the first keyframe]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1216844
[a KeyframeEffectReadOnly constructed with a two property PropertyIndexedKeyframes specification where one property is missing from the first Keyframe roundtrips]
[a KeyframeEffectReadOnly constructed with a two property property-indexed keyframes specification where one property is missing from the first keyframe roundtrips]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1216844
[a KeyframeEffectReadOnly can be constructed with a two property PropertyIndexedKeyframes specification where one property is missing from the last Keyframe]
[a KeyframeEffectReadOnly can be constructed with a two property property-indexed keyframes specification where one property is missing from the last keyframe]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1216844
[a KeyframeEffectReadOnly constructed with a two property PropertyIndexedKeyframes specification where one property is missing from the last Keyframe roundtrips]
[a KeyframeEffectReadOnly constructed with a two property property-indexed keyframes specification where one property is missing from the last keyframe roundtrips]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1216844

Просмотреть файл

@ -0,0 +1,86 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Tests that property values respond to changes to their context</title>
<link rel="help" href="https://w3c.github.io/web-animations/#keyframes-section">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
<link rel="stylesheet" href="/resources/testharness.css">
<body>
<div id="log"></div>
<script>
test(function(t) {
var div = createDiv(t);
div.style.fontSize = '10px';
var animation = div.animate([ { marginLeft: '10em' },
{ marginLeft: '20em' } ], 1000);
animation.currentTime = 500;
assert_equals(getComputedStyle(div).marginLeft, '150px',
'Effect value before updating font-size');
div.style.fontSize = '20px';
assert_equals(getComputedStyle(div).marginLeft, '300px',
'Effect value after updating font-size');
}, 'Effect values reflect changes to font-size on element');
test(function(t) {
var parentDiv = createDiv(t);
var div = createDiv(t);
parentDiv.appendChild(div);
parentDiv.style.fontSize = '10px';
var animation = div.animate([ { marginLeft: '10em' },
{ marginLeft: '20em' } ], 1000);
animation.currentTime = 500;
assert_equals(getComputedStyle(div).marginLeft, '150px',
'Effect value before updating font-size on parent element');
parentDiv.style.fontSize = '20px';
assert_equals(getComputedStyle(div).marginLeft, '300px',
'Effect value after updating font-size on parent element');
}, 'Effect values reflect changes to font-size on parent element');
promise_test(function(t) {
var parentDiv = createDiv(t);
var div = createDiv(t);
parentDiv.appendChild(div);
parentDiv.style.fontSize = '10px';
var animation = div.animate([ { marginLeft: '10em' },
{ marginLeft: '20em' } ], 1000);
animation.pause();
animation.currentTime = 500;
parentDiv.style.fontSize = '20px';
return animation.ready.then(function() {
assert_equals(getComputedStyle(div).marginLeft, '300px',
'Effect value after updating font-size on parent element');
});
}, 'Effect values reflect changes to font-size when computed style is not'
+ ' immediately flushed');
promise_test(function(t) {
var divWith10pxFontSize = createDiv(t);
divWith10pxFontSize.style.fontSize = '10px';
var divWith20pxFontSize = createDiv(t);
divWith20pxFontSize.style.fontSize = '20px';
var div = createDiv(t);
div.remove(); // Detach
var animation = div.animate([ { marginLeft: '10em' },
{ marginLeft: '20em' } ], 1000);
animation.pause();
return animation.ready.then(function() {
animation.currentTime = 500;
divWith10pxFontSize.appendChild(div);
assert_equals(getComputedStyle(div).marginLeft, '150px',
'Effect value after attaching to font-size:10px parent');
divWith20pxFontSize.appendChild(div);
assert_equals(getComputedStyle(div).marginLeft, '300px',
'Effect value after attaching to font-size:20px parent');
});
}, 'Effect values reflect changes to font-size from reparenting');
</script>
</body>

Просмотреть файл

@ -38,17 +38,6 @@ function assert_frame_lists_equal(a, b) {
var gEmptyKeyframeListTests = [
[],
[{}],
[{ easing: "ease-in" }],
[{ unknown: "unknown" }, { unknown: "unknown" }],
[{ color: "invalid" }, { color: "invalid" }],
{ easing: "ease-in" },
{ unknown: "unknown" },
{ unknown: [] },
{ unknown: ["unknown"] },
{ unknown: ["unknown", "unknown"] },
{ animationName: ["none", "abc"] },
{ color: [] },
null,
undefined,
];
@ -80,7 +69,7 @@ test(function(t) {
"resulting easing for '" + easing + "'");
});
}, "easing values are parsed correctly when passed to the " +
"KeyframeEffectReadOnly constructor in PropertyIndexedKeyframes");
"KeyframeEffectReadOnly constructor in a property-indexed keyframe");
test(function(t) {
gEasingValueTests.forEach(function(subtest) {
@ -94,7 +83,7 @@ test(function(t) {
"resulting easing for '" + easing + "'");
});
}, "easing values are parsed correctly when passed to the " +
"KeyframeEffectReadOnly constructor in Keyframe");
"KeyframeEffectReadOnly constructor in regular keyframes");
test(function(t) {
gEasingValueTests.forEach(function(subtest) {
@ -136,7 +125,7 @@ test(function(t) {
});
});
}, "composite values are parsed correctly when passed to the " +
"KeyframeEffectReadOnly constructor in PropertyIndexedKeyframes");
"KeyframeEffectReadOnly constructor in property-indexed keyframes");
test(function(t) {
var getFrames = function(composite) {
@ -156,7 +145,7 @@ test(function(t) {
});
});
}, "composite values are parsed correctly when passed to the " +
"KeyframeEffectReadOnly constructor in Keyframe");
"KeyframeEffectReadOnly constructor in regular keyframes");
test(function(t) {
gGoodOptionsCompositeValueTests.forEach(function(composite) {
@ -177,79 +166,119 @@ test(function(t) {
"KeyframeEffectReadOnly constructor in KeyframeTimingOptions");
var gPropertyIndexedKeyframesTests = [
{ desc: "a one property two value PropertyIndexedKeyframes specification",
{ desc: "a one property two value property-indexed keyframes specification",
input: { left: ["10px", "20px"] },
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" },
{ offset: 1, computedOffset: 1, easing: "linear", left: "20px" }] },
{ desc: "a one shorthand property two value PropertyIndexedKeyframes specification",
output: [{ offset: null, computedOffset: 0, easing: "linear",
left: "10px" },
{ offset: null, computedOffset: 1, easing: "linear",
left: "20px" }] },
{ desc: "a one shorthand property two value property-indexed keyframes"
+ " specification",
input: { margin: ["10px", "10px 20px 30px 40px"] },
output: [{ offset: 0, computedOffset: 0, easing: "linear", marginTop: "10px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
{ offset: 1, computedOffset: 1, easing: "linear", marginTop: "10px", marginRight: "20px", marginBottom: "30px", marginLeft: "40px" }] },
{ desc: "a two property (one shorthand and one of its longhand components) two value PropertyIndexedKeyframes specification",
output: [{ offset: null, computedOffset: 0, easing: "linear",
margin: "10px" },
{ offset: null, computedOffset: 1, easing: "linear",
margin: "10px 20px 30px 40px" }] },
{ desc: "a two property (one shorthand and one of its longhand components)"
+ " two value property-indexed keyframes specification",
input: { marginTop: ["50px", "60px"],
margin: ["10px", "10px 20px 30px 40px"] },
output: [{ offset: 0, computedOffset: 0, easing: "linear", marginTop: "50px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
{ offset: 1, computedOffset: 1, easing: "linear", marginTop: "60px", marginRight: "20px", marginBottom: "30px", marginLeft: "40px" }] },
{ desc: "a two property two value PropertyIndexedKeyframes specification",
output: [{ offset: null, computedOffset: 0, easing: "linear",
marginTop: "50px", margin: "10px" },
{ offset: null, computedOffset: 1, easing: "linear",
marginTop: "60px", margin: "10px 20px 30px 40px" }] },
{ desc: "a two property two value property-indexed keyframes specification",
input: { left: ["10px", "20px"],
top: ["30px", "40px"] },
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px", top: "30px" },
{ offset: 1, computedOffset: 1, easing: "linear", left: "20px", top: "40px" }] },
{ desc: "a two property PropertyIndexedKeyframes specification with different numbers of values",
output: [{ offset: null, computedOffset: 0, easing: "linear",
left: "10px", top: "30px" },
{ offset: null, computedOffset: 1, easing: "linear",
left: "20px", top: "40px" }] },
{ desc: "a two property property-indexed keyframes specification with"
+ " different numbers of values",
input: { left: ["10px", "20px", "30px"],
top: ["40px", "50px"] },
output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear", left: "10px", top: "40px" },
{ offset: 0.5, computedOffset: 0.5, easing: "linear", left: "20px" },
{ offset: 1.0, computedOffset: 1.0, easing: "linear", left: "30px", top: "50px" }] },
{ desc: "a PropertyIndexedKeyframes specification with an invalid value",
output: [{ offset: null, computedOffset: 0.0, easing: "linear",
left: "10px", top: "40px" },
{ offset: null, computedOffset: 0.5, easing: "linear",
left: "20px" },
{ offset: null, computedOffset: 1.0, easing: "linear",
left: "30px", top: "50px" }] },
{ desc: "a property-indexed keyframes specification with an invalid value",
input: { left: ["10px", "20px", "30px", "40px", "50px"],
top: ["15px", "25px", "invalid", "45px", "55px"] },
output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", left: "10px", top: "15px" },
{ offset: 0.25, computedOffset: 0.25, easing: "linear", left: "20px", top: "25px" },
{ offset: 0.50, computedOffset: 0.50, easing: "linear", left: "30px" },
{ offset: 0.75, computedOffset: 0.75, easing: "linear", left: "40px", top: "45px" },
{ offset: 1.00, computedOffset: 1.00, easing: "linear", left: "50px", top: "55px" }] },
{ desc: "a one property two value PropertyIndexedKeyframes specification that needs to stringify its values",
output: [{ offset: null, computedOffset: 0.00, easing: "linear",
left: "10px", top: "15px" },
{ offset: null, computedOffset: 0.25, easing: "linear",
left: "20px", top: "25px" },
{ offset: null, computedOffset: 0.50, easing: "linear",
left: "30px", top: "invalid" },
{ offset: null, computedOffset: 0.75, easing: "linear",
left: "40px", top: "45px" },
{ offset: null, computedOffset: 1.00, easing: "linear",
left: "50px", top: "55px" }] },
{ desc: "a one property two value property-indexed keyframes specification"
+ " that needs to stringify its values",
input: { opacity: [0, 1] },
output: [{ offset: 0, computedOffset: 0, easing: "linear", opacity: "0" },
{ offset: 1, computedOffset: 1, easing: "linear", opacity: "1" }] },
{ desc: "a one property one value PropertyIndexedKeyframes specification",
output: [{ offset: null, computedOffset: 0, easing: "linear",
opacity: "0" },
{ offset: null, computedOffset: 1, easing: "linear",
opacity: "1" }] },
{ desc: "a one property one value property-indexed keyframes specification",
input: { left: ["10px"] },
output: [{ offset: 0, computedOffset: 0, easing: "linear" },
{ offset: 1, computedOffset: 1, easing: "linear", left: "10px" }] },
{ desc: "a one property one non-array value PropertyIndexedKeyframes specification",
output: [{ offset: null, computedOffset: 1, easing: "linear",
left: "10px" }] },
{ desc: "a one property one non-array value property-indexed keyframes"
+ " specification",
input: { left: "10px" },
output: [{ offset: 0, computedOffset: 0, easing: "linear" },
{ offset: 1, computedOffset: 1, easing: "linear", left: "10px" }] },
{ desc: "a one property two value PropertyIndexedKeyframes specification where the first value is invalid",
output: [{ offset: null, computedOffset: 1, easing: "linear",
left: "10px" }] },
{ desc: "a one property two value property-indexed keyframes specification"
+ " where the first value is invalid",
input: { left: ["invalid", "10px"] },
output: [{ offset: 0, computedOffset: 0, easing: "linear" },
{ offset: 1, computedOffset: 1, easing: "linear", left: "10px" }] },
{ desc: "a one property two value PropertyIndexedKeyframes specification where the second value is invalid",
output: [{ offset: null, computedOffset: 0, easing: "linear",
left: "invalid" },
{ offset: null, computedOffset: 1, easing: "linear",
left: "10px" }] },
{ desc: "a one property two value property-indexed keyframes specification"
+ " where the second value is invalid",
input: { left: ["10px", "invalid"] },
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" },
{ offset: 1, computedOffset: 1, easing: "linear" }] },
{ desc: "a two property PropertyIndexedKeyframes specification where one property is missing from the first Keyframe",
output: [{ offset: null, computedOffset: 0, easing: "linear",
left: "10px" },
{ offset: null, computedOffset: 1, easing: "linear",
left: "invalid" }] },
{ desc: "a two property property-indexed keyframes specification where one"
+ " property is missing from the first keyframe",
input: [{ offset: 0, left: "10px" },
{ offset: 1, left: "20px", top: "30px" }],
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" },
{ offset: 1, computedOffset: 1, easing: "linear", left: "20px", top: "30px" }] },
{ desc: "a two property PropertyIndexedKeyframes specification where one property is missing from the last Keyframe",
{ offset: 1, computedOffset: 1, easing: "linear",
left: "20px", top: "30px" }] },
{ desc: "a two property property-indexed keyframes specification where one"
+ " property is missing from the last keyframe",
input: [{ offset: 0, left: "10px", top: "20px" },
{ offset: 1, left: "30px" }],
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" , top: "20px" },
{ offset: 1, computedOffset: 1, easing: "linear", left: "30px" }] },
{ desc: "a PropertyIndexedKeyframes specification with repeated values at offset 0 with different easings",
output: [{ offset: 0, computedOffset: 0, easing: "linear",
left: "10px" , top: "20px" },
{ offset: 1, computedOffset: 1, easing: "linear",
left: "30px" }] },
{ desc: "a property-indexed keyframes specification with repeated values"
+ " at offset 0 with different easings",
input: [{ offset: 0.0, left: "100px", easing: "ease" },
{ offset: 0.0, left: "200px", easing: "ease" },
{ offset: 0.5, left: "300px", easing: "linear" },
{ offset: 1.0, left: "400px", easing: "ease-out" },
{ offset: 1.0, left: "500px", easing: "step-end" }],
output: [{ offset: 0.0, computedOffset: 0.0, easing: "ease", left: "100px" },
{ offset: 0.0, computedOffset: 0.0, easing: "ease", left: "200px" },
{ offset: 0.5, computedOffset: 0.5, easing: "linear", left: "300px" },
{ offset: 1.0, computedOffset: 1.0, easing: "ease-out", left: "400px" },
{ offset: 1.0, computedOffset: 1.0, easing: "linear", left: "500px" }] },
output: [{ offset: 0.0, computedOffset: 0.0, easing: "ease",
left: "100px" },
{ offset: 0.0, computedOffset: 0.0, easing: "ease",
left: "200px" },
{ offset: 0.5, computedOffset: 0.5, easing: "linear",
left: "300px" },
{ offset: 1.0, computedOffset: 1.0, easing: "ease-out",
left: "400px" },
{ offset: 1.0, computedOffset: 1.0, easing: "step-end",
left: "500px" }] },
];
gPropertyIndexedKeyframesTests.forEach(function(subtest) {
@ -283,41 +312,56 @@ test(function(t) {
});
new KeyframeEffectReadOnly(target, [kf1, kf2]);
assert_array_equals(actualOrder, expectedOrder, "property access order");
}, "the KeyframeEffectReadOnly constructor reads Keyframe properties in the " +
}, "the KeyframeEffectReadOnly constructor reads keyframe properties in the " +
"expected order");
var gKeyframeSequenceTests = [
{ desc: "a one property two Keyframe sequence",
{ desc: "a one property two keyframe sequence",
input: [{ offset: 0, left: "10px" },
{ offset: 1, left: "20px" }],
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" },
{ offset: 1, computedOffset: 1, easing: "linear", left: "20px" }] },
{ desc: "a two property two Keyframe sequence",
{ offset: 1, computedOffset: 1, easing: "linear", left: "20px" }]
},
{ desc: "a two property two keyframe sequence",
input: [{ offset: 0, left: "10px", top: "30px" },
{ offset: 1, left: "20px", top: "40px" }],
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px", top: "30px" },
{ offset: 1, computedOffset: 1, easing: "linear", left: "20px", top: "40px" }] },
{ desc: "a one shorthand property two Keyframe sequence",
output: [{ offset: 0, computedOffset: 0, easing: "linear",
left: "10px", top: "30px" },
{ offset: 1, computedOffset: 1, easing: "linear",
left: "20px", top: "40px" }] },
{ desc: "a one shorthand property two keyframe sequence",
input: [{ offset: 0, margin: "10px" },
{ offset: 1, margin: "20px 30px 40px 50px" }],
output: [{ offset: 0, computedOffset: 0, easing: "linear", marginTop: "10px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
{ offset: 1, computedOffset: 1, easing: "linear", marginTop: "20px", marginRight: "30px", marginBottom: "40px", marginLeft: "50px" }] },
{ desc: "a two property (a shorthand and one of its component longhands) two Keyframe sequence",
output: [{ offset: 0, computedOffset: 0, easing: "linear",
margin: "10px" },
{ offset: 1, computedOffset: 1, easing: "linear",
margin: "20px 30px 40px 50px" }] },
{ desc: "a two property (a shorthand and one of its component longhands)"
+ " two keyframe sequence",
input: [{ offset: 0, margin: "10px", marginTop: "20px" },
{ offset: 1, marginTop: "70px", margin: "30px 40px 50px 60px" }],
output: [{ offset: 0, computedOffset: 0, easing: "linear", marginTop: "20px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
{ offset: 1, computedOffset: 1, easing: "linear", marginTop: "70px", marginRight: "40px", marginBottom: "50px", marginLeft: "60px" }] },
{ desc: "a Keyframe sequence with duplicate values for a given interior offset",
output: [{ offset: 0, computedOffset: 0, easing: "linear",
margin: "10px", marginTop: "20px" },
{ offset: 1, computedOffset: 1, easing: "linear",
marginTop: "70px", margin: "30px 40px 50px 60px" }] },
{ desc: "a keyframe sequence with duplicate values for a given interior"
+ " offset",
input: [{ offset: 0.0, left: "10px" },
{ offset: 0.5, left: "20px" },
{ offset: 0.5, left: "30px" },
{ offset: 0.5, left: "40px" },
{ offset: 1.0, left: "50px" }],
output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear", left: "10px" },
{ offset: 0.5, computedOffset: 0.5, easing: "linear", left: "20px" },
{ offset: 0.5, computedOffset: 0.5, easing: "linear", left: "40px" },
{ offset: 1.0, computedOffset: 1.0, easing: "linear", left: "50px" }] },
{ desc: "a Keyframe sequence with duplicate values for offsets 0 and 1",
output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear",
left: "10px" },
{ offset: 0.5, computedOffset: 0.5, easing: "linear",
left: "20px" },
{ offset: 0.5, computedOffset: 0.5, easing: "linear",
left: "30px" },
{ offset: 0.5, computedOffset: 0.5, easing: "linear",
left: "40px" },
{ offset: 1.0, computedOffset: 1.0, easing: "linear",
left: "50px" }] },
{ desc: "a keyframe sequence with duplicate values for offsets 0 and 1",
input: [{ offset: 0, left: "10px" },
{ offset: 0, left: "20px" },
{ offset: 0, left: "30px" },
@ -325,50 +369,72 @@ var gKeyframeSequenceTests = [
{ offset: 1, left: "50px" },
{ offset: 1, left: "60px" }],
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" },
{ offset: 0, computedOffset: 0, easing: "linear", left: "20px" },
{ offset: 0, computedOffset: 0, easing: "linear", left: "30px" },
{ offset: 1, computedOffset: 1, easing: "linear", left: "40px" },
{ offset: 1, computedOffset: 1, easing: "linear", left: "60px" }] },
{ desc: "a two property four Keyframe sequence",
{ offset: 1, computedOffset: 1, easing: "linear", left: "50px" },
{ offset: 1, computedOffset: 1, easing: "linear", left: "60px" }]
},
{ desc: "a two property four keyframe sequence",
input: [{ offset: 0, left: "10px" },
{ offset: 0, top: "20px" },
{ offset: 1, top: "30px" },
{ offset: 1, left: "40px" }],
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px", top: "20px" },
{ offset: 1, computedOffset: 1, easing: "linear", left: "40px", top: "30px" }] },
{ desc: "a one property Keyframe sequence with some omitted offsets",
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" },
{ offset: 0, computedOffset: 0, easing: "linear", top: "20px" },
{ offset: 1, computedOffset: 1, easing: "linear", top: "30px" },
{ offset: 1, computedOffset: 1, easing: "linear", left: "40px" }]
},
{ desc: "a one property keyframe sequence with some omitted offsets",
input: [{ offset: 0.00, left: "10px" },
{ offset: 0.25, left: "20px" },
{ left: "30px" },
{ left: "40px" },
{ offset: 1.00, left: "50px" }],
output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", left: "10px" },
{ offset: 0.25, computedOffset: 0.25, easing: "linear", left: "20px" },
{ offset: 0.50, computedOffset: 0.50, easing: "linear", left: "30px" },
{ offset: 0.75, computedOffset: 0.75, easing: "linear", left: "40px" },
{ offset: 1.00, computedOffset: 1.00, easing: "linear", left: "50px" }] },
{ desc: "a two property Keyframe sequence with some omitted offsets",
output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear",
left: "10px" },
{ offset: 0.25, computedOffset: 0.25, easing: "linear",
left: "20px" },
{ offset: null, computedOffset: 0.50, easing: "linear",
left: "30px" },
{ offset: null, computedOffset: 0.75, easing: "linear",
left: "40px" },
{ offset: 1.00, computedOffset: 1.00, easing: "linear",
left: "50px" }] },
{ desc: "a two property keyframe sequence with some omitted offsets",
input: [{ offset: 0.00, left: "10px", top: "20px" },
{ offset: 0.25, left: "30px" },
{ left: "40px" },
{ left: "50px", top: "60px" },
{ offset: 1.00, left: "70px", top: "80px" }],
output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", left: "10px", top: "20px" },
{ offset: 0.25, computedOffset: 0.25, easing: "linear", left: "30px" },
{ offset: 0.50, computedOffset: 0.50, easing: "linear", left: "40px" },
{ offset: 0.75, computedOffset: 0.75, easing: "linear", left: "50px", top: "60px" },
{ offset: 1.00, computedOffset: 1.00, easing: "linear", left: "70px", top: "80px" }] },
{ desc: "a one property Keyframe sequence with all omitted offsets",
output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear",
left: "10px", top: "20px" },
{ offset: 0.25, computedOffset: 0.25, easing: "linear",
left: "30px" },
{ offset: null, computedOffset: 0.50, easing: "linear",
left: "40px" },
{ offset: null, computedOffset: 0.75, easing: "linear",
left: "50px", top: "60px" },
{ offset: 1.00, computedOffset: 1.00, easing: "linear",
left: "70px", top: "80px" }] },
{ desc: "a one property keyframe sequence with all omitted offsets",
input: [{ left: "10px" },
{ left: "20px" },
{ left: "30px" },
{ left: "40px" },
{ left: "50px" }],
output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", left: "10px" },
{ offset: 0.25, computedOffset: 0.25, easing: "linear", left: "20px" },
{ offset: 0.50, computedOffset: 0.50, easing: "linear", left: "30px" },
{ offset: 0.75, computedOffset: 0.75, easing: "linear", left: "40px" },
{ offset: 1.00, computedOffset: 1.00, easing: "linear", left: "50px" }] },
{ desc: "a Keyframe sequence with different easing values, but the same easing value for a given offset",
output: [{ offset: null, computedOffset: 0.00, easing: "linear",
left: "10px" },
{ offset: null, computedOffset: 0.25, easing: "linear",
left: "20px" },
{ offset: null, computedOffset: 0.50, easing: "linear",
left: "30px" },
{ offset: null, computedOffset: 0.75, easing: "linear",
left: "40px" },
{ offset: null, computedOffset: 1.00, easing: "linear",
left: "50px" }] },
{ desc: "a keyframe sequence with different easing values, but the same"
+ " easing value for a given offset",
input: [{ offset: 0.0, easing: "ease", left: "10px"},
{ offset: 0.0, easing: "ease", top: "20px"},
{ offset: 0.5, easing: "linear", left: "30px" },
@ -376,62 +442,79 @@ var gKeyframeSequenceTests = [
{ offset: 1.0, easing: "step-end", left: "50px" },
{ offset: 1.0, easing: "step-end", top: "60px" }],
output: [{ offset: 0.0, computedOffset: 0.0, easing: "ease",
left: "10px", top: "20px" },
left: "10px" },
{ offset: 0.0, computedOffset: 0.0, easing: "ease",
top: "20px" },
{ offset: 0.5, computedOffset: 0.5, easing: "linear",
left: "30px", top: "40px" },
{ offset: 1.0, computedOffset: 1.0, easing: "linear",
left: "50px", top: "60px" }] },
{ desc: "a Keyframe sequence with different composite values, but the same composite value for a given offset",
left: "30px" },
{ offset: 0.5, computedOffset: 0.5, easing: "linear",
top: "40px" },
{ offset: 1.0, computedOffset: 1.0, easing: "step-end",
left: "50px" },
{ offset: 1.0, computedOffset: 1.0, easing: "step-end",
top: "60px" }] },
{ desc: "a keyframe sequence with different composite values, but the"
+ " same composite value for a given offset",
input: [{ offset: 0.0, composite: "replace", left: "10px" },
{ offset: 0.0, composite: "replace", top: "20px" },
{ offset: 0.5, composite: "add", left: "30px" },
{ offset: 0.5, composite: "add", top: "40px" },
{ offset: 1.0, composite: "replace", left: "50px" },
{ offset: 1.0, composite: "replace", top: "60px" }],
output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear", composite: "replace", left: "10px", top: "20px" },
{ offset: 0.5, computedOffset: 0.5, easing: "linear", composite: "add", left: "30px", top: "40px" },
{ offset: 1.0, computedOffset: 1.0, easing: "linear", composite: "replace", left: "50px", top: "60px" }] },
{ desc: "a one property two Keyframe sequence that needs to stringify its values",
output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear",
composite: "replace", left: "10px" },
{ offset: 0.0, computedOffset: 0.0, easing: "linear",
composite: "replace", top: "20px" },
{ offset: 0.5, computedOffset: 0.0, easing: "linear",
composite: "add", left: "30px" },
{ offset: 0.5, computedOffset: 0.0, easing: "linear",
composite: "add", top: "40px" },
{ offset: 1.0, computedOffset: 1.0, easing: "linear",
composite: "replace", left: "50px" },
{ offset: 1.0, computedOffset: 1.0, easing: "linear",
composite: "replace", top: "60px" }] },
{ desc: "a one property two keyframe sequence that needs to stringify"
+ " its values",
input: [{ offset: 0, opacity: 0 },
{ offset: 1, opacity: 1 }],
output: [{ offset: 0, computedOffset: 0, easing: "linear", opacity: "0" },
{ offset: 1, computedOffset: 1, easing: "linear", opacity: "1" }] },
{ desc: "a Keyframe sequence where shorthand precedes longhand",
{ offset: 1, computedOffset: 1, easing: "linear", opacity: "1" }]
},
{ desc: "a keyframe sequence where shorthand precedes longhand",
input: [{ offset: 0, margin: "10px", marginRight: "20px" },
{ offset: 1, margin: "30px" }],
output: [{ offset: 0, computedOffset: 0, easing: "linear", marginBottom: "10px", marginLeft: "10px", marginRight: "20px", marginTop: "10px" },
{ offset: 1, computedOffset: 1, easing: "linear", marginBottom: "30px", marginLeft: "30px", marginRight: "30px", marginTop: "30px" }] },
{ desc: "a Keyframe sequence where longhand precedes shorthand",
output: [{ offset: 0, computedOffset: 0, easing: "linear",
margin: "10px", marginRight: "20px" },
{ offset: 1, computedOffset: 1, easing: "linear",
margin: "30px" }] },
{ desc: "a keyframe sequence where longhand precedes shorthand",
input: [{ offset: 0, marginRight: "20px", margin: "10px" },
{ offset: 1, margin: "30px" }],
output: [{ offset: 0, computedOffset: 0, easing: "linear", marginBottom: "10px", marginLeft: "10px", marginRight: "20px", marginTop: "10px" },
{ offset: 1, computedOffset: 1, easing: "linear", marginBottom: "30px", marginLeft: "30px", marginRight: "30px", marginTop: "30px" }] },
{ desc: "a Keyframe sequence where lesser shorthand precedes greater shorthand",
input: [{ offset: 0, borderLeft: "1px solid rgb(1, 2, 3)", border: "2px dotted rgb(4, 5, 6)" },
output: [{ offset: 0, computedOffset: 0, easing: "linear",
marginRight: "20px", margin: "10px" },
{ offset: 1, computedOffset: 1, easing: "linear",
margin: "30px" }] },
{ desc: "a keyframe sequence where lesser shorthand precedes greater"
+ " shorthand",
input: [{ offset: 0,
borderLeft: "1px solid rgb(1, 2, 3)",
border: "2px dotted rgb(4, 5, 6)" },
{ offset: 1, border: "3px dashed rgb(7, 8, 9)" }],
output: [{ offset: 0, computedOffset: 0, easing: "linear",
borderBottomColor: "rgb(4, 5, 6)", borderBottomWidth: "2px",
borderLeftColor: "rgb(1, 2, 3)", borderLeftWidth: "1px",
borderRightColor: "rgb(4, 5, 6)", borderRightWidth: "2px",
borderTopColor: "rgb(4, 5, 6)", borderTopWidth: "2px" },
borderLeft: "1px solid rgb(1, 2, 3)",
border: "2px dotted rgb(4, 5, 6)" },
{ offset: 1, computedOffset: 1, easing: "linear",
borderBottomColor: "rgb(7, 8, 9)", borderBottomWidth: "3px",
borderLeftColor: "rgb(7, 8, 9)", borderLeftWidth: "3px",
borderRightColor: "rgb(7, 8, 9)", borderRightWidth: "3px",
borderTopColor: "rgb(7, 8, 9)", borderTopWidth: "3px" }] },
{ desc: "a Keyframe sequence where greater shorthand precedes lesser shorthand",
input: [{ offset: 0, border: "2px dotted rgb(4, 5, 6)", borderLeft: "1px solid rgb(1, 2, 3)" },
border: "3px dashed rgb(7, 8, 9)" }] },
{ desc: "a keyframe sequence where greater shorthand precedes lesser"
+ " shorthand",
input: [{ offset: 0, border: "2px dotted rgb(4, 5, 6)",
borderLeft: "1px solid rgb(1, 2, 3)" },
{ offset: 1, border: "3px dashed rgb(7, 8, 9)" }],
output: [{ offset: 0, computedOffset: 0, easing: "linear",
borderBottomColor: "rgb(4, 5, 6)", borderBottomWidth: "2px",
borderLeftColor: "rgb(1, 2, 3)", borderLeftWidth: "1px",
borderRightColor: "rgb(4, 5, 6)", borderRightWidth: "2px",
borderTopColor: "rgb(4, 5, 6)", borderTopWidth: "2px" },
border: "2px dotted rgb(4, 5, 6)",
borderLeft: "1px solid rgb(1, 2, 3)" },
{ offset: 1, computedOffset: 1, easing: "linear",
borderBottomColor: "rgb(7, 8, 9)", borderBottomWidth: "3px",
borderLeftColor: "rgb(7, 8, 9)", borderLeftWidth: "3px",
borderRightColor: "rgb(7, 8, 9)", borderRightWidth: "3px",
borderTopColor: "rgb(7, 8, 9)", borderTopWidth: "3px" }] },
border: "3px dashed rgb(7, 8, 9)" }] },
];
gKeyframeSequenceTests.forEach(function(subtest) {
@ -468,7 +551,7 @@ gInvalidEasingInKeyframeSequenceTests.forEach(function(subtest) {
assert_throws(new TypeError, function() {
new KeyframeEffectReadOnly(target, subtest.input);
});
}, "Invalid easing [" + subtest.desc + "] in KeyframeSequence " +
}, "Invalid easing [" + subtest.desc + "] in keyframe sequence " +
"should be thrown");
});

Просмотреть файл

@ -749,13 +749,32 @@ class Dumper_Win32(Dumper):
result = file
ctypes.windll.kernel32.SetErrorMode(ctypes.c_uint(1))
(path, filename) = os.path.split(file)
if os.path.isdir(path):
lc_filename = filename.lower()
for f in os.listdir(path):
if f.lower() == lc_filename:
result = os.path.join(path, f)
break
if not isinstance(file, unicode):
file = unicode(file, sys.getfilesystemencoding())
handle = ctypes.windll.kernel32.CreateFileW(file,
# GENERIC_READ
0x80000000,
# FILE_SHARE_READ
1,
None,
# OPEN_EXISTING
3,
0,
None)
if handle != -1:
size = ctypes.windll.kernel32.GetFinalPathNameByHandleW(handle,
None,
0,
0)
buf = ctypes.create_unicode_buffer(size)
if ctypes.windll.kernel32.GetFinalPathNameByHandleW(handle,
buf,
size,
0) > 0:
# The return value of GetFinalPathNameByHandleW uses the
# '\\?\' prefix.
result = buf.value.encode(sys.getfilesystemencoding())[4:]
ctypes.windll.kernel32.CloseHandle(handle)
# Cache the corrected version to avoid future filesystem hits.
self.fixedFilenameCaseCache[file] = result

Просмотреть файл

@ -64,12 +64,15 @@ class HelperMixin(object):
symbolstore.srcdirRepoInfo = {}
symbolstore.vcsFileInfoCache = {}
def make_dirs(self, f):
d = os.path.dirname(f)
if d and not os.path.exists(d):
os.makedirs(d)
def add_test_files(self, files):
for f in files:
f = os.path.join(self.test_dir, f)
d = os.path.dirname(f)
if d and not os.path.exists(d):
os.makedirs(d)
self.make_dirs(f)
writer(f)
class TestSizeOrder(HelperMixin, unittest.TestCase):
@ -288,6 +291,31 @@ class TestRepoManifest(HelperMixin, unittest.TestCase):
symbolstore.GetVCSFilename(file3, d.srcdirs)[0])
if platform.system() in ("Windows", "Microsoft"):
class TestFixFilenameCase(HelperMixin, unittest.TestCase):
def test_fix_filename_case(self):
# self.test_dir is going to be 8.3 paths...
junk = os.path.join(self.test_dir, 'x')
with open(junk, 'wb') as o:
o.write('x')
d = symbolstore.Dumper_Win32(dump_syms='dump_syms',
symbol_path=self.test_dir)
fixed_dir = os.path.dirname(d.FixFilenameCase(junk))
files = [
'one\\two.c',
'three\\Four.d',
'Five\\Six.e',
'seven\\Eight\\nine.F',
]
for rel_path in files:
full_path = os.path.normpath(os.path.join(self.test_dir,
rel_path))
self.make_dirs(full_path)
with open(full_path, 'wb') as o:
o.write('x')
fixed_path = d.FixFilenameCase(full_path.lower())
fixed_path = os.path.relpath(fixed_path, fixed_dir)
self.assertEqual(rel_path, fixed_path)
class TestSourceServer(HelperMixin, unittest.TestCase):
@patch("subprocess.call")
@patch("subprocess.Popen")

Просмотреть файл

@ -477,6 +477,7 @@ html|a:hover:active,
html|input[type="checkbox"] {
opacity: 0;
width: 0;
pointer-events: none;
position: absolute;
}

Просмотреть файл

@ -402,7 +402,7 @@ OSXNotificationCenter::ShowAlertWithIconData(nsIAlertNotification* aAlert,
rv = il->LoadImage(imageUri, nullptr, nullptr,
mozilla::net::RP_Default,
principal, nullptr,
this, nullptr,
this, nullptr, nullptr,
inPrivateBrowsing ? nsIRequest::LOAD_ANONYMOUS :
nsIRequest::LOAD_NORMAL,
nullptr, nsIContentPolicy::TYPE_INTERNAL_IMAGE,

Просмотреть файл

@ -312,7 +312,7 @@ nsMenuItemIconX::LoadIcon(nsIURI* aIconURI)
nsresult rv = loader->LoadImage(aIconURI, nullptr, nullptr,
mozilla::net::RP_Default,
nullptr, loadGroup, this,
nullptr, nsIRequest::LOAD_NORMAL, nullptr,
nullptr, nullptr, nsIRequest::LOAD_NORMAL, nullptr,
nsIContentPolicy::TYPE_INTERNAL_IMAGE, EmptyString(),
getter_AddRefs(mIconRequest));
if (NS_FAILED(rv)) return rv;

Просмотреть файл

@ -902,9 +902,9 @@ static void DrawCellWithSnapping(NSCell *cell,
@end
static void
RenderWithCoreUILegacy(CGRect aRect, CGContextRef cgContext, NSDictionary* aOptions)
RenderWithCoreUILegacy(CGRect aRect, CGContextRef cgContext, NSDictionary* aOptions, bool aSkipAreaCheck)
{
if (aRect.size.width * aRect.size.height <= BITMAP_MAX_AREA) {
if (aSkipAreaCheck || (aRect.size.width * aRect.size.height <= BITMAP_MAX_AREA)) {
CUIRendererRef renderer = [NSWindow respondsToSelector:@selector(coreUIRenderer)]
? [NSWindow coreUIRenderer] : nil;
CUIDraw(renderer, aRect, cgContext, (CFDictionaryRef)aOptions, NULL);
@ -947,7 +947,7 @@ RenderWithCoreUI(CGRect aRect, CGContextRef cgContext, NSDictionary* aOptions)
[appearance _drawInRect:aRect context:cgContext options:aOptions];
} else {
// 10.9 and below
RenderWithCoreUILegacy(aRect, cgContext, aOptions);
RenderWithCoreUILegacy(aRect, cgContext, aOptions, false);
}
}
@ -2903,7 +2903,8 @@ nsNativeThemeCocoa::DrawWidgetBackground(nsRenderingContext* aContext,
[NSNumber numberWithBool:YES], @"indiconly",
[NSNumber numberWithBool:YES], @"kCUIThumbProportionKey",
[NSNumber numberWithBool:YES], @"is.flipped",
nil]);
nil],
true);
}
break;
case NS_THEME_SCROLLBAR_BUTTON_UP:
@ -2942,6 +2943,7 @@ nsNativeThemeCocoa::DrawWidgetBackground(nsRenderingContext* aContext,
}
}
}
const BOOL isOnTopOfDarkBackground = IsDarkBackground(aFrame);
RenderWithCoreUILegacy(macRect, cgContext,
[NSDictionary dictionaryWithObjectsAndKeys:
@ -2952,7 +2954,8 @@ nsNativeThemeCocoa::DrawWidgetBackground(nsRenderingContext* aContext,
[NSNumber numberWithBool:YES], @"noindicator",
[NSNumber numberWithBool:YES], @"kCUIThumbProportionKey",
[NSNumber numberWithBool:YES], @"is.flipped",
nil]);
nil],
true);
}
}
break;

Просмотреть файл

@ -944,7 +944,6 @@
#define MODULE NS_ERROR_MODULE_DOM_ANIM
ERROR(NS_ERROR_DOM_ANIM_MISSING_PROPS_ERR, FAILURE(1)),
ERROR(NS_ERROR_DOM_ANIM_NO_TARGET_ERR, FAILURE(2)),
ERROR(NS_ERROR_DOM_ANIM_TARGET_NOT_IN_DOC_ERR, FAILURE(3)),
#undef MODULE
/* ======================================================================= */

Просмотреть файл

@ -79,7 +79,13 @@ public:
if (buf) {
mString = static_cast<char16_t*>(buf->Data());
} else {
buf = nsStringBuffer::Alloc((mLength + 1) * sizeof(char16_t));
const size_t size = (mLength + 1) * sizeof(char16_t);
buf = nsStringBuffer::Alloc(size);
if (MOZ_UNLIKELY(!buf)) {
// We OOM because atom allocations should be small and it's hard to
// handle them more gracefully in a constructor.
NS_ABORT_OOM(size);
}
mString = static_cast<char16_t*>(buf->Data());
CopyUnicodeTo(aString, 0, mString, mLength);
mString[mLength] = char16_t(0);

Просмотреть файл

@ -18,7 +18,9 @@
#include "nsCOMPtr.h"
#include "nsAutoPtr.h"
#include "mozilla/Atomics.h"
#include "mozilla/IndexSequence.h"
#include "mozilla/Likely.h"
#include "mozilla/Tuple.h"
#include "mozilla/TypeTraits.h"
//-----------------------------------------------------------------------------
@ -369,7 +371,7 @@ struct StoreCopyPassByValue
typedef T passed_type;
stored_type m;
template <typename A>
explicit StoreCopyPassByValue(A&& a) : m(mozilla::Forward<A>(a)) {}
MOZ_IMPLICIT StoreCopyPassByValue(A&& a) : m(mozilla::Forward<A>(a)) {}
passed_type PassAsParameter() { return m; }
};
template<typename S>
@ -383,7 +385,7 @@ struct StoreCopyPassByConstLRef
typedef const T& passed_type;
stored_type m;
template <typename A>
explicit StoreCopyPassByConstLRef(A&& a) : m(mozilla::Forward<A>(a)) {}
MOZ_IMPLICIT StoreCopyPassByConstLRef(A&& a) : m(mozilla::Forward<A>(a)) {}
passed_type PassAsParameter() { return m; }
};
template<typename S>
@ -397,7 +399,7 @@ struct StoreCopyPassByLRef
typedef T& passed_type;
stored_type m;
template <typename A>
explicit StoreCopyPassByLRef(A&& a) : m(mozilla::Forward<A>(a)) {}
MOZ_IMPLICIT StoreCopyPassByLRef(A&& a) : m(mozilla::Forward<A>(a)) {}
passed_type PassAsParameter() { return m; }
};
template<typename S>
@ -411,7 +413,7 @@ struct StoreCopyPassByRRef
typedef T&& passed_type;
stored_type m;
template <typename A>
explicit StoreCopyPassByRRef(A&& a) : m(mozilla::Forward<A>(a)) {}
MOZ_IMPLICIT StoreCopyPassByRRef(A&& a) : m(mozilla::Forward<A>(a)) {}
passed_type PassAsParameter() { return mozilla::Move(m); }
};
template<typename S>
@ -425,7 +427,7 @@ struct StoreRefPassByLRef
typedef T& passed_type;
stored_type m;
template <typename A>
explicit StoreRefPassByLRef(A& a) : m(a) {}
MOZ_IMPLICIT StoreRefPassByLRef(A& a) : m(a) {}
passed_type PassAsParameter() { return m; }
};
template<typename S>
@ -439,7 +441,7 @@ struct StoreConstRefPassByConstLRef
typedef const T& passed_type;
stored_type m;
template <typename A>
explicit StoreConstRefPassByConstLRef(const A& a) : m(a) {}
MOZ_IMPLICIT StoreConstRefPassByConstLRef(const A& a) : m(a) {}
passed_type PassAsParameter() { return m; }
};
template<typename S>
@ -453,7 +455,7 @@ struct StorensRefPtrPassByPtr
typedef T* passed_type;
stored_type m;
template <typename A>
explicit StorensRefPtrPassByPtr(A&& a) : m(mozilla::Forward<A>(a)) {}
MOZ_IMPLICIT StorensRefPtrPassByPtr(A&& a) : m(mozilla::Forward<A>(a)) {}
passed_type PassAsParameter() { return m.get(); }
};
template<typename S>
@ -467,7 +469,7 @@ struct StorePtrPassByPtr
typedef T* passed_type;
stored_type m;
template <typename A>
explicit StorePtrPassByPtr(A a) : m(a) {}
MOZ_IMPLICIT StorePtrPassByPtr(A a) : m(a) {}
passed_type PassAsParameter() { return m; }
};
template<typename S>
@ -481,7 +483,7 @@ struct StoreConstPtrPassByConstPtr
typedef const T* passed_type;
stored_type m;
template <typename A>
explicit StoreConstPtrPassByConstPtr(A a) : m(a) {}
MOZ_IMPLICIT StoreConstPtrPassByConstPtr(A a) : m(a) {}
passed_type PassAsParameter() { return m; }
};
template<typename S>
@ -495,7 +497,7 @@ struct StoreCopyPassByConstPtr
typedef const T* passed_type;
stored_type m;
template <typename A>
explicit StoreCopyPassByConstPtr(A&& a) : m(mozilla::Forward<A>(a)) {}
MOZ_IMPLICIT StoreCopyPassByConstPtr(A&& a) : m(mozilla::Forward<A>(a)) {}
passed_type PassAsParameter() { return &m; }
};
template<typename S>
@ -509,7 +511,7 @@ struct StoreCopyPassByPtr
typedef T* passed_type;
stored_type m;
template <typename A>
explicit StoreCopyPassByPtr(A&& a) : m(mozilla::Forward<A>(a)) {}
MOZ_IMPLICIT StoreCopyPassByPtr(A&& a) : m(mozilla::Forward<A>(a)) {}
passed_type PassAsParameter() { return &m; }
};
template<typename S>
@ -651,196 +653,28 @@ struct ParameterStorage
} /* namespace detail */
// struct used to store arguments and later apply them to a method.
template <typename... Ts> struct nsRunnableMethodArguments;
// Specializations for 0-8 arguments, add more as required.
// TODO Use tuple instead; And/or use lambdas (see bug 1152753)
template <>
struct nsRunnableMethodArguments<>
template <typename... Ts>
struct nsRunnableMethodArguments
{
template<class C, typename M> void apply(C* o, M m)
{
((*o).*m)();
}
};
template <typename T0>
struct nsRunnableMethodArguments<T0>
{
typename ::detail::ParameterStorage<T0>::Type m0;
template<typename A0>
explicit nsRunnableMethodArguments(A0&& a0)
: m0(mozilla::Forward<A0>(a0))
mozilla::Tuple<typename ::detail::ParameterStorage<Ts>::Type...> mArguments;
template <typename... As>
explicit nsRunnableMethodArguments(As&&... aArguments)
: mArguments(mozilla::Forward<As>(aArguments)...)
{}
template<class C, typename M> void apply(C* o, M m)
template<typename C, typename M, typename... Args, size_t... Indices>
static auto
applyImpl(C* o, M m, mozilla::Tuple<Args...>& args,
mozilla::IndexSequence<Indices...>)
-> decltype(((*o).*m)(mozilla::Get<Indices>(args).PassAsParameter()...))
{
((*o).*m)(m0.PassAsParameter());
return ((*o).*m)(mozilla::Get<Indices>(args).PassAsParameter()...);
}
};
template <typename T0, typename T1>
struct nsRunnableMethodArguments<T0, T1>
{
typename ::detail::ParameterStorage<T0>::Type m0;
typename ::detail::ParameterStorage<T1>::Type m1;
template<typename A0, typename A1>
nsRunnableMethodArguments(A0&& a0, A1&& a1)
: m0(mozilla::Forward<A0>(a0))
, m1(mozilla::Forward<A1>(a1))
{}
template<class C, typename M> void apply(C* o, M m)
template<class C, typename M> auto apply(C* o, M m)
-> decltype(applyImpl(o, m, mArguments,
typename mozilla::IndexSequenceFor<Ts...>::Type()))
{
((*o).*m)(m0.PassAsParameter(), m1.PassAsParameter());
}
};
template <typename T0, typename T1, typename T2>
struct nsRunnableMethodArguments<T0, T1, T2>
{
typename ::detail::ParameterStorage<T0>::Type m0;
typename ::detail::ParameterStorage<T1>::Type m1;
typename ::detail::ParameterStorage<T2>::Type m2;
template<typename A0, typename A1, typename A2>
nsRunnableMethodArguments(A0&& a0, A1&& a1, A2&& a2)
: m0(mozilla::Forward<A0>(a0))
, m1(mozilla::Forward<A1>(a1))
, m2(mozilla::Forward<A2>(a2))
{}
template<class C, typename M> void apply(C* o, M m)
{
((*o).*m)(m0.PassAsParameter(), m1.PassAsParameter(), m2.PassAsParameter());
}
};
template <typename T0, typename T1, typename T2, typename T3>
struct nsRunnableMethodArguments<T0, T1, T2, T3>
{
typename ::detail::ParameterStorage<T0>::Type m0;
typename ::detail::ParameterStorage<T1>::Type m1;
typename ::detail::ParameterStorage<T2>::Type m2;
typename ::detail::ParameterStorage<T3>::Type m3;
template<typename A0, typename A1, typename A2, typename A3>
nsRunnableMethodArguments(A0&& a0, A1&& a1, A2&& a2, A3&& a3)
: m0(mozilla::Forward<A0>(a0))
, m1(mozilla::Forward<A1>(a1))
, m2(mozilla::Forward<A2>(a2))
, m3(mozilla::Forward<A3>(a3))
{}
template<class C, typename M> void apply(C* o, M m)
{
((*o).*m)(m0.PassAsParameter(), m1.PassAsParameter(),
m2.PassAsParameter(), m3.PassAsParameter());
}
};
template <typename T0, typename T1, typename T2, typename T3, typename T4>
struct nsRunnableMethodArguments<T0, T1, T2, T3, T4>
{
typename ::detail::ParameterStorage<T0>::Type m0;
typename ::detail::ParameterStorage<T1>::Type m1;
typename ::detail::ParameterStorage<T2>::Type m2;
typename ::detail::ParameterStorage<T3>::Type m3;
typename ::detail::ParameterStorage<T4>::Type m4;
template<typename A0, typename A1, typename A2, typename A3, typename A4>
nsRunnableMethodArguments(A0&& a0, A1&& a1, A2&& a2, A3&& a3, A4&& a4)
: m0(mozilla::Forward<A0>(a0))
, m1(mozilla::Forward<A1>(a1))
, m2(mozilla::Forward<A2>(a2))
, m3(mozilla::Forward<A3>(a3))
, m4(mozilla::Forward<A4>(a4))
{}
template<class C, typename M> void apply(C* o, M m)
{
((*o).*m)(m0.PassAsParameter(), m1.PassAsParameter(),
m2.PassAsParameter(), m3.PassAsParameter(),
m4.PassAsParameter());
}
};
template <typename T0, typename T1, typename T2, typename T3, typename T4,
typename T5>
struct nsRunnableMethodArguments<T0, T1, T2, T3, T4, T5>
{
typename ::detail::ParameterStorage<T0>::Type m0;
typename ::detail::ParameterStorage<T1>::Type m1;
typename ::detail::ParameterStorage<T2>::Type m2;
typename ::detail::ParameterStorage<T3>::Type m3;
typename ::detail::ParameterStorage<T4>::Type m4;
typename ::detail::ParameterStorage<T5>::Type m5;
template<typename A0, typename A1, typename A2, typename A3, typename A4,
typename A5>
nsRunnableMethodArguments(A0&& a0, A1&& a1, A2&& a2, A3&& a3, A4&& a4,
A5&& a5)
: m0(mozilla::Forward<A0>(a0))
, m1(mozilla::Forward<A1>(a1))
, m2(mozilla::Forward<A2>(a2))
, m3(mozilla::Forward<A3>(a3))
, m4(mozilla::Forward<A4>(a4))
, m5(mozilla::Forward<A5>(a5))
{}
template<class C, typename M> void apply(C* o, M m)
{
((*o).*m)(m0.PassAsParameter(), m1.PassAsParameter(),
m2.PassAsParameter(), m3.PassAsParameter(),
m4.PassAsParameter(), m5.PassAsParameter());
}
};
template <typename T0, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6>
struct nsRunnableMethodArguments<T0, T1, T2, T3, T4, T5, T6>
{
typename ::detail::ParameterStorage<T0>::Type m0;
typename ::detail::ParameterStorage<T1>::Type m1;
typename ::detail::ParameterStorage<T2>::Type m2;
typename ::detail::ParameterStorage<T3>::Type m3;
typename ::detail::ParameterStorage<T4>::Type m4;
typename ::detail::ParameterStorage<T5>::Type m5;
typename ::detail::ParameterStorage<T6>::Type m6;
template<typename A0, typename A1, typename A2, typename A3, typename A4,
typename A5, typename A6>
nsRunnableMethodArguments(A0&& a0, A1&& a1, A2&& a2, A3&& a3, A4&& a4,
A5&& a5, A6&& a6)
: m0(mozilla::Forward<A0>(a0))
, m1(mozilla::Forward<A1>(a1))
, m2(mozilla::Forward<A2>(a2))
, m3(mozilla::Forward<A3>(a3))
, m4(mozilla::Forward<A4>(a4))
, m5(mozilla::Forward<A5>(a5))
, m6(mozilla::Forward<A6>(a6))
{}
template<class C, typename M> void apply(C* o, M m)
{
((*o).*m)(m0.PassAsParameter(), m1.PassAsParameter(),
m2.PassAsParameter(), m3.PassAsParameter(),
m4.PassAsParameter(), m5.PassAsParameter(),
m6.PassAsParameter());
}
};
template <typename T0, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7>
struct nsRunnableMethodArguments<T0, T1, T2, T3, T4, T5, T6, T7>
{
typename ::detail::ParameterStorage<T0>::Type m0;
typename ::detail::ParameterStorage<T1>::Type m1;
typename ::detail::ParameterStorage<T2>::Type m2;
typename ::detail::ParameterStorage<T3>::Type m3;
typename ::detail::ParameterStorage<T4>::Type m4;
typename ::detail::ParameterStorage<T5>::Type m5;
typename ::detail::ParameterStorage<T6>::Type m6;
typename ::detail::ParameterStorage<T7>::Type m7;
template<typename A0, typename A1, typename A2, typename A3, typename A4,
typename A5, typename A6, typename A7>
nsRunnableMethodArguments(A0&& a0, A1&& a1, A2&& a2, A3&& a3, A4&& a4,
A5&& a5, A6&& a6, A7&& a7)
: m0(mozilla::Forward<A0>(a0))
, m1(mozilla::Forward<A1>(a1))
, m2(mozilla::Forward<A2>(a2))
, m3(mozilla::Forward<A3>(a3))
, m4(mozilla::Forward<A4>(a4))
, m5(mozilla::Forward<A5>(a5))
, m6(mozilla::Forward<A6>(a6))
, m7(mozilla::Forward<A7>(a7))
{}
template<class C, typename M> void apply(C* o, M m)
{
((*o).*m)(m0.PassAsParameter(), m1.PassAsParameter(),
m2.PassAsParameter(), m3.PassAsParameter(),
m4.PassAsParameter(), m5.PassAsParameter(),
m6.PassAsParameter(), m7.PassAsParameter());
return applyImpl(o, m, mArguments,
typename mozilla::IndexSequenceFor<Ts...>::Type());
}
};