author | Zack Weinberg <zackw@panix.com> |
Sat, 28 May 2011 15:38:48 -0700 | |
changeset 79002 | 67673422f7d2eb344b763465c738d83cc5e8480c |
parent 79001 | 6d0fded8a2b3c01b6d8cec4c86facbf1c01cbf41 |
child 79003 | a4d50bd8053464450ba5326eafa50cf9b4f7c1ee |
child 79055 | 656c921623a87228b252a4ef5e680dad6fd17d0e |
push id | 2797 |
push user | zackw@panix.com |
push date | Thu, 20 Oct 2011 01:53:50 +0000 |
treeherder | mozilla-inbound@67673422f7d2 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | dbaron |
bugs | 659963 |
milestone | 10.0a1 |
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/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -259,17 +259,17 @@ public: 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); + InfallibleTArray<float>& aSelectorList); protected: class nsAutoParseCompoundProperty; friend class nsAutoParseCompoundProperty; void AppendRule(css::Rule* aRule); friend void AppendRuleToSheet(css::Rule*, void*); // calls AppendRule @@ -326,17 +326,17 @@ protected: bool CheckEndProperty(); nsSubstring* NextIdent(); void SkipUntil(PRUnichar aStopSymbol); void SkipUntilOneOf(const PRUnichar* aStopSymbolChars); void SkipRuleSet(bool aInsideBraces); bool SkipAtRule(bool aInsideBlock); bool SkipDeclaration(bool aCheckForBraces); - bool PushGroup(css::GroupRule* aRule); + void PushGroup(css::GroupRule* aRule); void PopGroup(); bool ParseRuleSet(RuleAppendFunc aAppendFunc, void* aProcessData, bool aInsideBraces = false); bool ParseAtRule(RuleAppendFunc aAppendFunc, void* aProcessData); bool ParseCharsetRule(RuleAppendFunc aAppendFunc, void* aProcessData); bool ParseImportRule(RuleAppendFunc aAppendFunc, void* aProcessData); bool ParseURLOrString(nsString& aURL); @@ -361,17 +361,17 @@ protected: bool ParseFontFaceRule(RuleAppendFunc aAppendFunc, void* aProcessData); bool ParseFontDescriptor(nsCSSFontFaceRule* aRule); bool ParseFontDescriptorValue(nsCSSFontDesc aDescID, nsCSSValue& aValue); bool ParsePageRule(RuleAppendFunc aAppendFunc, void* aProcessData); bool ParseKeyframesRule(RuleAppendFunc aAppendFunc, void* aProcessData); already_AddRefed<nsCSSKeyframeRule> ParseKeyframeRule(); - bool ParseKeyframeSelectorList(nsTArray<float>& aSelectorList); + bool ParseKeyframeSelectorList(InfallibleTArray<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, @@ -500,17 +500,17 @@ protected: bool ParseContent(); bool ParseCounterData(nsCSSProperty aPropID); bool ParseCursor(); bool ParseFont(); bool ParseFontWeight(nsCSSValue& aValue); bool ParseOneFamily(nsAString& aValue); bool ParseFamily(nsCSSValue& aValue); bool ParseFontSrc(nsCSSValue& aValue); - bool ParseFontSrcFormat(nsTArray<nsCSSValue>& values); + bool ParseFontSrcFormat(InfallibleTArray<nsCSSValue>& values); bool ParseFontRanges(nsCSSValue& aValue); bool ParseListStyle(); bool ParseMargin(); bool ParseMarks(nsCSSValue& aValue); bool ParseMozTransform(); bool ParseOutline(); bool ParseOverflow(); bool ParsePadding(); @@ -596,17 +596,17 @@ protected: /* Functions for -moz-transform Parsing */ bool ParseSingleTransform(nsCSSValue& aValue, bool& aIs3D); bool ParseFunction(const nsString &aFunction, const PRInt32 aAllowedTypes[], PRUint16 aMinElems, PRUint16 aMaxElems, nsCSSValue &aValue); bool ParseFunctionInternals(const PRInt32 aVariantMask[], PRUint16 aMinElems, PRUint16 aMaxElems, - nsTArray<nsCSSValue>& aOutput); + InfallibleTArray<nsCSSValue>& aOutput); /* Functions for -moz-transform-origin/-moz-perspective-origin Parsing */ bool ParseMozTransformOrigin(bool aPerspective); /* Find and return the namespace ID associated with aPrefix. If aPrefix has not been declared in an @namespace rule, returns kNameSpaceID_Unknown and sets mFoundUnresolvablePrefix to true. */ PRInt32 GetNamespaceIdForPrefix(const nsString& aPrefix); @@ -672,17 +672,17 @@ protected: // when it encounters a prefix that is not mapped to a namespace. bool mFoundUnresolvablePrefix : 1; #ifdef DEBUG bool mScannerInited : 1; #endif // Stack of rule groups; used for @media and such. - nsTArray<nsRefPtr<css::GroupRule> > mGroupStack; + InfallibleTArray<nsRefPtr<css::GroupRule> > mGroupStack; // During the parsing of a property (which may be a shorthand), the data // are stored in |mTempData|. (It is needed to ensure that parser // errors cause the data to be ignored, and to ensure that a // non-'!important' declaration does not override an '!important' // one.) nsCSSExpandedDataBlock mTempData; @@ -1011,35 +1011,29 @@ CSSParserImpl::ParseDeclarations(const n mSection = eCSSSection_General; mData.AssertInitialState(); aDeclaration->ClearData(); // We could check if it was already empty, but... *aChanged = true; - nsresult rv = NS_OK; for (;;) { // If we cleared the old decl, then we want to be calling // ValueAppended as we parse. if (!ParseDeclaration(aDeclaration, false, true, aChanged)) { - rv = mScanner.GetLowLevelError(); - if (NS_FAILED(rv)) - break; - if (!SkipDeclaration(false)) { - rv = mScanner.GetLowLevelError(); break; } } } aDeclaration->CompressFrom(&mData); ReleaseScanner(); - return rv; + return NS_OK; } nsresult CSSParserImpl::ParseRule(const nsAString& aRule, nsIURI* aSheetURI, nsIURI* aBaseURI, nsIPrincipal* aSheetPrincipal, nsCOMArray<css::Rule>& aResult) @@ -1138,19 +1132,18 @@ CSSParserImpl::ParseProperty(const nsCSS true, false, aDeclaration); aDeclaration->CompressFrom(&mData); } CLEAR_ERROR(); } mTempData.AssertInitialState(); - nsresult result = mScanner.GetLowLevelError(); ReleaseScanner(); - return result; + return NS_OK; } nsresult CSSParserImpl::ParseMediaList(const nsSubstring& aBuffer, nsIURI* aURI, // for error reporting PRUint32 aLineNumber, // for error reporting nsMediaList* aMediaList, bool aHTMLMode) @@ -1174,72 +1167,77 @@ CSSParserImpl::ParseMediaList(const nsSu // http://www.w3.org/TR/1999/REC-html401-19991224/types.html#type-media-descriptors // which wouldn't work for media queries since they remove all but the // first word. However, they're changed in // http://www.whatwg.org/specs/web-apps/current-work/multipage/section-document.html#media2 // (as of 2008-05-29) which says that the media attribute just points // to a media query. (The main substative difference is the relative // precedence of commas and paretheses.) - GatherMedia(aMediaList, false); // can only fail on low-level error (OOM) - - nsresult rv = mScanner.GetLowLevelError(); + GatherMedia(aMediaList, false); + CLEAR_ERROR(); ReleaseScanner(); mHTMLMediaMode = false; - return rv; + return NS_OK; } nsresult CSSParserImpl::ParseColorString(const nsSubstring& aBuffer, nsIURI* aURI, // for error reporting PRUint32 aLineNumber, // for error reporting nscolor* aColor) { AssertInitialState(); InitScanner(aBuffer, aURI, aLineNumber, aURI, nsnull); nsCSSValue value; // Parse a color, and check that there's nothing else after it. bool colorParsed = ParseColor(value) && !GetToken(true); - nsresult rv = mScanner.GetLowLevelError(); OUTPUT_ERROR(); ReleaseScanner(); if (!colorParsed) { - return NS_FAILED(rv) ? rv : NS_ERROR_FAILURE; - } - - if (value.GetUnit() == eCSSUnit_Ident) { + return NS_ERROR_FAILURE; + } + + switch (value.GetUnit()) { + case eCSSUnit_Color: + *aColor = value.GetColorValue(); + return NS_OK; + + case eCSSUnit_Ident: { + nsDependentString id(value.GetStringBufferValue()); + if (!NS_ColorNameToRGB(id, aColor)) { + return NS_ERROR_FAILURE; + } + return NS_OK; + } + + case eCSSUnit_EnumColor: { + PRInt32 val = value.GetIntValue(); + if (val < 0) { + // XXX - negative numbers are NS_COLOR_CURRENTCOLOR, + // NS_COLOR_MOZ_HYPERLINKTEXT, etc. which we don't handle. + // Should remove this limitation at some point. + return NS_ERROR_FAILURE; + } nscolor rgba; - if (NS_ColorNameToRGB(nsDependentString(value.GetStringBufferValue()), &rgba)) { - (*aColor) = rgba; - rv = NS_OK; - } - } else if (value.GetUnit() == eCSSUnit_Color) { - (*aColor) = value.GetColorValue(); - rv = NS_OK; - } else if (value.GetUnit() == eCSSUnit_EnumColor) { - PRInt32 intValue = value.GetIntValue(); - if (intValue >= 0) { - nscolor rgba; - rv = LookAndFeel::GetColor((LookAndFeel::ColorID) value.GetIntValue(), - &rgba); - if (NS_SUCCEEDED(rv)) - (*aColor) = rgba; - } else { - // XXX - this is NS_COLOR_CURRENTCOLOR, NS_COLOR_MOZ_HYPERLINKTEXT, etc. - // which we don't handle as per the ParseColorString definition. Should - // remove this limitation at some point. - rv = NS_ERROR_FAILURE; - } - } - - return rv; + nsresult rv = LookAndFeel::GetColor(LookAndFeel::ColorID(val), &rgba); + if (NS_FAILED(rv)) { + return rv; + } + *aColor = rgba; + return NS_OK; + } + + default: + return NS_ERROR_FAILURE; + } } nsresult CSSParserImpl::ParseSelectorString(const nsSubstring& aSelectorString, nsIURI* aURI, // for error reporting PRUint32 aLineNumber, // for error reporting nsCSSSelectorList **aSelectorList) { @@ -1298,17 +1296,17 @@ CSSParserImpl::ParseKeyframeRule(const n return result.forget(); } bool CSSParserImpl::ParseKeyframeSelectorString(const nsSubstring& aSelectorString, nsIURI* aURI, // for error reporting PRUint32 aLineNumber, // for error reporting - nsTArray<float>& aSelectorList) + InfallibleTArray<float>& aSelectorList) { NS_ABORT_IF_FALSE(aSelectorList.IsEmpty(), "given list should start empty"); InitScanner(aSelectorString, aURI, aLineNumber, aURI, nsnull); AssertInitialState(); bool success = ParseKeyframeSelectorList(aSelectorList) && @@ -1648,20 +1646,16 @@ CSSParserImpl::ParseMediaQuery(bool aInA *aHitStop = true; UngetToken(); return true; } UngetToken(); nsMediaQuery* query = new nsMediaQuery; *aQuery = query; - if (!query) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - return false; - } if (ExpectSymbol('(', true)) { // we got an expression without a media type UngetToken(); // so ParseMediaQueryExpression can handle it query->SetType(nsGkAtoms::all); query->SetTypeOmitted(); // Just parse the first expression here. if (!ParseMediaQueryExpression(query)) { @@ -1679,16 +1673,19 @@ CSSParserImpl::ParseMediaQuery(bool aInA if (eCSSToken_Ident != mToken.mType) { REPORT_UNEXPECTED_TOKEN(PEGatherMediaNotIdent); UngetToken(); return false; } // case insensitive from CSS - must be lower cased nsContentUtils::ASCIIToLower(mToken.mIdent); mediaType = do_GetAtom(mToken.mIdent); + if (!mediaType) { + NS_RUNTIMEABORT("do_GetAtom failed - out of memory?"); + } if (gotNotOrOnly || (mediaType != nsGkAtoms::_not && mediaType != nsGkAtoms::only)) break; gotNotOrOnly = true; if (mediaType == nsGkAtoms::_not) query->SetNegated(); else query->SetHasOnly(); @@ -1740,19 +1737,16 @@ CSSParserImpl::GatherMedia(nsMediaList* { for (;;) { nsAutoPtr<nsMediaQuery> query; bool hitStop; if (!ParseMediaQuery(aInAtRule, getter_Transfers(query), &hitStop)) { NS_ASSERTION(!hitStop, "should return true when hit stop"); OUTPUT_ERROR(); - if (NS_FAILED(mScanner.GetLowLevelError())) { - return false; - } if (query) { query->SetHadUnknownExpression(); } if (aInAtRule) { const PRUnichar stopChars[] = { PRUnichar(','), PRUnichar('{'), PRUnichar(';'), PRUnichar(0) }; SkipUntilOneOf(stopChars); } else { @@ -1761,21 +1755,17 @@ CSSParserImpl::GatherMedia(nsMediaList* // Rely on SkipUntilOneOf leaving mToken around as the last token read. if (mToken.mType == eCSSToken_Symbol && aInAtRule && (mToken.mSymbol == '{' || mToken.mSymbol == ';')) { UngetToken(); hitStop = true; } } if (query) { - nsresult rv = aMedia->AppendQuery(query); - if (NS_FAILED(rv)) { - mScanner.SetLowLevelError(rv); - return false; - } + aMedia->AppendQuery(query); } if (hitStop) { break; } } return true; } @@ -1793,37 +1783,35 @@ CSSParserImpl::ParseMediaQueryExpression if (eCSSToken_Ident != mToken.mType) { REPORT_UNEXPECTED_TOKEN(PEMQExpectedFeatureName); UngetToken(); SkipUntil(')'); return false; } nsMediaExpression *expr = aQuery->NewExpression(); - if (!expr) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - SkipUntil(')'); - return false; - } // case insensitive from CSS - must be lower cased nsContentUtils::ASCIIToLower(mToken.mIdent); const PRUnichar *featureString; if (StringBeginsWith(mToken.mIdent, NS_LITERAL_STRING("min-"))) { expr->mRange = nsMediaExpression::eMin; featureString = mToken.mIdent.get() + 4; } else if (StringBeginsWith(mToken.mIdent, NS_LITERAL_STRING("max-"))) { expr->mRange = nsMediaExpression::eMax; featureString = mToken.mIdent.get() + 4; } else { expr->mRange = nsMediaExpression::eEqual; featureString = mToken.mIdent.get(); } nsCOMPtr<nsIAtom> mediaFeatureAtom = do_GetAtom(featureString); + if (!mediaFeatureAtom) { + NS_RUNTIMEABORT("do_GetAtom failed - out of memory?"); + } const nsMediaFeature *feature = nsMediaFeatures::features; for (; feature->mName; ++feature) { if (*(feature->mName) == mediaFeatureAtom) { break; } } if (!feature->mName || (expr->mRange != nsMediaExpression::eEqual && @@ -1922,20 +1910,16 @@ CSSParserImpl::ParseMediaQueryExpression return true; } // Parse a CSS2 import rule: "@import STRING | URL [medium [, medium]]" bool CSSParserImpl::ParseImportRule(RuleAppendFunc aAppendFunc, void* aData) { nsRefPtr<nsMediaList> media = new nsMediaList(); - if (!media) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - return false; - } nsAutoString url; if (!ParseURLOrString(url)) { REPORT_UNEXPECTED_TOKEN(PEImportNotURI); return false; } if (!ExpectSymbol(';', true)) { @@ -1994,20 +1978,17 @@ CSSParserImpl::ParseGroupRule(css::Group void* aData) { // XXXbz this could use better error reporting throughout the method if (!ExpectSymbol('{', true)) { return false; } // push rule on stack, loop over children - if (!PushGroup(aRule)) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - return false; - } + PushGroup(aRule); nsCSSSection holdSection = mSection; mSection = eCSSSection_General; for (;;) { // Get next non-whitespace token if (! GetToken(true)) { REPORT_UNEXPECTED_EOF(PEGroupRuleEOF); break; @@ -2158,16 +2139,19 @@ CSSParserImpl::ProcessNameSpace(const ns const nsString& aURLSpec, RuleAppendFunc aAppendFunc, void* aData) { nsCOMPtr<nsIAtom> prefix; if (!aPrefix.IsEmpty()) { prefix = do_GetAtom(aPrefix); + if (!prefix) { + NS_RUNTIMEABORT("do_GetAtom failed - out of memory?"); + } } nsRefPtr<css::NameSpaceRule> rule = new css::NameSpaceRule(prefix, aURLSpec); (*aAppendFunc)(rule, aData); // If this was the first namespace rule encountered, it will trigger // creation of a namespace map. if (!mNameSpaceMap) { @@ -2181,20 +2165,16 @@ bool CSSParserImpl::ParseFontFaceRule(RuleAppendFunc aAppendFunc, void* aData) { if (!ExpectSymbol('{', true)) { REPORT_UNEXPECTED_TOKEN(PEBadFontBlockStart); return false; } nsRefPtr<nsCSSFontFaceRule> rule(new nsCSSFontFaceRule()); - if (!rule) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - return false; - } for (;;) { if (!GetToken(true)) { REPORT_UNEXPECTED_EOF(PEFontFaceEOF); break; } if (mToken.IsSymbol('}')) { // done! UngetToken(); @@ -2321,17 +2301,17 @@ CSSParserImpl::ParseKeyframesRule(RuleAp (*aAppendFunc)(rule, aData); return true; } already_AddRefed<nsCSSKeyframeRule> CSSParserImpl::ParseKeyframeRule() { - nsTArray<float> selectorList; + InfallibleTArray<float> selectorList; if (!ParseKeyframeSelectorList(selectorList)) { REPORT_UNEXPECTED(PEBadSelectorKeyframeRuleIgnored); return nsnull; } nsAutoPtr<css::Declaration> declaration(ParseDeclarationBlock(true)); if (!declaration) { REPORT_UNEXPECTED(PEBadSelectorKeyframeRuleIgnored); @@ -2341,17 +2321,17 @@ CSSParserImpl::ParseKeyframeRule() // Takes ownership of declaration, and steals contents of selectorList. nsRefPtr<nsCSSKeyframeRule> rule = new nsCSSKeyframeRule(selectorList, declaration); return rule.forget(); } bool -CSSParserImpl::ParseKeyframeSelectorList(nsTArray<float>& aSelectorList) +CSSParserImpl::ParseKeyframeSelectorList(InfallibleTArray<float>& aSelectorList) { for (;;) { if (!GetToken(true)) { // The first time through the loop, this means we got an empty // list. Otherwise, it means we have a trailing comma. return false; } float value; @@ -2504,26 +2484,23 @@ CSSParserImpl::SkipRuleSet(bool aInsideB SkipUntil(')'); } else if ('[' == symbol) { SkipUntil(']'); } } else if (eCSSToken_Function == tk->mType || eCSSToken_Bad_URL == tk->mType) { SkipUntil(')'); } - } -} - -bool + } +} + +void CSSParserImpl::PushGroup(css::GroupRule* aRule) { - if (mGroupStack.AppendElement(aRule)) - return true; - - return false; + mGroupStack.AppendElement(aRule); } void CSSParserImpl::PopGroup() { PRUint32 count = mGroupStack.Length(); if (0 < count) { mGroupStack.RemoveElementAt(count - 1); @@ -3118,18 +3095,17 @@ CSSParserImpl::ParsePseudoSelector(PRInt // OK, now we know we have an mIdent. Atomize it. All the atoms, for // pseudo-classes as well as pseudo-elements, start with a single ':'. nsAutoString buffer; buffer.Append(PRUnichar(':')); buffer.Append(mToken.mIdent); nsContentUtils::ASCIIToLower(buffer); nsCOMPtr<nsIAtom> pseudo = do_GetAtom(buffer); if (!pseudo) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - return eSelectorParsingStatus_Error; + NS_RUNTIMEABORT("do_GetAtom failed - out of memory?"); } // stash away some info about this pseudo so we only have to get it once. bool isTreePseudo = false; nsCSSPseudoElements::Type pseudoElementType = nsCSSPseudoElements::GetPseudoType(pseudo); #ifdef MOZ_XUL isTreePseudo = (pseudoElementType == nsCSSPseudoElements::ePseudo_XULTree); @@ -3329,20 +3305,16 @@ CSSParserImpl::ParseNegatedSimpleSelecto // Create a new nsCSSSelector and add it to the end of // aSelector.mNegations. // Given the current parsing rules, every selector in mNegations // contains only one simple selector (css3 definition) within it. // This could easily change in future versions of CSS, and the only // thing we need to change to support that is this parsing code and the // serialization code for nsCSSSelector. nsCSSSelector *newSel = new nsCSSSelector(); - if (!newSel) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - return eSelectorParsingStatus_Error; - } nsCSSSelector* negations = &aSelector; while (negations->mNegations) { negations = negations->mNegations; } negations->mNegations = newSel; nsSelectorParsingStatus parsingStatus; if (eCSSToken_ID == mToken.mType) { // #id @@ -4822,29 +4794,20 @@ CSSParserImpl::SetValueToURL(nsCSSValue& { if (!mSheetPrincipal) { NS_NOTREACHED("Codepaths that expect to parse URLs MUST pass in an " "origin principal"); return false; } nsRefPtr<nsStringBuffer> buffer(nsCSSValue::BufferFromString(aURL)); - if (NS_UNLIKELY(!buffer)) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - return false; - } // Note: urlVal retains its own reference to |buffer|. nsCSSValue::URL *urlVal = new nsCSSValue::URL(buffer, mBaseURI, mSheetURI, mSheetPrincipal); - - if (NS_UNLIKELY(!urlVal)) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - return false; - } aValue.SetURLValue(urlVal); return true; } /** * Parse the arguments of -moz-image-rect() function. * -moz-image-rect(<uri>, <top>, <right>, <bottom>, <left>) */ @@ -4852,20 +4815,16 @@ bool CSSParserImpl::ParseImageRect(nsCSSValue& aImage) { // A non-iterative for loop to break out when an error occurs. for (;;) { nsCSSValue newFunction; static const PRUint32 kNumArgs = 5; nsCSSValue::Array* func = newFunction.InitFunction(eCSSKeyword__moz_image_rect, kNumArgs); - if (!func) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - break; - } // func->Item(0) is reserved for the function name. nsCSSValue& url = func->Item(1); nsCSSValue& top = func->Item(2); nsCSSValue& right = func->Item(3); nsCSSValue& bottom = func->Item(4); nsCSSValue& left = func->Item(5); @@ -4923,21 +4882,16 @@ CSSParserImpl::ParseElement(nsCSSValue& return false; } // <color-stop> : <color> [ <percentage> | <length> ]? bool CSSParserImpl::ParseColorStop(nsCSSValueGradient* aGradient) { nsCSSValueGradientStop* stop = aGradient->mStops.AppendElement(); - if (!stop) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - return false; - } - if (!ParseVariant(stop->mColor, VARIANT_COLOR, nsnull)) { return false; } // Stop positions do not have to fall between the starting-point and // ending-point, so we don't use ParseNonNegativeVariant. if (!ParseVariant(stop->mLocation, VARIANT_LP, nsnull)) { stop->mLocation.SetNoneValue(); @@ -7206,28 +7160,25 @@ CSSParserImpl::ParseOneFamily(nsAString& /* Reads a function list of arguments. Do not call this function * directly; it's mean to be caled from ParseFunction. */ bool CSSParserImpl::ParseFunctionInternals(const PRInt32 aVariantMask[], PRUint16 aMinElems, PRUint16 aMaxElems, - nsTArray<nsCSSValue> &aOutput) + InfallibleTArray<nsCSSValue> &aOutput) { for (PRUint16 index = 0; index < aMaxElems; ++index) { nsCSSValue newValue; if (!ParseVariant(newValue, aVariantMask[index], nsnull)) return false; - if (!aOutput.AppendElement(newValue)) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - return false; - } - + aOutput.AppendElement(newValue); + // See whether to continue or whether to look for end of function. if (!ExpectSymbol(',', true)) { // We need to read the closing parenthesis, and also must take care // that we haven't read too few symbols. return ExpectSymbol(')', true) && (index + 1) >= aMinElems; } } @@ -7255,55 +7206,55 @@ CSSParserImpl::ParseFunctionInternals(co * @param aValue (out) The value that was parsed. */ bool CSSParserImpl::ParseFunction(const nsString &aFunction, const PRInt32 aAllowedTypes[], PRUint16 aMinElems, PRUint16 aMaxElems, nsCSSValue &aValue) { - typedef nsTArray<nsCSSValue>::size_type arrlen_t; + typedef InfallibleTArray<nsCSSValue>::size_type arrlen_t; /* 2^16 - 2, so that if we have 2^16 - 2 transforms, we have 2^16 - 1 * elements stored in the the nsCSSValue::Array. */ static const arrlen_t MAX_ALLOWED_ELEMS = 0xFFFE; /* Make a copy of the function name, since the reference is _probably_ to * mToken.mIdent, which is going to get overwritten during the course of this * function. */ nsString functionName(aFunction); - /* Read in a list of values as an nsTArray, failing if we can't or if + /* Read in a list of values as an array, failing if we can't or if * it's out of bounds. */ - nsTArray<nsCSSValue> foundValues; + InfallibleTArray<nsCSSValue> foundValues; if (!ParseFunctionInternals(aAllowedTypes, aMinElems, aMaxElems, foundValues)) return false; - - /* Now, convert this nsTArray into an nsCSSValue::Array object. + + /* Now, convert this array into an nsCSSValue::Array object. * We'll need N + 1 spots, one for the function name and the rest for the * arguments. In case the user has given us more than 2^16 - 2 arguments, * we'll truncate them at 2^16 - 2 arguments. */ PRUint16 numElements = (foundValues.Length() <= MAX_ALLOWED_ELEMS ? foundValues.Length() + 1 : MAX_ALLOWED_ELEMS); nsRefPtr<nsCSSValue::Array> convertedArray = nsCSSValue::Array::Create(numElements); /* Copy things over. */ convertedArray->Item(0).SetStringValue(functionName, eCSSUnit_Ident); for (PRUint16 index = 0; index + 1 < numElements; ++index) convertedArray->Item(index + 1) = foundValues[static_cast<arrlen_t>(index)]; - + /* Fill in the outparam value with the array. */ aValue.SetArrayValue(convertedArray, eCSSUnit_Function); - + /* Return it! */ return true; } /** * Given a token, determines the minimum and maximum number of function * parameters to read, along with the mask that should be used to read * those function parameters. If the token isn't a transform function, @@ -7635,18 +7586,18 @@ CSSParserImpl::ParseFamily(nsCSSValue& a // src: ( uri-src | local-src ) (',' ( uri-src | local-src ) )* // uri-src: uri [ 'format(' string ( ',' string )* ')' ] // local-src: 'local(' ( string | ident ) ')' bool CSSParserImpl::ParseFontSrc(nsCSSValue& aValue) { - // could we maybe turn nsCSSValue::Array into nsTArray<nsCSSValue>? - nsTArray<nsCSSValue> values; + // could we maybe turn nsCSSValue::Array into InfallibleTArray<nsCSSValue>? + InfallibleTArray<nsCSSValue> values; nsCSSValue cur; for (;;) { if (!GetToken(true)) break; if (mToken.mType == eCSSToken_URL) { SetValueToURL(cur, mToken.mIdent); values.AppendElement(cur); @@ -7689,31 +7640,27 @@ CSSParserImpl::ParseFontSrc(nsCSSValue& if (!ExpectSymbol(',', true)) break; } if (values.Length() == 0) return false; nsRefPtr<nsCSSValue::Array> srcVals - = nsCSSValue::Array::Create(mozilla::fallible_t(), values.Length()); - if (!srcVals) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - return false; - } + = nsCSSValue::Array::Create(values.Length()); PRUint32 i; for (i = 0; i < values.Length(); i++) srcVals->Item(i) = values[i]; aValue.SetArrayValue(srcVals, eCSSUnit_Array); return true; } bool -CSSParserImpl::ParseFontSrcFormat(nsTArray<nsCSSValue> & values) +CSSParserImpl::ParseFontSrcFormat(InfallibleTArray<nsCSSValue> & values) { if (!GetToken(true)) return true; // EOF harmless here if (mToken.mType != eCSSToken_Function || !mToken.mIdent.LowerCaseEqualsLiteral("format")) { UngetToken(); return true; } @@ -7739,17 +7686,17 @@ CSSParserImpl::ParseFontSrcFormat(nsTArr return true; } // font-ranges: urange ( ',' urange )* bool CSSParserImpl::ParseFontRanges(nsCSSValue& aValue) { - nsTArray<PRUint32> ranges; + InfallibleTArray<PRUint32> ranges; for (;;) { if (!GetToken(true)) break; if (mToken.mType != eCSSToken_URange) { UngetToken(); break; } @@ -7776,21 +7723,17 @@ CSSParserImpl::ParseFontRanges(nsCSSValu if (!ExpectSymbol(',', true)) break; } if (ranges.Length() == 0) return false; nsRefPtr<nsCSSValue::Array> srcVals - = nsCSSValue::Array::Create(mozilla::fallible_t(), ranges.Length()); - if (!srcVals) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - return false; - } + = nsCSSValue::Array::Create(ranges.Length()); for (PRUint32 i = 0; i < ranges.Length(); i++) srcVals->Item(i).SetIntValue(ranges[i], eCSSUnit_Integer); aValue.SetArrayValue(srcVals, eCSSUnit_Array); return true; } bool @@ -8705,16 +8648,19 @@ PRInt32 CSSParserImpl::GetNamespaceIdForPrefix(const nsString& aPrefix) { NS_PRECONDITION(!aPrefix.IsEmpty(), "Must have a prefix here"); PRInt32 nameSpaceID = kNameSpaceID_Unknown; if (mNameSpaceMap) { // user-specified identifiers are case-sensitive (bug 416106) nsCOMPtr<nsIAtom> prefix = do_GetAtom(aPrefix); + if (!prefix) { + NS_RUNTIMEABORT("do_GetAtom failed - out of memory?"); + } nameSpaceID = mNameSpaceMap->FindNameSpaceID(prefix); } // else no declared namespaces if (nameSpaceID == kNameSpaceID_Unknown) { // unknown prefix, dump it const PRUnichar *params[] = { aPrefix.get() }; @@ -8985,14 +8931,14 @@ nsCSSParser::ParseKeyframeRule(const nsS return static_cast<CSSParserImpl*>(mImpl)-> ParseKeyframeRule(aBuffer, aURI, aLineNumber); } bool nsCSSParser::ParseKeyframeSelectorString(const nsSubstring& aSelectorString, nsIURI* aURI, PRUint32 aLineNumber, - nsTArray<float>& aSelectorList) + InfallibleTArray<float>& aSelectorList) { return static_cast<CSSParserImpl*>(mImpl)-> ParseKeyframeSelectorString(aSelectorString, aURI, aLineNumber, aSelectorList); }
--- a/layout/style/nsCSSParser.h +++ b/layout/style/nsCSSParser.h @@ -199,17 +199,17 @@ public: /* * 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); + InfallibleTArray<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; };
--- a/layout/style/nsCSSRules.cpp +++ b/layout/style/nsCSSRules.cpp @@ -1846,17 +1846,17 @@ nsCSSKeyframeRule::GetKeyText(nsAString& return NS_OK; } NS_IMETHODIMP nsCSSKeyframeRule::SetKeyText(const nsAString& aKeyText) { nsCSSParser parser; - nsTArray<float> newSelectors; + InfallibleTArray<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 } if (mSheet) { @@ -2028,17 +2028,17 @@ nsCSSKeyframesRule::InsertRule(const nsA static const PRUint32 RULE_NOT_FOUND = PRUint32(-1); PRUint32 nsCSSKeyframesRule::FindRuleIndexForKey(const nsAString& aKey) { nsCSSParser parser; - nsTArray<float> keys; + InfallibleTArray<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; ) {
--- a/layout/style/nsCSSScanner.cpp +++ b/layout/style/nsCSSScanner.cpp @@ -269,17 +269,16 @@ nsCSSToken::AppendToString(nsString& aBu default: NS_ERROR("invalid token type"); break; } } nsCSSScanner::nsCSSScanner() : mReadPointer(nsnull) - , mLowLevelError(NS_OK) , mSVGMode(false) #ifdef CSS_REPORT_PARSE_ERRORS , mError(mErrorBuf, ArrayLength(mErrorBuf), 0) , mInnerWindowID(0) , mWindowIDCached(false) , mSheet(nsnull) , mLoader(nsnull) #endif @@ -296,30 +295,16 @@ nsCSSScanner::~nsCSSScanner() { MOZ_COUNT_DTOR(nsCSSScanner); Close(); if (mLocalPushback != mPushback) { delete [] mPushback; } } -nsresult -nsCSSScanner::GetLowLevelError() -{ - return mLowLevelError; -} - -void -nsCSSScanner::SetLowLevelError(nsresult aErrorCode) -{ - NS_ASSERTION(aErrorCode != NS_OK, "SetLowLevelError() used to clear error"); - NS_ASSERTION(mLowLevelError == NS_OK, "there is already a low-level error"); - mLowLevelError = aErrorCode; -} - #ifdef CSS_REPORT_PARSE_ERRORS #define CSS_ERRORS_PREF "layout.css.report_errors" static int CSSErrorsPrefChanged(const char *aPref, void *aClosure) { gReportErrors = Preferences::GetBool(CSS_ERRORS_PREF, true); return NS_OK; @@ -380,17 +365,16 @@ nsCSSScanner::Init(const nsAString& aBuf } } #endif // CSS_REPORT_PARSE_ERRORS mLineNumber = aLineNumber; // Reset variables that we use to keep track of our progress through the input mOffset = 0; mPushbackCount = 0; - mLowLevelError = NS_OK; #ifdef CSS_REPORT_PARSE_ERRORS mColNumber = 0; mSheet = aSheet; mLoader = aLoader; #endif }
--- a/layout/style/nsCSSScanner.h +++ b/layout/style/nsCSSScanner.h @@ -189,23 +189,16 @@ class nsCSSScanner { bool NextURL(nsCSSToken& aTokenResult); // It's really ugly that we have to expose this, but it's the easiest // way to do :nth-child() parsing sanely. (In particular, in // :nth-child(2n-1), "2n-1" is a dimension, and we need to push the // "-1" back so we can read it again as a number.) void Pushback(PRUnichar aChar); - // Reports operating-system level errors, e.g. read failures and - // out of memory. - nsresult GetLowLevelError(); - - // sometimes the parser wants to make note of a low-level error - void SetLowLevelError(nsresult aErrorCode); - protected: PRInt32 Read(); PRInt32 Peek(); bool LookAhead(PRUnichar aChar); bool LookAheadOrEOF(PRUnichar aChar); // expect either aChar or EOF void EatWhiteSpace(); bool ParseAndAppendEscape(nsString& aOutput, bool aInString); @@ -221,17 +214,16 @@ protected: const PRUnichar *mReadPointer; PRUint32 mOffset; PRUint32 mCount; PRUnichar* mPushback; PRInt32 mPushbackCount; PRInt32 mPushbackSize; PRUnichar mLocalPushback[4]; - nsresult mLowLevelError; PRUint32 mLineNumber; // True if we are in SVG mode; false in "normal" CSS bool mSVGMode; #ifdef CSS_REPORT_PARSE_ERRORS nsXPIDLCString mFileName; nsCOMPtr<nsIURI> mURI; // Cached so we know to not refetch mFileName PRUint32 mErrorLineNumber, mColNumber, mErrorColNumber;
--- a/layout/style/nsCSSValue.cpp +++ b/layout/style/nsCSSValue.cpp @@ -616,23 +616,18 @@ bool nsCSSValue::IsNonTransparentColor() !nsGkAtoms::transparent->Equals(GetStringValue(buf))) || (mUnit == eCSSUnit_EnumColor); } nsCSSValue::Array* nsCSSValue::InitFunction(nsCSSKeyword aFunctionId, PRUint32 aNumArgs) { nsRefPtr<nsCSSValue::Array> func = Array::Create(aNumArgs + 1); - if (!func) { - return nsnull; - } - func->Item(0).SetIntValue(aFunctionId, eCSSUnit_Enumerated); SetArrayValue(func, eCSSUnit_Function); - return func; } bool nsCSSValue::EqualsFunction(nsCSSKeyword aFunctionId) const { if (mUnit != eCSSUnit_Function) { return false; @@ -652,28 +647,30 @@ nsCSSValue::EqualsFunction(nsCSSKeyword already_AddRefed<nsStringBuffer> nsCSSValue::BufferFromString(const nsString& aValue) { nsStringBuffer* buffer = nsStringBuffer::FromString(aValue); if (buffer) { buffer->AddRef(); return buffer; } - + PRUnichar length = aValue.Length(); // NOTE: Alloc prouduces a new, already-addref'd (refcnt = 1) buffer. + // NOTE: String buffer allocation is currently fallible. buffer = nsStringBuffer::Alloc((length + 1) * sizeof(PRUnichar)); - if (NS_LIKELY(buffer != 0)) { - PRUnichar* data = static_cast<PRUnichar*>(buffer->Data()); - nsCharTraits<PRUnichar>::copy(data, aValue.get(), length); - // Null-terminate. - data[length] = 0; + if (NS_UNLIKELY(!buffer)) { + NS_RUNTIMEABORT("out of memory"); } + PRUnichar* data = static_cast<PRUnichar*>(buffer->Data()); + nsCharTraits<PRUnichar>::copy(data, aValue.get(), length); + // Null-terminate. + data[length] = 0; return buffer; } namespace { struct CSSValueSerializeCalcOps { CSSValueSerializeCalcOps(nsCSSProperty aProperty, nsAString& aResult) : mProperty(aProperty),
--- a/layout/style/nsCSSValue.h +++ b/layout/style/nsCSSValue.h @@ -44,17 +44,16 @@ #include "nsCRTGlue.h" #include "nsCSSKeywords.h" #include "nsCSSProperty.h" #include "nsColor.h" #include "nsCoord.h" #include "nsString.h" #include "nsStringBuffer.h" #include "nsTArray.h" -#include "mozilla/mozalloc.h" #include "nsStyleConsts.h" class imgIRequest; class nsIDocument; class nsIPrincipal; class nsPresContext; class nsIURI; @@ -549,21 +548,16 @@ protected: struct nsCSSValue::Array { // return |Array| with reference count of zero static Array* Create(size_t aItemCount) { return new (aItemCount) Array(aItemCount); } - static Array* Create(const mozilla::fallible_t& aFallible, - size_t aItemCount) { - return new (aFallible, aItemCount) Array(aItemCount); - } - nsCSSValue& operator[](size_t aIndex) { NS_ABORT_IF_FALSE(aIndex < mCount, "out of range"); return mArray[aIndex]; } const nsCSSValue& operator[](size_t aIndex) const { NS_ABORT_IF_FALSE(aIndex < mCount, "out of range"); return mArray[aIndex]; @@ -614,23 +608,16 @@ private: // alignment. nsCSSValue mArray[1]; void* operator new(size_t aSelfSize, size_t aItemCount) CPP_THROW_NEW { NS_ABORT_IF_FALSE(aItemCount > 0, "cannot have a 0 item count"); return ::operator new(aSelfSize + sizeof(nsCSSValue) * (aItemCount - 1)); } - void* operator new(size_t aSelfSize, const mozilla::fallible_t& aFallible, - size_t aItemCount) CPP_THROW_NEW { - NS_ABORT_IF_FALSE(aItemCount > 0, "cannot have a 0 item count"); - return ::operator new(aSelfSize + sizeof(nsCSSValue) * (aItemCount - 1), - aFallible); - } - void operator delete(void* aPtr) { ::operator delete(aPtr); } nsCSSValue* First() { return mArray; } const nsCSSValue* First() const { return mArray; } #define CSSVALUE_LIST_FOR_EXTRA_VALUES(var) \ for (nsCSSValue *var = First() + 1, *var##_end = First() + mCount; \ @@ -1014,17 +1001,18 @@ nsCSSValue::GetPairListValue() const NS_ABORT_IF_FALSE (mUnit == eCSSUnit_PairListDep, "not a pairlist value"); return mValue.mPairListDependent; } } struct nsCSSValueGradientStop { public: nsCSSValueGradientStop(); - // needed to keep bloat logs happy when we use the nsTArray in nsCSSValueGradient + // needed to keep bloat logs happy when we use the TArray + // in nsCSSValueGradient nsCSSValueGradientStop(const nsCSSValueGradientStop& aOther); ~nsCSSValueGradientStop(); nsCSSValue mLocation; nsCSSValue mColor; bool operator==(const nsCSSValueGradientStop& aOther) const { @@ -1047,17 +1035,17 @@ struct nsCSSValueGradient { // line position and angle nsCSSValuePair mBgPos; nsCSSValue mAngle; // Only meaningful if mIsRadial is true nsCSSValue mRadialShape; nsCSSValue mRadialSize; - nsTArray<nsCSSValueGradientStop> mStops; + InfallibleTArray<nsCSSValueGradientStop> mStops; bool operator==(const nsCSSValueGradient& aOther) const { if (mIsRadial != aOther.mIsRadial || mIsRepeating != aOther.mIsRepeating || mBgPos != aOther.mBgPos || mAngle != aOther.mAngle || mRadialShape != aOther.mRadialShape ||
--- a/layout/style/nsIMediaList.h +++ b/layout/style/nsIMediaList.h @@ -105,17 +105,17 @@ private: // FIXME: if we were better at maintaining invariants about clearing // rule cascades when media lists change, this could be a |const // nsMediaExpression*| instead. nsMediaExpression mExpression; bool mExpressionMatches; }; struct FeatureEntry { const nsMediaFeature *mFeature; - nsTArray<ExpressionEntry> mExpressions; + InfallibleTArray<ExpressionEntry> mExpressions; }; nsCOMPtr<nsIAtom> mMedium; nsTArray<FeatureEntry> mFeatureCache; }; class nsMediaQuery { public: nsMediaQuery() @@ -187,36 +187,32 @@ public: nsresult SetText(const nsAString& aMediaText); // Does this query apply to the presentation? // If |aKey| is non-null, add cache information to it. bool Matches(nsPresContext* aPresContext, nsMediaQueryResultCacheKey* aKey); nsresult SetStyleSheet(nsCSSStyleSheet* aSheet); - nsresult AppendQuery(nsAutoPtr<nsMediaQuery>& aQuery) { - // Takes ownership of aQuery (if it succeeds) - if (!mArray.AppendElement(aQuery.get())) { - return NS_ERROR_OUT_OF_MEMORY; - } - aQuery.forget(); - return NS_OK; + void AppendQuery(nsAutoPtr<nsMediaQuery>& aQuery) { + // Takes ownership of aQuery + mArray.AppendElement(aQuery.forget()); } nsresult Clone(nsMediaList** aResult); PRInt32 Count() { return mArray.Length(); } nsMediaQuery* MediumAt(PRInt32 aIndex) { return mArray[aIndex]; } void Clear() { mArray.Clear(); } protected: ~nsMediaList(); nsresult Delete(const nsAString & aOldMedium); nsresult Append(const nsAString & aOldMedium); - nsTArray<nsAutoPtr<nsMediaQuery> > mArray; + InfallibleTArray<nsAutoPtr<nsMediaQuery> > mArray; // not refcounted; sheet will let us know when it goes away // mStyleSheet is the sheet that needs to be dirtied when this medialist // changes nsCSSStyleSheet* mStyleSheet; }; #endif /* !defined(nsIMediaList_h_) */