author | L. David Baron <dbaron@dbaron.org> |
Mon, 11 Apr 2011 23:18:43 -0700 | |
changeset 67979 | f8dba37f47618e7d652aa1837faa408cc7878b45 |
parent 67978 | 2597d6ff2793ec4c9335a9953d382b7913bfff99 |
child 67980 | 23d79d8f5eda84afe7caf167bd48ac8e030245fe |
push id | 1 |
push user | root |
push date | Tue, 26 Apr 2011 22:38:44 +0000 |
treeherder | mozilla-beta@bfdb6e623a36 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | bzbarsky |
bugs | 435442 |
milestone | 2.2a1pre |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -322,16 +322,18 @@ #include "nsIDOMProgressEvent.h" #include "nsIDOMNSUIEvent.h" #include "nsIDOMCSS2Properties.h" #include "nsIDOMCSSCharsetRule.h" #include "nsIDOMCSSImportRule.h" #include "nsIDOMCSSMediaRule.h" #include "nsIDOMCSSFontFaceRule.h" #include "nsIDOMCSSMozDocumentRule.h" +#include "nsIDOMMozCSSKeyframeRule.h" +#include "nsIDOMMozCSSKeyframesRule.h" #include "nsIDOMCSSPrimitiveValue.h" #include "nsIDOMCSSStyleRule.h" #include "nsIDOMCSSStyleSheet.h" #include "nsDOMCSSValueList.h" #include "nsIDOMOrientationEvent.h" #include "nsIDOMRange.h" #include "nsIDOMNSRange.h" #include "nsIDOMRangeException.h" @@ -1477,16 +1479,21 @@ static nsDOMClassInfoData sClassInfoData DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(IDBVersionChangeRequest, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(IDBDatabaseException, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(EventException, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) + + NS_DEFINE_CLASSINFO_DATA(MozCSSKeyframeRule, nsDOMGenericSH, + DOM_DEFAULT_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(MozCSSKeyframesRule, nsDOMGenericSH, + DOM_DEFAULT_SCRIPTABLE_FLAGS) }; // Objects that should be constructable through |new Name();| struct nsContractIDMapData { PRInt32 mDOMClassInfoID; const char *mContractID; }; @@ -4209,16 +4216,24 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_ENTRY(nsIException) DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_BEGIN(EventException, nsIDOMEventException) DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventException) DOM_CLASSINFO_MAP_ENTRY(nsIException) DOM_CLASSINFO_MAP_END + DOM_CLASSINFO_MAP_BEGIN(MozCSSKeyframeRule, nsIDOMMozCSSKeyframeRule) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozCSSKeyframeRule) + DOM_CLASSINFO_MAP_END + + DOM_CLASSINFO_MAP_BEGIN(MozCSSKeyframesRule, nsIDOMMozCSSKeyframesRule) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozCSSKeyframesRule) + DOM_CLASSINFO_MAP_END + #ifdef NS_DEBUG { PRUint32 i = NS_ARRAY_LENGTH(sClassInfoData); if (i != eDOMClassInfoIDCount) { NS_ERROR("The number of items in sClassInfoData doesn't match the " "number of nsIDOMClassInfo ID's, this is bad! Fix it!");
--- a/dom/base/nsDOMClassInfoClasses.h +++ b/dom/base/nsDOMClassInfoClasses.h @@ -502,8 +502,11 @@ DOMCI_CLASS(IDBCursor) DOMCI_CLASS(IDBCursorWithValue) DOMCI_CLASS(IDBKeyRange) DOMCI_CLASS(IDBIndex) DOMCI_CLASS(IDBVersionChangeEvent) DOMCI_CLASS(IDBVersionChangeRequest) DOMCI_CLASS(IDBDatabaseException) DOMCI_CLASS(EventException) + +DOMCI_CLASS(MozCSSKeyframeRule) +DOMCI_CLASS(MozCSSKeyframesRule)
--- a/dom/interfaces/base/domstubs.idl +++ b/dom/interfaces/base/domstubs.idl @@ -107,16 +107,17 @@ interface nsIDOMHTMLCollection; interface nsIDOMHTMLHeadElement; // CSS interface nsIDOMCSSValue; interface nsIDOMCSSValueList; interface nsIDOMCSSPrimitiveValue; interface nsIDOMCSSRule; interface nsIDOMCSSRuleList; +interface nsIDOMMozCSSKeyframeRule; interface nsIDOMCSSStyleSheet; interface nsIDOMCSSStyleDeclaration; interface nsIDOMCounter; interface nsIDOMRect; interface nsIDOMRGBColor; interface nsIDOMCSSStyleRule; interface nsIDOMCSSStyleRuleCollection; interface nsIDOMHTMLTableCaptionElement;
--- a/dom/interfaces/css/Makefile.in +++ b/dom/interfaces/css/Makefile.in @@ -59,16 +59,18 @@ SDK_XPIDLSRCS = \ XPIDLSRCS = \ nsIDOMCSS2Properties.idl \ nsIDOMCSSCharsetRule.idl \ nsIDOMCSSFontFaceRule.idl \ nsIDOMCSSImportRule.idl \ nsIDOMCSSMediaRule.idl \ nsIDOMCSSMozDocumentRule.idl \ + nsIDOMMozCSSKeyframeRule.idl \ + nsIDOMMozCSSKeyframesRule.idl \ nsIDOMCSSPageRule.idl \ nsIDOMCSSStyleRule.idl \ nsIDOMCSSUnknownRule.idl \ nsIDOMCounter.idl \ nsIDOMDocumentCSS.idl \ nsIDOMRGBColor.idl \ nsIDOMRect.idl \ nsIDOMViewCSS.idl \
--- a/dom/interfaces/css/nsIDOMCSSRule.idl +++ b/dom/interfaces/css/nsIDOMCSSRule.idl @@ -42,27 +42,29 @@ /** * The nsIDOMCSSRule interface is a datatype for a CSS style rule in * the Document Object Model. * * For more information on this interface please see * http://www.w3.org/TR/DOM-Level-2-Style */ -[scriptable, uuid(a6cf90c1-15b3-11d2-932e-00805f8add32)] +[scriptable, uuid(2938307a-9d70-4b63-8afc-0197e82318ad)] interface nsIDOMCSSRule : nsISupports { // RuleType const unsigned short UNKNOWN_RULE = 0; const unsigned short STYLE_RULE = 1; const unsigned short CHARSET_RULE = 2; const unsigned short IMPORT_RULE = 3; const unsigned short MEDIA_RULE = 4; const unsigned short FONT_FACE_RULE = 5; const unsigned short PAGE_RULE = 6; + const unsigned short MOZ_KEYFRAMES_RULE = 7; + const unsigned short MOZ_KEYFRAME_RULE = 8; readonly attribute unsigned short type; attribute DOMString cssText; // raises(DOMException) on setting readonly attribute nsIDOMCSSStyleSheet parentStyleSheet; readonly attribute nsIDOMCSSRule parentRule; };
new file mode 100644 --- /dev/null +++ b/dom/interfaces/css/nsIDOMMozCSSKeyframeRule.idl @@ -0,0 +1,45 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is code for css3-animations. + * + * The Initial Developer of the Original Code is the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * L. David Baron <dbaron@dbaron.org>, Mozilla Corporation (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsIDOMCSSRule.idl" + +[scriptable, uuid(38a19612-dc58-414a-954c-233183808484)] +interface nsIDOMMozCSSKeyframeRule : nsIDOMCSSRule +{ + attribute DOMString keyText; + readonly attribute nsIDOMCSSStyleDeclaration style; +};
new file mode 100644 --- /dev/null +++ b/dom/interfaces/css/nsIDOMMozCSSKeyframesRule.idl @@ -0,0 +1,49 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is code for css3-animations. + * + * The Initial Developer of the Original Code is the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * L. David Baron <dbaron@dbaron.org>, Mozilla Corporation (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsIDOMCSSRule.idl" + +[scriptable, uuid(aa4ea11f-791b-4671-b192-b931e6539669)] +interface nsIDOMMozCSSKeyframesRule : nsIDOMCSSRule +{ + attribute DOMString name; + readonly attribute nsIDOMCSSRuleList cssRules; + + void insertRule(in DOMString rule); + void deleteRule(in DOMString key); + nsIDOMMozCSSKeyframeRule findRule(in DOMString key); +};
--- a/dom/locales/en-US/chrome/layout/css.properties +++ b/dom/locales/en-US/chrome/layout/css.properties @@ -55,19 +55,23 @@ PEImportNotURI=Expected URI in @import r PEImportBadURI=Invalid URI in @import rule: '%1$S'. PEImportUnexpected=Found unexpected '%1$S' within @import. PEGroupRuleEOF=end of @media or @-moz-document rule PEMozDocRuleBadFunc=Expected url(), url-prefix(), or domain() in @-moz-document rule but found '%1$S'. PEMozDocRuleNotURI=Expected URI in @-moz-document rule but found '%1$S'. PEAtNSPrefixEOF=namespace prefix in @namespace rule PEAtNSURIEOF=namespace URI in @namespace rule PEAtNSUnexpected=Unexpected token within @namespace: '%1$S'. +PEKeyframeNameEOF=name of @keyframes rule. +PEKeyframeBadName=Expected identifier for name of @keyframes rule. +PEKeyframeBrace=Expected opening { of @keyframes rule. PESkipDeclBraceEOF=closing } of declaration block PESkipRSBraceEOF=closing } of invalid rule set PEBadSelectorRSIgnored=Ruleset ignored due to bad selector. +PEBadSelectorKeyframeRuleIgnored=Keyframe rule ignored due to bad selector. PESelectorListExtraEOF=',' or '{' PESelectorListExtra=Expected ',' or '{' but found '%1$S'. PESelectorGroupNoSelector=Selector expected. PESelectorGroupExtraCombinator=Dangling combinator. PEClassSelEOF=class name PEClassSelNotIdent=Expected identifier for class selector but found '%1$S'. PETypeSelEOF=element type PETypeSelNotType=Expected element name or '*' but found '%1$S'. @@ -133,9 +137,9 @@ PEUnknownFontDesc=Unknown descriptor '%1 PEMQExpectedExpressionStart=Expected '(' to start media query expression but found '%1$S'. PEMQExpressionEOF=contents of media query expression PEMQExpectedFeatureName=Expected media feature name but found '%1$S'. PEMQExpectedFeatureNameEnd=Expected ':' or ')' after media feature name but found '%1$S'. PEMQNoMinMaxWithoutValue=Media features with min- or max- must have a value. PEMQExpectedFeatureValue=Found invalid value for media feature. PEBadFontBlockStart=Expected '{' to begin @font-face rule but found '%1$S'. PEBadFontBlockEnd=Expected '}' to end @font-face rule but found '%1$S'. -PEAnonBoxNotAlone=Did not expect anonymous box. \ No newline at end of file +PEAnonBoxNotAlone=Did not expect anonymous box.
--- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -249,16 +249,26 @@ public: PRUint32 aLineNumber, // for error reporting nscolor* aColor); nsresult ParseSelectorString(const nsSubstring& aSelectorString, nsIURI* aURL, // for error reporting PRUint32 aLineNumber, // for error reporting nsCSSSelectorList **aSelectorList); + already_AddRefed<nsCSSKeyframeRule> + ParseKeyframeRule(const nsSubstring& aBuffer, + nsIURI* aURL, + PRUint32 aLineNumber); + + bool ParseKeyframeSelectorString(const nsSubstring& aSelectorString, + nsIURI* aURL, // for error reporting + PRUint32 aLineNumber, // for error reporting + nsTArray<float>& aSelectorList); + protected: class nsAutoParseCompoundProperty; friend class nsAutoParseCompoundProperty; void AppendRule(nsICSSRule* aRule); friend void AppendRuleToSheet(nsICSSRule*, void*); // calls AppendRule /** @@ -352,16 +362,19 @@ protected: void* aProcessData); PRBool ParseFontFaceRule(RuleAppendFunc aAppendFunc, void* aProcessData); PRBool ParseFontDescriptor(nsCSSFontFaceRule* aRule); PRBool ParseFontDescriptorValue(nsCSSFontDesc aDescID, nsCSSValue& aValue); PRBool ParsePageRule(RuleAppendFunc aAppendFunc, void* aProcessData); + PRBool ParseKeyframesRule(RuleAppendFunc aAppendFunc, void* aProcessData); + already_AddRefed<nsCSSKeyframeRule> ParseKeyframeRule(); + PRBool ParseKeyframeSelectorList(nsTArray<float>& aSelectorList); enum nsSelectorParsingStatus { // we have parsed a selector and we saw a token that cannot be // part of a selector: eSelectorParsingStatus_Done, // we should continue parsing the selector: eSelectorParsingStatus_Continue, // we saw an unexpected token or token value, @@ -1295,16 +1308,66 @@ CSSParserImpl::ParseSelectorString(const NS_ASSERTION(!*aSelectorList, "Shouldn't have list!"); if (prefixErr) return NS_ERROR_DOM_NAMESPACE_ERR; return NS_ERROR_DOM_SYNTAX_ERR; } + +already_AddRefed<nsCSSKeyframeRule> +CSSParserImpl::ParseKeyframeRule(const nsSubstring& aBuffer, + nsIURI* aURI, + PRUint32 aLineNumber) +{ + InitScanner(aBuffer, aURI, aLineNumber, aURI, nsnull); + + AssertInitialState(); + + nsRefPtr<nsCSSKeyframeRule> result = ParseKeyframeRule(); + if (GetToken(PR_TRUE)) { + // extra garbage at the end + result = nsnull; + } + + OUTPUT_ERROR(); + ReleaseScanner(); + + return result.forget(); +} + +bool +CSSParserImpl::ParseKeyframeSelectorString(const nsSubstring& aSelectorString, + nsIURI* aURI, // for error reporting + PRUint32 aLineNumber, // for error reporting + nsTArray<float>& aSelectorList) +{ + NS_ABORT_IF_FALSE(aSelectorList.IsEmpty(), "given list should start empty"); + + InitScanner(aSelectorString, aURI, aLineNumber, aURI, nsnull); + + AssertInitialState(); + + bool success = ParseKeyframeSelectorList(aSelectorList) && + // must consume entire input string + !GetToken(PR_TRUE); + + OUTPUT_ERROR(); + ReleaseScanner(); + + if (success) { + NS_ASSERTION(!aSelectorList.IsEmpty(), "should not be empty"); + } else { + aSelectorList.Clear(); + } + + return success; +} + //---------------------------------------------------------------------- PRBool CSSParserImpl::GetToken(PRBool aSkipWS) { for (;;) { if (!mHavePushBack) { if (!mScanner.Next(mToken)) { @@ -1525,16 +1588,20 @@ CSSParserImpl::ParseAtRule(RuleAppendFun } else if (mToken.mIdent.LowerCaseEqualsLiteral("font-face")) { parseFunc = &CSSParserImpl::ParseFontFaceRule; newSection = eCSSSection_General; } else if (mToken.mIdent.LowerCaseEqualsLiteral("page")) { parseFunc = &CSSParserImpl::ParsePageRule; newSection = eCSSSection_General; + } else if (mToken.mIdent.LowerCaseEqualsLiteral("-moz-keyframes")) { + parseFunc = &CSSParserImpl::ParseKeyframesRule; + newSection = eCSSSection_General; + } else { if (!NonMozillaVendorIdentifier(mToken.mIdent)) { REPORT_UNEXPECTED_TOKEN(PEUnknownAtRule); OUTPUT_ERROR(); } // Skip over unsupported at rule, don't advance section return SkipAtRule(PR_FALSE); } @@ -2237,16 +2304,111 @@ CSSParserImpl::ParseFontDescriptor(nsCSS PRBool CSSParserImpl::ParsePageRule(RuleAppendFunc aAppendFunc, void* aData) { // XXX not yet implemented return PR_FALSE; } +PRBool +CSSParserImpl::ParseKeyframesRule(RuleAppendFunc aAppendFunc, void* aData) +{ + if (!GetToken(PR_TRUE)) { + REPORT_UNEXPECTED_EOF(PEKeyframeNameEOF); + return PR_FALSE; + } + + if (mToken.mType != eCSSToken_Ident) { + REPORT_UNEXPECTED_TOKEN(PEKeyframeBadName); + UngetToken(); + return PR_FALSE; + } + nsString name(mToken.mIdent); + + if (!ExpectSymbol('{', PR_TRUE)) { + REPORT_UNEXPECTED_TOKEN(PEKeyframeBrace); + return PR_FALSE; + } + + nsRefPtr<nsCSSKeyframesRule> rule = new nsCSSKeyframesRule(name); + + while (!ExpectSymbol('}', PR_TRUE)) { + nsRefPtr<nsCSSKeyframeRule> kid = ParseKeyframeRule(); + if (kid) { + rule->AppendStyleRule(kid); + } else { + OUTPUT_ERROR(); + SkipRuleSet(PR_TRUE); + } + } + + (*aAppendFunc)(rule, aData); + return PR_TRUE; +} + +already_AddRefed<nsCSSKeyframeRule> +CSSParserImpl::ParseKeyframeRule() +{ + nsTArray<float> selectorList; + if (!ParseKeyframeSelectorList(selectorList)) { + REPORT_UNEXPECTED(PEBadSelectorKeyframeRuleIgnored); + return nsnull; + } + + nsAutoPtr<css::Declaration> declaration(ParseDeclarationBlock(PR_TRUE)); + if (!declaration) { + REPORT_UNEXPECTED(PEBadSelectorKeyframeRuleIgnored); + return nsnull; + } + + // Takes ownership of declaration, and steals contents of selectorList. + nsRefPtr<nsCSSKeyframeRule> rule = + new nsCSSKeyframeRule(selectorList, declaration); + + return rule.forget(); +} + +PRBool +CSSParserImpl::ParseKeyframeSelectorList(nsTArray<float>& aSelectorList) +{ + for (;;) { + if (!GetToken(PR_TRUE)) { + // The first time through the loop, this means we got an empty + // list. Otherwise, it means we have a trailing comma. + return PR_FALSE; + } + float value; + switch (mToken.mType) { + case eCSSToken_Percentage: + value = mToken.mNumber; + break; + case eCSSToken_Ident: + if (mToken.mIdent.LowerCaseEqualsLiteral("from")) { + value = 0.0f; + break; + } + if (mToken.mIdent.LowerCaseEqualsLiteral("to")) { + value = 1.0f; + break; + } + // fall through + default: + UngetToken(); + // The first time through the loop, this means we got an empty + // list. Otherwise, it means we have a trailing comma. + return PR_FALSE; + } + aSelectorList.AppendElement(value); + if (!ExpectSymbol(',', PR_TRUE)) { + return PR_TRUE; + } + } +} + void CSSParserImpl::SkipUntil(PRUnichar aStopSymbol) { nsCSSToken* tk = &mToken; nsAutoTArray<PRUnichar, 16> stack; stack.AppendElement(aStopSymbol); for (;;) { if (!GetToken(PR_TRUE)) { @@ -2416,17 +2578,16 @@ CSSParserImpl::ParseRuleSet(RuleAppendFu return PR_FALSE; } NS_ASSERTION(nsnull != slist, "null selector list"); CLEAR_ERROR(); // Next parse the declaration block css::Declaration* declaration = ParseDeclarationBlock(PR_TRUE); if (nsnull == declaration) { - // XXX skip something here delete slist; return PR_FALSE; } #if 0 slist->Dump(); fputs("{\n", stdout); declaration->List(); @@ -8653,8 +8814,28 @@ nsresult nsCSSParser::ParseSelectorString(const nsSubstring& aSelectorString, nsIURI* aURI, PRUint32 aLineNumber, nsCSSSelectorList** aSelectorList) { return static_cast<CSSParserImpl*>(mImpl)-> ParseSelectorString(aSelectorString, aURI, aLineNumber, aSelectorList); } + +already_AddRefed<nsCSSKeyframeRule> +nsCSSParser::ParseKeyframeRule(const nsSubstring& aBuffer, + nsIURI* aURI, + PRUint32 aLineNumber) +{ + return static_cast<CSSParserImpl*>(mImpl)-> + ParseKeyframeRule(aBuffer, aURI, aLineNumber); +} + +bool +nsCSSParser::ParseKeyframeSelectorString(const nsSubstring& aSelectorString, + nsIURI* aURI, + PRUint32 aLineNumber, + nsTArray<float>& aSelectorList) +{ + return static_cast<CSSParserImpl*>(mImpl)-> + ParseKeyframeSelectorString(aSelectorString, aURI, aLineNumber, + aSelectorList); +}
--- a/layout/style/nsCSSParser.h +++ b/layout/style/nsCSSParser.h @@ -39,24 +39,26 @@ #ifndef nsCSSParser_h___ #define nsCSSParser_h___ #include "nsAString.h" #include "nsCSSProperty.h" #include "nsColor.h" #include "nsCOMArray.h" +#include "nsCOMPtr.h" class nsICSSRule; class nsCSSStyleSheet; class nsIPrincipal; class nsIURI; class nsIUnicharInputStream; struct nsCSSSelectorList; class nsMediaList; +class nsCSSKeyframeRule; namespace mozilla { namespace css { class Declaration; class Loader; class StyleRule; } } @@ -189,16 +191,34 @@ public: * Parse aBuffer into a selector list. On success, caller must * delete *aSelectorList when done with it. */ nsresult ParseSelectorString(const nsSubstring& aSelectorString, nsIURI* aURL, PRUint32 aLineNumber, nsCSSSelectorList** aSelectorList); + /* + * Parse a keyframe rule (which goes inside an @keyframes rule). + * Return it if the parse was successful. + */ + already_AddRefed<nsCSSKeyframeRule> + ParseKeyframeRule(const nsSubstring& aBuffer, + nsIURI* aURL, + PRUint32 aLineNumber); + + /* + * Parse a selector list for a keyframe rule. Return whether + * the parse succeeded. + */ + bool ParseKeyframeSelectorString(const nsSubstring& aSelectorString, + nsIURI* aURL, + PRUint32 aLineNumber, + nsTArray<float>& aSelectorList); + protected: // This is a CSSParserImpl*, but if we expose that type name in this // header, we can't put the type definition (in nsCSSParser.cpp) in // the anonymous namespace. void* mImpl; }; #endif /* nsCSSParser_h___ */
--- a/layout/style/nsCSSRules.cpp +++ b/layout/style/nsCSSRules.cpp @@ -57,16 +57,17 @@ #include "nsIDocument.h" #include "nsPresContext.h" #include "nsContentUtils.h" #include "nsStyleConsts.h" #include "nsDOMError.h" #include "nsStyleUtil.h" #include "mozilla/css/Declaration.h" +#include "nsCSSParser.h" #include "nsPrintfCString.h" namespace css = mozilla::css; #define IMPL_STYLE_RULE_INHERIT_GET_DOM_RULE_WEAK(class_, super_) \ nsIDOMCSSRule* class_::GetDOMRuleWeak(nsresult *aResult) \ { *aResult = NS_OK; return this; } #define IMPL_STYLE_RULE_INHERIT_MAP_RULE_INFO_INTO(class_, super_) \ @@ -1672,20 +1673,460 @@ nsCSSFontFaceRule::GetStyle(nsIDOMCSSSty // Arguably these should forward to nsCSSFontFaceStyleDecl methods. void nsCSSFontFaceRule::SetDesc(nsCSSFontDesc aDescID, nsCSSValue const & aValue) { NS_PRECONDITION(aDescID > eCSSFontDesc_UNKNOWN && aDescID < eCSSFontDesc_COUNT, "aDescID out of range in nsCSSFontFaceRule::SetDesc"); + // FIXME: handle dynamic changes + mDecl.*nsCSSFontFaceStyleDecl::Fields[aDescID] = aValue; } void nsCSSFontFaceRule::GetDesc(nsCSSFontDesc aDescID, nsCSSValue & aValue) { NS_PRECONDITION(aDescID > eCSSFontDesc_UNKNOWN && aDescID < eCSSFontDesc_COUNT, "aDescID out of range in nsCSSFontFaceRule::GetDesc"); aValue = mDecl.*nsCSSFontFaceStyleDecl::Fields[aDescID]; } + +// ------------------------------------------- +// nsCSSKeyframeStyleDeclaration +// + +nsCSSKeyframeStyleDeclaration::nsCSSKeyframeStyleDeclaration(nsCSSKeyframeRule *aRule) + : mRule(aRule) +{ +} + +nsCSSKeyframeStyleDeclaration::~nsCSSKeyframeStyleDeclaration() +{ + NS_ASSERTION(!mRule, "DropReference not called."); +} + +NS_IMPL_ADDREF(nsCSSKeyframeStyleDeclaration) +NS_IMPL_RELEASE(nsCSSKeyframeStyleDeclaration) + +css::Declaration* +nsCSSKeyframeStyleDeclaration::GetCSSDeclaration(PRBool aAllocate) +{ + if (mRule) { + return mRule->Declaration(); + } else { + return nsnull; + } +} + +/* + * This is a utility function. It will only fail if it can't get a + * parser. This means it can return NS_OK without aURI or aCSSLoader + * being initialized. + */ +nsresult +nsCSSKeyframeStyleDeclaration::GetCSSParsingEnvironment(nsIURI** aSheetURI, + nsIURI** aBaseURI, + nsIPrincipal** aSheetPrincipal, + css::Loader** aCSSLoader) +{ + return GetCSSParsingEnvironmentForRule(mRule, aSheetURI, aBaseURI, + aSheetPrincipal, aCSSLoader); +} + +NS_IMETHODIMP +nsCSSKeyframeStyleDeclaration::GetParentRule(nsIDOMCSSRule **aParent) +{ + NS_ENSURE_ARG_POINTER(aParent); + + NS_IF_ADDREF(*aParent = mRule); + return NS_OK; +} + +nsresult +nsCSSKeyframeStyleDeclaration::SetCSSDeclaration(css::Declaration* aDecl) +{ + NS_ABORT_IF_FALSE(aDecl, "must be non-null"); + mRule->ChangeDeclaration(aDecl); + return NS_OK; +} + +nsIDocument* +nsCSSKeyframeStyleDeclaration::DocToUpdate() +{ + return nsnull; +} + +// ------------------------------------------- +// nsCSSKeyframeRule +// + +nsCSSKeyframeRule::nsCSSKeyframeRule(const nsCSSKeyframeRule& aCopy) + // copy everything except our reference count and mDOMDeclaration + : Rule(aCopy) + , mKeys(aCopy.mKeys) + , mDeclaration(new mozilla::css::Declaration(*aCopy.mDeclaration)) +{ +} + +nsCSSKeyframeRule::~nsCSSKeyframeRule() +{ + if (mDOMDeclaration) { + mDOMDeclaration->DropReference(); + } +} + +/* virtual */ already_AddRefed<nsICSSRule> +nsCSSKeyframeRule::Clone() const +{ + nsCOMPtr<nsICSSRule> clone = new nsCSSKeyframeRule(*this); + return clone.forget(); +} + +NS_IMPL_ADDREF(nsCSSKeyframeRule) +NS_IMPL_RELEASE(nsCSSKeyframeRule) + +DOMCI_DATA(MozCSSKeyframeRule, nsCSSKeyframeRule) + +// QueryInterface implementation for nsCSSKeyframeRule +NS_INTERFACE_MAP_BEGIN(nsCSSKeyframeRule) + NS_INTERFACE_MAP_ENTRY(nsICSSRule) + NS_INTERFACE_MAP_ENTRY(nsIStyleRule) + NS_INTERFACE_MAP_ENTRY(nsIDOMMozCSSKeyframeRule) + NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsICSSRule) + NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozCSSKeyframeRule) +NS_INTERFACE_MAP_END + +IMPL_STYLE_RULE_INHERIT_GET_DOM_RULE_WEAK(nsCSSKeyframeRule, Rule) + +/* virtual */ void +nsCSSKeyframeRule::MapRuleInfoInto(nsRuleData* aRuleData) +{ + // We need to implement MapRuleInfoInto because the animation manager + // constructs a rule node pointing to us in order to compute the + // styles it needs to animate. + + // FIXME (spec): The spec doesn't say what to do with !important. + // We'll just map them. + if (mDeclaration->HasImportantData()) { + mDeclaration->MapImportantRuleInfoInto(aRuleData); + } + mDeclaration->MapNormalRuleInfoInto(aRuleData); +} + +#ifdef DEBUG +void +nsCSSKeyframeRule::List(FILE* out, PRInt32 aIndent) const +{ + // FIXME: WRITE ME +} +#endif + +/* virtual */ PRInt32 +nsCSSKeyframeRule::GetType() const +{ + return nsICSSRule::KEYFRAME_RULE; +} + +NS_IMETHODIMP +nsCSSKeyframeRule::GetType(PRUint16* aType) +{ + *aType = nsIDOMCSSRule::MOZ_KEYFRAME_RULE; + return NS_OK; +} + +NS_IMETHODIMP +nsCSSKeyframeRule::GetCssText(nsAString& aCssText) +{ + nsCSSKeyframeRule::GetKeyText(aCssText); + aCssText.AppendLiteral(" { "); + nsAutoString tmp; + mDeclaration->ToString(tmp); + aCssText.Append(tmp); + aCssText.AppendLiteral(" }"); + return NS_OK; +} + +NS_IMETHODIMP +nsCSSKeyframeRule::SetCssText(const nsAString& aCssText) +{ + // FIXME: implement??? + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsCSSKeyframeRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet) +{ + NS_IF_ADDREF(*aSheet = mSheet); + return NS_OK; +} + +NS_IMETHODIMP +nsCSSKeyframeRule::GetParentRule(nsIDOMCSSRule** aParentRule) +{ + if (mParentRule) { + return mParentRule->GetDOMRule(aParentRule); + } + *aParentRule = nsnull; + return NS_OK; +} + +NS_IMETHODIMP +nsCSSKeyframeRule::GetKeyText(nsAString& aKeyText) +{ + aKeyText.Truncate(); + PRUint32 i = 0, i_end = mKeys.Length(); + NS_ABORT_IF_FALSE(i_end != 0, "must have some keys"); + for (;;) { + aKeyText.AppendFloat(mKeys[i] * 100.0f); + aKeyText.Append(PRUnichar('%')); + if (++i == i_end) { + break; + } + aKeyText.AppendLiteral(", "); + } + return NS_OK; +} + +NS_IMETHODIMP +nsCSSKeyframeRule::SetKeyText(const nsAString& aKeyText) +{ + nsCSSParser parser; + NS_ENSURE_TRUE(parser, NS_ERROR_OUT_OF_MEMORY); + + nsTArray<float> newSelectors; + // FIXME: pass filename and line number + if (parser.ParseKeyframeSelectorString(aKeyText, nsnull, 0, newSelectors)) { + newSelectors.SwapElements(mKeys); + } else { + // for now, we don't do anything if the parse fails + } + + mSheet->SetModifiedByChildRule(); + + return NS_OK; +} + +NS_IMETHODIMP +nsCSSKeyframeRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle) +{ + if (!mDOMDeclaration) { + mDOMDeclaration = new nsCSSKeyframeStyleDeclaration(this); + } + NS_ADDREF(*aStyle = mDOMDeclaration); + return NS_OK; +} + +void +nsCSSKeyframeRule::ChangeDeclaration(mozilla::css::Declaration* aDeclaration) +{ + mDeclaration = aDeclaration; + + mSheet->SetModifiedByChildRule(); +} + +// ------------------------------------------- +// nsCSSKeyframesRule +// + +nsCSSKeyframesRule::nsCSSKeyframesRule(const nsCSSKeyframesRule& aCopy) + // copy everything except our reference count. GroupRule's copy + // constructor also doesn't copy the lazily-constructed + // mRuleCollection. + : GroupRule(aCopy), + mName(aCopy.mName) +{ +} + +nsCSSKeyframesRule::~nsCSSKeyframesRule() +{ +} + +/* virtual */ already_AddRefed<nsICSSRule> +nsCSSKeyframesRule::Clone() const +{ + nsCOMPtr<nsICSSRule> clone = new nsCSSKeyframesRule(*this); + return clone.forget(); +} + +NS_IMPL_ADDREF_INHERITED(nsCSSKeyframesRule, mozilla::css::GroupRule) +NS_IMPL_RELEASE_INHERITED(nsCSSKeyframesRule, mozilla::css::GroupRule) + +DOMCI_DATA(MozCSSKeyframesRule, nsCSSKeyframesRule) + +// QueryInterface implementation for nsCSSKeyframesRule +NS_INTERFACE_MAP_BEGIN(nsCSSKeyframesRule) + NS_INTERFACE_MAP_ENTRY(nsICSSRule) + NS_INTERFACE_MAP_ENTRY(nsIStyleRule) + NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule) + NS_INTERFACE_MAP_ENTRY(nsIDOMMozCSSKeyframesRule) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsICSSRule) + NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozCSSKeyframesRule) +NS_INTERFACE_MAP_END + +#ifdef DEBUG +void +nsCSSKeyframesRule::List(FILE* out, PRInt32 aIndent) const +{ + // FIXME: WRITE ME +} +#endif + +/* virtual */ PRInt32 +nsCSSKeyframesRule::GetType() const +{ + return nsICSSRule::KEYFRAMES_RULE; +} + +NS_IMETHODIMP +nsCSSKeyframesRule::GetType(PRUint16* aType) +{ + *aType = nsIDOMCSSRule::MOZ_KEYFRAMES_RULE; + return NS_OK; +} + +NS_IMETHODIMP +nsCSSKeyframesRule::GetCssText(nsAString& aCssText) +{ + aCssText.AssignLiteral("@-moz-keyframes "); + aCssText.Append(mName); + aCssText.AppendLiteral(" {\n"); + nsAutoString tmp; + for (PRUint32 i = 0, i_end = mRules.Count(); i != i_end; ++i) { + static_cast<nsCSSKeyframeRule*>(mRules[i])->GetCssText(tmp); + aCssText.Append(tmp); + aCssText.AppendLiteral("\n"); + } + aCssText.AppendLiteral("}"); + return NS_OK; +} + +NS_IMETHODIMP +nsCSSKeyframesRule::SetCssText(const nsAString& aCssText) +{ + // FIXME: implement??? + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsCSSKeyframesRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet) +{ + NS_IF_ADDREF(*aSheet = mSheet); + return NS_OK; +} + +NS_IMETHODIMP +nsCSSKeyframesRule::GetParentRule(nsIDOMCSSRule** aParentRule) +{ + if (mParentRule) { + return mParentRule->GetDOMRule(aParentRule); + } + *aParentRule = nsnull; + return NS_OK; +} + +NS_IMETHODIMP +nsCSSKeyframesRule::GetName(nsAString& aName) +{ + aName = mName; + return NS_OK; +} + +NS_IMETHODIMP +nsCSSKeyframesRule::SetName(const nsAString& aName) +{ + mName = aName; + + mSheet->SetModifiedByChildRule(); + + return NS_OK; +} + +NS_IMETHODIMP +nsCSSKeyframesRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList) +{ + NS_ADDREF(*aRuleList = GroupRule::GetCssRules()); + return NS_OK; +} + +NS_IMETHODIMP +nsCSSKeyframesRule::InsertRule(const nsAString& aRule) +{ + // The spec is confusing, and I think we should just append the rule, + // which also turns out to match WebKit: + // http://lists.w3.org/Archives/Public/www-style/2011Apr/0034.html + nsCSSParser parser; + NS_ENSURE_TRUE(parser, NS_OK); + + // FIXME: pass filename and line number + nsRefPtr<nsCSSKeyframeRule> rule = + parser.ParseKeyframeRule(aRule, nsnull, 0); + if (rule) { + mRules.AppendObject(rule); + mSheet->SetModifiedByChildRule(); + } + + return NS_OK; +} + +static const PRUint32 RULE_NOT_FOUND = PRUint32(-1); + +PRUint32 +nsCSSKeyframesRule::FindRuleIndexForKey(const nsAString& aKey) +{ + nsCSSParser parser; + NS_ENSURE_TRUE(parser, RULE_NOT_FOUND); + + nsTArray<float> keys; + // FIXME: pass filename and line number + if (parser.ParseKeyframeSelectorString(aKey, nsnull, 0, keys)) { + // The spec isn't clear, but we'll match on the key list, which + // mostly matches what WebKit does, except we'll do last-match + // instead of first-match, and handling parsing differences better. + // http://lists.w3.org/Archives/Public/www-style/2011Apr/0036.html + // http://lists.w3.org/Archives/Public/www-style/2011Apr/0037.html + for (PRUint32 i = mRules.Count(); i-- != 0; ) { + if (static_cast<nsCSSKeyframeRule*>(mRules[i])->GetKeys() == keys) { + return i; + } + } + } + + return RULE_NOT_FOUND; +} + +NS_IMETHODIMP +nsCSSKeyframesRule::DeleteRule(const nsAString& aKey) +{ + PRUint32 index = FindRuleIndexForKey(aKey); + if (index != RULE_NOT_FOUND) { + mRules.RemoveObjectAt(index); + mSheet->SetModifiedByChildRule(); + } + return NS_OK; +} + +NS_IMETHODIMP +nsCSSKeyframesRule::FindRule(const nsAString& aKey, + nsIDOMMozCSSKeyframeRule** aResult) +{ + PRUint32 index = FindRuleIndexForKey(aKey); + if (index == RULE_NOT_FOUND) { + *aResult = nsnull; + } else { + NS_ADDREF(*aResult = static_cast<nsCSSKeyframeRule*>(mRules[index])); + } + return NS_OK; +} + +// GroupRule interface +/* virtual */ PRBool +nsCSSKeyframesRule::UseForPresentation(nsPresContext* aPresContext, + nsMediaQueryResultCacheKey& aKey) +{ + NS_ABORT_IF_FALSE(PR_FALSE, "should not be called"); + return PR_FALSE; +} +
--- a/layout/style/nsCSSRules.h +++ b/layout/style/nsCSSRules.h @@ -43,21 +43,33 @@ #ifndef nsCSSRules_h_ #define nsCSSRules_h_ #include "Rule.h" #include "mozilla/css/GroupRule.h" #include "nsIDOMCSSMediaRule.h" #include "nsIDOMCSSMozDocumentRule.h" #include "nsIDOMCSSFontFaceRule.h" +#include "nsIDOMMozCSSKeyframeRule.h" +#include "nsIDOMMozCSSKeyframesRule.h" #include "nsIDOMCSSStyleDeclaration.h" +#include "nsICSSRuleList.h" #include "nsAutoPtr.h" #include "nsCSSProperty.h" #include "nsCSSValue.h" #include "nsIDOMCSSCharsetRule.h" +#include "nsTArray.h" +#include "nsDOMCSSDeclaration.h" +#include "Declaration.h" + +namespace mozilla { +namespace css { +class StyleRule; +} +} class nsMediaList; namespace mozilla { namespace css { class NS_FINAL_CLASS MediaRule : public GroupRule, public nsIDOMCSSMediaRule @@ -296,9 +308,135 @@ public: private: nsString mEncoding; }; } // namespace css } // namespace mozilla +class nsCSSKeyframeRule; + +class NS_FINAL_CLASS nsCSSKeyframeStyleDeclaration + : public nsDOMCSSDeclaration +{ +public: + nsCSSKeyframeStyleDeclaration(nsCSSKeyframeRule *aRule); + virtual ~nsCSSKeyframeStyleDeclaration(); + + NS_IMETHOD GetParentRule(nsIDOMCSSRule **aParent); + void DropReference() { mRule = nsnull; } + virtual mozilla::css::Declaration* GetCSSDeclaration(PRBool aAllocate); + virtual nsresult SetCSSDeclaration(mozilla::css::Declaration* aDecl); + virtual nsresult GetCSSParsingEnvironment(nsIURI** aSheetURI, + nsIURI** aBaseURI, + nsIPrincipal** aSheetPrincipal, + mozilla::css::Loader** aCSSLoader); + virtual nsIDocument* DocToUpdate(); + + NS_IMETHOD_(nsrefcnt) AddRef(); + NS_IMETHOD_(nsrefcnt) Release(); + + virtual nsINode *GetParentObject() + { + return nsnull; + } + +protected: + nsAutoRefCnt mRefCnt; + NS_DECL_OWNINGTHREAD + + // This reference is not reference-counted. The rule object tells us + // when it's about to go away. + nsCSSKeyframeRule *mRule; +}; + +class NS_FINAL_CLASS nsCSSKeyframeRule : public mozilla::css::Rule, + public nsIDOMMozCSSKeyframeRule +{ +public: + // WARNING: Steals the contents of aKeys *and* aDeclaration + nsCSSKeyframeRule(nsTArray<float> aKeys, + nsAutoPtr<mozilla::css::Declaration> aDeclaration) + : mDeclaration(aDeclaration) + { + mKeys.SwapElements(aKeys); + } + + nsCSSKeyframeRule(const nsCSSKeyframeRule& aCopy); + ~nsCSSKeyframeRule(); + + NS_DECL_ISUPPORTS + + // nsIStyleRule methods +#ifdef DEBUG + virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const; +#endif + + // nsICSSRule methods + DECL_STYLE_RULE_INHERIT + virtual PRInt32 GetType() const; + virtual already_AddRefed<nsICSSRule> Clone() const; + + // nsIDOMCSSRule interface + NS_DECL_NSIDOMCSSRULE + + // nsIDOMMozCSSKeyframeRule interface + NS_DECL_NSIDOMMOZCSSKEYFRAMERULE + + const nsTArray<float>& GetKeys() const { return mKeys; } + mozilla::css::Declaration* Declaration() { return mDeclaration; } + + void ChangeDeclaration(mozilla::css::Declaration* aDeclaration); + +private: + nsAutoTArray<float, 1> mKeys; + nsAutoPtr<mozilla::css::Declaration> mDeclaration; + // lazily created when needed: + nsRefPtr<nsCSSKeyframeStyleDeclaration> mDOMDeclaration; +}; + +class NS_FINAL_CLASS nsCSSKeyframesRule : public mozilla::css::GroupRule, + public nsIDOMMozCSSKeyframesRule +{ +public: + nsCSSKeyframesRule(const nsSubstring& aName) + : mName(aName) + { + } + nsCSSKeyframesRule(const nsCSSKeyframesRule& aCopy); + ~nsCSSKeyframesRule(); + + NS_DECL_ISUPPORTS_INHERITED + + // nsIStyleRule methods +#ifdef DEBUG + virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const; +#endif + + // nsICSSRule methods + virtual PRInt32 GetType() const; + virtual already_AddRefed<nsICSSRule> Clone() const; + virtual nsIDOMCSSRule* GetDOMRuleWeak(nsresult *aResult) + { + *aResult = NS_OK; + return this; + } + + // nsIDOMCSSRule interface + NS_DECL_NSIDOMCSSRULE + + // nsIDOMMozCSSKeyframesRule interface + NS_DECL_NSIDOMMOZCSSKEYFRAMESRULE + + // rest of GroupRule + virtual PRBool UseForPresentation(nsPresContext* aPresContext, + nsMediaQueryResultCacheKey& aKey); + + const nsString& GetName() { return mName; } + +private: + PRUint32 FindRuleIndexForKey(const nsAString& aKey); + + nsString mName; +}; + #endif /* !defined(nsCSSRules_h_) */
--- a/layout/style/nsICSSRule.h +++ b/layout/style/nsICSSRule.h @@ -73,16 +73,18 @@ public: UNKNOWN_RULE = 0, CHARSET_RULE, IMPORT_RULE, NAMESPACE_RULE, STYLE_RULE, MEDIA_RULE, FONT_FACE_RULE, PAGE_RULE, + KEYFRAME_RULE, + KEYFRAMES_RULE, DOCUMENT_RULE }; virtual PRInt32 GetType() const = 0; virtual nsIStyleSheet* GetStyleSheet() const = 0; virtual void SetStyleSheet(nsCSSStyleSheet* aSheet) = 0; virtual void SetParentRule(mozilla::css::GroupRule* aRule) = 0;
--- a/layout/style/test/Makefile.in +++ b/layout/style/test/Makefile.in @@ -147,16 +147,17 @@ GARBAGE += css_properties.js test_dont_use_document_colors.html \ test_font_face_parser.html \ test_garbage_at_end_of_declarations.html \ test_ident_escaping.html \ test_inherit_computation.html \ test_inherit_storage.html \ test_initial_computation.html \ test_initial_storage.html \ + test_keyframes_rules.html \ test_media_queries.html \ test_media_queries_dynamic.html \ test_media_queries_dynamic_xbl.html \ test_moz_device_pixel_ratio.html \ test_namespace_rule.html \ test_of_type_selectors.xhtml \ test_parse_ident.html \ test_parse_rule.html \
new file mode 100644 --- /dev/null +++ b/layout/style/test/test_keyframes_rules.html @@ -0,0 +1,135 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=577974 +--> +<head> + <title>Test for Bug 577974</title> + <script type="application/javascript" src="/MochiKit/packed.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <style id="style"> + + @-moz-keyframes bounce { + from { + margin-left: 0 + } + + /* + * These rules should get dropped due to syntax errors. The script + * below tests that the 25% rule following them is at cssRules[1]. + */ + from, { margin-left: 0 } + from , { margin-left: 0 } + , from { margin-left: 0 } + ,from { margin-left: 0 } + from from { margin-left: 0 } + from, 1 { margin-left: 0 } + 1 { margin-left: 0 } + 1, from { margin-left: 0 } + from, 1.0 { margin-left: 0 } + 1.0 { margin-left: 0 } + 1.0, from { margin-left: 0 } + + 25% { + margin-left: 25px; + } + + 75%, 85% { + margin-left: 90px; + } + + 100% { + margin-left: 100px; + } + } + + </style> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=577974">Mozilla Bug 577974</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 577974 **/ + +var sheet = document.getElementById("style").sheet; + +var bounce = sheet.cssRules[0]; +is(bounce.type, CSSRule.MOZ_KEYFRAMES_RULE, "bounce.type"); +is(bounce.type, 7, "bounce.type"); +is(bounce.name, "bounce", "bounce.name"); +bounce.name = "bouncier"; +is(bounce.name, "bouncier", "setting bounce.name"); + +is(bounce.cssRules[0].type, CSSRule.MOZ_KEYFRAME_RULE, "keyframe rule type"); +is(bounce.cssRules[0].type, 8, "keyframe rule type"); +is(bounce.cssRules[0].keyText, "0%", "keyframe rule keyText"); +is(bounce.cssRules[1].keyText, "25%", "keyframe rule keyText"); +is(bounce.cssRules[2].keyText, "75%, 85%", "keyframe rule keyText"); +is(bounce.cssRules[3].keyText, "100%", "keyframe rule keyText"); +is(bounce.cssRules[0].style.marginLeft, "0pt", "keyframe rule style"); +is(bounce.cssRules[1].style.marginLeft, "25px", "keyframe rule style"); + +is(bounce.cssRules[0].cssText, "0% { margin-left: 0pt; }"); +is(bounce.cssText, "@-moz-keyframes bouncier {\n" + + "0% { margin-left: 0pt; }\n" + + "25% { margin-left: 25px; }\n" + + "75%, 85% { margin-left: 90px; }\n" + + "100% { margin-left: 100px; }\n" + + "}"); + +bounce.cssRules[1].keyText = "from, 1"; // syntax error +bounce.cssRules[1].keyText = "from, x"; // syntax error +bounce.cssRules[1].keyText = "from,"; // syntax error +bounce.cssRules[1].keyText = "from x"; // syntax error +bounce.cssRules[1].keyText = "x"; // syntax error +is(bounce.cssRules[1].keyText, "25%", "keyframe rule keyText parsing"); +bounce.cssRules[1].keyText = "from, 10%"; +is(bounce.cssRules[1].keyText, "0%, 10%", "keyframe rule keyText parsing"); +bounce.cssRules[1].keyText = "from, 0%"; +is(bounce.cssRules[1].keyText, "0%, 0%", "keyframe rule keyText parsing"); +bounce.cssRules[1].keyText = "from, from, from"; +is(bounce.cssRules[1].keyText, "0%, 0%, 0%", "keyframe rule keyText parsing"); + +is(bounce.findRule("75%"), null, "findRule should match all keys"); +is(bounce.findRule("85%, 75%"), null, + "findRule should match all keys in order"); +is(bounce.findRule("75%,85%"), bounce.cssRules[2], + "findRule should match all keys in order, parsed"); +is(bounce.findRule("to"), bounce.cssRules[3], + "findRule should match keys as parsed"); +is(bounce.findRule("100%"), bounce.cssRules[3], + "findRule should match keys as parsed"); +is(bounce.findRule("100%, 100%"), null, + "findRule should match key list"); +is(bounce.findRule("100%,"), null, + "findRule should fail when given bad selector"); +is(bounce.findRule(",100%"), null, + "findRule should fail when given bad selector"); +is(bounce.cssRules.length, 4, "length of css rules"); +bounce.deleteRule("85%"); +is(bounce.cssRules.length, 4, "deleteRule should match all keys"); +bounce.deleteRule("85%, 75%"); +is(bounce.cssRules.length, 4, "deleteRule should match key list"); +bounce.deleteRule("75% ,85%"); +is(bounce.cssRules.length, 3, "deleteRule should match keys in order, parsed"); +bounce.deleteRule("0%"); +is(bounce.cssRules.length, 2, "deleteRule should match keys in order, parsed"); +bounce.insertRule("from { color: blue }"); +is(bounce.cssRules.length, 3, "insertRule should append"); +is(bounce.cssRules[2].keyText, "0%", "insertRule should append"); +bounce.insertRule("from { color: blue }"); +is(bounce.cssRules.length, 4, "insertRule should append"); +is(bounce.cssRules[3].keyText, "0%", "insertRule should append"); +bounce.insertRule("from { color: blue } to { color: green }"); +is(bounce.cssRules.length, 4, "insertRule should ignore garbage at end"); + +</script> +</pre> +</body> +</html>