зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to central, a=merge
MozReview-Commit-ID: 87zaFE5GN5Y
This commit is contained in:
Коммит
4db4931366
|
@ -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());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче