From 8335fdff7d95f1173e771402af4c8495b1a94d6d Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 30 Jul 2009 14:56:52 +1200 Subject: [PATCH 01/61] Bug 506304. Walk all the way up to the nearest widget when computing event coordinates for windowless plugins. r=bz --HG-- extra : rebase_source : be25ce5ffbae7c90cf0b211ae818046873b6e09a --- layout/generic/nsObjectFrame.cpp | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/layout/generic/nsObjectFrame.cpp b/layout/generic/nsObjectFrame.cpp index 0936741f5a2b..53b354167d54 100644 --- a/layout/generic/nsObjectFrame.cpp +++ b/layout/generic/nsObjectFrame.cpp @@ -1045,23 +1045,9 @@ nsIntPoint nsObjectFrame::GetWindowOriginInPixels(PRBool aWindowless) // if it's windowless, let's make sure we have our origin set right // it may need to be corrected, like after scrolling if (aWindowless && parentWithView) { - // XXX Should this be replaced by nsIView::GetNearestWidget? - // The implementation below doesn't handle cases where the widget's origin - // doesn't coincide with its view's origin. - - nsIViewManager* parentVM = parentWithView->GetViewManager(); - - // Walk up all the views and add up their positions until we - // reach the first view with a window (non-null widget). This will give us our - // position relative to the containing window which is what we want to give the plugin - nsIView* theView = parentWithView; - while (theView && !theView->GetWidget()) { - if (theView->GetViewManager() != parentVM) - break; - - origin += theView->GetPosition(); - theView = theView->GetParent(); - } + nsPoint offsetToWidget; + parentWithView->GetNearestWidget(&offsetToWidget); + origin += offsetToWidget; } return nsIntPoint(PresContext()->AppUnitsToDevPixels(origin.x), From db83f27954653560d14e5ea041773d9f27a02dfb Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 30 Jul 2009 14:59:41 +1200 Subject: [PATCH 02/61] Bug 492309. Remove useless gfxTextRuNnFactory flags. r=vlad --HG-- extra : rebase_source : 4cdbc37f404c07f509adbfb581c662187813bc4a --- gfx/thebes/public/gfxFont.h | 37 +++------------------ gfx/thebes/public/gfxTextRunCache.h | 3 +- gfx/thebes/public/gfxTextRunWordCache.h | 16 ++++----- gfx/thebes/src/gfxAtsuiFonts.cpp | 1 - gfx/thebes/src/gfxCoreTextFonts.cpp | 1 - gfx/thebes/src/gfxFT2Fonts.cpp | 2 -- gfx/thebes/src/gfxFont.cpp | 24 ------------- gfx/thebes/src/gfxOS2Fonts.cpp | 2 -- gfx/thebes/src/gfxPangoFonts.cpp | 2 -- gfx/thebes/src/gfxTextRunWordCache.cpp | 4 +-- gfx/thebes/src/gfxWindowsFonts.cpp | 2 -- gfx/thebes/test/gfxFontSelectionTest.cpp | 1 - gfx/thebes/test/gfxTextRunPerfTest.cpp | 1 - layout/generic/nsTextFrameThebes.cpp | 7 +--- layout/generic/nsTextRunTransformations.cpp | 6 ++-- 15 files changed, 19 insertions(+), 90 deletions(-) diff --git a/gfx/thebes/public/gfxFont.h b/gfx/thebes/public/gfxFont.h index 795cac374bee..ef2d98603a8f 100644 --- a/gfx/thebes/public/gfxFont.h +++ b/gfx/thebes/public/gfxFont.h @@ -745,25 +745,16 @@ public: * on the spacing provider. */ TEXT_ENABLE_SPACING = 0x0008, - /** - * When set, GetSpacing can return negative spacing. - */ - TEXT_ENABLE_NEGATIVE_SPACING = 0x0010, /** * When set, GetHyphenationBreaks may return true for some character * positions, otherwise it will always return false for all characters. */ - TEXT_ENABLE_HYPHEN_BREAKS = 0x0040, + TEXT_ENABLE_HYPHEN_BREAKS = 0x0010, /** * When set, the text has no characters above 255 and it is stored * in the textrun in 8-bit format. */ - TEXT_IS_8BIT = 0x0080, - /** - * When set, the text may have UTF16 surrogate pairs, otherwise it - * doesn't. - */ - TEXT_HAS_SURROGATES = 0x0100, + TEXT_IS_8BIT = 0x0020, /** * When set, the RunMetrics::mBoundingBox field will be initialized * properly based on glyph extents, in particular, glyph extents that @@ -771,18 +762,18 @@ public: * and advance width of the glyph). When not set, it may just be the * standard font-box even if glyphs overflow. */ - TEXT_NEED_BOUNDING_BOX = 0x0200, + TEXT_NEED_BOUNDING_BOX = 0x0040, /** * When set, optional ligatures are disabled. Ligatures that are * required for legible text should still be enabled. */ - TEXT_DISABLE_OPTIONAL_LIGATURES = 0x0400, + TEXT_DISABLE_OPTIONAL_LIGATURES = 0x0080, /** * When set, the textrun should favour speed of construction over * quality. This may involve disabling ligatures and/or kerning or * other effects. */ - TEXT_OPTIMIZE_SPEED = 0x0800 + TEXT_OPTIMIZE_SPEED = 0x0100 }; /** @@ -1196,7 +1187,6 @@ public: FLAG_NOT_MISSING = 0x01, FLAG_NOT_CLUSTER_START = 0x02, FLAG_NOT_LIGATURE_GROUP_START = 0x04, - FLAG_LOW_SURROGATE = 0x08, GLYPH_COUNT_MASK = 0x00FFFF00U, GLYPH_COUNT_SHIFT = 8 @@ -1222,9 +1212,6 @@ public: PRUint32 GetSimpleGlyph() const { return mValue & GLYPH_MASK; } PRBool IsMissing() const { return (mValue & (FLAG_NOT_MISSING|FLAG_IS_SIMPLE_GLYPH)) == 0; } - PRBool IsLowSurrogate() const { - return (mValue & (FLAG_LOW_SURROGATE|FLAG_IS_SIMPLE_GLYPH)) == FLAG_LOW_SURROGATE; - } PRBool IsClusterStart() const { return (mValue & FLAG_IS_SIMPLE_GLYPH) || !(mValue & FLAG_NOT_CLUSTER_START); } @@ -1271,15 +1258,6 @@ public: (aGlyphCount << GLYPH_COUNT_SHIFT); return *this; } - /** - * Low surrogates don't have any glyphs and are not the start of - * a cluster or ligature group. - */ - CompressedGlyph& SetLowSurrogate() { - mValue = (mValue & FLAG_CAN_BREAK_BEFORE) | FLAG_NOT_MISSING | - FLAG_LOW_SURROGATE; - return *this; - } PRUint32 GetGlyphCount() const { NS_ASSERTION(!IsSimpleGlyph(), "Expected non-simple-glyph"); return (mValue & GLYPH_COUNT_MASK) >> GLYPH_COUNT_SHIFT; @@ -1351,11 +1329,6 @@ public: // API for setting up the textrun glyphs. Should only be called by // things that construct textruns. - /** - * Record every character that is the second half of a surrogate pair. - * This should be called after creating a Unicode textrun. - */ - void RecordSurrogates(const PRUnichar *aString); /** * We've found a run of text that should use a particular font. Call this * only during initialization when font substitution has been computed. diff --git a/gfx/thebes/public/gfxTextRunCache.h b/gfx/thebes/public/gfxTextRunCache.h index 92d09446de30..dbc6d97878db 100644 --- a/gfx/thebes/public/gfxTextRunCache.h +++ b/gfx/thebes/public/gfxTextRunCache.h @@ -52,8 +52,7 @@ public: * Get a textrun for the given text, using a global cache. The textrun * must be released via ReleaseTextRun, not deleted. * Do not set any state in the textrun (e.g. actual or potential linebreaks). - * Flags IS_8BIT, IS_ASCII and HAS_SURROGATES are automatically set - * appropriately. + * Flags IS_8BIT and IS_ASCII are automatically set appropriately. * Flag IS_PERSISTENT must NOT be set unless aText is guaranteed to live * forever. * The string can contain any characters, invalid ones will be stripped diff --git a/gfx/thebes/public/gfxTextRunWordCache.h b/gfx/thebes/public/gfxTextRunWordCache.h index bc5dc9226a94..9584c9557554 100644 --- a/gfx/thebes/public/gfxTextRunWordCache.h +++ b/gfx/thebes/public/gfxTextRunWordCache.h @@ -70,10 +70,10 @@ public: * Create a textrun using cached words. * Invalid characters (see gfxFontGroup::IsInvalidChar) will be automatically * treated as invisible missing. - * @param aFlags the flags TEXT_IS_ASCII and TEXT_HAS_SURROGATES must be set - * by the caller, if applicable; TEXT_IN_CACHE is added if we - * have a reference to the textrun in the cache and RemoveTextRun must - * be called when the textrun dies. + * @param aFlags the flag TEXT_IS_ASCII must be set by the caller, + * if applicable; TEXT_IN_CACHE is added if we have a reference to + * the textrun in the cache and RemoveTextRun must be called when the + * textrun dies. */ static gfxTextRun *MakeTextRun(const PRUnichar *aText, PRUint32 aLength, gfxFontGroup *aFontGroup, @@ -83,10 +83,10 @@ public: * Create a textrun using cached words. * Invalid characters (see gfxFontGroup::IsInvalidChar) will be automatically * treated as invisible missing. - * @param aFlags the flags TEXT_IS_ASCII and TEXT_HAS_SURROGATES must be set - * by the caller, if applicable; TEXT_IN_CACHE is added if we - * have a reference to the textrun in the cache and RemoveTextRun must - * be called when the textrun dies. + * @param aFlags the flag TEXT_IS_ASCII must be set by the caller, + * if applicable; TEXT_IN_CACHE is added if we have a reference to + * the textrun in the cache and RemoveTextRun must be called when the + * textrun dies. */ static gfxTextRun *MakeTextRun(const PRUint8 *aText, PRUint32 aLength, gfxFontGroup *aFontGroup, diff --git a/gfx/thebes/src/gfxAtsuiFonts.cpp b/gfx/thebes/src/gfxAtsuiFonts.cpp index c743ef770a79..5aa2bd715d00 100644 --- a/gfx/thebes/src/gfxAtsuiFonts.cpp +++ b/gfx/thebes/src/gfxAtsuiFonts.cpp @@ -714,7 +714,6 @@ gfxAtsuiFontGroup::MakeTextRun(const PRUnichar *aString, PRUint32 aLength, if (!textRun) return nsnull; - textRun->RecordSurrogates(aString); gfxPlatformMac::SetupClusterBoundaries(textRun, aString); PRUint32 maxLen; diff --git a/gfx/thebes/src/gfxCoreTextFonts.cpp b/gfx/thebes/src/gfxCoreTextFonts.cpp index 5d31b8ea4f7d..9f138b33e3b8 100644 --- a/gfx/thebes/src/gfxCoreTextFonts.cpp +++ b/gfx/thebes/src/gfxCoreTextFonts.cpp @@ -721,7 +721,6 @@ gfxCoreTextFontGroup::MakeTextRun(const PRUnichar *aString, PRUint32 aLength, if (!textRun) return nsnull; - textRun->RecordSurrogates(aString); gfxPlatformMac::SetupClusterBoundaries(textRun, aString); nsAutoString utf16; diff --git a/gfx/thebes/src/gfxFT2Fonts.cpp b/gfx/thebes/src/gfxFT2Fonts.cpp index d3b2d4381bff..8a7ef15ddbb0 100644 --- a/gfx/thebes/src/gfxFT2Fonts.cpp +++ b/gfx/thebes/src/gfxFT2Fonts.cpp @@ -289,8 +289,6 @@ gfxTextRun *gfxFT2FontGroup::MakeTextRun(const PRUnichar* aString, PRUint32 aLen if (!textRun) return nsnull; - textRun->RecordSurrogates(aString); - mString.Assign(nsDependentSubstring(aString, aString + aLength)); InitTextRun(textRun); diff --git a/gfx/thebes/src/gfxFont.cpp b/gfx/thebes/src/gfxFont.cpp index ffc3953f4d8c..75f22c583677 100644 --- a/gfx/thebes/src/gfxFont.cpp +++ b/gfx/thebes/src/gfxFont.cpp @@ -2377,30 +2377,6 @@ gfxTextRun::SetMissingGlyph(PRUint32 aIndex, PRUint32 aChar) mCharacterGlyphs[aIndex].SetMissing(1); } -void -gfxTextRun::RecordSurrogates(const PRUnichar *aString) -{ - // !! FIXME !! - // - // This is called from the platform font implementations when making text runs, but currently it - // doesn't do anything because callers do not (consistently, or ever?) set the TEXT_HAS_SURROGATES flag. - // However, I have not seen anything that relies on the surrogate flag on glyphs, so perhaps we can - // simply eliminate this and remove that flag from gfxTextRunFactory? - - if (!(mFlags & gfxTextRunFactory::TEXT_HAS_SURROGATES)) - return; - - // Remember which characters are low surrogates (the second half of - // a surrogate pair). - PRUint32 i; - gfxTextRun::CompressedGlyph g; - for (i = 0; i < mCharacterCount; ++i) { - if (NS_IS_LOW_SURROGATE(aString[i])) { - SetGlyphs(i, g.SetLowSurrogate(), nsnull); - } - } -} - static void ClearCharacters(gfxTextRun::CompressedGlyph *aGlyphs, PRUint32 aLength) { diff --git a/gfx/thebes/src/gfxOS2Fonts.cpp b/gfx/thebes/src/gfxOS2Fonts.cpp index 861520fcb49e..bc6b45ca5a48 100644 --- a/gfx/thebes/src/gfxOS2Fonts.cpp +++ b/gfx/thebes/src/gfxOS2Fonts.cpp @@ -548,8 +548,6 @@ gfxTextRun *gfxOS2FontGroup::MakeTextRun(const PRUnichar* aString, PRUint32 aLen mEnableKerning = !(aFlags & gfxTextRunFactory::TEXT_OPTIMIZE_SPEED); - textRun->RecordSurrogates(aString); - nsCAutoString utf8; PRInt32 headerLen = AppendDirectionalIndicatorUTF8(textRun->IsRightToLeft(), utf8); AppendUTF16toUTF8(Substring(aString, aString + aLength), utf8); diff --git a/gfx/thebes/src/gfxPangoFonts.cpp b/gfx/thebes/src/gfxPangoFonts.cpp index aaa0b2686d6d..316a64a399fb 100644 --- a/gfx/thebes/src/gfxPangoFonts.cpp +++ b/gfx/thebes/src/gfxPangoFonts.cpp @@ -2860,8 +2860,6 @@ gfxPangoFontGroup::MakeTextRun(const PRUnichar *aString, PRUint32 aLength, if (!run) return nsnull; - run->RecordSurrogates(aString); - nsCAutoString utf8; PRInt32 headerLen = AppendDirectionalIndicatorUTF8(run->IsRightToLeft(), utf8); AppendUTF16toUTF8(Substring(aString, aString + aLength), utf8); diff --git a/gfx/thebes/src/gfxTextRunWordCache.cpp b/gfx/thebes/src/gfxTextRunWordCache.cpp index 35e051ace1b2..e92cca0d502d 100644 --- a/gfx/thebes/src/gfxTextRunWordCache.cpp +++ b/gfx/thebes/src/gfxTextRunWordCache.cpp @@ -93,8 +93,8 @@ public: * Create a textrun using cached words. * Invalid characters (see gfxFontGroup::IsInvalidChar) will be automatically * treated as invisible missing. - * @param aFlags the flags TEXT_IS_ASCII and TEXT_HAS_SURROGATES must be set - * by the caller, if applicable + * @param aFlags the flag TEXT_IS_ASCII must be set by the caller, + * if applicable * @param aIsInCache if true is returned, then RemoveTextRun must be called * before the textrun changes or dies. */ diff --git a/gfx/thebes/src/gfxWindowsFonts.cpp b/gfx/thebes/src/gfxWindowsFonts.cpp index aec428abc3ea..9a97fcc180be 100644 --- a/gfx/thebes/src/gfxWindowsFonts.cpp +++ b/gfx/thebes/src/gfxWindowsFonts.cpp @@ -1477,8 +1477,6 @@ gfxWindowsFontGroup::MakeTextRun(const PRUnichar *aString, PRUint32 aLength, return nsnull; NS_ASSERTION(aParams->mContext, "MakeTextRun called without a gfxContext"); - textRun->RecordSurrogates(aString); - #ifdef FORCE_UNISCRIBE const PRBool isComplex = PR_TRUE; #else diff --git a/gfx/thebes/test/gfxFontSelectionTest.cpp b/gfx/thebes/test/gfxFontSelectionTest.cpp index 77f0b6422c00..6109babd0758 100644 --- a/gfx/thebes/test/gfxFontSelectionTest.cpp +++ b/gfx/thebes/test/gfxFontSelectionTest.cpp @@ -304,7 +304,6 @@ RunTest (TestEntry *test, gfxContext *ctx) { length = strlen(test->string); textRun = gfxTextRunWordCache::MakeTextRun(reinterpret_cast(test->string), length, fontGroup, ¶ms, flags); } else { - flags |= gfxTextRunFactory::TEXT_HAS_SURROGATES; // just in case NS_ConvertUTF8toUTF16 str(nsDependentCString(test->string)); length = str.Length(); textRun = gfxTextRunWordCache::MakeTextRun(str.get(), length, fontGroup, ¶ms, flags); diff --git a/gfx/thebes/test/gfxTextRunPerfTest.cpp b/gfx/thebes/test/gfxTextRunPerfTest.cpp index 84b57672d9f7..483dd2ab6d7b 100644 --- a/gfx/thebes/test/gfxTextRunPerfTest.cpp +++ b/gfx/thebes/test/gfxTextRunPerfTest.cpp @@ -119,7 +119,6 @@ RunTest (TestEntry *test, gfxContext *ctx) { length = strlen(test->mString); textRun = fontGroup->MakeTextRun(reinterpret_cast(test->mString), length, ¶ms, flags); } else { - flags |= gfxTextRunFactory::TEXT_HAS_SURROGATES; // just in case NS_ConvertUTF8toUTF16 str(nsDependentCString(test->mString)); length = str.Length(); textRun = fontGroup->MakeTextRun(str.get(), length, ¶ms, flags); diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index dca4e620f05d..5bad68046cbc 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -1434,12 +1434,7 @@ BuildTextRunsScanner::GetNextBreakBeforeFrame(PRUint32* aIndex) static PRUint32 GetSpacingFlags(nscoord spacing) { - if (!spacing) - return 0; - if (spacing > 0) - return gfxTextRunFactory::TEXT_ENABLE_SPACING; - return gfxTextRunFactory::TEXT_ENABLE_SPACING | - gfxTextRunFactory::TEXT_ENABLE_NEGATIVE_SPACING; + return spacing ? gfxTextRunFactory::TEXT_ENABLE_SPACING : 0; } static gfxFontGroup* diff --git a/layout/generic/nsTextRunTransformations.cpp b/layout/generic/nsTextRunTransformations.cpp index f0b5fb1cdd13..635b580f8891 100644 --- a/layout/generic/nsTextRunTransformations.cpp +++ b/layout/generic/nsTextRunTransformations.cpp @@ -173,15 +173,13 @@ MergeCharactersInTextRun(gfxTextRun* aDest, gfxTextRun* aSrc, // to merge S's (uppercase ß), so it's not worth it. if (k + 1 < iter.GetStringEnd() && aCharsToMerge[k + 1]) { - NS_ASSERTION(g.IsClusterStart() && g.IsLigatureGroupStart() && - !g.IsLowSurrogate(), + NS_ASSERTION(g.IsClusterStart() && g.IsLigatureGroupStart(), "Don't know how to merge this stuff"); continue; } NS_ASSERTION(mergeRunStart == k || - (g.IsClusterStart() && g.IsLigatureGroupStart() && - !g.IsLowSurrogate()), + (g.IsClusterStart() && g.IsLigatureGroupStart()), "Don't know how to merge this stuff"); // If the start of the merge run is actually a character that should From 3a0de712cc6318741023866902a9dd223d147a5c Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 30 Jul 2009 15:02:22 +1200 Subject: [PATCH 03/61] Bug 504311. Don't reframe text when white-space changes between preformatted values, or between non-preformatted values. r=bz --HG-- extra : rebase_source : 7f545ad1d85bcda74d18d9308539b45149a4a194 --- layout/style/crashtests/504311-1.xul | 24 ++++++++++++++++++++++++ layout/style/crashtests/crashtests.list | 1 + layout/style/nsStyleStruct.cpp | 3 ++- 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 layout/style/crashtests/504311-1.xul diff --git a/layout/style/crashtests/504311-1.xul b/layout/style/crashtests/504311-1.xul new file mode 100644 index 000000000000..e2d40fa70a07 --- /dev/null +++ b/layout/style/crashtests/504311-1.xul @@ -0,0 +1,24 @@ + + + + + + + + + + diff --git a/layout/style/crashtests/crashtests.list b/layout/style/crashtests/crashtests.list index fe390f391c15..97ebd56f53e7 100644 --- a/layout/style/crashtests/crashtests.list +++ b/layout/style/crashtests/crashtests.list @@ -39,3 +39,4 @@ load 473914-1.html skip load long-url-list-stack-overflow.html # skipped due to being slow (bug 477490) load 495269-1.html load 495269-2.html +load 504311-1.xul diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index beaa8ab012e3..49eb59a0043b 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -1873,13 +1873,14 @@ nsStyleText::~nsStyleText(void) { } nsChangeHint nsStyleText::CalcDifference(const nsStyleText& aOther) const { - if (mWhiteSpace != aOther.mWhiteSpace) { + if (NewlineIsSignificant() != aOther.NewlineIsSignificant()) { // This may require construction of suppressed text frames return NS_STYLE_HINT_FRAMECHANGE; } if ((mTextAlign != aOther.mTextAlign) || (mTextTransform != aOther.mTextTransform) || + (mWhiteSpace != aOther.mWhiteSpace) || (mWordWrap != aOther.mWordWrap) || (mLetterSpacing != aOther.mLetterSpacing) || (mLineHeight != aOther.mLineHeight) || From 039fd09cdf0456eb5ce5b6b1dcfb2f975e071f6a Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Thu, 30 Jul 2009 15:04:14 +1200 Subject: [PATCH 04/61] Bug 467988. Merge canvas mochitests into one file to speed up mochitest running. r=roc --HG-- extra : rebase_source : 9a4f90fdbe07759e3970dbf665d753b7320b345a --- content/canvas/test/Makefile.in | 687 +- content/canvas/test/test_canvas.html | 24276 +++++++++++++++++++++++++ 2 files changed, 24285 insertions(+), 678 deletions(-) create mode 100644 content/canvas/test/test_canvas.html diff --git a/content/canvas/test/Makefile.in b/content/canvas/test/Makefile.in index 96b52e9f87e2..571d677c1c23 100644 --- a/content/canvas/test/Makefile.in +++ b/content/canvas/test/Makefile.in @@ -45,656 +45,7 @@ relativesrcdir = content/canvas/test include $(DEPTH)/config/autoconf.mk include $(topsrcdir)/config/rules.mk _TEST_FILES_0 = \ - test_fallback.basic.html \ - test_fallback.multiple.html \ - test_fallback.nested.html \ - test_type.name.html \ - test_type.exists.html \ - test_type.delete.html \ - test_type.prototype.html \ - test_type.replace.html \ - test_type.extend.html \ - test_size.attributes.html \ - test_size.attributes.type.get.html \ - test_size.attributes.type.set.html \ - test_size.attributes.default.html \ - test_size.attributes.reflect.1.html \ - test_size.attributes.reflect.2.html \ - test_size.attributes.removed.html \ - test_size.attributes.parse.whitespace.html \ - test_size.attributes.parse.nonnumber.html \ - test_size.attributes.parse.zero.html \ - test_size.attributes.parse.negative.html \ - test_size.attributes.parse.zerosuffix.html \ - test_size.attributes.parse.floatsuffix.html \ - test_size.attributes.parse.badsuffix.html \ - test_size.attributes.parse.percentsuffix.html \ - test_size.attributes.setAttribute.whitespace.html \ - test_size.attributes.setAttribute.nonnumber.html \ - test_size.attributes.setAttribute.zero.html \ - test_size.attributes.setAttribute.negative.html \ - test_size.attributes.setAttribute.zerosuffix.html \ - test_size.attributes.setAttribute.floatsuffix.html \ - test_size.attributes.setAttribute.badsuffix.html \ - test_size.attributes.setAttribute.percentsuffix.html \ - test_size.attributes.style.html \ - test_initial.colour.html \ - test_initial.reset.different.html \ - test_initial.reset.same.html \ - test_initial.reset.path.html \ - test_initial.reset.clip.html \ - test_initial.reset.transform.html \ - test_initial.reset.gradient.html \ - test_initial.reset.pattern.html \ - test_context.emptystring.html \ - test_context.unrecognised.badname.html \ - test_context.unrecognised.badsuffix.html \ - test_context.unrecognised.nullsuffix.html \ - test_context.unrecognised.unicode.html \ - test_context.casesensitive.html \ - test_context.arguments.missing.html \ - test_context.arguments.extra.html \ - test_toDataURL.default.html \ - test_toDataURL.png.html \ - test_toDataURL.unrecognised.html \ - test_toDataURL.lowercase.html \ - test_toDataURL.arguments.1.html \ - test_toDataURL.arguments.2.html \ - test_toDataURL.arguments.3.html \ - test_toDataURL.nocontext.html \ - test_toDataURL.zerosize.html \ - test_toDataURL.primarycolours.html \ - test_toDataURL.complexcolours.html \ - test_2d.getcontext.exists.html \ - test_2d.type.exists.html \ - test_2d.type.delete.html \ - test_2d.type.prototype.html \ - test_2d.type.replace.html \ - test_2d.type.extend.html \ - test_2d.getcontext.unique.html \ - test_2d.getcontext.shared.html \ - test_2d.voidreturn.html \ - test_2d.missingargs.html \ - test_2d.scaled.html \ - test_2d.canvas.reference.html \ - test_2d.canvas.readonly.html \ - test_2d.state.saverestore.strokeStyle.html \ - test_2d.state.saverestore.fillStyle.html \ - test_2d.state.saverestore.globalAlpha.html \ - test_2d.state.saverestore.lineWidth.html \ - test_2d.state.saverestore.lineCap.html \ - test_2d.state.saverestore.lineJoin.html \ - test_2d.state.saverestore.miterLimit.html \ - test_2d.state.saverestore.shadowOffsetX.html \ - test_2d.state.saverestore.shadowOffsetY.html \ - test_2d.state.saverestore.shadowBlur.html \ - test_2d.state.saverestore.shadowColor.html \ - test_2d.state.saverestore.globalCompositeOperation.html \ - test_initial.reset.2dstate.html \ - test_2d.state.saverestore.transformation.html \ - test_2d.state.saverestore.clip.html \ - test_2d.state.saverestore.path.html \ - test_2d.state.saverestore.bitmap.html \ - test_2d.state.saverestore.stack.html \ - test_2d.state.saverestore.stackdepth.html \ - test_2d.state.saverestore.underflow.html \ - test_2d.transformation.order.html \ - test_2d.transformation.scale.basic.html \ - test_2d.transformation.scale.zero.html \ - test_2d.transformation.scale.negative.html \ - test_2d.transformation.scale.large.html \ - test_2d.transformation.scale.nonfinite.html \ - test_2d.transformation.scale.multiple.html \ - $(NULL) - -_TEST_FILES_1 = \ - test_2d.transformation.rotate.zero.html \ - test_2d.transformation.rotate.radians.html \ - test_2d.transformation.rotate.direction.html \ - test_2d.transformation.rotate.wrap.html \ - test_2d.transformation.rotate.wrapnegative.html \ - test_2d.transformation.rotate.nonfinite.html \ - test_2d.transformation.translate.basic.html \ - test_2d.transformation.translate.nonfinite.html \ - test_2d.transformation.transform.identity.html \ - test_2d.transformation.transform.skewed.html \ - test_2d.transformation.transform.multiply.html \ - test_2d.transformation.transform.nonfinite.html \ - test_2d.transformation.setTransform.skewed.html \ - test_2d.transformation.setTransform.multiple.html \ - test_2d.transformation.setTransform.nonfinite.html \ - test_2d.composite.globalAlpha.range.html \ - test_2d.composite.globalAlpha.invalid.html \ - test_2d.composite.globalAlpha.default.html \ - test_2d.composite.globalAlpha.fill.html \ - test_2d.composite.globalAlpha.image.html \ - test_2d.composite.globalAlpha.canvas.html \ - test_2d.composite.globalAlpha.imagepattern.html \ - test_2d.composite.globalAlpha.canvaspattern.html \ - test_2d.composite.solid.source-over.html \ - test_2d.composite.solid.destination-over.html \ - test_2d.composite.solid.source-in.html \ - test_2d.composite.solid.destination-in.html \ - test_2d.composite.solid.source-out.html \ - test_2d.composite.solid.destination-out.html \ - test_2d.composite.solid.source-atop.html \ - test_2d.composite.solid.destination-atop.html \ - test_2d.composite.solid.copy.html \ - test_2d.composite.transparent.source-over.html \ - test_2d.composite.transparent.destination-over.html \ - test_2d.composite.transparent.source-in.html \ - test_2d.composite.transparent.destination-in.html \ - test_2d.composite.transparent.source-out.html \ - test_2d.composite.transparent.destination-out.html \ - test_2d.composite.transparent.source-atop.html \ - test_2d.composite.transparent.destination-atop.html \ - test_2d.composite.transparent.copy.html \ - test_2d.composite.image.source-over.html \ - test_2d.composite.image.destination-over.html \ - test_2d.composite.image.destination-out.html \ - test_2d.composite.image.source-atop.html \ - test_2d.composite.image.copy.html \ - test_2d.composite.canvas.source-over.html \ - test_2d.composite.canvas.destination-over.html \ - test_2d.composite.canvas.destination-out.html \ - test_2d.composite.canvas.source-atop.html \ - test_2d.composite.canvas.copy.html \ - test_2d.composite.uncovered.fill.copy.html \ - test_2d.composite.uncovered.image.copy.html \ - test_2d.composite.uncovered.pattern.copy.html \ - test_2d.composite.clip.source-over.html \ - test_2d.composite.clip.destination-over.html \ - test_2d.composite.clip.source-in.html \ - test_2d.composite.clip.destination-in.html \ - test_2d.composite.clip.source-out.html \ - test_2d.composite.clip.destination-out.html \ - test_2d.composite.clip.source-atop.html \ - test_2d.composite.clip.destination-atop.html \ - test_2d.composite.clip.copy.html \ - test_2d.composite.operation.get.html \ - test_2d.composite.operation.unrecognised.html \ - test_2d.composite.operation.darker.html \ - test_2d.composite.operation.over.html \ - test_2d.composite.operation.clear.html \ - test_2d.composite.operation.highlight.html \ - test_2d.composite.operation.nullsuffix.html \ - $(NULL) - -_TEST_FILES_2 = \ - test_2d.composite.operation.casesensitive.html \ - test_2d.composite.operation.default.html \ - test_2d.fillStyle.parse.html4.html \ - test_2d.fillStyle.parse.hex3.html \ - test_2d.fillStyle.parse.hex6.html \ - test_2d.fillStyle.parse.rgb-num.html \ - test_2d.fillStyle.parse.rgb-clamp-1.html \ - test_2d.fillStyle.parse.rgb-clamp-2.html \ - test_2d.fillStyle.parse.rgb-clamp-3.html \ - test_2d.fillStyle.parse.rgb-clamp-4.html \ - test_2d.fillStyle.parse.rgb-clamp-5.html \ - test_2d.fillStyle.parse.rgb-percent.html \ - test_2d.fillStyle.parse.rgba-solid-1.html \ - test_2d.fillStyle.parse.rgba-solid-2.html \ - test_2d.fillStyle.parse.rgba-num-1.html \ - test_2d.fillStyle.parse.rgba-num-2.html \ - test_2d.fillStyle.parse.rgba-percent.html \ - test_2d.fillStyle.parse.rgba-clamp-1.html \ - test_2d.fillStyle.parse.rgba-clamp-2.html \ - test_2d.fillStyle.parse.transparent-1.html \ - test_2d.fillStyle.parse.transparent-2.html \ - test_2d.fillStyle.parse.hsl-1.html \ - test_2d.fillStyle.parse.hsl-2.html \ - test_2d.fillStyle.parse.hsl-3.html \ - test_2d.fillStyle.parse.hsl-4.html \ - test_2d.fillStyle.parse.hsl-5.html \ - test_2d.fillStyle.parse.hsl-clamp-1.html \ - test_2d.fillStyle.parse.hsl-clamp-2.html \ - test_2d.fillStyle.parse.hsl-clamp-3.html \ - test_2d.fillStyle.parse.hsl-clamp-4.html \ - test_2d.fillStyle.parse.hsla-1.html \ - test_2d.fillStyle.parse.hsla-2.html \ - test_2d.fillStyle.parse.hsla-clamp-1.html \ - test_2d.fillStyle.parse.hsla-clamp-2.html \ - test_2d.fillStyle.parse.hsla-clamp-3.html \ - test_2d.fillStyle.parse.hsla-clamp-4.html \ - test_2d.fillStyle.parse.hsla-clamp-5.html \ - test_2d.fillStyle.parse.hsla-clamp-6.html \ - test_2d.fillStyle.parse.svg-1.html \ - test_2d.fillStyle.parse.svg-2.html \ - test_2d.fillStyle.parse.invalid.hex3.html \ - test_2d.fillStyle.parse.invalid.hex6.html \ - test_2d.fillStyle.parse.invalid.rgb-1.html \ - test_2d.fillStyle.parse.invalid.rgb-2.html \ - test_2d.fillStyle.parse.invalid.rgb-3.html \ - test_2d.fillStyle.parse.invalid.rgb-4.html \ - test_2d.fillStyle.parse.invalid.rgb-5.html \ - test_2d.fillStyle.parse.invalid.rgb-6.html \ - test_2d.fillStyle.parse.invalid.rgb-7.html \ - test_2d.fillStyle.parse.invalid.rgba-1.html \ - test_2d.fillStyle.parse.invalid.rgba-2.html \ - test_2d.fillStyle.parse.invalid.rgba-3.html \ - test_2d.fillStyle.parse.invalid.rgba-4.html \ - test_2d.fillStyle.parse.invalid.rgba-5.html \ - test_2d.fillStyle.parse.invalid.hsl-1.html \ - test_2d.fillStyle.parse.invalid.hsl-2.html \ - test_2d.fillStyle.parse.invalid.hsl-3.html \ - test_2d.fillStyle.parse.invalid.hsl-4.html \ - test_2d.fillStyle.parse.invalid.hsl-5.html \ - test_2d.fillStyle.parse.invalid.hsla-1.html \ - test_2d.fillStyle.parse.invalid.hsla-2.html \ - test_2d.fillStyle.parse.system.html \ - test_2d.fillStyle.parse.current.basic.html \ - test_2d.fillStyle.parse.current.changed.html \ - test_2d.fillStyle.parse.current.removed.html \ - test_2d.fillStyle.invalidstring.html \ - test_2d.fillStyle.invalidtype.html \ - test_2d.fillStyle.get.solid.html \ - test_2d.fillStyle.get.semitransparent.html \ - test_2d.fillStyle.get.transparent.html \ - test_2d.fillStyle.default.html \ - test_2d.strokeStyle.default.html \ - test_2d.gradient.object.type.html \ - test_2d.gradient.object.return.html \ - test_2d.gradient.interpolate.solid.html \ - test_2d.gradient.interpolate.colour.html \ - test_2d.gradient.interpolate.alpha.html \ - test_2d.gradient.interpolate.colouralpha.html \ - test_2d.gradient.interpolate.outside.html \ - test_2d.gradient.interpolate.zerosize.html \ - test_2d.gradient.interpolate.vertical.html \ - test_2d.gradient.interpolate.multiple.html \ - test_2d.gradient.interpolate.overlap.html \ - test_2d.gradient.interpolate.overlap2.html \ - test_2d.gradient.empty.html \ - test_2d.gradient.object.update.html \ - test_2d.gradient.object.compare.html \ - test_2d.gradient.object.crosscanvas.html \ - test_2d.gradient.object.invalidoffset.html \ - test_2d.gradient.object.invalidcolour.html \ - test_2d.gradient.linear.nonfinite.html \ - test_2d.gradient.linear.transform.1.html \ - test_2d.gradient.linear.transform.2.html \ - test_2d.gradient.linear.transform.3.html \ - test_2d.gradient.radial.negative.html \ - test_2d.gradient.radial.nonfinite.html \ - test_2d.gradient.radial.inside1.html \ - $(NULL) - -_TEST_FILES_3 = \ - test_2d.gradient.radial.cone.bottom.html \ - test_2d.gradient.radial.cone.cylinder.html \ - test_2d.gradient.radial.cone.shape1.html \ - test_2d.gradient.radial.transform.1.html \ - test_2d.gradient.radial.transform.2.html \ - test_2d.gradient.radial.transform.3.html \ - test_2d.pattern.basic.type.html \ - test_2d.pattern.basic.image.html \ - test_2d.pattern.basic.canvas.html \ - test_2d.pattern.basic.zerocanvas.html \ - test_2d.pattern.basic.nocontext.html \ - test_2d.pattern.image.undefined.html \ - test_2d.pattern.image.null.html \ - test_2d.pattern.image.string.html \ - test_2d.pattern.image.incomplete.html \ - test_2d.pattern.image.broken.html \ - test_2d.pattern.repeat.empty.html \ - test_2d.pattern.repeat.null.html \ - test_2d.pattern.repeat.undefined.html \ - test_2d.pattern.repeat.unrecognised.html \ - test_2d.pattern.repeat.case.html \ - test_2d.pattern.repeat.nullsuffix.html \ - test_2d.pattern.modify.image1.html \ - test_2d.pattern.modify.image2.html \ - test_2d.pattern.modify.canvas1.html \ - test_2d.pattern.modify.canvas2.html \ - test_2d.pattern.crosscanvas.html \ - test_2d.pattern.paint.norepeat.basic.html \ - test_2d.pattern.paint.norepeat.outside.html \ - test_2d.pattern.paint.norepeat.coord1.html \ - test_2d.pattern.paint.norepeat.coord2.html \ - test_2d.pattern.paint.norepeat.coord3.html \ - test_2d.pattern.paint.repeat.basic.html \ - test_2d.pattern.paint.repeat.outside.html \ - test_2d.pattern.paint.repeat.coord1.html \ - test_2d.pattern.paint.repeat.coord2.html \ - test_2d.pattern.paint.repeat.coord3.html \ - test_2d.pattern.paint.repeatx.basic.html \ - test_2d.pattern.paint.repeatx.outside.html \ - test_2d.pattern.paint.repeatx.coord1.html \ - test_2d.pattern.paint.repeaty.basic.html \ - test_2d.pattern.paint.repeaty.outside.html \ - test_2d.pattern.paint.repeaty.coord1.html \ - test_2d.pattern.paint.orientation.image.html \ - test_2d.pattern.paint.orientation.canvas.html \ - test_2d.pattern.animated.gif.html \ - test_2d.line.defaults.html \ - test_2d.line.width.basic.html \ - test_2d.line.width.transformed.html \ - test_2d.line.width.invalid.html \ - test_2d.line.cap.butt.html \ - test_2d.line.cap.round.html \ - test_2d.line.cap.square.html \ - test_2d.line.cap.open.html \ - test_2d.line.cap.invalid.html \ - test_2d.line.join.bevel.html \ - test_2d.line.join.round.html \ - test_2d.line.join.miter.html \ - test_2d.line.join.open.html \ - test_2d.line.join.closed.html \ - test_2d.line.join.invalid.html \ - test_2d.line.miter.exceeded.html \ - test_2d.line.miter.acute.html \ - test_2d.line.miter.obtuse.html \ - test_2d.line.miter.rightangle.html \ - test_2d.line.miter.lineedge.html \ - test_2d.line.miter.within.html \ - test_2d.line.miter.invalid.html \ - test_2d.line.cross.html \ - test_2d.line.union.html \ - test_2d.clearRect.basic.html \ - test_2d.clearRect.path.html \ - test_2d.clearRect.zero.html \ - test_2d.clearRect.negative.html \ - test_2d.clearRect.transform.html \ - test_2d.clearRect.globalalpha.html \ - test_2d.clearRect.globalcomposite.html \ - test_2d.clearRect.clip.html \ - test_2d.clearRect.shadow.html \ - test_2d.clearRect.nonfinite.html \ - test_2d.fillRect.basic.html \ - test_2d.fillRect.path.html \ - test_2d.fillRect.zero.html \ - test_2d.fillRect.negative.html \ - test_2d.fillRect.transform.html \ - test_2d.fillRect.clip.html \ - test_2d.fillRect.shadow.html \ - $(NULL) - -_TEST_FILES_4 = \ - test_2d.fillRect.nonfinite.html \ - test_2d.strokeRect.basic.html \ - test_2d.strokeRect.path.html \ - test_2d.strokeRect.zero.1.html \ - test_2d.strokeRect.zero.2.html \ - test_2d.strokeRect.zero.3.html \ - test_2d.strokeRect.zero.4.html \ - test_2d.strokeRect.negative.html \ - test_2d.strokeRect.transform.html \ - test_2d.strokeRect.globalalpha.html \ - test_2d.strokeRect.globalcomposite.html \ - test_2d.strokeRect.clip.html \ - test_2d.strokeRect.shadow.html \ - test_2d.strokeRect.nonfinite.html \ - test_2d.path.initial.html \ - test_2d.path.beginPath.html \ - test_2d.path.moveTo.basic.html \ - test_2d.path.moveTo.newsubpath.html \ - test_2d.path.moveTo.multiple.html \ - test_2d.path.moveTo.nonfinite.html \ - test_2d.path.closePath.empty.html \ - test_2d.path.closePath.newline.html \ - test_2d.path.closePath.nextpoint.html \ - test_2d.path.lineTo.emptysubpath.html \ - test_2d.path.lineTo.basic.html \ - test_2d.path.lineTo.nextpoint.html \ - test_2d.path.lineTo.nonfinite.html \ - test_2d.path.quadraticCurveTo.emptysubpath.html \ - test_2d.path.quadraticCurveTo.basic.html \ - test_2d.path.quadraticCurveTo.shape.html \ - test_2d.path.quadraticCurveTo.scaled.html \ - test_2d.path.quadraticCurveTo.nonfinite.html \ - test_2d.path.bezierCurveTo.emptysubpath.html \ - test_2d.path.bezierCurveTo.basic.html \ - test_2d.path.bezierCurveTo.shape.html \ - test_2d.path.bezierCurveTo.scaled.html \ - test_2d.path.bezierCurveTo.nonfinite.html \ - test_2d.path.arcTo.emptysubpath.html \ - test_2d.path.arcTo.coincide.1.html \ - test_2d.path.arcTo.coincide.2.html \ - test_2d.path.arcTo.collinear.1.html \ - test_2d.path.arcTo.collinear.2.html \ - test_2d.path.arcTo.collinear.3.html \ - test_2d.path.arcTo.shape.curve1.html \ - test_2d.path.arcTo.shape.curve2.html \ - test_2d.path.arcTo.shape.start.html \ - test_2d.path.arcTo.shape.end.html \ - test_2d.path.arcTo.negative.html \ - test_2d.path.arcTo.zero.1.html \ - test_2d.path.arcTo.zero.2.html \ - test_2d.path.arcTo.transformation.html \ - test_2d.path.arcTo.scale.html \ - test_2d.path.arcTo.nonfinite.html \ - test_2d.path.arc.empty.html \ - test_2d.path.arc.nonempty.html \ - test_2d.path.arc.end.html \ - test_2d.path.arc.angle.1.html \ - test_2d.path.arc.angle.2.html \ - test_2d.path.arc.angle.3.html \ - test_2d.path.arc.angle.4.html \ - test_2d.path.arc.angle.5.html \ - test_2d.path.arc.angle.6.html \ - test_2d.path.arc.zero.1.html \ - test_2d.path.arc.zero.2.html \ - test_2d.path.arc.twopie.1.html \ - test_2d.path.arc.twopie.2.html \ - test_2d.path.arc.twopie.3.html \ - test_2d.path.arc.twopie.4.html \ - test_2d.path.arc.shape.1.html \ - test_2d.path.arc.shape.2.html \ - test_2d.path.arc.shape.4.html \ - test_2d.path.arc.shape.5.html \ - test_2d.path.arc.selfintersect.1.html \ - test_2d.path.arc.selfintersect.2.html \ - test_2d.path.arc.negative.html \ - test_2d.path.arc.zeroradius.html \ - test_2d.path.arc.scale.1.html \ - test_2d.path.arc.scale.2.html \ - test_2d.path.arc.nonfinite.html \ - test_2d.path.rect.basic.html \ - test_2d.path.rect.newsubpath.html \ - test_2d.path.rect.closed.html \ - test_2d.path.rect.end.1.html \ - test_2d.path.rect.end.2.html \ - test_2d.path.rect.zero.1.html \ - test_2d.path.rect.zero.2.html \ - test_2d.path.rect.zero.3.html \ - test_2d.path.rect.zero.4.html \ - test_2d.path.rect.zero.5.html \ - test_2d.path.rect.negative.html \ - test_2d.path.rect.winding.html \ - test_2d.path.rect.nonfinite.html \ - test_2d.path.fill.overlap.html \ - test_2d.path.fill.winding.add.html \ - test_2d.path.fill.winding.subtract.1.html \ - test_2d.path.fill.winding.subtract.2.html \ - $(NULL) - -_TEST_FILES_5 = \ - test_2d.path.fill.winding.subtract.3.html \ - test_2d.path.fill.closed.basic.html \ - test_2d.path.fill.closed.unaffected.html \ - test_2d.path.stroke.overlap.html \ - test_2d.path.stroke.union.html \ - test_2d.path.stroke.unaffected.html \ - test_2d.path.stroke.scale1.html \ - test_2d.path.stroke.scale2.html \ - test_2d.path.stroke.skew.html \ - test_2d.path.stroke.empty.html \ - test_2d.path.stroke.prune.line.html \ - test_2d.path.stroke.prune.closed.html \ - test_2d.path.stroke.prune.curve.html \ - test_2d.path.stroke.prune.arc.html \ - test_2d.path.stroke.prune.rect.html \ - test_2d.path.stroke.prune.corner.html \ - test_2d.path.transformation.basic.html \ - test_2d.path.transformation.multiple.html \ - test_2d.path.transformation.changing.html \ - test_2d.path.clip.empty.html \ - test_2d.path.clip.basic.1.html \ - test_2d.path.clip.basic.2.html \ - test_2d.path.clip.intersect.html \ - test_2d.path.clip.winding.1.html \ - test_2d.path.clip.winding.2.html \ - test_2d.path.clip.unaffected.html \ - test_2d.path.isPointInPath.basic.1.html \ - test_2d.path.isPointInPath.basic.2.html \ - test_2d.path.isPointInPath.edge.html \ - test_2d.path.isPointInPath.empty.html \ - test_2d.path.isPointInPath.subpath.html \ - test_2d.path.isPointInPath.outside.html \ - test_2d.path.isPointInPath.unclosed.html \ - test_2d.path.isPointInPath.arc.html \ - test_2d.path.isPointInPath.bigarc.html \ - test_2d.path.isPointInPath.bezier.html \ - test_2d.path.isPointInPath.winding.html \ - test_2d.path.isPointInPath.transform.1.html \ - test_2d.path.isPointInPath.transform.2.html \ - test_2d.path.isPointInPath.transform.3.html \ - test_2d.path.isPointInPath.nonfinite.html \ - test_2d.drawImage.3arg.html \ - test_2d.drawImage.5arg.html \ - test_2d.drawImage.9arg.basic.html \ - test_2d.drawImage.9arg.sourcepos.html \ - test_2d.drawImage.9arg.sourcesize.html \ - test_2d.drawImage.9arg.destpos.html \ - test_2d.drawImage.9arg.destsize.html \ - test_2d.drawImage.canvas.html \ - test_2d.drawImage.self.1.html \ - test_2d.drawImage.self.2.html \ - test_2d.drawImage.null.html \ - test_2d.drawImage.wrongtype.html \ - test_2d.drawImage.floatsource.html \ - test_2d.drawImage.zerosource.html \ - test_2d.drawImage.negativesource.html \ - test_2d.drawImage.negativedest.html \ - test_2d.drawImage.outsidesource.html \ - test_2d.drawImage.incomplete.html \ - test_2d.drawImage.broken.html \ - test_2d.drawImage.animated.gif.html \ - test_2d.drawImage.animated.apng.html \ - test_2d.drawImage.animated.poster.html \ - test_2d.drawImage.path.html \ - test_2d.drawImage.transform.html \ - test_2d.drawImage.alpha.html \ - test_2d.drawImage.clip.html \ - test_2d.drawImage.composite.html \ - test_2d.drawImage.nowrap.html \ - test_2d.drawImage.nonfinite.html \ - test_2d.imageData.create.basic.html \ - test_2d.imageData.create.type.html \ - test_2d.imageData.create.initial.html \ - test_2d.imageData.create.large.html \ - test_2d.imageData.create.tiny.html \ - test_2d.imageData.create.negative.html \ - test_2d.imageData.create.zero.html \ - test_2d.imageData.create.nonfinite.html \ - test_2d.imageData.create.round.html \ - test_2d.imageData.get.basic.html \ - test_2d.imageData.get.type.html \ - test_2d.imageData.get.zero.html \ - test_2d.imageData.get.nonfinite.html \ - test_2d.imageData.get.source.outside.html \ - test_2d.imageData.get.source.negative.html \ - test_2d.imageData.get.source.size.html \ - test_2d.imageData.get.tiny.html \ - test_2d.imageData.get.nonpremul.html \ - test_2d.imageData.get.range.html \ - test_2d.imageData.get.clamp.html \ - test_2d.imageData.get.order.cols.html \ - test_2d.imageData.get.order.rows.html \ - test_2d.imageData.get.order.rgb.html \ - test_2d.imageData.get.order.alpha.html \ - test_2d.imageData.get.unaffected.html \ - test_2d.imageData.object.properties.html \ - test_2d.imageData.object.readonly.html \ - test_2d.imageData.object.ctor.html \ - test_2d.imageData.object.set.html \ - test_2d.imageData.object.undefined.html \ - $(NULL) - -_TEST_FILES_6 = \ - test_2d.imageData.object.nan.html \ - test_2d.imageData.object.string.html \ - test_2d.imageData.object.clamp.html \ - test_2d.imageData.object.round.html \ - test_2d.imageData.put.null.html \ - test_2d.imageData.put.nonfinite.html \ - test_2d.imageData.put.basic.html \ - test_2d.imageData.put.created.html \ - test_2d.imageData.put.wrongtype.html \ - test_2d.imageData.put.cross.html \ - test_2d.imageData.put.alpha.html \ - test_2d.imageData.put.modified.html \ - test_2d.imageData.put.dirty.zero.html \ - test_2d.imageData.put.dirty.rect1.html \ - test_2d.imageData.put.dirty.rect2.html \ - test_2d.imageData.put.dirty.negative.html \ - test_2d.imageData.put.dirty.outside.html \ - test_2d.imageData.put.unchanged.html \ - test_2d.imageData.put.unaffected.html \ - test_2d.imageData.put.clip.html \ - test_2d.imageData.put.path.html \ - test_2d.shadow.attributes.shadowBlur.1.html \ - test_2d.shadow.attributes.shadowBlur.2.html \ - test_2d.shadow.attributes.shadowOffset.1.html \ - test_2d.shadow.attributes.shadowOffset.2.html \ - test_2d.shadow.attributes.shadowColor.1.html \ - test_2d.shadow.attributes.shadowColor.2.html \ - test_2d.shadow.basic.1.html \ - test_2d.shadow.basic.2.html \ - test_2d.shadow.offset.positiveX.html \ - test_2d.shadow.offset.negativeX.html \ - test_2d.shadow.offset.positiveY.html \ - test_2d.shadow.offset.negativeY.html \ - test_2d.shadow.outside.html \ - test_2d.shadow.clip.1.html \ - test_2d.shadow.clip.2.html \ - test_2d.shadow.clip.3.html \ - test_2d.shadow.stroke.basic.html \ - test_2d.shadow.stroke.cap.1.html \ - test_2d.shadow.stroke.cap.2.html \ - test_2d.shadow.stroke.join.1.html \ - test_2d.shadow.stroke.join.2.html \ - test_2d.shadow.stroke.join.3.html \ - test_2d.shadow.image.basic.html \ - test_2d.shadow.image.transparent.1.html \ - test_2d.shadow.image.transparent.2.html \ - test_2d.shadow.image.alpha.html \ - test_2d.shadow.image.section.html \ - test_2d.shadow.image.scale.html \ - test_2d.shadow.canvas.basic.html \ - test_2d.shadow.canvas.transparent.1.html \ - test_2d.shadow.canvas.transparent.2.html \ - test_2d.shadow.canvas.alpha.html \ - test_2d.shadow.pattern.basic.html \ - test_2d.shadow.pattern.transparent.1.html \ - test_2d.shadow.pattern.transparent.2.html \ - test_2d.shadow.pattern.alpha.html \ - test_2d.shadow.gradient.basic.html \ - test_2d.shadow.gradient.transparent.1.html \ - test_2d.shadow.gradient.transparent.2.html \ - test_2d.shadow.gradient.alpha.html \ - test_2d.shadow.transform.1.html \ - test_2d.shadow.transform.2.html \ - test_2d.shadow.blur.low.html \ - test_2d.shadow.blur.high.html \ - test_2d.shadow.alpha.1.html \ - test_2d.shadow.alpha.2.html \ - test_2d.shadow.alpha.3.html \ - test_2d.shadow.alpha.4.html \ - test_2d.shadow.alpha.5.html \ - test_2d.shadow.composite.1.html \ - test_2d.shadow.composite.2.html \ - test_2d.shadow.composite.3.html \ - test_2d.shadow.composite.4.html \ - test_2d.imageSmoothing.html \ - test_bug397524.html \ - test_bug405982.html \ - test_text.font.html \ - test_text.textAlign.html \ - test_text.textBaseline.html \ - test_text.measure.html \ - test_text.space.replace.html \ + test_canvas.html \ image_transparent50.png \ image_redtransparent.png \ image_yellow.png \ @@ -714,7 +65,6 @@ _TEST_FILES_6 = \ image_green.png \ image_green-redirect \ image_green-redirect^headers^ \ - test_2d.imagedata_coercion.html \ $(NULL) # xor and lighter aren't well handled by cairo; they mostly work, but we don't want @@ -746,14 +96,14 @@ _TEST_FILES_6 = \ # Tests that fail on Mac (possibly because spec is underdefined?). Bug 407105 ifneq ($(MOZ_WIDGET_TOOLKIT),cocoa) # XXX vlad don't test these anywhere, cairo behaviour changed -_TEST_FILES_3 += \ +_TEST_FILES_0 += \ test_2d.line.join.parallel.html \ test_2d.strokeRect.zero.5.html \ $(NULL) # This is an issue with Quartz's handling of radial gradients and some numeric # imprecision that results in errors here. -_TEST_FILES_2 += \ +_TEST_FILES_0 += \ test_2d.gradient.radial.inside2.html \ test_2d.gradient.radial.inside3.html \ test_2d.gradient.radial.outside1.html \ @@ -761,7 +111,7 @@ _TEST_FILES_2 += \ test_2d.gradient.radial.cone.top.html \ $(NULL) -_TEST_FILES_3 += \ +_TEST_FILES_0 += \ test_2d.composite.uncovered.image.source-in.html \ test_2d.composite.uncovered.image.destination-in.html \ test_2d.composite.uncovered.image.source-out.html \ @@ -772,7 +122,7 @@ _TEST_FILES_3 += \ # destination bounds seem to have problems with the BEVEL/SQUARE join/cap combo. # The joins are rendered as if with MITER; the correct behaviour is also seen # if BUTT is used instead of SQUARE. -_TEST_FILES_4 += test_2d.line.cap.closed.html +_TEST_FILES_0 += test_2d.line.cap.closed.html endif @@ -780,7 +130,7 @@ endif ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa) # still need bug numbers -_TEST_FILES_1 += \ +_TEST_FILES_0 += \ test_2d.composite.uncovered.fill.source-in.html \ test_2d.composite.uncovered.fill.destination-in.html \ test_2d.composite.uncovered.fill.source-out.html \ @@ -792,7 +142,7 @@ _TEST_FILES_1 += \ $(NULL) # still need bug numbers -_TEST_FILES_3 += \ +_TEST_FILES_0 += \ test_2d.gradient.radial.outside2.html \ test_2d.gradient.radial.outside3.html \ test_2d.gradient.radial.cone.shape2.html \ @@ -801,9 +151,9 @@ _TEST_FILES_3 += \ $(NULL) # still need bug numbers -_TEST_FILES_4 += test_2d.path.arc.shape.3.html +_TEST_FILES_0 += test_2d.path.arc.shape.3.html -_TEST_FILES_5 += test_2d.path.rect.selfintersect.html +_TEST_FILES_0 += test_2d.path.rect.selfintersect.html endif # These tests only pass on Mac OS X >= 10.5; see bug 450114 @@ -818,22 +168,3 @@ endif # split up into groups to work around command-line length limits libs:: $(_TEST_FILES_0) $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir) - -libs:: $(_TEST_FILES_1) - $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir) - -libs:: $(_TEST_FILES_2) - $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir) - -libs:: $(_TEST_FILES_3) - $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir) - -libs:: $(_TEST_FILES_4) - $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir) - -libs:: $(_TEST_FILES_5) - $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir) - -libs:: $(_TEST_FILES_6) - $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir) - diff --git a/content/canvas/test/test_canvas.html b/content/canvas/test/test_canvas.html new file mode 100644 index 000000000000..29b42967af71 --- /dev/null +++ b/content/canvas/test/test_canvas.html @@ -0,0 +1,24276 @@ + +Canvas Tests + + + + + + + + + +

Canvas test: 2d.canvas.readonly

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.canvas.reference

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.clearRect.basic

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.clearRect.clip

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.clearRect.globalalpha

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.clearRect.globalcomposite

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.clearRect.negative

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.clearRect.nonfinite

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.clearRect.path

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.clearRect.shadow

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.clearRect.transform

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.clearRect.zero

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.canvas.copy

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.canvas.destination-atop

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.canvas.destination-in

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.canvas.destination-out

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.canvas.destination-over

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.canvas.lighter

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.canvas.source-atop

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.canvas.source-in

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.canvas.source-out

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.canvas.source-over

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.canvas.xor

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.clip.copy

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.clip.destination-atop

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.clip.destination-in

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.clip.destination-out

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.clip.destination-over

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.clip.lighter

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.clip.source-atop

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.clip.source-in

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.clip.source-out

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.clip.source-over

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.clip.xor

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.globalAlpha.canvas

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.globalAlpha.canvaspattern - bug 401790

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.globalAlpha.default

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.globalAlpha.fill

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.globalAlpha.image

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.globalAlpha.imagepattern - bug 401790

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.globalAlpha.invalid

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.globalAlpha.range

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.image.copy

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.image.destination-atop

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.image.destination-in

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.image.destination-out

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.image.destination-over

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.image.lighter

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.image.source-atop

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.image.source-in

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.image.source-out

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.image.source-over

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.image.xor

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.operation.casesensitive - bug 401788

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.operation.clear

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.operation.darker

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.operation.default

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.operation.get

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.operation.highlight - bug 401788

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.operation.nullsuffix - bug 401788

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.operation.over

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.operation.unrecognised - bug 401788

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.solid.copy

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.solid.destination-atop

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.solid.destination-in

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.solid.destination-out

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.solid.destination-over

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.solid.lighter

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.solid.source-atop

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.solid.source-in

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.solid.source-out

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.solid.source-over

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.solid.xor

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.transparent.copy

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.transparent.destination-atop

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.transparent.destination-in

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.transparent.destination-out

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.transparent.destination-over

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.transparent.lighter

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.transparent.source-atop

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.transparent.source-in

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.transparent.source-out

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.transparent.source-over

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.transparent.xor

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.uncovered.fill.copy

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.uncovered.fill.destination-atop

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.uncovered.fill.destination-in

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.uncovered.fill.source-in

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.uncovered.fill.source-out

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.composite.uncovered.image.copy

+ +

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.uncovered.image.destination-atop

+ +

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.uncovered.image.destination-in

+ +

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.uncovered.image.source-in

+ +

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.uncovered.image.source-out

+ +

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.uncovered.pattern.copy

+ +

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.uncovered.pattern.destination-atop

+ +

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.uncovered.pattern.destination-in

+ +

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.uncovered.pattern.source-in

+ +

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.composite.uncovered.pattern.source-out

+ +

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.drawImage.3arg

+

FAIL (fallback content)

+ + + + + + +

Canvas test: 2d.drawImage.5arg

+

FAIL (fallback content)

+ + + + + + +

Canvas test: 2d.drawImage.9arg.basic

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.drawImage.9arg.destpos

+

FAIL (fallback content)

+ + + + + + +

Canvas test: 2d.drawImage.9arg.destsize

+

FAIL (fallback content)

+ + + + + + +

Canvas test: 2d.drawImage.9arg.sourcepos

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.drawImage.9arg.sourcesize

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.drawImage.alpha

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.drawImage.animated.apng

+ +

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.drawImage.animated.gif

+ +

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.drawImage.animated.poster

+ +

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.drawImage.broken

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.drawImage.canvas

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.drawImage.clip

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.drawImage.composite

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.drawImage.floatsource

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.drawImage.incomplete

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.drawImage.negativedest

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.drawImage.negativesource

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.drawImage.nonfinite

+ +

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.drawImage.nowrap

+ +

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.drawImage.null

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.drawImage.outsidesource

+

FAIL (fallback content)

+ + + + + + +

Canvas test: 2d.drawImage.path

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.drawImage.self.1 - bug 433235

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.drawImage.self.2 - bug 433235

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.drawImage.transform

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.drawImage.wrongtype

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.drawImage.zerosource

+ +

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.fillRect.basic

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillRect.clip

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillRect.negative

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillRect.nonfinite

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillRect.path

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillRect.shadow

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillRect.transform

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillRect.zero

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.default

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.get.semitransparent

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.get.solid

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.get.transparent

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.invalidstring

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.invalidtype

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.current.basic

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.current.changed

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.current.removed

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.hex3

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.hex6

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.hsl-1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.hsl-2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.hsl-3

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.hsl-4

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.hsl-5

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.hsl-clamp-1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.hsl-clamp-2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.hsl-clamp-3

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.hsl-clamp-4

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.hsla-1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.hsla-2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.hsla-clamp-1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.hsla-clamp-2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.hsla-clamp-3

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.hsla-clamp-4

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.hsla-clamp-5

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.hsla-clamp-6

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.html4

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.invalid.hex3

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.invalid.hex6

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.invalid.hsl-1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.invalid.hsl-2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.invalid.hsl-3

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.invalid.hsl-4

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.invalid.hsl-5

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.invalid.hsla-1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.invalid.hsla-2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.invalid.rgb-1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.invalid.rgb-2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.invalid.rgb-3

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.invalid.rgb-4

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.invalid.rgb-5

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.invalid.rgb-6

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.invalid.rgb-7

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.invalid.rgba-1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.invalid.rgba-2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.invalid.rgba-3

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.invalid.rgba-4

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.invalid.rgba-5

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.rgb-clamp-1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.rgb-clamp-2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.rgb-clamp-3

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.rgb-clamp-4

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.rgb-clamp-5

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.rgb-num

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.rgb-percent

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.rgba-clamp-1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.rgba-clamp-2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.rgba-num-1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.rgba-num-2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.rgba-percent

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.rgba-solid-1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.rgba-solid-2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.svg-1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.svg-2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.system

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.transparent-1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.fillStyle.parse.transparent-2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.getcontext.exists

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.getcontext.shared

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.getcontext.unique

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.empty

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.interpolate.alpha

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.interpolate.colour

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.interpolate.colouralpha

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.interpolate.multiple

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.interpolate.outside

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.interpolate.overlap

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.interpolate.overlap2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.interpolate.solid

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.interpolate.vertical

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.interpolate.zerosize

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.linear.nonfinite

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.linear.transform.1

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.linear.transform.2

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.linear.transform.3

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.object.compare

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.object.crosscanvas

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.object.invalidcolour

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.object.invalidoffset

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.object.return

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.object.type

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.object.update

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.radial.cone.behind

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.radial.cone.beside

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.radial.cone.bottom

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.radial.cone.cylinder

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.radial.cone.front

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.radial.cone.shape1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.radial.cone.shape2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.radial.cone.top

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.radial.equal

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.radial.inside1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.radial.inside2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.radial.inside3

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.radial.negative

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.radial.nonfinite

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.radial.outside1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.radial.outside2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.radial.outside3

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.radial.touch1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.radial.touch2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.radial.touch3

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.radial.transform.1

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.radial.transform.2

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.gradient.radial.transform.3

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.create.basic - bug 433004

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.create.initial - bug 433004

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.create.large - bug 433004

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.create.negative - bug 433004

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.create.nonfinite - bug 433004

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.create.round - bug 433004

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.create.tiny - bug 433004

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.create.type - bug 433004

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.create.zero - bug 433004

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.get.basic

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.get.clamp

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.get.nonfinite

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.get.nonpremul

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.get.order.alpha

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.get.order.cols

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.get.order.rgb

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.get.order.rows

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.get.range

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.get.source.negative

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.get.source.outside

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.get.source.size

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.get.tiny

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.get.type

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.get.unaffected

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.get.zero

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.object.clamp

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.object.ctor

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.object.nan

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.object.properties

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.object.readonly

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.object.round

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.object.set

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.object.string

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.object.undefined

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.put.alpha

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.put.basic

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.put.clip - bug 433397

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.put.created - bug 433004

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.put.cross

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.put.dirty.negative

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.put.dirty.outside

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.put.dirty.rect1

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.put.dirty.rect2

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.put.dirty.zero

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.put.modified

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.put.nonfinite

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.put.null - bug 421715

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.put.path

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.put.unaffected

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.put.unchanged

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageData.put.wrongtype

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.line.cap.butt

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.line.cap.closed

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.line.cap.invalid - bug 401788

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.line.cap.open

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.line.cap.round

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.line.cap.square

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.line.cross

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.line.defaults

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.line.join.bevel

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.line.join.closed

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.line.join.invalid - bug 401788

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.line.join.miter

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.line.join.open

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.line.join.parallel

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.line.join.round

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.line.miter.acute

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.line.miter.exceeded

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.line.miter.invalid

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.line.miter.lineedge - bug 401791

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.line.miter.obtuse

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.line.miter.rightangle - bug 401791

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.line.miter.within

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.line.union

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.line.width.basic

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.line.width.invalid

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.line.width.transformed

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.missingargs

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arc.angle.1

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arc.angle.2

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arc.angle.3

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arc.angle.4

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arc.angle.5

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arc.angle.6

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arc.empty

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arc.end

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arc.negative

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arc.nonempty

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arc.nonfinite

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arc.scale.1

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arc.scale.2

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arc.selfintersect.1

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arc.selfintersect.2

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arc.shape.1

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arc.shape.2

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arc.shape.3

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arc.shape.4

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arc.shape.5

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arc.twopie.1

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arc.twopie.2

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arc.twopie.3

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arc.twopie.4

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arc.zero.1

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arc.zero.2

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arc.zeroradius

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arcTo.coincide.1

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arcTo.coincide.2

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arcTo.collinear.1

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arcTo.collinear.2

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arcTo.collinear.3

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arcTo.emptysubpath

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arcTo.negative

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arcTo.nonfinite

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arcTo.scale

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arcTo.shape.curve1

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arcTo.shape.curve2

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arcTo.shape.end

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arcTo.shape.start

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arcTo.transformation

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arcTo.zero.1

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.arcTo.zero.2

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.beginPath

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.bezierCurveTo.basic

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.bezierCurveTo.emptysubpath

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.bezierCurveTo.nonfinite

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.bezierCurveTo.scaled

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.bezierCurveTo.shape

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.clip.basic.1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.clip.basic.2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.clip.empty

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.clip.intersect

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.clip.unaffected

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.clip.winding.1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.clip.winding.2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.closePath.empty

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.closePath.newline

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.closePath.nextpoint

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.fill.closed.basic

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.fill.closed.unaffected

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.fill.overlap

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.fill.winding.add

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.fill.winding.subtract.1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.fill.winding.subtract.2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.fill.winding.subtract.3

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.initial

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.isPointInPath.arc

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.isPointInPath.basic.1

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.isPointInPath.basic.2

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.isPointInPath.bezier

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.isPointInPath.bigarc

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.isPointInPath.edge

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.isPointInPath.empty

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.isPointInPath.nonfinite

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.isPointInPath.outside

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.isPointInPath.subpath

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.isPointInPath.transform.1 - bug 405300

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.isPointInPath.transform.2 - bug 405300

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.isPointInPath.transform.3 - bug 405300

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.isPointInPath.unclosed

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.isPointInPath.winding

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.lineTo.basic

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.lineTo.emptysubpath

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.lineTo.nextpoint

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.lineTo.nonfinite

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.moveTo.basic

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.moveTo.multiple

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.moveTo.newsubpath

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.moveTo.nonfinite

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.quadraticCurveTo.basic

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.quadraticCurveTo.emptysubpath

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.quadraticCurveTo.nonfinite

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.quadraticCurveTo.scaled

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.quadraticCurveTo.shape

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.rect.basic

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.rect.closed

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.rect.end.1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.rect.end.2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.rect.negative

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.rect.newsubpath

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.rect.nonfinite

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.rect.selfintersect

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.rect.winding

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.rect.zero.1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.rect.zero.2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.rect.zero.3

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.rect.zero.4

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.rect.zero.5

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.rect.zero.6

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.stroke.empty

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.stroke.overlap

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.stroke.prune.arc

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.stroke.prune.closed

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.stroke.prune.corner

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.stroke.prune.curve

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.stroke.prune.line

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.stroke.prune.rect

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.stroke.scale1

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.stroke.scale2

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.stroke.skew

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.stroke.unaffected

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.stroke.union

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.transformation.basic

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.transformation.changing

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.path.transformation.multiple

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.pattern.animated.gif

+ +

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.pattern.basic.canvas

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.pattern.basic.image

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.pattern.basic.nocontext

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.pattern.basic.type

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.pattern.basic.zerocanvas

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.pattern.crosscanvas

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.pattern.image.broken

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.pattern.image.incomplete

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.pattern.image.null

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.pattern.image.string

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.pattern.image.undefined

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.pattern.modify.canvas1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.pattern.modify.canvas2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.pattern.modify.image1

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.pattern.modify.image2

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.pattern.paint.norepeat.basic

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.pattern.paint.norepeat.coord1

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.pattern.paint.norepeat.coord2

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.pattern.paint.norepeat.coord3

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.pattern.paint.norepeat.outside

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.pattern.paint.orientation.canvas

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.pattern.paint.orientation.image

+ +

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.pattern.paint.repeat.basic

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.pattern.paint.repeat.coord1

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.pattern.paint.repeat.coord2

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.pattern.paint.repeat.coord3

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.pattern.paint.repeat.outside

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.pattern.paint.repeatx.basic

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.pattern.paint.repeatx.coord1

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.pattern.paint.repeatx.outside

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.pattern.paint.repeaty.basic

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.pattern.paint.repeaty.coord1

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.pattern.paint.repeaty.outside

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.pattern.repeat.case

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.pattern.repeat.empty

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.pattern.repeat.null

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.pattern.repeat.nullsuffix

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.pattern.repeat.undefined

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.pattern.repeat.unrecognised

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.scaled

+ +

FAIL (fallback content)

+ + + +

Canvas test: 2d.shadow.alpha.1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.alpha.2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.alpha.3

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.alpha.4

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.alpha.5

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.attributes.shadowBlur.1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.attributes.shadowBlur.2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.attributes.shadowColor.1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.attributes.shadowColor.2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.attributes.shadowOffset.1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.attributes.shadowOffset.2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.basic.1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.basic.2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.blur.high

+

FAIL (fallback content)

+ + + +

Canvas test: 2d.shadow.blur.low

+

FAIL (fallback content)

+ + + +

Canvas test: 2d.shadow.canvas.alpha

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.shadow.canvas.basic

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.canvas.transparent.1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.canvas.transparent.2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.clip.1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.clip.2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.clip.3

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.composite.1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.composite.2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.composite.3

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.composite.4

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.gradient.alpha

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.gradient.basic

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.gradient.transparent.1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.gradient.transparent.2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.image.alpha

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.shadow.image.basic

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.shadow.image.scale

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.shadow.image.section

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.shadow.image.transparent.1

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.shadow.image.transparent.2

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.shadow.offset.negativeX

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.offset.negativeY

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.offset.positiveX

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.offset.positiveY

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.outside

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.pattern.alpha

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.shadow.pattern.basic

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.shadow.pattern.transparent.1

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.shadow.pattern.transparent.2

+

FAIL (fallback content)

+ + + + + +

Canvas test: 2d.shadow.stroke.basic

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.stroke.cap.1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.stroke.cap.2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.stroke.join.1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.stroke.join.2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.stroke.join.3

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.transform.1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.shadow.transform.2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.state.saverestore.bitmap

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.state.saverestore.clip

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.state.saverestore.fillStyle

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.state.saverestore.globalAlpha

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.state.saverestore.globalCompositeOperation

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.state.saverestore.lineCap

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.state.saverestore.lineJoin

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.state.saverestore.lineWidth

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.state.saverestore.miterLimit

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.state.saverestore.path

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.state.saverestore.shadowBlur

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.state.saverestore.shadowColor

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.state.saverestore.shadowOffsetX

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.state.saverestore.shadowOffsetY

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.state.saverestore.stack

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.state.saverestore.stackdepth

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.state.saverestore.strokeStyle

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.state.saverestore.transformation

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.state.saverestore.underflow - bug 296821

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.strokeRect.basic

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.strokeRect.clip

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.strokeRect.globalalpha

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.strokeRect.globalcomposite

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.strokeRect.negative

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.strokeRect.nonfinite

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.strokeRect.path

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.strokeRect.shadow

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.strokeRect.transform

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.strokeRect.zero.1

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.strokeRect.zero.2

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.strokeRect.zero.3

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.strokeRect.zero.4

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.strokeRect.zero.5

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.strokeStyle.default

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.transformation.order

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.transformation.rotate.direction

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.transformation.rotate.nonfinite

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.transformation.rotate.radians

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.transformation.rotate.wrap

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.transformation.rotate.wrapnegative

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.transformation.rotate.zero

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.transformation.scale.basic

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.transformation.scale.large

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.transformation.scale.multiple

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.transformation.scale.negative

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.transformation.scale.nonfinite

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.transformation.scale.zero

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.transformation.setTransform.multiple

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.transformation.setTransform.nonfinite

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.transformation.setTransform.skewed

+

FAIL (fallback content)

+ + + + +

Canvas test: 2d.transformation.transform.identity

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.transformation.transform.multiply

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.transformation.transform.nonfinite

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.transformation.transform.skewed

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.transformation.translate.basic

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.transformation.translate.nonfinite

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.type.delete

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.type.exists

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.type.extend

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.type.prototype

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.type.replace

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.voidreturn

+ +

FAIL (fallback content)

+ + + + + +

Test for Bug 397524

+Mozilla Bug 397524 +

+ + + + + + +

+ +
+
+
+ + + +

Canvas test: toDataURL.png

+

FAIL (fallback content)

+ + + +

Canvas test: context.arguments.extra

+

FAIL (fallback content)

+ + + + +

Canvas test: context.arguments.missing

+

FAIL (fallback content)

+ + + + +

Canvas test: context.casesensitive - bug 401788

+ +

FAIL (fallback content)

+ + + + +

Canvas test: context.emptystring - bug 401788

+ +

FAIL (fallback content)

+ + + + +

Canvas test: context.unrecognised.badname - bug 401788

+ +

FAIL (fallback content)

+ + + + +

Canvas test: context.unrecognised.badsuffix - bug 401788

+ +

FAIL (fallback content)

+ + + + +

Canvas test: context.unrecognised.nullsuffix - bug 401788

+ +

FAIL (fallback content)

+ + + + +

Canvas test: context.unrecognised.unicode - bug 401788

+ +

FAIL (fallback content)

+ + + + +

Canvas test: fallback.basic

+ +

FAIL (fallback content)

+ + + + +

Canvas test: fallback.multiple

+ +

FAIL

FAIL

+ + + + +

Canvas test: fallback.nested

+ +

FAIL (fallback content)

FAIL (fallback content)

+ + + + +

Canvas test: initial.colour

+ +

FAIL (fallback content)

+ + + + +

Canvas test: initial.reset.2dstate

+ +

FAIL (fallback content)

+ + + + +

Canvas test: initial.reset.clip

+ +

FAIL (fallback content)

+ + + + +

Canvas test: initial.reset.different

+ +

FAIL (fallback content)

+ + + + +

Canvas test: initial.reset.gradient

+ +

FAIL (fallback content)

+ + + + +

Canvas test: initial.reset.path

+ +

FAIL (fallback content)

+ + + + +

Canvas test: initial.reset.pattern

+ +

FAIL (fallback content)

+ + + + +

Canvas test: initial.reset.same

+ +

FAIL (fallback content)

+ + + + +

Canvas test: initial.reset.transform

+ +

FAIL (fallback content)

+ + + + +

Canvas test: size.attributes.default

+ +

FAIL (fallback content)

+ + + + +

Canvas test: size.attributes

+ +

FAIL (fallback content)

+ + + + +

Canvas test: size.attributes.parse.badsuffix

+ +

FAIL (fallback content)

+ + + + +

Canvas test: size.attributes.parse.floatsuffix

+ +

FAIL (fallback content)

+ + + + +

Canvas test: size.attributes.parse.negative

+ +

FAIL (fallback content)

+ + + + +

Canvas test: size.attributes.parse.nonnumber

+ +

FAIL (fallback content)

+ + + + +

Canvas test: size.attributes.parse.percentsuffix

+ +

FAIL (fallback content)

+ + + + +

Canvas test: size.attributes.parse.whitespace

+ +

FAIL (fallback content)

+ + + + +

Canvas test: size.attributes.parse.zero

+ +

FAIL (fallback content)

+ + + + +

Canvas test: size.attributes.parse.zerosuffix

+ +

FAIL (fallback content)

+ + + + +

Canvas test: size.attributes.reflect.1

+ +

FAIL (fallback content)

+ + + + +

Canvas test: size.attributes.reflect.2

+ +

FAIL (fallback content)

+ + + + +

Canvas test: size.attributes.removed

+ +

FAIL (fallback content)

+ + + + +

Canvas test: size.attributes.setAttribute.badsuffix

+ +

FAIL (fallback content)

+ + + + +

Canvas test: size.attributes.setAttribute.floatsuffix

+ +

FAIL (fallback content)

+ + + + +

Canvas test: size.attributes.setAttribute.negative

+ +

FAIL (fallback content)

+ + + + +

Canvas test: size.attributes.setAttribute.nonnumber

+ +

FAIL (fallback content)

+ + + + +

Canvas test: size.attributes.setAttribute.percentsuffix

+ +

FAIL (fallback content)

+ + + + +

Canvas test: size.attributes.setAttribute.whitespace

+ +

FAIL (fallback content)

+ + + + +

Canvas test: size.attributes.setAttribute.zero

+ +

FAIL (fallback content)

+ + + + +

Canvas test: size.attributes.setAttribute.zerosuffix

+ +

FAIL (fallback content)

+ + + + +

Canvas test: size.attributes.style

+ +

FAIL (fallback content)

+ + + + +

Canvas test: size.attributes.type.get

+ +

FAIL (fallback content)

+ + + + +

Canvas test: size.attributes.type.set

+ +

FAIL (fallback content)

+ + + + +

Canvas test: text.font

+

FAIL (fallback content)

+ + + + +

Canvas test: text.measure

+

FAIL (fallback content)

+ + + + +

Canvas test: text.space.replace

+

FAIL (fallback content)

+ + + + +

Canvas test: text.textAlign

+

FAIL (fallback content)

+ + + + +

Canvas test: text.textBaseline

+

FAIL (fallback content)

+ + + + +

Canvas test: toDataURL.arguments.1 - bug 401795

+ +

FAIL (fallback content)

+ + + + +

Canvas test: toDataURL.arguments.2 - bug 401795

+ +

FAIL (fallback content)

+ + + + +

Canvas test: toDataURL.arguments.3 - bug 401795

+ +

FAIL (fallback content)

+ + + + +

Canvas test: toDataURL.complexcolours

+ +

FAIL (fallback content)

+ + + + +

Canvas test: toDataURL.default

+ +

FAIL (fallback content)

+ + + + +

Canvas test: toDataURL.lowercase - bug 401795

+ +

FAIL (fallback content)

+ + + + +

Canvas test: toDataURL.nocontext

+ +

FAIL (fallback content)

+ + + + +

Canvas test: toDataURL.png

+ +

FAIL (fallback content)

+ + + + +

Canvas test: toDataURL.primarycolours

+ +

FAIL (fallback content)

+ + + + +

Canvas test: toDataURL.unrecognised - bug 401795

+ +

FAIL (fallback content)

+ + + + +

Canvas test: toDataURL.zerosize

+ +

FAIL (fallback content)

+ + + + +

Canvas test: type.delete

+ +

FAIL (fallback content)

+ + + + +

Canvas test: type.exists

+ +

FAIL (fallback content)

+ + + + +

Canvas test: type.extend

+ +

FAIL (fallback content)

+ + + + +

Canvas test: type.name

+ +

FAIL (fallback content)

+ + + + +

Canvas test: type.prototype

+ +

FAIL (fallback content)

+ + + + +

Canvas test: type.replace

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imagedata_coercion

+ +

FAIL (fallback content)

+ + + + +

Canvas test: 2d.imageRenderingQuality

+
+ + + + From e9f662e5fbf1b558f24844ec66c30d0ea0de2ca8 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 30 Jul 2009 15:16:44 +1200 Subject: [PATCH 05/61] Bug 486200. Add window.mozInnerScreenX/Y APIs to return usable screen coordinate APIs (as opposed to window.screenX/Y which return window frame coordinates and are unusable). Also adds window.mozScreenPixelsPerCSSPixel which chrome-prileged code can use to convert CSS pixels to actual screen pixels. r=dbaron,sr=jst --HG-- extra : rebase_source : 30f4c953f3e3866da042b935953ba239ac0a93c4 --- dom/base/nsGlobalWindow.cpp | 66 +++++++++++++++ dom/base/nsGlobalWindow.h | 2 + dom/interfaces/base/nsIDOMWindowInternal.idl | 5 +- dom/tests/mochitest/general/Makefile.in | 4 +- .../mochitest/general/test_innerScreen.xul | 83 +++++++++++++++++++ 5 files changed, 158 insertions(+), 2 deletions(-) create mode 100644 dom/tests/mochitest/general/test_innerScreen.xul diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index ac280f57dc6e..4123377d56cf 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -3347,6 +3347,72 @@ nsGlobalWindow::GetScreenX(PRInt32* aScreenX) return NS_OK; } +nsRect +nsGlobalWindow::GetInnerScreenRect() +{ + if (!mDocShell) + return nsRect(); + + nsGlobalWindow* rootWindow = + static_cast(GetPrivateRoot()); + if (rootWindow) { + rootWindow->FlushPendingNotifications(Flush_Layout); + } + + nsCOMPtr presShell; + mDocShell->GetPresShell(getter_AddRefs(presShell)); + if (!presShell) + return nsRect(); + nsIFrame* rootFrame = presShell->GetRootFrame(); + if (!rootFrame) + return nsRect(); + + return rootFrame->GetScreenRectInAppUnits(); +} + +NS_IMETHODIMP +nsGlobalWindow::GetMozInnerScreenX(float* aScreenX) +{ + FORWARD_TO_OUTER(GetMozInnerScreenX, (aScreenX), NS_ERROR_NOT_INITIALIZED); + + nsRect r = GetInnerScreenRect(); + *aScreenX = nsPresContext::AppUnitsToFloatCSSPixels(r.x); + return NS_OK; +} + +NS_IMETHODIMP +nsGlobalWindow::GetMozInnerScreenY(float* aScreenY) +{ + FORWARD_TO_OUTER(GetMozInnerScreenY, (aScreenY), NS_ERROR_NOT_INITIALIZED); + + nsRect r = GetInnerScreenRect(); + *aScreenY = nsPresContext::AppUnitsToFloatCSSPixels(r.y); + return NS_OK; +} + +NS_IMETHODIMP +nsGlobalWindow::GetMozScreenPixelsPerCSSPixel(float* aScreenPixels) +{ + FORWARD_TO_OUTER(GetMozScreenPixelsPerCSSPixel, + (aScreenPixels), NS_ERROR_NOT_INITIALIZED); + + *aScreenPixels = 1; + + if (!nsContentUtils::IsCallerTrustedForRead()) + return NS_ERROR_DOM_SECURITY_ERR; + if (!mDocShell) + return NS_OK; + nsCOMPtr presContext; + mDocShell->GetPresContext(getter_AddRefs(presContext)); + if (!presContext) + return NS_OK; + + *aScreenPixels = float(nsPresContext::AppUnitsPerCSSPixel())/ + presContext->AppUnitsPerDevPixel(); + + return NS_OK; +} + NS_IMETHODIMP nsGlobalWindow::SetScreenX(PRInt32 aScreenX) { diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index e568c7279fcc..7cd9814780a5 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -90,6 +90,7 @@ #include "nsIXPCScriptable.h" #include "nsPoint.h" #include "nsSize.h" +#include "nsRect.h" #include "mozFlushType.h" #include "prclist.h" #include "nsIDOMStorageObsolete.h" @@ -594,6 +595,7 @@ protected: nsresult GetOuterSize(nsIntSize* aSizeCSSPixels); nsresult SetOuterSize(PRInt32 aLengthCSSPixels, PRBool aIsWidth); + nsRect GetInnerScreenRect(); PRBool IsFrame() { diff --git a/dom/interfaces/base/nsIDOMWindowInternal.idl b/dom/interfaces/base/nsIDOMWindowInternal.idl index ceeedf678e5c..9cff9a929a33 100644 --- a/dom/interfaces/base/nsIDOMWindowInternal.idl +++ b/dom/interfaces/base/nsIDOMWindowInternal.idl @@ -44,7 +44,7 @@ interface nsIControllers; interface nsIDOMLocation; interface nsIVariant; -[scriptable, uuid(3414EBC7-731F-4697-9F43-ACA6F5050875)] +[scriptable, uuid(62579239-b619-4bf2-8d39-0b73e8663a85)] interface nsIDOMWindowInternal : nsIDOMWindow2 { readonly attribute nsIDOMWindowInternal window; @@ -104,6 +104,9 @@ interface nsIDOMWindowInternal : nsIDOMWindow2 attribute long outerHeight; attribute long screenX; attribute long screenY; + readonly attribute float mozInnerScreenX; + readonly attribute float mozInnerScreenY; + readonly attribute float mozScreenPixelsPerCSSPixel; /* The offset in pixels by which the window is scrolled */ readonly attribute long pageXOffset; diff --git a/dom/tests/mochitest/general/Makefile.in b/dom/tests/mochitest/general/Makefile.in index 36b8d81c2891..120abbd0df6c 100644 --- a/dom/tests/mochitest/general/Makefile.in +++ b/dom/tests/mochitest/general/Makefile.in @@ -44,7 +44,9 @@ relativesrcdir = dom/tests/mochitest/general include $(DEPTH)/config/autoconf.mk include $(topsrcdir)/config/rules.mk -_TEST_FILES = test_offsets.html \ +_TEST_FILES = \ + test_innerScreen.xul \ + test_offsets.html \ test_offsets.xul \ test_offsets.js \ test_domWindowUtils.html \ diff --git a/dom/tests/mochitest/general/test_innerScreen.xul b/dom/tests/mochitest/general/test_innerScreen.xul new file mode 100644 index 000000000000..46fdabffd826 --- /dev/null +++ b/dom/tests/mochitest/general/test_innerScreen.xul @@ -0,0 +1,83 @@ + + + + + + + + From 7ebe7c87bd3ce0d0f9333363cfae332daf87910c Mon Sep 17 00:00:00 2001 From: Blake Kaplan Date: Thu, 30 Jul 2009 15:26:59 +1200 Subject: [PATCH 06/61] Bug 505988. Don't unwrap when we shouldn't. r=bz --HG-- extra : rebase_source : d251c442ba2fae0f9ffcae99c2c84d780c99ea52 --- js/src/xpconnect/src/xpcprivate.h | 9 +-- js/src/xpconnect/src/xpcvariant.cpp | 69 +++++++++---------- js/src/xpconnect/tests/mochitest/Makefile.in | 1 + .../tests/mochitest/test_bug384632.html | 32 +++++++++ 4 files changed, 70 insertions(+), 41 deletions(-) create mode 100644 js/src/xpconnect/tests/mochitest/test_bug384632.html diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index 2ce45487d1b5..59db7a8afccf 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -4007,7 +4007,7 @@ public: jsval GetJSVal() const {return mJSVal;} - XPCVariant(jsval aJSVal); + XPCVariant(XPCCallContext& ccx, jsval aJSVal); /** * Convert a variant into a jsval. @@ -4032,6 +4032,7 @@ protected: protected: nsDiscriminatedUnion mData; jsval mJSVal; + JSBool mReturnRawObject; }; NS_DEFINE_STATIC_IID_ACCESSOR(XPCVariant, XPCVARIANT_IID) @@ -4040,10 +4041,10 @@ class XPCTraceableVariant: public XPCVariant, public XPCRootSetElem { public: - XPCTraceableVariant(XPCJSRuntime *runtime, jsval aJSVal) - : XPCVariant(aJSVal) + XPCTraceableVariant(XPCCallContext& ccx, jsval aJSVal) + : XPCVariant(ccx, aJSVal) { - runtime->AddVariantRoot(this); + ccx.GetRuntime()->AddVariantRoot(this); } virtual ~XPCTraceableVariant(); diff --git a/js/src/xpconnect/src/xpcvariant.cpp b/js/src/xpconnect/src/xpcvariant.cpp index 9ce012e82e19..6a5f0f6955c4 100644 --- a/js/src/xpconnect/src/xpcvariant.cpp +++ b/js/src/xpconnect/src/xpcvariant.cpp @@ -55,10 +55,26 @@ NS_IMPL_CI_INTERFACE_GETTER2(XPCVariant, XPCVariant, nsIVariant) NS_IMPL_CYCLE_COLLECTING_ADDREF(XPCVariant) NS_IMPL_CYCLE_COLLECTING_RELEASE(XPCVariant) -XPCVariant::XPCVariant(jsval aJSVal) +XPCVariant::XPCVariant(XPCCallContext& ccx, jsval aJSVal) : mJSVal(aJSVal) { nsVariant::Initialize(&mData); + if(!JSVAL_IS_PRIMITIVE(mJSVal)) + { + // If the incoming object is an XPCWrappedNative, then it could be a + // double-wrapped object, and we should return the double-wrapped + // object back out to script. + + JSObject* proto; + XPCWrappedNative* wn = + XPCWrappedNative::GetWrappedNativeOfJSObject(ccx, + JSVAL_TO_OBJECT(mJSVal), + nsnull, + &proto); + mReturnRawObject = !wn && !proto; + } + else + mReturnRawObject = JS_FALSE; } XPCTraceableVariant::~XPCTraceableVariant() @@ -119,9 +135,9 @@ XPCVariant* XPCVariant::newVariant(XPCCallContext& ccx, jsval aJSVal) XPCVariant* variant; if(!JSVAL_IS_TRACEABLE(aJSVal)) - variant = new XPCVariant(aJSVal); + variant = new XPCVariant(ccx, aJSVal); else - variant = new XPCTraceableVariant(ccx.GetRuntime(), aJSVal); + variant = new XPCTraceableVariant(ccx, aJSVal); if(!variant) return nsnull; @@ -401,6 +417,15 @@ XPCVariant::VariantDataToJS(XPCCallContext& ccx, return JS_TRUE; } + if(xpcvariant->mReturnRawObject) + { + NS_ASSERTION(type == nsIDataType::VTYPE_INTERFACE || + type == nsIDataType::VTYPE_INTERFACE_IS, + "Weird variant"); + *pJSVal = realVal; + return JS_TRUE; + } + // else, it's an object and we really need to double wrap it if we've // already decided that its 'natural' type is as some sort of interface. @@ -641,40 +666,10 @@ VARIANT_DONE: } else { - // Last ditch check to prevent us from double-wrapping a regular JS - // object. This allows us to unwrap regular JS objects (since we - // normally can't double wrap them). See bug 384632. - *pJSVal = JSVAL_VOID; - if(type == nsIDataType::VTYPE_INTERFACE || - type == nsIDataType::VTYPE_INTERFACE_IS) - { - nsISupports *src = reinterpret_cast(xpctvar.val.p); - if(nsXPCWrappedJSClass::IsWrappedJS(src)) - { - // First QI the wrapper to the right interface. - nsCOMPtr wrapper; - nsresult rv = src->QueryInterface(iid, getter_AddRefs(wrapper)); - NS_ENSURE_SUCCESS(rv, JS_FALSE); - - // Now, get the actual JS object out of the wrapper. - nsCOMPtr holder = - do_QueryInterface(wrapper); - NS_ENSURE_TRUE(holder, JS_FALSE); - - JSObject *obj; - holder->GetJSObject(&obj); - NS_ASSERTION(obj, "No JS object but the QIs above succeeded?"); - *pJSVal = OBJECT_TO_JSVAL(obj); - success = JS_TRUE; - } - } - if(!JSVAL_IS_OBJECT(*pJSVal)) - { - success = XPCConvert::NativeData2JS(ccx, pJSVal, - (const void*)&xpctvar.val, - xpctvar.type, - &iid, scope, pErr); - } + success = XPCConvert::NativeData2JS(ccx, pJSVal, + (const void*)&xpctvar.val, + xpctvar.type, + &iid, scope, pErr); } if(xpctvar.IsValAllocated()) diff --git a/js/src/xpconnect/tests/mochitest/Makefile.in b/js/src/xpconnect/tests/mochitest/Makefile.in index 3ff1465c03e3..90ed8ade38b8 100644 --- a/js/src/xpconnect/tests/mochitest/Makefile.in +++ b/js/src/xpconnect/tests/mochitest/Makefile.in @@ -47,6 +47,7 @@ include $(topsrcdir)/config/rules.mk _TEST_FILES = bug500931_helper.html \ inner.html \ test_bug361111.xul \ + test_bug384632.html \ test_bug390488.html \ test_bug393269.html \ test_bug396851.html \ diff --git a/js/src/xpconnect/tests/mochitest/test_bug384632.html b/js/src/xpconnect/tests/mochitest/test_bug384632.html new file mode 100644 index 000000000000..7cdc397adb4e --- /dev/null +++ b/js/src/xpconnect/tests/mochitest/test_bug384632.html @@ -0,0 +1,32 @@ + + + + + Test for Bug 384632 + + + + + +Mozilla Bug 384632 +

+ +
+
+
+ + From ecce4039959156cc784d8d2868177fac1ea5461f Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Thu, 30 Jul 2009 15:27:24 +1200 Subject: [PATCH 07/61] Bug 506552. Fix testcase doctype. r=dbaron --HG-- extra : rebase_source : ee371dbb3106880b1609e0d69d1824a3edb7a91e --- layout/reftests/css-mediaqueries/mq_print_orientation.xhtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layout/reftests/css-mediaqueries/mq_print_orientation.xhtml b/layout/reftests/css-mediaqueries/mq_print_orientation.xhtml index 418f0787f184..151686e72f33 100644 --- a/layout/reftests/css-mediaqueries/mq_print_orientation.xhtml +++ b/layout/reftests/css-mediaqueries/mq_print_orientation.xhtml @@ -1,5 +1,5 @@ - + Media Query - Print mode test - orientation From a9abb503c141066cea2c805ae6a9ebf340fa746b Mon Sep 17 00:00:00 2001 From: Mook Date: Thu, 30 Jul 2009 15:41:03 +1200 Subject: [PATCH 08/61] Bug 502188. Implement xptcall for mingw-Windows64. r=timeless --HG-- extra : rebase_source : 2c03e2ae8d491059b9c3759e7e5082a20c1b715a --- .../reflect/xptcall/src/md/win32/Makefile.in | 5 + .../src/md/win32/xptcinvoke_asm_x86_64_gnu.s | 158 +++++++++ .../src/md/win32/xptcstubs_x86_64_gnu.cpp | 331 ++++++++++++++++++ 3 files changed, 494 insertions(+) create mode 100644 xpcom/reflect/xptcall/src/md/win32/xptcinvoke_asm_x86_64_gnu.s create mode 100644 xpcom/reflect/xptcall/src/md/win32/xptcstubs_x86_64_gnu.cpp diff --git a/xpcom/reflect/xptcall/src/md/win32/Makefile.in b/xpcom/reflect/xptcall/src/md/win32/Makefile.in index b08d2e5f7e61..4ab8dbae3e81 100644 --- a/xpcom/reflect/xptcall/src/md/win32/Makefile.in +++ b/xpcom/reflect/xptcall/src/md/win32/Makefile.in @@ -82,8 +82,13 @@ ASFLAGS += /I../../..public endif ifeq ($(TARGET_CPU),x86_64) +ifndef GNU_CXX CPPSRCS := xptcinvoke_x86_64.cpp xptcstubs_x86_64.cpp ASFILES := xptcinvoke_asm_x86_64.asm xptcstubs_asm_x86_64.asm +else #!GNU_CXX +CPPSRCS := xptcinvoke_x86_64.cpp xptcstubs_x86_64_gnu.cpp +ASFILES := xptcinvoke_asm_x86_64_gnu.s +endif #!GNU_CXX endif ifeq ($(OS_ARCH),WINCE) diff --git a/xpcom/reflect/xptcall/src/md/win32/xptcinvoke_asm_x86_64_gnu.s b/xpcom/reflect/xptcall/src/md/win32/xptcinvoke_asm_x86_64_gnu.s new file mode 100644 index 000000000000..dfd9ecc20011 --- /dev/null +++ b/xpcom/reflect/xptcall/src/md/win32/xptcinvoke_asm_x86_64_gnu.s @@ -0,0 +1,158 @@ +# ***** 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 mozilla.org code. +# +# The Initial Developer of the Original Code is +# Makoto Kato . +# Portions created by the Initial Developer are Copyright (C) 2004 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# 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 ***** + +.extern _invoke_copy_to_stack + + +.text +.intel_syntax + +# +#_XPTC__InvokebyIndex(nsISupports* that, PRUint32 methodIndex, +# PRUint32 paramCount, nsXPTCVariant* params) +# + +.globl _XPTC__InvokebyIndex +.def _XPTC__InvokebyIndex + .scl 3 + .type 46 +.endef +_XPTC__InvokebyIndex: + + # + # store register parameters + # + + mov qword ptr [rsp+32], r9 # params + mov dword ptr [rsp+24], r8d # paramCount + mov dword ptr [rsp+16], edx # methodIndex + mov qword ptr [rsp+8], rcx # that + + # + # store RBX/RBP register for backup + # + + mov qword ptr [rsp-16], rbp + + mov rbp, rsp # store current RSP to RBP + # .SETFRAME rbp, 0 + # .ENDPROLOG + + sub rsp, 32 + + # + # maybe we don't have any parameters to copy + # + + test r8d, r8d + jz noparams + + # + # make space for 1st parameter + + mov eax, r8d + and eax, 1 # AMD64 must be alignment to 16 bytes + add eax, r8d + shl rax, 3 # *= 8 + sub rsp, rax + mov rcx, rsp + + # + # 2nd parameter is parameter count + # + + mov edx, r8d + + # + # 3rd parameter is params + # + + mov r8, r9 + + sub rsp, 32 + + call _invoke_copy_to_stack # rcx = d + # edx = paramCount + # r8 = s + + add rsp, 32 + + # + # Build parameters + # + + mov rdx, qword ptr [rsp] # 1st parameter + movsd xmm1, qword ptr [rsp] # for double + + mov r8, qword ptr [rsp+8] # 2nd parameter + movsd xmm2, qword ptr [rsp+8] # for double + + mov r9, qword ptr [rsp+16] # 3rd parameter + movsd xmm3, qword ptr [rsp+16] # for double + + # + # 1st parameter (this) + # + + mov rcx, qword ptr [rbp+8] # that + +noparams: + + # + # calculate call address + # + + mov r11, qword ptr [rcx] + mov eax, dword ptr [rbp+16] # methodIndex + + # + # Now current stack has parameter list + # But, since callee function backups parameters, make space into stack. + + sub rsp, 8 + + call qword ptr [r11+rax*8] # stdcall, i.e. callee cleans up stack. + + # + # restore registers + # + + mov rsp, rbp + mov rbp, qword ptr [rsp-16] + + ret + + diff --git a/xpcom/reflect/xptcall/src/md/win32/xptcstubs_x86_64_gnu.cpp b/xpcom/reflect/xptcall/src/md/win32/xptcstubs_x86_64_gnu.cpp new file mode 100644 index 000000000000..c55cba3ffde0 --- /dev/null +++ b/xpcom/reflect/xptcall/src/md/win32/xptcstubs_x86_64_gnu.cpp @@ -0,0 +1,331 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** 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 mozilla.org Code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 "xptcprivate.h" +#include "xptiprivate.h" +#include "../unix/xptc_gcc_x86_unix.h" + +/* + * This is for Windows 64 bit (x86_64) using GCC syntax + * Code was copied from the MSVC version. + */ + +#if !defined(_AMD64_) || !defined(__GNUC__) +# error xptcstubs_x86_64_gnu.cpp being used unexpectedly +#endif + +extern "C" nsresult +PrepareAndDispatch(nsXPTCStubBase * self, PRUint32 methodIndex, + PRUint64 * args, PRUint64 * gprData, double *fprData) +{ +#define PARAM_BUFFER_COUNT 16 +// +// "this" pointer is first parameter, so parameter count is 3. +// +#define PARAM_GPR_COUNT 3 +#define PARAM_FPR_COUNT 3 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + nsXPTCMiniVariant* dispatchParams = NULL; + const nsXPTMethodInfo* info = NULL; + PRUint8 paramCount; + PRUint8 i; + nsresult result = NS_ERROR_FAILURE; + + NS_ASSERTION(self, "no self"); + + self->mEntry->GetMethodInfo(PRUint16(methodIndex), &info); + NS_ASSERTION(info, "no method info"); + + paramCount = info->GetParamCount(); + + // + // setup variant array pointer + // + + if(paramCount > PARAM_BUFFER_COUNT) + dispatchParams = new nsXPTCMiniVariant[paramCount]; + else + dispatchParams = paramBuffer; + + NS_ASSERTION(dispatchParams,"no place for params"); + + PRUint64* ap = args; + PRUint32 iCount = 0; + + for(i = 0; i < paramCount; i++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = &dispatchParams[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + if (iCount < PARAM_GPR_COUNT) + dp->val.p = (void*)gprData[iCount++]; + else + dp->val.p = (void*)*ap++; + + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8: + if (iCount < PARAM_GPR_COUNT) + dp->val.i8 = (PRInt8)gprData[iCount++]; + else + dp->val.i8 = *((PRInt8*)ap++); + break; + + case nsXPTType::T_I16: + if (iCount < PARAM_GPR_COUNT) + dp->val.i16 = (PRInt16)gprData[iCount++]; + else + dp->val.i16 = *((PRInt16*)ap++); + break; + + case nsXPTType::T_I32: + if (iCount < PARAM_GPR_COUNT) + dp->val.i32 = (PRInt32)gprData[iCount++]; + else + dp->val.i32 = *((PRInt32*)ap++); + break; + + case nsXPTType::T_I64: + if (iCount < PARAM_GPR_COUNT) + dp->val.i64 = (PRInt64)gprData[iCount++]; + else + dp->val.i64 = *((PRInt64*)ap++); + break; + + case nsXPTType::T_U8: + if (iCount < PARAM_GPR_COUNT) + dp->val.u8 = (PRUint8)gprData[iCount++]; + else + dp->val.u8 = *((PRUint8*)ap++); + break; + + case nsXPTType::T_U16: + if (iCount < PARAM_GPR_COUNT) + dp->val.u16 = (PRUint16)gprData[iCount++]; + else + dp->val.u16 = *((PRUint16*)ap++); + break; + + case nsXPTType::T_U32: + if (iCount < PARAM_GPR_COUNT) + dp->val.u32 = (PRUint32)gprData[iCount++]; + else + dp->val.u32 = *((PRUint32*)ap++); + break; + + case nsXPTType::T_U64: + if (iCount < PARAM_GPR_COUNT) + dp->val.u64 = (PRUint64)gprData[iCount++]; + else + dp->val.u64 = *((PRUint64*)ap++); + break; + + case nsXPTType::T_FLOAT: + if (iCount < PARAM_FPR_COUNT) + dp->val.f = (float)fprData[iCount++]; + else + dp->val.f = *((float*)ap++); + break; + + case nsXPTType::T_DOUBLE: + if (iCount < PARAM_FPR_COUNT) + dp->val.d = (double)fprData[iCount++]; + else + dp->val.d = *((double*)ap++); + break; + + case nsXPTType::T_BOOL: + if (iCount < PARAM_GPR_COUNT) + dp->val.b = (PRBool)gprData[iCount++]; + else + dp->val.b = *((PRBool*)ap++); + break; + + case nsXPTType::T_CHAR: + if (iCount < PARAM_GPR_COUNT) + dp->val.c = (char)gprData[iCount++]; + else + dp->val.c = *((char*)ap++); + break; + + case nsXPTType::T_WCHAR: + if (iCount < PARAM_GPR_COUNT) + dp->val.wc = (wchar_t)gprData[iCount++]; + else + dp->val.wc = *((wchar_t*)ap++); + break; + + default: + NS_ASSERTION(0, "bad type"); + break; + } + } + + result = self->mOuter->CallMethod((PRUint16)methodIndex, info, dispatchParams); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; + + return result; +} + +__asm__ ( + ".text\n" + ".intel_syntax\n" /* switch to Intel syntax to look like the MSVC assembly */ + ".globl SharedStub\n" + ".def SharedStub ; .scl 3 ; .type 46 ; .endef \n" + "SharedStub:\n" + + /* rcx is this pointer. Need backup for optimized build */ + + "mov qword ptr [rsp+88], rcx\n" + + /* + * fist 4 parameters (1st is "this" pointer) are passed in registers. + */ + + /* for floating value */ + + "movsd qword ptr [rsp+64], xmm1\n" + "movsd qword ptr [rsp+72], xmm2\n" + "movsd qword ptr [rsp+80], xmm3\n" + + /* for integer value */ + + "mov qword ptr [rsp+40], rdx\n" + "mov qword ptr [rsp+48], r8\n" + "mov qword ptr [rsp+56], r9\n" + + /* + * Call PrepareAndDispatch function + */ + + /* 5th parameter (floating parameters) of PrepareAndDispatch */ + + "lea r9, qword ptr [rsp+64]\n" + "mov qword ptr [rsp+32], r9\n" + + /* 4th parameter (normal parameters) of PrepareAndDispatch */ + + "lea r9, qword ptr [rsp+40]\n" + + /* 3rd parameter (pointer to args on stack) */ + + "lea r8, qword ptr [rsp+40+104]\n" + + /* 2nd parameter (vtbl_index) */ + + "mov rdx, r11\n" + + /* 1st parameter (this) (rcx) */ + + "call _PrepareAndDispatch\n" + + /* restore rcx */ + + "mov rcx, qword ptr [rsp+88]\n" + + /* + * clean up register + */ + + "add rsp, 104+8\n" + + /* set return address */ + + "mov rdx, qword ptr [rsp-8]\n" + + /* simulate __stdcall return */ + + "jmp rdx\n" + + /* back to AT&T syntax */ + ".att_syntax\n" + +); + +#define STUB_ENTRY(n) \ +asm(".intel_syntax\n" /* this is in intel syntax */ \ + ".text\n" \ + ".align 2\n" \ + ".if " #n " < 10\n" \ + ".globl " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev@4\n" \ + ".def " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev@4\n" \ + ".scl 3\n" /* private */ \ + ".type 46\n" /* function returning unsigned int */ \ + ".endef\n" \ + SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev@4:\n" \ + ".elseif " #n " < 100\n" \ + ".globl " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev@4\n" \ + ".def " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev@4\n" \ + ".scl 3\n" /* private */\ + ".type 46\n" /* function returning unsigned int */ \ + ".endef\n" \ + SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev@4:\n" \ + ".elseif " #n " < 1000\n" \ + ".globl " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev@4\n" \ + ".def " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev@4\n" \ + ".scl 3\n" /* private */ \ + ".type 46\n" /* function returning unsigned int */ \ + ".endef\n" \ + SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev@4:\n" \ + ".else\n" \ + ".err \"stub number " #n " >= 1000 not yet supported\"\n" \ + ".endif\n" \ + "push rbx\n" \ + "mov rbx, " #n "\n" \ + "jmp SharedStub\n" \ + ".att_syntax\n" /* back to AT&T syntax */ \ + ""); + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" + From d859d678dec49e92ee8bc791e745736f574ba94b Mon Sep 17 00:00:00 2001 From: Zack Weinberg Date: Thu, 30 Jul 2009 15:43:22 +1200 Subject: [PATCH 09/61] Bug 486065. Hack nsCSSOffsetState::InitOffsets to zero out computed padding and borders when the scrollbar size is zero. r=dbaron --HG-- extra : rebase_source : 92bcaee46ded00722e3fc86b4ca538e5f90f16ef --- layout/generic/nsHTMLReflowState.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/layout/generic/nsHTMLReflowState.cpp b/layout/generic/nsHTMLReflowState.cpp index 7bdde4a9c4c5..2a207e4da193 100644 --- a/layout/generic/nsHTMLReflowState.cpp +++ b/layout/generic/nsHTMLReflowState.cpp @@ -1925,7 +1925,8 @@ nsCSSOffsetState::InitOffsets(nscoord aContainingBlockWidth, } mComputedBorderPadding += mComputedPadding; - if (frame->GetType() == nsGkAtoms::tableFrame) { + nsIAtom* frameType = frame->GetType(); + if (frameType == nsGkAtoms::tableFrame) { nsTableFrame *tableFrame = static_cast(frame); if (tableFrame->IsBorderCollapse()) { @@ -1936,6 +1937,23 @@ nsCSSOffsetState::InitOffsets(nscoord aContainingBlockWidth, mComputedPadding.SizeTo(0,0,0,0); mComputedBorderPadding = tableFrame->GetIncludedOuterBCBorder(); } + } else if (frameType == nsGkAtoms::scrollbarFrame) { + // scrollbars may have had their width or height smashed to zero + // by the associated scrollframe, in which case we must not report + // any padding or border on that axis. + nsSize size(frame->GetSize()); + if (size.width == 0) { + mComputedPadding.left = 0; + mComputedPadding.right = 0; + mComputedBorderPadding.left = 0; + mComputedBorderPadding.right = 0; + } + if (size.height == 0) { + mComputedPadding.top = 0; + mComputedPadding.bottom = 0; + mComputedBorderPadding.top = 0; + mComputedBorderPadding.bottom = 0; + } } } From 3e38caa3b3d4e2feadd3fd9d81d74981694345c4 Mon Sep 17 00:00:00 2001 From: Matthew Gregan Date: Thu, 30 Jul 2009 15:28:53 +1200 Subject: [PATCH 10/61] Bug 500311 - Count tracks as active during initialization. r=chris.double --HG-- extra : rebase_source : 25e5d3aa9661a95e1a623a9fe15f5c12f31d13f3 --- media/liboggplay/README_MOZILLA | 2 + media/liboggplay/bug500311.patch | 99 +++++++++++++++++++ media/liboggplay/src/liboggplay/oggplay.c | 3 +- .../src/liboggplay/oggplay_callback.c | 4 +- media/liboggplay/update.sh | 1 + 5 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 media/liboggplay/bug500311.patch diff --git a/media/liboggplay/README_MOZILLA b/media/liboggplay/README_MOZILLA index 2171af1dd1a5..87b7fccd38c5 100644 --- a/media/liboggplay/README_MOZILLA +++ b/media/liboggplay/README_MOZILLA @@ -45,3 +45,5 @@ oggplay_os2.patch: Bug 448918 - add OS/2 support (this patch should be bug498815.patch: Fix for bug 498815. bug498824.patch: Fix for bug 498824. +bug500311.patch: Fix crash during decoder initialization. + diff --git a/media/liboggplay/bug500311.patch b/media/liboggplay/bug500311.patch new file mode 100644 index 000000000000..c0ba0fb492a8 --- /dev/null +++ b/media/liboggplay/bug500311.patch @@ -0,0 +1,99 @@ +diff --git a/media/liboggplay/src/liboggplay/oggplay.c b/media/liboggplay/src/liboggplay/oggplay.c +--- a/media/liboggplay/src/liboggplay/oggplay.c ++++ b/media/liboggplay/src/liboggplay/oggplay.c +@@ -129,16 +129,17 @@ oggplay_initialise(OggPlay *me, int bloc + } + + /* + * set all the tracks to inactive + */ + for (i = 0; i < me->num_tracks; i++) { + me->decode_data[i]->active = 0; + } ++ me->active_tracks = 0; + + /* + * if the buffer was set up before initialisation, prepare it now + */ + if (me->buffer != NULL) { + oggplay_buffer_prepare(me); + } + +@@ -693,18 +694,18 @@ read_more_data: + /* end-of-file */ + if (r == 0) { + num_records = oggplay_callback_info_prepare(me, &info); + /* + * set all of the tracks to inactive + */ + for (i = 0; i < me->num_tracks; i++) { + me->decode_data[i]->active = 0; +- me->active_tracks = 0; + } ++ me->active_tracks = 0; + + if (info != NULL) { + me->callback (me, num_records, info, me->callback_user_ptr); + oggplay_callback_info_destroy(me, info); + } + + /* + * ensure all tracks have their final data packet set to end_of_stream +diff --git a/media/liboggplay/src/liboggplay/oggplay_callback.c b/media/liboggplay/src/liboggplay/oggplay_callback.c +--- a/media/liboggplay/src/liboggplay/oggplay_callback.c ++++ b/media/liboggplay/src/liboggplay/oggplay_callback.c +@@ -54,16 +54,17 @@ oggplay_init_theora(void *user_data) { + theora_info_init(&(decoder->video_info)); + theora_comment_init(&(decoder->video_comment)); + decoder->remaining_header_packets = 3; + decoder->granulepos_seen = 0; + decoder->frame_delta = 0; + decoder->y_width = 0; + decoder->convert_to_rgb = 0; + decoder->decoder.decoded_type = OGGPLAY_YUV_VIDEO; ++ decoder->decoder.player->active_tracks++; + } + + void + oggplay_shutdown_theora(void *user_data) { + + OggPlayTheoraDecode * decoder = (OggPlayTheoraDecode *)user_data; + + if (decoder->remaining_header_packets == 0) { +@@ -366,16 +367,17 @@ oggplay_init_audio (void * user_data) { + + decoder->sound_info.channels = 0; + fish_sound_set_interleave(decoder->sound_handle, 1); + fish_sound_set_decoded_float_ilv(decoder->sound_handle, + oggplay_fish_sound_callback_floats, + (void *)decoder); + + decoder->decoder.decoded_type = OGGPLAY_FLOATS_AUDIO; ++ decoder->decoder.player->active_tracks++; + } + + void + oggplay_shutdown_audio(void *user_data) { + + OggPlayAudioDecode * decoder = (OggPlayAudioDecode *)user_data; + + fish_sound_delete(decoder->sound_handle); +@@ -566,17 +568,17 @@ oggplay_initialise_decoder(OggPlay *me, + + if (decoder == NULL) + return NULL; + + decoder->serialno = serialno; + decoder->content_type = content_type; + decoder->content_type_name = + oggz_stream_get_content_type (me->oggz, serialno); +- decoder->active = 0; ++ decoder->active = 1; + decoder->final_granulepos = -1; + decoder->player = me; + decoder->decoded_type = OGGPLAY_TYPE_UNKNOWN; + + /* + * set the StreamInfo to unitialised until we get some real data in + */ + decoder->stream_info = OGGPLAY_STREAM_UNINITIALISED; diff --git a/media/liboggplay/src/liboggplay/oggplay.c b/media/liboggplay/src/liboggplay/oggplay.c index ef822f8558dd..98dd6a4b8f97 100644 --- a/media/liboggplay/src/liboggplay/oggplay.c +++ b/media/liboggplay/src/liboggplay/oggplay.c @@ -134,6 +134,7 @@ oggplay_initialise(OggPlay *me, int block) { for (i = 0; i < me->num_tracks; i++) { me->decode_data[i]->active = 0; } + me->active_tracks = 0; /* * if the buffer was set up before initialisation, prepare it now @@ -698,8 +699,8 @@ read_more_data: */ for (i = 0; i < me->num_tracks; i++) { me->decode_data[i]->active = 0; - me->active_tracks = 0; } + me->active_tracks = 0; if (info != NULL) { me->callback (me, num_records, info, me->callback_user_ptr); diff --git a/media/liboggplay/src/liboggplay/oggplay_callback.c b/media/liboggplay/src/liboggplay/oggplay_callback.c index a98aef6bc8ef..b0b21412c0da 100644 --- a/media/liboggplay/src/liboggplay/oggplay_callback.c +++ b/media/liboggplay/src/liboggplay/oggplay_callback.c @@ -59,6 +59,7 @@ oggplay_init_theora(void *user_data) { decoder->y_width = 0; decoder->convert_to_rgb = 0; decoder->decoder.decoded_type = OGGPLAY_YUV_VIDEO; + decoder->decoder.player->active_tracks++; } void @@ -371,6 +372,7 @@ oggplay_init_audio (void * user_data) { (void *)decoder); decoder->decoder.decoded_type = OGGPLAY_FLOATS_AUDIO; + decoder->decoder.player->active_tracks++; } void @@ -571,7 +573,7 @@ oggplay_initialise_decoder(OggPlay *me, int content_type, int serialno) { decoder->content_type = content_type; decoder->content_type_name = oggz_stream_get_content_type (me->oggz, serialno); - decoder->active = 0; + decoder->active = 1; decoder->final_granulepos = -1; decoder->player = me; decoder->decoded_type = OGGPLAY_TYPE_UNKNOWN; diff --git a/media/liboggplay/update.sh b/media/liboggplay/update.sh index d0c9e239ffb2..1d4788edd6b4 100644 --- a/media/liboggplay/update.sh +++ b/media/liboggplay/update.sh @@ -64,3 +64,4 @@ patch -p3 < bug498815.patch patch -p3 < bug498824.patch patch -p3 < bug496529.patch patch -p3 < bug499519.patch +patch -p3 < bug500311.patch From c8d8fdf19e10a2af65a1ffefd6aebf0f1bef03a2 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Wed, 29 Jul 2009 21:27:46 -0700 Subject: [PATCH 11/61] Bug 332173 - Followup followup fix for trunk-only necessary-for-templatization changes (not needed for any branches, that is). --HG-- extra : rebase_source : 767c90867afbbe7bf52e29820c987e45c9e60d03 --- xpcom/io/nsWildCard.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xpcom/io/nsWildCard.cpp b/xpcom/io/nsWildCard.cpp index 90f3d7181781..2f788ba9ae75 100644 --- a/xpcom/io/nsWildCard.cpp +++ b/xpcom/io/nsWildCard.cpp @@ -222,7 +222,7 @@ _handle_union(const T *str, const T *expr, PRBool case_insensitive, if (cp == ABORTED || cp < 4) /* must be at least "(a|b" before ')' */ return ABORTED; ++cp; /* now index of char after closing parenthesis */ - e2 = (T *) NS_Alloc(1 + nsCharTraits::length(expr)); + e2 = (T *) NS_Alloc((1 + nsCharTraits::length(expr)) * sizeof(T)); if (!e2) return ABORTED; for (sx = 1; ; ++sx) { @@ -386,7 +386,7 @@ ns_WildCardMatch(const T *str, const T *xp, PRBool case_insensitive) if (!nsCharTraits::find(xp, nsCharTraits::length(xp), T('~'))) return _shexp_match(str, xp, case_insensitive, 0); - expr = (T *) NS_Alloc(nsCharTraits::length(xp) + 1); + expr = (T *) NS_Alloc((nsCharTraits::length(xp) + 1) * sizeof(T)); if(!expr) return NOMATCH; From 46910e2c37c54742f1a5a8209ad23de4c47922e9 Mon Sep 17 00:00:00 2001 From: Josh Aas Date: Thu, 30 Jul 2009 00:47:06 -0400 Subject: [PATCH 12/61] Cache UTF-8 POSIX path in Mac OS X nsIFile impl. b=505792 r=mstange sr=bsmedberg --- xpcom/io/nsLocalFileOSX.h | 10 +-- xpcom/io/nsLocalFileOSX.mm | 172 +++++++++++-------------------------- 2 files changed, 53 insertions(+), 129 deletions(-) diff --git a/xpcom/io/nsLocalFileOSX.h b/xpcom/io/nsLocalFileOSX.h index f818e7428983..957e2d3abfa9 100644 --- a/xpcom/io/nsLocalFileOSX.h +++ b/xpcom/io/nsLocalFileOSX.h @@ -95,21 +95,17 @@ private: protected: nsLocalFile(const nsLocalFile& src); - nsresult SetBaseURL(CFURLRef aCFURLRef); // retains aCFURLRef - nsresult GetFSRefInternal(FSRef& aFSRef); - nsresult GetPathInternal(nsACString& path); // Returns path WRT mFollowLinks + nsresult GetPathInternal(nsACString& path); // Returns path respecting mFollowLinks nsresult CopyInternal(nsIFile* newParentDir, const nsAString& newName, PRBool followLinks); nsresult FillStatBufferInternal(struct STAT *statBuffer); - static nsresult CFStringReftoUTF8(CFStringRef aInStrRef, nsACString& aOutStr); - protected: - CFURLRef mBaseURL; // The FS object we represent - + CFURLRef mBaseURL; // The FS object we represent + char mPath[PATH_MAX]; // POSIX path, UTF-8, NULL terminated PRPackedBool mFollowLinks; }; diff --git a/xpcom/io/nsLocalFileOSX.mm b/xpcom/io/nsLocalFileOSX.mm index 8f6a4fea2564..14e13d89b584 100644 --- a/xpcom/io/nsLocalFileOSX.mm +++ b/xpcom/io/nsLocalFileOSX.mm @@ -76,6 +76,7 @@ static nsresult MacErrorMapper(OSErr inErr); static void CopyUTF8toUTF16NFC(const nsACString& aSrc, nsAString& aResult); +static nsresult CFStringReftoUTF8(CFStringRef aInStrRef, nsACString& aOutStr); #pragma mark - #pragma mark [FSRef operator==] @@ -281,30 +282,23 @@ class nsDirEnumerator : public nsISimpleEnumerator, NS_IMPL_ISUPPORTS2(nsDirEnumerator, nsISimpleEnumerator, nsIDirectoryEnumerator) -#define FILENAME_BUFFER_SIZE 512 - const char kPathSepChar = '/'; #pragma mark - #pragma mark [CTORs/DTOR] nsLocalFile::nsLocalFile() : - mBaseURL(nsnull), + mBaseURL(NULL), mFollowLinks(PR_TRUE) { + mPath[0] = '\0'; } nsLocalFile::nsLocalFile(const nsLocalFile& src) : - mBaseURL(src.mBaseURL), + mBaseURL(NULL), mFollowLinks(src.mFollowLinks) { - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // CFURL objects are immutable so no need to copy, just retain. - if (mBaseURL) - ::CFRetain(mBaseURL); - - NS_OBJC_END_TRY_ABORT_BLOCK; + SetBaseURL(src.mBaseURL); } nsLocalFile::~nsLocalFile() @@ -388,14 +382,8 @@ NS_IMETHODIMP nsLocalFile::Normalize() CHECK_INIT(); - // CFURL doesn't doesn't seem to resolve paths containing relative - // components, so we'll nick the stdlib code from nsLocalFileUnix - UInt8 path[PATH_MAX] = ""; - if (!::CFURLGetFileSystemRepresentation(mBaseURL, true, path, PATH_MAX)) - return NS_ERROR_FAILURE; - char resolved_path[PATH_MAX] = ""; - if (!realpath((char*)path, resolved_path)) + if (!realpath(mPath, resolved_path)) return NSRESULT_FOR_ERRNO(); // Need to know whether we're a directory to create a new CFURLRef @@ -437,7 +425,7 @@ NS_IMETHODIMP nsLocalFile::Create(PRUint32 type, PRUint32 permissions) CFURLRef pathURLRef = mBaseURL; FSRef pathFSRef; CFStringRef leafStrRef = nsnull; - nsAutoTArray buffer; + nsAutoTArray buffer; Boolean success; // Work backwards through the path to find the last node which @@ -607,12 +595,6 @@ NS_IMETHODIMP nsLocalFile::MoveToNative(nsIFile *newParentDir, const nsACString& if (NS_FAILED(rv)) return rv; - // Get the source path. - nsCAutoString srcPath; - rv = GetNativePath(srcPath); - if (NS_FAILED(rv)) - return rv; - // Build the destination path. nsCOMPtr parentDir = newParentDir; if (!parentDir) { @@ -650,7 +632,7 @@ NS_IMETHODIMP nsLocalFile::MoveToNative(nsIFile *newParentDir, const nsACString& } // Perform the move. - if (rename(srcPath.get(), destPath.get()) != 0) { + if (rename(mPath, destPath.get()) != 0) { if (errno == EXDEV) { // Can't move across volume (device) boundaries. Copy and remove. rv = CopyToNative(parentDir, newName); @@ -706,17 +688,11 @@ NS_IMETHODIMP nsLocalFile::Remove(PRBool recursive) } } else { - nsCAutoString path; - rv = GetNativePath(path); - if (NS_FAILED(rv)) - return rv; - - const char* pathPtr = path.get(); int status; if (isDirectory) - status = rmdir(pathPtr); + status = rmdir(mPath); else - status = unlink(pathPtr); + status = unlink(mPath); if (status != 0) rv = NSRESULT_FOR_ERRNO(); @@ -750,12 +726,7 @@ NS_IMETHODIMP nsLocalFile::SetPermissions(PRUint32 aPermissions) { CHECK_INIT(); - nsCAutoString path; - nsresult rv = GetPathInternal(path); - if (NS_FAILED(rv)) - return rv; - - if (chmod(path.get(), aPermissions) < 0) + if (chmod(mPath, aPermissions) < 0) return NSRESULT_FOR_ERRNO(); return NS_OK; @@ -847,15 +818,11 @@ NS_IMETHODIMP nsLocalFile::GetFileSize(PRInt64 *aFileSize) NS_ENSURE_ARG_POINTER(aFileSize); *aFileSize = 0; - nsCAutoString path; - nsresult rv = GetPathInternal(path); + struct STAT buf; + nsresult rv = FillStatBufferInternal(&buf); if (NS_FAILED(rv)) return rv; - struct STAT buf; - if (STAT(path.get(), &buf) != 0) - return NSRESULT_FOR_ERRNO(); - if (!S_ISDIR(buf.st_mode)) *aFileSize = (PRInt64)buf.st_size; @@ -866,13 +833,8 @@ NS_IMETHODIMP nsLocalFile::SetFileSize(PRInt64 aFileSize) { CHECK_INIT(); - nsCAutoString path; - nsresult rv = GetPathInternal(path); - if (NS_FAILED(rv)) - return rv; - off_t size = (off_t)aFileSize; - if (truncate(path.get(), size) == -1) + if (truncate(mPath, size) == -1) return NSRESULT_FOR_ERRNO(); return NS_OK; @@ -910,13 +872,8 @@ NS_IMETHODIMP nsLocalFile::GetNativeTarget(nsACString& aNativeTarget) if (!isSymLink) return NS_ERROR_FILE_INVALID_PATH; - nsCAutoString nativeString; - rv = GetNativePath(nativeString); - if (NS_FAILED(rv)) - return rv; - char resolvedPathBuf[PATH_MAX]; - if (!realpath(nativeString.get(), resolvedPathBuf)) + if (!realpath(mPath, resolvedPathBuf)) return NS_ERROR_FILE_INVALID_PATH; unsigned int resolvedPathLength = strlen(resolvedPathBuf); @@ -940,32 +897,19 @@ NS_IMETHODIMP nsLocalFile::GetPath(nsAString& aPath) NS_IMETHODIMP nsLocalFile::GetNativePath(nsACString& aNativePath) { - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - CHECK_INIT(); - nsresult rv = NS_ERROR_FAILURE; - CFStringRef pathStrRef = ::CFURLCopyFileSystemPath(mBaseURL, kCFURLPOSIXPathStyle); - if (pathStrRef) { - rv = CFStringReftoUTF8(pathStrRef, aNativePath); - ::CFRelease(pathStrRef); - } - return rv; + aNativePath.Assign(mPath); - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; + return NS_OK; } NS_IMETHODIMP nsLocalFile::Exists(PRBool *_retval) { NS_ENSURE_ARG_POINTER(_retval); - nsCAutoString path; - nsresult rv = GetPathInternal(path); - if (NS_FAILED(rv)) - return rv; - struct STAT buf; - *_retval = (STAT(path.get(), &buf) == 0); + *_retval = (STAT(mPath, &buf) == 0); return NS_OK; } @@ -1098,26 +1042,17 @@ NS_IMETHODIMP nsLocalFile::IsFile(PRBool *_retval) NS_IMETHODIMP nsLocalFile::IsSymlink(PRBool *_retval) { - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - CHECK_INIT(); NS_ENSURE_ARG(_retval); *_retval = PR_FALSE; - // First see if we are an actual symlink - nsCAutoString path; - nsresult rv = GetNativePath(path); - if (NS_FAILED(rv)) - return rv; struct stat symStat; - if (lstat(path.get(), &symStat) < 0) + if (lstat(mPath, &symStat) < 0) return NSRESULT_FOR_ERRNO(); *_retval = S_ISLNK(symStat.st_mode); return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; } NS_IMETHODIMP nsLocalFile::IsSpecial(PRBool *_retval) @@ -1149,12 +1084,7 @@ NS_IMETHODIMP nsLocalFile::Equals(nsIFile *inFile, PRBool *_retval) if (NS_FAILED(rv)) return rv; - nsCAutoString thisPath; - rv = GetNativePath(thisPath); - if (NS_FAILED(rv)) - return rv; - - *_retval = !strcmp(inPath.get(), thisPath.get()); + *_retval = !strcmp(mPath, inPath.get()); return NS_OK; } @@ -1976,6 +1906,9 @@ nsresult nsLocalFile::SetBaseURL(CFURLRef aCFURLRef) ::CFRelease(mBaseURL); mBaseURL = aCFURLRef; + if (!::CFURLGetFileSystemRepresentation(mBaseURL, NO, (UInt8*)mPath, PATH_MAX)) + return NS_ERROR_FAILURE; + return NS_OK; NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; @@ -2082,43 +2015,14 @@ nsresult nsLocalFile::FillStatBufferInternal(struct STAT *statBuffer) { CHECK_INIT(); - char path[PATH_MAX] = ""; - Boolean gotPath = ::CFURLGetFileSystemRepresentation(mBaseURL, true, (UInt8*)path, PATH_MAX); - if (!gotPath) - return NS_ERROR_FAILURE; - - if (STAT(path, statBuffer) == -1) { - if (LSTAT(path, statBuffer) == -1) + if (STAT(mPath, statBuffer) == -1) { + if (LSTAT(mPath, statBuffer) == -1) return NSRESULT_FOR_ERRNO(); } return NS_OK; } -nsresult nsLocalFile::CFStringReftoUTF8(CFStringRef aInStrRef, nsACString& aOutStr) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - // first see if the conversion would succeed and find the length of the result - CFIndex usedBufLen, inStrLen = ::CFStringGetLength(aInStrRef); - CFIndex charsConverted = ::CFStringGetBytes(aInStrRef, CFRangeMake(0, inStrLen), - kCFStringEncodingUTF8, 0, PR_FALSE, - NULL, 0, &usedBufLen); - if (charsConverted == inStrLen) { - // all characters converted, do the actual conversion - aOutStr.SetLength(usedBufLen); - if (aOutStr.Length() != (unsigned int)usedBufLen) - return NS_ERROR_OUT_OF_MEMORY; - UInt8 *buffer = (UInt8*)aOutStr.BeginWriting(); - ::CFStringGetBytes(aInStrRef, CFRangeMake(0, inStrLen), kCFStringEncodingUTF8, - 0, false, buffer, usedBufLen, &usedBufLen); - return NS_OK; - } - return NS_ERROR_FAILURE; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - // nsIHashable NS_IMETHODIMP @@ -2304,7 +2208,7 @@ static void CopyUTF8toUTF16NFC(const nsACString& aSrc, nsAString& aResult) aResult.Assign(chars, length); } else { - nsAutoTArray buffer; + nsAutoTArray buffer; if (!buffer.SetLength(length)) { CopyUTF8toUTF16(aSrc, aResult); } @@ -2317,3 +2221,27 @@ static void CopyUTF8toUTF16NFC(const nsACString& aSrc, nsAString& aResult) NS_OBJC_END_TRY_ABORT_BLOCK; } + +nsresult CFStringReftoUTF8(CFStringRef aInStrRef, nsACString& aOutStr) +{ + NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; + + // first see if the conversion would succeed and find the length of the result + CFIndex usedBufLen, inStrLen = ::CFStringGetLength(aInStrRef); + CFIndex charsConverted = ::CFStringGetBytes(aInStrRef, CFRangeMake(0, inStrLen), + kCFStringEncodingUTF8, 0, PR_FALSE, + NULL, 0, &usedBufLen); + if (charsConverted == inStrLen) { + // all characters converted, do the actual conversion + aOutStr.SetLength(usedBufLen); + if (aOutStr.Length() != (unsigned int)usedBufLen) + return NS_ERROR_OUT_OF_MEMORY; + UInt8 *buffer = (UInt8*)aOutStr.BeginWriting(); + ::CFStringGetBytes(aInStrRef, CFRangeMake(0, inStrLen), kCFStringEncodingUTF8, + 0, false, buffer, usedBufLen, &usedBufLen); + return NS_OK; + } + return NS_ERROR_FAILURE; + + NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; +} From 7170799d2d468cf533903c55e273a2d18b9416d8 Mon Sep 17 00:00:00 2001 From: Felipe Gomes Date: Wed, 29 Jul 2009 23:01:27 -0700 Subject: [PATCH 13/61] Bug 492152 - Scrollable menus should support panning on Win7. r=jmathies, sr=vlad --- widget/src/windows/nsWinGesture.cpp | 8 ++++---- widget/src/windows/nsWinGesture.h | 4 ++-- widget/src/windows/nsWindow.cpp | 19 ++++++++++++++----- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/widget/src/windows/nsWinGesture.cpp b/widget/src/windows/nsWinGesture.cpp index 887812a1025c..24cf2b23fb15 100644 --- a/widget/src/windows/nsWinGesture.cpp +++ b/widget/src/windows/nsWinGesture.cpp @@ -461,11 +461,11 @@ inline PRBool TestTransition(PRInt32 a, PRInt32 b) } void -nsWinGesture::UpdatePanFeedbackX(HWND hWnd, nsMouseScrollEvent& evt, PRBool& endFeedback) +nsWinGesture::UpdatePanFeedbackX(HWND hWnd, PRInt32 scrollOverflow, PRBool& endFeedback) { // If scroll overflow was returned indicating we panned past the bounds of // the scrollable view port, start feeback. - if (evt.scrollOverflow != 0) { + if (scrollOverflow != 0) { if (!mFeedbackActive) { BeginPanningFeedback(hWnd); mFeedbackActive = PR_TRUE; @@ -490,11 +490,11 @@ nsWinGesture::UpdatePanFeedbackX(HWND hWnd, nsMouseScrollEvent& evt, PRBool& end } void -nsWinGesture::UpdatePanFeedbackY(HWND hWnd, nsMouseScrollEvent& evt, PRBool& endFeedback) +nsWinGesture::UpdatePanFeedbackY(HWND hWnd, PRInt32 scrollOverflow, PRBool& endFeedback) { // If scroll overflow was returned indicating we panned past the bounds of // the scrollable view port, start feeback. - if (evt.scrollOverflow != 0) { + if (scrollOverflow != 0) { if (!mFeedbackActive) { BeginPanningFeedback(hWnd); mFeedbackActive = PR_TRUE; diff --git a/widget/src/windows/nsWinGesture.h b/widget/src/windows/nsWinGesture.h index a21b26d5a724..c8b3c9d4786e 100644 --- a/widget/src/windows/nsWinGesture.h +++ b/widget/src/windows/nsWinGesture.h @@ -206,8 +206,8 @@ public: PRBool ProcessPanMessage(HWND hWnd, WPARAM wParam, LPARAM lParam); PRBool PanDeltaToPixelScrollX(nsMouseScrollEvent& evt); PRBool PanDeltaToPixelScrollY(nsMouseScrollEvent& evt); - void UpdatePanFeedbackX(HWND hWnd, nsMouseScrollEvent& evt, PRBool& endFeedback); - void UpdatePanFeedbackY(HWND hWnd, nsMouseScrollEvent& evt, PRBool& endFeedback); + void UpdatePanFeedbackX(HWND hWnd, PRInt32 scrollOverflow, PRBool& endFeedback); + void UpdatePanFeedbackY(HWND hWnd, PRInt32 scrollOverflow, PRBool& endFeedback); void PanFeedbackFinalize(HWND hWnd, PRBool endFeedback); public: diff --git a/widget/src/windows/nsWindow.cpp b/widget/src/windows/nsWindow.cpp index d6976c8f08de..3bd7c73bd864 100644 --- a/widget/src/windows/nsWindow.cpp +++ b/widget/src/windows/nsWindow.cpp @@ -4620,17 +4620,26 @@ PRBool nsWindow::OnGesture(WPARAM wParam, LPARAM lParam) event.time = ::GetMessageTime(); PRBool endFeedback = PR_TRUE; - + + PRInt32 scrollOverflowX = 0; + PRInt32 scrollOverflowY = 0; + if (mGesture.PanDeltaToPixelScrollX(event)) { DispatchEvent(&event, status); + scrollOverflowX = event.scrollOverflow; } - mGesture.UpdatePanFeedbackX(mWnd, event, endFeedback); - + if (mGesture.PanDeltaToPixelScrollY(event)) { DispatchEvent(&event, status); + scrollOverflowY = event.scrollOverflow; } - mGesture.UpdatePanFeedbackY(mWnd, event, endFeedback); - mGesture.PanFeedbackFinalize(mWnd, endFeedback); + + if (mWindowType != eWindowType_popup) { + mGesture.UpdatePanFeedbackX(mWnd, scrollOverflowX, endFeedback); + mGesture.UpdatePanFeedbackY(mWnd, scrollOverflowY, endFeedback); + mGesture.PanFeedbackFinalize(mWnd, endFeedback); + } + mGesture.CloseGestureInfoHandle((HGESTUREINFO)lParam); return PR_TRUE; From bb34f661d59929e2557220ac2c3bb9d03518b2cf Mon Sep 17 00:00:00 2001 From: Robert Strong Date: Wed, 29 Jul 2009 23:01:36 -0700 Subject: [PATCH 14/61] Bug 506696 - [WinCE] updater.exe doesn't use the working directory when applying the update. r=bsmedberg, r=blassey --- .../update/src/updater/archivereader.cpp | 10 +- .../update/src/updater/archivereader.h | 15 +- .../mozapps/update/src/updater/updater.cpp | 233 ++++++++++++------ .../update/src/updater/updater_wince.cpp | 94 +++---- .../update/src/updater/updater_wince.h | 6 +- 5 files changed, 208 insertions(+), 150 deletions(-) diff --git a/toolkit/mozapps/update/src/updater/archivereader.cpp b/toolkit/mozapps/update/src/updater/archivereader.cpp index a2686a990693..10f81ea2f6e1 100644 --- a/toolkit/mozapps/update/src/updater/archivereader.cpp +++ b/toolkit/mozapps/update/src/updater/archivereader.cpp @@ -53,11 +53,7 @@ #endif int -#ifdef XP_WIN -ArchiveReader::Open(const WCHAR *path) -#else -ArchiveReader::Open(const char *path) -#endif +ArchiveReader::Open(const NS_tchar *path) { if (mArchive) Close(); @@ -83,14 +79,14 @@ ArchiveReader::Close() } int -ArchiveReader::ExtractFile(const char *name, const char *dest) +ArchiveReader::ExtractFile(const char *name, const NS_tchar *dest) { const MarItem *item = mar_find_item(mArchive, name); if (!item) return READ_ERROR; #ifdef XP_WIN - FILE* fp = fopen(dest, "wb+"); + FILE* fp = _wfopen(dest, L"wb+"); #else int fd = creat(dest, item->flags); if (fd == -1) diff --git a/toolkit/mozapps/update/src/updater/archivereader.h b/toolkit/mozapps/update/src/updater/archivereader.h index 2421faedee93..ce3fc6a9a39c 100644 --- a/toolkit/mozapps/update/src/updater/archivereader.h +++ b/toolkit/mozapps/update/src/updater/archivereader.h @@ -42,6 +42,12 @@ #include #include "mar.h" +#ifdef XP_WIN +# define NS_tchar WCHAR +#else +# define NS_tchar char +#endif + // This class provides an API to extract files from an update archive. class ArchiveReader { @@ -49,15 +55,10 @@ public: ArchiveReader() : mArchive(NULL) {} ~ArchiveReader() { Close(); } -#ifdef XP_WIN - int Open(const WCHAR *path); -#else - int Open(const char *path); -#endif - + int Open(const NS_tchar *path); void Close(); - int ExtractFile(const char *item, const char *destination); + int ExtractFile(const char *item, const NS_tchar *destination); int ExtractFileToStream(const char *item, FILE *fp); private: diff --git a/toolkit/mozapps/update/src/updater/updater.cpp b/toolkit/mozapps/update/src/updater/updater.cpp index b41bff278dcc..f41a06dd14f3 100644 --- a/toolkit/mozapps/update/src/updater/updater.cpp +++ b/toolkit/mozapps/update/src/updater/updater.cpp @@ -59,15 +59,23 @@ # define putenv _putenv # define snprintf _snprintf # define fchmod(a,b) -# define mkdir(path, perms) _mkdir(path) # define NS_T(str) L ## str # define NS_tsnprintf _snwprintf # define NS_tstrrchr wcsrchr +# define NS_taccess _waccess # define NS_tchdir _wchdir +# define NS_tchmod _wchmod +# define NS_tmkdir(path, perms) _wmkdir(path) # define NS_tremove _wremove # define NS_tfopen _wfopen # define NS_tatoi _wtoi64 +#ifndef WINCE +# define stat _stat +#endif +# define NS_tstat _wstat +# define BACKUP_EXT L".moz-backup" +# define LOG_S "%S" #else # include # include @@ -75,10 +83,16 @@ # define NS_T(str) str # define NS_tsnprintf snprintf # define NS_tstrrchr strrchr +# define NS_taccess access # define NS_tchdir chdir +# define NS_tchmod chmod +# define NS_tmkdir mkdir # define NS_tremove remove # define NS_tfopen fopen # define NS_tatoi atoi +# define NS_tstat stat +# define BACKUP_EXT ".moz-backup" +# define LOG_S "%s" #endif #include "bspatch.h" @@ -297,6 +311,11 @@ private: //----------------------------------------------------------------------------- +#ifdef WINCE +// Since WinCE doesn't have a current working directory store the current +// working directory specified in the command line arguments +static NS_tchar* gDestPath; +#endif static NS_tchar* gSourcePath; static ArchiveReader gArchiveReader; #ifdef XP_WIN @@ -392,10 +411,38 @@ mstrtok(const char *delims, char **str) return ret; } -static void ensure_write_permissions(const char *path) +#ifdef XP_WIN +// Returns a wchar path. The path returned will be absolute on Windows CE / +// Windows Mobile and relative on all other versions of Windows. +static NS_tchar* +get_wide_path(const char *path) +{ + WCHAR *s = (WCHAR*) malloc(MAXPATHLEN * sizeof(WCHAR)); + if (!s) + return NULL; + + WCHAR *c = s; + WCHAR wpath[MAXPATHLEN]; + MultiByteToWideChar(CP_ACP, 0, path, -1, wpath, MAXPATHLEN); +#ifndef WINCE + wcscpy(c, wpath); + c += wcslen(wpath); +#else + wcscpy(c, gDestPath); + c += wcslen(gDestPath); + wcscat(c, wpath); + c += wcslen(wpath); +#endif + *c = NS_T('\0'); + c++; + return s; +} +#endif + +static void ensure_write_permissions(const NS_tchar *path) { #ifdef XP_WIN - (void) chmod(path, _S_IREAD | _S_IWRITE); + (void) _wchmod(path, _S_IREAD | _S_IWRITE); #else struct stat fs; if (!stat(path, &fs) && !(fs.st_mode & S_IWUSR)) { @@ -404,25 +451,25 @@ static void ensure_write_permissions(const char *path) #endif } -static int ensure_remove(const char *path) +static int ensure_remove(const NS_tchar *path) { ensure_write_permissions(path); - int rv = remove(path); + int rv = NS_tremove(path); if (rv) - LOG(("remove failed: %d,%d (%s)\n", rv, errno, path)); + LOG(("remove failed: %d,%d (" LOG_S ")\n", rv, errno, path)); return rv; } -static FILE* ensure_open(const char *path, const char* flags, unsigned int options) +static FILE* ensure_open(const NS_tchar *path, const NS_tchar* flags, unsigned int options) { ensure_write_permissions(path); - FILE* f = fopen(path, flags); - if (chmod(path, options) != 0) { + FILE* f = NS_tfopen(path, flags); + if (NS_tchmod(path, options) != 0) { fclose(f); return NULL; } struct stat ss; - if (stat(path, &ss) != 0 || ss.st_mode != options) { + if (NS_tstat(path, &ss) != 0 || ss.st_mode != options) { fclose(f); return NULL; } @@ -430,30 +477,30 @@ static FILE* ensure_open(const char *path, const char* flags, unsigned int optio } // Ensure that the directory containing this file exists. -static int ensure_parent_dir(const char *path) +static int ensure_parent_dir(const NS_tchar *path) { int rv = OK; - char *slash = (char *) strrchr(path, '/'); - if (slash) - { - *slash = '\0'; + NS_tchar *slash = (NS_tchar *) NS_tstrrchr(path, NS_T('/')); + if (slash) { + *slash = NS_T('\0'); rv = ensure_parent_dir(path); if (rv == OK) { - rv = mkdir(path, 0755); - // If the directory already exists, then ignore the error. + rv = NS_tmkdir(path, 0755); + // If the directory already exists, then ignore the error. On WinCE rv + // will equal 0 if the directory already exists. if (rv < 0 && errno != EEXIST) { rv = WRITE_ERROR; } else { rv = OK; } } - *slash = '/'; + *slash = NS_T('/'); } return rv; } -static int copy_file(const char *spath, const char *dpath) +static int copy_file(const NS_tchar *spath, const NS_tchar *dpath) { int rv = ensure_parent_dir(dpath); if (rv) @@ -461,15 +508,15 @@ static int copy_file(const char *spath, const char *dpath) struct stat ss; - AutoFile sfile = fopen(spath, "rb"); + AutoFile sfile = NS_tfopen(spath, NS_T("rb")); if (sfile == NULL || fstat(fileno(sfile), &ss)) { - LOG(("copy_file: failed to open or stat: %p,%s,%d\n", sfile.get(), spath, errno)); + LOG(("copy_file: failed to open or stat: %p," LOG_S ",%d\n", sfile, spath, errno)); return READ_ERROR; } - AutoFile dfile = ensure_open(dpath, "wb+", ss.st_mode); + AutoFile dfile = ensure_open(dpath, NS_T("wb+"), ss.st_mode); if (dfile == NULL) { - LOG(("copy_file: failed to open: %s,%d\n", dpath, errno)); + LOG(("copy_file: failed to open: " LOG_S ",%d\n", dpath, errno)); return WRITE_ERROR; } @@ -498,13 +545,11 @@ static int copy_file(const char *spath, const char *dpath) //----------------------------------------------------------------------------- -#define BACKUP_EXT ".moz-backup" - // Create a backup copy of the specified file alongside it. -static int backup_create(const char *path) +static int backup_create(const NS_tchar *path) { - char backup[MAXPATHLEN]; - snprintf(backup, sizeof(backup), "%s" BACKUP_EXT, path); + NS_tchar backup[MAXPATHLEN]; + NS_tsnprintf(backup, sizeof(backup), NS_T("%s" BACKUP_EXT), path); return copy_file(path, backup); } @@ -512,10 +557,10 @@ static int backup_create(const char *path) // Copy the backup copy of the specified file back overtop // the specified file. // XXX should be a file move instead -static int backup_restore(const char *path) +static int backup_restore(const NS_tchar *path) { - char backup[MAXPATHLEN]; - snprintf(backup, sizeof(backup), "%s" BACKUP_EXT, path); + NS_tchar backup[MAXPATHLEN]; + NS_tsnprintf(backup, sizeof(backup), NS_T("%s" BACKUP_EXT), path); int rv = copy_file(backup, path); if (rv) @@ -529,10 +574,10 @@ static int backup_restore(const char *path) } // Discard the backup copy of the specified file. -static int backup_discard(const char *path) +static int backup_discard(const NS_tchar *path) { - char backup[MAXPATHLEN]; - snprintf(backup, sizeof(backup), "%s" BACKUP_EXT, path); + NS_tchar backup[MAXPATHLEN]; + NS_tsnprintf(backup, sizeof(backup), NS_T("%s" BACKUP_EXT), path); int rv = ensure_remove(backup); if (rv) @@ -542,7 +587,7 @@ static int backup_discard(const char *path) } // Helper function for post-processing a temporary backup. -static void backup_finish(const char *path, int status) +static void backup_finish(const NS_tchar *path, int status) { if (status == OK) backup_discard(path); @@ -586,7 +631,7 @@ private: class RemoveFile : public Action { public: - RemoveFile() : mFile(NULL), mSkip(0) { } + RemoveFile() : mFile(NULL), mDestFile(NULL), mSkip(0) { } int Parse(char *line); int Prepare(); @@ -595,6 +640,7 @@ public: private: const char* mFile; + const NS_tchar* mDestFile; int mSkip; }; @@ -607,35 +653,45 @@ RemoveFile::Parse(char *line) if (!mFile) return PARSE_ERROR; +#ifdef XP_WIN + mDestFile = get_wide_path(mFile); + if (!mDestFile) + return PARSE_ERROR; +#else + mDestFile = mFile; +#endif + return OK; } int RemoveFile::Prepare() { - LOG(("PREPARE REMOVE %s\n", mFile)); + LOG(("PREPARE REMOVE " LOG_S "\n", mDestFile)); // We expect the file to exist if we are to remove it. - int rv = access(mFile, F_OK); + int rv = NS_taccess(mDestFile, F_OK); if (rv) { LOG(("file cannot be removed because it does not exist; skipping\n")); mSkip = 1; return OK; } - char *slash = (char *) strrchr(mFile, '/'); +#ifndef WINCE + NS_tchar *slash = (NS_tchar *) NS_tstrrchr(mDestFile, NS_T('/')); if (slash) { - *slash = '\0'; - rv = access(mFile, W_OK); - *slash = '/'; + *slash = NS_T('\0'); + rv = NS_taccess(mDestFile, W_OK); + *slash = NS_T('/'); } else { - rv = access(".", W_OK); + rv = NS_taccess(NS_T("."), W_OK); } if (rv) { LOG(("access failed: %d\n", errno)); return WRITE_ERROR; } +#endif return OK; } @@ -643,7 +699,7 @@ RemoveFile::Prepare() int RemoveFile::Execute() { - LOG(("EXECUTE REMOVE %s\n", mFile)); + LOG(("EXECUTE REMOVE " LOG_S "\n", mDestFile)); if (mSkip) return OK; @@ -651,7 +707,7 @@ RemoveFile::Execute() // We expect the file to exist if we are to remove it. We check here as well // as in PREPARE since we might have been asked to remove the same file more // than once: bug 311099. - int rv = access(mFile, F_OK); + int rv = NS_taccess(mDestFile, F_OK); if (rv) { LOG(("file cannot be removed because it does not exist; skipping\n")); mSkip = 1; @@ -661,13 +717,13 @@ RemoveFile::Execute() // save a complete copy of the old file, and then remove the // old file. we'll clean up the copy in Finish. - rv = backup_create(mFile); + rv = backup_create(mDestFile); if (rv) { LOG(("backup_create failed: %d\n", rv)); return rv; } - rv = ensure_remove(mFile); + rv = ensure_remove(mDestFile); if (rv) return WRITE_ERROR; @@ -677,18 +733,18 @@ RemoveFile::Execute() void RemoveFile::Finish(int status) { - LOG(("FINISH REMOVE %s\n", mFile)); + LOG(("FINISH REMOVE " LOG_S "\n", mDestFile)); if (mSkip) return; - backup_finish(mFile, status); + backup_finish(mDestFile, status); } class AddFile : public Action { public: - AddFile() : mFile(NULL) { } + AddFile() : mFile(NULL), mDestFile(NULL) { } virtual int Parse(char *line); virtual int Prepare(); // check that the source file exists @@ -697,6 +753,7 @@ public: private: const char *mFile; + const NS_tchar *mDestFile; }; int @@ -708,13 +765,21 @@ AddFile::Parse(char *line) if (!mFile) return PARSE_ERROR; +#ifdef XP_WIN + mDestFile = get_wide_path(mFile); + if (!mDestFile) + return PARSE_ERROR; +#else + mDestFile = mFile; +#endif + return OK; } int AddFile::Prepare() { - LOG(("PREPARE ADD %s\n", mFile)); + LOG(("PREPARE ADD " LOG_S "\n", mDestFile)); return OK; } @@ -722,37 +787,35 @@ AddFile::Prepare() int AddFile::Execute() { - LOG(("EXECUTE ADD %s\n", mFile)); + LOG(("EXECUTE ADD " LOG_S "\n", mDestFile)); int rv; // First make sure that we can actually get rid of any existing file. - if (access(mFile, F_OK) == 0) - { - rv = backup_create(mFile); + rv = NS_taccess(mDestFile, F_OK); + if (rv == 0) { + rv = backup_create(mDestFile); if (rv) return rv; - rv = ensure_remove(mFile); + rv = ensure_remove(mDestFile); if (rv) return WRITE_ERROR; - } - else - { - rv = ensure_parent_dir(mFile); + } else { + rv = ensure_parent_dir(mDestFile); if (rv) return rv; } - - return gArchiveReader.ExtractFile(mFile, mFile); + + return gArchiveReader.ExtractFile(mFile, mDestFile); } void AddFile::Finish(int status) { - LOG(("FINISH ADD %s\n", mFile)); + LOG(("FINISH ADD " LOG_S "\n", mDestFile)); - backup_finish(mFile, status); + backup_finish(mDestFile, status); } class PatchFile : public Action @@ -773,6 +836,7 @@ private: const char *mPatchFile; const char *mFile; + const NS_tchar *mDestFile; int mPatchIndex; MBSPatchHeader header; FILE* pfile; @@ -855,13 +919,21 @@ PatchFile::Parse(char *line) if (!mFile) return PARSE_ERROR; +#ifdef XP_WIN + mDestFile = get_wide_path(mFile); + if (!mDestFile) + return PARSE_ERROR; +#else + mDestFile = mFile; +#endif + return OK; } int PatchFile::Prepare() { - LOG(("PREPARE PATCH %s\n", mFile)); + LOG(("PREPARE PATCH " LOG_S "\n", mDestFile)); // extract the patch to a temporary file mPatchIndex = sPatchIndex++; @@ -893,7 +965,7 @@ PatchFile::Prepare() if (rv) return rv; - AutoFile ofile = fopen(mFile, "rb"); + AutoFile ofile = NS_tfopen(mDestFile, NS_T("rb")); if (ofile == NULL) return READ_ERROR; @@ -906,23 +978,23 @@ PatchFile::Prepare() int PatchFile::Execute() { - LOG(("EXECUTE PATCH %s\n", mFile)); + LOG(("EXECUTE PATCH %s\n", mDestFile)); // Create backup copy of the destination file before proceeding. struct stat ss; - if (stat(mFile, &ss)) + if (NS_tstat(mDestFile, &ss)) return READ_ERROR; - int rv = backup_create(mFile); + int rv = backup_create(mDestFile); if (rv) return rv; - rv = ensure_remove(mFile); + rv = ensure_remove(mDestFile); if (rv) return WRITE_ERROR; - AutoFile ofile = ensure_open(mFile, "wb+", ss.st_mode); + AutoFile ofile = ensure_open(mDestFile, NS_T("wb+"), ss.st_mode); if (ofile == NULL) return WRITE_ERROR; @@ -932,9 +1004,9 @@ PatchFile::Execute() void PatchFile::Finish(int status) { - LOG(("FINISH PATCH %s\n", mFile)); + LOG(("FINISH PATCH %s\n", mDestFile)); - backup_finish(mFile, status); + backup_finish(mDestFile, status); } class AddIfFile : public AddFile @@ -1177,7 +1249,7 @@ LaunchCallbackApp(const NS_tchar *workingDir, int argc, NS_tchar **argv) // Run from the specified working directory (see bug 312360). if(NS_tchdir(workingDir) != 0) - LOG(("Warning: chdir failed")); + LOG(("Warning: chdir failed\n")); #if defined(USE_EXECV) execv(argv[0], argv); @@ -1250,10 +1322,17 @@ int NS_main(int argc, NS_tchar **argv) // necessary for the parent process to exit before its executable image may // be altered. +#ifndef WINCE if (argc < 2) { fprintf(stderr, "Usage: updater [parent-pid [working-dir callback args...]]\n"); return 1; } +#else + if (argc < 4) { + fprintf(stderr, "Usage: updater parent-pid [callback args...]]\n"); + return 1; + } +#endif if (argc > 2 ) { int pid = NS_tatoi(argv[2]); @@ -1366,6 +1445,9 @@ int NS_main(int argc, NS_tchar **argv) #endif gSourcePath = argv[1]; +#ifdef WINCE + gDestPath = argv[3]; +#endif LogInit(); @@ -1477,8 +1559,7 @@ ActionList::Execute() UpdateProgressUI(1.0f + float(i++) / divisor); int rv = a->Execute(); - if (rv) - { + if (rv) { LOG(("### execution failed\n")); return rv; } diff --git a/toolkit/mozapps/update/src/updater/updater_wince.cpp b/toolkit/mozapps/update/src/updater/updater_wince.cpp index 3f6ea35712b0..04ca864ca242 100644 --- a/toolkit/mozapps/update/src/updater/updater_wince.cpp +++ b/toolkit/mozapps/update/src/updater/updater_wince.cpp @@ -42,55 +42,39 @@ # define W_OK 02 # define R_OK 04 -int remove(const char* path) +int chmod(const char* path, unsigned int mode) { - if (!_unlink(path)) { - return 0; - } - else if (GetLastError() == ERROR_ACCESS_DENIED) { - WCHAR wpath[MAX_PATH]; - - MultiByteToWideChar(CP_ACP, - 0, - path, - -1, - wpath, - MAX_PATH ); - return RemoveDirectoryW(wpath) ? 0:-1; - } - else { - return -1; - } + return 0; } -int chmod(const char* path, unsigned int mode) +int _wchmod(const WCHAR* path, unsigned int mode) { return 0; } int fstat(FILE* handle, struct stat* buff) { - int position = ftell(handle); - if (position < 0) - return -1; + int position = ftell(handle); + if (position < 0) + return -1; - if (fseek(handle, 0, SEEK_END) < 0) - return -1; + if (fseek(handle, 0, SEEK_END) < 0) + return -1; - buff->st_size = ftell(handle); + buff->st_size = ftell(handle); - if (fseek(handle, position, SEEK_SET) < 0) - return -1; + if (fseek(handle, position, SEEK_SET) < 0) + return -1; - if (buff->st_size < 0) - return -1; + if (buff->st_size < 0) + return -1; - buff->st_mode = _S_IFREG | _S_IREAD | _S_IWRITE | _S_IEXEC; - /* can't get time from a file handle on wince */ - buff->st_ctime = 0; - buff->st_atime = 0; - buff->st_mtime = 0; - return 0; + buff->st_mode = _S_IFREG | _S_IREAD | _S_IWRITE | _S_IEXEC; + /* can't get time from a file handle on wince */ + buff->st_ctime = 0; + buff->st_atime = 0; + buff->st_mtime = 0; + return 0; } int stat(const char* path, struct stat* buf) @@ -101,16 +85,20 @@ int stat(const char* path, struct stat* buf) return rv; } -int _mkdir(const char* path) +int _wstat(const WCHAR* path, struct stat* buf) { - WCHAR wpath[MAX_PATH]; - MultiByteToWideChar(CP_ACP, - 0, - path, - -1, - wpath, - MAX_PATH ); - return CreateDirectoryW(wpath, NULL) ? 0 : -1; + FILE* f = _wfopen(path, L"r"); + int rv = fstat(f, buf); + fclose(f); + return rv; +} + +int _wmkdir(const WCHAR* path) +{ + DWORD dwAttr = GetFileAttributesW(path); + if (dwAttr != INVALID_FILE_ATTRIBUTES) + return (dwAttr & FILE_ATTRIBUTE_DIRECTORY) ? 0 : -1; + return CreateDirectoryW(path, NULL) ? 0 : -1; } FILE* fileno(FILE* f) @@ -127,22 +115,14 @@ int _access(const char* path, int amode) -1, wpath, MAX_PATH ); - switch (amode) { - case R_OK: - return (GetFileAttributesW(wpath) != INVALID_FILE_ATTRIBUTES); - default: - return 0; - } + return _waccess(wpath, amode); } + int _waccess(const WCHAR* path, int amode) { - switch (amode) { - case R_OK: - return (GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES); - default: - return 0; - } - + if (amode == F_OK) + return (GetFileAttributesW(path) == INVALID_FILE_ATTRIBUTES) ? -1 : 0; + return -1; } int _wremove(const WCHAR* wpath) diff --git a/toolkit/mozapps/update/src/updater/updater_wince.h b/toolkit/mozapps/update/src/updater/updater_wince.h index 11e300f72da2..a32d6a69087e 100644 --- a/toolkit/mozapps/update/src/updater/updater_wince.h +++ b/toolkit/mozapps/update/src/updater/updater_wince.h @@ -54,11 +54,11 @@ struct stat { time_t st_atime; time_t st_mtime; }; -int remove(const char* path); -int chmod(const char* path, unsigned int mode); +int _wchmod(const WCHAR* path, unsigned int mode); int fstat(FILE* handle, struct stat* buff); int stat(const char* path, struct stat* buf); -int _mkdir(const char* path); +int _wstat(const WCHAR* path, struct stat* buf); +int _wmkdir(const WCHAR* path); int access(const char* path, int amode); int _waccess(const WCHAR* path, int amode); int _wremove(const WCHAR* wpath); From eddcc72376b83222b36a6e09f5a46e129d7b3e7e Mon Sep 17 00:00:00 2001 From: Robert Strong Date: Wed, 29 Jul 2009 23:01:43 -0700 Subject: [PATCH 15/61] Updated tests for Bug 506696. r=me --- .../test/unit/data/aus-0110_general.mar | Bin 1444 -> 1577 bytes .../test/unit/data/aus-0111_general.mar | Bin 1255 -> 1392 bytes .../update/test/unit/test_0110_general.js | 46 ++-- .../update/test/unit/test_0111_general.js | 63 +++--- .../update/test/unit/test_0112_general.js | 199 ++++++++++++++++++ 5 files changed, 258 insertions(+), 50 deletions(-) create mode 100644 toolkit/mozapps/update/test/unit/test_0112_general.js diff --git a/toolkit/mozapps/update/test/unit/data/aus-0110_general.mar b/toolkit/mozapps/update/test/unit/data/aus-0110_general.mar index f24dfd4fc9c532b4ba405b17346ff814a625f754..9642ff94e25a0842136a381bbb341f823eff4540 100644 GIT binary patch delta 302 zcmZ3&y^<%>*D=VDfq}KaDJsL#&@oaiI5KVRDH#R^rP~b*0s)L07#J9qEsk+eU`RSpc z{o+Ng76B7LMsAF~$TIl{i)H;*pphIvoXEhyxUIAxC9xz`FE=qSGcC2a1Srgq$-uyp z4wB1FEQ&7y3hEo`8^(iid}eN9da9vbK^{;61Iq;()q6&K8G=Q+WetGu&W_~6UQ-p--%-8+@$Xn1JPPc&xO zn0b+<3}`|T5OV-=C<6oIw$g%>#FA9K+{C=hwAA7fpfE!$0|QGsNG>s0E zvg1GlL)WZc;VWqimwokjRu|jlExbx}%E=z~76qs7qMR2xt|uK@b~<}mE}P{j$f@me z_aUc^c-;=Yh!sX5PriAc`jC?s7p)^2qwhKMiCow6q<0=1%ejQaU#p27*qHa1d9odg zfz589jT}H+&%nUAt+XH|u_RS5H!&|WEw#7=D9q5#z`(o^B$u056kh@q)Hl>Oj0fZR v$qQISax{R7^l>OCNv$XWdY6GE97yQmQDh8K)PkYNSl<|E6%Ye$2AKo^l?i7E delta 228 zcmeys^_;Wb*D=VDfq^C4DJsL#&@oaiIC7G%i3tOP*6jucfdIxG3=9nG9^Z9PVDRwt zIB_|{p~}HEAcM_u;$)S$ZLKfPE;}(Tjn#;GVc(=8RX_g>KL<;umh+xVb|`CEE&brN zbdJ}ux0~w4i(D-NCV+h|?zTWf2$3V_;xj$iTq3 pEjO_!z9hA{M1S%J77=59paOjq;gZyf5}@-LSnPm=E{2pb0{}LsNPYkS diff --git a/toolkit/mozapps/update/test/unit/test_0110_general.js b/toolkit/mozapps/update/test/unit/test_0110_general.js index 372bea97050a..fa77b9d1af06 100644 --- a/toolkit/mozapps/update/test/unit/test_0110_general.js +++ b/toolkit/mozapps/update/test/unit/test_0110_general.js @@ -36,15 +36,14 @@ * ***** END LICENSE BLOCK ***** */ -/* General Complete MAR File Patch Apply Tests */ +/* General Complete MAR File Patch Apply Test */ function run_test() { // The directory the updates will be applied to is the current working // directory and not dist/bin. - var testDir = do_get_cwd(); + var testDir = do_get_file("mar_test", true); // The mar files were created with all files in a subdirectory named // mar_test... clear it out of the way if it exists and then create it. - testDir.append("mar_test"); try { if (testDir.exists()) testDir.remove(true); @@ -55,12 +54,12 @@ function run_test() { } dump("Testing: successful removal of the directory used to apply the mar file\n"); do_check_false(testDir.exists()); + testDir = do_get_file("mar_test/1/1_1/", true); testDir.create(AUS_Ci.nsIFile.DIRECTORY_TYPE, PERMS_DIRECTORY); // Create an empty test file to test the complete mar's ability to replace an // existing file. - var testFile = testDir.clone(); - testFile.append("text1"); + var testFile = do_get_file("mar_test/1/1_1/1_1_text1", true); testFile.create(AUS_Ci.nsIFile.NORMAL_FILE_TYPE, PERMS_FILE); var binDir = getGREDir(); @@ -81,9 +80,7 @@ function run_test() { } // Use a directory outside of dist/bin to lessen the garbage in dist/bin - var updatesSubDir = do_get_cwd(); - updatesSubDir.append("0110_complete_mar"); - + var updatesSubDir = do_get_file("0110_complete_mar", true); try { // Mac OS X intermittently fails when removing the dir where the updater // binary was launched. @@ -104,14 +101,24 @@ function run_test() { "a complete mar\n"); do_check_eq(exitValue, 0); + dump("Testing: update.status should be set to STATE_SUCCEEDED\n"); + testFile = updatesSubDir.clone(); + testFile.append("update.status"); + do_check_eq(readFile(testFile).split("\n")[0], STATE_SUCCEEDED); + dump("Testing: contents of files added by a complete mar\n"); - do_check_eq(getFileBytes(getTestFile(testDir, "text1")), "ToBeModified\n"); - do_check_eq(getFileBytes(getTestFile(testDir, "text2")), "ToBeDeleted\n"); + do_check_eq(getFileBytes(do_get_file("mar_test/1/1_1/1_1_text1", true)), + "ToBeModified\n"); + do_check_eq(getFileBytes(do_get_file("mar_test/1/1_1/1_1_text2", true)), + "ToBeDeleted\n"); var refImage = do_get_file("data/aus-0110_general_ref_image.png"); - var srcImage = getTestFile(testDir, "image1.png"); + var srcImage = do_get_file("mar_test/1/1_1/1_1_image1.png", true); do_check_eq(getFileBytes(srcImage), getFileBytes(refImage)); + do_check_eq(getFileBytes(do_get_file("mar_test/2/2_1/2_1_text1", true)), + "ToBeDeleted\n"); + try { // Mac OS X intermittently fails when removing the dir where the updater // binary was launched. @@ -146,25 +153,18 @@ function runUpdate(aUpdatesSubDir, aUpdater) { if (/ /.test(updatesSubDirPath)) updatesSubDirPath = '"' + updatesSubDirPath + '"'; + var cwdPath = do_get_file("/", true).path; + if (/ /.test(cwdPath)) + cwdPath = '"' + cwdPath + '"'; + var process = AUS_Cc["@mozilla.org/process/util;1"]. createInstance(AUS_Ci.nsIProcess); process.init(updateBin); - var args = [updatesSubDirPath]; + var args = [updatesSubDirPath, 0, cwdPath]; process.run(true, args, args.length); return process.exitValue; } -// Gets a file in the mar_test subdirectory of the current working directory -// which is where the mar will be applied. -function getTestFile(aDir, aLeafName) { - var file = aDir.clone(); - file.append(aLeafName); - if (!(file instanceof AUS_Ci.nsILocalFile)) - do_throw("File must be a nsILocalFile for this test! File: " + aLeafName); - - return file; -} - // Returns the binary contents of a file function getFileBytes(aFile) { var fis = AUS_Cc["@mozilla.org/network/file-input-stream;1"]. diff --git a/toolkit/mozapps/update/test/unit/test_0111_general.js b/toolkit/mozapps/update/test/unit/test_0111_general.js index 6639ef5b9132..17dcb54dbacc 100644 --- a/toolkit/mozapps/update/test/unit/test_0111_general.js +++ b/toolkit/mozapps/update/test/unit/test_0111_general.js @@ -36,15 +36,14 @@ * ***** END LICENSE BLOCK ***** */ -/* General Partial MAR File Patch Apply Tests */ +/* General Partial MAR File Patch Apply Test */ function run_test() { // The directory the updates will be applied to is the current working // directory and not dist/bin. - var testDir = do_get_cwd(); + var testDir = do_get_file("mar_test", true); // The mar files were created with all files in a subdirectory named // mar_test... clear it out of the way if it exists and then create it. - testDir.append("mar_test"); try { if (testDir.exists()) testDir.remove(true); @@ -55,20 +54,22 @@ function run_test() { } dump("Testing: successful removal of the directory used to apply the mar file\n"); do_check_false(testDir.exists()); + testDir = do_get_file("mar_test/1/1_1/", true); testDir.create(AUS_Ci.nsIFile.DIRECTORY_TYPE, PERMS_DIRECTORY); // Create the files to test the partial mar's ability to modify and delete // files. - var testFile = testDir.clone(); - testFile.append("text1"); + var testFile = do_get_file("mar_test/1/1_1/1_1_text1", true); writeFile(testFile, "ToBeModified\n"); - testFile = testDir.clone(); - testFile.append("text2"); + testFile = do_get_file("mar_test/1/1_1/1_1_text2", true); writeFile(testFile, "ToBeDeleted\n"); testFile = do_get_file("data/aus-0110_general_ref_image.png"); - testFile.copyTo(testDir, "image1.png"); + testFile.copyTo(testDir, "1_1_image1.png"); + + testFile = do_get_file("mar_test/2/2_1/2_1_text1", true); + writeFile(testFile, "ToBeDeleted\n"); var binDir = getGREDir(); @@ -88,9 +89,7 @@ function run_test() { } // Use a directory outside of dist/bin to lessen the garbage in dist/bin - var updatesSubDir = do_get_cwd(); - updatesSubDir.append("0111_partial_mar"); - + var updatesSubDir = do_get_file("0111_complete_mar", true); try { // Mac OS X intermittently fails when removing the dir where the updater // binary was launched. @@ -111,16 +110,33 @@ function run_test() { "a partial mar\n"); do_check_eq(exitValue, 0); + dump("Testing: update.status should be set to STATE_SUCCEEDED\n"); + testFile = updatesSubDir.clone(); + testFile.append("update.status"); + do_check_eq(readFile(testFile).split("\n")[0], STATE_SUCCEEDED); + dump("Testing: removal of a file and contents of added / modified files by " + "a partial mar\n"); - do_check_eq(getFileBytes(getTestFile(testDir, "text1")), "Modified\n"); - do_check_false(getTestFile(testDir, "text2").exists()); // file removed - do_check_eq(getFileBytes(getTestFile(testDir, "text3")), "Added\n"); + do_check_eq(getFileBytes(do_get_file("mar_test/1/1_1/1_1_text1", true)), + "Modified\n"); + do_check_false(do_get_file("mar_test/1/1_1/1_1_text2", true).exists()); + do_check_eq(getFileBytes(do_get_file("mar_test/1/1_1/1_1_text3", true)), + "Added\n"); var refImage = do_get_file("data/aus-0111_general_ref_image.png"); - var srcImage = getTestFile(testDir, "image1.png"); + var srcImage = do_get_file("mar_test/1/1_1/1_1_image1.png", true); do_check_eq(getFileBytes(srcImage), getFileBytes(refImage)); + dump("Testing: removal of a file by a partial mar\n"); + do_check_false(do_get_file("mar_test/2/2_1/2_1_text1", true).exists()); + + do_check_eq(getFileBytes(do_get_file("mar_test/3/3_1/3_1_text1", true)), + "Added\n"); + + dump("Testing: directory still exists after removal of the last file in " + + "the directory (bug 386760)\n"); + do_check_true(do_get_file("mar_test/2/2_1/", true).exists()); + try { // Mac OS X intermittently fails when removing the dir where the updater // binary was launched. @@ -155,25 +171,18 @@ function runUpdate(aUpdatesSubDir, aUpdater) { if (/ /.test(updatesSubDirPath)) updatesSubDirPath = '"' + updatesSubDirPath + '"'; + var cwdPath = do_get_file("/", true).path; + if (/ /.test(cwdPath)) + cwdPath = '"' + cwdPath + '"'; + var process = AUS_Cc["@mozilla.org/process/util;1"]. createInstance(AUS_Ci.nsIProcess); process.init(updateBin); - var args = [updatesSubDirPath]; + var args = [updatesSubDirPath, 0, cwdPath]; process.run(true, args, args.length); return process.exitValue; } -// Gets a file in the mar_test subdirectory of the current working directory -// which is where the mar will be applied. -function getTestFile(aDir, aLeafName) { - var file = aDir.clone(); - file.append(aLeafName); - if (!(file instanceof AUS_Ci.nsILocalFile)) - do_throw("File must be a nsILocalFile for this test! File: " + aLeafName); - - return file; -} - // Returns the binary contents of a file function getFileBytes(aFile) { var fis = AUS_Cc["@mozilla.org/network/file-input-stream;1"]. diff --git a/toolkit/mozapps/update/test/unit/test_0112_general.js b/toolkit/mozapps/update/test/unit/test_0112_general.js new file mode 100644 index 000000000000..1672ca99aba1 --- /dev/null +++ b/toolkit/mozapps/update/test/unit/test_0112_general.js @@ -0,0 +1,199 @@ +/* ***** 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 the Application Update Service. + * + * The Initial Developer of the Original Code is + * Robert Strong . + * + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Mozilla Foundation . All Rights Reserved. + * + * Contributor(s): + * + * 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 ***** + */ + +/* General Partial MAR File Patch Apply Failure Test */ + +function run_test() { + // The directory the updates will be applied to is the current working + // directory and not dist/bin. + var testDir = do_get_file("mar_test", true); + // The mar files were created with all files in a subdirectory named + // mar_test... clear it out of the way if it exists and then create it. + try { + if (testDir.exists()) + testDir.remove(true); + } + catch (e) { + dump("Unable to remove directory\npath: " + testDir.path + + "\nException: " + e + "\n"); + } + dump("Testing: successful removal of the directory used to apply the mar file\n"); + do_check_false(testDir.exists()); + testDir = do_get_file("mar_test/1/1_1/", true); + testDir.create(AUS_Ci.nsIFile.DIRECTORY_TYPE, PERMS_DIRECTORY); + + // Create the files to test the partial mar's ability to modify and delete + // files. + var testFile = do_get_file("mar_test/1/1_1/1_1_text1", true); + writeFile(testFile, "ShouldNotBeModified\n"); + + testFile = do_get_file("mar_test/1/1_1/1_1_text2", true); + writeFile(testFile, "ShouldNotBeDeleted\n"); + + testFile = do_get_file("data/aus-0111_general_ref_image.png"); + testFile.copyTo(testDir, "1_1_image1.png"); + + testFile = do_get_file("mar_test/2/2_1/2_1_text1", true); + writeFile(testFile, "ShouldNotBeDeleted\n"); + + var binDir = getGREDir(); + + // The updater binary file + var updater = binDir.clone(); + updater.append("updater.app"); + if (!updater.exists()) { + updater = binDir.clone(); + updater.append("updater.exe"); + if (!updater.exists()) { + updater = binDir.clone(); + updater.append("updater"); + if (!updater.exists()) { + do_throw("Unable to find updater binary!"); + } + } + } + + // Use a directory outside of dist/bin to lessen the garbage in dist/bin + var updatesSubDir = do_get_file("0112_complete_mar", true); + try { + // Mac OS X intermittently fails when removing the dir where the updater + // binary was launched. + if (updatesSubDir.exists()) + updatesSubDir.remove(true); + } + catch (e) { + dump("Unable to remove directory\npath: " + updatesSubDir.path + + "\nException: " + e + "\n"); + } + + var mar = do_get_file("data/aus-0111_general.mar"); + mar.copyTo(updatesSubDir, "update.mar"); + + // apply the partial mar and check the innards of the files + var exitValue = runUpdate(updatesSubDir, updater); + dump("Testing: updater binary process exitValue for success when applying " + + "a partial mar\n"); + do_check_eq(exitValue, 0); + + dump("Testing: update.status should be set to STATE_FAILED\n"); + testFile = updatesSubDir.clone(); + testFile.append("update.status"); + // The update status format for a failure is failed: # where # is the error + // code for the failure. + do_check_eq(readFile(testFile).split(": ")[0], STATE_FAILED); + + dump("Testing: files should not be modified or deleted when an update " + + "fails\n"); + do_check_eq(getFileBytes(do_get_file("mar_test/1/1_1/1_1_text1", true)), + "ShouldNotBeModified\n"); + do_check_true(do_get_file("mar_test/1/1_1/1_1_text2", true).exists()); + do_check_eq(getFileBytes(do_get_file("mar_test/1/1_1/1_1_text2", true)), + "ShouldNotBeDeleted\n"); + + var refImage = do_get_file("data/aus-0111_general_ref_image.png"); + var srcImage = do_get_file("mar_test/1/1_1/1_1_image1.png", true); + do_check_eq(getFileBytes(srcImage), getFileBytes(refImage)); + + dump("Testing: removal of a file by a partial mar\n"); + do_check_true(do_get_file("mar_test/2/2_1/2_1_text1", true).exists()); + do_check_eq(getFileBytes(do_get_file("mar_test/1/1_1/1_1_text2", true)), + "ShouldNotBeDeleted\n"); + + do_check_false(do_get_file("mar_test/3/3_1/3_1_text1", true).exists()); + do_check_eq(getFileBytes(do_get_file("mar_test/1/1_1/1_1_text2", true)), + "ShouldNotBeDeleted\n"); + + try { + // Mac OS X intermittently fails when removing the dir where the updater + // binary was launched. + if (updatesSubDir.exists()) + updatesSubDir.remove(true); + } + catch (e) { + dump("Unable to remove directory\npath: " + updatesSubDir.path + + "\nException: " + e + "\n"); + } + + cleanUp(); +} + +// Launches the updater binary to apply a mar file +function runUpdate(aUpdatesSubDir, aUpdater) { + // Copy the updater binary to the update directory so the updater.ini is not + // in the same directory as it is. This prevents ui from displaying and the + // PostUpdate executable which is defined in the updater.ini from launching. + aUpdater.copyTo(aUpdatesSubDir, aUpdater.leafName); + var updateBin = aUpdatesSubDir.clone(); + updateBin.append(aUpdater.leafName); + if (updateBin.leafName == "updater.app") { + updateBin.append("Contents"); + updateBin.append("MacOS"); + updateBin.append("updater"); + if (!updateBin.exists()) + do_throw("Unable to find the updater executable!"); + } + + var updatesSubDirPath = aUpdatesSubDir.path; + if (/ /.test(updatesSubDirPath)) + updatesSubDirPath = '"' + updatesSubDirPath + '"'; + + var cwdPath = do_get_file("/", true).path; + if (/ /.test(cwdPath)) + cwdPath = '"' + cwdPath + '"'; + + var process = AUS_Cc["@mozilla.org/process/util;1"]. + createInstance(AUS_Ci.nsIProcess); + process.init(updateBin); + var args = [updatesSubDirPath, 0, cwdPath]; + process.run(true, args, args.length); + return process.exitValue; +} + +// Returns the binary contents of a file +function getFileBytes(aFile) { + var fis = AUS_Cc["@mozilla.org/network/file-input-stream;1"]. + createInstance(AUS_Ci.nsIFileInputStream); + fis.init(aFile, -1, -1, false); + var bis = AUS_Cc["@mozilla.org/binaryinputstream;1"]. + createInstance(AUS_Ci.nsIBinaryInputStream); + bis.setInputStream(fis); + var data = bis.readBytes(bis.available()); + bis.close(); + fis.close(); + return data; +} From c02a6b6c3ffefb443bfa7eec2b74a3b343e57e9e Mon Sep 17 00:00:00 2001 From: Robert Strong Date: Wed, 29 Jul 2009 23:01:50 -0700 Subject: [PATCH 16/61] Bug 504432 - [WinCE] updater.exe not launched when there is an update during startup. r=vlad --- toolkit/xre/nsUpdateDriver.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/toolkit/xre/nsUpdateDriver.cpp b/toolkit/xre/nsUpdateDriver.cpp index ba6f94ff055d..6d981e3865d8 100644 --- a/toolkit/xre/nsUpdateDriver.cpp +++ b/toolkit/xre/nsUpdateDriver.cpp @@ -125,12 +125,11 @@ GetCurrentWorkingDir(char *buf, size_t size) if (DosQueryPathInfo( ".", FIL_QUERYFULLNAME, buf, size)) return NS_ERROR_FAILURE; #elif defined(XP_WIN) - wchar_t *wpath = _wgetcwd(NULL, size); - if (!wpath) + wchar_t wpath[MAX_PATH]; + if (!_wgetcwd(wpath, size)) return NS_ERROR_FAILURE; NS_ConvertUTF16toUTF8 path(wpath); strncpy(buf, path.get(), size); - free(wpath); #else if(!getcwd(buf, size)) return NS_ERROR_FAILURE; From 1fb19be474f9a0956531391a03e1ed90b44d244f Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Thu, 28 May 2009 11:09:05 -0700 Subject: [PATCH 17/61] Bug 189519 - Implement CSS3 (-moz- for now)background-size. r=dbaron, other useful review comments from roc/bz --- dom/interfaces/css/nsIDOMNSCSS2Properties.idl | 5 +- gfx/public/nsCoord.h | 23 +- layout/base/nsCSSRendering.cpp | 216 ++++++++++++++---- layout/base/nsStyleConsts.h | 5 + .../background-size-auto-auto.html | 20 ++ .../background-size-auto-length-ref.html | 23 ++ .../background-size-auto-length.html | 25 ++ .../background-size-auto-percent.html | 25 ++ .../backgrounds/background-size-auto-ref.html | 24 ++ .../backgrounds/background-size-auto.html | 20 ++ ...ackground-size-body-contain-no-repeat.html | 17 ++ ...ackground-size-body-contain-not-fixed.html | 17 ++ .../background-size-body-contain.html | 16 ++ .../background-size-body-cover-no-repeat.html | 17 ++ .../background-size-body-cover-not-fixed.html | 17 ++ .../background-size-body-cover-ref.html | 14 ++ .../background-size-body-cover.html | 16 ++ ...d-size-body-percent-percent-no-repeat.html | 17 ++ ...d-size-body-percent-percent-not-fixed.html | 16 ++ ...ize-body-percent-percent-overflow-ref.html | 14 ++ ...nd-size-body-percent-percent-overflow.html | 31 +++ ...kground-size-body-percent-percent-ref.html | 14 ++ .../background-size-body-percent-percent.html | 16 ++ ...background-size-body-single-not-fixed.html | 16 ++ .../background-size-bounding-box.html | 36 +++ ...ckground-size-contain-clip-border-ref.html | 29 +++ .../background-size-contain-clip-border.html | 27 +++ ...lip-padding-origin-border-padding-ref.html | 40 ++++ ...in-clip-padding-origin-border-padding.html | 30 +++ ...ontain-clip-padding-origin-border-ref.html | 29 +++ ...ze-contain-clip-padding-origin-border.html | 28 +++ ...kground-size-contain-clip-padding-ref.html | 29 +++ .../background-size-contain-clip-padding.html | 27 +++ ...size-contain-position-fifty-fifty-ref.html | 28 +++ ...und-size-contain-position-fifty-fifty.html | 26 +++ .../background-size-contain-ref.html | 23 ++ .../backgrounds/background-size-contain.html | 25 ++ .../background-size-continuous.html | 36 +++ .../background-size-cover-bounding-box.html | 37 +++ .../background-size-cover-continuous.html | 37 +++ .../background-size-cover-each-box.html | 37 +++ .../background-size-cover-ref.html | 18 ++ .../backgrounds/background-size-cover.html | 20 ++ .../backgrounds/background-size-each-box.html | 36 +++ .../background-size-length-auto.html | 25 ++ .../background-size-length-length-ref.html | 23 ++ .../background-size-length-length.html | 25 ++ .../background-size-length-percent-ref.html | 23 ++ .../background-size-length-percent.html | 25 ++ .../backgrounds/background-size-length.html | 25 ++ ...nd-size-no-intrinsic-height-image-ref.html | 23 ++ ...ground-size-no-intrinsic-height-image.html | 25 ++ ...und-size-no-intrinsic-width-image-ref.html | 23 ++ ...kground-size-no-intrinsic-width-image.html | 25 ++ .../background-size-percent-auto.html | 25 ++ .../background-size-percent-length.html | 25 ++ .../background-size-percent-percent-ref.html | 23 ++ ...ound-size-percent-percent-stretch-ref.html | 39 ++++ ...ckground-size-percent-percent-stretch.html | 33 +++ .../background-size-percent-percent.html | 25 ++ .../backgrounds/background-size-percent.html | 25 ++ .../background-size-zoom-no-repeat-ref.html | 34 +++ .../background-size-zoom-no-repeat.html | 35 +++ .../background-size-zoom-repeat-ref.html | 60 +++++ .../background-size-zoom-repeat.html | 61 +++++ .../green-8x20-blue-8x20-vertical.png | Bin 0 -> 107 bytes .../backgrounds/no-intrinsic-size.svg | 8 + layout/reftests/backgrounds/reftest.list | 69 ++++++ layout/style/nsCSSDeclaration.cpp | 22 +- layout/style/nsCSSKeywordList.h | 2 + layout/style/nsCSSParser.cpp | 123 +++++++++- layout/style/nsCSSPropList.h | 10 + layout/style/nsCSSProps.cpp | 7 + layout/style/nsCSSProps.h | 1 + layout/style/nsCSSStruct.cpp | 2 + layout/style/nsCSSStruct.h | 1 + layout/style/nsComputedDOMStyle.cpp | 79 ++++++- layout/style/nsComputedDOMStyle.h | 1 + layout/style/nsRuleNode.cpp | 98 ++++++++ layout/style/nsStyleStruct.cpp | 45 ++++ layout/style/nsStyleStruct.h | 40 +++- layout/style/test/property_database.js | 12 +- 82 files changed, 2302 insertions(+), 67 deletions(-) create mode 100644 layout/reftests/backgrounds/background-size-auto-auto.html create mode 100644 layout/reftests/backgrounds/background-size-auto-length-ref.html create mode 100644 layout/reftests/backgrounds/background-size-auto-length.html create mode 100644 layout/reftests/backgrounds/background-size-auto-percent.html create mode 100644 layout/reftests/backgrounds/background-size-auto-ref.html create mode 100644 layout/reftests/backgrounds/background-size-auto.html create mode 100644 layout/reftests/backgrounds/background-size-body-contain-no-repeat.html create mode 100644 layout/reftests/backgrounds/background-size-body-contain-not-fixed.html create mode 100644 layout/reftests/backgrounds/background-size-body-contain.html create mode 100644 layout/reftests/backgrounds/background-size-body-cover-no-repeat.html create mode 100644 layout/reftests/backgrounds/background-size-body-cover-not-fixed.html create mode 100644 layout/reftests/backgrounds/background-size-body-cover-ref.html create mode 100644 layout/reftests/backgrounds/background-size-body-cover.html create mode 100644 layout/reftests/backgrounds/background-size-body-percent-percent-no-repeat.html create mode 100644 layout/reftests/backgrounds/background-size-body-percent-percent-not-fixed.html create mode 100644 layout/reftests/backgrounds/background-size-body-percent-percent-overflow-ref.html create mode 100644 layout/reftests/backgrounds/background-size-body-percent-percent-overflow.html create mode 100644 layout/reftests/backgrounds/background-size-body-percent-percent-ref.html create mode 100644 layout/reftests/backgrounds/background-size-body-percent-percent.html create mode 100644 layout/reftests/backgrounds/background-size-body-single-not-fixed.html create mode 100644 layout/reftests/backgrounds/background-size-bounding-box.html create mode 100644 layout/reftests/backgrounds/background-size-contain-clip-border-ref.html create mode 100644 layout/reftests/backgrounds/background-size-contain-clip-border.html create mode 100644 layout/reftests/backgrounds/background-size-contain-clip-padding-origin-border-padding-ref.html create mode 100644 layout/reftests/backgrounds/background-size-contain-clip-padding-origin-border-padding.html create mode 100644 layout/reftests/backgrounds/background-size-contain-clip-padding-origin-border-ref.html create mode 100644 layout/reftests/backgrounds/background-size-contain-clip-padding-origin-border.html create mode 100644 layout/reftests/backgrounds/background-size-contain-clip-padding-ref.html create mode 100644 layout/reftests/backgrounds/background-size-contain-clip-padding.html create mode 100644 layout/reftests/backgrounds/background-size-contain-position-fifty-fifty-ref.html create mode 100644 layout/reftests/backgrounds/background-size-contain-position-fifty-fifty.html create mode 100644 layout/reftests/backgrounds/background-size-contain-ref.html create mode 100644 layout/reftests/backgrounds/background-size-contain.html create mode 100644 layout/reftests/backgrounds/background-size-continuous.html create mode 100644 layout/reftests/backgrounds/background-size-cover-bounding-box.html create mode 100644 layout/reftests/backgrounds/background-size-cover-continuous.html create mode 100644 layout/reftests/backgrounds/background-size-cover-each-box.html create mode 100644 layout/reftests/backgrounds/background-size-cover-ref.html create mode 100644 layout/reftests/backgrounds/background-size-cover.html create mode 100644 layout/reftests/backgrounds/background-size-each-box.html create mode 100644 layout/reftests/backgrounds/background-size-length-auto.html create mode 100644 layout/reftests/backgrounds/background-size-length-length-ref.html create mode 100644 layout/reftests/backgrounds/background-size-length-length.html create mode 100644 layout/reftests/backgrounds/background-size-length-percent-ref.html create mode 100644 layout/reftests/backgrounds/background-size-length-percent.html create mode 100644 layout/reftests/backgrounds/background-size-length.html create mode 100644 layout/reftests/backgrounds/background-size-no-intrinsic-height-image-ref.html create mode 100644 layout/reftests/backgrounds/background-size-no-intrinsic-height-image.html create mode 100644 layout/reftests/backgrounds/background-size-no-intrinsic-width-image-ref.html create mode 100644 layout/reftests/backgrounds/background-size-no-intrinsic-width-image.html create mode 100644 layout/reftests/backgrounds/background-size-percent-auto.html create mode 100644 layout/reftests/backgrounds/background-size-percent-length.html create mode 100644 layout/reftests/backgrounds/background-size-percent-percent-ref.html create mode 100644 layout/reftests/backgrounds/background-size-percent-percent-stretch-ref.html create mode 100644 layout/reftests/backgrounds/background-size-percent-percent-stretch.html create mode 100644 layout/reftests/backgrounds/background-size-percent-percent.html create mode 100644 layout/reftests/backgrounds/background-size-percent.html create mode 100644 layout/reftests/backgrounds/background-size-zoom-no-repeat-ref.html create mode 100644 layout/reftests/backgrounds/background-size-zoom-no-repeat.html create mode 100644 layout/reftests/backgrounds/background-size-zoom-repeat-ref.html create mode 100644 layout/reftests/backgrounds/background-size-zoom-repeat.html create mode 100644 layout/reftests/backgrounds/green-8x20-blue-8x20-vertical.png create mode 100644 layout/reftests/backgrounds/no-intrinsic-size.svg diff --git a/dom/interfaces/css/nsIDOMNSCSS2Properties.idl b/dom/interfaces/css/nsIDOMNSCSS2Properties.idl index f8c5ebb3a41a..c7929428e4e4 100644 --- a/dom/interfaces/css/nsIDOMNSCSS2Properties.idl +++ b/dom/interfaces/css/nsIDOMNSCSS2Properties.idl @@ -39,7 +39,7 @@ #include "nsIDOMCSS2Properties.idl" -[scriptable, uuid(e7245a21-3f46-4e67-82bf-a9b326fe74ee)] +[scriptable, uuid(643f64d3-6b95-4d9a-ac75-c01a6f4c88cb)] interface nsIDOMNSCSS2Properties : nsIDOMCSS2Properties { /* Non-DOM 2 extensions */ @@ -256,5 +256,8 @@ interface nsIDOMNSCSS2Properties : nsIDOMCSS2Properties attribute DOMString MozWindowShadow; // raises(DOMException) on setting + + attribute DOMString MozBackgroundSize; + // raises(DOMException) on setting }; diff --git a/gfx/public/nsCoord.h b/gfx/public/nsCoord.h index eb28a240eb65..baee38e4af86 100644 --- a/gfx/public/nsCoord.h +++ b/gfx/public/nsCoord.h @@ -88,12 +88,29 @@ inline void VERIFY_COORD(nscoord aCoord) { #endif } -inline nscoord NSCoordMultiply(nscoord aCoord, float aVal) { +/** + * Returns aCoord * aVal, capping the product to nscoord_MAX. + * + * Note: If/when we start using floats for nscoords, this function won't be + * necessary. Normal float multiplication correctly handles overflowing + * multiplications, automatically saturating to infinity. + */ +inline nscoord NSCoordSaturatingMultiply(nscoord aCoord, float aVal) { VERIFY_COORD(aCoord); + NS_ABORT_IF_FALSE(aVal >= 0.0f, + "negative scaling factors must be handled manually"); #ifdef NS_COORD_IS_FLOAT - return floorf(aCoord*aVal); + return floorf(aCoord * aVal); #else - return (PRInt32)(aCoord*aVal); + // This one's only a warning because it's possible to trigger + NS_WARN_IF_FALSE(aCoord > 0 + ? floorf(aCoord * aVal) < nscoord_MAX + : ceilf(aCoord * aVal) > nscoord_MIN, + "nscoord multiplication capped"); + + if (aCoord > 0) + return PRInt32(PR_MIN(nscoord_MAX, aCoord * aVal)); + return PRInt32(PR_MAX(nscoord_MIN, aCoord * aVal)); #endif } diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index e6bbc6cc0305..ded69d922116 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -27,6 +27,7 @@ * L. David Baron , Mozilla Corporation * Michael Ventnor * Rob Arnold + * Jeff Walden * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -1395,8 +1396,12 @@ IsSolidBorder(const nsStyleBorder& aBorder) return PR_TRUE; } +/** + * Returns true if the given request is for a background image (that is, it is + * non-null) and that image is fully loaded and its size calculated. + */ static PRBool -UseImageRequestForBackground(imgIRequest *aRequest) +HaveCompleteBackgroundImage(imgIRequest *aRequest) { if (!aRequest) return PR_FALSE; @@ -1496,37 +1501,37 @@ static nscolor DetermineBackgroundColorInternal(nsPresContext* aPresContext, const nsStyleBackground& aBackground, nsIFrame* aFrame, - PRBool* aDrawBackgroundImage, - PRBool* aDrawBackgroundColor, + PRBool& aDrawBackgroundImage, + PRBool& aDrawBackgroundColor, nsCOMPtr& aBottomImage) { - *aDrawBackgroundImage = PR_TRUE; - *aDrawBackgroundColor = PR_TRUE; + aDrawBackgroundImage = PR_TRUE; + aDrawBackgroundColor = PR_TRUE; if (aFrame->HonorPrintBackgroundSettings()) { - *aDrawBackgroundImage = aPresContext->GetBackgroundImageDraw(); - *aDrawBackgroundColor = aPresContext->GetBackgroundColorDraw(); + aDrawBackgroundImage = aPresContext->GetBackgroundImageDraw(); + aDrawBackgroundColor = aPresContext->GetBackgroundColorDraw(); } aBottomImage = aBackground.BottomLayer().mImage; - if (!aDrawBackgroundImage || !UseImageRequestForBackground(aBottomImage)) { + if (!aDrawBackgroundImage || !HaveCompleteBackgroundImage(aBottomImage)) { aBottomImage = nsnull; } nscolor bgColor; - if (*aDrawBackgroundColor) { + if (aDrawBackgroundColor) { bgColor = aBackground.mBackgroundColor; if (NS_GET_A(bgColor) == 0) - *aDrawBackgroundColor = PR_FALSE; + aDrawBackgroundColor = PR_FALSE; } else { // If GetBackgroundColorDraw() is false, we are still expected to // draw color in the background of any frame that's not completely // transparent, but we are expected to use white instead of whatever // color was specified. bgColor = NS_RGB(255, 255, 255); - if (*aDrawBackgroundImage || !aBackground.IsTransparent()) - *aDrawBackgroundColor = PR_TRUE; + if (aDrawBackgroundImage || !aBackground.IsTransparent()) + aDrawBackgroundColor = PR_TRUE; else bgColor = NS_RGBA(0,0,0,0); } @@ -1545,8 +1550,8 @@ nsCSSRendering::DetermineBackgroundColor(nsPresContext* aPresContext, return DetermineBackgroundColorInternal(aPresContext, aBackground, aFrame, - &drawBackgroundImage, - &drawBackgroundColor, + drawBackgroundImage, + drawBackgroundColor, bottomImage); } @@ -1596,8 +1601,8 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext, nscolor bgColor = DetermineBackgroundColorInternal(aPresContext, aBackground, aForFrame, - &drawBackgroundImage, - &drawBackgroundColor, + drawBackgroundImage, + drawBackgroundColor, bottomImage); // At this point, drawBackgroundImage and drawBackgroundColor are @@ -1628,7 +1633,7 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext, // determined by the value of 'background-clip' in // SetupCurrentBackgroundClip. (Arguably it should be the // intersection, but that breaks the table painter -- in particular, - // taking the intersection breaks reftests/bugs/403429-1[ab].) + // taking the intersection breaks reftests/bugs/403249-1[ab].) nsRect bgClipArea, dirtyRect; gfxRect dirtyRectGfx; PRUint8 currentBackgroundClip; @@ -1722,6 +1727,25 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext, } } +static inline float +ScaleDimension(nsStyleBackground::Size::Dimension aDimension, + PRUint8 aType, + nscoord aLength, nscoord aAvailLength) +{ + switch (aType) { + case nsStyleBackground::Size::ePercentage: + return double(aDimension.mFloat) * (double(aAvailLength) / double(aLength)); + case nsStyleBackground::Size::eLength: + return double(aDimension.mCoord) / double(aLength); + default: + NS_ABORT_IF_FALSE(PR_FALSE, "bad aDimension.mType"); + return 1.0f; + case nsStyleBackground::Size::eAuto: + NS_ABORT_IF_FALSE(PR_FALSE, "aDimension.mType == eAuto isn't handled"); + return 1.0f; + } +} + static void PaintBackgroundLayer(nsPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -1732,15 +1756,69 @@ PaintBackgroundLayer(nsPresContext* aPresContext, const nsStyleBackground& aBackground, const nsStyleBackground::Layer& aLayer) { + /* + * The background properties we need to keep in mind when drawing background + * layers are: + * + * background-image + * background-repeat + * background-attachment + * background-position + * background-clip (-moz-background-clip) + * background-origin (-moz-background-origin) + * background-size (-moz-background-size) + * background-break (-moz-background-inline-policy) + * + * (background-color applies to the entire element and not to individual + * layers, so it is irrelevant to this method.) + * + * These properties have the following dependencies upon each other when + * determining rendering: + * + * background-image + * no dependencies + * background-repeat + * no dependencies + * background-attachment + * no dependencies + * background-position + * depends upon background-size (for the image's scaled size) and + * background-break (for the background positioning area) + * background-clip + * no dependencies + * background-origin + * depends upon background-attachment (only in the case where that value + * is 'fixed') + * background-size + * depends upon background-break (for the background positioning area for + * resolving percentages), background-image (for the image's intrinsic + * size), background-repeat (if that value is 'round'), and + * background-origin (for the background painting area, when + * background-repeat is 'round') + * background-break + * depends upon background-origin (specifying how the boxes making up the + * background positioning area are determined) + * + * As a result of only-if dependencies we don't strictly do a topological + * sort of the above properties when processing, but it's pretty close to one: + * + * background-clip (by caller) + * background-image + * background-break, background-origin + * background-attachment (postfix for background-{origin,break} if 'fixed') + * background-size + * background-position + * background-repeat + */ + // Lookup the image imgIRequest *req = aLayer.mImage; - if (!UseImageRequestForBackground(req)) { - // There's no image or it's not ready to be painted. + if (!HaveCompleteBackgroundImage(req)) return; - } nsCOMPtr image; req->GetImage(getter_AddRefs(image)); + req = nsnull; nsIntSize imageIntSize; image->GetWidth(&imageIntSize.width); @@ -1750,27 +1828,33 @@ PaintBackgroundLayer(nsPresContext* aPresContext, imageSize.width = nsPresContext::CSSPixelsToAppUnits(imageIntSize.width); imageSize.height = nsPresContext::CSSPixelsToAppUnits(imageIntSize.height); - req = nsnull; + if (imageSize.width == 0 || imageSize.height == 0) + return; // relative to aBorderArea - nsRect bgOriginRect(0, 0, 0, 0); + nsRect bgPositioningArea(0, 0, 0, 0); nsIAtom* frameType = aForFrame->GetType(); nsIFrame* geometryFrame = aForFrame; if (frameType == nsGkAtoms::inlineFrame || frameType == nsGkAtoms::positionedInlineFrame) { + // XXXjwalden Strictly speaking this is not quite faithful to how + // background-break is supposed to interact with background-origin values, + // but it's a non-trivial amount of work to make it fully conformant, and + // until the specification is more finalized (and assuming background-break + // even makes the cut) it doesn't make sense to hammer out exact behavior. switch (aBackground.mBackgroundInlinePolicy) { case NS_STYLE_BG_INLINE_POLICY_EACH_BOX: - bgOriginRect = nsRect(nsPoint(0,0), aBorderArea.Size()); + bgPositioningArea = nsRect(nsPoint(0,0), aBorderArea.Size()); break; case NS_STYLE_BG_INLINE_POLICY_BOUNDING_BOX: - bgOriginRect = gInlineBGData->GetBoundingRect(aForFrame); + bgPositioningArea = gInlineBGData->GetBoundingRect(aForFrame); break; default: NS_ERROR("Unknown background-inline-policy value! " "Please, teach me what to do."); case NS_STYLE_BG_INLINE_POLICY_CONTINUOUS: - bgOriginRect = gInlineBGData->GetContinuousRect(aForFrame); + bgPositioningArea = gInlineBGData->GetContinuousRect(aForFrame); break; } } else if (frameType == nsGkAtoms::canvasFrame) { @@ -1780,10 +1864,10 @@ PaintBackgroundLayer(nsPresContext* aPresContext, // finished and this page only displays the continuations of // absolutely positioned content). if (geometryFrame) { - bgOriginRect = geometryFrame->GetRect(); + bgPositioningArea = geometryFrame->GetRect(); } } else { - bgOriginRect = nsRect(nsPoint(0,0), aBorderArea.Size()); + bgPositioningArea = nsRect(nsPoint(0,0), aBorderArea.Size()); } // Background images are tiled over the 'background-clip' area @@ -1791,11 +1875,11 @@ PaintBackgroundLayer(nsPresContext* aPresContext, if (aLayer.mOrigin != NS_STYLE_BG_ORIGIN_BORDER && geometryFrame) { nsMargin border = geometryFrame->GetUsedBorder(); geometryFrame->ApplySkipSides(border); - bgOriginRect.Deflate(border); + bgPositioningArea.Deflate(border); if (aLayer.mOrigin != NS_STYLE_BG_ORIGIN_PADDING) { nsMargin padding = geometryFrame->GetUsedPadding(); geometryFrame->ApplySkipSides(padding); - bgOriginRect.Deflate(padding); + bgPositioningArea.Deflate(padding); NS_ASSERTION(aLayer.mOrigin == NS_STYLE_BG_ORIGIN_CONTENT, "unknown background-origin value"); } @@ -1805,7 +1889,7 @@ PaintBackgroundLayer(nsPresContext* aPresContext, // // relative to aBorderArea.TopLeft() (which is where the top-left // of aForFrame's border-box will be rendered) - nsPoint imageTopLeft, anchor; + nsPoint imageTopLeft, anchor, offset; if (NS_STYLE_BG_ATTACHMENT_FIXED == aLayer.mAttachment) { // If it's a fixed background attachment, then the image is placed // relative to the viewport, which is the area of the root frame @@ -1827,7 +1911,8 @@ PaintBackgroundLayer(nsPresContext* aPresContext, // else this is an embedded shell and its root frame is what we want } - nsRect viewportArea(nsPoint(0, 0), topFrame->GetSize()); + // Set the background positioning area to the viewport's area. + bgPositioningArea.SetRect(nsPoint(0, 0), topFrame->GetSize()); if (!pageContentFrame) { // Subtract the size of scrollbars. @@ -1835,29 +1920,70 @@ PaintBackgroundLayer(nsPresContext* aPresContext, aPresContext->PresShell()->GetRootScrollFrameAsScrollable(); if (scrollableFrame) { nsMargin scrollbars = scrollableFrame->GetActualScrollbarSizes(); - viewportArea.Deflate(scrollbars); + bgPositioningArea.Deflate(scrollbars); } } - - // Get the anchor point, relative to the viewport. - ComputeBackgroundAnchorPoint(aLayer, viewportArea.Size(), imageSize, - &imageTopLeft, &anchor); - // Convert the anchor point from viewport coordinates to aForFrame - // coordinates. - nsPoint offset = viewportArea.TopLeft() - aForFrame->GetOffsetTo(topFrame); - imageTopLeft += offset; - anchor += offset; + offset = bgPositioningArea.TopLeft() - aForFrame->GetOffsetTo(topFrame); } else { - ComputeBackgroundAnchorPoint(aLayer, bgOriginRect.Size(), imageSize, - &imageTopLeft, &anchor); - imageTopLeft += bgOriginRect.TopLeft(); - anchor += bgOriginRect.TopLeft(); + offset = bgPositioningArea.TopLeft(); } + + // Scale the image as specified for background-size and as required for + // proper background positioning when background-position is defined with + // percentages. + float scaleX, scaleY; + switch (aLayer.mSize.mWidthType) { + case nsStyleBackground::Size::eContain: + case nsStyleBackground::Size::eCover: { + float scaleFitX = double(bgPositioningArea.width) / imageSize.width; + float scaleFitY = double(bgPositioningArea.height) / imageSize.height; + if (aLayer.mSize.mWidthType == nsStyleBackground::Size::eCover) { + scaleX = scaleY = PR_MAX(scaleFitX, scaleFitY); + } else { + scaleX = scaleY = PR_MIN(scaleFitX, scaleFitY); + } + break; + } + default: { + if (aLayer.mSize.mWidthType == nsStyleBackground::Size::eAuto) { + if (aLayer.mSize.mHeightType == nsStyleBackground::Size::eAuto) { + scaleX = scaleY = 1.0f; + } else { + scaleX = scaleY = + ScaleDimension(aLayer.mSize.mHeight, aLayer.mSize.mHeightType, + imageSize.height, bgPositioningArea.height); + } + } else { + if (aLayer.mSize.mHeightType == nsStyleBackground::Size::eAuto) { + scaleX = scaleY = + ScaleDimension(aLayer.mSize.mWidth, aLayer.mSize.mWidthType, + imageSize.width, bgPositioningArea.width); + } else { + scaleX = ScaleDimension(aLayer.mSize.mWidth, aLayer.mSize.mWidthType, + imageSize.width, bgPositioningArea.width); + scaleY = ScaleDimension(aLayer.mSize.mHeight, aLayer.mSize.mHeightType, + imageSize.height, bgPositioningArea.height); + } + } + break; + } + } + imageSize.width = NSCoordSaturatingMultiply(imageSize.width, scaleX); + imageSize.height = NSCoordSaturatingMultiply(imageSize.height, scaleY); + + // Compute the position of the background now that the background's size is + // determined. + ComputeBackgroundAnchorPoint(aLayer, bgPositioningArea.Size(), imageSize, + &imageTopLeft, &anchor); + imageTopLeft += offset; + anchor += offset; nsRect destArea(imageTopLeft + aBorderArea.TopLeft(), imageSize); nsRect fillArea = destArea; PRIntn repeat = aLayer.mRepeat; + PR_STATIC_ASSERT(NS_STYLE_BG_REPEAT_XY == + (NS_STYLE_BG_REPEAT_X | NS_STYLE_BG_REPEAT_Y)); if (repeat & NS_STYLE_BG_REPEAT_X) { fillArea.x = aBGClipRect.x; fillArea.width = aBGClipRect.width; diff --git a/layout/base/nsStyleConsts.h b/layout/base/nsStyleConsts.h index 6926a24b01ae..ee1f3a73e05a 100644 --- a/layout/base/nsStyleConsts.h +++ b/layout/base/nsStyleConsts.h @@ -269,11 +269,16 @@ #define NS_STYLE_BG_POSITION_RIGHT (1<<4) // See nsStyleBackground +// Code depends on (BG_REPEAT_X | BG_REPEAT_Y) == BG_REPEAT_XY #define NS_STYLE_BG_REPEAT_OFF 0x00 #define NS_STYLE_BG_REPEAT_X 0x01 #define NS_STYLE_BG_REPEAT_Y 0x02 #define NS_STYLE_BG_REPEAT_XY 0x03 +// See nsStyleBackground +#define NS_STYLE_BG_SIZE_CONTAIN 0 +#define NS_STYLE_BG_SIZE_COVER 1 + // See nsStyleTable #define NS_STYLE_BORDER_COLLAPSE 0 #define NS_STYLE_BORDER_SEPARATE 1 diff --git a/layout/reftests/backgrounds/background-size-auto-auto.html b/layout/reftests/backgrounds/background-size-auto-auto.html new file mode 100644 index 000000000000..22108f013d32 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-auto-auto.html @@ -0,0 +1,20 @@ + + + + background-size: auto auto; + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-auto-length-ref.html b/layout/reftests/backgrounds/background-size-auto-length-ref.html new file mode 100644 index 000000000000..ae7535a84bf5 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-auto-length-ref.html @@ -0,0 +1,23 @@ + + + + background-size: auto 16px; reference + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-auto-length.html b/layout/reftests/backgrounds/background-size-auto-length.html new file mode 100644 index 000000000000..5d54b5c75795 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-auto-length.html @@ -0,0 +1,25 @@ + + + + background-size: auto 16px; + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-auto-percent.html b/layout/reftests/backgrounds/background-size-auto-percent.html new file mode 100644 index 000000000000..b1bed853eeca --- /dev/null +++ b/layout/reftests/backgrounds/background-size-auto-percent.html @@ -0,0 +1,25 @@ + + + + background-size: auto 12.5%; + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-auto-ref.html b/layout/reftests/backgrounds/background-size-auto-ref.html new file mode 100644 index 000000000000..8b2bd45d518a --- /dev/null +++ b/layout/reftests/backgrounds/background-size-auto-ref.html @@ -0,0 +1,24 @@ + + + + background-size: auto; reference + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-auto.html b/layout/reftests/backgrounds/background-size-auto.html new file mode 100644 index 000000000000..14a4bc9575af --- /dev/null +++ b/layout/reftests/backgrounds/background-size-auto.html @@ -0,0 +1,20 @@ + + + + background-size: auto; + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-body-contain-no-repeat.html b/layout/reftests/backgrounds/background-size-body-contain-no-repeat.html new file mode 100644 index 000000000000..1afe70ea039d --- /dev/null +++ b/layout/reftests/backgrounds/background-size-body-contain-no-repeat.html @@ -0,0 +1,17 @@ + + + + background-size: contain; on body, no-repeat, fixed + + + + + diff --git a/layout/reftests/backgrounds/background-size-body-contain-not-fixed.html b/layout/reftests/backgrounds/background-size-body-contain-not-fixed.html new file mode 100644 index 000000000000..371e08be1dfa --- /dev/null +++ b/layout/reftests/backgrounds/background-size-body-contain-not-fixed.html @@ -0,0 +1,17 @@ + + + + background-size: contain; not fixed, no-repeat on body + + + + + diff --git a/layout/reftests/backgrounds/background-size-body-contain.html b/layout/reftests/backgrounds/background-size-body-contain.html new file mode 100644 index 000000000000..851a582f981f --- /dev/null +++ b/layout/reftests/backgrounds/background-size-body-contain.html @@ -0,0 +1,16 @@ + + + + background-size: contain; fixed, repeat on body + + + + + diff --git a/layout/reftests/backgrounds/background-size-body-cover-no-repeat.html b/layout/reftests/backgrounds/background-size-body-cover-no-repeat.html new file mode 100644 index 000000000000..b758d7a2f4dc --- /dev/null +++ b/layout/reftests/backgrounds/background-size-body-cover-no-repeat.html @@ -0,0 +1,17 @@ + + + + background-size: cover; on body, no-repeat, fixed + + + + + diff --git a/layout/reftests/backgrounds/background-size-body-cover-not-fixed.html b/layout/reftests/backgrounds/background-size-body-cover-not-fixed.html new file mode 100644 index 000000000000..16e79583f31c --- /dev/null +++ b/layout/reftests/backgrounds/background-size-body-cover-not-fixed.html @@ -0,0 +1,17 @@ + + + + background-size: cover; no-repeat, not-fixed on body + + + + + diff --git a/layout/reftests/backgrounds/background-size-body-cover-ref.html b/layout/reftests/backgrounds/background-size-body-cover-ref.html new file mode 100644 index 000000000000..3dfe4ea6b7d0 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-body-cover-ref.html @@ -0,0 +1,14 @@ + + + + background-size: cover; on body reference + + + + + diff --git a/layout/reftests/backgrounds/background-size-body-cover.html b/layout/reftests/backgrounds/background-size-body-cover.html new file mode 100644 index 000000000000..09b4a83376c0 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-body-cover.html @@ -0,0 +1,16 @@ + + + + background-size: cover; on body + + + + + diff --git a/layout/reftests/backgrounds/background-size-body-percent-percent-no-repeat.html b/layout/reftests/backgrounds/background-size-body-percent-percent-no-repeat.html new file mode 100644 index 000000000000..aba071be3246 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-body-percent-percent-no-repeat.html @@ -0,0 +1,17 @@ + + + + background-size: 100% 100%; no-repeat/fixed on body + + + + + diff --git a/layout/reftests/backgrounds/background-size-body-percent-percent-not-fixed.html b/layout/reftests/backgrounds/background-size-body-percent-percent-not-fixed.html new file mode 100644 index 000000000000..1d1153177387 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-body-percent-percent-not-fixed.html @@ -0,0 +1,16 @@ + + + + background-size: 100% 100%; no-repeat/not fixed on body + + + + + diff --git a/layout/reftests/backgrounds/background-size-body-percent-percent-overflow-ref.html b/layout/reftests/backgrounds/background-size-body-percent-percent-overflow-ref.html new file mode 100644 index 000000000000..c9bfd99819af --- /dev/null +++ b/layout/reftests/backgrounds/background-size-body-percent-percent-overflow-ref.html @@ -0,0 +1,14 @@ + + + + background-size: 100% 100%; on body + + + + + diff --git a/layout/reftests/backgrounds/background-size-body-percent-percent-overflow.html b/layout/reftests/backgrounds/background-size-body-percent-percent-overflow.html new file mode 100644 index 000000000000..46085a906032 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-body-percent-percent-overflow.html @@ -0,0 +1,31 @@ + + + + background-size: 100% 100%; on body + + + + + diff --git a/layout/reftests/backgrounds/background-size-body-percent-percent-ref.html b/layout/reftests/backgrounds/background-size-body-percent-percent-ref.html new file mode 100644 index 000000000000..3f03f74afaa9 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-body-percent-percent-ref.html @@ -0,0 +1,14 @@ + + + + background-size: 100% 100%; on body reference + + + + + diff --git a/layout/reftests/backgrounds/background-size-body-percent-percent.html b/layout/reftests/backgrounds/background-size-body-percent-percent.html new file mode 100644 index 000000000000..e5722bd7ba59 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-body-percent-percent.html @@ -0,0 +1,16 @@ + + + + background-size: 100% 100%; on body + + + + + diff --git a/layout/reftests/backgrounds/background-size-body-single-not-fixed.html b/layout/reftests/backgrounds/background-size-body-single-not-fixed.html new file mode 100644 index 000000000000..e901abad6217 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-body-single-not-fixed.html @@ -0,0 +1,16 @@ + + + + background-size: contain; on body + + + + + diff --git a/layout/reftests/backgrounds/background-size-bounding-box.html b/layout/reftests/backgrounds/background-size-bounding-box.html new file mode 100644 index 000000000000..6136a3729cf9 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-bounding-box.html @@ -0,0 +1,36 @@ + + + + background-break: bounding-box + + + +
+ + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-contain-clip-border-ref.html b/layout/reftests/backgrounds/background-size-contain-clip-border-ref.html new file mode 100644 index 000000000000..a061b39dd058 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-contain-clip-border-ref.html @@ -0,0 +1,29 @@ + + + + background-size: contain; -moz-background-clip: border reference + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-contain-clip-border.html b/layout/reftests/backgrounds/background-size-contain-clip-border.html new file mode 100644 index 000000000000..76b209a17361 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-contain-clip-border.html @@ -0,0 +1,27 @@ + + + + background-size: contain; -moz-background-clip: border + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-contain-clip-padding-origin-border-padding-ref.html b/layout/reftests/backgrounds/background-size-contain-clip-padding-origin-border-padding-ref.html new file mode 100644 index 000000000000..f3bb19eb168c --- /dev/null +++ b/layout/reftests/backgrounds/background-size-contain-clip-padding-origin-border-padding-ref.html @@ -0,0 +1,40 @@ + + + + background-size: contain; -moz-background-clip: padding reference, -moz-background-origin: border + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-contain-clip-padding-origin-border-padding.html b/layout/reftests/backgrounds/background-size-contain-clip-padding-origin-border-padding.html new file mode 100644 index 000000000000..12cdbc5a95d1 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-contain-clip-padding-origin-border-padding.html @@ -0,0 +1,30 @@ + + + + background-size: contain; -moz-background-clip: padding, -moz-background-origin: border + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-contain-clip-padding-origin-border-ref.html b/layout/reftests/backgrounds/background-size-contain-clip-padding-origin-border-ref.html new file mode 100644 index 000000000000..7a3b9f7beb21 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-contain-clip-padding-origin-border-ref.html @@ -0,0 +1,29 @@ + + + + background-size: contain; -moz-background-clip: padding reference, -moz-background-origin: border + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-contain-clip-padding-origin-border.html b/layout/reftests/backgrounds/background-size-contain-clip-padding-origin-border.html new file mode 100644 index 000000000000..ab36021fb871 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-contain-clip-padding-origin-border.html @@ -0,0 +1,28 @@ + + + + background-size: contain; -moz-background-clip: padding, -moz-background-origin: border + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-contain-clip-padding-ref.html b/layout/reftests/backgrounds/background-size-contain-clip-padding-ref.html new file mode 100644 index 000000000000..3e2af30b9039 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-contain-clip-padding-ref.html @@ -0,0 +1,29 @@ + + + + background-size: contain; -moz-background-clip: padding reference + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-contain-clip-padding.html b/layout/reftests/backgrounds/background-size-contain-clip-padding.html new file mode 100644 index 000000000000..36408f785c74 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-contain-clip-padding.html @@ -0,0 +1,27 @@ + + + + background-size: contain; -moz-background-clip: padding + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-contain-position-fifty-fifty-ref.html b/layout/reftests/backgrounds/background-size-contain-position-fifty-fifty-ref.html new file mode 100644 index 000000000000..811f4c047cdc --- /dev/null +++ b/layout/reftests/backgrounds/background-size-contain-position-fifty-fifty-ref.html @@ -0,0 +1,28 @@ + + + + background-size: contain; background-position: 50% 50% reference + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-contain-position-fifty-fifty.html b/layout/reftests/backgrounds/background-size-contain-position-fifty-fifty.html new file mode 100644 index 000000000000..7e3dab555e84 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-contain-position-fifty-fifty.html @@ -0,0 +1,26 @@ + + + + background-size: contain; background-position: 50% 50% + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-contain-ref.html b/layout/reftests/backgrounds/background-size-contain-ref.html new file mode 100644 index 000000000000..53c346cc74fc --- /dev/null +++ b/layout/reftests/backgrounds/background-size-contain-ref.html @@ -0,0 +1,23 @@ + + + + background-size: contain; reference + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-contain.html b/layout/reftests/backgrounds/background-size-contain.html new file mode 100644 index 000000000000..654a94c122ce --- /dev/null +++ b/layout/reftests/backgrounds/background-size-contain.html @@ -0,0 +1,25 @@ + + + + background-size: contain; + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-continuous.html b/layout/reftests/backgrounds/background-size-continuous.html new file mode 100644 index 000000000000..4373cdcd238a --- /dev/null +++ b/layout/reftests/backgrounds/background-size-continuous.html @@ -0,0 +1,36 @@ + + + + background-break: continuous + + + +
+ + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-cover-bounding-box.html b/layout/reftests/backgrounds/background-size-cover-bounding-box.html new file mode 100644 index 000000000000..ca12800e0ab7 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-cover-bounding-box.html @@ -0,0 +1,37 @@ + + + + background-size: cover; background-break: bounding-box + + + +
+ + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-cover-continuous.html b/layout/reftests/backgrounds/background-size-cover-continuous.html new file mode 100644 index 000000000000..3f81d372b4b8 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-cover-continuous.html @@ -0,0 +1,37 @@ + + + + background-size: cover; background-break: continuous + + + +
+ + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-cover-each-box.html b/layout/reftests/backgrounds/background-size-cover-each-box.html new file mode 100644 index 000000000000..a53333fc6449 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-cover-each-box.html @@ -0,0 +1,37 @@ + + + + background-size: cover; background-break: each-box + + + +
+ + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-cover-ref.html b/layout/reftests/backgrounds/background-size-cover-ref.html new file mode 100644 index 000000000000..7d74f7b3c247 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-cover-ref.html @@ -0,0 +1,18 @@ + + + + background-size: cover; reference + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-cover.html b/layout/reftests/backgrounds/background-size-cover.html new file mode 100644 index 000000000000..20e23eb24241 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-cover.html @@ -0,0 +1,20 @@ + + + + background-size: cover; + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-each-box.html b/layout/reftests/backgrounds/background-size-each-box.html new file mode 100644 index 000000000000..35c1a205a77c --- /dev/null +++ b/layout/reftests/backgrounds/background-size-each-box.html @@ -0,0 +1,36 @@ + + + + background-break: each-box + + + +
+ + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-length-auto.html b/layout/reftests/backgrounds/background-size-length-auto.html new file mode 100644 index 000000000000..9ef400915dd3 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-length-auto.html @@ -0,0 +1,25 @@ + + + + background-size: 16px auto; + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-length-length-ref.html b/layout/reftests/backgrounds/background-size-length-length-ref.html new file mode 100644 index 000000000000..05b5c6758791 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-length-length-ref.html @@ -0,0 +1,23 @@ + + + + background-size: 32px 64px; reference + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-length-length.html b/layout/reftests/backgrounds/background-size-length-length.html new file mode 100644 index 000000000000..dca9c8bd834a --- /dev/null +++ b/layout/reftests/backgrounds/background-size-length-length.html @@ -0,0 +1,25 @@ + + + + background-size: 32px 64px; + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-length-percent-ref.html b/layout/reftests/backgrounds/background-size-length-percent-ref.html new file mode 100644 index 000000000000..9c95873190e2 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-length-percent-ref.html @@ -0,0 +1,23 @@ + + + + background-size: 16px 25%; + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-length-percent.html b/layout/reftests/backgrounds/background-size-length-percent.html new file mode 100644 index 000000000000..ae630d53f531 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-length-percent.html @@ -0,0 +1,25 @@ + + + + background-size: 16px 25%; + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-length.html b/layout/reftests/backgrounds/background-size-length.html new file mode 100644 index 000000000000..362c601541dc --- /dev/null +++ b/layout/reftests/backgrounds/background-size-length.html @@ -0,0 +1,25 @@ + + + + background-size: 16px; + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-no-intrinsic-height-image-ref.html b/layout/reftests/backgrounds/background-size-no-intrinsic-height-image-ref.html new file mode 100644 index 000000000000..c453fed751d1 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-no-intrinsic-height-image-ref.html @@ -0,0 +1,23 @@ + + + + background-size: 32px auto; for image with no intrinsic height reference + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-no-intrinsic-height-image.html b/layout/reftests/backgrounds/background-size-no-intrinsic-height-image.html new file mode 100644 index 000000000000..7b01c98465ab --- /dev/null +++ b/layout/reftests/backgrounds/background-size-no-intrinsic-height-image.html @@ -0,0 +1,25 @@ + + + + background-size: 32px auto; for image with no intrinsic height + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-no-intrinsic-width-image-ref.html b/layout/reftests/backgrounds/background-size-no-intrinsic-width-image-ref.html new file mode 100644 index 000000000000..a01539de7411 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-no-intrinsic-width-image-ref.html @@ -0,0 +1,23 @@ + + + + background-size: 32px auto; for image with no intrinsic size reference + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-no-intrinsic-width-image.html b/layout/reftests/backgrounds/background-size-no-intrinsic-width-image.html new file mode 100644 index 000000000000..501085f45287 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-no-intrinsic-width-image.html @@ -0,0 +1,25 @@ + + + + background-size: auto 32px; for image with no intrinsic width + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-percent-auto.html b/layout/reftests/backgrounds/background-size-percent-auto.html new file mode 100644 index 000000000000..266619549b1d --- /dev/null +++ b/layout/reftests/backgrounds/background-size-percent-auto.html @@ -0,0 +1,25 @@ + + + + background-size: 25% auto; + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-percent-length.html b/layout/reftests/backgrounds/background-size-percent-length.html new file mode 100644 index 000000000000..695a7a506c22 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-percent-length.html @@ -0,0 +1,25 @@ + + + + background-size: 25% 32px; + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-percent-percent-ref.html b/layout/reftests/backgrounds/background-size-percent-percent-ref.html new file mode 100644 index 000000000000..a30b75c6b03e --- /dev/null +++ b/layout/reftests/backgrounds/background-size-percent-percent-ref.html @@ -0,0 +1,23 @@ + + + + background-size: 50% 25%; reference + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-percent-percent-stretch-ref.html b/layout/reftests/backgrounds/background-size-percent-percent-stretch-ref.html new file mode 100644 index 000000000000..65c999d6d990 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-percent-percent-stretch-ref.html @@ -0,0 +1,39 @@ + + + + background-size: 100% 100%; stretch reference + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-percent-percent-stretch.html b/layout/reftests/backgrounds/background-size-percent-percent-stretch.html new file mode 100644 index 000000000000..baf3e8e6c40a --- /dev/null +++ b/layout/reftests/backgrounds/background-size-percent-percent-stretch.html @@ -0,0 +1,33 @@ + + + + background-size: 100% 100%; stretch + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-percent-percent.html b/layout/reftests/backgrounds/background-size-percent-percent.html new file mode 100644 index 000000000000..64ce972c531e --- /dev/null +++ b/layout/reftests/backgrounds/background-size-percent-percent.html @@ -0,0 +1,25 @@ + + + + background-size: 50% 25%; + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-percent.html b/layout/reftests/backgrounds/background-size-percent.html new file mode 100644 index 000000000000..76f26c2b8398 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-percent.html @@ -0,0 +1,25 @@ + + + + background-size: 25%; + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-zoom-no-repeat-ref.html b/layout/reftests/backgrounds/background-size-zoom-no-repeat-ref.html new file mode 100644 index 000000000000..dd05ee386aff --- /dev/null +++ b/layout/reftests/backgrounds/background-size-zoom-no-repeat-ref.html @@ -0,0 +1,34 @@ + + + + background-size + zoom + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-zoom-no-repeat.html b/layout/reftests/backgrounds/background-size-zoom-no-repeat.html new file mode 100644 index 000000000000..f89ff92dda4e --- /dev/null +++ b/layout/reftests/backgrounds/background-size-zoom-no-repeat.html @@ -0,0 +1,35 @@ + + + + background-size + zoom + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-zoom-repeat-ref.html b/layout/reftests/backgrounds/background-size-zoom-repeat-ref.html new file mode 100644 index 000000000000..1a5a1fd0af39 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-zoom-repeat-ref.html @@ -0,0 +1,60 @@ + + + + background-size: 64px 40px; repeat, zoom reference + + + +
+ + diff --git a/layout/reftests/backgrounds/background-size-zoom-repeat.html b/layout/reftests/backgrounds/background-size-zoom-repeat.html new file mode 100644 index 000000000000..26581e57aff7 --- /dev/null +++ b/layout/reftests/backgrounds/background-size-zoom-repeat.html @@ -0,0 +1,61 @@ + + + + background-size: 64px 40px; repeat, zoom + + + +
+ + diff --git a/layout/reftests/backgrounds/green-8x20-blue-8x20-vertical.png b/layout/reftests/backgrounds/green-8x20-blue-8x20-vertical.png new file mode 100644 index 0000000000000000000000000000000000000000..4236f5b1cebc8c9d6d22545135cf35425bfed836 GIT binary patch literal 107 zcmeAS@N?(olHy`uVBq!ia0vp^B0wy_!3HG7B;uuk6k~CayA#8@b22Z1992&j#}JFt z$yaKXf6j00YUpe{m2l<2!~})K4F`T-EV0OX;2_PxFljSOTti0iRG + + Image with no intrinsic size + + diff --git a/layout/reftests/backgrounds/reftest.list b/layout/reftests/backgrounds/reftest.list index eada98ee65c7..c037d0a0803a 100644 --- a/layout/reftests/backgrounds/reftest.list +++ b/layout/reftests/backgrounds/reftest.list @@ -24,3 +24,72 @@ == continuous-inline-4b.html continuous-inline-4-ref.html == continuous-inline-5a.html continuous-inline-5-ref.html == continuous-inline-5b.html continuous-inline-5-ref.html + +== background-size-auto-auto.html background-size-auto-ref.html +== background-size-auto.html background-size-auto-ref.html +== background-size-contain.html background-size-contain-ref.html +== background-size-cover.html background-size-cover-ref.html +== background-size-auto-length.html background-size-auto-length-ref.html +== background-size-length-auto.html background-size-auto-length-ref.html +== background-size-length.html background-size-auto-length-ref.html +== background-size-auto-percent.html background-size-auto-length-ref.html +== background-size-percent-auto.html background-size-auto-length-ref.html +== background-size-percent.html background-size-auto-length-ref.html +== background-size-length-percent.html background-size-length-percent-ref.html +== background-size-percent-length.html background-size-length-percent-ref.html +== background-size-percent-percent.html background-size-percent-percent-ref.html +== background-size-length-length.html background-size-length-length-ref.html +== background-size-percent-percent-stretch.html background-size-percent-percent-stretch-ref.html + +== background-size-body-percent-percent.html background-size-body-percent-percent-ref.html +== background-size-body-percent-percent-no-repeat.html background-size-body-percent-percent-ref.html +== background-size-body-percent-percent-not-fixed.html background-size-body-percent-percent-ref.html +== background-size-body-cover.html background-size-body-cover-ref.html +== background-size-body-cover-no-repeat.html background-size-body-cover-ref.html +!= background-size-body-cover-not-fixed.html background-size-body-cover-ref.html +!= background-size-body-cover-not-fixed.html background-size-body-single-not-fixed.html + +# relies on reftest window having greater height than width +== background-size-body-contain.html background-size-body-cover-ref.html +!= background-size-body-contain-no-repeat.html background-size-body-cover-ref.html +!= background-size-body-contain-not-fixed.html background-size-body-cover-ref.html +!= background-size-body-cover-not-fixed.html background-size-body-contain-not-fixed.html + +!= background-size-body-percent-percent-overflow.html background-size-body-percent-percent-overflow-ref.html + +== background-size-zoom-no-repeat.html background-size-zoom-no-repeat-ref.html + +== background-size-contain-clip-padding.html background-size-contain-clip-padding-ref.html +== background-size-contain-clip-border.html background-size-contain-clip-border-ref.html +== background-size-contain-position-fifty-fifty.html background-size-contain-position-fifty-fifty-ref.html +== background-size-contain-clip-padding-origin-border.html background-size-contain-clip-padding-origin-border-ref.html +== background-size-contain-clip-padding-origin-border-padding.html background-size-contain-clip-padding-origin-border-padding-ref.html + +# -moz-background-inline-policy is touchy and hard to test due to stretching +# artifacts and the difficulty of covering exact lines, and its CSS3 analog is +# on the chopping block at the moment, so just make sure background-size results +# in a different rendering when present. +!= background-size-cover-continuous.html background-size-continuous.html +!= background-size-cover-each-box.html background-size-each-box.html +!= background-size-cover-bounding-box.html background-size-bounding-box.html + +# ...and make sure each rendering with background-size is different from the +# others +!= background-size-cover-continuous.html background-size-cover-each-box.html +!= background-size-cover-continuous.html background-size-cover-bounding-box.html +!= background-size-cover-each-box.html background-size-cover-bounding-box.html + + +# There seems to be a pixel-snapping problem here, where the repeated background +# image isn't being snapped at its boundaries. Note that the boundaries within +# the image aren't the issue, because they're being obscured to avoid sampling +# algorithm dependencies (at least assuming the sampling algorithm in use +# doesn't sample too far astray from the boundaries). +fails == background-size-zoom-repeat.html background-size-zoom-repeat-ref.html + +# background-size affects images without intrinsic dimensions specially; we may +# not support such image formats right now, but when we do, we want +# background-size to be changed accordingly, and hopefully these tests should +# start failing when we do. +fails == background-size-no-intrinsic-width-image.html background-size-no-intrinsic-width-image-ref.html +fails == background-size-no-intrinsic-height-image.html background-size-no-intrinsic-height-image-ref.html diff --git a/layout/style/nsCSSDeclaration.cpp b/layout/style/nsCSSDeclaration.cpp index 315fab2307e3..4eebd5bf3368 100644 --- a/layout/style/nsCSSDeclaration.cpp +++ b/layout/style/nsCSSDeclaration.cpp @@ -174,11 +174,16 @@ PRBool nsCSSDeclaration::AppendValueToString(nsCSSProperty aProperty, nsAString& ((aProperty == eCSSProperty_background_position || aProperty == eCSSProperty__moz_transform_origin) && pair->mXValue.GetUnit() != eCSSUnit_Inherit && - pair->mXValue.GetUnit() != eCSSUnit_Initial)) { - // Only output a Y value if it's different from the X value + pair->mXValue.GetUnit() != eCSSUnit_Initial) || + (aProperty == eCSSProperty__moz_background_size && + pair->mXValue.GetUnit() != eCSSUnit_Inherit && + pair->mXValue.GetUnit() != eCSSUnit_Initial && + pair->mXValue.GetUnit() != eCSSUnit_Enumerated)) { + // Only output a Y value if it's different from the X value, // or if it's a background-position value other than 'initial' - // or 'inherit' or if it's a -moz-transform-origin value other - // than 'initial' or 'inherit'. + // or 'inherit', or if it's a -moz-transform-origin value other + // than 'initial' or 'inherit', or if it's a -moz-background-size + // value other than 'initial' or 'inherit' or 'contain' or 'cover'. aResult.Append(PRUnichar(' ')); AppendCSSValueToString(aProperty, pair->mYValue, aResult); } @@ -772,6 +777,8 @@ nsCSSDeclaration::GetValue(nsCSSProperty aProperty, * data->ValueListStorageFor(eCSSProperty__moz_background_clip); const nsCSSValueList *origin = * data->ValueListStorageFor(eCSSProperty__moz_background_origin); + const nsCSSValuePairList *size = + * data->ValuePairListStorageFor(eCSSProperty__moz_background_size); for (;;) { AppendCSSValueToString(eCSSProperty_background_image, image->mValue, aValue); @@ -800,7 +807,7 @@ nsCSSDeclaration::GetValue(nsCSSProperty aProperty, // support for content-box on background-clip. PR_STATIC_ASSERT(NS_STYLE_BG_CLIP_BORDER == NS_STYLE_BG_ORIGIN_BORDER); - PR_STATIC_ASSERT(NS_STYLE_BG_CLIP_PADDING == + PR_STATIC_ASSERT(NS_STYLE_BG_CLIP_PADDING == NS_STYLE_BG_ORIGIN_PADDING); // PR_STATIC_ASSERT(NS_STYLE_BG_CLIP_CONTENT == /* does not exist */ // NS_STYLE_BG_ORIGIN_CONTENT); @@ -824,16 +831,17 @@ nsCSSDeclaration::GetValue(nsCSSProperty aProperty, position = position->mNext; clip = clip->mNext; origin = origin->mNext; + size = size->mNext; if (!image) { - if (repeat || attachment || position || clip || origin) { + if (repeat || attachment || position || clip || origin || size) { // Uneven length lists, so can't be serialized as shorthand. aValue.Truncate(); return NS_OK; } break; } - if (!repeat || !attachment || !position || !clip || !origin) { + if (!repeat || !attachment || !position || !clip || !origin || !size) { // Uneven length lists, so can't be serialized as shorthand. aValue.Truncate(); return NS_OK; diff --git a/layout/style/nsCSSKeywordList.h b/layout/style/nsCSSKeywordList.h index 082933ccfc55..85e26b6cef79 100644 --- a/layout/style/nsCSSKeywordList.h +++ b/layout/style/nsCSSKeywordList.h @@ -241,11 +241,13 @@ CSS_KEY(code, code) CSS_KEY(col-resize, col_resize) CSS_KEY(collapse, collapse) CSS_KEY(condensed, condensed) +CSS_KEY(contain, contain) CSS_KEY(content, content) CSS_KEY(content-box, content_box) CSS_KEY(context-menu, context_menu) CSS_KEY(continuous, continuous) CSS_KEY(copy, copy) +CSS_KEY(cover, cover) CSS_KEY(crop, crop) CSS_KEY(cross, cross) CSS_KEY(crosshair, crosshair) diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index e30a329af8b7..6ac64e3691d2 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -26,6 +26,7 @@ * Boris Zbarsky * Mats Palmgren * Christian Biesinger + * Jeff Walden * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -407,6 +408,7 @@ protected: nsCSSValuePair mPosition; nsCSSValue mClip; nsCSSValue mOrigin; + nsCSSValuePair mSize; // The background-color is set as a side-effect, and if so, mLastItem // is set to true. PRBool mLastItem; @@ -421,6 +423,8 @@ protected: PRBool ParseBackgroundList(nsCSSProperty aPropID); // a single value prop-id PRBool ParseBackgroundPosition(); PRBool ParseBoxPositionValues(nsCSSValuePair& aOut); + PRBool ParseBackgroundSize(); + PRBool ParseBackgroundSizeValues(nsCSSValuePair& aOut); PRBool ParseBorderColor(); PRBool ParseBorderColors(nsCSSValueList** aResult, nsCSSProperty aProperty); @@ -5061,6 +5065,8 @@ CSSParserImpl::ParseProperty(nsCSSProperty aPropID) case eCSSProperty__moz_background_origin: case eCSSProperty_background_repeat: return ParseBackgroundList(aPropID); + case eCSSProperty__moz_background_size: + return ParseBackgroundSize(); case eCSSProperty_border: return ParseBorderSide(kBorderTopIDs, PR_TRUE); case eCSSProperty_border_color: @@ -5341,6 +5347,7 @@ CSSParserImpl::ParseSingleValueProperty(nsCSSValue& aValue, case eCSSProperty_border_start: case eCSSProperty_border_top: case eCSSProperty_border_width: + case eCSSProperty__moz_background_size: case eCSSProperty__moz_border_radius: case eCSSProperty__moz_border_radius_topLeft: case eCSSProperty__moz_border_radius_topRight: @@ -5986,6 +5993,7 @@ CSSParserImpl::ParseBackground() BackgroundItem bgitem; nsCSSValuePairList *positionHead = nsnull, **positionTail = &positionHead; + nsCSSValuePairList *sizeHead = nsnull, **sizeTail = &sizeHead; static const BackgroundItemSimpleValueInfo simpleValues[] = { { &BackgroundItem::mImage, eCSSProperty_background_image }, { &BackgroundItem::mRepeat, eCSSProperty_background_repeat }, @@ -6003,6 +6011,7 @@ CSSParserImpl::ParseBackground() if (!ParseBackgroundItem(bgitem, !positionHead)) { break; } + nsCSSValuePairList *positionItem = new nsCSSValuePairList; if (!positionItem) { mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); @@ -6013,6 +6022,16 @@ CSSParserImpl::ParseBackground() *positionTail = positionItem; positionTail = &positionItem->mNext; + nsCSSValuePairList *sizeItem = new nsCSSValuePairList; + if (!sizeItem) { + mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); + break; + } + sizeItem->mXValue = bgitem.mSize.mXValue; + sizeItem->mYValue = bgitem.mSize.mYValue; + *sizeTail = sizeItem; + sizeTail = &sizeItem->mNext; + PRBool fail = PR_FALSE; for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(simpleValues); ++i) { nsCSSValueList *item = new nsCSSValueList; @@ -6037,6 +6056,7 @@ CSSParserImpl::ParseBackground() } mTempData.mColor.mBackPosition = positionHead; + mTempData.mColor.mBackSize = sizeHead; for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(simpleValues); ++i) { nsCSSValueList **source = static_cast( mTempData.PropertyAt(simpleValues[i].propID)); @@ -6049,9 +6069,11 @@ CSSParserImpl::ParseBackground() mTempData.SetPropertyBit(eCSSProperty_background_position); mTempData.SetPropertyBit(eCSSProperty__moz_background_clip); mTempData.SetPropertyBit(eCSSProperty__moz_background_origin); + mTempData.SetPropertyBit(eCSSProperty__moz_background_size); return PR_TRUE; } delete positionHead; + delete sizeHead; for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(simpleValues); ++i) { delete simpleHeads[i]; } @@ -6073,6 +6095,8 @@ CSSParserImpl::ParseBackgroundItem(CSSParserImpl::BackgroundItem& aItem, aItem.mPosition.mYValue.SetPercentValue(0.0f); aItem.mClip.SetIntValue(NS_STYLE_BG_CLIP_BORDER, eCSSUnit_Enumerated); aItem.mOrigin.SetIntValue(NS_STYLE_BG_ORIGIN_PADDING, eCSSUnit_Enumerated); + aItem.mSize.mXValue.SetAutoValue(); + aItem.mSize.mYValue.SetAutoValue(); aItem.mLastItem = PR_FALSE; PRBool haveColor = PR_FALSE, @@ -6113,6 +6137,8 @@ CSSParserImpl::ParseBackgroundItem(CSSParserImpl::BackgroundItem& aItem, aItem.mPosition.SetBothValuesTo(val); aItem.mClip = val; aItem.mOrigin = val; + aItem.mSize.mXValue = val; + aItem.mSize.mYValue = val; aItem.mLastItem = PR_TRUE; haveSomething = PR_TRUE; break; @@ -6160,9 +6186,9 @@ CSSParserImpl::ParseBackgroundItem(CSSParserImpl::BackgroundItem& aItem, // support for content-box on background-clip. } else if (nsCSSProps::FindKeyword(keyword, nsCSSProps::kBackgroundClipKTable, dummy)) { - // For now, we use the background-clip table, because we don't - // support 'content' on background-clip. But that's dangerous - // if we eventually support no-clip. + // For now, we use the background-clip table rather than have a special + // background-origin table, because we don't support 'content-box' on + // background-origin. NS_ASSERTION( nsCSSProps::kBackgroundClipKTable[0] == eCSSKeyword_border && nsCSSProps::kBackgroundClipKTable[2] == eCSSKeyword_padding && @@ -6230,7 +6256,8 @@ CSSParserImpl::ParseBackgroundItem(CSSParserImpl::BackgroundItem& aItem, return haveSomething; } -// This function is very similar to ParseBackgroundPosition. +// This function is very similar to ParseBackgroundPosition and +// ParseBackgroundSize. PRBool CSSParserImpl::ParseBackgroundList(nsCSSProperty aPropID) { @@ -6271,7 +6298,7 @@ CSSParserImpl::ParseBackgroundList(nsCSSProperty aPropID) return PR_FALSE; } -// This function is very similar to ParseBackgroundList. +// This function is very similar to ParseBackgroundList and ParseBackgroundSize. PRBool CSSParserImpl::ParseBackgroundPosition() { @@ -6316,7 +6343,7 @@ CSSParserImpl::ParseBackgroundPosition() * values corresponding to percentages of the box, raw offsets, or keywords * like "top," "left center," etc. * - * @param aOut The nsCSSValuePair where to place the result. + * @param aOut The nsCSSValuePair in which to place the result. * @return Whether or not the operation succeeded. */ PRBool CSSParserImpl::ParseBoxPositionValues(nsCSSValuePair &aOut) @@ -6398,6 +6425,90 @@ PRBool CSSParserImpl::ParseBoxPositionValues(nsCSSValuePair &aOut) return PR_TRUE; } +// This function is very similar to ParseBackgroundList and +// ParseBackgroundPosition. +PRBool +CSSParserImpl::ParseBackgroundSize() +{ + nsCSSValuePair valuePair; + nsCSSValuePairList *head = nsnull, **tail = &head; + if (ParseVariant(valuePair.mXValue, VARIANT_INHERIT, nsnull)) { + // 'initial' and 'inherit' stand alone, no second value. + head = new nsCSSValuePairList; + if (!head) { + mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); + return PR_FALSE; + } + head->mXValue = valuePair.mXValue; + head->mYValue.Reset(); + mTempData.mColor.mBackSize = head; + mTempData.SetPropertyBit(eCSSProperty__moz_background_size); + return ExpectEndProperty(); + } + + for (;;) { + if (!ParseBackgroundSizeValues(valuePair)) { + break; + } + nsCSSValuePairList *item = new nsCSSValuePairList; + if (!item) { + mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); + break; + } + item->mXValue = valuePair.mXValue; + item->mYValue = valuePair.mYValue; + *tail = item; + tail = &item->mNext; + if (ExpectSymbol(',', PR_TRUE)) { + continue; + } + if (!ExpectEndProperty()) { + break; + } + mTempData.mColor.mBackSize = head; + mTempData.SetPropertyBit(eCSSProperty__moz_background_size); + return PR_TRUE; + } + delete head; + return PR_FALSE; +} + +/** + * Parses two values that correspond to lengths for the -moz-background-size + * property. These can be one or two lengths (or the 'auto' keyword) or + * percentages corresponding to the element's dimensions or the single keywords + * 'contain' or 'cover'. 'initial' and 'inherit' must be handled by the caller + * if desired. + * + * @param aOut The nsCSSValuePair in which to place the result. + * @return Whether or not the operation succeeded. + */ +PRBool CSSParserImpl::ParseBackgroundSizeValues(nsCSSValuePair &aOut) +{ + // First try a percentage or a length value + nsCSSValue &xValue = aOut.mXValue, + &yValue = aOut.mYValue; + if (ParseNonNegativeVariant(xValue, VARIANT_LP | VARIANT_AUTO, nsnull)) { + // We have one percentage/length/auto. Get the optional second + // percentage/length/keyword. + if (ParseNonNegativeVariant(yValue, VARIANT_LP | VARIANT_AUTO, nsnull)) { + // We have a second percentage/length/auto. + return PR_TRUE; + } + + // If only one percentage or length value is given, it sets the + // horizontal size only, and the vertical size will be as if by 'auto'. + yValue.SetAutoValue(); + return PR_TRUE; + } + + // Now address 'contain' and 'cover'. + if (!ParseEnum(xValue, nsCSSProps::kBackgroundSizeKTable)) + return PR_FALSE; + yValue.Reset(); + return PR_TRUE; +} + PRBool CSSParserImpl::ParseBorderColor() { diff --git a/layout/style/nsCSSPropList.h b/layout/style/nsCSSPropList.h index baccdb9522a5..32da6d747e6a 100644 --- a/layout/style/nsCSSPropList.h +++ b/layout/style/nsCSSPropList.h @@ -470,6 +470,16 @@ CSS_PROP_BACKGROUND( mBackRepeat, eCSSType_ValueList, kBackgroundRepeatKTable) +CSS_PROP_BACKGROUND( + -moz-background-size, + _moz_background_size, + MozBackgroundSize, + CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE | + CSS_PROPERTY_VALUE_LIST_USES_COMMAS, + Color, + mBackSize, + eCSSType_ValuePairList, + kBackgroundSizeKTable) CSS_PROP_DISPLAY( -moz-binding, binding, diff --git a/layout/style/nsCSSProps.cpp b/layout/style/nsCSSProps.cpp index 71aca561afd5..161aefc6e8d3 100644 --- a/layout/style/nsCSSProps.cpp +++ b/layout/style/nsCSSProps.cpp @@ -527,6 +527,12 @@ const PRInt32 nsCSSProps::kBackgroundRepeatKTable[] = { eCSSKeyword_UNKNOWN,-1 }; +const PRInt32 nsCSSProps::kBackgroundSizeKTable[] = { + eCSSKeyword_contain, NS_STYLE_BG_SIZE_CONTAIN, + eCSSKeyword_cover, NS_STYLE_BG_SIZE_COVER, + eCSSKeyword_UNKNOWN,-1 +}; + const PRInt32 nsCSSProps::kBorderCollapseKTable[] = { eCSSKeyword_collapse, NS_STYLE_BORDER_COLLAPSE, eCSSKeyword_separate, NS_STYLE_BORDER_SEPARATE, @@ -1502,6 +1508,7 @@ static const nsCSSProperty gBackgroundSubpropTable[] = { eCSSProperty_background_position, eCSSProperty__moz_background_clip, eCSSProperty__moz_background_origin, + eCSSProperty__moz_background_size, eCSSProperty_UNKNOWN }; diff --git a/layout/style/nsCSSProps.h b/layout/style/nsCSSProps.h index 4a4a04c96a57..7bd5836cc6f7 100644 --- a/layout/style/nsCSSProps.h +++ b/layout/style/nsCSSProps.h @@ -170,6 +170,7 @@ public: static const PRInt32 kBackgroundOriginKTable[]; static const PRInt32 kBackgroundPositionKTable[]; static const PRInt32 kBackgroundRepeatKTable[]; + static const PRInt32 kBackgroundSizeKTable[]; static const PRInt32 kBorderCollapseKTable[]; static const PRInt32 kBorderColorKTable[]; static const PRInt32 kBorderImageKTable[]; diff --git a/layout/style/nsCSSStruct.cpp b/layout/style/nsCSSStruct.cpp index 71805fa2f916..05e413b518b3 100644 --- a/layout/style/nsCSSStruct.cpp +++ b/layout/style/nsCSSStruct.cpp @@ -110,6 +110,7 @@ nsCSSColor::nsCSSColor(void) , mBackRepeat(nsnull) , mBackAttachment(nsnull) , mBackPosition(nsnull) + , mBackSize(nsnull) , mBackClip(nsnull) , mBackOrigin(nsnull) { @@ -124,6 +125,7 @@ nsCSSColor::~nsCSSColor(void) delete mBackRepeat; delete mBackAttachment; delete mBackPosition; + delete mBackSize; delete mBackClip; delete mBackOrigin; } diff --git a/layout/style/nsCSSStruct.h b/layout/style/nsCSSStruct.h index a928cdd325c5..cb617f35e9c8 100644 --- a/layout/style/nsCSSStruct.h +++ b/layout/style/nsCSSStruct.h @@ -312,6 +312,7 @@ struct nsCSSColor : public nsCSSStruct { nsCSSValueList* mBackRepeat; nsCSSValueList* mBackAttachment; nsCSSValuePairList* mBackPosition; + nsCSSValuePairList* mBackSize; nsCSSValueList* mBackClip; nsCSSValueList* mBackOrigin; nsCSSValue mBackInlinePolicy; diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index b63091e582f6..c299ffa80d59 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -1209,7 +1209,7 @@ nsComputedDOMStyle::GetBackgroundList(PRUint8 nsStyleBackground::Layer::* aMembe delete valueList; return NS_ERROR_OUT_OF_MEMORY; } - val->SetIdent(nsCSSProps::ValueToKeywordEnum(bg->mLayers[i].*aMember, + val->SetIdent(nsCSSProps::ValueToKeywordEnum(bg->mLayers[i].*aMember, aTable)); } @@ -1358,6 +1358,82 @@ nsComputedDOMStyle::GetBackgroundRepeat(nsIDOMCSSValue** aValue) aValue); } +nsresult +nsComputedDOMStyle::GetMozBackgroundSize(nsIDOMCSSValue** aValue) +{ + const nsStyleBackground* bg = GetStyleBackground(); + + nsDOMCSSValueList *valueList = GetROCSSValueList(PR_TRUE); + NS_ENSURE_TRUE(valueList, NS_ERROR_OUT_OF_MEMORY); + + for (PRUint32 i = 0, i_end = bg->mSizeCount; i < i_end; ++i) { + const nsStyleBackground::Size &size = bg->mLayers[i].mSize; + + switch (size.mWidthType) { + case nsStyleBackground::Size::eContain: + case nsStyleBackground::Size::eCover: { + NS_ABORT_IF_FALSE(size.mWidthType == size.mHeightType, + "unsynced types"); + nsCSSKeyword keyword = size.mWidthType == nsStyleBackground::Size::eContain + ? eCSSKeyword_contain + : eCSSKeyword_cover; + nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue(); + if (!val || !valueList->AppendCSSValue(val)) { + delete valueList; + delete val; + return NS_ERROR_OUT_OF_MEMORY; + } + val->SetIdent(keyword); + break; + } + default: { + nsDOMCSSValueList *itemList = GetROCSSValueList(PR_FALSE); + if (!itemList || !valueList->AppendCSSValue(itemList)) { + delete valueList; + delete itemList; + return NS_ERROR_OUT_OF_MEMORY; + } + + nsROCSSPrimitiveValue* valX = GetROCSSPrimitiveValue(); + nsROCSSPrimitiveValue* valY = GetROCSSPrimitiveValue(); + if (!valX || !itemList->AppendCSSValue(valX)) { + delete valueList; + delete valX; + return NS_ERROR_OUT_OF_MEMORY; + } + if (!valY || !itemList->AppendCSSValue(valY)) { + delete valueList; + delete valY; + return NS_ERROR_OUT_OF_MEMORY; + } + + if (size.mWidthType == nsStyleBackground::Size::eAuto) { + valX->SetIdent(eCSSKeyword_auto); + } else if (size.mWidthType == nsStyleBackground::Size::ePercentage) { + valX->SetPercent(size.mWidth.mFloat); + } else { + NS_ABORT_IF_FALSE(size.mWidthType == nsStyleBackground::Size::eLength, + "bad mWidthType"); + valX->SetAppUnits(size.mWidth.mCoord); + } + + if (size.mHeightType == nsStyleBackground::Size::eAuto) { + valY->SetIdent(eCSSKeyword_auto); + } else if (size.mHeightType == nsStyleBackground::Size::ePercentage) { + valY->SetPercent(size.mHeight.mFloat); + } else { + NS_ABORT_IF_FALSE(size.mHeightType == nsStyleBackground::Size::eLength, + "bad mHeightType"); + valY->SetAppUnits(size.mHeight.mCoord); + } + break; + } + } + } + + return CallQueryInterface(valueList, aValue); +} + nsresult nsComputedDOMStyle::GetPadding(nsIDOMCSSValue** aValue) { @@ -4216,6 +4292,7 @@ nsComputedDOMStyle::GetQueryablePropertyMap(PRUint32* aLength) COMPUTED_STYLE_MAP_ENTRY(_moz_background_clip, BackgroundClip), COMPUTED_STYLE_MAP_ENTRY(_moz_background_inline_policy, BackgroundInlinePolicy), COMPUTED_STYLE_MAP_ENTRY(_moz_background_origin, BackgroundOrigin), + COMPUTED_STYLE_MAP_ENTRY(_moz_background_size, MozBackgroundSize), COMPUTED_STYLE_MAP_ENTRY(binding, Binding), COMPUTED_STYLE_MAP_ENTRY(border_bottom_colors, BorderBottomColors), COMPUTED_STYLE_MAP_ENTRY(border_image, BorderImage), diff --git a/layout/style/nsComputedDOMStyle.h b/layout/style/nsComputedDOMStyle.h index 178d7594ae4c..7e8bf8fc7106 100644 --- a/layout/style/nsComputedDOMStyle.h +++ b/layout/style/nsComputedDOMStyle.h @@ -175,6 +175,7 @@ private: nsresult GetBackgroundClip(nsIDOMCSSValue** aValue); nsresult GetBackgroundInlinePolicy(nsIDOMCSSValue** aValue); nsresult GetBackgroundOrigin(nsIDOMCSSValue** aValue); + nsresult GetMozBackgroundSize(nsIDOMCSSValue** aValue); /* Padding properties */ nsresult GetPadding(nsIDOMCSSValue** aValue); diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index b02f42382a25..47625d13eab1 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -1446,6 +1446,7 @@ nsRuleNode::GetBackgroundData(nsStyleContext* aContext) colorData.mBackRepeat = nsnull; colorData.mBackAttachment = nsnull; colorData.mBackPosition = nsnull; + colorData.mBackSize = nsnull; colorData.mBackClip = nsnull; colorData.mBackOrigin = nsnull; @@ -3871,6 +3872,91 @@ struct BackgroundItemComputer }; +struct BackgroundSizeAxis { + nsCSSValue nsCSSValuePairList::* specified; + nsStyleBackground::Size::Dimension nsStyleBackground::Size::* result; + PRUint8 nsStyleBackground::Size::* type; +}; + +static const BackgroundSizeAxis gBGSizeAxes[] = { + { &nsCSSValuePairList::mXValue, + &nsStyleBackground::Size::mWidth, + &nsStyleBackground::Size::mWidthType }, + { &nsCSSValuePairList::mYValue, + &nsStyleBackground::Size::mHeight, + &nsStyleBackground::Size::mHeightType } +}; + +NS_SPECIALIZE_TEMPLATE +struct BackgroundItemComputer +{ + static void ComputeValue(nsStyleContext* aStyleContext, + const nsCSSValuePairList* aSpecifiedValue, + nsStyleBackground::Size& aComputedValue, + PRBool& aCanStoreInRuleTree) + { + nsStyleBackground::Size &size = aComputedValue; + for (const BackgroundSizeAxis *axis = gBGSizeAxes, + *axis_end = gBGSizeAxes + NS_ARRAY_LENGTH(gBGSizeAxes); + axis != axis_end; ++axis) { + const nsCSSValue &specified = aSpecifiedValue->*(axis->specified); + if (eCSSUnit_Auto == specified.GetUnit()) { + size.*(axis->type) = nsStyleBackground::Size::eAuto; + } + else if (eCSSUnit_Enumerated == specified.GetUnit()) { + PR_STATIC_ASSERT(nsStyleBackground::Size::eContain == + NS_STYLE_BG_SIZE_CONTAIN); + PR_STATIC_ASSERT(nsStyleBackground::Size::eCover == + NS_STYLE_BG_SIZE_COVER); + NS_ABORT_IF_FALSE(specified.GetIntValue() == NS_STYLE_BG_SIZE_CONTAIN || + specified.GetIntValue() == NS_STYLE_BG_SIZE_COVER, + "invalid enumerated value for size coordinate"); + size.*(axis->type) = specified.GetIntValue(); + } + else if (eCSSUnit_Null == specified.GetUnit()) { + NS_ABORT_IF_FALSE(axis == gBGSizeAxes + 1, + "null allowed only as height value, and only " + "for contain/cover/initial/inherit"); +#ifdef DEBUG + { + const nsCSSValue &widthValue = aSpecifiedValue->mXValue; + NS_ABORT_IF_FALSE(widthValue.GetUnit() != eCSSUnit_Inherit && + widthValue.GetUnit() != eCSSUnit_Initial, + "initial/inherit should already have been handled"); + NS_ABORT_IF_FALSE(widthValue.GetUnit() == eCSSUnit_Enumerated && + (widthValue.GetIntValue() == NS_STYLE_BG_SIZE_CONTAIN || + widthValue.GetIntValue() == NS_STYLE_BG_SIZE_COVER), + "null height value not corresponding to allowable " + "non-null width value"); + } +#endif + size.*(axis->type) = size.mWidthType; + } + else if (eCSSUnit_Percent == specified.GetUnit()) { + (size.*(axis->result)).mFloat = specified.GetPercentValue(); + size.*(axis->type) = nsStyleBackground::Size::ePercentage; + } + else { + NS_ABORT_IF_FALSE(specified.IsLengthUnit(), "unexpected unit"); + (size.*(axis->result)).mCoord = + CalcLength(specified, aStyleContext, aStyleContext->PresContext(), + aCanStoreInRuleTree); + size.*(axis->type) = nsStyleBackground::Size::eLength; + } + } + + NS_ABORT_IF_FALSE(size.mWidthType < nsStyleBackground::Size::eDimensionType_COUNT, + "bad width type"); + NS_ABORT_IF_FALSE(size.mHeightType < nsStyleBackground::Size::eDimensionType_COUNT, + "bad height type"); + NS_ABORT_IF_FALSE((size.mWidthType != nsStyleBackground::Size::eContain && + size.mWidthType != nsStyleBackground::Size::eCover) || + size.mWidthType == size.mHeightType, + "contain/cover apply to both dimensions or to neither"); + } +}; + + template static void SetBackgroundList(nsStyleContext* aStyleContext, @@ -4018,6 +4104,15 @@ nsRuleNode::ComputeBackgroundData(void* aStartStruct, bg->mPositionCount, maxItemCount, rebuild, canStoreInRuleTree); + // background-size: enum, length, auto, inherit, initial [pair list] + nsStyleBackground::Size initialSize; + initialSize.SetInitialValues(); + SetBackgroundList(aContext, colorData.mBackSize, bg->mLayers, + parentBG->mLayers, &nsStyleBackground::Layer::mSize, + initialSize, parentBG->mSizeCount, + bg->mSizeCount, maxItemCount, rebuild, + canStoreInRuleTree); + if (rebuild) { // Delete any extra items. We need to keep layers in which any // property was specified. @@ -4036,6 +4131,8 @@ nsRuleNode::ComputeBackgroundData(void* aStartStruct, bg->mOriginCount, fillCount); FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mPosition, bg->mPositionCount, fillCount); + FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mSize, + bg->mSizeCount, fillCount); } COMPUTE_END_RESET(Background, bg) @@ -5750,6 +5847,7 @@ nsRuleNode::HasAuthorSpecifiedRules(nsStyleContext* aStyleContext, colorData.mBackPosition = nsnull; colorData.mBackClip = nsnull; colorData.mBackOrigin = nsnull; + colorData.mBackSize = nsnull; if (ruleData.mLevel == nsStyleSet::eAgentSheet || ruleData.mLevel == nsStyleSet::eUserSheet) { diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index 49eb59a0043b..20ee637a5215 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -1217,6 +1217,7 @@ nsStyleBackground::nsStyleBackground() , mRepeatCount(1) , mPositionCount(1) , mImageCount(1) + , mSizeCount(1) , mBackgroundColor(NS_RGBA(0, 0, 0, 0)) , mBackgroundInlinePolicy(NS_STYLE_BG_INLINE_POLICY_CONTINUOUS) { @@ -1232,6 +1233,7 @@ nsStyleBackground::nsStyleBackground(const nsStyleBackground& aSource) , mRepeatCount(aSource.mRepeatCount) , mPositionCount(aSource.mPositionCount) , mImageCount(aSource.mImageCount) + , mSizeCount(aSource.mSizeCount) , mLayers(aSource.mLayers) // deep copy , mBackgroundColor(aSource.mBackgroundColor) , mBackgroundInlinePolicy(aSource.mBackgroundInlinePolicy) @@ -1246,6 +1248,7 @@ nsStyleBackground::nsStyleBackground(const nsStyleBackground& aSource) mRepeatCount = PR_MAX(mRepeatCount, count); mPositionCount = PR_MAX(mPositionCount, count); mImageCount = PR_MAX(mImageCount, count); + mSizeCount = PR_MAX(mSizeCount, count); } } @@ -1303,6 +1306,46 @@ nsStyleBackground::Position::SetInitialValues() mYIsPercent = PR_TRUE; } +void +nsStyleBackground::Size::SetInitialValues() +{ + mWidthType = mHeightType = eAuto; +} + +PRBool +nsStyleBackground::Size::operator==(const Size& aOther) const +{ + NS_ABORT_IF_FALSE(mWidthType < eDimensionType_COUNT, + "bad mWidthType for this"); + NS_ABORT_IF_FALSE(mHeightType < eDimensionType_COUNT, + "bad mHeightType for this"); + NS_ABORT_IF_FALSE(aOther.mWidthType < eDimensionType_COUNT, + "bad mWidthType for aOther"); + NS_ABORT_IF_FALSE(aOther.mHeightType < eDimensionType_COUNT, + "bad mHeightType for aOther"); + + if (mWidthType != aOther.mWidthType || mHeightType != aOther.mHeightType) + return PR_FALSE; + + if (mWidthType == ePercentage) { + if (mWidth.mFloat != aOther.mWidth.mFloat) + return PR_FALSE; + } else if (mWidthType == eLength) { + if (mWidth.mCoord != aOther.mWidth.mCoord) + return PR_FALSE; + } + + if (mHeightType == ePercentage) { + if (mHeight.mFloat != aOther.mHeight.mFloat) + return PR_FALSE; + } else if (mHeightType == eLength) { + if (mHeight.mCoord != aOther.mHeight.mCoord) + return PR_FALSE; + } + + return PR_TRUE; +} + nsStyleBackground::Layer::Layer() { } @@ -1319,6 +1362,7 @@ nsStyleBackground::Layer::SetInitialValues() mOrigin = NS_STYLE_BG_ORIGIN_PADDING; mRepeat = NS_STYLE_BG_REPEAT_XY; mPosition.SetInitialValues(); + mSize.SetInitialValues(); mImage = nsnull; } @@ -1329,6 +1373,7 @@ PRBool nsStyleBackground::Layer::operator==(const Layer& aOther) const mOrigin == aOther.mOrigin && mRepeat == aOther.mRepeat && mPosition == aOther.mPosition && + mSize == aOther.mSize && EqualImages(mImage, aOther.mImage); } diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 13a1fd3179bb..c8fff5e98ee0 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -194,6 +194,40 @@ struct nsStyleBackground { } }; + struct Size; + friend struct Size; + struct Size { + typedef union { + nscoord mCoord; // for lengths + float mFloat; // for percents + } Dimension; + Dimension mWidth, mHeight; + + enum DimensionType { + // If one of mWidth and mHeight is eContain or eCover, then both are. + // Also, these two values must equal the corresponding values in + // kBackgroundSizeKTable. + eContain, eCover, + + eAuto, + ePercentage, + eLength, + eDimensionType_COUNT + }; + PRUint8 mWidthType, mHeightType; + + // Initialize nothing + Size() {} + + // Initialize to initial values + void SetInitialValues(); + + PRBool operator==(const Size& aOther) const; + PRBool operator!=(const Size& aOther) const { + return !(*this == aOther); + } + }; + struct Layer; friend struct Layer; struct Layer { @@ -203,6 +237,7 @@ struct nsStyleBackground { PRUint8 mRepeat; // [reset] See nsStyleConsts.h Position mPosition; // [reset] nsCOMPtr mImage; // [reset] + Size mSize; // [reset] // Initializes only mImage Layer(); @@ -225,7 +260,8 @@ struct nsStyleBackground { mOriginCount, mRepeatCount, mPositionCount, - mImageCount; + mImageCount, + mSizeCount; // Layers are stored in an array, matching the top-to-bottom order in // which they are specified in CSS. The number of layers to be used // should come from the background-image property. We create @@ -234,7 +270,7 @@ struct nsStyleBackground { // callers in layout care about (which is also the one whose // background-clip applies to the background-color) may not be last // layer. In layers below the bottom layer, properties will be - // unitialized unless their count, above, indicates that they are + // uninitialized unless their count, above, indicates that they are // present. nsAutoTArray mLayers; diff --git a/layout/style/test/property_database.js b/layout/style/test/property_database.js index 684cf658c361..420b0955676b 100644 --- a/layout/style/test/property_database.js +++ b/layout/style/test/property_database.js @@ -100,6 +100,14 @@ var gCSSProperties = { other_values: [ "border", "content", "border, padding", "padding, padding, padding", "border, border" ], invalid_values: [ "margin", "padding padding" ] }, + "-moz-background-size": { + domProp: "MozBackgroundSize", + inherited: false, + type: CSS_TYPE_LONGHAND, + initial_values: [ "auto", "auto auto" ], + other_values: [ "contain", "cover", "100px auto", "auto 100px", "100% auto", "auto 100%", "25% 50px", "3em 40%" ], + invalid_values: [ "contain contain", "cover cover", "cover auto", "auto cover", "contain cover", "cover contain", "-5px 3px", "3px -5px", "auto -5px", "-5px auto" ] + }, "-moz-binding": { domProp: "MozBinding", inherited: false, @@ -613,8 +621,8 @@ var gCSSProperties = { domProp: "background", inherited: false, type: CSS_TYPE_TRUE_SHORTHAND, - subproperties: [ "background-attachment", "background-color", "background-image", "background-position", "background-repeat", "-moz-background-clip", "-moz-background-origin" ], - initial_values: [ "transparent", "none", "repeat", "scroll", "0% 0%", "top left", "left top", "transparent none", "top left none", "left top none", "none left top", "none top left", "none 0% 0%", "transparent none repeat scroll top left", "left top repeat none scroll transparent"], + subproperties: [ "background-attachment", "background-color", "background-image", "background-position", "background-repeat", "-moz-background-clip", "-moz-background-origin", "-moz-background-size" ], + initial_values: [ "transparent", "none", "repeat", "scroll", "0% 0%", "top left", "left top", "transparent none", "top left none", "left top none", "none left top", "none top left", "none 0% 0%", "transparent none repeat scroll top left", "left top repeat none scroll transparent" ], other_values: [ /* without multiple backgrounds */ "green", "none green repeat scroll left top", "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==)", "repeat url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==') transparent left top scroll", "repeat-x", "repeat-y", "no-repeat", "none repeat-y transparent scroll 0% 0%", "fixed", "0% top transparent fixed repeat none", "top", "left", "50% 50%", "center", "bottom right scroll none transparent repeat", "50% transparent", "transparent 50%", "50%", From 215848eb9b96d3af170bda049ec37d9f78e9a06d Mon Sep 17 00:00:00 2001 From: Leon Sha Date: Mon, 27 Jul 2009 11:30:57 +0800 Subject: [PATCH 18/61] Bug 506201 - regexp.cpp fails to compile on opensolaris: goto bypasses variable init. r=gal --- js/src/jsregexp.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/js/src/jsregexp.cpp b/js/src/jsregexp.cpp index 91a41e49da76..960593e235a1 100644 --- a/js/src/jsregexp.cpp +++ b/js/src/jsregexp.cpp @@ -3166,10 +3166,6 @@ CompileRegExpToNative(JSContext* cx, JSRegExp* re, Fragment* fragment) goto out; } rv = rc.compile(cx); - static int fail = 0; // TODO: remove - if (!rv) - ++fail; - debug_only_printf(LC_TMRegexp, "## Fail? %d, Total %d\n", (int)!rv, fail); out: JS_ARENA_RELEASE(&cx->tempPool, mark); return rv; From 1d5548f39bd0f52f865c54f4803a2efcfc80e960 Mon Sep 17 00:00:00 2001 From: "wes@page.ca" Date: Mon, 27 Jul 2009 12:40:59 +0800 Subject: [PATCH 19/61] Bug 504594 - Addresses in nanojit-debug output are wrong on SPARC. r=graydon. --- js/src/nanojit/NativeSparc.h | 184 +++++++++++++++++------------------ 1 file changed, 92 insertions(+), 92 deletions(-) diff --git a/js/src/nanojit/NativeSparc.h b/js/src/nanojit/NativeSparc.h index 13e0b8dee323..7c7b43866b90 100644 --- a/js/src/nanojit/NativeSparc.h +++ b/js/src/nanojit/NativeSparc.h @@ -214,7 +214,7 @@ namespace nanojit int offset = (c->_address) - ((int)_nIns) + 4; \ int i = 0x40000000 | ((offset >> 2) & 0x3FFFFFFF); \ IMM32(i); \ - verbose_only(asm_output("call %s",(c->_name));) \ + asm_output("call %s",(c->_name)); \ } while (0) #define Format_2_1(rd, op2, imm22) do { \ @@ -292,548 +292,548 @@ namespace nanojit #define ADDCC(rs1, rs2, rd) \ do { \ - asm_output("addcc %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ Format_3_1(2, rd, 0x10, rs1, 0, rs2); \ + asm_output("addcc %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ } while (0) #define ADD(rs1, rs2, rd) \ do { \ - asm_output("add %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ Format_3_1(2, rd, 0, rs1, 0, rs2); \ + asm_output("add %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ } while (0) #define AND(rs1, rs2, rd) \ do { \ - asm_output("and %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ Format_3_1(2, rd, 0x1, rs1, 0, rs2); \ + asm_output("and %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ } while (0) #define BA(a, dsp22) \ do { \ - asm_output("ba %p", _nIns + dsp22 - 1); \ Format_2_2(a, 0x8, 0x2, dsp22); \ + asm_output("ba %p", _nIns + dsp22 - 1); \ } while (0) #define BE(a, dsp22) \ do { \ - asm_output("be %p", _nIns + dsp22 - 1); \ Format_2_2(a, 0x1, 0x2, dsp22); \ + asm_output("be %p", _nIns + dsp22 - 1); \ } while (0) #define BG(a, dsp22) \ do { \ - asm_output("bg %p", _nIns + dsp22 - 1); \ Format_2_2(a, 0xA, 0x2, dsp22); \ + asm_output("bg %p", _nIns + dsp22 - 1); \ } while (0) #define BGU(a, dsp22) \ do { \ - asm_output("bgu %p", _nIns + dsp22 - 1); \ Format_2_2(a, 0xC, 0x2, dsp22); \ + asm_output("bgu %p", _nIns + dsp22 - 1); \ } while (0) #define BGE(a, dsp22) \ do { \ - asm_output("bge %p", _nIns + dsp22 - 1); \ Format_2_2(a, 0xB, 0x2, dsp22); \ + asm_output("bge %p", _nIns + dsp22 - 1); \ } while (0) #define BL(a, dsp22) \ do { \ - asm_output("bl %p", _nIns + dsp22 - 1); \ Format_2_2(a, 0x3, 0x2, dsp22); \ + asm_output("bl %p", _nIns + dsp22 - 1); \ } while (0) #define BLE(a, dsp22) \ do { \ - asm_output("ble %p", _nIns + dsp22 - 1); \ Format_2_2(a, 0x2, 0x2, dsp22); \ + asm_output("ble %p", _nIns + dsp22 - 1); \ } while (0) #define BLEU(a, dsp22) \ do { \ - asm_output("bleu %p", _nIns + dsp22 - 1); \ Format_2_2(a, 0x4, 0x2, dsp22); \ + asm_output("bleu %p", _nIns + dsp22 - 1); \ } while (0) #define BCC(a, dsp22) \ do { \ - asm_output("bcc %p", _nIns + dsp22 - 1); \ Format_2_2(a, 0xd, 0x2, dsp22); \ + asm_output("bcc %p", _nIns + dsp22 - 1); \ } while (0) #define BCS(a, dsp22) \ do { \ - asm_output("bcs %p", _nIns + dsp22 - 1); \ Format_2_2(a, 0x5, 0x2, dsp22); \ + asm_output("bcs %p", _nIns + dsp22 - 1); \ } while (0) #define BVC(a, dsp22) \ do { \ - asm_output("bvc %p", _nIns + dsp22 - 1); \ Format_2_2(a, 0xf, 0x2, dsp22); \ + asm_output("bvc %p", _nIns + dsp22 - 1); \ } while (0) #define BVS(a, dsp22) \ do { \ - asm_output("bvc %p", _nIns + dsp22 - 1); \ Format_2_2(a, 0x7, 0x2, dsp22); \ + asm_output("bvc %p", _nIns + dsp22 - 1); \ } while (0) #define BNE(a, dsp22) \ do { \ - asm_output("bne %p", _nIns + dsp22 - 1); \ Format_2_2(a, 0x9, 0x2, dsp22); \ + asm_output("bne %p", _nIns + dsp22 - 1); \ } while (0) #define FABSS(rs2, rd) \ do { \ - asm_output("fabs %s, %s", gpn(rs2+32), gpn(rd+32)); \ Format_3_8(2, rd, 0x34, 0, 0x9, rs2); \ + asm_output("fabs %s, %s", gpn(rs2+32), gpn(rd+32)); \ } while (0) #define FADDD(rs1, rs2, rd) \ do { \ - asm_output("faddd %s, %s, %s", gpn(rs1+32), gpn(rs2+32), gpn(rd+32)); \ Format_3_8(2, rd, 0x34, rs1, 0x42, rs2); \ + asm_output("faddd %s, %s, %s", gpn(rs1+32), gpn(rs2+32), gpn(rd+32)); \ } while (0) #define FBE(a, dsp22) \ do { \ - asm_output("fbe %p", _nIns + dsp22 - 1); \ Format_2_2(a, 0x9, 0x6, dsp22); \ + asm_output("fbe %p", _nIns + dsp22 - 1); \ } while(0) #define FBNE(a, dsp22) \ do { \ - asm_output("fbne %p", _nIns + dsp22 - 1); \ Format_2_2(a, 0x1, 0x6, dsp22); \ + asm_output("fbne %p", _nIns + dsp22 - 1); \ } while(0) #define FBUE(a, dsp22) \ do { \ - asm_output("fbue %p", _nIns + dsp22 - 1); \ Format_2_2(a, 0xA, 0x6, dsp22); \ + asm_output("fbue %p", _nIns + dsp22 - 1); \ } while(0) #define FBG(a, dsp22) \ do { \ - asm_output("fng %p", _nIns + dsp22 - 1); \ Format_2_2(a, 0x6, 0x6, dsp22); \ + asm_output("fng %p", _nIns + dsp22 - 1); \ } while(0) #define FBUG(a, dsp22) \ do { \ - asm_output("fbug %p", _nIns + dsp22 - 1); \ Format_2_2(a, 0x5, 0x6, dsp22); \ + asm_output("fbug %p", _nIns + dsp22 - 1); \ } while(0) #define FBGE(a, dsp22) \ do { \ - asm_output("fbge %p", _nIns + dsp22 - 1); \ Format_2_2(a, 0xB, 0x6, dsp22); \ + asm_output("fbge %p", _nIns + dsp22 - 1); \ } while(0) #define FBUGE(a, dsp22) \ do { \ - asm_output("fbuge %p", _nIns + dsp22 - 1); \ Format_2_2(a, 0xC, 0x6, dsp22); \ + asm_output("fbuge %p", _nIns + dsp22 - 1); \ } while(0) #define FBL(a, dsp22) \ do { \ - asm_output("fbl %p", _nIns + dsp22 - 1); \ Format_2_2(a, 0x4, 0x6, dsp22); \ + asm_output("fbl %p", _nIns + dsp22 - 1); \ } while(0) #define FBLE(a, dsp22) \ do { \ - asm_output("fble %p", _nIns + dsp22 - 1); \ Format_2_2(a, 0xD, 0x6, dsp22); \ + asm_output("fble %p", _nIns + dsp22 - 1); \ } while(0) #define FCMPD(rs1, rs2) \ do { \ - asm_output("fcmpd %s, %s", gpn(rs1+32), gpn(rs2+32)); \ Format_3_9(2, 0, 0, 0x35, rs1, 0x52, rs2); \ + asm_output("fcmpd %s, %s", gpn(rs1+32), gpn(rs2+32)); \ } while (0) #define FSUBD(rs1, rs2, rd) \ do { \ - asm_output("fsubd %s, %s, %s", gpn(rs1+32), gpn(rs2+32), gpn(rd+32)); \ Format_3_8(2, rd, 0x34, rs1, 0x46, rs2); \ + asm_output("fsubd %s, %s, %s", gpn(rs1+32), gpn(rs2+32), gpn(rd+32)); \ } while (0) #define FMULD(rs1, rs2, rd) \ do { \ - asm_output("fmuld %s, %s, %s", gpn(rs1+32), gpn(rs2+32), gpn(rd+32)); \ Format_3_8(2, rd, 0x34, rs1, 0x4a, rs2); \ + asm_output("fmuld %s, %s, %s", gpn(rs1+32), gpn(rs2+32), gpn(rd+32)); \ } while (0) #define FDIVD(rs1, rs2, rd) \ do { \ - asm_output("fdivd %s, %s, %s", gpn(rs1+32), gpn(rs2+32), gpn(rd+32)); \ Format_3_8(2, rd, 0x34, rs1, 0x4e, rs2); \ + asm_output("fdivd %s, %s, %s", gpn(rs1+32), gpn(rs2+32), gpn(rd+32)); \ } while (0) #define FMOVD(rs2, rd) \ do { \ - asm_output("fmovd %s, %s", gpn(rs2+32), gpn(rd+32)); \ Format_3_8(2, rd, 0x34, 0, 0x2, rs2); \ + asm_output("fmovd %s, %s", gpn(rs2+32), gpn(rd+32)); \ } while (0) #define FNEGD(rs2, rd) \ do { \ - asm_output("fnegd %s, %s", gpn(rs2+32), gpn(rd+32)); \ Format_3_8(2, rd, 0x34, 0, 0x6, rs2); \ + asm_output("fnegd %s, %s", gpn(rs2+32), gpn(rd+32)); \ } while (0) #define FITOD(rs2, rd) \ do { \ - asm_output("fitod %s, %s", gpn(rs2+32), gpn(rd+32)); \ Format_3_8(2, rd, 0x34, 0, 0xc8, rs2); \ + asm_output("fitod %s, %s", gpn(rs2+32), gpn(rd+32)); \ } while (0) #define JMPL(rs1, rs2, rd) \ do { \ - asm_output("jmpl [%s + %s]", gpn(rs1), gpn(rs2)); \ Format_3_1(2, rd, 0x38, rs1, 0, rs2); \ + asm_output("jmpl [%s + %s]", gpn(rs1), gpn(rs2)); \ } while (0) #define JMPLI(rs1, simm13, rd) \ do { \ - asm_output("jmpl [%s + %d]", gpn(rs1), simm13); \ Format_3_1I(2, rd, 0x38, rs1, simm13); \ + asm_output("jmpl [%s + %d]", gpn(rs1), simm13); \ } while (0) #define LDF(rs1, rs2, rd) \ do { \ - asm_output("ld [%s + %s], %s", gpn(rs1), gpn(rs2), gpn(rd+32)); \ Format_3_1(3, rd, 0x20, rs1, 0, rs2); \ + asm_output("ld [%s + %s], %s", gpn(rs1), gpn(rs2), gpn(rd+32)); \ } while (0) #define LDFI(rs1, simm13, rd) \ do { \ - asm_output("ld [%s + %d], %s", gpn(rs1), simm13, gpn(rd+32)); \ Format_3_1I(3, rd, 0x20, rs1, simm13); \ + asm_output("ld [%s + %d], %s", gpn(rs1), simm13, gpn(rd+32)); \ } while (0) #define LDUB(rs1, rs2, rd) \ do { \ - asm_output("ld [%s + %s], %s", gpn(rs1), gpn(rs2), gpn(rd)); \ Format_3_1(3, rd, 0x1, rs1, 0, rs2); \ + asm_output("ld [%s + %s], %s", gpn(rs1), gpn(rs2), gpn(rd)); \ } while (0) #define LDUBI(rs1, simm13, rd) \ do { \ - asm_output("ld [%s + %d], %s", gpn(rs1), simm13, gpn(rd)); \ Format_3_1I(3, rd, 0x1, rs1, simm13); \ + asm_output("ld [%s + %d], %s", gpn(rs1), simm13, gpn(rd)); \ } while (0) #define LDUH(rs1, rs2, rd) \ do { \ - asm_output("ld [%s + %s], %s", gpn(rs1), gpn(rs2), gpn(rd)); \ Format_3_1(3, rd, 0x2, rs1, 0, rs2); \ + asm_output("ld [%s + %s], %s", gpn(rs1), gpn(rs2), gpn(rd)); \ } while (0) #define LDUHI(rs1, simm13, rd) \ do { \ - asm_output("ld [%s + %d], %s", gpn(rs1), simm13, gpn(rd)); \ Format_3_1I(3, rd, 0x2, rs1, simm13); \ + asm_output("ld [%s + %d], %s", gpn(rs1), simm13, gpn(rd)); \ } while (0) #define LDSW(rs1, rs2, rd) \ do { \ - asm_output("ld [%s + %s], %s", gpn(rs1), gpn(rs2), gpn(rd)); \ Format_3_1(3, rd, 0x8, rs1, 0, rs2); \ + asm_output("ld [%s + %s], %s", gpn(rs1), gpn(rs2), gpn(rd)); \ } while (0) #define LDSWI(rs1, simm13, rd) \ do { \ - asm_output("ld [%s + %d], %s", gpn(rs1), simm13, gpn(rd)); \ Format_3_1I(3, rd, 0x8, rs1, simm13); \ + asm_output("ld [%s + %d], %s", gpn(rs1), simm13, gpn(rd)); \ } while (0) #define MOVE(rs, cc2, cc1, cc0, rd) \ do { \ - asm_output("move %s, %s", gpn(rs), gpn(rd)); \ Format_4_2(rd, 0x2c, cc2, 1, cc1, cc0, rs); \ + asm_output("move %s, %s", gpn(rs), gpn(rd)); \ } while (0) #define MOVNE(rs, cc2, cc1, cc0, rd) \ do { \ - asm_output("movne %s, %s", gpn(rs), gpn(rd)); \ Format_4_2(rd, 0x2c, cc2, 9, cc1, cc0, rs); \ + asm_output("movne %s, %s", gpn(rs), gpn(rd)); \ } while (0) #define MOVL(rs, cc2, cc1, cc0, rd) \ do { \ - asm_output("movl %s, %s", gpn(rs), gpn(rd)); \ Format_4_2(rd, 0x2c, cc2, 3, cc1, cc0, rs); \ + asm_output("movl %s, %s", gpn(rs), gpn(rd)); \ } while (0) #define MOVLE(rs, cc2, cc1, cc0, rd) \ do { \ - asm_output("movle %s, %s", gpn(rs), gpn(rd)); \ Format_4_2(rd, 0x2c, cc2, 2, cc1, cc0, rs); \ + asm_output("movle %s, %s", gpn(rs), gpn(rd)); \ } while (0) #define MOVG(rs, cc2, cc1, cc0, rd) \ do { \ - asm_output("movg %s, %s", gpn(rs), gpn(rd)); \ Format_4_2(rd, 0x2c, cc2, 0xa, cc1, cc0, rs); \ + asm_output("movg %s, %s", gpn(rs), gpn(rd)); \ } while (0) #define MOVGE(rs, cc2, cc1, cc0, rd) \ do { \ - asm_output("movge %s, %s", gpn(rs), gpn(rd)); \ Format_4_2(rd, 0x2c, cc2, 0xb, cc1, cc0, rs); \ + asm_output("movge %s, %s", gpn(rs), gpn(rd)); \ } while (0) #define MOVCS(rs, cc2, cc1, cc0, rd) \ do { \ - asm_output("movcs %s, %s", gpn(rs), gpn(rd)); \ Format_4_2(rd, 0x2c, cc2, 5, cc1, cc0, rs); \ + asm_output("movcs %s, %s", gpn(rs), gpn(rd)); \ } while (0) #define MOVLEU(rs, cc2, cc1, cc0, rd) \ do { \ - asm_output("movleu %s, %s", gpn(rs), gpn(rd)); \ Format_4_2(rd, 0x2c, cc2, 4, cc1, cc0, rs); \ + asm_output("movleu %s, %s", gpn(rs), gpn(rd)); \ } while (0) #define MOVGU(rs, cc2, cc1, cc0, rd) \ do { \ - asm_output("movgu %s, %s", gpn(rs), gpn(rd)); \ Format_4_2(rd, 0x2c, cc2, 0xc, cc1, cc0, rs); \ + asm_output("movgu %s, %s", gpn(rs), gpn(rd)); \ } while (0) #define MOVCC(rs, cc2, cc1, cc0, rd) \ do { \ - asm_output("movcc %s, %s", gpn(rs), gpn(rd)); \ Format_4_2(rd, 0x2c, cc2, 0xd, cc1, cc0, rs); \ + asm_output("movcc %s, %s", gpn(rs), gpn(rd)); \ } while (0) #define MOVVC(rs, cc2, cc1, cc0, rd) \ do { \ - asm_output("movvc %s, %s", gpn(rs), gpn(rd)); \ Format_4_2(rd, 0x2c, cc2, 0xf, cc1, cc0, rs); \ + asm_output("movvc %s, %s", gpn(rs), gpn(rd)); \ } while (0) #define MOVEI(simm11, cc2, cc1, cc0, rd) \ do { \ - asm_output("move %d, %s", simm11, gpn(rd)); \ Format_4_2I(rd, 0x2c, cc2, 1, cc1, cc0, simm11); \ + asm_output("move %d, %s", simm11, gpn(rd)); \ } while (0) #define MOVFEI(simm11, cc2, cc1, cc0, rd) \ do { \ - asm_output("move %d, %s", simm11, gpn(rd)); \ Format_4_2I(rd, 0x2c, cc2, 9, cc1, cc0, simm11); \ + asm_output("move %d, %s", simm11, gpn(rd)); \ } while (0) #define MOVNEI(simm11, cc2, cc1, cc0, rd) \ do { \ - asm_output("move %d, %s", simm11, gpn(rd)); \ Format_4_2I(rd, 0x2c, cc2, 9, cc1, cc0, simm11); \ + asm_output("move %d, %s", simm11, gpn(rd)); \ } while (0) #define MOVLI(simm11, cc2, cc1, cc0, rd) \ do { \ - asm_output("move %d, %s", simm11, gpn(rd)); \ Format_4_2I(rd, 0x2c, cc2, 3, cc1, cc0, simm11); \ + asm_output("move %d, %s", simm11, gpn(rd)); \ } while (0) #define MOVFLI(simm11, cc2, cc1, cc0, rd) \ do { \ - asm_output("move %d, %s", simm11, gpn(rd)); \ Format_4_2I(rd, 0x2c, cc2, 4, cc1, cc0, simm11); \ + asm_output("move %d, %s", simm11, gpn(rd)); \ } while (0) #define MOVLEI(simm11, cc2, cc1, cc0, rd) \ do { \ - asm_output("movle %d, %s", simm11, gpn(rd)); \ Format_4_2I(rd, 0x2c, cc2, 2, cc1, cc0, simm11); \ + asm_output("movle %d, %s", simm11, gpn(rd)); \ } while (0) #define MOVFLEI(simm11, cc2, cc1, cc0, rd) \ do { \ - asm_output("movle %d, %s", simm11, gpn(rd)); \ Format_4_2I(rd, 0x2c, cc2, 0xd, cc1, cc0, simm11); \ + asm_output("movle %d, %s", simm11, gpn(rd)); \ } while (0) #define MOVGI(simm11, cc2, cc1, cc0, rd) \ do { \ - asm_output("movg %d, %s", simm11, gpn(rd)); \ Format_4_2I(rd, 0x2c, cc2, 0xa, cc1, cc0, simm11); \ + asm_output("movg %d, %s", simm11, gpn(rd)); \ } while (0) #define MOVFGI(simm11, cc2, cc1, cc0, rd) \ do { \ - asm_output("movg %d, %s", simm11, gpn(rd)); \ Format_4_2I(rd, 0x2c, cc2, 6, cc1, cc0, simm11); \ + asm_output("movg %d, %s", simm11, gpn(rd)); \ } while (0) #define MOVGEI(simm11, cc2, cc1, cc0, rd) \ do { \ - asm_output("movge %d, %s", simm11, gpn(rd)); \ Format_4_2I(rd, 0x2c, cc2, 0xb, cc1, cc0, simm11); \ + asm_output("movge %d, %s", simm11, gpn(rd)); \ } while (0) #define MOVFGEI(simm11, cc2, cc1, cc0, rd) \ do { \ - asm_output("movge %d, %s", simm11, gpn(rd)); \ Format_4_2I(rd, 0x2c, cc2, 0xb, cc1, cc0, simm11); \ + asm_output("movge %d, %s", simm11, gpn(rd)); \ } while (0) #define MOVLEUI(simm11, cc2, cc1, cc0, rd) \ do { \ - asm_output("movleu %d, %s", simm11, gpn(rd)); \ Format_4_2I(rd, 0x2c, cc2, 4, cc1, cc0, simm11); \ + asm_output("movleu %d, %s", simm11, gpn(rd)); \ } while (0) #define MOVGUI(simm11, cc2, cc1, cc0, rd) \ do { \ - asm_output("movgu %d, %s", simm11, gpn(rd)); \ Format_4_2I(rd, 0x2c, cc2, 0xc, cc1, cc0, simm11); \ + asm_output("movgu %d, %s", simm11, gpn(rd)); \ } while (0) #define MOVCCI(simm11, cc2, cc1, cc0, rd) \ do { \ - asm_output("movcc %d, %s", simm11, gpn(rd)); \ Format_4_2I(rd, 0x2c, cc2, 0xd, cc1, cc0, simm11); \ + asm_output("movcc %d, %s", simm11, gpn(rd)); \ } while (0) #define MOVVSI(simm11, cc2, cc1, cc0, rd) \ do { \ - asm_output("movvs %d, %s", simm11, gpn(rd)); \ Format_4_2I(rd, 0x2c, cc2, 7, cc1, cc0, simm11); \ + asm_output("movvs %d, %s", simm11, gpn(rd)); \ } while (0) #define MULX(rs1, rs2, rd) \ do { \ - asm_output("mul %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ Format_3_1(2, rd, 0x9, rs1, 0, rs2); \ + asm_output("mul %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ } while (0) #define NOP() \ do { \ - asm_output("nop"); \ Format_2_1(0, 0x4, 0); \ + asm_output("nop"); \ } while (0) #define ORI(rs1, simm13, rd) \ do { \ - asm_output("or %s, %d, %s", gpn(rs1), simm13, gpn(rd)); \ Format_3_1I(2, rd, 0x2, rs1, simm13); \ + asm_output("or %s, %d, %s", gpn(rs1), simm13, gpn(rd)); \ } while (0) #define OR(rs1, rs2, rd) \ do { \ - asm_output("or %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ Format_3_1(2, rd, 0x2, rs1, 0, rs2); \ + asm_output("or %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ } while (0) #define ORN(rs1, rs2, rd) \ do { \ - asm_output("orn %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ Format_3_1(2, rd, 0x6, rs1, 0, rs2); \ + asm_output("orn %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ } while (0) #define ANDCC(rs1, rs2, rd) \ do { \ - asm_output("andcc %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ Format_3_1(2, rd, 0x11, rs1, 0, rs2); \ + asm_output("andcc %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ } while (0) #define RESTORE(rs1, rs2, rd) \ do { \ - asm_output("restore"); \ Format_3_1(2, rd, 0x3D, rs1, 0, rs2); \ + asm_output("restore"); \ } while (0) #define SAVEI(rs1, simm13, rd) \ do { \ - asm_output("save %s, %d, %s", gpn(rs1), simm13, gpn(rd)); \ Format_3_1I(2, rd, 0x3C, rs1, simm13); \ + asm_output("save %s, %d, %s", gpn(rs1), simm13, gpn(rd)); \ } while (0) #define SAVE(rs1, rs2, rd) \ do { \ - asm_output("save %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ Format_3_1(2, rd, 0x3C, rs1, 0, rs2); \ + asm_output("save %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ } while (0) #define SETHI(imm22, rd) \ do { \ - asm_output("sethi %p, %s", imm22, gpn(rd)); \ Format_2_1(rd, 0x4, (imm22 >> 10)); \ + asm_output("sethi %p, %s", imm22, gpn(rd)); \ } while (0) #define SLL(rs1, rs2, rd) \ do { \ - asm_output("sll %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ Format_3_5(2, rd, 0x25, rs1, 0, rs2); \ + asm_output("sll %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ } while (0) #define SRA(rs1, rs2, rd) \ do { \ - asm_output("sra %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ Format_3_5(2, rd, 0x27, rs1, 0, rs2); \ + asm_output("sra %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ } while (0) #define SRL(rs1, rs2, rd) \ do { \ - asm_output("srl %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ Format_3_5(2, rd, 0x26, rs1, 0, rs2); \ + asm_output("srl %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ } while (0) #define STF(rd, rs1, rs2) \ do { \ - asm_output("st %s, [%s + %s]", gpn(rd+32), gpn(rs1), gpn(rs2)); \ Format_3_1(3, rd, 0x24, rs1, 0, rs2); \ + asm_output("st %s, [%s + %s]", gpn(rd+32), gpn(rs1), gpn(rs2)); \ } while (0) #define STFI(rd, simm13, rs1) \ do { \ - asm_output("st %s, [%s + %d]", gpn(rd+32), gpn(rs1), simm13); \ Format_3_1I(3, rd, 0x24, rs1, simm13); \ + asm_output("st %s, [%s + %d]", gpn(rd+32), gpn(rs1), simm13); \ } while (0) #define STW(rd, rs2, rs1) \ do { \ - asm_output("st %s, [%s + %s]", gpn(rd), gpn(rs1), gpn(rs2)); \ Format_3_1(3, rd, 0x4, rs1, 0, rs2); \ + asm_output("st %s, [%s + %s]", gpn(rd), gpn(rs1), gpn(rs2)); \ } while (0) #define STWI(rd, simm13, rs1) \ do { \ - asm_output("st %s, [%s + %d]", gpn(rd), gpn(rs1), simm13); \ Format_3_1I(3, rd, 0x4, rs1, simm13); \ + asm_output("st %s, [%s + %d]", gpn(rd), gpn(rs1), simm13); \ } while (0) #define SUBCC(rs1, rs2, rd) \ do { \ - asm_output("subcc %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ Format_3_1(2, rd, 0x14, rs1, 0, rs2); \ + asm_output("subcc %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ } while (0) #define SUB(rs1, rs2, rd) \ do { \ - asm_output("sub %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ Format_3_1(2, rd, 0x4, rs1, 0, rs2); \ + asm_output("sub %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ } while (0) #define SUBI(rs1, simm13, rd) \ do { \ - asm_output("sub %s, %d, %s", gpn(rs1), simm13, gpn(rd)); \ Format_3_1I(2, rd, 0x4, rs1, simm13); \ + asm_output("sub %s, %d, %s", gpn(rs1), simm13, gpn(rd)); \ } while (0) #define XOR(rs1, rs2, rd) \ do { \ - asm_output("xor %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ Format_3_1(2, rd, 0x3, rs1, 0, rs2); \ + asm_output("xor %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ } while (0) // Returns true if imm below 13-bit unsigned immediate) From 1f1e1452e4a60c55cef0bca7f558b4a2488f6080 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Fri, 17 Jul 2009 00:48:39 -0500 Subject: [PATCH 20/61] Bug 505249 - lirasm - Style cleanup and new tokenizer. r=graydon. --- js/src/lirasm/lirasm.cpp | 1067 ++++++++++++++++++++------------------ 1 file changed, 575 insertions(+), 492 deletions(-) diff --git a/js/src/lirasm/lirasm.cpp b/js/src/lirasm/lirasm.cpp index 060460898f68..f3c22fc77ed5 100644 --- a/js/src/lirasm/lirasm.cpp +++ b/js/src/lirasm/lirasm.cpp @@ -44,7 +44,6 @@ #include #include #include -#include #ifdef AVMPLUS_UNIX #include @@ -54,6 +53,8 @@ #include #include +#include +#include #include "nanojit/nanojit.h" #include "jstracer.h" @@ -106,6 +107,88 @@ const int PTRRET = #endif ; +enum LirTokenType { + NAME, NUMBER, PUNCT, NEWLINE +}; + +struct LirToken { + LirTokenType type; + string data; + int lineno; +}; + +inline bool +startsWith(const string &s, const string &prefix) +{ + return s.size() >= prefix.size() && s.compare(0, prefix.length(), prefix) == 0; +} + +// LIR files must be ASCII, for simplicity. +class LirTokenStream { +public: + LirTokenStream(istream &in) : mIn(in), mLineno(0) {} + + bool get(LirToken &token) { + if (mLine.empty()) { + if (!getline(mIn, mLine)) + return false; + mLine += '\n'; + mLineno++; + } + mLine.erase(0, mLine.find_first_not_of(" \t\v\r")); + char c = mLine[0]; + size_t e = mLine.find_first_not_of("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$.+-"); + if (startsWith(mLine, "->")) { + mLine.erase(0, 2); + token.type = PUNCT; + token.data = "->"; + } else if (e > 0) { + string s = mLine.substr(0, e); + mLine.erase(0, e); + if (e > 1 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) + token.type = NUMBER; + else if (isdigit(s[0]) || (e > 1 && s[0] == '.' && isdigit(s[1]))) + token.type = NUMBER; + else + token.type = NAME; + token.data = s; + } else if (strchr(":,=[]()", c)) { + token.type = PUNCT; + token.data = c; + mLine.erase(0, 1); + } else if (c == ';' || c == '\n') { + token.type = NEWLINE; + token.data.clear(); + mLine.clear(); + } else { + cerr << mLineno << ": error: Unrecognized character in file." << endl; + return false; + } + + token.lineno = mLineno; + return true; + } + + bool eat(LirTokenType type, const char *exact = NULL) { + LirToken token; + return (get(token) && token.type == type && (exact == NULL || token.data == exact)); + } + + bool getName(string &name) { + LirToken t; + if (get(t) && t.type == NAME) { + name = t.data; + return true; + } + return false; + } + +private: + istream &mIn; + string mLine; + int mLineno; +}; + class LirasmFragment { public: union { @@ -122,23 +205,46 @@ typedef map Fragments; class Lirasm { public: + Lirasm(bool verbose); + ~Lirasm(); + + void assemble(istream &in); + void lookupFunction(const string &name, CallInfo *&ci); + Fragmento *mFragmento; LirBuffer *mLirbuf; LogControl mLogc; bool mVerbose; - avmplus::AvmCore s_core; Fragments mFragments; - vector mCallInfos; + map > mOpMap; - Lirasm(bool verbose); - ~Lirasm(); + void bad(const string &msg) { + cerr << "error: " << msg << endl; + exit(1); + } + +private: + void handlePatch(LirTokenStream &in); + + avmplus::AvmCore mCore; }; -class LirasmAssembler { +class FragmentAssembler { +public: + FragmentAssembler(Lirasm &parent, const string &fragmentName); + ~FragmentAssembler(); + + void assembleFragment(LirTokenStream &in, bool implied, const LirToken *firstToken); + private: + // Prohibit copying. + FragmentAssembler(const FragmentAssembler &); + FragmentAssembler & operator=(const FragmentAssembler &); + Lirasm *mParent; + const string mFragName; Fragment *mFragment; - string mFragName; + vector mCallInfos; map mLabels; LirWriter *mLir; LirBufWriter *mBufWriter; @@ -146,37 +252,26 @@ private: LirWriter *mExprFilter; LirWriter *mVerboseWriter; multimap mFwdJumps; - map > op_map; size_t mLineno; LOpcode mOpcode; size_t mOpcount; - bool mInFrag; - char mReturnTypeBits; vector mTokens; - void lookupFunction(const char*, CallInfo *&); + void tokenizeLine(LirTokenStream &in, LirToken &token); void need(size_t); - istream& read_and_tokenize_line(istream&); - void tokenize(string const &tok_sep); - LIns *ref(string const &); + LIns *ref(const string &); LIns *do_skip(size_t); - LIns *assemble_call(string &); + LIns *assemble_call(const string &); LIns *assemble_general(); LIns *assemble_guard(); LIns *assemble_jump(); LIns *assemble_load(); - void bad(string const &msg); - void beginFragment(); + void bad(const string &msg); + void extract_any_label(string &lab, char lab_delim); void endFragment(); - void extract_any_label(string &op, string &lab, char lab_delim); - void patch(); - -public: - LirasmAssembler(Lirasm &); - void assemble(istream &); }; Function functions[] = { @@ -186,66 +281,6 @@ Function functions[] = { FN(free, I32 | (PTRARG<<2)) }; -void -LirasmAssembler::lookupFunction(const char *name, CallInfo *&ci) -{ - const size_t nfuns = sizeof(functions) / sizeof(functions[0]); - for (size_t i = 0; i < nfuns; i++) - if (strcmp(name, functions[i].name) == 0) { - *ci = functions[i].callInfo; - return; - } - - Fragments::const_iterator func = mParent->mFragments.find(name); - if (func != mParent->mFragments.end()) { - if (func->second.mReturnType == RT_FLOAT) { - CallInfo target = {(uintptr_t) func->second.rfloat, ARGSIZE_F, 0, - 0, nanojit::ABI_FASTCALL, func->first.c_str()}; - *ci = target; - - } else { - CallInfo target = {(uintptr_t) func->second.rint, ARGSIZE_LO, 0, - 0, nanojit::ABI_FASTCALL, func->first.c_str()}; - *ci = target; - } - } else { - ci = NULL; - } -} - -istream & -LirasmAssembler::read_and_tokenize_line(istream &in) -{ - char buf[1024]; - string tok_sep(" \n\t"); - - mTokens.clear(); - - if (in.getline(buf,sizeof(buf))) { - ++mLineno; - string line(buf); - - size_t comment = line.find("//"); - if (comment != string::npos) - line.resize(comment); - - line += '\n'; - - size_t start = 0; - size_t end = 0; - while((start = line.find_first_not_of(tok_sep, end)) != string::npos && - (end = line.find_first_of(tok_sep, start)) != string::npos) { - string ss = line.substr(start, (end-start)); - if (ss == "=") { - mTokens[mTokens.size()-1] += ss; - continue; - } - mTokens.push_back(ss); - } - } - return in; -} - template out lexical_cast(in arg) { @@ -258,18 +293,19 @@ lexical_cast(in arg) } int32_t -imm(string const &s) +imm(const string &s) { stringstream tmp(s); int32_t ret; if ((s.find("0x") == 0 || s.find("0X") == 0) && - (tmp >> hex >> ret && tmp.eof())) + (tmp >> hex >> ret && tmp.eof())) { return ret; + } return lexical_cast(s); } uint64_t -quad(string const &s) +quad(const string &s) { stringstream tmp1(s), tmp2(s); union { @@ -292,223 +328,9 @@ pop_front(vector &vec) cerr << "pop_front of empty vector" << endl; exit(1); } - t tmp = vec[0]; - vec.erase(vec.begin()); - return tmp; -} - -void -LirasmAssembler::bad(string const &msg) -{ - cerr << "instruction " << mLineno << ": " << msg << endl; - exit(1); -} - -void -LirasmAssembler::need(size_t n) -{ - if (mTokens.size() != n) - bad("need " + lexical_cast(n) - + " tokens, have " + lexical_cast(mTokens.size())); -} - -LIns* -LirasmAssembler::ref(string const &lab) -{ - if (mLabels.find(lab) == mLabels.end()) - bad("unknown label '" + lab + "'"); - return mLabels.find(lab)->second; -} - -LIns* -LirasmAssembler::do_skip(size_t i) -{ - LIns *s = mLir->insSkip(i); - memset(s->payload(), 0xba, i); - return s; -} - -LIns* -LirasmAssembler::assemble_jump() -{ - LIns *target = NULL; - LIns *condition = NULL; - - if (mOpcode == LIR_j) { - need(1); - } else { - need(2); - string cond = pop_front(mTokens); - condition = ref(cond); - } - string name = pop_front(mTokens); - if (mLabels.find(name) != mLabels.end()) { - target = ref(name); - return mLir->insBranch(mOpcode, condition, target); - } else { - LIns *ins = mLir->insBranch(mOpcode, condition, target); - mFwdJumps.insert(make_pair(name, ins)); - return ins; - } -} - -LIns* -LirasmAssembler::assemble_load() -{ - // Support implicit immediate-as-second-operand modes - // since, unlike sti/stqi, no immediate-displacement - // load opcodes were defined in LIR. - need(2); - if (mTokens[1].find("0x") == 0 || - mTokens[1].find("0x") == 0 || - mTokens[1].find_first_of("0123456789") == 0) { - return mLir->insLoad(mOpcode, - ref(mTokens[0]), - imm(mTokens[1])); - } - bad("immediate offset required for load"); - return NULL; // not reached -} - -LIns* -LirasmAssembler::assemble_call(string &op) -{ - CallInfo *ci = new CallInfo(); - mParent->mCallInfos.push_back(ci); - LIns* args[MAXARGS]; - - // Assembler syntax for a call: - // - // call 0x1234 fastcall a b c - // - // requires at least 2 args, - // fn address immediate and ABI token. - - if (mTokens.size() < 2) - bad("need at least address and ABI code for " + op); - - string func = pop_front(mTokens); - string abi = pop_front(mTokens); - - AbiKind _abi; - if (abi == "fastcall") - _abi = ABI_FASTCALL; - else if (abi == "stdcall") - _abi = ABI_STDCALL; - else if (abi == "thiscall") - _abi = ABI_THISCALL; - else if (abi == "cdecl") - _abi = ABI_CDECL; - else - bad("call abi name '" + abi + "'"); - ci->_abi = _abi; - - if (mTokens.size() > MAXARGS) - bad("too many args to " + op); - - if (func.find("0x") == 0) { - ci->_address = imm(func); - - ci->_cse = 0; - ci->_fold = 0; - -#ifdef DEBUG - ci->_name = "fn"; -#endif - - } else { - lookupFunction(func.c_str(), ci); - if (ci == NULL) - bad("invalid function reference " + func); - if (_abi != ci->_abi) - bad("invalid calling convention for " + func); - } - - ci->_argtypes = 0; - - for (size_t i = 0; i < mTokens.size(); ++i) { - args[i] = ref(mTokens[mTokens.size() - (i+1)]); - ci->_argtypes |= args[i]->isQuad() ? ARGSIZE_F : ARGSIZE_LO; - ci->_argtypes <<= 2; - } - - // Select return type from opcode. - // FIXME: callh needs special treatment currently - // missing from here. - if (mOpcode == LIR_call) - ci->_argtypes |= ARGSIZE_LO; - else - ci->_argtypes |= ARGSIZE_F; - - return mLir->insCall(ci, args); -} - -LIns* -LirasmAssembler::assemble_guard() -{ - LIns *exitIns = do_skip(sizeof(LasmSideExit)); - LasmSideExit* exit = (LasmSideExit*) exitIns->payload(); - memset(exit, 0, sizeof(LasmSideExit)); - exit->from = mFragment; - exit->target = NULL; - exit->line = mLineno; - - LIns *guardRec = do_skip(sizeof(GuardRecord)); - GuardRecord *rec = (GuardRecord*) guardRec->payload(); - memset(rec, 0, sizeof(GuardRecord)); - rec->exit = exit; - exit->addGuard(rec); - - need(mOpcount); - - if (mOpcode != LIR_loop) - mReturnTypeBits |= RT_GUARD; - - LIns *ins_cond; - if (mOpcode == LIR_xt || mOpcode == LIR_xf) - ins_cond = ref(pop_front(mTokens)); - else - ins_cond = NULL; - - if (!mTokens.empty()) - bad("too many arguments"); - - return mLir->insGuard(mOpcode, ins_cond, guardRec); -} - -LIns* -LirasmAssembler::assemble_general() -{ - if (mOpcount == 0) { - // 0-ary ops may, or may not, have an immediate - // thing wedged in them; depends on the op. We - // are lax and set it if it's provided. - LIns *ins = mLir->ins0(mOpcode); - if (mTokens.size() > 0) { - assert(mTokens.size() == 1); - ins->initLInsI(mOpcode, imm(mTokens[0])); - } - return ins; - } else { - need(mOpcount); - if (mOpcount == 1) { - if (mOpcode == LIR_ret) - mReturnTypeBits |= RT_INT32; - if (mOpcode == LIR_fret) - mReturnTypeBits |= RT_FLOAT; - - return mLir->ins1(mOpcode, - ref(mTokens[0])); - } else if (mOpcount == 2) { - return mLir->ins2(mOpcode, - ref(mTokens[0]), - ref(mTokens[1])); - } else { - bad("too many operands"); - } - } - // Never get here. - return NULL; + t tmp = vec[0]; + vec.erase(vec.begin()); + return tmp; } void @@ -575,26 +397,8 @@ dump_srecords(ostream &out, Fragment *frag) } } -void -LirasmAssembler::extract_any_label(string &op, - string &lab, - char lab_delim) -{ - if (op.size() > 1 && - op[op.size()-1] == lab_delim && - !mTokens.empty()) { - - lab = op; - op = pop_front(mTokens); - lab.erase(lab.size()-1); - - if (mLabels.find(lab) != mLabels.end()) - bad("duplicate label"); - } -} - -void -LirasmAssembler::beginFragment() +FragmentAssembler::FragmentAssembler(Lirasm &parent, const string &fragmentName) + : mParent(&parent), mFragName(fragmentName) { mFragment = new (&gc) Fragment(NULL); mFragment->lirbuf = mParent->mLirbuf; @@ -615,24 +419,249 @@ LirasmAssembler::beginFragment() } #endif - mInFrag = true; mReturnTypeBits = 0; mLir->ins0(LIR_start); + + mLineno = 0; +} + +FragmentAssembler::~FragmentAssembler() +{ + delete mVerboseWriter; + delete mExprFilter; + delete mCseFilter; + delete mBufWriter; + + for (size_t i = 0; i < mCallInfos.size(); ++i) + delete mCallInfos[i]; } void -LirasmAssembler::endFragment() +FragmentAssembler::bad(const string &msg) { - mInFrag = false; + cerr << "instruction " << mLineno << ": " << msg << endl; + exit(1); +} - if (mReturnTypeBits == 0) +void +FragmentAssembler::need(size_t n) +{ + if (mTokens.size() != n) { + bad("need " + lexical_cast(n) + + " tokens, have " + lexical_cast(mTokens.size())); + } +} + +LIns * +FragmentAssembler::ref(const string &lab) +{ + if (mLabels.find(lab) == mLabels.end()) + bad("unknown label '" + lab + "'"); + return mLabels.find(lab)->second; +} + +LIns * +FragmentAssembler::do_skip(size_t i) +{ + LIns *s = mLir->insSkip(i); + memset(s->payload(), 0xba, i); + return s; +} + +LIns * +FragmentAssembler::assemble_jump() +{ + LIns *target = NULL; + LIns *condition = NULL; + + if (mOpcode == LIR_j) { + need(1); + } else { + need(2); + string cond = pop_front(mTokens); + condition = ref(cond); + } + string name = pop_front(mTokens); + if (mLabels.find(name) != mLabels.end()) { + target = ref(name); + return mLir->insBranch(mOpcode, condition, target); + } else { + LIns *ins = mLir->insBranch(mOpcode, condition, target); + mFwdJumps.insert(make_pair(name, ins)); + return ins; + } +} + +LIns * +FragmentAssembler::assemble_load() +{ + // Support implicit immediate-as-second-operand modes + // since, unlike sti/stqi, no immediate-displacement + // load opcodes were defined in LIR. + need(2); + if (mTokens[1].find("0x") == 0 || + mTokens[1].find("0x") == 0 || + mTokens[1].find_first_of("0123456789") == 0) { + return mLir->insLoad(mOpcode, + ref(mTokens[0]), + imm(mTokens[1])); + } + bad("immediate offset required for load"); + return NULL; // not reached +} + +LIns * +FragmentAssembler::assemble_call(const string &op) +{ + CallInfo *ci = new CallInfo(); + mCallInfos.push_back(ci); + LIns *args[MAXARGS]; + + // Assembler syntax for a call: + // + // call 0x1234 fastcall a b c + // + // requires at least 2 args, + // fn address immediate and ABI token. + + if (mTokens.size() < 2) + bad("need at least address and ABI code for " + op); + + string func = pop_front(mTokens); + string abi = pop_front(mTokens); + + AbiKind _abi; + if (abi == "fastcall") + _abi = ABI_FASTCALL; + else if (abi == "stdcall") + _abi = ABI_STDCALL; + else if (abi == "thiscall") + _abi = ABI_THISCALL; + else if (abi == "cdecl") + _abi = ABI_CDECL; + else + bad("call abi name '" + abi + "'"); + ci->_abi = _abi; + + if (mTokens.size() > MAXARGS) + bad("too many args to " + op); + + if (func.find("0x") == 0) { + ci->_address = imm(func); + + ci->_cse = 0; + ci->_fold = 0; + +#ifdef DEBUG + ci->_name = "fn"; +#endif + } else { + mParent->lookupFunction(func, ci); + if (ci == NULL) + bad("invalid function reference " + func); + if (_abi != ci->_abi) + bad("invalid calling convention for " + func); + } + + ci->_argtypes = 0; + + for (size_t i = 0; i < mTokens.size(); ++i) { + args[i] = ref(mTokens[mTokens.size() - (i+1)]); + ci->_argtypes |= args[i]->isQuad() ? ARGSIZE_F : ARGSIZE_LO; + ci->_argtypes <<= 2; + } + + // Select return type from opcode. + // FIXME: callh needs special treatment currently + // missing from here. + if (mOpcode == LIR_call) + ci->_argtypes |= ARGSIZE_LO; + else + ci->_argtypes |= ARGSIZE_F; + + return mLir->insCall(ci, args); +} + +LIns * +FragmentAssembler::assemble_guard() +{ + LIns *exitIns = do_skip(sizeof(LasmSideExit)); + LasmSideExit* exit = (LasmSideExit*) exitIns->payload(); + memset(exit, 0, sizeof(LasmSideExit)); + exit->from = mFragment; + exit->target = NULL; + exit->line = mLineno; + + LIns *guardRec = do_skip(sizeof(GuardRecord)); + GuardRecord *rec = (GuardRecord*) guardRec->payload(); + memset(rec, 0, sizeof(GuardRecord)); + rec->exit = exit; + exit->addGuard(rec); + + need(mOpcount); + + if (mOpcode != LIR_loop) + mReturnTypeBits |= RT_GUARD; + + LIns *ins_cond; + if (mOpcode == LIR_xt || mOpcode == LIR_xf) + ins_cond = ref(pop_front(mTokens)); + else + ins_cond = NULL; + + if (!mTokens.empty()) + bad("too many arguments"); + + return mLir->insGuard(mOpcode, ins_cond, guardRec); +} + +LIns * +FragmentAssembler::assemble_general() +{ + if (mOpcount == 0) { + // 0-ary ops may, or may not, have an immediate + // thing wedged in them; depends on the op. We + // are lax and set it if it's provided. + LIns *ins = mLir->ins0(mOpcode); + if (mTokens.size() > 0) { + assert(mTokens.size() == 1); + ins->initLInsI(mOpcode, imm(mTokens[0])); + } + return ins; + } else { + need(mOpcount); + if (mOpcount == 1) { + if (mOpcode == LIR_ret) + mReturnTypeBits |= RT_INT32; + if (mOpcode == LIR_fret) + mReturnTypeBits |= RT_FLOAT; + + return mLir->ins1(mOpcode, + ref(mTokens[0])); + } else if (mOpcount == 2) { + return mLir->ins2(mOpcode, + ref(mTokens[0]), + ref(mTokens[1])); + } else { + bad("too many operands"); + } + } + // Never get here. + return NULL; +} + +void +FragmentAssembler::endFragment() +{ + if (mReturnTypeBits == 0) { cerr << "warning: no return type in fragment '" << mFragName << "'" << endl; - if (mReturnTypeBits != RT_INT32 && mReturnTypeBits != RT_FLOAT - && mReturnTypeBits != RT_GUARD) + } + if (mReturnTypeBits != RT_INT32 && mReturnTypeBits != RT_FLOAT && + mReturnTypeBits != RT_GUARD) { cerr << "warning: multiple return types in fragment '" << mFragName << "'" << endl; - + } LIns *exitIns = do_skip(sizeof(SideExit)); SideExit* exit = (SideExit*) exitIns->payload(); memset(exit, 0, sizeof(SideExit)); @@ -645,15 +674,15 @@ LirasmAssembler::endFragment() if (mParent->mFragmento->assm()->error() != nanojit::None) { cerr << "error during assembly: "; switch (mParent->mFragmento->assm()->error()) { - case nanojit::OutOMem: cerr << "OutOMem"; break; - case nanojit::StackFull: cerr << "StackFull"; break; - case nanojit::RegionFull: cerr << "RegionFull"; break; - case nanojit::MaxLength: cerr << "MaxLength"; break; - case nanojit::MaxExit: cerr << "MaxExit"; break; - case nanojit::MaxXJump: cerr << "MaxXJump"; break; - case nanojit::UnknownPrim: cerr << "UnknownPrim"; break; - case nanojit::UnknownBranch: cerr << "UnknownBranch"; break; - case nanojit::None: cerr << "None"; break; + case nanojit::OutOMem: cerr << "OutOMem"; break; + case nanojit::StackFull: cerr << "StackFull"; break; + case nanojit::RegionFull: cerr << "RegionFull"; break; + case nanojit::MaxLength: cerr << "MaxLength"; break; + case nanojit::MaxExit: cerr << "MaxExit"; break; + case nanojit::MaxXJump: cerr << "MaxXJump"; break; + case nanojit::UnknownPrim: cerr << "UnknownPrim"; break; + case nanojit::UnknownBranch: cerr << "UnknownBranch"; break; + case nanojit::None: cerr << "None"; break; } cerr << endl; std::exit(1); @@ -663,170 +692,156 @@ LirasmAssembler::endFragment() f = &mParent->mFragments[mFragName]; switch (mReturnTypeBits) { - case RT_FLOAT: - default: - f->rfloat = reinterpret_cast(mFragment->code()); - f->mReturnType = RT_FLOAT; - break; - case RT_INT32: - f->rint = reinterpret_cast(mFragment->code()); - f->mReturnType = RT_INT32; - break; case RT_GUARD: f->rguard = reinterpret_cast(mFragment->code()); f->mReturnType = RT_GUARD; break; + case RT_FLOAT: + f->rfloat = reinterpret_cast(mFragment->code()); + f->mReturnType = RT_FLOAT; + break; + default: + f->rint = reinterpret_cast(mFragment->code()); + f->mReturnType = RT_INT32; + break; } - delete mVerboseWriter; - delete mExprFilter; - delete mCseFilter; - delete mBufWriter; - for (size_t i = 0; i < mParent->mCallInfos.size(); ++i) - delete mParent->mCallInfos[i]; - mParent->mCallInfos.clear(); - mParent->mFragments[mFragName].mLabels = mLabels; - mLabels.clear(); } void -LirasmAssembler::assemble(istream &in) +FragmentAssembler::tokenizeLine(LirTokenStream &in, LirToken &token) { -#define OPDEF(op, number, args, repkind) \ - op_map[#op] = make_pair(LIR_##op, args); -#define OPDEF64(op, number, args, repkind) \ - op_map[#op] = make_pair(LIR_##op, args); -#include "nanojit/LIRopcode.tbl" -#undef OPDEF -#undef OPDEF64 + mTokens.clear(); + mTokens.push_back(token.data); - op_map["alloc"] = op_map["ialloc"]; - op_map["param"] = op_map["iparam"]; + while (in.get(token)) { + if (token.type == NEWLINE) + break; + mTokens.push_back(token.data); + } +} - bool singleFrag = false; - bool first = true; - while(read_and_tokenize_line(in)) { +void +FragmentAssembler::extract_any_label(string &lab, char lab_delim) +{ + if (mTokens.size() > 2 && mTokens[1].size() == 1 && mTokens[1][0] == lab_delim) { + lab = pop_front(mTokens); + pop_front(mTokens); // remove punctuation - if (mParent->mLirbuf->outOMem()) { - cerr << "lirbuf out of memory" << endl; - exit(1); + if (mLabels.find(lab) != mLabels.end()) + bad("duplicate label"); + } +} + +void +FragmentAssembler::assembleFragment(LirTokenStream &in, bool implied, const LirToken *firstToken) +{ + LirToken token; + while (true) { + if (firstToken) { + token = *firstToken; + firstToken = NULL; + } else if (!in.get(token)) { + if (!implied) + bad("unexpected end of file in fragment '" + mFragName + "'"); + break; } - - if (mTokens.empty()) + if (token.type == NEWLINE) continue; + if (token.type != NAME) + bad("unexpected token '" + token.data + "'"); - string op = pop_front(mTokens); - - if (op == ".patch") { - tokenize("."); - patch(); - continue; + string op = token.data; + if (op == ".begin") + bad("nested fragments are not supported"); + if (op == ".end") { + if (implied) + bad(".end without .begin"); + if (!in.eat(NEWLINE)) + bad("extra junk after .end"); + break; } - if (!singleFrag) { - if (op == ".begin") { - if (mTokens.size() != 1) - bad("missing fragment name"); - if (mInFrag) - bad("nested fragments are not supported"); - - mFragName = pop_front(mTokens); - - beginFragment(); - first = false; - continue; - } else if (op == ".end") { - if (!mInFrag) - bad("expecting .begin before .end"); - if (!mTokens.empty()) - bad("too many tokens"); - endFragment(); - continue; - } - } - if (first) { - first = false; - singleFrag = true; - mFragName = "main"; - - beginFragment(); - } + mLineno = token.lineno; + tokenizeLine(in, token); string lab; LIns *ins = NULL; - extract_any_label(op, lab, ':'); + extract_any_label(lab, ':'); /* Save label and do any back-patching of deferred forward-jumps. */ if (!lab.empty()) { ins = mLir->ins0(LIR_label); - typedef multimap mulmap; + typedef multimap mulmap; typedef mulmap::const_iterator ci; - pair range = mFwdJumps.equal_range(lab); + pair range = mFwdJumps.equal_range(lab); for (ci i = range.first; i != range.second; ++i) { i->second->setTarget(ins); } mFwdJumps.erase(lab); lab.clear(); } - extract_any_label(op, lab, '='); + extract_any_label(lab, '='); - if (op_map.find(op) == op_map.end()) + assert(!mTokens.empty()); + op = pop_front(mTokens); + if (mParent->mOpMap.find(op) == mParent->mOpMap.end()) bad("unknown instruction '" + op + "'"); - pair entry = op_map[op]; + pair entry = mParent->mOpMap[op]; mOpcode = entry.first; mOpcount = entry.second; switch (mOpcode) { // A few special opcode cases. - case LIR_j: - case LIR_jt: - case LIR_jf: - case LIR_ji: + case LIR_j: + case LIR_jt: + case LIR_jf: + case LIR_ji: ins = assemble_jump(); break; - case LIR_int: + case LIR_int: need(1); ins = mLir->insImm(imm(mTokens[0])); break; - case LIR_quad: + case LIR_quad: need(1); ins = mLir->insImmq(quad(mTokens[0])); break; - case LIR_sti: - case LIR_stqi: + case LIR_sti: + case LIR_stqi: need(3); ins = mLir->insStorei(ref(mTokens[0]), ref(mTokens[1]), imm(mTokens[2])); break; - case LIR_ld: - case LIR_ldc: - case LIR_ldq: - case LIR_ldqc: - case LIR_ldcb: - case LIR_ldcs: + case LIR_ld: + case LIR_ldc: + case LIR_ldq: + case LIR_ldqc: + case LIR_ldcb: + case LIR_ldcs: ins = assemble_load(); break; - case LIR_iparam: + case LIR_iparam: need(2); ins = mLir->insParam(imm(mTokens[0]), imm(mTokens[1])); break; - case LIR_ialloc: + case LIR_ialloc: need(1); ins = mLir->insAlloc(imm(mTokens[0])); break; - case LIR_skip: + case LIR_skip: need(1); { int32_t count = imm(mTokens[0]); @@ -836,20 +851,21 @@ LirasmAssembler::assemble(istream &in) } break; - case LIR_xt: - case LIR_xf: - case LIR_x: - case LIR_xbarrier: - case LIR_loop: + case LIR_xt: + case LIR_xf: + case LIR_x: + case LIR_xbarrier: + case LIR_loop: ins = assemble_guard(); break; - case LIR_call: - case LIR_callh: - case LIR_fcall: + case LIR_call: + case LIR_callh: + case LIR_fcall: ins = assemble_call(op); break; - default: + + default: ins = assemble_general(); break; } @@ -857,47 +873,43 @@ LirasmAssembler::assemble(istream &in) assert(ins); if (!lab.empty()) mLabels.insert(make_pair(lab, ins)); - } - if (mInFrag && singleFrag) - endFragment(); - if (mInFrag) - bad("unexpected EOF"); - if (mParent->mLirbuf->outOMem()) { - cerr << "lirbuf out of memory" << endl; - exit(1); - } -} - -bool -has_flag(vector &args, string const &flag) -{ - for (vector::iterator i = args.begin(); - i != args.end(); ++i) { - if (*i == flag) { - args.erase(i); - return true; + if (mParent->mLirbuf->outOMem()) { + cerr << "lirbuf out of memory" << endl; + exit(1); } } - return false; + endFragment(); } - Lirasm::Lirasm(bool verbose) { mVerbose = verbose; nanojit::AvmCore::config.tree_opt = true; mLogc.lcbits = 0; - mFragmento = new (&gc) Fragmento(&s_core, &mLogc, 32); + mFragmento = new (&gc) Fragmento(&mCore, &mLogc, 32); mFragmento->labels = NULL; mLirbuf = new (&gc) LirBuffer(mFragmento); #ifdef DEBUG if (mVerbose) { mLogc.lcbits = LC_Assembly; - mFragmento->labels = new (&gc) LabelMap(&s_core); + mFragmento->labels = new (&gc) LabelMap(&mCore); mLirbuf->names = new (&gc) LirNameMap(&gc, mFragmento->labels); } #endif + + // Populate the mOpMap table. +#define OPDEF(op, number, args, repkind) \ + mOpMap[#op] = make_pair(LIR_##op, args); +#define OPDEF64(op, number, args, repkind) \ + mOpMap[#op] = make_pair(LIR_##op, args); +#include "nanojit/LIRopcode.tbl" +#undef OPDEF +#undef OPDEF64 + + // TODO - These should alias to the appropriate platform-specific LIR opcode. + mOpMap["alloc"] = mOpMap["ialloc"]; + mOpMap["param"] = mOpMap["iparam"]; } Lirasm::~Lirasm() @@ -912,49 +924,120 @@ Lirasm::~Lirasm() delete mFragmento; } -LirasmAssembler::LirasmAssembler(Lirasm &lasm) -{ - mParent = &lasm; - mInFrag = false; - mLineno = 0; -} - void -LirasmAssembler::tokenize(string const &tok_sep) +Lirasm::lookupFunction(const string &name, CallInfo *&ci) { - vector::iterator i; - for (i = mTokens.begin(); i < mTokens.end(); i++) - { - string line = *i; - size_t start = 0; - size_t end = 0; - while((start = line.find_first_not_of(tok_sep, end)) != string::npos && - (end = line.find_first_of(tok_sep, start)) != string::npos) { - const string ss = line.substr(start, (end-start)); - i->erase(start, end-start+1); - mTokens.insert(i++, ss); - mTokens.insert(i++, tok_sep); + const size_t nfuns = sizeof(functions) / sizeof(functions[0]); + for (size_t i = 0; i < nfuns; i++) { + if (name == functions[i].name) { + *ci = functions[i].callInfo; + return; } } + + Fragments::const_iterator func = mFragments.find(name); + if (func != mFragments.end()) { + if (func->second.mReturnType == RT_FLOAT) { + CallInfo target = {(uintptr_t) func->second.rfloat, ARGSIZE_F, 0, + 0, nanojit::ABI_FASTCALL, func->first.c_str()}; + *ci = target; + + } else { + CallInfo target = {(uintptr_t) func->second.rint, ARGSIZE_LO, 0, + 0, nanojit::ABI_FASTCALL, func->first.c_str()}; + *ci = target; + } + } else { + ci = NULL; + } } void -LirasmAssembler::patch() +Lirasm::assemble(istream &in) { - if (mTokens[1] != "." || mTokens[3] != "->") + LirTokenStream ts(in); + bool first = true; + + LirToken token; + while (ts.get(token)) { + if (mLirbuf->outOMem()) { + cerr << "lirbuf out of memory" << endl; + exit(1); + } + if (token.type == NEWLINE) + continue; + if (token.type != NAME) + bad("unexpected token '" + token.data + "'"); + + const string &op = token.data; + if (op == ".patch") { + handlePatch(ts); + } else if (op == ".begin") { + string name; + if (!ts.getName(name)) + bad("expected fragment name after .begin"); + if (!ts.eat(NEWLINE)) + bad("extra junk after .begin " + name); + + FragmentAssembler assembler(*this, name); + assembler.assembleFragment(ts, false, NULL); + first = false; + } else if (op == ".end") { + bad(".end without .begin"); + } else if (first) { + FragmentAssembler assembler(*this, "main"); + assembler.assembleFragment(ts, true, &token); + break; + } else { + bad("unexpected stray opcode '" + op + "'"); + } + } + + if (mLirbuf->outOMem()) { + cerr << "lirbuf out of memory" << endl; + exit(1); + } +} + +void +Lirasm::handlePatch(LirTokenStream &in) +{ + string src, fragName, guardName, destName; + + if (!in.getName(src) || !in.eat(PUNCT, "->") || !in.getName(destName)) bad("incorrect syntax"); + + // Break the src at '.'. This is awkward but the syntax looks nice. + size_t j = src.find('.'); + if (j == string::npos || j == 0 || j == src.size() - 1) + bad("incorrect syntax"); + fragName = src.substr(0, j); + guardName = src.substr(j + 1); + Fragments::iterator i; - if ((i=mParent->mFragments.find(mTokens[0])) == mParent->mFragments.end()) + if ((i=mFragments.find(fragName)) == mFragments.end()) bad("invalid fragment reference"); LirasmFragment *frag = &i->second; - if (frag->mLabels.find(mTokens[2]) == frag->mLabels.end()) + if (frag->mLabels.find(guardName) == frag->mLabels.end()) bad("invalid guard reference"); - LIns *ins = frag->mLabels.find(mTokens[2])->second; - if ((i=mParent->mFragments.find(mTokens[4])) == mParent->mFragments.end()) + LIns *ins = frag->mLabels.find(guardName)->second; + if ((i=mFragments.find(destName)) == mFragments.end()) bad("invalid guard reference"); ins->record()->exit->target = i->second.fragptr; - mParent->mFragmento->assm()->patch(ins->record()->exit); + mFragmento->assm()->patch(ins->record()->exit); +} + +bool +has_flag(vector &args, const string &flag) +{ + for (vector::iterator i = args.begin(); i != args.end(); ++i) { + if (*i == flag) { + args.erase(i); + return true; + } + } + return false; } int @@ -996,7 +1079,7 @@ main(int argc, char **argv) } Lirasm lasm(verbose); - LirasmAssembler(lasm).assemble(in); + lasm.assemble(in); Fragments::const_iterator i; if (execute) { From 58fc4b29f6fb0181e5185c009bb90e9969dc860b Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Mon, 27 Jul 2009 16:14:12 -0400 Subject: [PATCH 21/61] Bug 496908. Make JSVAL_IS_* functions, not macros. r=brendan,jwalden --- js/src/jsapi.h | 159 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 114 insertions(+), 45 deletions(-) diff --git a/js/src/jsapi.h b/js/src/jsapi.h index d03b13d83a6e..8d6de69f2301 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -54,35 +54,122 @@ JS_BEGIN_EXTERN_C /* * Type tags stored in the low bits of a jsval. */ -#define JSVAL_OBJECT 0x0 /* untagged reference to object */ -#define JSVAL_INT 0x1 /* tagged 31-bit integer value */ -#define JSVAL_DOUBLE 0x2 /* tagged reference to double */ -#define JSVAL_STRING 0x4 /* tagged reference to string */ -#define JSVAL_BOOLEAN 0x6 /* tagged boolean value */ +typedef enum jsvaltag { + JSVAL_OBJECT = 0x0, /* untagged reference to object */ + JSVAL_INT = 0x1, /* tagged 31-bit integer value */ + JSVAL_DOUBLE = 0x2, /* tagged reference to double */ + JSVAL_STRING = 0x4, /* tagged reference to string */ + JSVAL_BOOLEAN = 0x6 /* tagged boolean value */ +} jsvaltag; + +#define JSVAL_OBJECT ((jsvaltag)0x0) +#define JSVAL_INT ((jsvaltag)0x1) +#define JSVAL_DOUBLE ((jsvaltag)0x2) +#define JSVAL_STRING ((jsvaltag)0x4) +#define JSVAL_BOOLEAN ((jsvaltag)0x6) /* Type tag bitfield length and derived macros. */ #define JSVAL_TAGBITS 3 #define JSVAL_TAGMASK JS_BITMASK(JSVAL_TAGBITS) -#define JSVAL_TAG(v) ((v) & JSVAL_TAGMASK) -#define JSVAL_SETTAG(v,t) ((v) | (t)) -#define JSVAL_CLRTAG(v) ((v) & ~(jsval)JSVAL_TAGMASK) #define JSVAL_ALIGN JS_BIT(JSVAL_TAGBITS) +/* Not a function, because we have static asserts that use it */ +#define JSVAL_TAG(v) ((jsvaltag)((v) & JSVAL_TAGMASK)) + +/* Not a function, because we have static asserts that use it */ +#define JSVAL_SETTAG(v, t) ((v) | (t)) + +static JS_ALWAYS_INLINE jsval +JSVAL_CLRTAG(jsval v) +{ + return v & ~(jsval)JSVAL_TAGMASK; +} + +/* + * Well-known JS values. The extern'd variables are initialized when the + * first JSContext is created by JS_NewContext (see below). + */ +#define JSVAL_NULL ((jsval) 0) +#define JSVAL_ZERO INT_TO_JSVAL(0) +#define JSVAL_ONE INT_TO_JSVAL(1) +#define JSVAL_FALSE PSEUDO_BOOLEAN_TO_JSVAL(JS_FALSE) +#define JSVAL_TRUE PSEUDO_BOOLEAN_TO_JSVAL(JS_TRUE) +#define JSVAL_VOID PSEUDO_BOOLEAN_TO_JSVAL(2) + +/* + * A pseudo-boolean is a 29-bit (for 32-bit jsval) or 61-bit (for 64-bit jsval) + * value other than 0 or 1 encoded as a jsval whose tag is JSVAL_BOOLEAN. + * + * JSVAL_VOID happens to be defined as a jsval encoding a pseudo-boolean, but + * embedders MUST NOT rely on this. All other possible pseudo-boolean values + * are implementation-reserved and MUST NOT be constructed by any embedding of + * SpiderMonkey. + */ +#define JSVAL_TO_PSEUDO_BOOLEAN(v) ((JSBool) ((v) >> JSVAL_TAGBITS)) +#define PSEUDO_BOOLEAN_TO_JSVAL(b) \ + JSVAL_SETTAG((jsval) (b) << JSVAL_TAGBITS, JSVAL_BOOLEAN) + /* Predicates for type testing. */ -#define JSVAL_IS_OBJECT(v) (JSVAL_TAG(v) == JSVAL_OBJECT) -#define JSVAL_IS_NUMBER(v) (JSVAL_IS_INT(v) || JSVAL_IS_DOUBLE(v)) -#define JSVAL_IS_INT(v) ((v) & JSVAL_INT) -#define JSVAL_IS_DOUBLE(v) (JSVAL_TAG(v) == JSVAL_DOUBLE) -#define JSVAL_IS_STRING(v) (JSVAL_TAG(v) == JSVAL_STRING) -#define JSVAL_IS_BOOLEAN(v) (((v) & ~((jsval)1 << JSVAL_TAGBITS)) == \ - JSVAL_BOOLEAN) -#define JSVAL_IS_NULL(v) ((v) == JSVAL_NULL) -#define JSVAL_IS_VOID(v) ((v) == JSVAL_VOID) -#define JSVAL_IS_PRIMITIVE(v) (!JSVAL_IS_OBJECT(v) || JSVAL_IS_NULL(v)) +static JS_ALWAYS_INLINE JSBool +JSVAL_IS_OBJECT(jsval v) +{ + return JSVAL_TAG(v) == JSVAL_OBJECT; +} + +static JS_ALWAYS_INLINE JSBool +JSVAL_IS_INT(jsval v) +{ + return v & JSVAL_INT; +} + +static JS_ALWAYS_INLINE JSBool +JSVAL_IS_DOUBLE(jsval v) +{ + return JSVAL_TAG(v) == JSVAL_DOUBLE; +} + +static JS_ALWAYS_INLINE JSBool +JSVAL_IS_NUMBER(jsval v) +{ + return JSVAL_IS_INT(v) || JSVAL_IS_DOUBLE(v); +} + +static JS_ALWAYS_INLINE JSBool +JSVAL_IS_STRING(jsval v) +{ + return JSVAL_TAG(v) == JSVAL_STRING; +} + +static JS_ALWAYS_INLINE JSBool +JSVAL_IS_BOOLEAN(jsval v) +{ + return (v & ~((jsval)1 << JSVAL_TAGBITS)) == JSVAL_BOOLEAN; +} + +static JS_ALWAYS_INLINE JSBool +JSVAL_IS_NULL(jsval v) +{ + return v == JSVAL_NULL; +} + +static JS_ALWAYS_INLINE JSBool +JSVAL_IS_VOID(jsval v) +{ + return v == JSVAL_VOID; +} + +static JS_ALWAYS_INLINE JSBool +JSVAL_IS_PRIMITIVE(jsval v) +{ + return !JSVAL_IS_OBJECT(v) || JSVAL_IS_NULL(v); +} /* Objects, strings, and doubles are GC'ed. */ -#define JSVAL_IS_GCTHING(v) (!((v) & JSVAL_INT) && \ - JSVAL_TAG(v) != JSVAL_BOOLEAN) +static JS_ALWAYS_INLINE JSBool +JSVAL_IS_GCTHING(jsval v) +{ + return !(v & JSVAL_INT) && JSVAL_TAG(v) != JSVAL_BOOLEAN; +} static JS_ALWAYS_INLINE void * JSVAL_TO_GCTHING(jsval v) @@ -145,36 +232,18 @@ STRING_TO_JSVAL(JSString *str) #define JSVAL_INT_POW2(n) ((jsval)1 << (n)) #define JSVAL_INT_MIN (-JSVAL_INT_POW2(30)) #define JSVAL_INT_MAX (JSVAL_INT_POW2(30) - 1) + +/* Not a function, because we have static asserts that use it */ #define INT_FITS_IN_JSVAL(i) ((jsuint)(i) - (jsuint)JSVAL_INT_MIN <= \ (jsuint)(JSVAL_INT_MAX - JSVAL_INT_MIN)) +/* Not a function, because we have static asserts that use it */ +/* FIXME: Bug 506721, since that means we can't assert JSVAL_IS_INT(v) */ #define JSVAL_TO_INT(v) ((jsint)(v) >> 1) + +/* Not a function, because we have static asserts that use it */ +/* FIXME: Bug 506721, since that means we can't assert INT_FITS_IN_JSVAL(i) */ #define INT_TO_JSVAL(i) (((jsval)(i) << 1) | JSVAL_INT) -/* - * A pseudo-boolean is a 29-bit (for 32-bit jsval) or 61-bit (for 64-bit jsval) - * value other than 0 or 1 encoded as a jsval whose tag is JSVAL_BOOLEAN. - * - * JSVAL_VOID happens to be defined as a jsval encoding a pseudo-boolean, but - * embedders MUST NOT rely on this. All other possible pseudo-boolean values - * are implementation-reserved and MUST NOT be constructed by any embedding of - * SpiderMonkey. - */ -#define JSVAL_TO_PSEUDO_BOOLEAN(v) ((JSBool) ((v) >> JSVAL_TAGBITS)) -#define PSEUDO_BOOLEAN_TO_JSVAL(b) \ - JSVAL_SETTAG((jsval) (b) << JSVAL_TAGBITS, JSVAL_BOOLEAN) - -/* - * Well-known JS values. The extern'd variables are initialized when the - * first JSContext is created by JS_NewContext (see below). - */ -#define JSVAL_NULL ((jsval) 0) -#define JSVAL_ZERO INT_TO_JSVAL(0) -#define JSVAL_ONE INT_TO_JSVAL(1) -#define JSVAL_FALSE PSEUDO_BOOLEAN_TO_JSVAL(JS_FALSE) -#define JSVAL_TRUE PSEUDO_BOOLEAN_TO_JSVAL(JS_TRUE) -#define JSVAL_VOID PSEUDO_BOOLEAN_TO_JSVAL(2) - - /* Convert between boolean and jsval, asserting that inputs are valid. */ static JS_ALWAYS_INLINE JSBool JSVAL_TO_BOOLEAN(jsval v) From 10702b702ba6e36c8958e79946aa51ea5515750f Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Mon, 27 Jul 2009 16:29:02 -0500 Subject: [PATCH 22/61] Bug 505932 - Shape regeneration does not touch most empty scopes. r=brendan. --- js/src/jscntxt.h | 13 ++++++++++++- js/src/jsgc.cpp | 1 + js/src/jsobj.cpp | 39 ++++++++++++++++++++++++++++----------- js/src/jsscope.cpp | 4 ++-- js/src/jsscope.h | 10 +++++++++- 5 files changed, 52 insertions(+), 15 deletions(-) diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 091a2529a39d..b079cb014d19 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -391,7 +391,18 @@ struct JSRuntime { JSPackedBool gcPoke; JSPackedBool gcRunning; JSPackedBool gcRegenShapes; - uint8 gcPadding; + + /* + * During gc, if rt->gcRegenShapes && + * (scope->flags & JSScope::SHAPE_REGEN) == rt->gcRegenShapesScopeFlag, + * then the scope's shape has already been regenerated during this GC. + * To avoid having to sweep JSScopes, the bit's meaning toggles with each + * shape-regenerating GC. + * + * FIXME Once scopes are GC'd (bug 505004), this will be obsolete. + */ + uint8 gcRegenShapesScopeFlag; + #ifdef JS_GC_ZEAL jsrefcount gcZeal; #endif diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index b2ee47f5a0c1..f6a76120c4d4 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -3519,6 +3519,7 @@ js_GC(JSContext *cx, JSGCInvocationKind gckind) */ if (rt->shapeGen & SHAPE_OVERFLOW_BIT) { rt->gcRegenShapes = true; + rt->gcRegenShapesScopeFlag ^= JSScope::SHAPE_REGEN; rt->shapeGen = 0; rt->protoHazardShape = 0; } diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index c14b66e837aa..9ca39003a927 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -5773,23 +5773,40 @@ js_TraceObject(JSTracer *trc, JSObject *obj) #endif sprop = scope->lastProp; - if (sprop) { - JS_ASSERT(scope->has(sprop)); + uint8 regenFlag = cx->runtime->gcRegenShapesScopeFlag; + if (IS_GC_MARKING_TRACER(trc) && + cx->runtime->gcRegenShapes && + scope->hasRegenFlag(regenFlag)) { + /* + * Either scope has its own shape, which must be regenerated, or it + * must have the same shape as its lastProp. + */ + uint32 shape; - /* Regenerate property cache shape ids if GC'ing. */ - if (IS_GC_MARKING_TRACER(trc) && cx->runtime->gcRegenShapes) { + if (sprop) { if (!(sprop->flags & SPROP_FLAG_SHAPE_REGEN)) { sprop->shape = js_RegenerateShapeForGC(cx); sprop->flags |= SPROP_FLAG_SHAPE_REGEN; } - - uint32 shape = sprop->shape; - if (scope->hasOwnShape()) { - shape = js_RegenerateShapeForGC(cx); - JS_ASSERT(shape != sprop->shape); - } - scope->shape = shape; + shape = sprop->shape; } + if (!sprop || scope->hasOwnShape()) { + shape = js_RegenerateShapeForGC(cx); + JS_ASSERT_IF(sprop, shape != sprop->shape); + } + scope->shape = shape; + scope->flags ^= JSScope::SHAPE_REGEN; + + /* Also regenerate the shapes of empty scopes, in case they are not shared. */ + for (JSScope *empty = scope->emptyScope; + empty && empty->hasRegenFlag(regenFlag); + empty = empty->emptyScope) { + empty->shape = js_RegenerateShapeForGC(cx); + empty->flags ^= JSScope::SHAPE_REGEN; + } + } + if (sprop) { + JS_ASSERT(scope->has(sprop)); /* Trace scope's property tree ancestor line. */ do { diff --git a/js/src/jsscope.cpp b/js/src/jsscope.cpp index c343533dde35..7da51cd43f71 100644 --- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -196,7 +196,7 @@ JSScope::create(JSContext *cx, JSObjectOps *ops, JSClass *clasp, JSObject *obj) scope->object = obj; scope->nrefs = 1; scope->freeslot = JSSLOT_FREE(clasp); - scope->flags = 0; + scope->flags = cx->runtime->gcRegenShapesScopeFlag; js_LeaveTraceIfGlobalObject(cx, obj); scope->initMinimal(cx); @@ -226,7 +226,7 @@ JSScope::createEmptyScope(JSContext *cx, JSClass *clasp) */ scope->nrefs = 2; scope->freeslot = JSSLOT_FREE(clasp); - scope->flags = 0; + scope->flags = OWN_SHAPE | cx->runtime->gcRegenShapesScopeFlag; scope->initMinimal(cx); #ifdef JS_THREADSAFE diff --git a/js/src/jsscope.h b/js/src/jsscope.h index 481da6a4a5b3..fe8b5798e4f1 100644 --- a/js/src/jsscope.h +++ b/js/src/jsscope.h @@ -283,7 +283,13 @@ struct JSScope { SEALED = 0x0002, BRANDED = 0x0004, INDEXED_PROPERTIES = 0x0008, - OWN_SHAPE = 0x0010 + OWN_SHAPE = 0x0010, + + /* + * This flag toggles with each shape-regenerating GC cycle. + * See JSRuntime::gcRegenShapesScopeFlag. + */ + SHAPE_REGEN = 0x0020 }; bool hadMiddleDelete() { return flags & MIDDLE_DELETE; } @@ -312,6 +318,8 @@ struct JSScope { bool hasOwnShape() { return flags & OWN_SHAPE; } void setOwnShape() { flags |= OWN_SHAPE; } + bool hasRegenFlag(uint8 regenFlag) { return (flags & SHAPE_REGEN) == regenFlag; } + bool owned() { return object != NULL; } }; From fad2d36065c720615f020d189602247670f80ea8 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Mon, 27 Jul 2009 16:38:39 -0500 Subject: [PATCH 23/61] lirasm - Rename a parameter, as graydon requested in review for bug 505249. --- js/src/lirasm/lirasm.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/js/src/lirasm/lirasm.cpp b/js/src/lirasm/lirasm.cpp index f3c22fc77ed5..84f73113f730 100644 --- a/js/src/lirasm/lirasm.cpp +++ b/js/src/lirasm/lirasm.cpp @@ -234,7 +234,7 @@ public: FragmentAssembler(Lirasm &parent, const string &fragmentName); ~FragmentAssembler(); - void assembleFragment(LirTokenStream &in, bool implied, const LirToken *firstToken); + void assembleFragment(LirTokenStream &in, bool implicitBegin, const LirToken *firstToken); private: // Prohibit copying. @@ -735,7 +735,7 @@ FragmentAssembler::extract_any_label(string &lab, char lab_delim) } void -FragmentAssembler::assembleFragment(LirTokenStream &in, bool implied, const LirToken *firstToken) +FragmentAssembler::assembleFragment(LirTokenStream &in, bool implicitBegin, const LirToken *firstToken) { LirToken token; while (true) { @@ -743,7 +743,7 @@ FragmentAssembler::assembleFragment(LirTokenStream &in, bool implied, const LirT token = *firstToken; firstToken = NULL; } else if (!in.get(token)) { - if (!implied) + if (!implicitBegin) bad("unexpected end of file in fragment '" + mFragName + "'"); break; } @@ -756,7 +756,7 @@ FragmentAssembler::assembleFragment(LirTokenStream &in, bool implied, const LirT if (op == ".begin") bad("nested fragments are not supported"); if (op == ".end") { - if (implied) + if (implicitBegin) bad(".end without .begin"); if (!in.eat(NEWLINE)) bad("extra junk after .end"); From 04786e0f3d14dc471aa8eb7b3031c6616420dd5f Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Mon, 27 Jul 2009 16:47:34 -0500 Subject: [PATCH 24/61] Bug 503408 - Trace native setters. r=brendan. --- js/src/jsbuiltins.cpp | 2 - js/src/jsinterp.cpp | 1 - js/src/jsinterp.h | 4 + js/src/jstracer.cpp | 423 ++++++++++++++++++++++++++++-------------- js/src/jstracer.h | 25 ++- js/src/trace-test.js | 15 ++ 6 files changed, 327 insertions(+), 143 deletions(-) diff --git a/js/src/jsbuiltins.cpp b/js/src/jsbuiltins.cpp index 961e11331276..fe088a03aad8 100644 --- a/js/src/jsbuiltins.cpp +++ b/js/src/jsbuiltins.cpp @@ -242,8 +242,6 @@ JSBool FASTCALL js_AddProperty(JSContext* cx, JSObject* obj, JSScopeProperty* sprop) { JS_ASSERT(OBJ_IS_NATIVE(obj)); - JS_ASSERT(SPROP_HAS_STUB_SETTER(sprop)); - JS_LOCK_OBJ(cx, obj); JSScope* scope = OBJ_SCOPE(obj); diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 6f60b4b0821c..25506179975c 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -4802,7 +4802,6 @@ js_Interpret(JSContext *cx) } JS_UNLOCK_SCOPE(cx, scope); PCMETER(cache->setpcmisses++); - atom = NULL; } } diff --git a/js/src/jsinterp.h b/js/src/jsinterp.h index 3848d5498b1a..23e77a7171ef 100644 --- a/js/src/jsinterp.h +++ b/js/src/jsinterp.h @@ -243,6 +243,10 @@ struct JSPropCacheEntry { jsuword kshape; /* key shape if pc, else obj for atom */ jsuword vcap; /* value capability, see above */ jsuword vword; /* value word, see PCVAL_* below */ + + bool adding() const { + return PCVCAP_TAG(vcap) == 0 && kshape != PCVCAP_SHAPE(vcap); + } }; /* diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 5d4da83d8742..dba2449d3bee 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -2950,7 +2950,8 @@ TraceRecorder::snapshot(ExitType exitType) bool resumeAfter = (pendingTraceableNative && JSTN_ERRTYPE(pendingTraceableNative) == FAIL_STATUS); if (resumeAfter) { - JS_ASSERT(*pc == JSOP_CALL || *pc == JSOP_APPLY || *pc == JSOP_NEW); + JS_ASSERT(*pc == JSOP_CALL || *pc == JSOP_APPLY || *pc == JSOP_NEW || + *pc == JSOP_SETPROP || *pc == JSOP_SETNAME); pc += cs.length; regs->pc = pc; MUST_FLOW_THROUGH("restore_pc"); @@ -5410,11 +5411,11 @@ LeaveTree(InterpState& state, VMSideExit* lr) * js_ExecuteTree. We are about to return to the interpreter. Adjust * the top stack frame to resume on the next op. */ - JS_ASSERT(*cx->fp->regs->pc == JSOP_CALL || - *cx->fp->regs->pc == JSOP_APPLY || - *cx->fp->regs->pc == JSOP_NEW); - uintN argc = GET_ARGC(cx->fp->regs->pc); - cx->fp->regs->pc += JSOP_CALL_LENGTH; + jsbytecode *pc = cx->fp->regs->pc; + JS_ASSERT(*pc == JSOP_CALL || *pc == JSOP_APPLY || *pc == JSOP_NEW || + *pc == JSOP_SETPROP || *pc == JSOP_SETNAME); + uintN argc = (js_CodeSpec[*pc].format & JOF_INVOKE) ? GET_ARGC(pc) : 0; + cx->fp->regs->pc += js_CodeSpec[*pc].length; cx->fp->regs->sp -= argc + 1; JS_ASSERT_IF(!cx->fp->imacpc, cx->fp->slots + cx->fp->script->nfixed + @@ -7581,6 +7582,41 @@ TraceRecorder::map_is_native(JSObjectMap* map, LIns* map_ins, LIns*& ops_ins, si return true; } +JS_REQUIRES_STACK JSRecordingStatus +TraceRecorder::guardNativePropertyOp(JSObject* aobj, LIns* map_ins) +{ + /* + * Interpreter calls to PROPERTY_CACHE_TEST guard on native object ops + * which is required to use native objects (those whose maps are scopes), + * or even more narrow conditions required because the cache miss case + * will call a particular object-op (js_GetProperty, js_SetProperty). + * + * We parameterize using offsetof and guard on match against the hook at + * the given offset in js_ObjectOps. TraceRecorder::record_JSOP_SETPROP + * guards the js_SetProperty case. + */ + uint32 format = js_CodeSpec[*cx->fp->regs->pc].format; + uint32 mode = JOF_MODE(format); + + // No need to guard native-ness of global object. + JS_ASSERT(OBJ_IS_NATIVE(globalObj)); + if (aobj != globalObj) { + size_t op_offset = offsetof(JSObjectOps, objectMap); + if (mode == JOF_PROP || mode == JOF_VARPROP) { + op_offset = (format & JOF_SET) + ? offsetof(JSObjectOps, setProperty) + : offsetof(JSObjectOps, getProperty); + } else { + JS_ASSERT(mode == JOF_NAME); + } + + LIns* ops_ins; + if (!map_is_native(aobj->map, map_ins, ops_ins, op_offset)) + ABORT_TRACE("non-native map"); + } + return JSRS_CONTINUE; +} + JS_REQUIRES_STACK JSRecordingStatus TraceRecorder::test_property_cache(JSObject* obj, LIns* obj_ins, JSObject*& obj2, jsuword& pcval) { @@ -7598,33 +7634,8 @@ TraceRecorder::test_property_cache(JSObject* obj, LIns* obj_ins, JSObject*& obj2 } LIns* map_ins = map(obj_ins); - LIns* ops_ins; - // Interpreter calls to PROPERTY_CACHE_TEST guard on native object ops - // which is required to use native objects (those whose maps are scopes), - // or even more narrow conditions required because the cache miss case - // will call a particular object-op (js_GetProperty, js_SetProperty). - // - // We parameterize using offsetof and guard on match against the hook at - // the given offset in js_ObjectOps. TraceRecorder::record_JSOP_SETPROP - // guards the js_SetProperty case. - uint32 format = js_CodeSpec[*pc].format; - uint32 mode = JOF_MODE(format); - - // No need to guard native-ness of global object. - JS_ASSERT(OBJ_IS_NATIVE(globalObj)); - if (aobj != globalObj) { - size_t op_offset = offsetof(JSObjectOps, objectMap); - if (mode == JOF_PROP || mode == JOF_VARPROP) { - JS_ASSERT(!(format & JOF_SET)); - op_offset = offsetof(JSObjectOps, getProperty); - } else { - JS_ASSERT(mode == JOF_NAME); - } - - if (!map_is_native(aobj->map, map_ins, ops_ins, op_offset)) - ABORT_TRACE("non-native map"); - } + CHECK_STATUS(guardNativePropertyOp(aobj, map_ins)); JSAtom* atom; JSPropCacheEntry* entry; @@ -7692,31 +7703,60 @@ TraceRecorder::test_property_cache(JSObject* obj, LIns* obj_ins, JSObject*& obj2 JS_ASSERT(cx->requestDepth); #endif - // Emit guard(s), common code for both hit and miss cases. + return guardPropertyCacheHit(obj_ins, map_ins, aobj, obj2, entry, pcval); +} + +JS_REQUIRES_STACK JSRecordingStatus +TraceRecorder::guardPropertyCacheHit(LIns* obj_ins, + LIns* map_ins, + JSObject* aobj, + JSObject* obj2, + JSPropCacheEntry* entry, + jsuword& pcval) +{ + uint32 vshape = PCVCAP_SHAPE(entry->vcap); + // Check for first-level cache hit and guard on kshape if possible. // Otherwise guard on key object exact match. if (PCVCAP_TAG(entry->vcap) <= 1) { if (aobj != globalObj) { LIns* shape_ins = addName(lir->insLoad(LIR_ld, map_ins, offsetof(JSScope, shape)), "shape"); - guard(true, addName(lir->ins2i(LIR_eq, shape_ins, entry->kshape), "guard(kshape)(test_property_cache)"), + guard(true, + addName(lir->ins2i(LIR_eq, shape_ins, entry->kshape), "guard_kshape"), BRANCH_EXIT); } + + if (entry->adding()) { + if (aobj == globalObj) + ABORT_TRACE("adding a property to the global object"); + + LIns *vshape_ins = addName( + lir->insLoad(LIR_ld, + addName(lir->insLoad(LIR_ldp, cx_ins, offsetof(JSContext, runtime)), + "runtime"), + offsetof(JSRuntime, protoHazardShape)), + "protoHazardShape"); + guard(true, + addName(lir->ins2i(LIR_eq, vshape_ins, vshape), "guard_protoHazardShape"), + MISMATCH_EXIT); + } } else { #ifdef DEBUG - JSOp op = js_GetOpcode(cx, cx->fp->script, pc); + JSOp op = js_GetOpcode(cx, cx->fp->script, cx->fp->regs->pc); JSAtom *pcatom; if (op == JSOP_LENGTH) { pcatom = cx->runtime->atomState.lengthAtom; } else { ptrdiff_t pcoff = (JOF_TYPE(js_CodeSpec[op].format) == JOF_SLOTATOM) ? SLOTNO_LEN : 0; - GET_ATOM_FROM_BYTECODE(cx->fp->script, pc, pcoff, pcatom); + GET_ATOM_FROM_BYTECODE(cx->fp->script, cx->fp->regs->pc, pcoff, pcatom); } JS_ASSERT(entry->kpc == (jsbytecode *) pcatom); JS_ASSERT(entry->kshape == jsuword(aobj)); #endif if (aobj != globalObj && !obj_ins->isconstp()) { - guard(true, addName(lir->ins2i(LIR_eq, obj_ins, entry->kshape), "guard(kobj)"), + guard(true, + addName(lir->ins2i(LIR_eq, obj_ins, entry->kshape), "guard_kobj"), BRANCH_EXIT); } } @@ -7724,26 +7764,25 @@ TraceRecorder::test_property_cache(JSObject* obj, LIns* obj_ins, JSObject*& obj2 // For any hit that goes up the scope and/or proto chains, we will need to // guard on the shape of the object containing the property. if (PCVCAP_TAG(entry->vcap) >= 1) { - jsuword vcap = entry->vcap; - uint32 vshape = PCVCAP_SHAPE(vcap); JS_ASSERT(OBJ_SHAPE(obj2) == vshape); LIns* obj2_ins; if (PCVCAP_TAG(entry->vcap) == 1) { // Duplicate the special case in PROPERTY_CACHE_TEST. - obj2_ins = stobj_get_fslot(obj_ins, JSSLOT_PROTO); + obj2_ins = addName(stobj_get_fslot(obj_ins, JSSLOT_PROTO), "proto"); guard(false, lir->ins_eq0(obj2_ins), BRANCH_EXIT); } else { obj2_ins = INS_CONSTPTR(obj2); } map_ins = map(obj2_ins); + LIns* ops_ins; if (!map_is_native(obj2->map, map_ins, ops_ins)) ABORT_TRACE("non-native map"); LIns* shape_ins = addName(lir->insLoad(LIR_ld, map_ins, offsetof(JSScope, shape)), - "shape"); + "obj2_shape"); guard(true, - addName(lir->ins2i(LIR_eq, shape_ins, vshape), "guard(vshape)(test_property_cache)"), + addName(lir->ins2i(LIR_eq, shape_ins, vshape), "guard_vshape"), BRANCH_EXIT); } @@ -7801,16 +7840,6 @@ TraceRecorder::stobj_get_slot(LIns* obj_ins, unsigned slot, LIns*& dslots_ins) return stobj_get_dslot(obj_ins, slot - JS_INITIAL_NSLOTS, dslots_ins); } -JSRecordingStatus -TraceRecorder::native_set(LIns* obj_ins, JSScopeProperty* sprop, LIns*& dslots_ins, LIns* v_ins) -{ - if (SPROP_HAS_STUB_SETTER(sprop) && sprop->slot != SPROP_INVALID_SLOT) { - stobj_set_slot(obj_ins, sprop->slot, dslots_ins, v_ins); - return JSRS_CONTINUE; - } - ABORT_TRACE("unallocated or non-stub sprop"); -} - JSRecordingStatus TraceRecorder::native_get(LIns* obj_ins, LIns* pobj_ins, JSScopeProperty* sprop, LIns*& dslots_ins, LIns*& v_ins) @@ -8703,6 +8732,83 @@ TraceRecorder::newArray(JSObject* ctor, uint32 argc, jsval* argv, jsval* rval) return JSRS_CONTINUE; } +JS_REQUIRES_STACK void +TraceRecorder::propagateFailureToBuiltinStatus(LIns* ok_ins, LIns*& status_ins) +{ + /* + * Check the boolean return value (ok_ins) of a native JSNative, + * JSFastNative, or JSPropertyOp hook for failure. On failure, set the + * JSBUILTIN_ERROR bit of cx->builtinStatus. + * + * If the return value (ok_ins) is true, status' == status. Otherwise + * status' = status | JSBUILTIN_ERROR. We calculate (rval&1)^1, which is 1 + * if rval is JS_FALSE (error), and then shift that by 1, which is the log2 + * of JSBUILTIN_ERROR. + */ + JS_STATIC_ASSERT(((JS_TRUE & 1) ^ 1) << 1 == 0); + JS_STATIC_ASSERT(((JS_FALSE & 1) ^ 1) << 1 == JSBUILTIN_ERROR); + status_ins = lir->ins2(LIR_or, + status_ins, + lir->ins2i(LIR_lsh, + lir->ins2i(LIR_xor, + lir->ins2i(LIR_and, ok_ins, 1), + 1), + 1)); + lir->insStorei(status_ins, lirbuf->state, (int) offsetof(InterpState, builtinStatus)); +} + +JS_REQUIRES_STACK void +TraceRecorder::emitNativePropertyOp(JSScope* scope, JSScopeProperty* sprop, LIns* obj_ins, + bool setflag, LIns* boxed_ins) +{ + JS_ASSERT(!(sprop->attrs & (setflag ? JSPROP_SETTER : JSPROP_GETTER))); + JS_ASSERT(setflag ? !SPROP_HAS_STUB_SETTER(sprop) : !SPROP_HAS_STUB_GETTER(sprop)); + + // Take snapshot for js_DeepBail and store it in cx->bailExit. + VMSideExit* exit = snapshot(DEEP_BAIL_EXIT); + lir->insStorei(INS_CONSTPTR(exit), cx_ins, offsetof(JSContext, bailExit)); + + // Tell nanojit not to discard or defer stack writes before this call. + LIns* guardRec = createGuardRecord(exit); + lir->insGuard(LIR_xbarrier, guardRec, guardRec); + + // It is unsafe to pass the address of an object slot as the out parameter, + // because the getter or setter could end up resizing the object's dslots. + // Instead, use a word of stack and root it in nativeVp. + LIns* vp_ins = lir->insAlloc(sizeof(jsval)); + lir->insStorei(vp_ins, cx_ins, offsetof(JSContext, nativeVp)); + lir->insStorei(INS_CONST(1), cx_ins, offsetof(JSContext, nativeVpLen)); + if (setflag) + lir->insStorei(boxed_ins, vp_ins, 0); + + CallInfo* ci = (CallInfo*) lir->insSkip(sizeof(struct CallInfo))->payload(); + ci->_address = uintptr_t(setflag ? sprop->setter : sprop->getter); + ci->_argtypes = ARGSIZE_LO | ARGSIZE_LO << 2 | ARGSIZE_LO << 4 | ARGSIZE_LO << 6 | ARGSIZE_LO << 8; + ci->_cse = ci->_fold = 0; + ci->_abi = ABI_CDECL; +#ifdef DEBUG + ci->_name = "JSPropertyOp"; +#endif + LIns* args[] = { vp_ins, INS_CONSTWORD(SPROP_USERID(sprop)), obj_ins, cx_ins }; + LIns* ok_ins = lir->insCall(ci, args); + + // Unroot the vp. + lir->insStorei(INS_CONSTPTR(NULL), cx_ins, offsetof(JSContext, nativeVp)); + + // Guard that the call succeeded and builtinStatus is still 0. + // If the native op succeeds but we deep-bail here, the result value is + // lost! Therefore this can only be used for setters of shared properties. + // In that case we ignore the result value anyway. + LIns* status_ins = lir->insLoad(LIR_ld, + lirbuf->state, + (int) offsetof(InterpState, builtinStatus)); + propagateFailureToBuiltinStatus(ok_ins, status_ins); + guard(true, lir->ins_eq0(status_ins), STATUS_EXIT); + + // Re-load the value--but this is currently unused, so commented out. + //boxed_ins = lir->insLoad(LIR_ldp, vp_ins, 0); +} + JS_REQUIRES_STACK JSRecordingStatus TraceRecorder::emitNativeCall(JSTraceableNative* known, uintN argc, LIns* args[]) { @@ -9261,30 +9367,90 @@ TraceRecorder::record_JSOP_SETPROP() return JSRS_CONTINUE; } +/* Emit a specialized, inlined copy of js_NativeSet. */ JS_REQUIRES_STACK JSRecordingStatus -TraceRecorder::record_SetPropHit(JSPropCacheEntry* entry, JSScopeProperty* sprop) +TraceRecorder::nativeSet(JSObject* obj, LIns* obj_ins, JSScopeProperty* sprop, + jsval v, LIns* v_ins) +{ + JSScope* scope = OBJ_SCOPE(obj); + uint32 slot = sprop->slot; + + /* + * We do not trace assignment to properties that have both a nonstub setter + * and a slot, for several reasons. + * + * First, that would require sampling rt->propertyRemovals before and after + * (see js_NativeSet), and even more code to handle the case where the two + * samples differ. A mere guard is not enough, because you can't just bail + * off trace in the middle of a property assignment without storing the + * value and making the stack right. + * + * If obj is the global object, there are two additional problems. We would + * have to emit still more code to store the result in the object (not the + * native global frame) if the setter returned successfully after + * deep-bailing. And we would have to cope if the run-time type of the + * setter's return value differed from the record-time type of v, in which + * case unboxing would fail and, having called a native setter, we could + * not just retry the instruction in the interpreter. + */ + JS_ASSERT(SPROP_HAS_STUB_SETTER(sprop) || slot == SPROP_INVALID_SLOT); + + // Box the value to be stored, if necessary. + LIns* boxed_ins = NULL; + if (!SPROP_HAS_STUB_SETTER(sprop) || (slot != SPROP_INVALID_SLOT && obj != globalObj)) { + boxed_ins = v_ins; + box_jsval(v, boxed_ins); + } + + // Call the setter, if any. + if (!SPROP_HAS_STUB_SETTER(sprop)) + emitNativePropertyOp(scope, sprop, obj_ins, true, boxed_ins); + + // Store the value, if this property has a slot. + if (slot != SPROP_INVALID_SLOT) { + JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop, scope)); + JS_ASSERT(!(sprop->attrs & JSPROP_SHARED)); + if (obj == globalObj) { + if (!lazilyImportGlobalSlot(slot)) + ABORT_TRACE("lazy import of global slot failed"); + + // If we called a native setter, unbox the result. + if (!SPROP_HAS_STUB_SETTER(sprop)) { + v_ins = boxed_ins; + unbox_jsval(STOBJ_GET_SLOT(obj, slot), v_ins, snapshot(BRANCH_EXIT)); + } + set(&STOBJ_GET_SLOT(obj, slot), v_ins); + } else { + LIns* dslots_ins = NULL; + stobj_set_slot(obj_ins, slot, dslots_ins, boxed_ins); + } + } + + return JSRS_CONTINUE; +} + +JS_REQUIRES_STACK JSRecordingStatus +TraceRecorder::setProp(jsval &l, JSPropCacheEntry* entry, JSScopeProperty* sprop, + jsval &v, LIns*& v_ins) { if (entry == JS_NO_PROP_CACHE_FILL) ABORT_TRACE("can't trace uncacheable property set"); - if (PCVCAP_TAG(entry->vcap) >= 1) - ABORT_TRACE("can't trace inherited property set"); + JS_ASSERT_IF(PCVCAP_TAG(entry->vcap) >= 1, sprop->attrs & JSPROP_SHARED); + if (!SPROP_HAS_STUB_SETTER(sprop) && sprop->slot != SPROP_INVALID_SLOT) + ABORT_TRACE("can't trace set of property with setter and slot"); + if (sprop->attrs & JSPROP_SETTER) + ABORT_TRACE("can't trace JavaScript function setter"); - jsbytecode* pc = cx->fp->regs->pc; - JS_ASSERT(entry->kpc == pc); - - jsval& r = stackval(-1); - jsval& l = stackval(-2); + // These two cases are actually errors and can't be cached. + JS_ASSERT(!(sprop->attrs & JSPROP_GETTER)); // getter without setter + JS_ASSERT(!(sprop->attrs & JSPROP_READONLY)); JS_ASSERT(!JSVAL_IS_PRIMITIVE(l)); JSObject* obj = JSVAL_TO_OBJECT(l); LIns* obj_ins = get(&l); JSScope* scope = OBJ_SCOPE(obj); - JS_ASSERT(scope->owned()); - JS_ASSERT(scope->has(sprop)); - - if (!isValidSlot(scope, sprop)) - return JSRS_STOP; + JS_ASSERT_IF(entry->vcap == PCVCAP_MAKE(entry->kshape, 0, 0), scope->has(sprop)); /* * Setting a function-valued property might need to rebrand the object; we @@ -9292,57 +9458,54 @@ TraceRecorder::record_SetPropHit(JSPropCacheEntry* entry, JSScopeProperty* sprop * separating functions into the trace-time type TT_FUNCTION will save the * day! */ - if (scope->branded() && VALUE_IS_FUNCTION(cx, r)) + if (scope->branded() && VALUE_IS_FUNCTION(cx, v)) ABORT_TRACE("can't trace function-valued property set in branded scope"); - if (obj == globalObj) { - JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop, scope)); - uint32 slot = sprop->slot; - if (!lazilyImportGlobalSlot(slot)) - ABORT_TRACE("lazy import of global slot failed"); + // Find obj2. If entry->adding(), the TAG bits are all 0. + JSObject* obj2 = obj; + for (jsuword i = PCVCAP_TAG(entry->vcap) >> PCVCAP_PROTOBITS; i; i--) + obj2 = OBJ_GET_PARENT(cx, obj2); + for (jsuword j = PCVCAP_TAG(entry->vcap) & PCVCAP_PROTOMASK; j; j--) + obj2 = OBJ_GET_PROTO(cx, obj2); + scope = OBJ_SCOPE(obj2); + JS_ASSERT_IF(entry->adding(), obj2 == obj); - LIns* r_ins = get(&r); - set(&STOBJ_GET_SLOT(obj, slot), r_ins); - - JS_ASSERT(*pc != JSOP_INITPROP); - if (pc[JSOP_SETPROP_LENGTH] != JSOP_POP) - set(&l, r_ins); - return JSRS_CONTINUE; - } - - // The global object's shape is guarded at trace entry, all others need a guard here. + // Guard before anything else. LIns* map_ins = map(obj_ins); - LIns* ops_ins; - if (!map_is_native(obj->map, map_ins, ops_ins, offsetof(JSObjectOps, setProperty))) - ABORT_TRACE("non-native map"); + CHECK_STATUS(guardNativePropertyOp(obj, map_ins)); + jsuword pcval; + CHECK_STATUS(guardPropertyCacheHit(obj_ins, map_ins, obj, obj2, entry, pcval)); + JS_ASSERT(scope->object == obj2); + JS_ASSERT(scope->has(sprop)); + JS_ASSERT_IF(obj2 != obj, sprop->attrs & JSPROP_SHARED); - LIns* shape_ins = addName(lir->insLoad(LIR_ld, map_ins, offsetof(JSScope, shape)), "shape"); - guard(true, - addName(lir->ins2i(LIR_eq, shape_ins, entry->kshape), "guard(kshape)(record_SetPropHit)"), - BRANCH_EXIT); - - uint32 vshape = PCVCAP_SHAPE(entry->vcap); - if (entry->kshape != vshape) { - LIns *vshape_ins = lir->insLoad(LIR_ld, - lir->insLoad(LIR_ldp, cx_ins, offsetof(JSContext, runtime)), - offsetof(JSRuntime, protoHazardShape)); - guard(true, - addName(lir->ins2i(LIR_eq, vshape_ins, vshape), "guard(vshape)(record_SetPropHit)"), - MISMATCH_EXIT); + // Add a property to the object if necessary. + if (entry->adding()) { + JS_ASSERT(!(sprop->attrs & JSPROP_SHARED)); + if (obj == globalObj) + ABORT_TRACE("adding a property to the global object"); LIns* args[] = { INS_CONSTPTR(sprop), obj_ins, cx_ins }; LIns* ok_ins = lir->insCall(&js_AddProperty_ci, args); guard(false, lir->ins_eq0(ok_ins), OOM_EXIT); } - LIns* dslots_ins = NULL; - LIns* v_ins = get(&r); - LIns* boxed_ins = v_ins; - box_jsval(r, boxed_ins); - CHECK_STATUS(native_set(obj_ins, sprop, dslots_ins, boxed_ins)); + v_ins = get(&v); + return nativeSet(obj, obj_ins, sprop, v, v_ins); +} +JS_REQUIRES_STACK JSRecordingStatus +TraceRecorder::record_SetPropHit(JSPropCacheEntry* entry, JSScopeProperty* sprop) +{ + jsval& r = stackval(-1); + jsval& l = stackval(-2); + LIns* v_ins; + CHECK_STATUS(setProp(l, entry, sprop, r, v_ins)); + + jsbytecode* pc = cx->fp->regs->pc; if (*pc != JSOP_INITPROP && pc[JSOP_SETPROP_LENGTH] != JSOP_POP) set(&l, v_ins); + return JSRS_CONTINUE; } @@ -10097,22 +10260,24 @@ TraceRecorder::record_NativeCallComplete() jsbytecode* pc = cx->fp->regs->pc; JS_ASSERT(pendingTraceableNative); - JS_ASSERT(*pc == JSOP_CALL || *pc == JSOP_APPLY || *pc == JSOP_NEW); + JS_ASSERT(*pc == JSOP_CALL || *pc == JSOP_APPLY || *pc == JSOP_NEW || *pc == JSOP_SETPROP); jsval& v = stackval(-1); LIns* v_ins = get(&v); - /* At this point the generated code has already called the native function - and we can no longer fail back to the original pc location (JSOP_CALL) - because that would cause the interpreter to re-execute the native - function, which might have side effects. - - Instead, the snapshot() call below sees that we are currently parked on - a traceable native's JSOP_CALL instruction, and it will advance the pc - to restore by the length of the current opcode. If the native's return - type is jsval, snapshot() will also indicate in the type map that the - element on top of the stack is a boxed value which doesn't need to be - boxed if the type guard generated by unbox_jsval() fails. */ + /* + * At this point the generated code has already called the native function + * and we can no longer fail back to the original pc location (JSOP_CALL) + * because that would cause the interpreter to re-execute the native + * function, which might have side effects. + * + * Instead, the snapshot() call below sees that we are currently parked on + * a traceable native's JSOP_CALL instruction, and it will advance the pc + * to restore by the length of the current opcode. If the native's return + * type is jsval, snapshot() will also indicate in the type map that the + * element on top of the stack is a boxed value which doesn't need to be + * boxed if the type guard generated by unbox_jsval() fails. + */ if (JSTN_ERRTYPE(pendingTraceableNative) == FAIL_STATUS) { // Keep cx->bailExit null when it's invalid. @@ -10145,27 +10310,9 @@ TraceRecorder::record_NativeCallComplete() } set(&v, v_ins); - /* - * If this is a generic traceable native invocation, propagate the boolean return - * value of the native into builtinStatus. If the return value (v_ins) - * is true, status' == status. Otherwise status' = status | JSBUILTIN_ERROR. - * We calculate (rval&1)^1, which is 1 if rval is JS_FALSE (error), and then - * shift that by 1 which is JSBUILTIN_ERROR. - */ - JS_STATIC_ASSERT((1 - JS_TRUE) << 1 == 0); - JS_STATIC_ASSERT((1 - JS_FALSE) << 1 == JSBUILTIN_ERROR); - status = lir->ins2(LIR_or, - status, - lir->ins2i(LIR_lsh, - lir->ins2i(LIR_xor, - lir->ins2i(LIR_and, ok_ins, 1), - 1), - 1)); - lir->insStorei(status, lirbuf->state, (int) offsetof(InterpState, builtinStatus)); + propagateFailureToBuiltinStatus(ok_ins, status); } - guard(true, - lir->ins_eq0(status), - STATUS_EXIT); + guard(true, lir->ins_eq0(status), STATUS_EXIT); } JSRecordingStatus ok = JSRS_CONTINUE; @@ -10303,9 +10450,8 @@ TraceRecorder::prop(JSObject* obj, LIns* obj_ins, uint32& slot, LIns*& v_ins) return JSRS_CONTINUE; } - /* Insist if setting on obj being the directly addressed object. */ - uint32 setflags = (cs.format & (JOF_SET | JOF_INCDEC | JOF_FOR)); - LIns* dslots_ins = NULL; + uint32 setflags = (cs.format & (JOF_INCDEC | JOF_FOR)); + JS_ASSERT(!(cs.format & JOF_SET)); /* Don't trace getter or setter calls, our caller wants a direct slot. */ if (PCVAL_IS_SPROP(pcval)) { @@ -10364,11 +10510,12 @@ TraceRecorder::prop(JSObject* obj, LIns* obj_ins, uint32& slot, LIns*& v_ins) * obj_ins the last proto-load. */ while (obj != obj2) { - obj_ins = stobj_get_slot(obj_ins, JSSLOT_PROTO, dslots_ins); + obj_ins = stobj_get_fslot(obj_ins, JSSLOT_PROTO); obj = STOBJ_GET_PROTO(obj); } } + LIns* dslots_ins = NULL; v_ins = stobj_get_slot(obj_ins, slot, dslots_ins); unbox_jsval(STOBJ_GET_SLOT(obj, slot), v_ins, snapshot(BRANCH_EXIT)); diff --git a/js/src/jstracer.h b/js/src/jstracer.h index 82a1b13cdb43..61dca54ecd8c 100644 --- a/js/src/jstracer.h +++ b/js/src/jstracer.h @@ -687,6 +687,15 @@ class TraceRecorder : public avmplus::GCObject { nanojit::LIns*& ops_ins, size_t op_offset = 0); JS_REQUIRES_STACK JSRecordingStatus test_property_cache(JSObject* obj, nanojit::LIns* obj_ins, JSObject*& obj2, jsuword& pcval); + JS_REQUIRES_STACK JSRecordingStatus guardNativePropertyOp(JSObject* aobj, + nanojit::LIns* map_ins); + JS_REQUIRES_STACK JSRecordingStatus guardPropertyCacheHit(nanojit::LIns* obj_ins, + nanojit::LIns* map_ins, + JSObject* aobj, + JSObject* obj2, + JSPropCacheEntry* entry, + jsuword& pcval); + void stobj_set_fslot(nanojit::LIns *obj_ins, unsigned slot, nanojit::LIns* v_ins, const char *name); void stobj_set_dslot(nanojit::LIns *obj_ins, unsigned slot, nanojit::LIns*& dslots_ins, @@ -704,8 +713,6 @@ class TraceRecorder : public avmplus::GCObject { stobj_get_fslot(obj_ins, JSSLOT_PRIVATE), lir->insImmPtr((void*) ~mask)); } - JSRecordingStatus native_set(nanojit::LIns* obj_ins, JSScopeProperty* sprop, - nanojit::LIns*& dslots_ins, nanojit::LIns* v_ins); JSRecordingStatus native_get(nanojit::LIns* obj_ins, nanojit::LIns* pobj_ins, JSScopeProperty* sprop, nanojit::LIns*& dslots_ins, nanojit::LIns*& v_ins); @@ -722,6 +729,13 @@ class TraceRecorder : public avmplus::GCObject { JS_REQUIRES_STACK JSRecordingStatus getProp(jsval& v); JS_REQUIRES_STACK JSRecordingStatus getThis(nanojit::LIns*& this_ins); + JS_REQUIRES_STACK JSRecordingStatus nativeSet(JSObject* obj, nanojit::LIns* obj_ins, + JSScopeProperty* sprop, + jsval v, nanojit::LIns* v_ins); + JS_REQUIRES_STACK JSRecordingStatus setProp(jsval &l, JSPropCacheEntry* entry, + JSScopeProperty* sprop, + jsval &v, nanojit::LIns*& v_ins); + JS_REQUIRES_STACK void box_jsval(jsval v, nanojit::LIns*& v_ins); JS_REQUIRES_STACK void unbox_jsval(jsval v, nanojit::LIns*& v_ins, VMSideExit* exit); JS_REQUIRES_STACK bool guardClass(JSObject* obj, nanojit::LIns* obj_ins, JSClass* clasp, @@ -748,8 +762,15 @@ class TraceRecorder : public avmplus::GCObject { jsval* rval); JS_REQUIRES_STACK JSRecordingStatus interpretedFunctionCall(jsval& fval, JSFunction* fun, uintN argc, bool constructing); + JS_REQUIRES_STACK void propagateFailureToBuiltinStatus(nanojit::LIns *ok_ins, + nanojit::LIns *&status_ins); JS_REQUIRES_STACK JSRecordingStatus emitNativeCall(JSTraceableNative* known, uintN argc, nanojit::LIns* args[]); + JS_REQUIRES_STACK void emitNativePropertyOp(JSScope* scope, + JSScopeProperty* sprop, + nanojit::LIns* obj_ins, + bool setflag, + nanojit::LIns* boxed_ins); JS_REQUIRES_STACK JSRecordingStatus callTraceableNative(JSFunction* fun, uintN argc, bool constructing); JS_REQUIRES_STACK JSRecordingStatus callNative(uintN argc, JSOp mode); diff --git a/js/src/trace-test.js b/js/src/trace-test.js index df5f7746560f..5525267faef4 100644 --- a/js/src/trace-test.js +++ b/js/src/trace-test.js @@ -5497,6 +5497,21 @@ testOwnPropertyWithInOperator.jitstats = { }; test(testEliminatedGuardWithinAnchor); +function testNativeSetter() { + var re = /foo/; + var N = RUNLOOP + 10; + for (var i = 0; i < N; i++) + re.lastIndex = i; + assertEq(re.lastIndex, N - 1); +} +testNativeSetter.jitstats = { + recorderStarted: 1, + recorderAborted: 0, + traceTriggered: 1, + sideExitIntoInterpreter: 1 +}; +test(testNativeSetter); + /***************************************************************************** * * * _____ _ _ _____ ______ _____ _______ * From f9b40174d451439d0a38f8929ad12c7811f3c474 Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Mon, 27 Jul 2009 18:13:53 -0700 Subject: [PATCH 25/61] Bug 495329: Trace JSOP_BINDNAME/JSOP_SETNAME for closures, r=brendan --- js/src/jsbuiltins.h | 5 +++++ js/src/jsfun.cpp | 19 +++++++++++++++++-- js/src/jsfun.h | 20 +++++++++++++++++++- js/src/jstracer.cpp | 41 ++++++++++++++++++++++++++++++++++++----- 4 files changed, 77 insertions(+), 8 deletions(-) diff --git a/js/src/jsbuiltins.h b/js/src/jsbuiltins.h index baef4f07be6e..d576e32424fc 100644 --- a/js/src/jsbuiltins.h +++ b/js/src/jsbuiltins.h @@ -187,6 +187,7 @@ struct JSTraceableNative { #define _JS_CTYPE_JSVAL _JS_JSVAL_CTYPE( _JS_PTR, "","v", INFALLIBLE) #define _JS_CTYPE_JSVAL_RETRY _JS_JSVAL_CTYPE( _JS_PTR, --, --, FAIL_COOKIE) #define _JS_CTYPE_JSVAL_FAIL _JS_JSVAL_CTYPE( _JS_PTR, --, --, FAIL_STATUS) +#define _JS_CTYPE_JSID _JS_CTYPE(jsid, _JS_PTR, --, --, INFALLIBLE) #define _JS_CTYPE_BOOL _JS_CTYPE(JSBool, _JS_I32, "","i", INFALLIBLE) #define _JS_CTYPE_BOOL_RETRY _JS_CTYPE(JSBool, _JS_I32, --, --, FAIL_VOID) #define _JS_CTYPE_BOOL_FAIL _JS_CTYPE(JSBool, _JS_I32, --, --, FAIL_STATUS) @@ -444,6 +445,10 @@ JS_DECLARE_CALLINFO(js_ArrayCompPush) JS_DECLARE_CALLINFO(js_AllocFlatClosure) JS_DECLARE_CALLINFO(js_PutArguments) +/* Defined in jsfun.cpp. */ +JS_DECLARE_CALLINFO(js_SetCallVar) +JS_DECLARE_CALLINFO(js_SetCallArg) + /* Defined in jsnum.cpp. */ JS_DECLARE_CALLINFO(js_NumberToString) diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index c3076d055a0a..90fc581a95c0 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -1133,7 +1133,7 @@ js_GetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp) return CallPropertyOp(cx, obj, id, vp, JSCPK_ARG, JS_FALSE); } -static JSBool +JSBool SetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp) { return CallPropertyOp(cx, obj, id, vp, JSCPK_ARG, JS_TRUE); @@ -1154,12 +1154,27 @@ js_GetCallVarChecked(JSContext *cx, JSObject *obj, jsid id, jsval *vp) return CheckForEscapingClosure(cx, obj, vp); } -static JSBool +JSBool SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp) { return CallPropertyOp(cx, obj, id, vp, JSCPK_VAR, JS_TRUE); } +JSBool JS_FASTCALL +js_SetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval v) +{ + return CallPropertyOp(cx, obj, id, &v, JSCPK_ARG, JS_TRUE); +} + +JSBool JS_FASTCALL +js_SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval v) +{ + return CallPropertyOp(cx, obj, id, &v, JSCPK_VAR, JS_TRUE); +} + +JS_DEFINE_CALLINFO_4(extern, BOOL, js_SetCallArg, CONTEXT, OBJECT, JSID, JSVAL, 0, 0) +JS_DEFINE_CALLINFO_4(extern, BOOL, js_SetCallVar, CONTEXT, OBJECT, JSID, JSVAL, 0, 0) + static JSBool call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags, JSObject **objp) diff --git a/js/src/jsfun.h b/js/src/jsfun.h index 6be8fb2a0976..9a651cf2958c 100644 --- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -280,7 +280,25 @@ extern JSBool js_GetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp); extern JSBool -js_GetCallVar(JSContext *cx, JSObject *obj, jsval id, jsval *vp); +js_GetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp); + +extern JSBool +SetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp); + +extern JSBool +SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp); + +/* + * js_SetCallArg and js_SetCallVar are extern fastcall copies of the setter + * functions. These versions are required in order to set call vars from traces. + * The normal versions must not be fastcall because they are stored in the + * property ops map. + */ +extern JSBool JS_FASTCALL +js_SetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval v); + +extern JSBool JS_FASTCALL +js_SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval v); /* * Slower version of js_GetCallVar used when call_resolve detects an attempt to diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index dba2449d3bee..8ecbd8a80bcb 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -9452,6 +9452,29 @@ TraceRecorder::setProp(jsval &l, JSPropCacheEntry* entry, JSScopeProperty* sprop JS_ASSERT_IF(entry->vcap == PCVCAP_MAKE(entry->kshape, 0, 0), scope->has(sprop)); + // Fast path for CallClass. This is about 20% faster than the general case. + if (OBJ_GET_CLASS(cx, obj) == &js_CallClass) { + const CallInfo* ci = NULL; + if (sprop->setter == SetCallArg) + ci = &js_SetCallArg_ci; + else if (sprop->setter == SetCallVar) + ci = &js_SetCallVar_ci; + else + ABORT_TRACE("can't trace special CallClass setter"); + + LIns* v_ins = get(&v); + box_jsval(v, v_ins); + LIns* args[] = { + v_ins, + INS_CONST(SPROP_USERID(sprop)), + obj_ins, + cx_ins + }; + LIns* call_ins = lir->insCall(ci, args); + guard(false, addName(lir->ins_eq0(call_ins), "guard(set upvar)"), STATUS_EXIT); + return JSRS_CONTINUE; + } + /* * Setting a function-valued property might need to rebrand the object; we * don't trace that case. There's no need to guard on that, though, because @@ -11067,8 +11090,14 @@ TraceRecorder::record_JSOP_BINDNAME() } } - if (obj != globalObj) - ABORT_TRACE("JSOP_BINDNAME must return global object on trace"); + /* + * If obj is a js_CallClass object, then we are tracing a reference to an + * upvar in a heavyweight function. We cannot reach this point of the trace + * with a different call object because of the guard on the function call, + * so we can assume the result of the bindname is constant on this trace. + */ + if (obj != globalObj && OBJ_GET_CLASS(cx, obj) != &js_CallClass) + ABORT_TRACE("Can only trace JSOP_BINDNAME with global or call object"); // The trace is specialized to this global object. Furthermore, // we know it is the sole 'global' object on the scope chain: we @@ -11076,7 +11105,7 @@ TraceRecorder::record_JSOP_BINDNAME() // reached it starting from the function closure or the current // scopeChain, so there is nothing inner to it. So this must be // the right base object. - stack(0, INS_CONSTPTR(globalObj)); + stack(0, INS_CONSTPTR(obj)); return JSRS_CONTINUE; } @@ -11087,10 +11116,12 @@ TraceRecorder::record_JSOP_SETNAME() JS_ASSERT(!JSVAL_IS_PRIMITIVE(l)); /* - * Trace cases that are global code or in lightweight functions scoped by - * the global object only. + * Trace only cases that are global code, in lightweight functions + * scoped by the global object only, or in call objects. */ JSObject* obj = JSVAL_TO_OBJECT(l); + if (OBJ_GET_CLASS(cx, obj) == &js_CallClass) + return JSRS_CONTINUE; if (obj != cx->fp->scopeChain || obj != globalObj) ABORT_TRACE("JSOP_SETNAME left operand is not the global object"); From 5c1ca3e00a8aeee5671b21d479a76bbe8ba4ff55 Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Mon, 27 Jul 2009 18:40:12 -0700 Subject: [PATCH 26/61] Bug 506821: clean up trailing whitespace, r=brendan --- js/src/jsapi.cpp | 12 ++++++------ js/src/jsapi.h | 6 +++--- js/src/jsarray.cpp | 4 ++-- js/src/jsbuiltins.cpp | 2 +- js/src/jsbuiltins.h | 6 +++--- js/src/jscntxt.cpp | 8 ++++---- js/src/jsfun.h | 2 +- js/src/jsinterp.cpp | 8 ++++---- js/src/jsinterp.h | 6 +++--- js/src/jsinttypes.h | 2 +- js/src/jsmath.cpp | 2 +- js/src/json.cpp | 22 +++++++++++----------- js/src/jsparse.cpp | 2 +- js/src/jspubtd.h | 4 ++-- js/src/jsregexp.cpp | 6 +++--- js/src/jsscan.cpp | 14 +++++++------- js/src/jsscope.cpp | 4 ++-- js/src/jsstdint.h | 2 +- js/src/jstracer.cpp | 34 +++++++++++++++++----------------- js/src/jstracer.h | 12 ++++++------ js/src/prmjtime.cpp | 12 ++++++------ js/src/resource.h | 2 +- 22 files changed, 86 insertions(+), 86 deletions(-) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 93d3a2e542a6..f93cd95bf3c3 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1328,7 +1328,7 @@ JS_InitStandardClasses(JSContext *cx, JSObject *obj) /* Define a top-level property 'undefined' with the undefined value. */ atom = cx->runtime->atomState.typeAtoms[JSTYPE_VOID]; if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID, - JS_PropertyStub, JS_PropertyStub, JSPROP_PERMANENT, + JS_PropertyStub, JS_PropertyStub, JSPROP_PERMANENT, NULL)) { return JS_FALSE; } @@ -1535,7 +1535,7 @@ JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsval id, if (idstr == ATOM_TO_STRING(atom)) { *resolved = JS_TRUE; return OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID, - JS_PropertyStub, JS_PropertyStub, + JS_PropertyStub, JS_PropertyStub, JSPROP_PERMANENT, NULL); } @@ -1630,7 +1630,7 @@ JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj) atom = rt->atomState.typeAtoms[JSTYPE_VOID]; if (!AlreadyHasOwnProperty(cx, obj, atom) && !OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID, - JS_PropertyStub, JS_PropertyStub, JSPROP_PERMANENT, + JS_PropertyStub, JS_PropertyStub, JSPROP_PERMANENT, NULL)) { return JS_FALSE; } @@ -3001,7 +3001,7 @@ DefinePropertyById(JSContext *cx, JSObject *obj, jsid id, jsval value, attrs, flags, tinyid, NULL); } return OBJ_DEFINE_PROPERTY(cx, obj, id, value, getter, setter, attrs, - NULL); + NULL); } static JSBool @@ -3720,7 +3720,7 @@ JS_HasUCProperty(JSContext *cx, JSObject *obj, JSProperty *prop; CHECK_REQUEST(cx); - ok = LookupUCProperty(cx, obj, name, namelen, + ok = LookupUCProperty(cx, obj, name, namelen, JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING, &obj2, &prop); if (ok) { @@ -5197,7 +5197,7 @@ JS_SetOperationCallback(JSContext *cx, JSOperationCallback callback) { #ifdef JS_THREADSAFE JS_ASSERT(CURRENT_THREAD_IS_ME(cx->thread)); -#endif +#endif JSOperationCallback old = cx->operationCallback; cx->operationCallback = callback; return old; diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 8d6de69f2301..2a6a422331d0 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -2298,14 +2298,14 @@ JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, uintN argc, * These functions allow setting an operation callback that will be called * from the thread the context is associated with some time after any thread * triggered the callback using JS_TriggerOperationCallback(cx). - * + * * In a threadsafe build the engine internally triggers operation callbacks * under certain circumstances (i.e. GC and title transfer) to force the - * context to yield its current request, which the engine always + * context to yield its current request, which the engine always * automatically does immediately prior to calling the callback function. * The embedding should thus not rely on callbacks being triggered through * the external API only. - * + * * Important note: Additional callbacks can occur inside the callback handler * if it re-enters the JS engine. The embedding must ensure that the callback * is disconnected before attempting such re-entry. diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 2d121e3ddc4b..d3bff3916b4d 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -1368,7 +1368,7 @@ array_toSource(JSContext *cx, uintN argc, jsval *vp) JSBool ok = JS_TRUE; /* - * This object will take responsibility for the jschar buffer until the + * This object will take responsibility for the jschar buffer until the * buffer is transferred to the returned JSString. */ JSTempVector buf(cx); @@ -1520,7 +1520,7 @@ array_toString_sub(JSContext *cx, JSObject *obj, JSBool locale, } /* - * This object will take responsibility for the jschar buffer until the + * This object will take responsibility for the jschar buffer until the * buffer is transferred to the returned JSString. */ JSTempVector buf(cx); diff --git a/js/src/jsbuiltins.cpp b/js/src/jsbuiltins.cpp index fe088a03aad8..1f1408bf460c 100644 --- a/js/src/jsbuiltins.cpp +++ b/js/src/jsbuiltins.cpp @@ -129,7 +129,7 @@ js_BoxInt32(JSContext* cx, int32 i) if (!js_NewDoubleInRootedValue(cx, d, &v)) return JSVAL_ERROR_COOKIE; return v; -} +} JS_DEFINE_CALLINFO_2(extern, JSVAL, js_BoxInt32, CONTEXT, INT32, 1, 1) jsdouble FASTCALL diff --git a/js/src/jsbuiltins.h b/js/src/jsbuiltins.h index d576e32424fc..96a1c904f34f 100644 --- a/js/src/jsbuiltins.h +++ b/js/src/jsbuiltins.h @@ -86,7 +86,7 @@ struct JSTraceableNative { const nanojit::CallInfo *builtin; const char *prefix; const char *argtypes; - uintN flags; /* JSTNErrType | JSTN_UNBOX_AFTER | JSTN_MORE | + uintN flags; /* JSTNErrType | JSTN_UNBOX_AFTER | JSTN_MORE | JSTN_CONSTRUCTOR */ }; @@ -117,7 +117,7 @@ struct JSTraceableNative { #endif /* - * Supported types for builtin functions. + * Supported types for builtin functions. * * Types with -- for the two string fields are not permitted as argument types * in JS_DEFINE_TRCINFO. @@ -165,7 +165,7 @@ struct JSTraceableNative { * trace. If an exception is pending, it is thrown; otherwise, we assume the * builtin had no side effects and retry the current bytecode in the * interpreter. - * + * * So a builtin must not return a value indicating failure after causing side * effects (such as reporting an error), without setting an exception pending. * The operation would be retried, despite the first attempt's observable diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index 9ce2db55eb7d..6bcd70f97f3f 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -819,7 +819,7 @@ js_NextActiveContext(JSRuntime *rt, JSContext *cx) return cx; #else return js_ContextIterator(rt, JS_FALSE, &iter); -#endif +#endif } #ifdef JS_THREADSAFE @@ -1738,10 +1738,10 @@ JSBool js_InvokeOperationCallback(JSContext *cx) { JS_ASSERT(cx->operationCallbackFlag); - + /* * Reset the callback flag first, then yield. If another thread is racing - * us here we will accumulate another callback request which will be + * us here we will accumulate another callback request which will be * serviced at the next opportunity. */ cx->operationCallbackFlag = 0; @@ -1755,7 +1755,7 @@ js_InvokeOperationCallback(JSContext *cx) */ if (cx->runtime->gcIsNeeded) js_GC(cx, GC_NORMAL); -#ifdef JS_THREADSAFE +#ifdef JS_THREADSAFE else JS_YieldRequest(cx); #endif diff --git a/js/src/jsfun.h b/js/src/jsfun.h index 9a651cf2958c..cbf76932d6c8 100644 --- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -289,7 +289,7 @@ extern JSBool SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp); /* - * js_SetCallArg and js_SetCallVar are extern fastcall copies of the setter + * js_SetCallArg and js_SetCallVar are extern fastcall copies of the setter * functions. These versions are required in order to set call vars from traces. * The normal versions must not be fastcall because they are stored in the * property ops map. diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 25506179975c..d77602e4782f 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -1534,7 +1534,7 @@ js_Execute(JSContext *cx, JSObject *chain, JSScript *script, js_LeaveTrace(cx); #ifdef JS_TRACER - /* + /* * The JIT requires that the scope chain here is equal to its global * object. Disable the JIT for this call if this condition is not true. */ @@ -2095,7 +2095,7 @@ js_GetUpvar(JSContext *cx, uintN level, uintN cookie) } else if (slot == CALLEE_UPVAR_SLOT) { vp = &fp->argv[-2]; slot = 0; - } else { + } else { slot -= fp->fun->nargs; JS_ASSERT(slot < fp->script->nslots); vp = fp->slots; @@ -2132,7 +2132,7 @@ js_TraceOpcode(JSContext *cx) fp->script, cx->tracePrevPc); /* - * If there aren't that many elements on the stack, then + * If there aren't that many elements on the stack, then * we have probably entered a new frame, and printing output * would just be misleading. */ @@ -2717,7 +2717,7 @@ js_Interpret(JSContext *cx) * 'op=x; DO_OP()' to let another opcode's implementation finish * their work, and many opcodes share entry points with a run of * consecutive BEGIN_CASEs. - * + * * Take care to trace OP only when it is the opcode fetched from * the instruction stream, so the trace matches what one would * expect from looking at the code. (We do omit POPs after SETs; diff --git a/js/src/jsinterp.h b/js/src/jsinterp.h index 23e77a7171ef..5190a06114a0 100644 --- a/js/src/jsinterp.h +++ b/js/src/jsinterp.h @@ -90,7 +90,7 @@ struct JSStackFrame { * variables on the stack initially, note when they are closed * over, and copy those that are out to the heap when we leave * their dynamic scope. - * + * * The bytecode compiler produces a tree of block objects * accompanying each JSScript representing those lexical blocks in * the script that have let-bound variables associated with them. @@ -102,7 +102,7 @@ struct JSStackFrame { * When we are in the static scope of such a block, blockChain * points to its compiler-allocated block object; otherwise, it is * NULL. - * + * * scopeChain is the current scope chain, including 'call' and * 'block' objects for those function calls and lexical blocks * whose static scope we are currently executing in, and 'with' @@ -158,7 +158,7 @@ static JS_INLINE uintN GlobalVarCount(JSStackFrame *fp) { uintN n; - + JS_ASSERT(!fp->fun); n = fp->script->nfixed; if (fp->script->regexpsOffset != 0) diff --git a/js/src/jsinttypes.h b/js/src/jsinttypes.h index e239551f90c3..7e06b3edf0d5 100644 --- a/js/src/jsinttypes.h +++ b/js/src/jsinttypes.h @@ -43,7 +43,7 @@ * Types: * JSInt, JSUint (for = 8, 16, 32, and 64) * JSIntPtr, JSUIntPtr - * + * * JSInt and JSUint are signed and unsigned types known to be * bits long. Note that neither JSInt8 nor JSUInt8 is necessarily * equivalent to a plain "char". diff --git a/js/src/jsmath.cpp b/js/src/jsmath.cpp index daed88393b99..dd6fd51665c1 100644 --- a/js/src/jsmath.cpp +++ b/js/src/jsmath.cpp @@ -231,7 +231,7 @@ static inline jsdouble JS_FASTCALL math_ceil_kernel(jsdouble x) { #ifdef __APPLE__ - if (x < 0 && x > -1.0) + if (x < 0 && x > -1.0) return js_copysign(0, -1); #endif return ceil(x); diff --git a/js/src/json.cpp b/js/src/json.cpp index 7f7c2f2dfe43..43bf3ab03259 100644 --- a/js/src/json.cpp +++ b/js/src/json.cpp @@ -78,7 +78,7 @@ js_json_parse(JSContext *cx, uintN argc, jsval *vp) jsval *argv = vp + 2; jsval reviver = JSVAL_NULL; JSAutoTempValueRooter(cx, 1, &reviver); - + if (!JS_ConvertArguments(cx, argc, argv, "S / v", &s, &reviver)) return JS_FALSE; @@ -523,7 +523,7 @@ Str(JSContext *cx, jsid id, JSObject *holder, StringifyContext *scx, jsval *vp, char numBuf[DTOSTR_STANDARD_BUFFER_SIZE], *numStr; jsdouble d = JSVAL_IS_INT(*vp) ? jsdouble(JSVAL_TO_INT(*vp)) : *JSVAL_TO_DOUBLE(*vp); - numStr = JS_dtostr(numBuf, sizeof numBuf, DTOSTR_STANDARD, 0, d); + numStr = JS_dtostr(numBuf, sizeof numBuf, DTOSTR_STANDARD, 0, d); if (!numStr) { JS_ReportOutOfMemory(cx); return JS_FALSE; @@ -546,7 +546,7 @@ Str(JSContext *cx, jsid id, JSObject *holder, StringifyContext *scx, jsval *vp, return ok; } - + *vp = JSVAL_VOID; return JS_TRUE; } @@ -640,7 +640,7 @@ static JSBool Walk(JSContext *cx, jsid id, JSObject *holder, jsval reviver, jsval *vp) { JS_CHECK_RECURSION(cx, return JS_FALSE); - + if (!OBJ_GET_PROPERTY(cx, holder, id, vp)) return JS_FALSE; @@ -649,7 +649,7 @@ Walk(JSContext *cx, jsid id, JSObject *holder, jsval reviver, jsval *vp) if (!JSVAL_IS_PRIMITIVE(*vp) && !js_IsCallable(obj = JSVAL_TO_OBJECT(*vp), cx)) { jsval propValue = JSVAL_NULL; JSAutoTempValueRooter tvr(cx, 1, &propValue); - + if(OBJ_IS_ARRAY(cx, obj)) { jsuint length = 0; if (!js_GetLengthProperty(cx, obj, &length)) @@ -713,7 +713,7 @@ Walk(JSContext *cx, jsid id, JSObject *holder, jsval reviver, jsval *vp) static JSBool Revive(JSContext *cx, jsval reviver, jsval *vp) { - + JSObject *obj = js_NewObject(cx, &js_ObjectClass, NULL, NULL); if (!obj) return JS_FALSE; @@ -820,7 +820,7 @@ PushState(JSContext *cx, JSONParser *jp, JSONParserState state) if (*jp->statep == JSON_PARSE_STATE_FINISHED) { // extra input JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_JSON_BAD_PARSE); - return JS_FALSE; + return JS_FALSE; } jp->statep++; @@ -993,10 +993,10 @@ HandleNumber(JSContext *cx, JSONParser *jp, const jschar *buf, uint32 len) return JS_FALSE; } - jsval numVal; + jsval numVal; if (!JS_NewNumberValue(cx, val, &numVal)) return JS_FALSE; - + return PushPrimitive(cx, jp, numVal); } @@ -1248,7 +1248,7 @@ js_ConsumeJSONText(JSContext *cx, JSONParser *jp, const jschar *data, uint32 len JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_JSON_BAD_PARSE); return JS_FALSE; } - + if (++(jp->numHex) == 4) { js_FastAppendChar(&jp->buffer, jp->hexChar); jp->hexChar = 0; @@ -1265,7 +1265,7 @@ js_ConsumeJSONText(JSContext *cx, JSONParser *jp, const jschar *data, uint32 len i--; if (!PopState(cx, jp)) return JS_FALSE; - + if (!HandleData(cx, jp, JSON_DATA_KEYWORD)) return JS_FALSE; } diff --git a/js/src/jsparse.cpp b/js/src/jsparse.cpp index 8d87d9df77e5..161dfbc94ae2 100644 --- a/js/src/jsparse.cpp +++ b/js/src/jsparse.cpp @@ -3802,7 +3802,7 @@ CheckDestructuring(JSContext *cx, BindData *data, /* * This is a greatly pared down version of CheckDestructuring that extends the * pn_pos.end source coordinate of each name in a destructuring binding such as - * + * * var [x, y] = [function () y, 42]; * * to cover its corresponding initializer, so that the initialized binding does diff --git a/js/src/jspubtd.h b/js/src/jspubtd.h index 6c28b136a792..c2068d65d07c 100644 --- a/js/src/jspubtd.h +++ b/js/src/jspubtd.h @@ -106,8 +106,8 @@ typedef enum JSAccessMode { JSACC_PROTO = 0, /* XXXbe redundant w.r.t. id */ JSACC_PARENT = 1, /* XXXbe redundant w.r.t. id */ - /* - * enum value #2 formerly called JSACC_IMPORT, + /* + * enum value #2 formerly called JSACC_IMPORT, * gap preserved for ABI compatibility. */ diff --git a/js/src/jsregexp.cpp b/js/src/jsregexp.cpp index 960593e235a1..05762c296b49 100644 --- a/js/src/jsregexp.cpp +++ b/js/src/jsregexp.cpp @@ -1997,7 +1997,7 @@ CompileRegExpToAST(JSContext* cx, JSTokenStream* ts, + GetCompactIndexWidth(len); return JS_TRUE; } - + return ParseRegExp(&state); } @@ -2410,7 +2410,7 @@ class RegExpNativeCompiler { LIns *branch = lir->insBranch(LIR_jt, test, 0); extras[i].match = branch; } - + fails.pushBack(lir->insBranch(LIR_jf, lir->ins2(LIR_eq, text_ch, lir->insImm(ch)), 0)); for (int i = 0; i < nextras; ++i) @@ -2418,7 +2418,7 @@ class RegExpNativeCompiler { return lir->ins2(LIR_piadd, pos, lir->insImm(2)); } - JS_INLINE bool hasCases(jschar ch) + JS_INLINE bool hasCases(jschar ch) { return JS_TOLOWER(ch) != JS_TOUPPER(ch); } diff --git a/js/src/jsscan.cpp b/js/src/jsscan.cpp index 4cab27e92684..37e50a80d85a 100644 --- a/js/src/jsscan.cpp +++ b/js/src/jsscan.cpp @@ -308,7 +308,7 @@ GetChar(JSTokenStream *ts) ts->flags |= TSF_EOF; return EOF; } - + /* Fill ts->userbuf so that \r and \r\n convert to \n. */ crflag = (ts->flags & TSF_CRFLAG) != 0; len = js_fgets(cbuf, JS_LINE_LIMIT - crflag, ts->file); @@ -336,7 +336,7 @@ GetChar(JSTokenStream *ts) ts->listener(ts->filename, ts->lineno, ts->userbuf.ptr, len, &ts->listenerTSData, ts->listenerData); } - + nl = ts->saveEOL; if (!nl) { /* @@ -362,7 +362,7 @@ GetChar(JSTokenStream *ts) } } } - + /* * If there was a line terminator, copy thru it into linebuf. * Else copy JS_LINE_LIMIT-1 bytes into linebuf. @@ -378,7 +378,7 @@ GetChar(JSTokenStream *ts) js_strncpy(ts->linebuf.base, ts->userbuf.ptr, len); ts->userbuf.ptr += len; olen = len; - + /* * Make sure linebuf contains \n for EOL (don't do this in * userbuf because the user's string might be readonly). @@ -420,11 +420,11 @@ GetChar(JSTokenStream *ts) ts->linebuf.base[len-1] = '\n'; } } - + /* Reset linebuf based on adjusted segment length. */ ts->linebuf.limit = ts->linebuf.base + len; ts->linebuf.ptr = ts->linebuf.base; - + /* Update position of linebuf within physical userbuf line. */ if (!(ts->flags & TSF_NLFLAG)) ts->linepos += ts->linelen; @@ -434,7 +434,7 @@ GetChar(JSTokenStream *ts) ts->flags |= TSF_NLFLAG; else ts->flags &= ~TSF_NLFLAG; - + /* Update linelen from original segment length. */ ts->linelen = olen; } diff --git a/js/src/jsscope.cpp b/js/src/jsscope.cpp index 7da51cd43f71..929f01f72715 100644 --- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -1594,7 +1594,7 @@ JSScope::replacingShapeChange(JSContext *cx, JSScopeProperty *sprop, JSScopeProp { if (shape == sprop->shape) shape = newsprop->shape; - else + else generateOwnShape(cx); } @@ -1604,7 +1604,7 @@ JSScope::sealingShapeChange(JSContext *cx) generateOwnShape(cx); } -void +void JSScope::shadowingShapeChange(JSContext *cx, JSScopeProperty *sprop) { generateOwnShape(cx); diff --git a/js/src/jsstdint.h b/js/src/jsstdint.h index 1ce569aea1b5..247149bc592d 100644 --- a/js/src/jsstdint.h +++ b/js/src/jsstdint.h @@ -40,7 +40,7 @@ /* * This header provides definitions for the types we use, * even on systems that lack . - * + * * NOTE: This header should only be included in private SpiderMonkey * code; public headers should use only the JS{Int,Uint}N types; see * the comment for them in "jsinttypes.h". diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 8ecbd8a80bcb..f693fcd16847 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -1757,7 +1757,7 @@ TraceRecorder::isGlobal(jsval* p) const (size_t(p - globalObj->dslots) < (STOBJ_NSLOTS(globalObj) - JS_INITIAL_NSLOTS))); } -/* +/* * Return the offset in the native stack for the given jsval. More formally, * |p| must be the address of a jsval that is represented in the native stack * area. The return value is the offset, from InterpState::stackBase, in bytes, @@ -2240,7 +2240,7 @@ js_GetUpvarStackOnTrace(JSContext* cx, uint32 upvarLevel, int32 slot, uint32 cal } /* - * Generic function to read upvars from Call objects of active heavyweight functions. + * Generic function to read upvars from Call objects of active heavyweight functions. * callee Callee Function object in which the upvar is accessed. * scopeIndex Number of parent steps to make from |callee| to find upvar definition. * This must be at least 1 because |callee| is a Function and we must reach a Call. @@ -2249,7 +2249,7 @@ js_GetUpvarStackOnTrace(JSContext* cx, uint32 upvarLevel, int32 slot, uint32 cal */ template uint32 JS_INLINE -js_GetFromClosure(JSContext* cx, JSObject* callee, uint32 scopeIndex, uint32 slot, uint32 callDepth, +js_GetFromClosure(JSContext* cx, JSObject* callee, uint32 scopeIndex, uint32 slot, uint32 callDepth, double* result) { JS_ASSERT(scopeIndex >= 1); @@ -2305,7 +2305,7 @@ private: }; uint32 JS_FASTCALL -js_GetClosureArg(JSContext* cx, JSObject* callee, uint32 scopeIndex, uint32 slot, uint32 callDepth, +js_GetClosureArg(JSContext* cx, JSObject* callee, uint32 scopeIndex, uint32 slot, uint32 callDepth, double* result) { return js_GetFromClosure(cx, callee, scopeIndex, slot, callDepth, result); @@ -2320,7 +2320,7 @@ private: }; uint32 JS_FASTCALL -js_GetClosureVar(JSContext* cx, JSObject* callee, uint32 scopeIndex, uint32 slot, uint32 callDepth, +js_GetClosureVar(JSContext* cx, JSObject* callee, uint32 scopeIndex, uint32 slot, uint32 callDepth, double* result) { return js_GetFromClosure(cx, callee, scopeIndex, slot, callDepth, result); @@ -4788,14 +4788,14 @@ js_AttemptToExtendTree(JSContext* cx, VMSideExit* anchor, VMSideExit* exitedFrom if (e2->numGlobalSlots < e1->numGlobalSlots) { /* * Watch out for an extremely rare case (bug 502714). The sequence of events is: - * + * * 1) Inner tree compiles not knowing about global X (which has type A). * 2) Inner tree learns about global X and specializes it to a different type * (type B). * 3) Outer tree records inner tree with global X as type A, exiting as B. * 4) Outer tree now has a nesting guard with typeof(X)=B. * 5) Inner tree takes its original exit that does not know about X. - * + * * In this case, the nesting guard fails, and now it is illegal to use the nested * typemap entry for X. The correct entry is in the inner guard's TreeInfo, * analogous to the solution for bug 476653. @@ -6523,9 +6523,9 @@ TraceRecorder::frameIfInRange(JSObject* obj, unsigned* depthp) const return NULL; } -JS_DEFINE_CALLINFO_6(extern, UINT32, js_GetClosureVar, CONTEXT, OBJECT, UINT32, +JS_DEFINE_CALLINFO_6(extern, UINT32, js_GetClosureVar, CONTEXT, OBJECT, UINT32, UINT32, UINT32, DOUBLEPTR, 0, 0) -JS_DEFINE_CALLINFO_6(extern, UINT32, js_GetClosureArg, CONTEXT, OBJECT, UINT32, +JS_DEFINE_CALLINFO_6(extern, UINT32, js_GetClosureArg, CONTEXT, OBJECT, UINT32, UINT32, UINT32, DOUBLEPTR, 0, 0) /* @@ -6622,13 +6622,13 @@ TraceRecorder::scopeChainProp(JSObject* obj, jsval*& vp, LIns*& ins, bool& track LIns* callee_ins = get(&cx->fp->argv[-2]); LIns* outp = lir->insAlloc(sizeof(double)); - LIns* args[] = { + LIns* args[] = { outp, INS_CONST(callDepth), INS_CONST(slot), - INS_CONST(scopeIndex), + INS_CONST(scopeIndex), callee_ins, - cx_ins + cx_ins }; const CallInfo* ci; if (sprop->getter == js_GetCallArg) @@ -9700,7 +9700,7 @@ TraceRecorder::record_JSOP_GETELEM() typemap_ins = lir->ins2(LIR_add, fip_ins, INS_CONST(sizeof(FrameInfo) + 2/*callee,this*/ * sizeof(JSTraceType))); } - LIns* typep_ins = lir->ins2(LIR_add, typemap_ins, + LIns* typep_ins = lir->ins2(LIR_add, typemap_ins, lir->ins2(LIR_mul, idx_ins, INS_CONST(sizeof(JSTraceType)))); LIns* type_ins = lir->insLoad(LIR_ldcb, typep_ins, 0); guard(true, @@ -9709,7 +9709,7 @@ TraceRecorder::record_JSOP_GETELEM() BRANCH_EXIT); // Read the value out of the native stack area. - guard(true, lir->ins2(LIR_ult, idx_ins, INS_CONST(afp->argc)), + guard(true, lir->ins2(LIR_ult, idx_ins, INS_CONST(afp->argc)), snapshot(BRANCH_EXIT)); size_t stackOffset = -treeInfo->nativeStackBase + nativeStackOffset(&afp->argv[0]); LIns* args_addr_ins = lir->ins2(LIR_add, lirbuf->sp, INS_CONST(stackOffset)); @@ -9717,7 +9717,7 @@ TraceRecorder::record_JSOP_GETELEM() lir->ins2(LIR_mul, idx_ins, INS_CONST(sizeof(double)))); v_ins = stackLoad(argi_addr_ins, type); } else { - guard(false, lir->ins2(LIR_ult, idx_ins, INS_CONST(afp->argc)), + guard(false, lir->ins2(LIR_ult, idx_ins, INS_CONST(afp->argc)), snapshot(BRANCH_EXIT)); v_ins = INS_VOID(); } @@ -10225,7 +10225,7 @@ TraceRecorder::record_JSOP_APPLY() aobj = JSVAL_TO_OBJECT(vp[3]); aobj_ins = get(&vp[3]); - /* + /* * We trace dense arrays and arguments objects. The code we generate for apply * uses imacros to handle a specific number of arguments. */ @@ -11093,7 +11093,7 @@ TraceRecorder::record_JSOP_BINDNAME() /* * If obj is a js_CallClass object, then we are tracing a reference to an * upvar in a heavyweight function. We cannot reach this point of the trace - * with a different call object because of the guard on the function call, + * with a different call object because of the guard on the function call, * so we can assume the result of the bindname is constant on this trace. */ if (obj != globalObj && OBJ_GET_CLASS(cx, obj) != &js_CallClass) diff --git a/js/src/jstracer.h b/js/src/jstracer.h index 61dca54ecd8c..523ea7047457 100644 --- a/js/src/jstracer.h +++ b/js/src/jstracer.h @@ -281,7 +281,7 @@ typedef int8_t JSTraceType; /* * This indicates an invalid type or error. Note that it should not be used in typemaps, - * because it is the wrong size. It can only be used as a uint32, for example as the + * because it is the wrong size. It can only be used as a uint32, for example as the * return value from a function that returns a type as a uint32. */ const uint32 TT_INVALID = uint32(-1); @@ -332,7 +332,7 @@ public: _(TIMEOUT) \ _(DEEP_BAIL) \ _(STATUS) - + enum ExitType { #define MAKE_EXIT_CODE(x) x##_EXIT, @@ -408,7 +408,7 @@ struct FrameInfo { * stack frame for the caller *before* the slots covered by spdist. * This may be negative if the caller is the top level script. * The key fact is that if we let 'cpos' be the start of the caller's - * native stack frame, then (cpos + spoffset) points to the first + * native stack frame, then (cpos + spoffset) points to the first * non-argument slot in the callee's native stack frame. */ int32 spoffset; @@ -548,7 +548,7 @@ struct JSRecordingStatus JSRS_ERROR = { JSRS_ERROR_code }; #define STATUS_ABORTS_RECORDING(s) ((s) == JSRS_STOP || (s) == JSRS_ERROR) #else enum JSRecordingStatus { - JSRS_ERROR, // Error; propagate to interpreter. + JSRS_ERROR, // Error; propagate to interpreter. JSRS_STOP, // Abort recording. JSRS_CONTINUE, // Continue recording. JSRS_IMACRO // Entered imacro; continue recording. @@ -995,13 +995,13 @@ js_LogTraceVisState(TraceVisState s, TraceVisExitReason r) } } -static inline void +static inline void js_EnterTraceVisState(TraceVisState s, TraceVisExitReason r) { js_LogTraceVisState(s, r); } -static inline void +static inline void js_ExitTraceVisState(TraceVisExitReason r) { js_LogTraceVisState(S_EXITLAST, r); diff --git a/js/src/prmjtime.cpp b/js/src/prmjtime.cpp index 61b99b65bdcc..986f480a30be 100644 --- a/js/src/prmjtime.cpp +++ b/js/src/prmjtime.cpp @@ -109,7 +109,7 @@ PRMJ_LocalGMTDifference() #if defined(XP_WIN) && !defined(WINCE) /* Windows does not follow POSIX. Updates to the - * TZ environment variable are not reflected + * TZ environment variable are not reflected * immediately on that platform as they are * on UNIX systems without this call. */ @@ -170,8 +170,8 @@ static const JSInt64 win2un = JSLL_INIT(0x19DB1DE, 0xD53E8000); #if defined(HAVE_GETSYSTEMTIMEASFILETIME) inline void LowResTime(LPFILETIME lpft) -{ - GetSystemTimeAsFileTime(lpft); +{ + GetSystemTimeAsFileTime(lpft); } #elif defined(HAVE_SYSTEMTIMETOFILETIME) inline void @@ -229,9 +229,9 @@ NowCalibrate() LowResTime(&ft); } while (memcmp(&ftStart,&ft, sizeof(ft)) == 0); timeEndPeriod(1); - + #ifdef WINCE - calibration.granularity = (FILETIME2INT64(ft) - + calibration.granularity = (FILETIME2INT64(ft) - FILETIME2INT64(ftStart))/10; #endif /* @@ -581,7 +581,7 @@ PRMJ_DSTOffset(JSInt64 local_time) #if defined(XP_WIN) && !defined(WINCE) /* Windows does not follow POSIX. Updates to the - * TZ environment variable are not reflected + * TZ environment variable are not reflected * immediately on that platform as they are * on UNIX systems without this call. */ diff --git a/js/src/resource.h b/js/src/resource.h index 9301810e4448..59dbde3775e9 100644 --- a/js/src/resource.h +++ b/js/src/resource.h @@ -4,7 +4,7 @@ // // Next default values for new objects -// +// #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 101 From dce181923ffc352aacb7a81f865b1ec06e26e862 Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Mon, 27 Jul 2009 18:49:27 -0700 Subject: [PATCH 27/61] Fix incompatible enum warnings in static asserts --- js/src/jstracer.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index f693fcd16847..a2c45c0b627d 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -515,9 +515,9 @@ static inline JSTraceType getPromotedType(jsval v) } uint8_t tag = JSVAL_TAG(v); JS_ASSERT(tag == JSVAL_DOUBLE || tag == JSVAL_STRING || tag == JSVAL_BOOLEAN); - JS_STATIC_ASSERT(TT_DOUBLE == JSVAL_DOUBLE); - JS_STATIC_ASSERT(TT_STRING == JSVAL_STRING); - JS_STATIC_ASSERT(TT_PSEUDOBOOLEAN == JSVAL_BOOLEAN); + JS_STATIC_ASSERT(static_cast(TT_DOUBLE) == JSVAL_DOUBLE); + JS_STATIC_ASSERT(static_cast(TT_STRING) == JSVAL_STRING); + JS_STATIC_ASSERT(static_cast(TT_PSEUDOBOOLEAN) == JSVAL_BOOLEAN); return JSTraceType(tag); } @@ -535,9 +535,9 @@ static inline JSTraceType getCoercedType(jsval v) } uint8_t tag = JSVAL_TAG(v); JS_ASSERT(tag == JSVAL_DOUBLE || tag == JSVAL_STRING || tag == JSVAL_BOOLEAN); - JS_STATIC_ASSERT(TT_DOUBLE == JSVAL_DOUBLE); - JS_STATIC_ASSERT(TT_STRING == JSVAL_STRING); - JS_STATIC_ASSERT(TT_PSEUDOBOOLEAN == JSVAL_BOOLEAN); + JS_STATIC_ASSERT(static_cast(TT_DOUBLE) == JSVAL_DOUBLE); + JS_STATIC_ASSERT(static_cast(TT_STRING) == JSVAL_STRING); + JS_STATIC_ASSERT(static_cast(TT_PSEUDOBOOLEAN) == JSVAL_BOOLEAN); return JSTraceType(tag); } @@ -2895,8 +2895,8 @@ TraceRecorder::determineSlotType(jsval* vp) m = TT_OBJECT; } else { JS_ASSERT(JSVAL_TAG(*vp) == JSVAL_STRING || JSVAL_TAG(*vp) == JSVAL_BOOLEAN); - JS_STATIC_ASSERT(TT_STRING == JSVAL_STRING); - JS_STATIC_ASSERT(TT_PSEUDOBOOLEAN == JSVAL_BOOLEAN); + JS_STATIC_ASSERT(static_cast(TT_STRING) == JSVAL_STRING); + JS_STATIC_ASSERT(static_cast(TT_PSEUDOBOOLEAN) == JSVAL_BOOLEAN); m = JSTraceType(JSVAL_TAG(*vp)); } JS_ASSERT(m != TT_INT32 || isInt32(*vp)); From d1254f2c2c17c11b6f40c2a2d570e91aeba53890 Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Mon, 27 Jul 2009 21:10:12 -0700 Subject: [PATCH 28/61] When finalizing, deallocate memory in a separate thread (505612, r=bent,brendan,waldo). --- js/src/Makefile.in | 2 + js/src/jsapi.cpp | 84 ++++++++++++----------------- js/src/jsarena.cpp | 12 ++--- js/src/jsarray.cpp | 28 +++++----- js/src/jsatom.cpp | 2 +- js/src/jscntxt.cpp | 66 +++++++++++------------ js/src/jscntxt.h | 104 ++++++++++++++++++++++++++++++++++-- js/src/jsdate.cpp | 2 +- js/src/jsdbgapi.cpp | 30 +++++------ js/src/jsdhash.cpp | 12 ++--- js/src/jsdtoa.cpp | 6 +-- js/src/jsemit.cpp | 23 ++++---- js/src/jsexn.cpp | 24 ++++----- js/src/jsfile.cpp | 127 ++++++++++++++++++++++---------------------- js/src/jsfun.cpp | 24 ++++----- js/src/jsgc.cpp | 30 +++++++---- js/src/jsgc.h | 23 ++++++++ js/src/jshash.cpp | 4 +- js/src/jsinterp.cpp | 8 +-- js/src/jsiter.cpp | 6 +-- js/src/jslock.cpp | 10 ++-- js/src/jsnum.cpp | 24 ++++----- js/src/jsobj.cpp | 42 +++++++-------- js/src/json.cpp | 7 ++- js/src/jsopcode.cpp | 86 +++++++++++++++--------------- js/src/jsparse.cpp | 4 +- js/src/jsprf.cpp | 20 +++---- js/src/jspubtd.h | 1 - js/src/jsregexp.cpp | 57 ++++++++++---------- js/src/jsscan.cpp | 26 ++++----- js/src/jsscope.cpp | 30 +++++------ js/src/jsscript.cpp | 32 +++++------ js/src/jsstr.cpp | 97 +++++++++++++++++---------------- js/src/jstask.cpp | 126 +++++++++++++++++++++++++++++++++++++++++++ js/src/jstask.h | 84 +++++++++++++++++++++++++++++ js/src/jstracer.cpp | 6 +-- js/src/jsutil.cpp | 2 +- js/src/jsutil.h | 25 ++++++++- js/src/jsxdrapi.cpp | 30 +++++------ js/src/jsxml.cpp | 46 ++++++++-------- 40 files changed, 859 insertions(+), 513 deletions(-) create mode 100644 js/src/jstask.cpp create mode 100644 js/src/jstask.h diff --git a/js/src/Makefile.in b/js/src/Makefile.in index 1653c69c0e45..9e8d426ebf00 100644 --- a/js/src/Makefile.in +++ b/js/src/Makefile.in @@ -144,6 +144,7 @@ CPPSRCS = \ jsscope.cpp \ jsscript.cpp \ jsstr.cpp \ + jstask.cpp \ jsutil.cpp \ jsxdrapi.cpp \ jsxml.cpp \ @@ -200,6 +201,7 @@ INSTALLED_HEADERS = \ jsscript.h \ jsstaticcheck.h \ jsstr.h \ + jstask.h \ jstracer.h \ jstypes.h \ jsutil.h \ diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index f93cd95bf3c3..00e8a6ec37b3 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -79,6 +79,7 @@ #include "jsscope.h" #include "jsscript.h" #include "jsstr.h" +#include "jstask.h" #include "jstracer.h" #include "jsdbgapi.h" #include "prmjtime.h" @@ -448,7 +449,7 @@ JS_AddArgumentFormatter(JSContext *cx, const char *format, goto out; mpp = &map->next; } - map = (JSArgumentFormatMap *) JS_malloc(cx, sizeof *map); + map = (JSArgumentFormatMap *) cx->malloc(sizeof *map); if (!map) return JS_FALSE; map->format = format; @@ -471,7 +472,7 @@ JS_RemoveArgumentFormatter(JSContext *cx, const char *format) while ((map = *mpp) != NULL) { if (map->length == length && !strcmp(map->format, format)) { *mpp = map->next; - JS_free(cx, map); + cx->free(map); return; } mpp = &map->next; @@ -773,7 +774,7 @@ JS_NewRuntime(uint32 maxbytes) } #endif /* DEBUG */ - rt = (JSRuntime *) malloc(sizeof(JSRuntime)); + rt = (JSRuntime *) js_malloc(sizeof(JSRuntime)); if (!rt) return NULL; @@ -817,6 +818,9 @@ JS_NewRuntime(uint32 maxbytes) rt->debuggerLock = JS_NEW_LOCK(); if (!rt->debuggerLock) goto bad; + rt->deallocatorThread = new JSBackgroundThread(); + if (!rt->deallocatorThread || !rt->deallocatorThread->init()) + goto bad; #endif if (!js_InitPropertyTree(rt)) goto bad; @@ -886,9 +890,13 @@ JS_DestroyRuntime(JSRuntime *rt) JS_DESTROY_CONDVAR(rt->titleSharingDone); if (rt->debuggerLock) JS_DESTROY_LOCK(rt->debuggerLock); + if (rt->deallocatorThread) { + rt->deallocatorThread->cancel(); + delete rt->deallocatorThread; + } #endif js_FinishPropertyTree(rt); - free(rt); + js_free(rt); } JS_PUBLIC_API(void) @@ -1653,7 +1661,7 @@ NewIdArray(JSContext *cx, jsint length) JSIdArray *ida; ida = (JSIdArray *) - JS_malloc(cx, offsetof(JSIdArray, vector) + length * sizeof(jsval)); + cx->malloc(offsetof(JSIdArray, vector) + length * sizeof(jsval)); if (ida) ida->length = length; return ida; @@ -1831,41 +1839,19 @@ JS_ComputeThis(JSContext *cx, jsval *vp) JS_PUBLIC_API(void *) JS_malloc(JSContext *cx, size_t nbytes) { - void *p; - - JS_ASSERT(nbytes != 0); - if (nbytes == 0) - nbytes = 1; - - p = malloc(nbytes); - if (!p) { - JS_ReportOutOfMemory(cx); - return NULL; - } - cx->updateMallocCounter(nbytes); - - return p; + return cx->malloc(nbytes); } JS_PUBLIC_API(void *) JS_realloc(JSContext *cx, void *p, size_t nbytes) { - void *orig = p; - p = realloc(p, nbytes); - if (!p) { - JS_ReportOutOfMemory(cx); - return NULL; - } - if (!orig) - cx->updateMallocCounter(nbytes); - return p; + return cx->realloc(p, nbytes); } JS_PUBLIC_API(void) JS_free(JSContext *cx, void *p) { - if (p) - free(p); + return cx->free(p); } JS_PUBLIC_API(char *) @@ -1875,7 +1861,7 @@ JS_strdup(JSContext *cx, const char *s) void *p; n = strlen(s) + 1; - p = JS_malloc(cx, n); + p = cx->malloc(n); if (!p) return NULL; return (char *)memcpy(p, s, n); @@ -2260,7 +2246,7 @@ DumpNotify(JSTracer *trc, void *thing, uint32 kind) edgeNameSize = strlen(edgeName) + 1; node = (JSHeapDumpNode *) - JS_malloc(cx, offsetof(JSHeapDumpNode, edgeName) + edgeNameSize); + cx->malloc(offsetof(JSHeapDumpNode, edgeName) + edgeNameSize); if (!node) { dtrc->ok = JS_FALSE; return; @@ -2412,7 +2398,7 @@ JS_DumpHeap(JSContext *cx, FILE *fp, void* startThing, uint32 startKind, for (;;) { next = node->next; parent = node->parent; - JS_free(cx, node); + cx->free(node); node = next; if (node) break; @@ -2679,7 +2665,7 @@ JS_SetScriptStackQuota(JSContext *cx, size_t quota) JS_PUBLIC_API(void) JS_DestroyIdArray(JSContext *cx, JSIdArray *ida) { - JS_free(cx, ida); + cx->free(ida); } JS_PUBLIC_API(JSBool) @@ -4644,7 +4630,7 @@ JS_CompileScript(JSContext *cx, JSObject *obj, if (!chars) return NULL; script = JS_CompileUCScript(cx, obj, chars, length, filename, lineno); - JS_free(cx, chars); + cx->free(chars); return script; } @@ -4663,7 +4649,7 @@ JS_CompileScriptForPrincipals(JSContext *cx, JSObject *obj, return NULL; script = JS_CompileUCScriptForPrincipals(cx, obj, principals, chars, length, filename, lineno); - JS_free(cx, chars); + cx->free(chars); return script; } @@ -4748,7 +4734,7 @@ JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj, JS_SetErrorReporter(cx, older); } } - JS_free(cx, chars); + cx->free(chars); JS_RestoreExceptionState(cx, exnState); return result; } @@ -4857,7 +4843,7 @@ JS_CompileFunction(JSContext *cx, JSObject *obj, const char *name, return NULL; fun = JS_CompileUCFunction(cx, obj, name, nargs, argnames, chars, length, filename, lineno); - JS_free(cx, chars); + cx->free(chars); return fun; } @@ -4878,7 +4864,7 @@ JS_CompileFunctionForPrincipals(JSContext *cx, JSObject *obj, fun = JS_CompileUCFunctionForPrincipals(cx, obj, principals, name, nargs, argnames, chars, length, filename, lineno); - JS_free(cx, chars); + cx->free(chars); return fun; } @@ -5088,7 +5074,7 @@ JS_EvaluateScript(JSContext *cx, JSObject *obj, if (!chars) return JS_FALSE; ok = JS_EvaluateUCScript(cx, obj, chars, length, filename, lineno, rval); - JS_free(cx, chars); + cx->free(chars); return ok; } @@ -5110,7 +5096,7 @@ JS_EvaluateScriptForPrincipals(JSContext *cx, JSObject *obj, return JS_FALSE; ok = JS_EvaluateUCScriptForPrincipals(cx, obj, principals, chars, length, filename, lineno, rval); - JS_free(cx, chars); + cx->free(chars); return ok; } @@ -5319,13 +5305,13 @@ JS_NewString(JSContext *cx, char *bytes, size_t nbytes) /* Free chars (but not bytes, which caller frees on error) if we fail. */ str = js_NewString(cx, chars, length); if (!str) { - JS_free(cx, chars); + cx->free(chars); return NULL; } /* Hand off bytes to the deflated string cache, if possible. */ if (!js_SetStringBytes(cx, str, bytes, nbytes)) - JS_free(cx, bytes); + cx->free(bytes); return str; } @@ -5341,7 +5327,7 @@ JS_NewStringCopyN(JSContext *cx, const char *s, size_t n) return NULL; str = js_NewString(cx, js, n); if (!str) - JS_free(cx, js); + cx->free(js); return str; } @@ -5361,7 +5347,7 @@ JS_NewStringCopyZ(JSContext *cx, const char *s) return NULL; str = js_NewString(cx, js, n); if (!str) - JS_free(cx, js); + cx->free(js); return str; } @@ -5449,7 +5435,7 @@ JS_GetStringChars(JSString *str) if (str->isDependent()) { n = str->dependentLength(); size = (n + 1) * sizeof(jschar); - s = (jschar *) malloc(size); + s = (jschar *) js_malloc(size); if (s) { memcpy(s, str->dependentChars(), n * sizeof *s); s[n] = 0; @@ -5727,7 +5713,7 @@ JS_NewRegExpObject(JSContext *cx, char *bytes, size_t length, uintN flags) if (!chars) return NULL; obj = js_NewRegExpObject(cx, NULL, chars, length, flags); - JS_free(cx, chars); + cx->free(chars); return obj; } @@ -5857,7 +5843,7 @@ JS_SaveExceptionState(JSContext *cx) JSExceptionState *state; CHECK_REQUEST(cx); - state = (JSExceptionState *) JS_malloc(cx, sizeof(JSExceptionState)); + state = (JSExceptionState *) cx->malloc(sizeof(JSExceptionState)); if (state) { state->throwing = JS_GetPendingException(cx, &state->exception); if (state->throwing && JSVAL_IS_GCTHING(state->exception)) @@ -5886,7 +5872,7 @@ JS_DropExceptionState(JSContext *cx, JSExceptionState *state) if (state) { if (state->throwing && JSVAL_IS_GCTHING(state->exception)) JS_RemoveRoot(cx, &state->exception); - JS_free(cx, state); + cx->free(state); } } diff --git a/js/src/jsarena.cpp b/js/src/jsarena.cpp index 254d6801e1d4..68407af0a632 100644 --- a/js/src/jsarena.cpp +++ b/js/src/jsarena.cpp @@ -160,12 +160,12 @@ JS_ArenaAllocate(JSArenaPool *pool, size_t nb) if (pool->quotap) { if (gross > *pool->quotap) return NULL; - b = (JSArena *) malloc(gross); + b = (JSArena *) js_malloc(gross); if (!b) return NULL; *pool->quotap -= gross; } else { - b = (JSArena *) malloc(gross); + b = (JSArena *) js_malloc(gross); if (!b) return NULL; } @@ -227,12 +227,12 @@ JS_ArenaRealloc(JSArenaPool *pool, void *p, size_t size, size_t incr) growth = gross - (a->limit - (jsuword) a); if (growth > *pool->quotap) return NULL; - a = (JSArena *) realloc(a, gross); + a = (JSArena *) js_realloc(a, gross); if (!a) return NULL; *pool->quotap -= growth; } else { - a = (JSArena *) realloc(a, gross); + a = (JSArena *) js_realloc(a, gross); if (!a) return NULL; } @@ -315,7 +315,7 @@ FreeArenaList(JSArenaPool *pool, JSArena *head) *pool->quotap += a->limit - (jsuword) a; JS_CLEAR_ARENA(a); JS_COUNT_ARENA(pool,--); - free(a); + js_free(a); } while ((a = *ap) != NULL); pool->current = head; @@ -354,7 +354,7 @@ JS_FinishArenaPool(JSArenaPool *pool) JSArenaStats *stats, **statsp; if (pool->stats.name) { - free(pool->stats.name); + js_free(pool->stats.name); pool->stats.name = NULL; } for (statsp = &arena_stats_list; (stats = *statsp) != 0; diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index d3bff3916b4d..f4b1039efab6 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -314,7 +314,7 @@ ResizeSlots(JSContext *cx, JSObject *obj, uint32 oldsize, uint32 size) if (size == 0) { if (obj->dslots) { - JS_free(cx, obj->dslots - 1); + cx->free(obj->dslots - 1); obj->dslots = NULL; } return JS_TRUE; @@ -330,7 +330,7 @@ ResizeSlots(JSContext *cx, JSObject *obj, uint32 oldsize, uint32 size) } slots = obj->dslots ? obj->dslots - 1 : NULL; - newslots = (jsval *) JS_realloc(cx, slots, (size + 1) * sizeof(jsval)); + newslots = (jsval *) cx->realloc(slots, (size + 1) * sizeof(jsval)); if (!newslots) return JS_FALSE; @@ -1099,7 +1099,7 @@ array_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, if (obj->dslots[i] == JSVAL_HOLE) { if (!ii) { ii = (JSIndexIterState *) - JS_malloc(cx, offsetof(JSIndexIterState, holes) + + cx->malloc(offsetof(JSIndexIterState, holes) + JS_BITMAP_SIZE(capacity)); if (!ii) return JS_FALSE; @@ -1116,7 +1116,7 @@ array_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, break; } ii = (JSIndexIterState *) - JS_malloc(cx, offsetof(JSIndexIterState, holes)); + cx->malloc(offsetof(JSIndexIterState, holes)); if (!ii) return JS_FALSE; ii->hasHoles = JS_FALSE; @@ -1157,7 +1157,7 @@ array_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, if (JSVAL_TAG(*statep) != JSVAL_BOOLEAN) { JS_ASSERT((*statep & INDEX_ITER_TAG) == INDEX_ITER_TAG); ii = (JSIndexIterState *) (*statep & ~INDEX_ITER_TAG); - JS_free(cx, ii); + cx->free(ii); } *statep = JSVAL_NULL; break; @@ -1188,7 +1188,7 @@ static void array_finalize(JSContext *cx, JSObject *obj) { if (obj->dslots) - JS_free(cx, obj->dslots - 1); + cx->free(obj->dslots - 1); obj->dslots = NULL; } @@ -1336,7 +1336,7 @@ BufferToString(JSContext *cx, JSTempVector &buf, jsval *rval) jschar *chars = buf.extractRawBuffer(); JSString *str = js_NewString(cx, chars, length); if (!str) { - JS_free(cx, chars); + cx->free(chars); return JS_FALSE; } *rval = STRING_TO_JSVAL(str); @@ -1392,7 +1392,7 @@ array_toSource(JSContext *cx, uintN argc, jsval *vp) if (!(ok = buf.pushBack(arr, arr + 3))) goto done; if (sharpchars) - JS_free(cx, sharpchars); + cx->free(sharpchars); goto make_string; } #endif @@ -2151,7 +2151,7 @@ array_sort(JSContext *cx, uintN argc, jsval *vp) return JS_FALSE; } #endif - vec = (jsval *) JS_malloc(cx, 2 * (size_t) len * sizeof(jsval)); + vec = (jsval *) cx->malloc(2 * (size_t) len * sizeof(jsval)); if (!vec) return JS_FALSE; @@ -2280,8 +2280,8 @@ array_sort(JSContext *cx, uintN argc, jsval *vp) } while (i != 0); JS_ASSERT(tvr.u.array == vec); - vec = (jsval *) JS_realloc(cx, vec, - 4 * (size_t) newlen * sizeof(jsval)); + vec = (jsval *) cx->realloc(vec, + 4 * (size_t) newlen * sizeof(jsval)); if (!vec) { vec = tvr.u.array; ok = JS_FALSE; @@ -2342,7 +2342,7 @@ array_sort(JSContext *cx, uintN argc, jsval *vp) out: JS_POP_TEMP_ROOT(cx, &tvr); - JS_free(cx, vec); + cx->free(vec); if (!ok) return JS_FALSE; @@ -3507,7 +3507,7 @@ js_ArrayInfo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) if (JSVAL_IS_PRIMITIVE(argv[i]) || !OBJ_IS_ARRAY(cx, (array = JSVAL_TO_OBJECT(argv[i])))) { fprintf(stderr, "%s: not array\n", bytes); - JS_free(cx, bytes); + cx->free(bytes); continue; } fprintf(stderr, "%s: %s (len %lu", bytes, @@ -3519,7 +3519,7 @@ js_ArrayInfo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) js_DenseArrayCapacity(array)); } fputs(")\n", stderr); - JS_free(cx, bytes); + cx->free(bytes); } return JS_TRUE; } diff --git a/js/src/jsatom.cpp b/js/src/jsatom.cpp index 6a921d9b0b92..8943f22f224d 100644 --- a/js/src/jsatom.cpp +++ b/js/src/jsatom.cpp @@ -783,7 +783,7 @@ js_Atomize(JSContext *cx, const char *bytes, size_t length, uintN flags) str.initFlat(chars, inflatedLength); atom = js_AtomizeString(cx, &str, ATOM_TMPSTR | flags); if (chars != inflated && str.flatChars()) - JS_free(cx, chars); + cx->free(chars); return atom; } diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index 6bcd70f97f3f..42b579b363bf 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -142,7 +142,7 @@ static JSThread * NewThread(jsword id) { JS_ASSERT(js_CurrentThreadId() == id); - JSThread *thread = (JSThread *) calloc(1, sizeof(JSThread)); + JSThread *thread = (JSThread *) js_calloc(sizeof(JSThread)); if (!thread) return NULL; JS_INIT_CLIST(&thread->contextList); @@ -158,7 +158,7 @@ DestroyThread(JSThread *thread) JS_ASSERT(JS_CLIST_IS_EMPTY(&thread->contextList)); JS_ASSERT(!thread->titleToShare); FinishThreadData(&thread->data); - free(thread); + js_free(thread); } JSBool @@ -370,7 +370,7 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize) * runtime list. After that it can be accessed from another thread via * js_ContextIterator. */ - cx = (JSContext *) calloc(1, sizeof *cx); + cx = (JSContext *) js_calloc(sizeof *cx); if (!cx) return NULL; @@ -743,14 +743,14 @@ FreeContext(JSContext *cx) JS_FinishArenaPool(&cx->tempPool); if (cx->lastMessage) - free(cx->lastMessage); + js_free(cx->lastMessage); /* Remove any argument formatters. */ map = cx->argumentFormatMap; while (map) { JSArgumentFormatMap *temp = map; map = map->next; - JS_free(cx, temp); + cx->free(temp); } /* Destroy the busy array table. */ @@ -769,13 +769,13 @@ FreeContext(JSContext *cx) if (lrs) { while ((lrc = lrs->topChunk) != &lrs->firstChunk) { lrs->topChunk = lrc->down; - JS_free(cx, lrc); + cx->free(lrc); } - JS_free(cx, lrs); + cx->free(lrs); } /* Finally, free cx itself. */ - free(cx); + js_free(cx); } JSBool @@ -1013,7 +1013,7 @@ js_EnterLocalRootScope(JSContext *cx) lrs = cx->localRootStack; if (!lrs) { - lrs = (JSLocalRootStack *) JS_malloc(cx, sizeof *lrs); + lrs = (JSLocalRootStack *) cx->malloc(sizeof *lrs); if (!lrs) return JS_FALSE; lrs->scopeMark = JSLRS_NULL_MARK; @@ -1056,7 +1056,7 @@ js_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval) lrc = lrs->topChunk; JS_ASSERT(lrc != &lrs->firstChunk); lrs->topChunk = lrc->down; - JS_free(cx, lrc); + cx->free(lrc); --n; } @@ -1096,10 +1096,10 @@ js_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval) */ if (mark == 0) { cx->localRootStack = NULL; - JS_free(cx, lrs); + cx->free(lrs); } else if (m == 0) { lrs->topChunk = lrc->down; - JS_free(cx, lrc); + cx->free(lrc); } } @@ -1158,7 +1158,7 @@ js_ForgetLocalRoot(JSContext *cx, jsval v) JS_ASSERT(n != 0); JS_ASSERT(lrc != &lrs->firstChunk); lrs->topChunk = lrc->down; - JS_free(cx, lrc); + cx->free(lrc); } } @@ -1187,7 +1187,7 @@ js_PushLocalRoot(JSContext *cx, JSLocalRootStack *lrs, jsval v) * After lrs->firstChunk, trying to index at a power-of-two chunk * boundary: need a new chunk. */ - lrc = (JSLocalRootChunk *) JS_malloc(cx, sizeof *lrc); + lrc = (JSLocalRootChunk *) cx->malloc(sizeof *lrc); if (!lrc) return -1; lrc->down = lrs->topChunk; @@ -1380,8 +1380,8 @@ js_ReportErrorVA(JSContext *cx, uintN flags, const char *format, va_list ap) } ReportError(cx, message, &report); - free(message); - JS_free(cx, ucmessage); + js_free(message); + cx->free(ucmessage); return warning; } @@ -1432,7 +1432,7 @@ js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback, * pointers later. */ reportp->messageArgs = (const jschar **) - JS_malloc(cx, sizeof(jschar *) * (argCount + 1)); + cx->malloc(sizeof(jschar *) * (argCount + 1)); if (!reportp->messageArgs) return JS_FALSE; reportp->messageArgs[argCount] = NULL; @@ -1476,9 +1476,9 @@ js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback, * is used once and only once in the expansion !!! */ reportp->ucmessage = out = (jschar *) - JS_malloc(cx, (expandedLength + 1) * sizeof(jschar)); + cx->malloc((expandedLength + 1) * sizeof(jschar)); if (!out) { - JS_free (cx, buffer); + cx->free(buffer); goto error; } while (*fmt) { @@ -1498,7 +1498,7 @@ js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback, } JS_ASSERT(expandedArgs == argCount); *out = 0; - JS_free (cx, buffer); + cx->free(buffer); *messagep = js_DeflateString(cx, reportp->ucmessage, (size_t)(out - reportp->ucmessage)); @@ -1527,7 +1527,7 @@ js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback, const char *defaultErrorMessage = "No error message available for error number %d"; size_t nbytes = strlen(defaultErrorMessage) + 16; - *messagep = (char *)JS_malloc(cx, nbytes); + *messagep = (char *)cx->malloc(nbytes); if (!*messagep) goto error; JS_snprintf(*messagep, nbytes, defaultErrorMessage, errorNumber); @@ -1540,17 +1540,17 @@ error: if (charArgs) { i = 0; while (reportp->messageArgs[i]) - JS_free(cx, (void *)reportp->messageArgs[i++]); + cx->free((void *)reportp->messageArgs[i++]); } - JS_free(cx, (void *)reportp->messageArgs); + cx->free((void *)reportp->messageArgs); reportp->messageArgs = NULL; } if (reportp->ucmessage) { - JS_free(cx, (void *)reportp->ucmessage); + cx->free((void *)reportp->ucmessage); reportp->ucmessage = NULL; } if (*messagep) { - JS_free(cx, (void *)*messagep); + cx->free((void *)*messagep); *messagep = NULL; } return JS_FALSE; @@ -1581,7 +1581,7 @@ js_ReportErrorNumberVA(JSContext *cx, uintN flags, JSErrorCallback callback, ReportError(cx, message, &report); if (message) - JS_free(cx, message); + cx->free(message); if (report.messageArgs) { /* * js_ExpandErrorArguments owns its messageArgs only if it had to @@ -1590,12 +1590,12 @@ js_ReportErrorNumberVA(JSContext *cx, uintN flags, JSErrorCallback callback, if (charArgs) { int i = 0; while (report.messageArgs[i]) - JS_free(cx, (void *)report.messageArgs[i++]); + cx->free((void *)report.messageArgs[i++]); } - JS_free(cx, (void *)report.messageArgs); + cx->free((void *)report.messageArgs); } if (report.ucmessage) - JS_free(cx, (void *)report.ucmessage); + cx->free((void *)report.ucmessage); return warning; } @@ -1609,7 +1609,7 @@ js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *reportp) return; if (cx->lastMessage) - free(cx->lastMessage); + js_free(cx->lastMessage); cx->lastMessage = JS_strdup(cx, message); if (!cx->lastMessage) return; @@ -1667,7 +1667,7 @@ js_ReportIsNullOrUndefined(JSContext *cx, intN spindex, jsval v, js_null_str, NULL); } - JS_free(cx, bytes); + cx->free(bytes); return ok; } @@ -1690,7 +1690,7 @@ js_ReportMissingArg(JSContext *cx, jsval *vp, uintN arg) JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MISSING_FUN_ARG, argbuf, bytes ? bytes : ""); - JS_free(cx, bytes); + cx->free(bytes); } JSBool @@ -1709,7 +1709,7 @@ js_ReportValueErrorFlags(JSContext *cx, uintN flags, const uintN errorNumber, ok = JS_ReportErrorFlagsAndNumber(cx, flags, js_GetErrorMessage, NULL, errorNumber, bytes, arg1, arg2); - JS_free(cx, bytes); + cx->free(bytes); return ok; } diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index b079cb014d19..c3d2465472ec 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -57,6 +57,7 @@ #include "jsregexp.h" #include "jsutil.h" #include "jsarray.h" +#include "jstask.h" JS_BEGIN_EXTERN_C @@ -255,6 +256,13 @@ struct JSThreadData { * locks on each JS_malloc. */ size_t gcMallocBytes; + +#ifdef JS_THREADSAFE + /* + * Deallocator task for this thread. + */ + JSFreePointerListTask *deallocatorTask; +#endif }; #ifdef JS_THREADSAFE @@ -699,6 +707,26 @@ struct JSRuntime { void setGCTriggerFactor(uint32 factor); void setGCLastBytes(size_t lastBytes); + + inline void* malloc(size_t bytes) { + return ::js_malloc(bytes); + } + + inline void* calloc(size_t bytes) { + return ::js_calloc(bytes); + } + + inline void* realloc(void* p, size_t bytes) { + return ::js_realloc(p, bytes); + } + + inline void free(void* p) { + ::js_free(p); + } + +#ifdef JS_THREADSAFE + JSBackgroundThread *deallocatorThread; +#endif }; /* Common macros to access thread-local caches in JSThread or JSRuntime. */ @@ -1050,16 +1078,86 @@ struct JSContext { jsval *nativeVp; #endif +#ifdef JS_THREADSAFE + inline void createDeallocatorTask() { + JSThreadData* tls = JS_THREAD_DATA(this); + JS_ASSERT(!tls->deallocatorTask); + if (runtime->deallocatorThread && !runtime->deallocatorThread->busy()) + tls->deallocatorTask = new JSFreePointerListTask(); + } + + inline void submitDeallocatorTask() { + JSThreadData* tls = JS_THREAD_DATA(this); + if (tls->deallocatorTask) { + runtime->deallocatorThread->schedule(tls->deallocatorTask); + tls->deallocatorTask = NULL; + } + } +#endif + /* Call this after succesful malloc of memory for GC-related things. */ - inline void - updateMallocCounter(size_t nbytes) - { + inline void updateMallocCounter(size_t nbytes) { size_t *pbytes, bytes; pbytes = &JS_THREAD_DATA(this)->gcMallocBytes; bytes = *pbytes; *pbytes = (size_t(-1) - bytes <= nbytes) ? size_t(-1) : bytes + nbytes; } + + inline void* malloc(size_t bytes) { + JS_ASSERT(bytes != 0); + void *p = runtime->malloc(bytes); + if (!p) { + JS_ReportOutOfMemory(this); + return NULL; + } + updateMallocCounter(bytes); + return p; + } + + inline void* calloc(size_t bytes) { + JS_ASSERT(bytes != 0); + void *p = runtime->calloc(bytes); + if (!p) { + JS_ReportOutOfMemory(this); + return NULL; + } + updateMallocCounter(bytes); + return p; + } + + inline void* realloc(void* p, size_t bytes) { + void *orig = p; + p = runtime->realloc(p, bytes); + if (!p) { + JS_ReportOutOfMemory(this); + return NULL; + } + if (!orig) + updateMallocCounter(bytes); + return p; + } + +#ifdef JS_THREADSAFE + inline void free(void* p) { + if (!p) + return; + if (thread) { + JSFreePointerListTask* task = JS_THREAD_DATA(this)->deallocatorTask; + if (task) { + task->add(p); + return; + } + } + runtime->free(p); + } +#else + inline void free(void* p) { + if (!p) + return; + runtime->free(p); + } +#endif }; #ifdef JS_THREADSAFE diff --git a/js/src/jsdate.cpp b/js/src/jsdate.cpp index c6a5f870a57c..9eaa85e60fc6 100644 --- a/js/src/jsdate.cpp +++ b/js/src/jsdate.cpp @@ -1961,7 +1961,7 @@ date_toSource(JSContext *cx, uintN argc, jsval *vp) str = JS_NewString(cx, bytes, strlen(bytes)); if (!str) { - free(bytes); + js_free(bytes); return JS_FALSE; } *vp = STRING_TO_JSVAL(str); diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 92f35ed6c407..d9e9ed62a2fb 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -123,7 +123,7 @@ js_UntrapScriptCode(JSContext *cx, JSScript *script) continue; nbytes += (sn - notes + 1) * sizeof *sn; - code = (jsbytecode *) JS_malloc(cx, nbytes); + code = (jsbytecode *) cx->malloc(nbytes); if (!code) break; memcpy(code, script->code, nbytes); @@ -155,12 +155,12 @@ JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc, } else { sample = rt->debuggerMutations; DBG_UNLOCK(rt); - trap = (JSTrap *) JS_malloc(cx, sizeof *trap); + trap = (JSTrap *) cx->malloc(sizeof *trap); if (!trap) return JS_FALSE; trap->closure = NULL; if(!js_AddRoot(cx, &trap->closure, "trap->closure")) { - JS_free(cx, trap); + cx->free(trap); return JS_FALSE; } DBG_LOCK(rt); @@ -184,7 +184,7 @@ JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc, DBG_UNLOCK(rt); if (junk) { js_RemoveRoot(rt, &junk->closure); - JS_free(cx, junk); + cx->free(junk); } return JS_TRUE; } @@ -213,7 +213,7 @@ DestroyTrapAndUnlock(JSContext *cx, JSTrap *trap) DBG_UNLOCK(cx->runtime); js_RemoveRoot(cx->runtime, &trap->closure); - JS_free(cx, trap); + cx->free(trap); } JS_PUBLIC_API(void) @@ -413,7 +413,7 @@ DropWatchPointAndUnlock(JSContext *cx, JSWatchPoint *wp, uintN flag) } } - JS_free(cx, wp); + cx->free(wp); return ok; } @@ -619,7 +619,7 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp) if (nslots <= JS_ARRAY_LENGTH(smallv)) { argv = smallv; } else { - argv = (jsval *) JS_malloc(cx, nslots * sizeof(jsval)); + argv = (jsval *) cx->malloc(nslots * sizeof(jsval)); if (!argv) { DBG_LOCK(rt); DropWatchPointAndUnlock(cx, wp, JSWP_HELD); @@ -651,7 +651,7 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp) JSFUN_HEAVYWEIGHT_TEST(fun->flags) && !js_GetCallObject(cx, &frame)) { if (argv != smallv) - JS_free(cx, argv); + cx->free(argv); DBG_LOCK(rt); DropWatchPointAndUnlock(cx, wp, JSWP_HELD); return JS_FALSE; @@ -679,7 +679,7 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp) cx->fp = frame.down; if (argv != smallv) - JS_free(cx, argv); + cx->free(argv); } } DBG_LOCK(rt); @@ -825,7 +825,7 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval idval, goto out; } - wp = (JSWatchPoint *) JS_malloc(cx, sizeof *wp); + wp = (JSWatchPoint *) cx->malloc(sizeof *wp); if (!wp) { ok = JS_FALSE; goto out; @@ -1343,7 +1343,7 @@ JS_EvaluateInStackFrame(JSContext *cx, JSStackFrame *fp, length = (uintN) len; ok = JS_EvaluateUCInStackFrame(cx, fp, chars, length, filename, lineno, rval); - JS_free(cx, chars); + cx->free(chars); return ok; } @@ -1469,7 +1469,7 @@ JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda) } n = scope->entryCount; - pd = (JSPropertyDesc *) JS_malloc(cx, (size_t)n * sizeof(JSPropertyDesc)); + pd = (JSPropertyDesc *) cx->malloc((size_t)n * sizeof(JSPropertyDesc)); if (!pd) return JS_FALSE; i = 0; @@ -1511,7 +1511,7 @@ JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda) if (pd[i].flags & JSPD_ALIAS) js_RemoveRoot(cx->runtime, &pd[i].alias); } - JS_free(cx, pd); + cx->free(pd); } /************************************************************************/ @@ -1884,7 +1884,7 @@ js_DumpCallgrind(JSContext *cx, JSObject *obj, cstr = js_DeflateString(cx, str->chars(), str->length()); if (cstr) { CALLGRIND_DUMP_STATS_AT(cstr); - JS_free(cx, cstr); + cx->free(cstr); return JS_TRUE; } } @@ -1962,7 +1962,7 @@ js_StartVtune(JSContext *cx, JSObject *obj, status = VTStartSampling(¶ms); if (params.tb5Filename != default_filename) - JS_free(cx, params.tb5Filename); + cx->free(params.tb5Filename); if (status != 0) { if (status == VTAPI_MULTIPLE_RUNS) diff --git a/js/src/jsdhash.cpp b/js/src/jsdhash.cpp index 8252b4b651b4..c8b9db09dc0d 100644 --- a/js/src/jsdhash.cpp +++ b/js/src/jsdhash.cpp @@ -111,13 +111,13 @@ JS_PUBLIC_API(void *) JS_DHashAllocTable(JSDHashTable *table, uint32 nbytes) { - return malloc(nbytes); + return js_malloc(nbytes); } JS_PUBLIC_API(void) JS_DHashFreeTable(JSDHashTable *table, void *ptr) { - free(ptr); + js_free(ptr); } JS_PUBLIC_API(JSDHashNumber) @@ -180,7 +180,7 @@ JS_DHashFreeStringKey(JSDHashTable *table, JSDHashEntryHdr *entry) { const JSDHashEntryStub *stub = (const JSDHashEntryStub *)entry; - free((void *) stub->key); + js_free((void *) stub->key); memset(entry, 0, table->entrySize); } @@ -212,11 +212,11 @@ JS_NewDHashTable(const JSDHashTableOps *ops, void *data, uint32 entrySize, { JSDHashTable *table; - table = (JSDHashTable *) malloc(sizeof *table); + table = (JSDHashTable *) js_malloc(sizeof *table); if (!table) return NULL; if (!JS_DHashTableInit(table, ops, data, entrySize, capacity)) { - free(table); + js_free(table); return NULL; } return table; @@ -226,7 +226,7 @@ JS_PUBLIC_API(void) JS_DHashTableDestroy(JSDHashTable *table) { JS_DHashTableFinish(table); - free(table); + js_free(table); } JS_PUBLIC_API(JSBool) diff --git a/js/src/jsdtoa.cpp b/js/src/jsdtoa.cpp index b1197ac043d3..111cb5dec9d3 100644 --- a/js/src/jsdtoa.cpp +++ b/js/src/jsdtoa.cpp @@ -368,7 +368,7 @@ JS_dtobasestr(int base, double dinput) JS_ASSERT(base >= 2 && base <= 36); dval(d) = dinput; - buffer = (char*) malloc(DTOBASESTR_BUFFER_SIZE); + buffer = (char*) js_malloc(DTOBASESTR_BUFFER_SIZE); if (buffer) { p = buffer; if (dval(d) < 0.0 @@ -412,7 +412,7 @@ JS_dtobasestr(int base, double dinput) nomem1: Bfree(b); UNLOCK_DTOA(); - free(buffer); + js_free(buffer); return NULL; } do { @@ -449,7 +449,7 @@ JS_dtobasestr(int base, double dinput) Bfree(mlo); Bfree(mhi); UNLOCK_DTOA(); - free(buffer); + js_free(buffer); return NULL; } JS_ASSERT(e < 0); diff --git a/js/src/jsemit.cpp b/js/src/jsemit.cpp index f591e844b6f0..5105d8bba498 100644 --- a/js/src/jsemit.cpp +++ b/js/src/jsemit.cpp @@ -112,10 +112,10 @@ JSCodeGenerator::~JSCodeGenerator() /* NB: non-null only after OOM. */ if (spanDeps) - JS_free(compiler->context, spanDeps); + compiler->context->free(spanDeps); if (upvarMap.vector) - JS_free(compiler->context, upvarMap.vector); + compiler->context->free(upvarMap.vector); } static ptrdiff_t @@ -549,7 +549,7 @@ AddSpanDep(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc, jsbytecode *pc2, if ((index & (index - 1)) == 0 && (!(sdbase = cg->spanDeps) || index >= SPANDEPS_MIN)) { size = sdbase ? SPANDEPS_SIZE(index) : SPANDEPS_SIZE_MIN / 2; - sdbase = (JSSpanDep *) JS_realloc(cx, sdbase, size + size); + sdbase = (JSSpanDep *) cx->realloc(sdbase, size + size); if (!sdbase) return JS_FALSE; cg->spanDeps = sdbase; @@ -1165,7 +1165,7 @@ OptimizeSpanDeps(JSContext *cx, JSCodeGenerator *cg) * can span top-level statements, because JS lacks goto. */ size = SPANDEPS_SIZE(JS_BIT(JS_CeilingLog2(cg->numSpanDeps))); - JS_free(cx, cg->spanDeps); + cx->free(cg->spanDeps); cg->spanDeps = NULL; FreeJumpTargets(cg, cg->jumpTargets); cg->jumpTargets = NULL; @@ -1899,7 +1899,7 @@ MakeUpvarForEval(JSParseNode *pn, JSCodeGenerator *cg) JS_ASSERT(ALE_INDEX(ale) <= length); if (ALE_INDEX(ale) == length) { length = 2 * JS_MAX(2, length); - vector = (uint32 *) JS_realloc(cx, vector, length * sizeof *vector); + vector = (uint32 *) cx->realloc(vector, length * sizeof *vector); if (!vector) return false; cg->upvarMap.vector = vector; @@ -2197,7 +2197,7 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) if (!vector) { uint32 length = cg->lexdeps.count; - vector = (uint32 *) calloc(length, sizeof *vector); + vector = (uint32 *) js_calloc(length * sizeof *vector); if (!vector) { JS_ReportOutOfMemory(cx); return JS_FALSE; @@ -3144,9 +3144,8 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, /* Just grab 8K for the worst-case bitmap. */ intmap_bitlen = JS_BIT(16); intmap = (jsbitmap *) - JS_malloc(cx, - (JS_BIT(16) >> JS_BITS_PER_WORD_LOG2) - * sizeof(jsbitmap)); + cx->malloc((JS_BIT(16) >> JS_BITS_PER_WORD_LOG2) + * sizeof(jsbitmap)); if (!intmap) { JS_ReportOutOfMemory(cx); return JS_FALSE; @@ -3163,7 +3162,7 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, release: if (intmap && intmap != intmap_space) - JS_free(cx, intmap); + cx->free(intmap); if (!ok) return JS_FALSE; @@ -3307,7 +3306,7 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, */ if (tableLength != 0) { tableSize = (size_t)tableLength * sizeof *table; - table = (JSParseNode **) JS_malloc(cx, tableSize); + table = (JSParseNode **) cx->malloc(tableSize); if (!table) return JS_FALSE; memset(table, 0, tableSize); @@ -3475,7 +3474,7 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, out: if (table) - JS_free(cx, table); + cx->free(table); if (ok) { ok = js_PopStatementCG(cx, cg); diff --git a/js/src/jsexn.cpp b/js/src/jsexn.cpp index 34d9312cce8e..a83d658a4e61 100644 --- a/js/src/jsexn.cpp +++ b/js/src/jsexn.cpp @@ -164,7 +164,7 @@ CopyErrorReport(JSContext *cx, JSErrorReport *report) */ mallocSize = sizeof(JSErrorReport) + argsArraySize + argsCopySize + ucmessageSize + uclinebufSize + linebufSize + filenameSize; - cursor = (uint8 *)JS_malloc(cx, mallocSize); + cursor = (uint8 *)cx->malloc(mallocSize); if (!cursor) return NULL; @@ -301,7 +301,7 @@ InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message, js_ReportAllocationOverflow(cx); return JS_FALSE; } - priv = (JSExnPrivate *)JS_malloc(cx, size); + priv = (JSExnPrivate *)cx->malloc(size); if (!priv) return JS_FALSE; @@ -417,8 +417,8 @@ exn_finalize(JSContext *cx, JSObject *obj) priv = GetExnPrivate(cx, obj); if (priv) { if (priv->errorReport) - JS_free(cx, priv->errorReport); - JS_free(cx, priv); + cx->free(priv->errorReport); + cx->free(priv); } } @@ -586,7 +586,7 @@ StackTraceToString(JSContext *cx, JSExnPrivate *priv) if (stackmax >= STACK_LENGTH_LIMIT) \ goto done; \ stackmax = stackmax ? 2 * stackmax : 64; \ - ptr_ = JS_realloc(cx, stackbuf, (stackmax+1) * sizeof(jschar)); \ + ptr_ = cx->realloc(stackbuf, (stackmax+1) * sizeof(jschar)); \ if (!ptr_) \ goto bad; \ stackbuf = (jschar *) ptr_; \ @@ -608,7 +608,7 @@ StackTraceToString(JSContext *cx, JSExnPrivate *priv) goto done; \ } \ stackmax = JS_BIT(JS_CeilingLog2(stacklen + length_)); \ - ptr_ = JS_realloc(cx, stackbuf, (stackmax+1) * sizeof(jschar)); \ + ptr_ = cx->realloc(stackbuf, (stackmax+1) * sizeof(jschar)); \ if (!ptr_) \ goto bad; \ stackbuf = (jschar *) ptr_; \ @@ -659,7 +659,7 @@ StackTraceToString(JSContext *cx, JSExnPrivate *priv) * don't use JS_realloc here; simply let the oversized allocation * be owned by the string in that rare case. */ - void *shrunk = JS_realloc(cx, stackbuf, (stacklen+1) * sizeof(jschar)); + void *shrunk = cx->realloc(stackbuf, (stacklen+1) * sizeof(jschar)); if (shrunk) stackbuf = (jschar *) shrunk; } @@ -671,7 +671,7 @@ StackTraceToString(JSContext *cx, JSExnPrivate *priv) bad: if (stackbuf) - JS_free(cx, stackbuf); + cx->free(stackbuf); return NULL; } @@ -800,7 +800,7 @@ exn_toString(JSContext *cx, uintN argc, jsval *vp) name_length = name->length(); message_length = message->length(); length = (name_length ? name_length + 2 : 0) + message_length; - cp = chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar)); + cp = chars = (jschar *) cx->malloc((length + 1) * sizeof(jschar)); if (!chars) return JS_FALSE; @@ -815,7 +815,7 @@ exn_toString(JSContext *cx, uintN argc, jsval *vp) result = js_NewString(cx, chars, length); if (!result) { - JS_free(cx, chars); + cx->free(chars); return JS_FALSE; } } else { @@ -915,7 +915,7 @@ exn_toSource(JSContext *cx, uintN argc, jsval *vp) } } - cp = chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar)); + cp = chars = (jschar *) cx->malloc((length + 1) * sizeof(jschar)); if (!chars) { ok = JS_FALSE; goto out; @@ -955,7 +955,7 @@ exn_toSource(JSContext *cx, uintN argc, jsval *vp) result = js_NewString(cx, chars, length); if (!result) { - JS_free(cx, chars); + cx->free(chars); ok = JS_FALSE; goto out; } diff --git a/js/src/jsfile.cpp b/js/src/jsfile.cpp index b3d618275ddb..8228c44add60 100644 --- a/js/src/jsfile.cpp +++ b/js/src/jsfile.cpp @@ -296,7 +296,7 @@ static char* js_combinePath(JSContext *cx, const char *base, const char *name) { int len = strlen(base); - char* result = JS_malloc(cx, len + strlen(name) + 2); + char* result = cx->malloc(len + strlen(name) + 2); if (!result) return NULL; @@ -335,7 +335,7 @@ js_fileBaseName(JSContext *cx, const char *pathname) } /* Allocate and copy. */ - result = JS_malloc(cx, aux - index + 1); + result = cx->malloc(aux - index + 1); if (!result) return NULL; strncpy(result, pathname + index + 1, aux - index); @@ -366,7 +366,7 @@ js_fileDirectoryName(JSContext *cx, const char *pathname) if (cp < pathname && end != pathname) { /* There were just /s, return the root. */ - result = JS_malloc(cx, 1 + 1); /* The separator + trailing NUL. */ + result = cx->malloc(1 + 1); /* The separator + trailing NUL. */ result[0] = FILESEPARATOR; result[1] = '\0'; return result; @@ -388,7 +388,7 @@ js_fileDirectoryName(JSContext *cx, const char *pathname) } pathsize = end - pathname + 1; - result = JS_malloc(cx, pathsize + 1); + result = cx->malloc(pathsize + 1); if (!result) return NULL; @@ -401,7 +401,7 @@ js_fileDirectoryName(JSContext *cx, const char *pathname) /* Return everything up to and including the seperator. */ pathsize = cp - pathname + 1; - result = JS_malloc(cx, pathsize + 1); + result = cx->malloc(pathsize + 1); if (!result) return NULL; @@ -462,7 +462,7 @@ js_canonicalPath(JSContext *cx, char *oldpath) while (j >= 0 && path[j] == ' ') j--; - tmp = JS_malloc(cx, j-i+2); + tmp = cx->malloc(j-i+2); if (!tmp) return NULL; @@ -478,7 +478,7 @@ js_canonicalPath(JSContext *cx, char *oldpath) /* file:// support. */ if (!strncmp(path, URL_PREFIX, strlen(URL_PREFIX))) { tmp = js_canonicalPath(cx, path + strlen(URL_PREFIX)); - JS_free(cx, path); + cx->free(path); return tmp; } @@ -486,7 +486,7 @@ js_canonicalPath(JSContext *cx, char *oldpath) tmp = js_absolutePath(cx, path); if (!tmp) return NULL; - JS_free(cx, path); + cx->free(path); path = tmp; } @@ -505,7 +505,7 @@ js_canonicalPath(JSContext *cx, char *oldpath) back--; } else { tmp = result; - result = JS_malloc(cx, strlen(base) + 1 + strlen(tmp) + 1); + result = cx->malloc(strlen(base) + 1 + strlen(tmp) + 1); if (!result) goto out; @@ -516,18 +516,18 @@ js_canonicalPath(JSContext *cx, char *oldpath) result[c + 1] = '\0'; strcat(result, tmp); } - JS_free(cx, tmp); + cx->free(tmp); } } - JS_free(cx, current); - JS_free(cx, base); + cx->free(current); + cx->free(base); current = dir; base = js_fileBaseName(cx, current); dir = js_fileDirectoryName(cx, current); } tmp = result; - result = JS_malloc(cx, strlen(dir)+1+strlen(tmp)+1); + result = cx->malloc(strlen(dir) + 1 + strlen(tmp) + 1); if (!result) goto out; @@ -543,13 +543,13 @@ js_canonicalPath(JSContext *cx, char *oldpath) out: if (tmp) - JS_free(cx, tmp); + cx->free(tmp); if (dir) - JS_free(cx, dir); + cx->free(dir); if (base) - JS_free(cx, base); + cx->free(base); if (current) - JS_free(cx, current); + cx->free(current); return result; } @@ -753,7 +753,7 @@ js_FileHasOption(JSContext *cx, const char *oldoptions, const char *name) break; current = comma + 1; } - JS_free(cx, options); + cx->free(options); return found; } @@ -838,20 +838,20 @@ js_FileRead(JSContext *cx, JSFile *file, jschar *buf, int32 len, int32 mode) switch (mode) { case ASCII: - aux = (unsigned char*)JS_malloc(cx, len); + aux = (unsigned char*)cx->malloc(len); if (!aux) return 0; count = js_BufferedRead(file, aux, len); if (count == -1) { - JS_free(cx, aux); + cx->free(aux); return 0; } for (i = 0; i < len; i++) buf[i] = (jschar)aux[i]; - JS_free(cx, aux); + cx->free(aux); break; case UTF8: @@ -977,7 +977,7 @@ js_FileWrite(JSContext *cx, JSFile *file, jschar *buf, int32 len, int32 mode) switch (mode) { case ASCII: - aux = (unsigned char*)JS_malloc(cx, len); + aux = (unsigned char*)cx->malloc(len); if (!aux) return 0; @@ -989,21 +989,21 @@ js_FileWrite(JSContext *cx, JSFile *file, jschar *buf, int32 len, int32 mode) : fwrite(aux, 1, len, file->nativehandle); if (count==-1) { - JS_free(cx, aux); + cx->free(aux); return 0; } - JS_free(cx, aux); + cx->free(aux); break; case UTF8: - utfbuf = (unsigned char*)JS_malloc(cx, len*3); + utfbuf = (unsigned char*)cx->malloc(len*3); if (!utfbuf) return 0; i = 0; for (count = 0;countfree(utfbuf); return 0; } i+=j; @@ -1013,10 +1013,10 @@ js_FileWrite(JSContext *cx, JSFile *file, jschar *buf, int32 len, int32 mode) : fwrite(utfbuf, 1, i, file->nativehandle); if (jfree(utfbuf); return 0; } - JS_free(cx, utfbuf); + cx->free(utfbuf); break; case UCS2: @@ -1179,13 +1179,13 @@ js_parent(JSContext *cx, JSFile *file, jsval *resultp) } else { JSObject *obj = js_NewFileObject(cx, str); if (!obj) { - JS_free(cx, str); + cx->free(str); return JS_FALSE; } *resultp = OBJECT_TO_JSVAL(obj); } - JS_free(cx, str); + cx->free(str); return JS_TRUE; } @@ -1206,7 +1206,7 @@ js_name(JSContext *cx, JSFile *file, jsval *vp) str = JS_NewString(cx, name, strlen(name)); if (!str) { - JS_free(cx, name); + cx->free(name); return JS_FALSE; } @@ -1353,7 +1353,7 @@ file_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) pipemode[i++] = '\0'; file->nativehandle = POPEN(&file->path[1], pipemode); } else if(file->path[len-1] == PIPE_SYMBOL) { - char *command = JS_malloc(cx, len); + char *command = cx->malloc(len); strncpy(command, file->path, len-1); command[len-1] = '\0'; @@ -1364,7 +1364,7 @@ file_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) #endif pipemode[i++] = '\0'; file->nativehandle = POPEN(command, pipemode); - JS_free(cx, command); + cx->free(command); } /* set the flags */ file->isNative = JS_TRUE; @@ -1377,7 +1377,7 @@ file_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) } js_ResetBuffers(file); - JS_free(cx, mode); + cx->free(mode); mode = NULL; /* Set the open flag and return result */ @@ -1396,7 +1396,7 @@ good: out: if(mode) - JS_free(cx, mode); + cx->free(mode); return JS_FALSE; } @@ -1511,13 +1511,13 @@ file_copyTo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) goto out; } - buffer = JS_malloc(cx, size); + buffer = cx->malloc(size); count = INT_TO_JSVAL(PR_Read(file->handle, buffer, size)); /* reading panic */ if (count!=size) { - JS_free(cx, buffer); + cx->free(buffer); JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, JSFILEMSG_COPY_READ_ERROR, file->path); goto out; @@ -1527,13 +1527,13 @@ file_copyTo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) /* writing panic */ if (count!=size) { - JS_free(cx, buffer); + cx->free(buffer); JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, JSFILEMSG_COPY_WRITE_ERROR, file->path); goto out; } - JS_free(cx, buffer); + cx->free(buffer); if(!fileInitiallyOpen){ if(!file_close(cx, obj, 0, NULL, rval)) goto out; @@ -1577,7 +1577,7 @@ file_renameTo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval if (PR_Rename(file->path, dest)==PR_SUCCESS){ /* copy the new filename */ - JS_free(cx, file->path); + cx->free(file->path); file->path = dest; *rval = JSVAL_TRUE; return JS_TRUE; @@ -1729,17 +1729,17 @@ file_read(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) /* want = (want>262144)?262144:want; * arbitrary size limitation */ - buf = JS_malloc(cx, want*sizeof buf[0]); + buf = cx->malloc(want*sizeof buf[0]); if (!buf) goto out; count = js_FileRead(cx, file, buf, want, file->type); if (count>0) { str = JS_NewUCStringCopyN(cx, buf, count); *rval = STRING_TO_JSVAL(str); - JS_free(cx, buf); + cx->free(buf); return JS_TRUE; } else { - JS_free(cx, buf); + cx->free(buf); goto out; } out: @@ -1760,7 +1760,7 @@ file_readln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) SECURITY_CHECK(cx, NULL, "readln", file); JSFILE_CHECK_READ; - buf = JS_malloc(cx, MAX_LINE_LENGTH * sizeof data); + buf = cx->malloc(MAX_LINE_LENGTH * sizeof data); if (!buf) return JS_FALSE; @@ -1792,8 +1792,7 @@ file_readln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) default: if (--room < 0) { - tmp = JS_realloc(cx, buf, - (offset + MAX_LINE_LENGTH) * sizeof data); + tmp = cx->realloc(buf, (offset + MAX_LINE_LENGTH) * sizeof data); if (!tmp) goto out; @@ -1814,7 +1813,7 @@ eof: done: buf[offset] = 0; - tmp = JS_realloc(cx, buf, (offset + 1) * sizeof data); + tmp = cx->realloc(buf, (offset + 1) * sizeof data); if (!tmp) goto out; @@ -1827,7 +1826,7 @@ done: out: if (buf) - JS_free(cx, buf); + cx->free(buf); return JS_FALSE; } @@ -1980,7 +1979,7 @@ file_list(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) filePath = js_combinePath(cx, file->path, (char*)entry->name); eachFile = js_NewFileObject(cx, filePath); - JS_free(cx, filePath); + cx->free(filePath); if (!eachFile){ JS_ReportWarning(cx, "File %s cannot be retrieved", filePath); continue; @@ -2017,7 +2016,7 @@ file_mkdir(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) char *dir = js_fileDirectoryName(cx, file->path); JSObject *dirObj = js_NewFileObject(cx, dir); - JS_free(cx, dir); + cx->free(dir); /* call file_mkdir with the right set of parameters if needed */ if (file_mkdir(cx, dirObj, argc, argv, rval)) @@ -2031,12 +2030,12 @@ file_mkdir(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) fullName = js_combinePath(cx, file->path, dirName); if (PR_MkDir(fullName, 0755)==PR_SUCCESS){ *rval = JSVAL_TRUE; - JS_free(cx, fullName); + cx->free(fullName); return JS_TRUE; }else{ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, JSFILEMSG_OP_FAILED, "mkdir", fullName); - JS_free(cx, fullName); + cx->free(fullName); goto out; } } @@ -2077,7 +2076,7 @@ file_toURL(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) return JS_FALSE; str = js_NewString(cx, urlChars, len); if (!str) { - JS_free(cx, urlChars); + cx->free(urlChars); return JS_FALSE; } *rval = STRING_TO_JSVAL(str); @@ -2104,9 +2103,9 @@ file_finalize(JSContext *cx, JSObject *obj) } if (file->path) - JS_free(cx, file->path); + cx->free(file->path); - JS_free(cx, file); + cx->free(file); } } @@ -2118,7 +2117,7 @@ file_init(JSContext *cx, JSObject *obj, char *bytes) { JSFile *file; - file = JS_malloc(cx, sizeof *file); + file = cx->malloc(sizeof *file); if (!file) return NULL; memset(file, 0 , sizeof *file); @@ -2130,7 +2129,7 @@ file_init(JSContext *cx, JSObject *obj, char *bytes) if (!JS_SetPrivate(cx, obj, file)) { JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, JSFILEMSG_CANNOT_SET_PRIVATE_FILE, file->path); - JS_free(cx, file); + cx->free(file); return NULL; } @@ -2176,7 +2175,7 @@ js_NewFileObjectFromFILE(JSContext *cx, FILE *nativehandle, char *filename, /* free result of RESOLVE_PATH from file_init. */ JS_ASSERT(file->path != NULL); - JS_free(cx, file->path); + cx->free(file->path); file->path = strdup(filename); file->isOpen = open; @@ -2399,7 +2398,7 @@ file_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) case FILE_MODE: SECURITY_CHECK(cx, NULL, "mode", file); JSFILE_CHECK_OPEN("mode"); - bytes = JS_malloc(cx, MODE_SIZE); + bytes = cx->malloc(MODE_SIZE); bytes[0] = '\0'; flag = JS_FALSE; @@ -2439,7 +2438,7 @@ file_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) flag = JS_TRUE; } *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, bytes)); - JS_free(cx, bytes); + cx->free(bytes); break; case FILE_CREATED: SECURITY_CHECK(cx, NULL, "creationTime", file); @@ -2575,7 +2574,7 @@ file_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) bytes = js_combinePath(cx, file->path, prop_name); *vp = OBJECT_TO_JSVAL(js_NewFileObject(cx, bytes)); PR_CloseDir(dir); - JS_free(cx, bytes); + cx->free(bytes); return !JSVAL_IS_NULL(*vp); } } @@ -2717,10 +2716,10 @@ js_InitFileClass(JSContext *cx, JSObject* obj) /* Define CURRENTDIR property. We are doing this to get a slash at the end of the current dir */ afile = js_NewFileObject(cx, CURRENT_DIR); - currentdir = JS_malloc(cx, MAX_PATH_LENGTH); - currentdir = getcwd(currentdir, MAX_PATH_LENGTH); + currentdir = cx->malloc(MAX_PATH_LENGTH); + currentdir = getcwd(currentdir, MAX_PATH_LENGTH); afile = js_NewFileObject(cx, currentdir); - JS_free(cx, currentdir); + cx->free(currentdir); vp = OBJECT_TO_JSVAL(afile); JS_DefinePropertyWithTinyId(cx, ctor, CURRENTDIR_PROPERTY, 0, vp, JS_PropertyStub, file_currentDirSetter, diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 90fc581a95c0..d4b02a1cb220 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -136,7 +136,7 @@ MarkArgDeleted(JSContext *cx, JSStackFrame *fp, uintN slot) bitmap = (jsbitmap *) &bmapint; } else { nbytes = JS_HOWMANY(nbits, JS_BITS_PER_WORD) * sizeof(jsbitmap); - bitmap = (jsbitmap *) JS_malloc(cx, nbytes); + bitmap = (jsbitmap *) cx->malloc(nbytes); if (!bitmap) return JS_FALSE; memset(bitmap, 0, nbytes); @@ -311,7 +311,7 @@ js_PutArgsObject(JSContext *cx, JSStackFrame *fp) if (!JSVAL_IS_VOID(bmapval)) { JS_SetReservedSlot(cx, argsobj, 0, JSVAL_VOID); if (fp->argc > JSVAL_INT_BITS) - JS_free(cx, JSVAL_TO_PRIVATE(bmapval)); + cx->free(JSVAL_TO_PRIVATE(bmapval)); } /* @@ -2758,10 +2758,10 @@ FreeLocalNameHash(JSContext *cx, JSLocalNameMap *map) for (dup = map->lastdup; dup; dup = next) { next = dup->link; - JS_free(cx, dup); + cx->free(dup); } JS_DHashTableFinish(&map->names); - JS_free(cx, map); + cx->free(map); } static JSBool @@ -2789,7 +2789,7 @@ HashLocalName(JSContext *cx, JSLocalNameMap *map, JSAtom *name, if (entry->name) { JS_ASSERT(entry->name == name); JS_ASSERT(entry->localKind == JSLOCAL_ARG); - dup = (JSNameIndexPair *) JS_malloc(cx, sizeof *dup); + dup = (JSNameIndexPair *) cx->malloc(sizeof *dup); if (!dup) return JS_FALSE; dup->name = entry->name; @@ -2835,7 +2835,7 @@ js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind) if (n > 1) { array = fun->u.i.names.array; } else { - array = (jsuword *) JS_malloc(cx, MAX_ARRAY_LOCALS * sizeof *array); + array = (jsuword *) cx->malloc(MAX_ARRAY_LOCALS * sizeof *array); if (!array) return JS_FALSE; array[0] = fun->u.i.names.taggedAtom; @@ -2860,7 +2860,7 @@ js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind) } } else if (n == MAX_ARRAY_LOCALS) { array = fun->u.i.names.array; - map = (JSLocalNameMap *) JS_malloc(cx, sizeof *map); + map = (JSLocalNameMap *) cx->malloc(sizeof *map); if (!map) return JS_FALSE; if (!JS_DHashTableInit(&map->names, JS_DHashGetStubOps(), @@ -2868,7 +2868,7 @@ js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind) JS_DHASH_DEFAULT_CAPACITY(MAX_ARRAY_LOCALS * 2))) { JS_ReportOutOfMemory(cx); - JS_free(cx, map); + cx->free(map); return JS_FALSE; } @@ -2901,7 +2901,7 @@ js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind) * to replace fun->u.i.names with the built map. */ fun->u.i.names.map = map; - JS_free(cx, array); + cx->free(array); } else { if (*indexp == JS_BITMASK(16)) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, @@ -3123,7 +3123,7 @@ DestroyLocalNames(JSContext *cx, JSFunction *fun) if (n <= 1) return; if (n <= MAX_ARRAY_LOCALS) - JS_free(cx, fun->u.i.names.array); + cx->free(fun->u.i.names.array); else FreeLocalNameHash(cx, fun->u.i.names.map); } @@ -3139,8 +3139,8 @@ js_FreezeLocalNames(JSContext *cx, JSFunction *fun) n = fun->nargs + fun->u.i.nvars + fun->u.i.nupvars; if (2 <= n && n < MAX_ARRAY_LOCALS) { /* Shrink over-allocated array ignoring realloc failures. */ - array = (jsuword *) JS_realloc(cx, fun->u.i.names.array, - n * sizeof *array); + array = (jsuword *) cx->realloc(fun->u.i.names.array, + n * sizeof *array); if (array) fun->u.i.names.array = array; } diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index f6a76120c4d4..386a65c83e83 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -76,6 +76,7 @@ #include "jsscript.h" #include "jsstaticcheck.h" #include "jsstr.h" +#include "jstask.h" #include "jstracer.h" #if JS_HAS_XML_SUPPORT @@ -722,7 +723,7 @@ FreePtrTable(JSPtrTable *table, const JSPtrTableInfo *info) { if (table->array) { JS_ASSERT(table->count > 0); - free(table->array); + js_free(table->array); table->array = NULL; table->count = 0; } @@ -756,8 +757,8 @@ AddToPtrTable(JSContext *cx, JSPtrTable *table, const JSPtrTableInfo *info, if (capacity > (size_t)-1 / sizeof table->array[0]) goto bad; } - array = (void **) realloc(table->array, - capacity * sizeof table->array[0]); + array = (void **) js_realloc(table->array, + capacity * sizeof table->array[0]); if (!array) goto bad; #ifdef DEBUG @@ -796,11 +797,11 @@ ShrinkPtrTable(JSPtrTable *table, const JSPtrTableInfo *info, array = table->array; JS_ASSERT(array); if (capacity == 0) { - free(array); + js_free(array); table->array = NULL; return; } - array = (void **) realloc(array, capacity * sizeof array[0]); + array = (void **) js_realloc(array, capacity * sizeof array[0]); if (array) table->array = array; } @@ -881,7 +882,7 @@ NewGCChunk(void) * * bytes to ensure that we always have room to store the gap. */ - p = malloc((js_gcArenasPerChunk + 1) << GC_ARENA_SHIFT); + p = js_malloc((js_gcArenasPerChunk + 1) << GC_ARENA_SHIFT); if (!p) return 0; @@ -913,11 +914,11 @@ DestroyGCChunk(jsuword chunk) #endif #if HAS_POSIX_MEMALIGN - free((void *) chunk); + js_free((void *) chunk); #else /* See comments in NewGCChunk. */ JS_ASSERT(*GetMallocedChunkGapPtr(chunk) < GC_ARENA_SIZE); - free((void *) (chunk - *GetMallocedChunkGapPtr(chunk))); + js_free((void *) (chunk - *GetMallocedChunkGapPtr(chunk))); #endif } @@ -3270,7 +3271,10 @@ js_FinalizeStringRT(JSRuntime *rt, JSString *str, intN type, JSContext *cx) JS_ASSERT(type < 0); rt->unitStrings[*chars] = NULL; } else if (type < 0) { - free(chars); + if (cx) + cx->free(chars); + else + rt->free(chars); } else { JS_ASSERT((uintN) type < JS_ARRAY_LENGTH(str_finalizers)); finalizer = str_finalizers[type]; @@ -3556,6 +3560,10 @@ js_GC(JSContext *cx, JSGCInvocationKind gckind) rt->gcMarkingTracer = NULL; +#ifdef JS_THREADSAFE + cx->createDeallocatorTask(); +#endif + /* * Sweep phase. * @@ -3734,6 +3742,10 @@ js_GC(JSContext *cx, JSGCInvocationKind gckind) */ DestroyGCArenas(rt, emptyArenas); +#ifdef JS_THREADSAFE + cx->submitDeallocatorTask(); +#endif + if (rt->gcCallback) (void) rt->gcCallback(cx, JSGC_FINALIZE_END); #ifdef DEBUG_srcnotesize diff --git a/js/src/jsgc.h b/js/src/jsgc.h index 417c6405274d..52ec7982fd68 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -47,6 +47,7 @@ #include "jsdhash.h" #include "jsbit.h" #include "jsutil.h" +#include "jstask.h" JS_BEGIN_EXTERN_C @@ -341,6 +342,28 @@ js_AddAsGCBytes(JSContext *cx, size_t sz); extern void js_RemoveAsGCBytes(JSRuntime* rt, size_t sz); +#ifdef JS_THREADSAFE +class JSFreePointerListTask : public JSBackgroundTask { + void *head; + public: + JSFreePointerListTask() : head(NULL) {} + + void add(void* ptr) { + *(void**)ptr = head; + head = ptr; + } + + void run() { + void *ptr = head; + while (ptr) { + void *next = *(void **)ptr; + js_free(ptr); + ptr = next; + } + } +}; +#endif + /* * Free the chars held by str when it is finalized by the GC. When type is * less then zero, it denotes an internal string. Otherwise it denotes the diff --git a/js/src/jshash.cpp b/js/src/jshash.cpp index 9e9466e4b6ed..e347744e7319 100644 --- a/js/src/jshash.cpp +++ b/js/src/jshash.cpp @@ -73,7 +73,7 @@ DefaultAllocTable(void *pool, size_t size) static void DefaultFreeTable(void *pool, void *item, size_t size) { - free(item); + js_free(item); } static JSHashEntry * @@ -86,7 +86,7 @@ static void DefaultFreeEntry(void *pool, JSHashEntry *he, uintN flag) { if (flag == HT_FREE_ENTRY) - free(he); + js_free(he); } static JSHashAllocOps defaultHashAllocOps = { diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index d77602e4782f..0d9a50ba5ad1 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -2145,7 +2145,7 @@ js_TraceOpcode(JSContext *cx) fprintf(tracefp, "%s %s", (n == -ndefs) ? " output:" : ",", bytes); - JS_free(cx, bytes); + cx->free(bytes); } } fprintf(tracefp, " @ %u\n", (uintN) (regs->sp - StackBase(fp))); @@ -2177,7 +2177,7 @@ js_TraceOpcode(JSContext *cx) fprintf(tracefp, "%s %s", (n == -nuses) ? " inputs:" : ",", bytes); - JS_free(cx, bytes); + cx->free(bytes); } } fprintf(tracefp, " @ %u\n", (uintN) (regs->sp - StackBase(fp))); @@ -2264,7 +2264,7 @@ js_DumpOpMeters() # define SIGNIFICANT(count,total) (200. * (count) >= (total)) - graph = (Edge *) calloc(nedges, sizeof graph[0]); + graph = (Edge *) js_calloc(nedges * sizeof graph[0]); for (i = nedges = 0; i < JSOP_LIMIT; i++) { from = js_CodeName[i]; for (j = 0; j < JSOP_LIMIT; j++) { @@ -2293,7 +2293,7 @@ js_DumpOpMeters() graph[i].from, graph[i].to, (unsigned long)graph[i].count, style); } - free(graph); + js_free(graph); fputs("}\n", fp); fclose(fp); diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index f941a6e3bd7e..a9c3473f9775 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -649,7 +649,7 @@ generator_finalize(JSContext *cx, JSObject *obj) */ JS_ASSERT(gen->state == JSGEN_NEWBORN || gen->state == JSGEN_CLOSED || gen->state == JSGEN_OPEN); - JS_free(cx, gen); + cx->free(gen); } } @@ -716,7 +716,7 @@ js_NewGenerator(JSContext *cx, JSStackFrame *fp) /* Allocate obj's private data struct. */ gen = (JSGenerator *) - JS_malloc(cx, sizeof(JSGenerator) + (nslots - 1) * sizeof(jsval)); + cx->malloc(sizeof(JSGenerator) + (nslots - 1) * sizeof(jsval)); if (!gen) goto bad; @@ -783,7 +783,7 @@ js_NewGenerator(JSContext *cx, JSStackFrame *fp) gen->state = JSGEN_NEWBORN; if (!JS_SetPrivate(cx, obj, gen)) { - JS_free(cx, gen); + cx->free(gen); goto bad; } return obj; diff --git a/js/src/jslock.cpp b/js/src/jslock.cpp index e31c15b9ab00..e1064f26a390 100644 --- a/js/src/jslock.cpp +++ b/js/src/jslock.cpp @@ -896,7 +896,7 @@ DestroyFatlock(JSFatLock *fl) { PR_DestroyLock(fl->slock); PR_DestroyCondVar(fl->svar); - free(fl); + js_free(fl); } static JSFatLock * @@ -990,7 +990,7 @@ js_SetupLocks(int listc, int globc) global_locks_log2 = JS_CeilingLog2(globc); global_locks_mask = JS_BITMASK(global_locks_log2); global_lock_count = JS_BIT(global_locks_log2); - global_locks = (PRLock **) malloc(global_lock_count * sizeof(PRLock*)); + global_locks = (PRLock **) js_malloc(global_lock_count * sizeof(PRLock*)); if (!global_locks) return JS_FALSE; for (i = 0; i < global_lock_count; i++) { @@ -1001,7 +1001,7 @@ js_SetupLocks(int listc, int globc) return JS_FALSE; } } - fl_list_table = (JSFatLockTable *) malloc(i * sizeof(JSFatLockTable)); + fl_list_table = (JSFatLockTable *) js_malloc(i * sizeof(JSFatLockTable)); if (!fl_list_table) { js_CleanupLocks(); return JS_FALSE; @@ -1023,7 +1023,7 @@ js_CleanupLocks() if (global_locks) { for (i = 0; i < global_lock_count; i++) PR_DestroyLock(global_locks[i]); - free(global_locks); + js_free(global_locks); global_locks = NULL; global_lock_count = 1; global_locks_log2 = 0; @@ -1036,7 +1036,7 @@ js_CleanupLocks() DeleteListOfFatlocks(fl_list_table[i].taken); fl_list_table[i].taken = NULL; } - free(fl_list_table); + js_free(fl_list_table); fl_list_table = NULL; fl_list_table_len = 0; } diff --git a/js/src/jsnum.cpp b/js/src/jsnum.cpp index 893f74aaaa2c..5c8993aa080e 100644 --- a/js/src/jsnum.cpp +++ b/js/src/jsnum.cpp @@ -384,7 +384,7 @@ num_toString(JSContext *cx, uintN argc, jsval *vp) return JS_FALSE; } str = JS_NewStringCopyZ(cx, dStr); - free(dStr); + js_free(dStr); } if (!str) return JS_FALSE; @@ -460,7 +460,7 @@ num_toLocaleString(JSContext *cx, uintN argc, jsval *vp) } tmpGroup--; - buf = (char *)JS_malloc(cx, size + 1); + buf = (char *)cx->malloc(size + 1); if (!buf) return JS_FALSE; @@ -492,7 +492,7 @@ num_toLocaleString(JSContext *cx, uintN argc, jsval *vp) str = JS_NewString(cx, buf, size); if (!str) { - JS_free(cx, buf); + cx->free(buf); return JS_FALSE; } @@ -739,9 +739,9 @@ js_FinishRuntimeNumberState(JSContext *cx) rt->jsNegativeInfinity = NULL; rt->jsPositiveInfinity = NULL; - JS_free(cx, (void *)rt->thousandsSeparator); - JS_free(cx, (void *)rt->decimalSeparator); - JS_free(cx, (void *)rt->numGrouping); + cx->free((void *)rt->thousandsSeparator); + cx->free((void *)rt->decimalSeparator); + cx->free((void *)rt->numGrouping); rt->thousandsSeparator = rt->decimalSeparator = rt->numGrouping = NULL; } @@ -852,7 +852,7 @@ NumberToStringWithBase(JSContext *cx, jsdouble d, jsint base) return NULL; s = JS_NewStringCopyZ(cx, numStr); if (!(numStr >= buf && numStr < buf + sizeof buf)) - free(numStr); + js_free(numStr); return s; } @@ -1251,7 +1251,7 @@ js_strtod(JSContext *cx, const jschar *s, const jschar *send, /* Use cbuf to avoid malloc */ if (length >= sizeof cbuf) { - cstr = (char *) JS_malloc(cx, length + 1); + cstr = (char *) cx->malloc(length + 1); if (!cstr) return JS_FALSE; } else { @@ -1292,7 +1292,7 @@ js_strtod(JSContext *cx, const jschar *s, const jschar *send, i = estr - cstr; if (cstr != cbuf) - JS_free(cx, cstr); + cx->free(cstr); *ep = i ? s1 + i : s; *dp = d; return JS_TRUE; @@ -1405,7 +1405,7 @@ js_strtointeger(JSContext *cx, const jschar *s, const jschar *send, */ size_t i; size_t length = s1 - start; - char *cstr = (char *) JS_malloc(cx, length + 1); + char *cstr = (char *) cx->malloc(length + 1); char *estr; int err=0; @@ -1418,12 +1418,12 @@ js_strtointeger(JSContext *cx, const jschar *s, const jschar *send, value = JS_strtod(cstr, &estr, &err); if (err == JS_DTOA_ENOMEM) { JS_ReportOutOfMemory(cx); - JS_free(cx, cstr); + cx->free(cstr); return JS_FALSE; } if (err == JS_DTOA_ERANGE && value == HUGE_VAL) value = *cx->runtime->jsPositiveInfinity; - JS_free(cx, cstr); + cx->free(cstr); } else if ((base & (base - 1)) == 0) { /* * The number may also be inaccurate for power-of-two bases. This diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 9ca39003a927..ed62904eecdc 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -560,7 +560,7 @@ out: ida = JS_Enumerate(cx, obj); if (!ida) { if (*sp) { - JS_free(cx, *sp); + cx->free(*sp); *sp = NULL; } goto bad; @@ -704,7 +704,7 @@ obj_toSource(JSContext *cx, uintN argc, jsval *vp) if (!chars) { /* If outermost, allocate 4 + 1 for "({})" and the terminator. */ - chars = (jschar *) malloc(((outermost ? 4 : 2) + 1) * sizeof(jschar)); + chars = (jschar *) js_malloc(((outermost ? 4 : 2) + 1) * sizeof(jschar)); nchars = 0; if (!chars) goto error; @@ -715,9 +715,9 @@ obj_toSource(JSContext *cx, uintN argc, jsval *vp) MAKE_SHARP(he); nchars = js_strlen(chars); chars = (jschar *) - realloc((ochars = chars), (nchars + 2 + 1) * sizeof(jschar)); + js_realloc((ochars = chars), (nchars + 2 + 1) * sizeof(jschar)); if (!chars) { - free(ochars); + js_free(ochars); goto error; } if (outermost) { @@ -958,11 +958,11 @@ obj_toSource(JSContext *cx, uintN argc, jsval *vp) /* Allocate 1 + 1 at end for closing brace and terminating 0. */ chars = (jschar *) - realloc((ochars = chars), curlen * sizeof(jschar)); + js_realloc((ochars = chars), curlen * sizeof(jschar)); if (!chars) { /* Save code space on error: let JS_free ignore null vsharp. */ - JS_free(cx, vsharp); - free(ochars); + cx->free(vsharp); + js_free(ochars); goto error; } @@ -1005,7 +1005,7 @@ obj_toSource(JSContext *cx, uintN argc, jsval *vp) nchars += vlength; if (vsharp) - JS_free(cx, vsharp); + cx->free(vsharp); } } @@ -1019,7 +1019,7 @@ obj_toSource(JSContext *cx, uintN argc, jsval *vp) if (!ok) { if (chars) - free(chars); + js_free(chars); goto out; } @@ -1031,7 +1031,7 @@ obj_toSource(JSContext *cx, uintN argc, jsval *vp) make_string: str = js_NewString(cx, chars, nchars); if (!str) { - free(chars); + js_free(chars); ok = JS_FALSE; goto out; } @@ -1042,8 +1042,8 @@ obj_toSource(JSContext *cx, uintN argc, jsval *vp) return ok; overflow: - JS_free(cx, vsharp); - free(chars); + cx->free(vsharp); + js_free(chars); chars = NULL; goto error; } @@ -1064,7 +1064,7 @@ obj_toString(JSContext *cx, uintN argc, jsval *vp) obj = js_GetWrappedObject(cx, obj); clazz = OBJ_GET_CLASS(cx, obj)->name; nchars = 9 + strlen(clazz); /* 9 for "[object ]" */ - chars = (jschar *) JS_malloc(cx, (nchars + 1) * sizeof(jschar)); + chars = (jschar *) cx->malloc((nchars + 1) * sizeof(jschar)); if (!chars) return JS_FALSE; @@ -1079,7 +1079,7 @@ obj_toString(JSContext *cx, uintN argc, jsval *vp) str = js_NewString(cx, chars, nchars); if (!str) { - JS_free(cx, chars); + cx->free(chars); return JS_FALSE; } *vp = STRING_TO_JSVAL(str); @@ -2986,7 +2986,7 @@ AllocSlots(JSContext *cx, JSObject *obj, size_t nslots) JS_ASSERT(nslots > JS_INITIAL_NSLOTS); jsval* slots; - slots = (jsval*) JS_malloc(cx, SLOTS_TO_DYNAMIC_WORDS(nslots) * sizeof(jsval)); + slots = (jsval*) cx->malloc(SLOTS_TO_DYNAMIC_WORDS(nslots) * sizeof(jsval)); if (!slots) return true; @@ -3044,7 +3044,7 @@ js_GrowSlots(JSContext *cx, JSObject *obj, size_t nslots) size_t oslots = size_t(slots[-1]); - slots = (jsval*) JS_realloc(cx, slots - 1, nwords * sizeof(jsval)); + slots = (jsval*) cx->realloc(slots - 1, nwords * sizeof(jsval)); *slots++ = nslots; obj->dslots = slots; @@ -3069,11 +3069,11 @@ js_ShrinkSlots(JSContext *cx, JSObject *obj, size_t nslots) JS_ASSERT(nslots <= size_t(slots[-1])); if (nslots <= JS_INITIAL_NSLOTS) { - JS_free(cx, slots - 1); + cx->free(slots - 1); obj->dslots = NULL; } else { size_t nwords = SLOTS_TO_DYNAMIC_WORDS(nslots); - slots = (jsval*) JS_realloc(cx, slots - 1, nwords * sizeof(jsval)); + slots = (jsval*) cx->realloc(slots - 1, nwords * sizeof(jsval)); *slots++ = nslots; obj->dslots = slots; } @@ -4965,7 +4965,7 @@ js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, } allocated = NativeEnumeratorSize(length); - ne = (JSNativeEnumerator *) JS_malloc(cx, allocated); + ne = (JSNativeEnumerator *) cx->malloc(allocated); if (!ne) { JS_UNLOCK_SCOPE(cx, scope); return JS_FALSE; @@ -4997,7 +4997,7 @@ js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, JS_LOCK_GC(cx->runtime); if (!js_AddAsGCBytes(cx, allocated)) { /* js_AddAsGCBytes releases the GC lock on failures. */ - JS_free(cx, ne); + cx->free(ne); return JS_FALSE; } ne->next = cx->runtime->nativeEnumerators; @@ -5090,7 +5090,7 @@ js_TraceNativeEnumerators(JSTracer *trc) } else if (doGC) { js_RemoveAsGCBytes(rt, NativeEnumeratorSize(ne->length)); *nep = ne->next; - JS_free(trc->context, ne); + trc->context->free(ne); continue; } nep = &ne->next; diff --git a/js/src/json.cpp b/js/src/json.cpp index 43bf3ab03259..6f790f0e9843 100644 --- a/js/src/json.cpp +++ b/js/src/json.cpp @@ -38,7 +38,7 @@ * * ***** END LICENSE BLOCK ***** */ -#include /* memset */ +#include #include "jsapi.h" #include "jsarena.h" #include "jsarray.h" @@ -740,10 +740,9 @@ js_BeginJSONParse(JSContext *cx, jsval *rootVal) if (!arr) return NULL; - JSONParser *jp = (JSONParser*) JS_malloc(cx, sizeof(JSONParser)); + JSONParser *jp = (JSONParser*) cx->calloc(sizeof(JSONParser)); if (!jp) return NULL; - memset(jp, 0, sizeof *jp); jp->objectStack = arr; if (!js_AddRoot(cx, &jp->objectStack, "JSON parse stack")) @@ -798,7 +797,7 @@ js_FinishJSONParse(JSContext *cx, JSONParser *jp, jsval reviver) JSBool ok = *jp->statep == JSON_PARSE_STATE_FINISHED; jsval *vp = jp->rootVal; - JS_free(cx, jp); + cx->free(jp); if (!early_ok) return JS_FALSE; diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index 98e0970ceddb..28376ee0076b 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -604,7 +604,7 @@ Sprint(Sprinter *sp, const char *format, ...) return -1; } offset = SprintCString(sp, bp); - free(bp); + js_free(bp); return offset; } @@ -737,7 +737,7 @@ JS_NEW_PRINTER(JSContext *cx, const char *name, JSFunction *fun, { JSPrinter *jp; - jp = (JSPrinter *) JS_malloc(cx, sizeof(JSPrinter)); + jp = (JSPrinter *) cx->malloc(sizeof(JSPrinter)); if (!jp) return NULL; INIT_SPRINTER(cx, &jp->sprinter, &jp->pool, 0); @@ -764,7 +764,7 @@ void js_DestroyPrinter(JSPrinter *jp) { JS_FinishArenaPool(&jp->pool); - JS_free(jp->sprinter.context, jp); + jp->sprinter.context->free(jp); } JSString * @@ -832,7 +832,7 @@ js_printf(JSPrinter *jp, const char *format, ...) /* Allocate temp space, convert format, and put. */ bp = JS_vsmprintf(format, ap); /* XXX vsaprintf */ if (fp) { - JS_free(jp->sprinter.context, fp); + jp->sprinter.context->free(fp); format = NULL; } if (!bp) { @@ -843,7 +843,7 @@ js_printf(JSPrinter *jp, const char *format, ...) cc = strlen(bp); if (SprintPut(&jp->sprinter, bp, (size_t)cc) < 0) cc = -1; - free(bp); + js_free(bp); va_end(ap); return cc; @@ -929,7 +929,7 @@ GetOff(SprintStack *ss, uintN i) if (off < 0) off = 0; ss->offsets[i] = off; - JS_free(ss->sprinter.context, bytes); + ss->sprinter.context->free(bytes); return off; } if (!ss->sprinter.base && SprintPut(&ss->sprinter, "", 0) >= 0) { @@ -2508,14 +2508,14 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) len = 0; if (!Decompile(ss, done, pc - done, JSOP_POP)) { - JS_free(cx, (char *)lval); + cx->free((char *)lval); return NULL; } /* Pop Decompile result and print comma expression. */ rval = POP_STR(); todo = Sprint(&ss->sprinter, "%s, %s", lval, rval); - JS_free(cx, (char *)lval); + cx->free((char *)lval); break; case SRC_HIDDEN: @@ -2547,7 +2547,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) /* Set saveop to reflect what we will push. */ saveop = JSOP_LEAVEBLOCKEXPR; if (!Decompile(ss, pc, len, saveop)) { - JS_free(cx, (char *)lval); + cx->free((char *)lval); return NULL; } rval = PopStr(ss, JSOP_SETNAME); @@ -2556,7 +2556,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) ? "let (%s) (%s)" : "let (%s) %s", lval, rval); - JS_free(cx, (char *)lval); + cx->free((char *)lval); } break; @@ -2620,7 +2620,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) if ((size_t)argc <= JS_ARRAY_LENGTH(smallv)) { atomv = smallv; } else { - atomv = (JSAtom **) JS_malloc(cx, argc * sizeof(JSAtom *)); + atomv = (JSAtom **) cx->malloc(argc * sizeof(JSAtom *)); if (!atomv) return NULL; } @@ -2755,7 +2755,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) #undef LOCAL_ASSERT_OUT enterblock_out: if (atomv != smallv) - JS_free(cx, atomv); + cx->free(atomv); if (!ok) return NULL; } @@ -3280,7 +3280,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) DECOMPILE_CODE(pc + oplen, len - oplen); lval = JS_strdup(cx, POP_STR()); if (!lval) { - JS_free(cx, (void *)xval); + cx->free((void *)xval); return NULL; } pc += len; @@ -3291,8 +3291,8 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) rval = POP_STR(); todo = Sprint(&ss->sprinter, "%s ? %s : %s", xval, lval, rval); - JS_free(cx, (void *)xval); - JS_free(cx, (void *)lval); + cx->free((void *)xval); + cx->free((void *)lval); break; default: @@ -3319,7 +3319,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) pc += len; len = done - pc; if (!Decompile(ss, pc, len, op)) { - JS_free(cx, (char *)lval); + cx->free((char *)lval); return NULL; } rval = POP_STR(); @@ -3332,14 +3332,14 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) todo = Sprint(&ss->sprinter, "%s %s\n", lval, xval); tail = Sprint(&ss->sprinter, "%*s%s", jp->indent + 4, "", rval); - JS_free(cx, (char *)rval); + cx->free((char *)rval); } if (tail < 0) todo = -1; } else { todo = Sprint(&ss->sprinter, "%s %s %s", lval, xval, rval); } - JS_free(cx, (char *)lval); + cx->free((char *)lval); break; case JSOP_AND: @@ -3532,7 +3532,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) #endif argc = GET_ARGC(pc); argv = (char **) - JS_malloc(cx, (size_t)(argc + 1) * sizeof *argv); + cx->malloc((size_t)(argc + 1) * sizeof *argv); if (!argv) return NULL; @@ -3590,8 +3590,8 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) ok = JS_FALSE; for (i = 0; i <= argc; i++) - JS_free(cx, argv[i]); - JS_free(cx, argv); + cx->free(argv[i]); + cx->free(argv); if (!ok) return NULL; #if JS_HAS_LVALUE_RETURN @@ -4095,7 +4095,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) if (!rval) return NULL; todo = SprintCString(&ss->sprinter, rval); - JS_free(cx, (void *)rval); + cx->free((void *)rval); break; } #endif /* JS_HAS_GENERATOR_EXPRS */ @@ -4166,7 +4166,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) ok = JS_TRUE; } else { table = (TableEntry *) - JS_malloc(cx, (size_t)n * sizeof *table); + cx->malloc((size_t)n * sizeof *table); if (!table) return NULL; for (i = j = 0; i < n; i++) { @@ -4186,12 +4186,12 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) pc2 += jmplen; } tmp = (TableEntry *) - JS_malloc(cx, (size_t)j * sizeof *table); + cx->malloc((size_t)j * sizeof *table); if (tmp) { VOUCH_DOES_NOT_REQUIRE_STACK(); ok = js_MergeSort(table, (size_t)j, sizeof(TableEntry), CompareOffsets, NULL, tmp); - JS_free(cx, tmp); + cx->free(tmp); } else { ok = JS_FALSE; } @@ -4201,7 +4201,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) ok = DecompileSwitch(ss, table, (uintN)j, pc, len, off, JS_FALSE); } - JS_free(cx, table); + cx->free(table); if (!ok) return NULL; todo = -2; @@ -4227,7 +4227,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) pc2 += UINT16_LEN; table = (TableEntry *) - JS_malloc(cx, (size_t)npairs * sizeof *table); + cx->malloc((size_t)npairs * sizeof *table); if (!table) return NULL; for (k = 0; k < npairs; k++) { @@ -4248,7 +4248,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) ok = DecompileSwitch(ss, table, (uintN)npairs, pc, len, off, JS_FALSE); - JS_free(cx, table); + cx->free(table); if (!ok) return NULL; todo = -2; @@ -4292,7 +4292,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) * and the distance to its statements in table[i].offset. */ table = (TableEntry *) - JS_malloc(cx, (size_t)ncases * sizeof *table); + cx->malloc((size_t)ncases * sizeof *table); if (!table) return NULL; pc2 = pc; @@ -4322,7 +4322,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) ok = DecompileSwitch(ss, table, (uintN)ncases, pc, len, off, JS_TRUE); - JS_free(cx, table); + cx->free(table); if (!ok) return NULL; todo = -2; @@ -4370,7 +4370,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) break; } - argv = (char **) JS_malloc(cx, size_t(argc) * sizeof *argv); + argv = (char **) cx->malloc(size_t(argc) * sizeof *argv); if (!argv) return NULL; @@ -4394,8 +4394,8 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) } for (i = 0; i < argc; i++) - JS_free(cx, argv[i]); - JS_free(cx, argv); + cx->free(argv[i]); + cx->free(argv); if (!ok) return NULL; @@ -4728,7 +4728,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) (*rval == '\0' || (SprintPut(&ss->sprinter, " ", 1) >= 0 && SprintCString(&ss->sprinter, rval))); - JS_free(cx, (char *)rval); + cx->free((char *)rval); if (!ok) return NULL; SprintPut(&ss->sprinter, "?>", 2); @@ -4836,7 +4836,7 @@ DecompileCode(JSPrinter *jp, JSScript *script, jsbytecode *pc, uintN len, ok = Decompile(&ss, pc, len, JSOP_NOP) != NULL; if (code != oldcode) { - JS_free(cx, jp->script->code); + cx->free(jp->script->code); jp->script->code = oldcode; jp->script->main = oldmain; } @@ -5055,7 +5055,7 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v, * populated interpreter's stack with its current content. */ pcstack = (jsbytecode **) - JS_malloc(cx, StackDepth(script) * sizeof *pcstack); + cx->malloc(StackDepth(script) * sizeof *pcstack); if (!pcstack) return NULL; pcdepth = ReconstructPCStack(cx, script, pc, pcstack); @@ -5096,7 +5096,7 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v, } release_pcstack: - JS_free(cx, pcstack); + cx->free(pcstack); if (pcdepth < 0) goto do_fallback; } @@ -5232,7 +5232,7 @@ DecompileExpression(JSContext *cx, JSScript *script, JSFunction *fun, } pcstack = (jsbytecode **) - JS_malloc(cx, StackDepth(script) * sizeof *pcstack); + cx->malloc(StackDepth(script) * sizeof *pcstack); if (!pcstack) { name = NULL; goto out; @@ -5259,12 +5259,12 @@ DecompileExpression(JSContext *cx, JSScript *script, JSFunction *fun, out: if (code != oldcode) { - JS_free(cx, script->code); + cx->free(script->code); script->code = oldcode; script->main = oldmain; } - JS_free(cx, pcstack); + cx->free(pcstack); return name; } @@ -5339,7 +5339,7 @@ SimulateImacroCFG(JSContext *cx, JSScript *script, jsbytecode **pcstack) { size_t nbytes = StackDepth(script) * sizeof *pcstack; - jsbytecode** tmp_pcstack = (jsbytecode **) JS_malloc(cx, nbytes); + jsbytecode** tmp_pcstack = (jsbytecode **) cx->malloc(nbytes); if (!tmp_pcstack) return -1; memcpy(tmp_pcstack, pcstack, nbytes); @@ -5379,11 +5379,11 @@ SimulateImacroCFG(JSContext *cx, JSScript *script, success: memcpy(pcstack, tmp_pcstack, nbytes); - JS_free(cx, tmp_pcstack); + cx->free(tmp_pcstack); return pcdepth; failure: - JS_free(cx, tmp_pcstack); + cx->free(tmp_pcstack); return -1; } diff --git a/js/src/jsparse.cpp b/js/src/jsparse.cpp index 161dfbc94ae2..35cd45dd9d63 100644 --- a/js/src/jsparse.cpp +++ b/js/src/jsparse.cpp @@ -9036,12 +9036,12 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, bool inCond) } /* Allocate a new buffer and string descriptor for the result. */ - chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar)); + chars = (jschar *) cx->malloc((length + 1) * sizeof(jschar)); if (!chars) return JS_FALSE; str = js_NewString(cx, chars, length); if (!str) { - JS_free(cx, chars); + cx->free(chars); return JS_FALSE; } diff --git a/js/src/jsprf.cpp b/js/src/jsprf.cpp index 5686c1eabcda..6e02bc2d1857 100644 --- a/js/src/jsprf.cpp +++ b/js/src/jsprf.cpp @@ -412,7 +412,7 @@ static int cvt_ws(SprintfState *ss, const jschar *ws, int width, int prec, if (!s) return -1; /* JSStuffFunc error indicator. */ result = cvt_s(ss, s, width, prec, flags); - free(s); + js_free(s); } else { result = cvt_s(ss, NULL, width, prec, flags); } @@ -630,7 +630,7 @@ static struct NumArgState* BuildArgArray( const char *fmt, va_list ap, int* rv, if( *rv < 0 ){ if( nas != nasArray ) - free( nas ); + js_free( nas ); return NULL; } @@ -667,7 +667,7 @@ static struct NumArgState* BuildArgArray( const char *fmt, va_list ap, int* rv, default: if( nas != nasArray ) - free( nas ); + js_free( nas ); *rv = -1; return NULL; } @@ -756,7 +756,7 @@ static int dosprintf(SprintfState *ss, const char *fmt, va_list ap) if( nas[i-1].type == TYPE_UNKNOWN ){ if( nas && ( nas != nasArray ) ) - free( nas ); + js_free( nas ); return -1; } @@ -1037,7 +1037,7 @@ static int dosprintf(SprintfState *ss, const char *fmt, va_list ap) rv = (*ss->stuff)(ss, "\0", 1); if( nas && ( nas != nasArray ) ){ - free( nas ); + js_free( nas ); } return rv; @@ -1098,9 +1098,9 @@ static int GrowStuff(SprintfState *ss, const char *sp, JSUint32 len) /* Grow the buffer */ newlen = ss->maxlen + ((len > 32) ? len : 32); if (ss->base) { - newbase = (char*) realloc(ss->base, newlen); + newbase = (char*) js_realloc(ss->base, newlen); } else { - newbase = (char*) malloc(newlen); + newbase = (char*) js_malloc(newlen); } if (!newbase) { /* Ran out of memory */ @@ -1139,7 +1139,7 @@ JS_PUBLIC_API(char *) JS_smprintf(const char *fmt, ...) */ JS_PUBLIC_API(void) JS_smprintf_free(char *mem) { - free(mem); + js_free(mem); } JS_PUBLIC_API(char *) JS_vsmprintf(const char *fmt, va_list ap) @@ -1154,7 +1154,7 @@ JS_PUBLIC_API(char *) JS_vsmprintf(const char *fmt, va_list ap) rv = dosprintf(&ss, fmt, ap); if (rv < 0) { if (ss.base) { - free(ss.base); + js_free(ss.base); } return 0; } @@ -1253,7 +1253,7 @@ JS_PUBLIC_API(char *) JS_vsprintf_append(char *last, const char *fmt, va_list ap rv = dosprintf(&ss, fmt, ap); if (rv < 0) { if (ss.base) { - free(ss.base); + js_free(ss.base); } return 0; } diff --git a/js/src/jspubtd.h b/js/src/jspubtd.h index c2068d65d07c..7efcbfbcc64a 100644 --- a/js/src/jspubtd.h +++ b/js/src/jspubtd.h @@ -145,7 +145,6 @@ typedef struct JSObject JSObject; typedef struct JSObjectMap JSObjectMap; typedef struct JSObjectOps JSObjectOps; typedef struct JSRuntime JSRuntime; -typedef struct JSRuntime JSTaskState; /* XXX deprecated name */ typedef struct JSScript JSScript; typedef struct JSStackFrame JSStackFrame; typedef struct JSString JSString; diff --git a/js/src/jsregexp.cpp b/js/src/jsregexp.cpp index 05762c296b49..8a098ee42659 100644 --- a/js/src/jsregexp.cpp +++ b/js/src/jsregexp.cpp @@ -585,12 +585,12 @@ ParseRegExp(CompilerState *state) } operatorStack = (REOpData *) - JS_malloc(state->context, sizeof(REOpData) * operatorStackSize); + state->context->malloc(sizeof(REOpData) * operatorStackSize); if (!operatorStack) return JS_FALSE; operandStack = (RENode **) - JS_malloc(state->context, sizeof(RENode *) * operandStackSize); + state->context->malloc(sizeof(RENode *) * operandStackSize); if (!operandStack) goto out; @@ -682,8 +682,8 @@ pushOperand: RENode **tmp; operandStackSize += operandStackSize; tmp = (RENode **) - JS_realloc(state->context, operandStack, - sizeof(RENode *) * operandStackSize); + state->context->realloc(operandStack, + sizeof(RENode *) * operandStackSize); if (!tmp) goto out; operandStack = tmp; @@ -817,8 +817,8 @@ pushOperator: REOpData *tmp; operatorStackSize += operatorStackSize; tmp = (REOpData *) - JS_realloc(state->context, operatorStack, - sizeof(REOpData) * operatorStackSize); + state->context->realloc(operatorStack, + sizeof(REOpData) * operatorStackSize); if (!tmp) goto out; operatorStack = tmp; @@ -831,9 +831,9 @@ pushOperator: } out: if (operatorStack) - JS_free(state->context, operatorStack); + state->context->free(operatorStack); if (operandStack) - JS_free(state->context, operandStack); + state->context->free(operandStack); return result; } @@ -1647,9 +1647,8 @@ EmitREBytecode(CompilerState *state, JSRegExp *re, size_t treeDepth, emitStateStack = NULL; } else { emitStateStack = - (EmitStateStackEntry *)JS_malloc(state->context, - sizeof(EmitStateStackEntry) * - treeDepth); + (EmitStateStackEntry *) + state->context->malloc(sizeof(EmitStateStackEntry) * treeDepth); if (!emitStateStack) return NULL; } @@ -1951,7 +1950,7 @@ EmitREBytecode(CompilerState *state, JSRegExp *re, size_t treeDepth, cleanup: if (emitStateStack) - JS_free(state->context, emitStateStack); + state->context->free(emitStateStack); return pc; jump_too_big: @@ -3228,7 +3227,7 @@ js_NewRegExp(JSContext *cx, JSTokenStream *ts, goto out; resize = offsetof(JSRegExp, program) + state.progLength + 1; - re = (JSRegExp *) JS_malloc(cx, resize); + re = (JSRegExp *) cx->malloc(resize); if (!re) goto out; @@ -3237,7 +3236,7 @@ js_NewRegExp(JSContext *cx, JSTokenStream *ts, re->classCount = state.classCount; if (re->classCount) { re->classList = (RECharSet *) - JS_malloc(cx, re->classCount * sizeof(RECharSet)); + cx->malloc(re->classCount * sizeof(RECharSet)); if (!re->classList) { js_DestroyRegExp(cx, re); re = NULL; @@ -3266,7 +3265,7 @@ js_NewRegExp(JSContext *cx, JSTokenStream *ts, JSRegExp *tmp; JS_ASSERT((size_t)(endPC - re->program) < state.progLength + 1); resize = offsetof(JSRegExp, program) + (endPC - re->program); - tmp = (JSRegExp *) JS_realloc(cx, re, resize); + tmp = (JSRegExp *) cx->realloc(re, resize); if (tmp) re = tmp; } @@ -3606,7 +3605,7 @@ ProcessCharSet(JSContext *cx, JSRegExp *re, RECharSet *charSet) JS_ASSERT(end[0] == ']'); byteLength = (charSet->length >> 3) + 1; - charSet->u.bits = (uint8 *)JS_malloc(cx, byteLength); + charSet->u.bits = (uint8 *)cx->malloc(byteLength); if (!charSet->u.bits) { JS_ReportOutOfMemory(cx); return JS_FALSE; @@ -3800,12 +3799,12 @@ js_DestroyRegExp(JSContext *cx, JSRegExp *re) uintN i; for (i = 0; i < re->classCount; i++) { if (re->classList[i].converted) - JS_free(cx, re->classList[i].u.bits); + cx->free(re->classList[i].u.bits); re->classList[i].u.bits = NULL; } - JS_free(cx, re->classList); + cx->free(re->classList); } - JS_free(cx, re); + cx->free(re); } } @@ -4870,12 +4869,12 @@ js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp, if (!morepar) { res->moreLength = 10; morepar = (JSSubString*) - JS_malloc(cx, 10 * sizeof(JSSubString)); + cx->malloc(10 * sizeof(JSSubString)); } else if (morenum >= res->moreLength) { res->moreLength += 10; morepar = (JSSubString*) - JS_realloc(cx, morepar, - res->moreLength * sizeof(JSSubString)); + cx->realloc(morepar, + res->moreLength * sizeof(JSSubString)); } if (!morepar) { cx->weakRoots.newborn[GCX_OBJECT] = NULL; @@ -5114,7 +5113,7 @@ js_FreeRegExpStatics(JSContext *cx) JSRegExpStatics *res = &cx->regExpStatics; if (res->moreParens) { - JS_free(cx, res->moreParens); + cx->free(res->moreParens); res->moreParens = NULL; } JS_FinishArenaPool(&cx->regexpPool); @@ -5365,7 +5364,7 @@ js_regexp_toString(JSContext *cx, JSObject *obj, jsval *vp) nflags = 0; for (flags = re->flags; flags != 0; flags &= flags - 1) nflags++; - chars = (jschar*) JS_malloc(cx, (length + nflags + 1) * sizeof(jschar)); + chars = (jschar*) cx->malloc((length + nflags + 1) * sizeof(jschar)); if (!chars) { JS_UNLOCK_OBJ(cx, obj); return JS_FALSE; @@ -5389,7 +5388,7 @@ js_regexp_toString(JSContext *cx, JSObject *obj, jsval *vp) str = js_NewString(cx, chars, length); if (!str) { - JS_free(cx, chars); + cx->free(chars); return JS_FALSE; } *vp = STRING_TO_JSVAL(str); @@ -5472,15 +5471,15 @@ regexp_compile_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, if (*cp == '/' && (cp == start || cp[-1] != '\\')) { nbytes = (++length + 1) * sizeof(jschar); if (!nstart) { - nstart = (jschar *) JS_malloc(cx, nbytes); + nstart = (jschar *) cx->malloc(nbytes); if (!nstart) return JS_FALSE; ncp = nstart + (cp - start); js_strncpy(nstart, start, cp - start); } else { - tmp = (jschar *) JS_realloc(cx, nstart, nbytes); + tmp = (jschar *) cx->realloc(nstart, nbytes); if (!tmp) { - JS_free(cx, nstart); + cx->free(nstart); return JS_FALSE; } ncp = tmp + (ncp - nstart); @@ -5498,7 +5497,7 @@ regexp_compile_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, *ncp = 0; str = js_NewString(cx, nstart, length); if (!str) { - JS_free(cx, nstart); + cx->free(nstart); return JS_FALSE; } argv[0] = STRING_TO_JSVAL(str); diff --git a/js/src/jsscan.cpp b/js/src/jsscan.cpp index 37e50a80d85a..90f3547671d4 100644 --- a/js/src/jsscan.cpp +++ b/js/src/jsscan.cpp @@ -258,7 +258,7 @@ void js_CloseTokenStream(JSContext *cx, JSTokenStream *ts) { if (ts->flags & TSF_OWNFILENAME) - JS_free(cx, (void *) ts->filename); + cx->free((void *) ts->filename); } JS_FRIEND_API(int) @@ -562,7 +562,7 @@ js_ReportCompileErrorNumber(JSContext *cx, JSTokenStream *ts, JSParseNode *pn, } report.lineno = ts->lineno; linelength = ts->linebuf.limit - ts->linebuf.base; - linechars = (jschar *)JS_malloc(cx, (linelength + 1) * sizeof(jschar)); + linechars = (jschar *)cx->malloc((linelength + 1) * sizeof(jschar)); if (!linechars) { warning = JS_FALSE; goto out; @@ -651,21 +651,21 @@ js_ReportCompileErrorNumber(JSContext *cx, JSTokenStream *ts, JSParseNode *pn, out: if (linebytes) - JS_free(cx, linebytes); + cx->free(linebytes); if (linechars) - JS_free(cx, linechars); + cx->free(linechars); if (message) - JS_free(cx, message); + cx->free(message); if (report.ucmessage) - JS_free(cx, (void *)report.ucmessage); + cx->free((void *)report.ucmessage); if (report.messageArgs) { if (!(flags & JSREPORT_UC)) { i = 0; while (report.messageArgs[i]) - JS_free(cx, (void *)report.messageArgs[i++]); + cx->free((void *)report.messageArgs[i++]); } - JS_free(cx, (void *)report.messageArgs); + cx->free((void *)report.messageArgs); } if (!JSREPORT_IS_WARNING(flags)) { @@ -698,7 +698,7 @@ GrowStringBuffer(JSStringBuffer *sb, size_t amount) /* Now do the full overflow check. */ if (size_t(offset) < newlength && newlength < ~size_t(0) / sizeof(jschar)) { - jschar *bp = (jschar *) realloc(sb->base, newlength * sizeof(jschar)); + jschar *bp = (jschar *) js_realloc(sb->base, newlength * sizeof(jschar)); if (bp) { sb->base = bp; sb->ptr = bp + offset; @@ -709,7 +709,7 @@ GrowStringBuffer(JSStringBuffer *sb, size_t amount) } /* Either newlength overflow or realloc failure: poison the well. */ - free(sb->base); + js_free(sb->base); sb->base = STRING_BUFFER_ERROR_BASE; return false; } @@ -719,7 +719,7 @@ FreeStringBuffer(JSStringBuffer *sb) { JS_ASSERT(STRING_BUFFER_OK(sb)); if (sb->base) - free(sb->base); + js_free(sb->base); } void @@ -924,7 +924,7 @@ bad: if (bytes) { js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR, msg, bytes); - JS_free(cx, bytes); + cx->free(bytes); } return JS_FALSE; } @@ -1788,7 +1788,7 @@ retry: if (c == '\n') { if (i > 0) { if (ts->flags & TSF_OWNFILENAME) - JS_free(cx, (void *) ts->filename); + cx->free((void *) ts->filename); ts->filename = JS_strdup(cx, filename); if (!ts->filename) goto error; diff --git a/js/src/jsscope.cpp b/js/src/jsscope.cpp index 929f01f72715..40c5add19fe3 100644 --- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -166,7 +166,7 @@ JSScope::createTable(JSContext *cx, bool report) sizeLog2 = MIN_SCOPE_SIZE_LOG2; } - table = (JSScopeProperty **) calloc(JS_BIT(sizeLog2), sizeof(JSScopeProperty *)); + table = (JSScopeProperty **) js_calloc(JS_BIT(sizeLog2) * sizeof(JSScopeProperty *)); if (!table) { if (report) JS_ReportOutOfMemory(cx); @@ -188,7 +188,7 @@ JSScope::create(JSContext *cx, JSObjectOps *ops, JSClass *clasp, JSObject *obj) JS_ASSERT(OPS_IS_NATIVE(ops)); JS_ASSERT(obj); - JSScope *scope = (JSScope *) JS_malloc(cx, sizeof(JSScope)); + JSScope *scope = (JSScope *) cx->malloc(sizeof(JSScope)); if (!scope) return NULL; @@ -213,7 +213,7 @@ JSScope::createEmptyScope(JSContext *cx, JSClass *clasp) { JS_ASSERT(!emptyScope); - JSScope *scope = (JSScope *) JS_malloc(cx, sizeof(JSScope)); + JSScope *scope = (JSScope *) cx->malloc(sizeof(JSScope)); if (!scope) return NULL; @@ -252,13 +252,13 @@ JSScope::destroy(JSContext *cx, JSScope *scope) js_FinishTitle(cx, &scope->title); #endif if (scope->table) - JS_free(cx, scope->table); + cx->free(scope->table); if (scope->emptyScope) scope->emptyScope->drop(cx, NULL); LIVE_SCOPE_METER(cx, cx->runtime->liveScopeProps -= scope->entryCount); JS_RUNTIME_UNMETER(cx->runtime, liveScopes); - JS_free(cx, scope); + cx->free(scope); } #ifdef JS_DUMP_PROPTREE_STATS @@ -401,11 +401,9 @@ JSScope::changeTable(JSContext *cx, int change) oldsize = JS_BIT(oldlog2); newsize = JS_BIT(newlog2); nbytes = SCOPE_TABLE_NBYTES(newsize); - newtable = (JSScopeProperty **) calloc(nbytes, 1); - if (!newtable) { - JS_ReportOutOfMemory(cx); + newtable = (JSScopeProperty **) cx->calloc(nbytes); + if (!newtable) return false; - } /* Now that we have newtable allocated, update members. */ hashShift = JS_DHASH_BITS - newlog2; @@ -428,7 +426,7 @@ JSScope::changeTable(JSContext *cx, int change) } /* Finally, free the old table storage. */ - JS_free(cx, oldtable); + cx->free(oldtable); return true; } @@ -578,7 +576,7 @@ NewPropTreeKidsChunk(JSRuntime *rt) { PropTreeKidsChunk *chunk; - chunk = (PropTreeKidsChunk *) calloc(1, sizeof *chunk); + chunk = (PropTreeKidsChunk *) js_calloc(sizeof *chunk); if (!chunk) return NULL; JS_ASSERT(((jsuword)chunk & CHUNKY_KIDS_TAG) == 0); @@ -592,7 +590,7 @@ DestroyPropTreeKidsChunk(JSRuntime *rt, PropTreeKidsChunk *chunk) JS_RUNTIME_UNMETER(rt, propTreeKidsChunks); if (chunk->table) JS_DHashTableDestroy(chunk->table); - free(chunk); + js_free(chunk); } /* NB: Called with rt->gcLock held. */ @@ -1215,7 +1213,7 @@ JSScope::add(JSContext *cx, jsid id, splen = entryCount; JS_ASSERT(splen != 0); spvec = (JSScopeProperty **) - JS_malloc(cx, SCOPE_TABLE_NBYTES(splen)); + cx->malloc(SCOPE_TABLE_NBYTES(splen)); if (!spvec) goto fail_overwrite; i = splen; @@ -1248,7 +1246,7 @@ JSScope::add(JSContext *cx, jsid id, } else { sprop = GetPropertyTreeChild(cx, sprop, spvec[i]); if (!sprop) { - JS_free(cx, spvec); + cx->free(spvec); goto fail_overwrite; } @@ -1257,7 +1255,7 @@ JSScope::add(JSContext *cx, jsid id, SPROP_STORE_PRESERVING_COLLISION(spp2, sprop); } } while (++i < splen); - JS_free(cx, spvec); + cx->free(spvec); /* * Now sprop points to the last property in this scope, where @@ -1558,7 +1556,7 @@ JSScope::clear(JSContext *cx) LIVE_SCOPE_METER(cx, cx->runtime->liveScopeProps -= entryCount); if (table) - free(table); + js_free(table); clearMiddleDelete(); js_LeaveTraceIfGlobalObject(cx, object); initMinimal(cx); diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index 35d203d5e598..54e87a75697e 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -140,7 +140,7 @@ script_toSource(JSContext *cx, uintN argc, jsval *vp) } /* Allocate the source string and copy into it. */ - t = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar)); + t = (jschar *) cx->malloc((n + 1) * sizeof(jschar)); if (!t) return JS_FALSE; for (i = 0; i < j; i++) @@ -154,7 +154,7 @@ script_toSource(JSContext *cx, uintN argc, jsval *vp) /* Create and return a JS string for t. */ str = JS_NewUCString(cx, t, n); if (!str) { - JS_free(cx, t); + cx->free(t); return JS_FALSE; } *vp = STRING_TO_JSVAL(str); @@ -533,7 +533,7 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp, JSBool *hasMagic) ok = JS_XDRBytes(xdr, (char *) code, length * sizeof(jsbytecode)); if (code != script->code) - JS_free(cx, code); + cx->free(code); if (!ok) goto error; @@ -576,7 +576,7 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp, JSBool *hasMagic) filename = js_SaveScriptFilename(cx, filename); if (!filename) goto error; - JS_free(cx, (void *) script->filename); + cx->free((void *) script->filename); script->filename = filename; filenameWasSaved = JS_TRUE; } @@ -665,7 +665,7 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp, JSBool *hasMagic) if (xdr->mode == JSXDR_DECODE) { JS_POP_TEMP_ROOT(cx, &tvr); if (script->filename && !filenameWasSaved) { - JS_free(cx, (void *) script->filename); + cx->free((void *) script->filename); script->filename = NULL; } js_DestroyScript(cx, script); @@ -783,7 +783,7 @@ script_thaw(JSContext *cx, uintN argc, jsval *vp) /* Swap bytes in Unichars to keep frozen strings machine-independent. */ from = (jschar *)buf; - to = (jschar *) JS_malloc(cx, len * sizeof(jschar)); + to = (jschar *) cx->malloc(len * sizeof(jschar)); if (!to) { JS_XDRDestroy(xdr); return JS_FALSE; @@ -839,7 +839,7 @@ out: JS_XDRMemSetData(xdr, NULL, 0); JS_XDRDestroy(xdr); #if IS_BIG_ENDIAN - JS_free(cx, buf); + cx->free(buf); #endif *vp = JSVAL_TRUE; return ok; @@ -995,13 +995,13 @@ typedef struct ScriptFilenameEntry { static void * js_alloc_table_space(void *priv, size_t size) { - return malloc(size); + return js_malloc(size); } static void js_free_table_space(void *priv, void *item, size_t size) { - free(item); + js_free(item); } static JSHashEntry * @@ -1010,7 +1010,7 @@ js_alloc_sftbl_entry(void *priv, const void *key) size_t nbytes = offsetof(ScriptFilenameEntry, filename) + strlen((const char *) key) + 1; - return (JSHashEntry *) malloc(JS_MAX(nbytes, sizeof(JSHashEntry))); + return (JSHashEntry *) js_malloc(JS_MAX(nbytes, sizeof(JSHashEntry))); } static void @@ -1018,7 +1018,7 @@ js_free_sftbl_entry(void *priv, JSHashEntry *he, uintN flag) { if (flag != HT_FREE_ENTRY) return; - free(he); + js_free(he); } static JSHashAllocOps sftbl_alloc_ops = { @@ -1080,7 +1080,7 @@ js_FreeRuntimeScriptState(JSRuntime *rt) while (!JS_CLIST_IS_EMPTY(&rt->scriptFilenamePrefixes)) { sfp = (ScriptFilenamePrefix *) rt->scriptFilenamePrefixes.next; JS_REMOVE_LINK(&sfp->links); - free(sfp); + js_free(sfp); } js_FinishRuntimeScriptState(rt); } @@ -1143,7 +1143,7 @@ SaveScriptFilename(JSRuntime *rt, const char *filename, uint32 flags) if (!sfp) { /* No such prefix: add one now. */ - sfp = (ScriptFilenamePrefix *) malloc(sizeof(ScriptFilenamePrefix)); + sfp = (ScriptFilenamePrefix *) js_malloc(sizeof(ScriptFilenamePrefix)); if (!sfp) return NULL; JS_INSERT_AFTER(&sfp->links, link); @@ -1384,7 +1384,7 @@ js_NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 natoms, if (ntrynotes != 0) size += sizeof(JSTryNoteArray) + ntrynotes * sizeof(JSTryNote); - script = (JSScript *) JS_malloc(cx, size); + script = (JSScript *) cx->malloc(size); if (!script) return NULL; memset(script, 0, sizeof(JSScript)); @@ -1536,7 +1536,7 @@ js_NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg) memcpy(JS_SCRIPT_UPVARS(script)->vector, cg->upvarMap.vector, cg->upvarList.count * sizeof(uint32)); cg->upvarList.clear(); - JS_free(cx, cg->upvarMap.vector); + cx->free(cg->upvarMap.vector); cg->upvarMap.vector = NULL; } @@ -1648,7 +1648,7 @@ js_DestroyScript(JSContext *cx, JSScript *script) } } - JS_free(cx, script); + cx->free(script); } void diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index e9440dd82c22..c59efa86d02a 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -145,7 +145,7 @@ js_ConcatStrings(JSContext *cx, JSString *left, JSString *right) if (!left->isMutable()) { /* We must copy if left does not own a buffer to realloc. */ - s = (jschar *) JS_malloc(cx, (ln + rn + 1) * sizeof(jschar)); + s = (jschar *) cx->malloc((ln + rn + 1) * sizeof(jschar)); if (!s) return NULL; js_strncpy(s, ls, ln); @@ -153,7 +153,7 @@ js_ConcatStrings(JSContext *cx, JSString *left, JSString *right) } else { /* We can realloc left's space and make it depend on our result. */ JS_ASSERT(left->isFlat()); - s = (jschar *) JS_realloc(cx, ls, (ln + rn + 1) * sizeof(jschar)); + s = (jschar *) cx->realloc(ls, (ln + rn + 1) * sizeof(jschar)); if (!s) return NULL; @@ -173,9 +173,9 @@ js_ConcatStrings(JSContext *cx, JSString *left, JSString *right) if (!str) { /* Out of memory: clean up any space we (re-)allocated. */ if (!ldep) { - JS_free(cx, s); + cx->free(s); } else { - s = (jschar *) JS_realloc(cx, ls, (ln + 1) * sizeof(jschar)); + s = (jschar *) cx->realloc(ls, (ln + 1) * sizeof(jschar)); if (s) left->mChars = s; } @@ -210,7 +210,7 @@ js_UndependString(JSContext *cx, JSString *str) if (str->isDependent()) { n = str->dependentLength(); size = (n + 1) * sizeof(jschar); - s = (jschar *) JS_malloc(cx, size); + s = (jschar *) cx->malloc(size); if (!s) return NULL; @@ -402,7 +402,7 @@ js_str_escape(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval return JS_FALSE; } - newchars = (jschar *) JS_malloc(cx, (newlength + 1) * sizeof(jschar)); + newchars = (jschar *) cx->malloc((newlength + 1) * sizeof(jschar)); if (!newchars) return JS_FALSE; for (i = 0, ni = 0; i < length; i++) { @@ -430,7 +430,7 @@ js_str_escape(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval str = js_NewString(cx, newchars, newlength); if (!str) { - JS_free(cx, newchars); + cx->free(newchars); return JS_FALSE; } *rval = STRING_TO_JSVAL(str); @@ -464,7 +464,7 @@ str_unescape(JSContext *cx, uintN argc, jsval *vp) str->getCharsAndLength(chars, length); /* Don't bother allocating less space for the new string. */ - newchars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar)); + newchars = (jschar *) cx->malloc((length + 1) * sizeof(jschar)); if (!newchars) return JS_FALSE; ni = i = 0; @@ -493,7 +493,7 @@ str_unescape(JSContext *cx, uintN argc, jsval *vp) str = js_NewString(cx, newchars, ni); if (!str) { - JS_free(cx, newchars); + cx->free(newchars); return JS_FALSE; } *vp = STRING_TO_JSVAL(str); @@ -695,7 +695,7 @@ str_toSource(JSContext *cx, uintN argc, jsval *vp) j = JS_snprintf(buf, sizeof buf, "(new %s(", js_StringClass.name); str->getCharsAndLength(s, k); n = j + k + 2; - t = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar)); + t = (jschar *) cx->malloc((n + 1) * sizeof(jschar)); if (!t) return JS_FALSE; for (i = 0; i < j; i++) @@ -707,7 +707,7 @@ str_toSource(JSContext *cx, uintN argc, jsval *vp) t[i] = 0; str = js_NewString(cx, t, n); if (!str) { - JS_free(cx, t); + cx->free(t); return JS_FALSE; } *vp = STRING_TO_JSVAL(str); @@ -799,7 +799,7 @@ js_toLowerCase(JSContext *cx, JSString *str) jschar *news; str->getCharsAndLength(s, n); - news = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar)); + news = (jschar *) cx->malloc((n + 1) * sizeof(jschar)); if (!news) return NULL; for (i = 0; i < n; i++) @@ -807,7 +807,7 @@ js_toLowerCase(JSContext *cx, JSString *str) news[n] = 0; str = js_NewString(cx, news, n); if (!str) { - JS_free(cx, news); + cx->free(news); return NULL; } return str; @@ -850,7 +850,7 @@ js_toUpperCase(JSContext *cx, JSString *str) jschar *news; str->getCharsAndLength(s, n); - news = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar)); + news = (jschar *) cx->malloc((n + 1) * sizeof(jschar)); if (!news) return NULL; for (i = 0; i < n; i++) @@ -858,7 +858,7 @@ js_toUpperCase(JSContext *cx, JSString *str) news[n] = 0; str = js_NewString(cx, news, n); if (!str) { - JS_free(cx, news); + cx->free(news); return NULL; } return str; @@ -1659,7 +1659,7 @@ find_replen(JSContext *cx, ReplaceData *rdata, size_t *sizep) lambda_out: js_FreeStack(cx, mark); if (freeMoreParens) - JS_free(cx, cx->regExpStatics.moreParens); + cx->free(cx->regExpStatics.moreParens); cx->regExpStatics = save; return ok; } @@ -1716,7 +1716,7 @@ replace_destroy(JSContext *cx, GlobData *data) ReplaceData *rdata; rdata = (ReplaceData *)data; - JS_free(cx, rdata->chars); + cx->free(rdata->chars); rdata->chars = NULL; } @@ -1741,9 +1741,9 @@ replace_glob(JSContext *cx, jsint count, GlobData *data) growth = leftlen + replen; chars = (jschar *) (rdata->chars - ? JS_realloc(cx, rdata->chars, (rdata->length + growth + 1) + ? cx->realloc(rdata->chars, (rdata->length + growth + 1) * sizeof(jschar)) - : JS_malloc(cx, (growth + 1) * sizeof(jschar))); + : cx->malloc((growth + 1) * sizeof(jschar))); if (!chars) return JS_FALSE; rdata->chars = chars; @@ -1826,7 +1826,7 @@ js_StringReplaceHelper(JSContext *cx, uintN argc, JSObject *lambda, if (!ok) goto out; length += leftlen; - chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar)); + chars = (jschar *) cx->malloc((length + 1) * sizeof(jschar)); if (!chars) { ok = JS_FALSE; goto out; @@ -1840,9 +1840,9 @@ js_StringReplaceHelper(JSContext *cx, uintN argc, JSObject *lambda, rightlen = cx->regExpStatics.rightContext.length; length = rdata.length + rightlen; chars = (jschar *) - JS_realloc(cx, rdata.chars, (length + 1) * sizeof(jschar)); + cx->realloc(rdata.chars, (length + 1) * sizeof(jschar)); if (!chars) { - JS_free(cx, rdata.chars); + cx->free(rdata.chars); ok = JS_FALSE; goto out; } @@ -1852,7 +1852,7 @@ js_StringReplaceHelper(JSContext *cx, uintN argc, JSObject *lambda, str = js_NewString(cx, chars, length); if (!str) { - JS_free(cx, chars); + cx->free(chars); ok = JS_FALSE; goto out; } @@ -2266,7 +2266,7 @@ tagify(JSContext *cx, const char *begin, JSString *param, const char *end, return JS_FALSE; } - tagbuf = (jschar *) JS_malloc(cx, (taglen + 1) * sizeof(jschar)); + tagbuf = (jschar *) cx->malloc((taglen + 1) * sizeof(jschar)); if (!tagbuf) return JS_FALSE; @@ -2294,7 +2294,7 @@ tagify(JSContext *cx, const char *begin, JSString *param, const char *end, str = js_NewString(cx, tagbuf, taglen); if (!str) { - free((char *)tagbuf); + js_free((char *)tagbuf); return JS_FALSE; } *vp = STRING_TO_JSVAL(str); @@ -2531,13 +2531,13 @@ str_fromCharCode(JSContext *cx, uintN argc, jsval *vp) *vp = STRING_TO_JSVAL(str); return JS_TRUE; } - chars = (jschar *) JS_malloc(cx, (argc + 1) * sizeof(jschar)); + chars = (jschar *) cx->malloc((argc + 1) * sizeof(jschar)); if (!chars) return JS_FALSE; for (i = 0; i < argc; i++) { code = js_ValueToUint16(cx, &argv[i]); if (JSVAL_IS_NULL(argv[i])) { - JS_free(cx, chars); + cx->free(chars); return JS_FALSE; } chars[i] = (jschar)code; @@ -2545,7 +2545,7 @@ str_fromCharCode(JSContext *cx, uintN argc, jsval *vp) chars[i] = 0; str = js_NewString(cx, chars, argc); if (!str) { - JS_free(cx, chars); + cx->free(chars); return JS_FALSE; } *vp = STRING_TO_JSVAL(str); @@ -2621,9 +2621,8 @@ js_GetUnitStringForChar(JSContext *cx, jschar c) JS_ASSERT(c < UNIT_STRING_LIMIT); rt = cx->runtime; if (!rt->unitStrings) { - sp = (JSString **) calloc(UNIT_STRING_LIMIT * sizeof(JSString *) + - UNIT_STRING_LIMIT * 2 * sizeof(jschar), - 1); + sp = (JSString **) js_calloc(UNIT_STRING_LIMIT * sizeof(JSString *) + + UNIT_STRING_LIMIT * 2 * sizeof(jschar)); if (!sp) { JS_ReportOutOfMemory(cx); return NULL; @@ -2639,7 +2638,7 @@ js_GetUnitStringForChar(JSContext *cx, jschar c) JS_UNLOCK_GC(rt); } else { JS_UNLOCK_GC(rt); - free(sp); + js_free(sp); } } if (!rt->unitStrings[c]) { @@ -2676,7 +2675,7 @@ js_GetUnitString(JSContext *cx, JSString *str, size_t index) void js_FinishUnitStrings(JSRuntime *rt) { - free(rt->unitStrings); + js_free(rt->unitStrings); rt->unitStrings = NULL; } @@ -2832,14 +2831,14 @@ js_NewStringCopyN(JSContext *cx, const jschar *s, size_t n) jschar *news; JSString *str; - news = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar)); + news = (jschar *) cx->malloc((n + 1) * sizeof(jschar)); if (!news) return NULL; js_strncpy(news, s, n); news[n] = 0; str = js_NewString(cx, news, n); if (!str) - JS_free(cx, news); + cx->free(news); return str; } @@ -2852,13 +2851,13 @@ js_NewStringCopyZ(JSContext *cx, const jschar *s) n = js_strlen(s); m = (n + 1) * sizeof(jschar); - news = (jschar *) JS_malloc(cx, m); + news = (jschar *) cx->malloc(m); if (!news) return NULL; memcpy(news, s, m); str = js_NewString(cx, news, n); if (!str) - JS_free(cx, news); + cx->free(news); return str; } @@ -2876,7 +2875,7 @@ js_PurgeDeflatedStringCache(JSRuntime *rt, JSString *str) #ifdef DEBUG rt->deflatedStringCacheBytes -= str->length(); #endif - free(he->value); + js_free(he->value); JS_HashTableRawRemove(rt->deflatedStringCache, hep, he); } JS_RELEASE_LOCK(rt->deflatedStringCacheLock); @@ -3121,7 +3120,7 @@ js_InflateString(JSContext *cx, const char *bytes, size_t *lengthp) if (js_CStringsAreUTF8) { if (!js_InflateStringToBuffer(cx, bytes, nbytes, NULL, &nchars)) goto bad; - chars = (jschar *) JS_malloc(cx, (nchars + 1) * sizeof (jschar)); + chars = (jschar *) cx->malloc((nchars + 1) * sizeof (jschar)); if (!chars) goto bad; #ifdef DEBUG @@ -3131,7 +3130,7 @@ js_InflateString(JSContext *cx, const char *bytes, size_t *lengthp) JS_ASSERT(ok); } else { nchars = nbytes; - chars = (jschar *) JS_malloc(cx, (nchars + 1) * sizeof(jschar)); + chars = (jschar *) cx->malloc((nchars + 1) * sizeof(jschar)); if (!chars) goto bad; for (i = 0; i < nchars; i++) @@ -3166,7 +3165,7 @@ js_DeflateString(JSContext *cx, const jschar *chars, size_t nchars) nbytes = js_GetDeflatedStringLength(cx, chars, nchars); if (nbytes == (size_t) -1) return NULL; - bytes = (char *) (cx ? JS_malloc(cx, nbytes + 1) : malloc(nbytes + 1)); + bytes = (char *) (cx ? cx->malloc(nbytes + 1) : js_malloc(nbytes + 1)); if (!bytes) return NULL; #ifdef DEBUG @@ -3176,7 +3175,7 @@ js_DeflateString(JSContext *cx, const jschar *chars, size_t nchars) JS_ASSERT(ok); } else { nbytes = nchars; - bytes = (char *) (cx ? JS_malloc(cx, nbytes + 1) : malloc(nbytes + 1)); + bytes = (char *) (cx ? cx->malloc(nbytes + 1) : js_malloc(nbytes + 1)); if (!bytes) return NULL; for (i = 0; i < nbytes; i++) @@ -3491,9 +3490,9 @@ js_GetStringBytes(JSContext *cx, JSString *str) str->setDeflated(); } else { if (cx) - JS_free(cx, bytes); + cx->free(bytes); else - free(bytes); + js_free(bytes); bytes = NULL; } } @@ -4836,8 +4835,8 @@ AddCharsToURI(JSContext *cx, JSCharBuffer *buf, if (!buf->chars || JS_HOWMANY(total, URI_CHUNK) > JS_HOWMANY(buf->length + 1, URI_CHUNK)) { total = JS_ROUNDUP(total, URI_CHUNK); - newchars = (jschar *) JS_realloc(cx, buf->chars, - total * sizeof(jschar)); + newchars = (jschar *) cx->realloc(buf->chars, + total * sizeof(jschar)); if (!newchars) return JS_FALSE; buf->chars = newchars; @@ -4860,7 +4859,7 @@ TransferBufferToString(JSContext *cx, JSCharBuffer *cb, jsval *rval) * don't worry about that case here. */ n = cb->length; - chars = (jschar *) JS_realloc(cx, cb->chars, (n + 1) * sizeof(jschar)); + chars = (jschar *) cx->realloc(cb->chars, (n + 1) * sizeof(jschar)); if (!chars) chars = cb->chars; str = js_NewString(cx, chars, n); @@ -4953,7 +4952,7 @@ Encode(JSContext *cx, JSString *str, const jschar *unescapedSet, return JS_TRUE; bad: - JS_free(cx, cb.chars); + cx->free(cb.chars); return JS_FALSE; } @@ -5048,7 +5047,7 @@ Decode(JSContext *cx, JSString *str, const jschar *reservedSet, jsval *rval) /* FALL THROUGH */ bad: - JS_free(cx, cb.chars); + cx->free(cb.chars); return JS_FALSE; } diff --git a/js/src/jstask.cpp b/js/src/jstask.cpp new file mode 100644 index 000000000000..2814b953292d --- /dev/null +++ b/js/src/jstask.cpp @@ -0,0 +1,126 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=4 sw=4 et tw=99 ft=cpp: + * + * ***** 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 Mozilla SpiderMonkey JavaScript 1.9.1 code, released + * June 30, 2009. + * + * The Initial Developer of the Original Code is + * Andreas Gal + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 "jstask.h" + +#ifdef JS_THREADSAFE +static void start(void* arg) { + ((JSBackgroundThread*)arg)->work(); +} + +JSBackgroundThread::JSBackgroundThread() + : thread(NULL), stack(NULL), lock(NULL), wakeup(NULL), shutdown(false) +{ +} + +JSBackgroundThread::~JSBackgroundThread() +{ + if (wakeup) + PR_DestroyCondVar(wakeup); + if (lock) + PR_DestroyLock(lock); + /* PR_DestroyThread is not necessary. */ +} + +bool +JSBackgroundThread::init() +{ + if (!(lock = PR_NewLock())) + return false; + if (!(wakeup = PR_NewCondVar(lock))) + return false; + thread = PR_CreateThread(PR_USER_THREAD, start, this, PR_PRIORITY_LOW, + PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); + return !!thread; +} + +void +JSBackgroundThread::cancel() +{ + PR_Lock(lock); + if (shutdown) { + PR_Unlock(lock); + return; + } + shutdown = true; + PR_NotifyCondVar(wakeup); + PR_Unlock(lock); + PR_JoinThread(thread); +} + +void +JSBackgroundThread::work() +{ + PR_Lock(lock); + do { + PR_WaitCondVar(wakeup, PR_INTERVAL_NO_TIMEOUT); + JSBackgroundTask* t; + while ((t = stack) != NULL) { + stack = t->next; + PR_Unlock(lock); + t->run(); + delete t; + PR_Lock(lock); + } + } while (!shutdown); + PR_Unlock(lock); +} + +bool +JSBackgroundThread::busy() +{ + return !!stack; // we tolerate some racing here +} + +void +JSBackgroundThread::schedule(JSBackgroundTask* task) +{ + PR_Lock(lock); + if (shutdown) { + PR_Unlock(lock); + task->run(); + delete task; + return; + } + task->next = stack; + stack = task; + PR_NotifyCondVar(wakeup); + PR_Unlock(lock); +} + +#endif diff --git a/js/src/jstask.h b/js/src/jstask.h new file mode 100644 index 000000000000..30bc009a2c2a --- /dev/null +++ b/js/src/jstask.h @@ -0,0 +1,84 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=4 sw=4 et tw=99 ft=cpp: + * + * ***** 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 Mozilla SpiderMonkey JavaScript 1.9 code, released + * June 30, 2009. + * + * The Initial Developer of the Original Code is + * Andreas Gal + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 ***** */ + +#ifndef jstask_h___ +#define jstask_h___ + +class JSBackgroundTask { + friend class JSBackgroundThread; + JSBackgroundTask* next; + public: + virtual void run() = 0; +}; + +#ifdef JS_THREADSAFE + +#include "prthread.h" +#include "prlock.h" +#include "prcvar.h" + +class JSBackgroundThread { + PRThread* thread; + JSBackgroundTask* stack; + PRLock* lock; + PRCondVar* wakeup; + bool shutdown; + + public: + JSBackgroundThread(); + ~JSBackgroundThread(); + + bool init(); + void cancel(); + void work(); + bool busy(); + void schedule(JSBackgroundTask* task); +}; + +#else + +class JSBackgroundThread { + public: + void schedule(JSBackgroundTask* task) { + task->run(); + } +}; + +#endif + +#endif /* jstask_h___ */ diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index a2c45c0b627d..90c0fd2bd082 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -3616,11 +3616,11 @@ TraceRecorder::compile(JSTraceMonitor* tm) /* :TODO: windows support */ #if defined DEBUG && !defined WIN32 const char* filename = cx->fp->script->filename; - char* label = (char*)malloc((filename ? strlen(filename) : 7) + 16); + char* label = (char*)js_malloc((filename ? strlen(filename) : 7) + 16); sprintf(label, "%s:%u", filename ? filename : "", js_FramePCToLineNumber(cx, cx->fp)); fragmento->labels->add(fragment, sizeof(Fragment), 0, label); - free(label); + js_free(label); #endif AUDIT(traceCompleted); } @@ -12445,7 +12445,7 @@ js_StartTraceVis(JSContext *cx, JSObject *obj, if (!filename) goto error; ok = JS_StartTraceVis(filename); - JS_free(cx, filename); + cx->free(filename); } else { ok = JS_StartTraceVis(); } diff --git a/js/src/jsutil.cpp b/js/src/jsutil.cpp index e3a62878e3d8..43d4eb37ff44 100644 --- a/js/src/jsutil.cpp +++ b/js/src/jsutil.cpp @@ -297,7 +297,7 @@ CallTree(void **bp) return NULL; /* Create a new callsite record. */ - site = (JSCallsite *) malloc(sizeof(JSCallsite)); + site = (JSCallsite *) js_malloc(sizeof(JSCallsite)); if (!site) return NULL; diff --git a/js/src/jsutil.h b/js/src/jsutil.h index 18264ccca459..6e0895b2fb9d 100644 --- a/js/src/jsutil.h +++ b/js/src/jsutil.h @@ -44,6 +44,8 @@ #ifndef jsutil_h___ #define jsutil_h___ +#include + JS_BEGIN_EXTERN_C /* @@ -176,9 +178,30 @@ JS_Backtrace(int skip); extern JS_FRIEND_API(void) JS_DumpBacktrace(JSCallsite *trace); - #endif +static JS_INLINE void* js_malloc(size_t bytes) { + if (bytes < sizeof(void*)) /* for asyncFree */ + bytes = sizeof(void*); + return malloc(bytes); +} + +static JS_INLINE void* js_calloc(size_t bytes) { + if (bytes < sizeof(void*)) /* for asyncFree */ + bytes = sizeof(void*); + return calloc(bytes, 1); +} + +static JS_INLINE void* js_realloc(void* p, size_t bytes) { + if (bytes < sizeof(void*)) /* for asyncFree */ + bytes = sizeof(void*); + return realloc(p, bytes); +} + +static JS_INLINE void js_free(void* p) { + free(p); +} + JS_END_EXTERN_C #endif /* jsutil_h___ */ diff --git a/js/src/jsxdrapi.cpp b/js/src/jsxdrapi.cpp index b2d3efc1bf83..2eb9419d74e4 100644 --- a/js/src/jsxdrapi.cpp +++ b/js/src/jsxdrapi.cpp @@ -90,7 +90,7 @@ typedef struct JSXDRMemState { if (MEM_LIMIT(xdr) && \ MEM_COUNT(xdr) + bytes > MEM_LIMIT(xdr)) { \ uint32 limit_ = JS_ROUNDUP(MEM_COUNT(xdr) + bytes, MEM_BLOCK);\ - void *data_ = JS_realloc((xdr)->cx, MEM_BASE(xdr), limit_); \ + void *data_ = (xdr)->cx->realloc(MEM_BASE(xdr), limit_); \ if (!data_) \ return 0; \ MEM_BASE(xdr) = (char *) data_; \ @@ -216,7 +216,7 @@ mem_tell(JSXDRState *xdr) static void mem_finalize(JSXDRState *xdr) { - JS_free(xdr->cx, MEM_BASE(xdr)); + xdr->cx->free(MEM_BASE(xdr)); } static JSXDROps xdrmem_ops = { @@ -239,13 +239,13 @@ JS_XDRInitBase(JSXDRState *xdr, JSXDRMode mode, JSContext *cx) JS_PUBLIC_API(JSXDRState *) JS_XDRNewMem(JSContext *cx, JSXDRMode mode) { - JSXDRState *xdr = (JSXDRState *) JS_malloc(cx, sizeof(JSXDRMemState)); + JSXDRState *xdr = (JSXDRState *) cx->malloc(sizeof(JSXDRMemState)); if (!xdr) return NULL; JS_XDRInitBase(xdr, mode, cx); if (mode == JSXDR_ENCODE) { - if (!(MEM_BASE(xdr) = (char *) JS_malloc(cx, MEM_BLOCK))) { - JS_free(cx, xdr); + if (!(MEM_BASE(xdr) = (char *) cx->malloc(MEM_BLOCK))) { + cx->free(xdr); return NULL; } } else { @@ -299,11 +299,11 @@ JS_XDRDestroy(JSXDRState *xdr) JSContext *cx = xdr->cx; xdr->ops->finalize(xdr); if (xdr->registry) { - JS_free(cx, xdr->registry); + cx->free(xdr->registry); if (xdr->reghash) JS_DHashTableDestroy((JSDHashTable *) xdr->reghash); } - JS_free(cx, xdr); + cx->free(xdr); } JS_PUBLIC_API(JSBool) @@ -381,18 +381,18 @@ JS_XDRCString(JSXDRState *xdr, char **sp) len = strlen(*sp); JS_XDRUint32(xdr, &len); if (xdr->mode == JSXDR_DECODE) { - if (!(*sp = (char *) JS_malloc(xdr->cx, len + 1))) + if (!(*sp = (char *) xdr->cx->malloc(len + 1))) return JS_FALSE; } if (!JS_XDRBytes(xdr, *sp, len)) { if (xdr->mode == JSXDR_DECODE) - JS_free(xdr->cx, *sp); + xdr->cx->free(*sp); return JS_FALSE; } if (xdr->mode == JSXDR_DECODE) { (*sp)[len] = '\0'; } else if (xdr->mode == JSXDR_FREE) { - JS_free(xdr->cx, *sp); + xdr->cx->free(*sp); *sp = NULL; } return JS_TRUE; @@ -452,7 +452,7 @@ JS_XDRString(JSXDRState *xdr, JSString **strp) return JS_FALSE; if (xdr->mode == JSXDR_DECODE) { - chars = (jschar *) JS_malloc(xdr->cx, (nchars + 1) * sizeof(jschar)); + chars = (jschar *) xdr->cx->malloc((nchars + 1) * sizeof(jschar)); if (!chars) return JS_FALSE; } else { @@ -471,7 +471,7 @@ JS_XDRString(JSXDRState *xdr, JSString **strp) bad: if (xdr->mode == JSXDR_DECODE) - JS_free(xdr->cx, chars); + xdr->cx->free(chars); return JS_FALSE; } @@ -662,7 +662,7 @@ js_XDRStringAtom(JSXDRState *xdr, JSAtom **atomp) * This is very uncommon. Don't use the tempPool arena for this as * most allocations here will be bigger than tempPool's arenasize. */ - chars = (jschar *) JS_malloc(cx, nchars * sizeof(jschar)); + chars = (jschar *) cx->malloc(nchars * sizeof(jschar)); if (!chars) return JS_FALSE; } @@ -670,7 +670,7 @@ js_XDRStringAtom(JSXDRState *xdr, JSAtom **atomp) if (XDRChars(xdr, chars, nchars)) atom = js_AtomizeChars(cx, chars, nchars, 0); if (chars != stackChars) - JS_free(cx, chars); + cx->free(chars); if (!atom) return JS_FALSE; @@ -709,7 +709,7 @@ JS_XDRRegisterClass(JSXDRState *xdr, JSClass *clasp, uint32 *idp) if (numclasses == maxclasses) { maxclasses = (maxclasses == 0) ? CLASS_REGISTRY_MIN : maxclasses << 1; registry = (JSClass **) - JS_realloc(xdr->cx, xdr->registry, maxclasses * sizeof(JSClass *)); + xdr->cx->realloc(xdr->registry, maxclasses * sizeof(JSClass *)); if (!registry) return JS_FALSE; xdr->registry = registry; diff --git a/js/src/jsxml.cpp b/js/src/jsxml.cpp index 46cdb5e66b6a..1e8d73f9a892 100644 --- a/js/src/jsxml.cpp +++ b/js/src/jsxml.cpp @@ -460,7 +460,7 @@ qname_toString(JSContext *cx, uintN argc, jsval *vp) if (str && clasp == &js_AttributeNameClass) { length = str->length(); - chars = (jschar *) JS_malloc(cx, (length + 2) * sizeof(jschar)); + chars = (jschar *) cx->malloc((length + 2) * sizeof(jschar)); if (!chars) return JS_FALSE; *chars = '@'; @@ -468,7 +468,7 @@ qname_toString(JSContext *cx, uintN argc, jsval *vp) chars[++length] = 0; str = js_NewString(cx, chars, length); if (!str) { - JS_free(cx, chars); + cx->free(chars); return JS_FALSE; } } @@ -933,7 +933,7 @@ XMLArraySetCapacity(JSContext *cx, JSXMLArray *array, uint32 capacity) if (capacity == 0) { /* We could let realloc(p, 0) free this, but purify gets confused. */ if (array->vector) - free(array->vector); + cx->free(array->vector); vector = NULL; } else { if ( @@ -941,7 +941,7 @@ XMLArraySetCapacity(JSContext *cx, JSXMLArray *array, uint32 capacity) (size_t)capacity > ~(size_t)0 / sizeof(void *) || #endif !(vector = (void **) - realloc(array->vector, capacity * sizeof(void *)))) { + js_realloc(array->vector, capacity * sizeof(void *)))) { if (cx) JS_ReportOutOfMemory(cx); return JS_FALSE; @@ -975,7 +975,7 @@ XMLArrayFinish(JSContext *cx, JSXMLArray *array) { JSXMLArrayCursor *cursor; - JS_free(cx, array->vector); + cx->free(array->vector); while ((cursor = array->cursors) != NULL) XMLArrayCursorFinish(cursor); @@ -1039,7 +1039,7 @@ XMLArrayAddMember(JSContext *cx, JSXMLArray *array, uint32 index, void *elt) (size_t)capacity > ~(size_t)0 / sizeof(void *) || #endif !(vector = (void **) - realloc(array->vector, capacity * sizeof(void *)))) { + js_realloc(array->vector, capacity * sizeof(void *)))) { JS_ReportOutOfMemory(cx); return JS_FALSE; } @@ -1120,10 +1120,10 @@ XMLArrayTruncate(JSContext *cx, JSXMLArray *array, uint32 length) if (length == 0) { if (array->vector) - free(array->vector); + cx->free(array->vector); vector = NULL; } else { - vector = (void **) realloc(array->vector, length * sizeof(void *)); + vector = (void **) js_realloc(array->vector, length * sizeof(void *)); if (!vector) return; } @@ -1854,7 +1854,7 @@ ParseXMLSource(JSContext *cx, JSString *src) length = constrlen(prefix) + urilen + constrlen(middle) + srclen + constrlen(suffix); - chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar)); + chars = (jschar *) cx->malloc((length + 1) * sizeof(jschar)); if (!chars) return NULL; @@ -1905,7 +1905,7 @@ ParseXMLSource(JSContext *cx, JSString *src) } } - JS_free(cx, chars); + cx->free(chars); return xml; #undef constrlen @@ -2138,7 +2138,7 @@ MakeXMLSpecialString(JSContext *cx, JSStringBuffer *sb, prefixlength + length + ((length2 != 0) ? 1 + length2 : 0) + suffixlength; bp = base = (jschar *) - JS_realloc(cx, sb->base, (newlength + 1) * sizeof(jschar)); + cx->realloc(sb->base, (newlength + 1) * sizeof(jschar)); if (!bp) { js_FinishStringBuffer(sb); return NULL; @@ -2159,7 +2159,7 @@ MakeXMLSpecialString(JSContext *cx, JSStringBuffer *sb, str = js_NewString(cx, base, newlength); if (!str) - free(base); + cx->free(base); return str; } @@ -2210,7 +2210,7 @@ AppendAttributeValue(JSContext *cx, JSStringBuffer *sb, JSString *valstr) valstr = js_EscapeAttributeValue(cx, valstr, JS_TRUE); if (!valstr) { if (STRING_BUFFER_OK(sb)) { - free(sb->base); + cx->free(sb->base); sb->base = STRING_BUFFER_ERROR_BASE; } return; @@ -2482,7 +2482,7 @@ GeneratePrefix(JSContext *cx, JSString *uri, JSXMLArray *decls) if (STARTS_WITH_XML(cp, length) || !IsXMLName(cp, length)) { newlength = length + 2 + (size_t) log10((double) decls->length); bp = (jschar *) - JS_malloc(cx, (newlength + 1) * sizeof(jschar)); + cx->malloc((newlength + 1) * sizeof(jschar)); if (!bp) return NULL; @@ -2507,7 +2507,7 @@ GeneratePrefix(JSContext *cx, JSString *uri, JSXMLArray *decls) if (bp == cp) { newlength = length + 2 + (size_t) log10((double) n); bp = (jschar *) - JS_malloc(cx, (newlength + 1) * sizeof(jschar)); + cx->malloc((newlength + 1) * sizeof(jschar)); if (!bp) return NULL; js_strncpy(bp, cp, length); @@ -2534,7 +2534,7 @@ GeneratePrefix(JSContext *cx, JSString *uri, JSXMLArray *decls) } else { prefix = js_NewString(cx, bp, newlength); if (!prefix) - JS_free(cx, bp); + cx->free(bp); } return prefix; } @@ -5132,7 +5132,7 @@ xml_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, if (length == 0) { cursor = NULL; } else { - cursor = (JSXMLArrayCursor *) JS_malloc(cx, sizeof *cursor); + cursor = (JSXMLArrayCursor *) cx->malloc(sizeof *cursor); if (!cursor) return JS_FALSE; XMLArrayCursorInit(cursor, &xml->xml_kids); @@ -5155,7 +5155,7 @@ xml_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, cursor = (JSXMLArrayCursor *) JSVAL_TO_PRIVATE(*statep); if (cursor) { XMLArrayCursorFinish(cursor); - JS_free(cx, cursor); + cx->free(cursor); } *statep = JSVAL_NULL; break; @@ -5266,7 +5266,7 @@ js_EnumerateXMLValues(JSContext *cx, JSObject *obj, JSIterateOp enum_op, if (length == 0) { cursor = NULL; } else { - cursor = (JSXMLArrayCursor *) JS_malloc(cx, sizeof *cursor); + cursor = (JSXMLArrayCursor *) cx->malloc(sizeof *cursor); if (!cursor) return JS_FALSE; XMLArrayCursorInit(cursor, &xml->xml_kids); @@ -5301,7 +5301,7 @@ js_EnumerateXMLValues(JSContext *cx, JSObject *obj, JSIterateOp enum_op, if (cursor) { destroy: XMLArrayCursorFinish(cursor); - JS_free(cx, cursor); + cx->free(cursor); } *statep = JSVAL_NULL; break; @@ -7801,7 +7801,7 @@ js_AddAttributePart(JSContext *cx, JSBool isName, JSString *str, JSString *str2) str2->getCharsAndLength(chars2, len2); newlen = (isName) ? len + 1 + len2 : len + 2 + len2 + 1; - chars = (jschar *) JS_realloc(cx, chars, (newlen+1) * sizeof(jschar)); + chars = (jschar *) cx->realloc(chars, (newlen+1) * sizeof(jschar)); if (!chars) return NULL; @@ -8114,7 +8114,7 @@ xmlfilter_finalize(JSContext *cx, JSObject *obj) return; XMLArrayCursorFinish(&filter->cursor); - JS_free(cx, filter); + cx->free(filter); } JSClass js_XMLFilterClass = { @@ -8169,7 +8169,7 @@ js_StepXMLListFilter(JSContext *cx, JSBool initialized) if (!filterobj) return JS_FALSE; - filter = (JSXMLFilter *) JS_malloc(cx, sizeof *filter); + filter = (JSXMLFilter *) cx->malloc(sizeof *filter); if (!filter) return JS_FALSE; From 102d0ced5271f9d05e030a72be7ab48ce6491e12 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Tue, 28 Jul 2009 04:00:35 -0500 Subject: [PATCH 29/61] Bug 506786 - JSScope::trace method. r=brendan. --- js/src/jsapi.cpp | 4 ++-- js/src/jsdbgapi.cpp | 2 +- js/src/jsgc.cpp | 2 +- js/src/jsobj.cpp | 47 ++---------------------------------- js/src/jsscope.cpp | 2 +- js/src/jsscope.h | 58 ++++++++++++++++++++++++++++++++++++++------- 6 files changed, 57 insertions(+), 58 deletions(-) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 00e8a6ec37b3..dd3ab2e83557 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -4058,13 +4058,13 @@ prop_iter_trace(JSTracer *trc, JSObject *obj) /* Native case: just mark the next property to visit. */ sprop = (JSScopeProperty *) JSVAL_TO_PRIVATE(v); if (sprop) - TRACE_SCOPE_PROPERTY(trc, sprop); + sprop->trace(trc); } else { /* Non-native case: mark each id in the JSIdArray private. */ ida = (JSIdArray *) JSVAL_TO_PRIVATE(v); for (i = 0, n = ida->length; i < n; i++) { id = ida->vector[i]; - TRACE_ID(trc, id); + js_TraceId(trc, id); } } } diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index d9e9ed62a2fb..fd6af3ee7dc3 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -434,7 +434,7 @@ js_TraceWatchPoints(JSTracer *trc, JSObject *obj) &wp->links != &rt->watchPointList; wp = (JSWatchPoint *)wp->links.next) { if (wp->object == obj) { - TRACE_SCOPE_PROPERTY(trc, wp->sprop); + wp->sprop->trace(trc); if ((wp->sprop->attrs & JSPROP_SETTER) && wp->setter) { JS_CALL_OBJECT_TRACER(trc, js_CastAsObject(wp->setter), "wp->setter"); diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 386a65c83e83..d4a31a249df7 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -3043,7 +3043,7 @@ js_TraceContext(JSTracer *trc, JSContext *acx) tvr->u.trace(trc, tvr); break; case JSTVU_SPROP: - TRACE_SCOPE_PROPERTY(trc, tvr->u.sprop); + tvr->u.sprop->trace(trc); break; case JSTVU_WEAK_ROOTS: TraceWeakRoots(trc, tvr->u.weakRoots); diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index ed62904eecdc..bf5f72b4e808 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -5085,7 +5085,7 @@ js_TraceNativeEnumerators(JSTracer *trc) cursor = ne->ids; end = cursor + ne->length; do { - TRACE_ID(trc, *cursor); + js_TraceId(trc, *cursor); } while (++cursor != end); } else if (doGC) { js_RemoveAsGCBytes(rt, NativeEnumeratorSize(ne->length)); @@ -5748,7 +5748,6 @@ js_TraceObject(JSTracer *trc, JSObject *obj) { JSContext *cx; JSScope *scope; - JSScopeProperty *sprop; JSClass *clasp; size_t nslots, i; jsval v; @@ -5772,49 +5771,7 @@ js_TraceObject(JSTracer *trc, JSObject *obj) MeterEntryCount(scope->entryCount); #endif - sprop = scope->lastProp; - uint8 regenFlag = cx->runtime->gcRegenShapesScopeFlag; - if (IS_GC_MARKING_TRACER(trc) && - cx->runtime->gcRegenShapes && - scope->hasRegenFlag(regenFlag)) { - /* - * Either scope has its own shape, which must be regenerated, or it - * must have the same shape as its lastProp. - */ - uint32 shape; - - if (sprop) { - if (!(sprop->flags & SPROP_FLAG_SHAPE_REGEN)) { - sprop->shape = js_RegenerateShapeForGC(cx); - sprop->flags |= SPROP_FLAG_SHAPE_REGEN; - } - shape = sprop->shape; - } - if (!sprop || scope->hasOwnShape()) { - shape = js_RegenerateShapeForGC(cx); - JS_ASSERT_IF(sprop, shape != sprop->shape); - } - scope->shape = shape; - scope->flags ^= JSScope::SHAPE_REGEN; - - /* Also regenerate the shapes of empty scopes, in case they are not shared. */ - for (JSScope *empty = scope->emptyScope; - empty && empty->hasRegenFlag(regenFlag); - empty = empty->emptyScope) { - empty->shape = js_RegenerateShapeForGC(cx); - empty->flags ^= JSScope::SHAPE_REGEN; - } - } - if (sprop) { - JS_ASSERT(scope->has(sprop)); - - /* Trace scope's property tree ancestor line. */ - do { - if (scope->hadMiddleDelete() && !scope->has(sprop)) - continue; - TRACE_SCOPE_PROPERTY(trc, sprop); - } while ((sprop = sprop->parent) != NULL); - } + scope->trace(trc); if (!JS_CLIST_IS_EMPTY(&cx->runtime->watchPointList)) js_TraceWatchPoints(trc, obj); diff --git a/js/src/jsscope.cpp b/js/src/jsscope.cpp index 40c5add19fe3..02791e40cff0 100644 --- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -1649,7 +1649,7 @@ JSScopeProperty::trace(JSTracer *trc) { if (IS_GC_MARKING_TRACER(trc)) flags |= SPROP_MARK; - TRACE_ID(trc, id); + js_TraceId(trc, id); #if JS_HAS_GETTER_SETTER if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) { diff --git a/js/src/jsscope.h b/js/src/jsscope.h index fe8b5798e4f1..211b88c9014b 100644 --- a/js/src/jsscope.h +++ b/js/src/jsscope.h @@ -265,6 +265,8 @@ struct JSScope { void extend(JSContext *cx, JSScopeProperty *sprop); + void trace(JSTracer *trc); + void brandingShapeChange(JSContext *cx, uint32 slot, jsval v); void deletingShapeChange(JSContext *cx, JSScopeProperty *sprop); void methodShapeChange(JSContext *cx, uint32 slot, jsval toval); @@ -501,6 +503,54 @@ JSScope::extend(JSContext *cx, JSScopeProperty *sprop) lastProp = sprop; } +inline void +JSScope::trace(JSTracer *trc) +{ + JSContext *cx = trc->context; + JSScopeProperty *sprop = lastProp; + uint8 regenFlag = cx->runtime->gcRegenShapesScopeFlag; + if (IS_GC_MARKING_TRACER(trc) && cx->runtime->gcRegenShapes && hasRegenFlag(regenFlag)) { + /* + * Either this scope has its own shape, which must be regenerated, or + * it must have the same shape as lastProp. + */ + uint32 newShape; + + if (sprop) { + if (!(sprop->flags & SPROP_FLAG_SHAPE_REGEN)) { + sprop->shape = js_RegenerateShapeForGC(cx); + sprop->flags |= SPROP_FLAG_SHAPE_REGEN; + } + newShape = sprop->shape; + } + if (!sprop || hasOwnShape()) { + newShape = js_RegenerateShapeForGC(cx); + JS_ASSERT_IF(sprop, newShape != sprop->shape); + } + shape = newShape; + flags ^= JSScope::SHAPE_REGEN; + + /* Also regenerate the shapes of empty scopes, in case they are not shared. */ + for (JSScope *empty = emptyScope; + empty && empty->hasRegenFlag(regenFlag); + empty = empty->emptyScope) { + empty->shape = js_RegenerateShapeForGC(cx); + empty->flags ^= JSScope::SHAPE_REGEN; + } + } + if (sprop) { + JS_ASSERT(has(sprop)); + + /* Trace scope's property tree ancestor line. */ + do { + if (hadMiddleDelete() && !has(sprop)) + continue; + sprop->trace(trc); + } while ((sprop = sprop->parent) != NULL); + } +} + + static JS_INLINE bool js_GetSprop(JSContext* cx, JSScopeProperty* sprop, JSObject* obj, jsval* vp) { @@ -553,14 +603,6 @@ js_SetSprop(JSContext* cx, JSScopeProperty* sprop, JSObject* obj, jsval* vp) extern JSScope * js_GetMutableScope(JSContext *cx, JSObject *obj); -/* - * These macros used to inline short code sequences, but they grew over time. - * We retain them for internal backward compatibility, and in case one or both - * ever shrink to inline-able size. - */ -#define TRACE_ID(trc, id) js_TraceId(trc, id) -#define TRACE_SCOPE_PROPERTY(trc, sprop) sprop->trace(trc) - extern void js_TraceId(JSTracer *trc, jsid id); From aa70cca682c9dcefa88f7010d0757e9ed0656567 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Tue, 28 Jul 2009 04:39:40 -0500 Subject: [PATCH 30/61] Bug 506880 - Deadlock on exit in threadsafe shell. r=gal. --- js/src/jstask.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/src/jstask.cpp b/js/src/jstask.cpp index 2814b953292d..9071e632efdf 100644 --- a/js/src/jstask.cpp +++ b/js/src/jstask.cpp @@ -87,7 +87,7 @@ void JSBackgroundThread::work() { PR_Lock(lock); - do { + while (!shutdown) { PR_WaitCondVar(wakeup, PR_INTERVAL_NO_TIMEOUT); JSBackgroundTask* t; while ((t = stack) != NULL) { @@ -97,7 +97,7 @@ JSBackgroundThread::work() delete t; PR_Lock(lock); } - } while (!shutdown); + } PR_Unlock(lock); } From 3431af1c47e251d584e4b576ea919ba270b51d96 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Tue, 21 Jul 2009 12:13:21 -0500 Subject: [PATCH 31/61] Bug 505522 - Support building with C++ exceptions. r=bsmedberg. --- config/autoconf.mk.in | 1 + configure.in | 2 ++ js/src/config/autoconf.mk.in | 1 + js/src/configure.in | 2 ++ 4 files changed, 6 insertions(+) diff --git a/config/autoconf.mk.in b/config/autoconf.mk.in index f46c76edcc89..51f26fba0bf8 100644 --- a/config/autoconf.mk.in +++ b/config/autoconf.mk.in @@ -297,6 +297,7 @@ MOZ_OPTIMIZE_LDFLAGS = @MOZ_OPTIMIZE_LDFLAGS@ MOZ_OPTIMIZE_SIZE_TWEAK = @MOZ_OPTIMIZE_SIZE_TWEAK@ MOZ_RTTI_FLAGS_ON = @_MOZ_RTTI_FLAGS_ON@ +MOZ_EXCEPTIONS_FLAGS_ON = @_MOZ_EXCEPTIONS_FLAGS_ON@ MOZ_PROFILE_GUIDED_OPTIMIZE_DISABLE = @MOZ_PROFILE_GUIDED_OPTIMIZE_DISABLE@ PROFILE_GEN_CFLAGS = @PROFILE_GEN_CFLAGS@ diff --git a/configure.in b/configure.in index b903ce5a5490..f70021719e83 100644 --- a/configure.in +++ b/configure.in @@ -7330,6 +7330,8 @@ else _MOZ_EXCEPTIONS_FLAGS=$_MOZ_EXCEPTIONS_FLAGS_OFF fi +AC_SUBST(_MOZ_EXCEPTIONS_FLAGS_ON) + # Irix & OSF native compilers do not like exception declarations # when exceptions are disabled if test -n "$MIPSPRO_CXX" -o -n "$COMPAQ_CXX" -o -n "$VACPP"; then diff --git a/js/src/config/autoconf.mk.in b/js/src/config/autoconf.mk.in index 0ff86b970134..9f5f9cfed8e6 100644 --- a/js/src/config/autoconf.mk.in +++ b/js/src/config/autoconf.mk.in @@ -162,6 +162,7 @@ MOZ_OPTIMIZE_LDFLAGS = @MOZ_OPTIMIZE_LDFLAGS@ MOZ_OPTIMIZE_SIZE_TWEAK = @MOZ_OPTIMIZE_SIZE_TWEAK@ MOZ_RTTI_FLAGS_ON = @_MOZ_RTTI_FLAGS_ON@ +MOZ_EXCEPTIONS_FLAGS_ON = @_MOZ_EXCEPTIONS_FLAGS_ON@ MOZ_PROFILE_GUIDED_OPTIMIZE_DISABLE = @MOZ_PROFILE_GUIDED_OPTIMIZE_DISABLE@ PROFILE_GEN_CFLAGS = @PROFILE_GEN_CFLAGS@ diff --git a/js/src/configure.in b/js/src/configure.in index 4d28a3fbd7cd..3e3abb43b74d 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -4737,6 +4737,8 @@ else _MOZ_EXCEPTIONS_FLAGS=$_MOZ_EXCEPTIONS_FLAGS_OFF fi +AC_SUBST(_MOZ_EXCEPTIONS_FLAGS_ON) + # Irix & OSF native compilers do not like exception declarations # when exceptions are disabled if test -n "$MIPSPRO_CXX" -o -n "$COMPAQ_CXX" -o -n "$VACPP"; then From 69bd6c8514f5fe993bd0117bf3df78a90fc6557f Mon Sep 17 00:00:00 2001 From: Neil Deakin Date: Wed, 29 Jul 2009 14:33:53 -0400 Subject: [PATCH 32/61] Bug 478416, replace chromedir attribute with :moz-locale-dir pseudoclass, r=neil,dao,dbaron,sr=dbaron --- browser/base/content/browser-context.inc | 2 - browser/base/content/browser-doctype.inc | 2 - browser/base/content/browser-menubar.inc | 2 - browser/base/content/browser-places.js | 4 +- browser/base/content/browser.css | 2 +- browser/base/content/browser.js | 4 +- browser/base/content/browser.xul | 20 +- browser/base/content/pageinfo/pageInfo.xul | 5 +- browser/base/content/tabbrowser.xml | 23 +- browser/base/content/web-panels.xul | 2 - browser/components/places/content/places.xml | 5 - browser/components/places/content/places.xul | 8 +- browser/components/places/content/toolbar.xml | 3 - browser/components/search/content/search.xml | 8 +- .../themes/gnomestripe/browser/browser.css | 42 ++-- .../gnomestripe/browser/places/organizer.css | 8 +- .../themes/gnomestripe/browser/searchbar.css | 2 +- browser/themes/pinstripe/browser/browser.css | 92 ++++---- .../pinstripe/browser/places/organizer.css | 28 +-- .../themes/pinstripe/browser/searchbar.css | 24 +- .../themes/winstripe/browser/browser-aero.css | 10 +- browser/themes/winstripe/browser/browser.css | 124 +++++----- .../winstripe/browser/places/organizer.css | 18 +- .../themes/winstripe/browser/searchbar.css | 6 +- content/base/public/nsIDocument.h | 13 +- content/base/src/nsGkAtomList.h | 1 + content/xul/content/src/nsXULElement.cpp | 21 +- content/xul/document/public/nsIXULDocument.h | 5 + content/xul/document/src/Makefile.in | 3 + content/xul/document/src/nsXULDocument.cpp | 104 +++++++++ content/xul/document/src/nsXULDocument.h | 18 +- layout/style/nsCSSParser.cpp | 8 + layout/style/nsCSSPseudoClassList.h | 4 + layout/style/nsCSSPseudoClasses.cpp | 3 +- layout/style/nsCSSRuleProcessor.cpp | 29 +++ layout/style/test/test_selectors.html | 10 + modules/libpref/src/init/all.js | 5 + .../components/console/content/console.xul | 5 +- toolkit/components/help/content/help.xul | 10 +- .../help/content/helpContextOverlay.xul | 4 - .../printing/content/printPreviewBindings.xml | 10 +- toolkit/content/tests/chrome/Makefile.in | 4 + .../content/tests/chrome/rtltest/Makefile.in | 49 ++++ .../content/tests/chrome/rtltest/dirtest.xul | 25 ++ .../tests/chrome/rtltest/righttoleft.manifest | 3 + .../content/tests/chrome/test_righttoleft.xul | 217 ++++++++++++++++++ toolkit/content/textbox.css | 4 +- toolkit/content/widgets/datetimepicker.xml | 22 +- toolkit/content/widgets/findbar.xml | 5 - toolkit/content/widgets/menu.xml | 12 +- toolkit/content/widgets/resizer.xml | 15 -- toolkit/content/widgets/scrollbox.xml | 13 +- toolkit/content/widgets/tabbox.xml | 7 +- toolkit/content/widgets/textbox.xml | 14 +- toolkit/content/widgets/toolbarbutton.xml | 9 +- toolkit/content/widgets/tree.xml | 11 +- toolkit/content/widgets/wizard.xml | 14 +- toolkit/content/xul.css | 6 +- .../mozapps/extensions/content/extensions.xml | 2 - .../mozapps/extensions/content/extensions.xul | 4 +- toolkit/themes/faststripe/global/tabbox.css | 18 +- toolkit/themes/faststripe/global/textbox.css | 2 +- toolkit/themes/gnomestripe/global/button.css | 8 +- toolkit/themes/gnomestripe/global/findBar.css | 8 +- .../gnomestripe/global/printPreview.css | 8 +- toolkit/themes/gnomestripe/global/textbox.css | 2 +- toolkit/themes/gnomestripe/global/tree.css | 8 +- toolkit/themes/gnomestripe/help/help.css | 16 +- .../pinstripe/global/datetimepicker.css | 2 +- toolkit/themes/pinstripe/global/findBar.css | 8 +- toolkit/themes/pinstripe/global/resizer.css | 4 +- toolkit/themes/pinstripe/global/tree.css | 8 +- .../themes/pinstripe/global/viewbuttons.css | 16 +- .../winstripe/global/datetimepicker.css | 12 +- .../themes/winstripe/global/printPreview.css | 16 +- toolkit/themes/winstripe/global/resizer.css | 6 +- toolkit/themes/winstripe/global/scrollbox.css | 16 +- toolkit/themes/winstripe/global/tabbox.css | 18 +- toolkit/themes/winstripe/global/textbox.css | 2 +- toolkit/themes/winstripe/global/tree-aero.css | 8 +- toolkit/themes/winstripe/global/tree.css | 8 +- toolkit/themes/winstripe/help/help.css | 2 +- 82 files changed, 857 insertions(+), 472 deletions(-) create mode 100644 toolkit/content/tests/chrome/rtltest/Makefile.in create mode 100644 toolkit/content/tests/chrome/rtltest/dirtest.xul create mode 100644 toolkit/content/tests/chrome/rtltest/righttoleft.manifest create mode 100644 toolkit/content/tests/chrome/test_righttoleft.xul diff --git a/browser/base/content/browser-context.inc b/browser/base/content/browser-context.inc index ddd1f60ec434..93979c16369d 100644 --- a/browser/base/content/browser-context.inc +++ b/browser/base/content/browser-context.inc @@ -167,13 +167,11 @@ %browserDTD; - -%globalDTD; %globalRegionDTD; diff --git a/browser/base/content/browser-menubar.inc b/browser/base/content/browser-menubar.inc index e186a1af9555..485c041c639a 100644 --- a/browser/base/content/browser-menubar.inc +++ b/browser/base/content/browser-menubar.inc @@ -474,7 +474,6 @@ #else key="goBackKb" #endif - chromedir="&locale.dir;" command="Browser:BackOrBackDuplicate" onclick="checkForMiddleClick(this, event);"/> toolbaritem > hbox[type="places"] { display: none; } -#feed-menu[chromedir="rtl"] > menuitem { +#feed-menu:-moz-locale-dir(rtl) > menuitem { direction: rtl; } diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 2cae4f4b2d51..12f78515ddd6 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -6628,9 +6628,7 @@ var gIdentityHandler = { // Make sure the identity popup hangs toward the middle of the location bar // in RTL builds - var position = 'after_start'; - if (gURLBar.getAttribute("chromedir") == "rtl") - position = 'after_end'; + var position = (getComputedStyle(gNavToolbox, "").direction == "rtl") ? 'after_end' : 'after_start'; // Add the "open" attribute to the identity box for styling this._identityBox.setAttribute("open", "true"); diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul index de65307112f0..d8a9a5022e7f 100644 --- a/browser/base/content/browser.xul +++ b/browser/base/content/browser.xul @@ -104,17 +104,16 @@ - - + #ifdef XP_MACOSX + diff --git a/browser/components/places/content/toolbar.xml b/browser/components/places/content/toolbar.xml index 7638d6baa656..ec06ddb933aa 100644 --- a/browser/components/places/content/toolbar.xml +++ b/browser/components/places/content/toolbar.xml @@ -41,8 +41,6 @@ -%globalDTD; %browserDTD; ]> @@ -80,7 +78,6 @@ mousethrough="never" collapsed="true" tooltiptext="&bookmarksToolbarChevron.tooltip;" - chromedir="&locale.dir;" onpopupshowing="chevronPopupShowing(event);"> %searchBarDTD; - -%globalDTD; %browserDTD; ]> @@ -80,8 +78,7 @@ xbl:inherits="disabled,disableautocomplete,searchengine,src,newlines"> + anonid="searchbar-engine-button"> - + diff --git a/browser/themes/gnomestripe/browser/browser.css b/browser/themes/gnomestripe/browser/browser.css index d1196ad6f883..5669fb879a3a 100644 --- a/browser/themes/gnomestripe/browser/browser.css +++ b/browser/themes/gnomestripe/browser/browser.css @@ -401,13 +401,13 @@ menuitem:not([type]) { list-style-image: url("moz-icon://stock/gtk-go-back-ltr?size=menu&state=disabled"); } -#historyMenuBack[chromedir="rtl"], -#context-back[chromedir="rtl"] { +#historyMenuBack:-moz-locale-dir(rtl), +#context-back:-moz-locale-dir(rtl) { list-style-image: url("moz-icon://stock/gtk-go-back-rtl?size=menu"); } -#historyMenuBack[disabled][chromedir="rtl"], -#context-back[disabled][chromedir="rtl"] { +#historyMenuBack[disabled]:-moz-locale-dir(rtl), +#context-back[disabled]:-moz-locale-dir(rtl) { list-style-image: url("moz-icon://stock/gtk-go-back-rtl?size=menu&state=disabled"); } @@ -421,13 +421,13 @@ menuitem:not([type]) { list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=menu&state=disabled"); } -#historyMenuForward[chromedir="rtl"], -#context-forward[chromedir="rtl"] { +#historyMenuForward:-moz-locale-dir(rtl), +#context-forward:-moz-locale-dir(rtl) { list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=menu"); } -#historyMenuForward[disabled][chromedir="rtl"], -#context-forward[disabled][chromedir="rtl"] { +#historyMenuForward[disabled]:-moz-locale-dir(rtl), +#context-forward[disabled]:-moz-locale-dir(rtl) { list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=menu&state=disabled"); } @@ -522,10 +522,10 @@ toolbar[mode="full"] .toolbarbutton-menubutton-button { list-style-image: url("moz-icon://stock/gtk-go-back-ltr?size=toolbar&state=disabled"); } -#back-button[chromedir="rtl"] { +#back-button:-moz-locale-dir(rtl) { list-style-image: url("moz-icon://stock/gtk-go-back-rtl?size=toolbar"); } -#back-button[disabled="true"][chromedir="rtl"] { +#back-button[disabled="true"]:-moz-locale-dir(rtl) { list-style-image: url("moz-icon://stock/gtk-go-back-rtl?size=toolbar&state=disabled"); } @@ -536,10 +536,10 @@ toolbar[mode="full"] .toolbarbutton-menubutton-button { list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=toolbar&state=disabled"); } -#forward-button[chromedir="rtl"] { +#forward-button:-moz-locale-dir(rtl) { list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=toolbar"); } -#forward-button[disabled="true"][chromedir="rtl"] { +#forward-button[disabled="true"]:-moz-locale-dir(rtl) { list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=toolbar&state=disabled"); } @@ -648,13 +648,13 @@ toolbar[iconsize="small"] #back-button[disabled="true"] { list-style-image: url("moz-icon://stock/gtk-go-back-ltr?size=menu&state=disabled"); } -toolbar[iconsize="small"] #back-button[chromedir="rtl"] { +toolbar[iconsize="small"] #back-button:-moz-locale-dir(rtl) { list-style-image: url("moz-icon://stock/gtk-go-back-rtl?size=menu"); } -menupopup[chromedir="rtl"] > .unified-nav-back[_moz-menuactive] { +menupopup:-moz-locale-dir(rtl) > .unified-nav-back[_moz-menuactive] { list-style-image: url("moz-icon://stock/gtk-go-back-rtl?size=menu") !important; } -toolbar[iconsize="small"] #back-button[disabled="true"][chromedir="rtl"] { +toolbar[iconsize="small"] #back-button[disabled="true"]:-moz-locale-dir(rtl) { list-style-image: url("moz-icon://stock/gtk-go-back-rtl?size=menu&state=disabled"); } @@ -668,13 +668,13 @@ toolbar[iconsize="small"] #forward-button[disabled="true"] { list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=menu&state=disabled"); } -toolbar[iconsize="small"] #forward-button[chromedir="rtl"] { +toolbar[iconsize="small"] #forward-button:-moz-locale-dir(rtl) { list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=menu"); } -menupopup[chromedir="rtl"] > .unified-nav-forward[_moz-menuactive] { +menupopup:-moz-locale-dir(rtl) > .unified-nav-forward[_moz-menuactive] { list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=menu") !important; } -toolbar[iconsize="small"] #forward-button[disabled="true"][chromedir="rtl"] { +toolbar[iconsize="small"] #forward-button[disabled="true"]:-moz-locale-dir(rtl) { list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=menu&state=disabled"); } @@ -833,7 +833,7 @@ toolbar[iconsize="small"] #paste-button[disabled="true"] { direction: ltr !important; } -#PopupAutoComplete[chromedir="rtl"] > tree > treerows { +#PopupAutoComplete:-moz-locale-dir(rtl) > tree > treerows { direction: rtl; } @@ -875,7 +875,7 @@ toolbar[iconsize="small"] #paste-button[disabled="true"] { -moz-border-end: 1px solid ThreeDShadow; } -#identity-box[chromedir="rtl"] { +#identity-box:-moz-locale-dir(rtl) { -moz-border-start: 1px solid ThreeDShadow; } @@ -1338,7 +1338,7 @@ toolbarbutton.chevron { list-style-image: url("chrome://global/skin/toolbar/chevron.gif") !important; } -toolbarbutton.chevron[chromedir="rtl"] { +toolbarbutton.chevron:-moz-locale-dir(rtl) { list-style-image: url("chrome://global/skin/toolbar/chevron-rtl.gif") !important; } diff --git a/browser/themes/gnomestripe/browser/places/organizer.css b/browser/themes/gnomestripe/browser/places/organizer.css index ca7b67f3f219..f9a3afba1f79 100644 --- a/browser/themes/gnomestripe/browser/places/organizer.css +++ b/browser/themes/gnomestripe/browser/places/organizer.css @@ -13,10 +13,10 @@ list-style-image: url("moz-icon://stock/gtk-go-back-ltr?size=toolbar&state=disabled"); } -#back-button[chromedir="rtl"] { +#back-button:-moz-locale-dir(rtl) { list-style-image: url("moz-icon://stock/gtk-go-back-rtl?size=toolbar"); } -#back-button[disabled="true"][chromedir="rtl"] { +#back-button[disabled="true"]:-moz-locale-dir(rtl) { list-style-image: url("moz-icon://stock/gtk-go-back-rtl?size=toolbar&state=disabled"); } @@ -29,10 +29,10 @@ list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=toolbar&state=disabled"); } -#forward-button[chromedir="rtl"] { +#forward-button:-moz-locale-dir(rtl) { list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=toolbar"); } -#forward-button[disabled="true"][chromedir="rtl"] { +#forward-button[disabled="true"]:-moz-locale-dir(rtl) { list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=toolbar&state=disabled"); } diff --git a/browser/themes/gnomestripe/browser/searchbar.css b/browser/themes/gnomestripe/browser/searchbar.css index d034e68922ad..5c2d6cc1db7e 100644 --- a/browser/themes/gnomestripe/browser/searchbar.css +++ b/browser/themes/gnomestripe/browser/searchbar.css @@ -73,7 +73,7 @@ cursor: pointer; } -.search-go-button[chromedir="rtl"] { +.search-go-button:-moz-locale-dir(rtl) { -moz-transform: scaleX(-1); } diff --git a/browser/themes/pinstripe/browser/browser.css b/browser/themes/pinstripe/browser/browser.css index 7a9ce2268aae..eb205da1db4b 100644 --- a/browser/themes/pinstripe/browser/browser.css +++ b/browser/themes/pinstripe/browser/browser.css @@ -124,12 +124,12 @@ toolbarbutton.bookmark-item[type=menu] > .toolbarbutton-menu-dropmarker { -moz-padding-end: 7px; } -toolbarbutton.bookmark-item[type=menu][chromedir="rtl"] > .toolbarbutton-menu-dropmarker { +toolbarbutton.bookmark-item[type=menu]:-moz-locale-dir(rtl) > .toolbarbutton-menu-dropmarker { -moz-padding-start: 4px; -moz-padding-end: 2px; } -toolbarbutton.bookmark-item[chromedir="rtl"] { +toolbarbutton.bookmark-item:-moz-locale-dir(rtl) { -moz-padding-start: 0px; -moz-padding-end: 7px; } @@ -150,7 +150,7 @@ toolbarbutton.bookmark-item:not([container]) > .toolbarbutton-text { -moz-padding-end: 7px; } -toolbarbutton.bookmark-item[chromedir="rtl"] > .toolbarbutton-text { +toolbarbutton.bookmark-item:-moz-locale-dir(rtl) > .toolbarbutton-text { -moz-padding-end: 0; -moz-padding-start: 7px; } @@ -170,14 +170,14 @@ toolbarbutton.bookmark-item[container]:not([open]):hover > .toolbarbutton-menu-d } toolbarbutton.bookmark-item[container]:hover > .toolbarbutton-text, -toolbarbutton.bookmark-item[container][chromedir="rtl"]:not([open]):hover > .toolbarbutton-menu-dropmarker, +toolbarbutton.bookmark-item[container]:-moz-locale-dir(rtl):not([open]):hover > .toolbarbutton-menu-dropmarker, #home-button.bookmark-item:hover > .toolbarbutton-icon, -#home-button.bookmark-item[chromedir="rtl"]:hover > .toolbarbutton-text { +#home-button.bookmark-item:-moz-locale-dir(rtl):hover > .toolbarbutton-text { background: url("chrome://global/skin/toolbar/toolbarbutton-customhover-mid.png") repeat-x; } -#home-button.bookmark-item:hover[chromedir="rtl"] > .toolbarbutton-icon, -toolbarbutton.bookmark-item[chromedir="rtl"]:hover > .toolbarbutton-text { +#home-button.bookmark-item:hover:-moz-locale-dir(rtl) > .toolbarbutton-icon, +toolbarbutton.bookmark-item:-moz-locale-dir(rtl):hover > .toolbarbutton-text { background: url("chrome://global/skin/toolbar/toolbarbutton-customhover-right.png") no-repeat right top; } @@ -190,15 +190,15 @@ toolbarbutton.bookmark-item[container]:hover:active > .toolbarbutton-menu-dropma toolbarbutton.bookmark-item[container]:hover:active > .toolbarbutton-text, toolbarbutton.bookmark-item[container][open="true"] > .toolbarbutton-text, #home-button.bookmark-item:hover:active > .toolbarbutton-icon, -toolbarbutton.bookmark-item[container][chromedir="rtl"]:hover:active > .toolbarbutton-menu-dropmarker, -toolbarbutton.bookmark-item[container][chromedir="rtl"][open="true"] > .toolbarbutton-menu-dropmarker, -#home-button.bookmark-item:hover:active[chromedir="rtl"] > .toolbarbutton-text { +toolbarbutton.bookmark-item[container]:-moz-locale-dir(rtl):hover:active > .toolbarbutton-menu-dropmarker, +toolbarbutton.bookmark-item[container]:-moz-locale-dir(rtl)[open="true"] > .toolbarbutton-menu-dropmarker, +#home-button.bookmark-item:hover:active:-moz-locale-dir(rtl) > .toolbarbutton-text { background: url("chrome://browser/skin/bookmark-open-mid.png") repeat-x !important; } -toolbarbutton.bookmark-item[chromedir="rtl"][container]:hover:active > .toolbarbutton-text, -toolbarbutton.bookmark-item[chromedir="rtl"][container][open] > .toolbarbutton-text, -#home-button.bookmark-item[chromedir="rtl"]:hover:active > .toolbarbutton-icon { +toolbarbutton.bookmark-item:-moz-locale-dir(rtl)[container]:hover:active > .toolbarbutton-text, +toolbarbutton.bookmark-item:-moz-locale-dir(rtl)[container][open] > .toolbarbutton-text, +#home-button.bookmark-item:-moz-locale-dir(rtl):hover:active > .toolbarbutton-icon { background: url("chrome://browser/skin/bookmark-open-right.png") no-repeat right top !important; } @@ -290,8 +290,8 @@ toolbarbutton.bookmark-item-microsummarized { -moz-box-orient: vertical; } -.toolbarbutton-1[chromedir="rtl"], -#back-forward-dropmarker[chromedir="rtl"] { +.toolbarbutton-1:-moz-locale-dir(rtl), +#back-forward-dropmarker:-moz-locale-dir(rtl) { list-style-image: url("chrome://browser/skin/Toolbar-rtl.png"); } @@ -375,7 +375,7 @@ toolbar[mode="icons"] #unified-back-forward-button > #back-button { border-right: none; } -toolbar[mode="icons"] #unified-back-forward-button > #back-button[chromedir="rtl"] { +toolbar[mode="icons"] #unified-back-forward-button > #back-button:-moz-locale-dir(rtl) { -moz-image-region: rect(0px, 571px, 33px, 540px); } @@ -383,7 +383,7 @@ toolbar[mode="icons"] #unified-back-forward-button > #back-button[disabled="true -moz-image-region: rect(33px, 535px, 66px, 504px); } -toolbar[mode="icons"] #unified-back-forward-button > #back-button[disabled="true"][chromedir="rtl"] { +toolbar[mode="icons"] #unified-back-forward-button > #back-button[disabled="true"]:-moz-locale-dir(rtl) { -moz-image-region: rect(33px, 571px, 66px, 540px); } @@ -392,8 +392,8 @@ toolbar[mode="icons"] #unified-back-forward-button > #back-button[open="true"] { -moz-image-region: rect(66px, 535px, 99px, 504px); } -toolbar[mode="icons"] #unified-back-forward-button > #back-button:hover:active[chromedir="rtl"]:not([disabled]), -toolbar[mode="icons"] #unified-back-forward-button > #back-button[open="true"][chromedir="rtl"] { +toolbar[mode="icons"] #unified-back-forward-button > #back-button:hover:active:-moz-locale-dir(rtl):not([disabled]), +toolbar[mode="icons"] #unified-back-forward-button > #back-button[open="true"]:-moz-locale-dir(rtl) { -moz-image-region: rect(66px, 571px, 99px, 540px); } @@ -407,7 +407,7 @@ toolbar[mode="icons"] #unified-back-forward-button > #forward-button { border-right: none; } -toolbar[mode="icons"] #unified-back-forward-button > #forward-button[chromedir="rtl"] { +toolbar[mode="icons"] #unified-back-forward-button > #forward-button:-moz-locale-dir(rtl) { -moz-image-region: rect(0px, 540px, 33px, 514px); } @@ -415,7 +415,7 @@ toolbar[mode="icons"] #unified-back-forward-button > #forward-button[disabled="t -moz-image-region: rect(33px, 560px, 66px, 535px); } -toolbar[mode="icons"] #unified-back-forward-button > #forward-button[disabled="true"][chromedir="rtl"] { +toolbar[mode="icons"] #unified-back-forward-button > #forward-button[disabled="true"]:-moz-locale-dir(rtl) { -moz-image-region: rect(33px, 540px, 66px, 514px); } @@ -425,8 +425,8 @@ toolbar[mode="icons"] #unified-back-forward-button > #forward-button[open="true" -moz-margin-start: -5px; } -toolbar[mode="icons"] #unified-back-forward-button > #forward-button[chromedir="rtl"]:hover:active:not([disabled]), -toolbar[mode="icons"] #unified-back-forward-button > #forward-button[open="true"][chromedir="rtl"] { +toolbar[mode="icons"] #unified-back-forward-button > #forward-button:-moz-locale-dir(rtl):hover:active:not([disabled]), +toolbar[mode="icons"] #unified-back-forward-button > #forward-button[open="true"]:-moz-locale-dir(rtl) { -moz-image-region: rect(99px, 545px, 132px, 514px); } @@ -440,7 +440,7 @@ toolbar[mode="icons"] #unified-back-forward-button > #forward-button[open="true" border-right: none; } -#back-forward-dropmarker[chromedir="rtl"] { +#back-forward-dropmarker:-moz-locale-dir(rtl) { -moz-image-region: rect(0px, 514px, 33px, 504px); } @@ -458,7 +458,7 @@ toolbar[mode="icons"] #back-forward-dropmarker > dropmarker { -moz-image-region: rect(33px, 571px, 66px, 560px); } -#back-forward-dropmarker[disabled="true"][chromedir="rtl"] { +#back-forward-dropmarker[disabled="true"]:-moz-locale-dir(rtl) { -moz-image-region: rect(33px, 514px, 66px, 504px); } @@ -467,18 +467,18 @@ toolbar[mode="icons"] #back-forward-dropmarker > dropmarker { -moz-image-region: rect(66px, 571px, 99px, 560px); } -#back-forward-dropmarker[chromedir="rtl"]:hover:active:not([disabled]), -#back-forward-dropmarker[open="true"][chromedir="rtl"] { +#back-forward-dropmarker:-moz-locale-dir(rtl):hover:active:not([disabled]), +#back-forward-dropmarker[open="true"]:-moz-locale-dir(rtl) { -moz-image-region: rect(66px, 514px, 99px, 504px); } .unified-nav-back[_moz-menuactive], -menupopup[chromedir="rtl"] > .unified-nav-forward[_moz-menuactive] { +menupopup:-moz-locale-dir(rtl) > .unified-nav-forward[_moz-menuactive] { list-style-image: url("chrome://browser/skin/menu-back.png") !important; } .unified-nav-forward[_moz-menuactive], -menupopup[chromedir="rtl"] > .unified-nav-back[_moz-menuactive] { +menupopup:-moz-locale-dir(rtl) > .unified-nav-back[_moz-menuactive] { list-style-image: url("chrome://browser/skin/menu-forward.png") !important; } @@ -493,7 +493,7 @@ toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #back-but border-right: none; } -toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #back-button[chromedir="rtl"] { +toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #back-button:-moz-locale-dir(rtl) { -moz-image-region: rect(0px, 648px, 23px, 614px); } @@ -501,7 +501,7 @@ toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #back-but -moz-image-region: rect(23px, 605px, 46px, 571px); } -toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #back-button[disabled="true"][chromedir="rtl"] { +toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #back-button[disabled="true"]:-moz-locale-dir(rtl) { -moz-image-region: rect(23px, 648px, 46px, 614px); } @@ -510,8 +510,8 @@ toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #back-but -moz-image-region: rect(46px, 605px, 69px, 571px); } -toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #back-button[chromedir="rtl"]:hover:active:not([disabled]), -toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #back-button[open="true"][chromedir="rtl"] { +toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #back-button:-moz-locale-dir(rtl):hover:active:not([disabled]), +toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #back-button[open="true"]:-moz-locale-dir(rtl) { -moz-image-region: rect(46px, 648px, 69px, 614px); } @@ -525,7 +525,7 @@ toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #forward- border-right: none; } -toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #forward-button[chromedir="rtl"] { +toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #forward-button:-moz-locale-dir(rtl) { -moz-image-region: rect(0px, 614px, 23px, 580px); } @@ -533,7 +533,7 @@ toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #forward- -moz-image-region: rect(23px, 638px, 46px, 605px); } -toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #forward-button[disabled="true"][chromedir="rtl"] { +toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #forward-button[disabled="true"]:-moz-locale-dir(rtl) { -moz-image-region: rect(23px, 614px, 46px, 580px); } @@ -543,8 +543,8 @@ toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #forward- -moz-margin-start: 0; } -toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #forward-button[chromedir="rtl"]:hover:active:not([disabled]), -toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #forward-button[open="true"][chromedir="rtl"] { +toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #forward-button:-moz-locale-dir(rtl):hover:active:not([disabled]), +toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #forward-button[open="true"]:-moz-locale-dir(rtl) { -moz-image-region: rect(46px, 614px, 69px, 580px); } @@ -554,7 +554,7 @@ toolbar[iconsize="small"] #unified-back-forward-button > #back-forward-dropmarke -moz-image-region: rect(0px, 648px, 23px, 638px); } -toolbar[iconsize="small"] #unified-back-forward-button > #back-forward-dropmarker[chromedir="rtl"] { +toolbar[iconsize="small"] #unified-back-forward-button > #back-forward-dropmarker:-moz-locale-dir(rtl) { -moz-image-region: rect(0px, 580px, 23px, 571px); } @@ -562,7 +562,7 @@ toolbar[iconsize="small"] #unified-back-forward-button > #back-forward-dropmarke -moz-image-region: rect(23px, 648px, 46px, 638px); } -toolbar[iconsize="small"] #unified-back-forward-button > #back-forward-dropmarker[disabled="true"][chromedir="rtl"] { +toolbar[iconsize="small"] #unified-back-forward-button > #back-forward-dropmarker[disabled="true"]:-moz-locale-dir(rtl) { -moz-image-region: rect(23px, 580px, 46px, 571px); } @@ -571,8 +571,8 @@ toolbar[iconsize="small"] #unified-back-forward-button > #back-forward-dropmarke -moz-image-region: rect(46px, 648px, 69px, 638px); } -toolbar[iconsize="small"] #unified-back-forward-button > #back-forward-dropmarker[chromedir="rtl"]:hover:active:not([disabled]), -toolbar[iconsize="small"] #unified-back-forward-button > #back-forward-dropmarker[open="true"][chromedir="rtl"] { +toolbar[iconsize="small"] #unified-back-forward-button > #back-forward-dropmarker:-moz-locale-dir(rtl):hover:active:not([disabled]), +toolbar[iconsize="small"] #unified-back-forward-button > #back-forward-dropmarker[open="true"]:-moz-locale-dir(rtl) { -moz-image-region: rect(46px, 580px, 69px, 571px); } @@ -1461,7 +1461,7 @@ toolbarbutton.chevron { list-style-image: url("chrome://global/skin/icons/chevron.png") !important; } -toolbarbutton.chevron[chromedir="rtl"] { +toolbarbutton.chevron:-moz-locale-dir(rtl) { list-style-image: url("chrome://global/skin/icons/chevron-rtl.png") !important; } @@ -1663,15 +1663,15 @@ tabbrowser > tabbox > tabpanels { border: none; } -.tabbrowser-arrowscrollbox > .scrollbutton-up[chromedir="ltr"], -.tabbrowser-arrowscrollbox > .scrollbutton-down-stack > .scrollbutton-down[chromedir="rtl"] { +.tabbrowser-arrowscrollbox > .scrollbutton-up:-moz-locale-dir(ltr), +.tabbrowser-arrowscrollbox > .scrollbutton-down-stack > .scrollbutton-down:-moz-locale-dir(rtl) { border-right: 2px solid; -moz-border-right-colors: rgba(0,0,0,0.25) rgba(255,255,255,0.15); list-style-image: url("chrome://browser/skin/tabbrowser/tab-arrow-left.png"); } -.tabbrowser-arrowscrollbox > .scrollbutton-down-stack > .scrollbutton-down[chromedir="ltr"], -.tabbrowser-arrowscrollbox > .scrollbutton-up[chromedir="rtl"] { +.tabbrowser-arrowscrollbox > .scrollbutton-down-stack > .scrollbutton-down:-moz-locale-dir(ltr), +.tabbrowser-arrowscrollbox > .scrollbutton-up:-moz-locale-dir(rtl) { border-left: 2px solid; -moz-border-left-colors: rgba(0,0,0,0.25) rgba(255,255,255,0.15); list-style-image: url("chrome://browser/skin/tabbrowser/tab-arrow-right.png"); diff --git a/browser/themes/pinstripe/browser/places/organizer.css b/browser/themes/pinstripe/browser/places/organizer.css index a997a0e6a4ad..a5805a922109 100644 --- a/browser/themes/pinstripe/browser/places/organizer.css +++ b/browser/themes/pinstripe/browser/places/organizer.css @@ -96,7 +96,7 @@ border-right: none; } -#back-button[chromedir="rtl"] { +#back-button:-moz-locale-dir(rtl) { -moz-image-region: rect(0px, 67px, 23px, 34px); } @@ -104,7 +104,7 @@ -moz-image-region: rect(23px, 34px, 46px, 0px) !important; } -#back-button[disabled="true"][chromedir="rtl"] { +#back-button[disabled="true"]:-moz-locale-dir(rtl) { -moz-image-region: rect(23px, 67px, 46px, 34px) !important; } @@ -114,9 +114,9 @@ -moz-image-region: rect(46px, 34px, 69px, 0px); } -#back-button:hover:active[chromedir="rtl"], -#back-button[buttondown="true"][chromedir="rtl"], -#back-button[open="true"][chromedir="rtl"] { +#back-button:hover:active:-moz-locale-dir(rtl), +#back-button[buttondown="true"]:-moz-locale-dir(rtl), +#back-button[open="true"]:-moz-locale-dir(rtl) { -moz-image-region: rect(46px, 67px, 69px, 34px); } @@ -136,7 +136,7 @@ border-right: none; } -#forward-button[chromedir="rtl"] { +#forward-button:-moz-locale-dir(rtl) { -moz-image-region: rect(0px, 34px, 23px, 0px); } @@ -144,7 +144,7 @@ -moz-image-region: rect(23px, 67px, 46px, 34px) !important; } -#forward-button[disabled="true"][chromedir="rtl"] { +#forward-button[disabled="true"]:-moz-locale-dir(rtl) { -moz-image-region: rect(23px, 34px, 46px, 0px) !important; } @@ -154,9 +154,9 @@ -moz-image-region: rect(46px, 67px, 69px, 34px); } -#forward-button:hover:active[chromedir="rtl"], -#forward-button[buttondown="true"][chromedir="rtl"], -#forward-button[open="true"][chromedir="rtl"] { +#forward-button:hover:active:-moz-locale-dir(rtl), +#forward-button[buttondown="true"]:-moz-locale-dir(rtl), +#forward-button[open="true"]:-moz-locale-dir(rtl) { -moz-image-region: rect(46px, 34px, 69px, 0px); } @@ -169,10 +169,10 @@ background: url("chrome://browser/skin/places/menubutton-end-pressed.png") right center no-repeat; } -#placesToolbar[chromedir="rtl"] > toolbarbutton[type="menu"] { +#placesToolbar:-moz-locale-dir(rtl) > toolbarbutton[type="menu"] { background: url("chrome://browser/skin/places/menubutton-end-rtl.png") left center no-repeat; } -#placesToolbar[chromedir="rtl"] > toolbarbutton[type="menu"][open="true"] { +#placesToolbar:-moz-locale-dir(rtl) > toolbarbutton[type="menu"][open="true"] { background: url("chrome://browser/skin/places/menubutton-end-pressed-rtl.png") left center no-repeat; } @@ -192,10 +192,10 @@ background: url("chrome://browser/skin/places/menubutton-start-pressed.png") left center no-repeat; } -#placesToolbar[chromedir="rtl"] > toolbarbutton[type="menu"] > .toolbarbutton-icon { +#placesToolbar:-moz-locale-dir(rtl) > toolbarbutton[type="menu"] > .toolbarbutton-icon { background: url("chrome://browser/skin/places/menubutton-start-rtl.png") right center no-repeat; } -#placesToolbar[chromedir="rtl"] > toolbarbutton[type="menu"][open="true"] > .toolbarbutton-icon { +#placesToolbar:-moz-locale-dir(rtl) > toolbarbutton[type="menu"][open="true"] > .toolbarbutton-icon { background: url("chrome://browser/skin/places/menubutton-start-pressed-rtl.png") right center no-repeat; } diff --git a/browser/themes/pinstripe/browser/searchbar.css b/browser/themes/pinstripe/browser/searchbar.css index ef80b3b52770..59a7325afb57 100644 --- a/browser/themes/pinstripe/browser/searchbar.css +++ b/browser/themes/pinstripe/browser/searchbar.css @@ -45,7 +45,7 @@ padding: 0; } -.searchbar-engine-button[chromedir="rtl"] { +.searchbar-engine-button:-moz-locale-dir(rtl) { background-image: url("chrome://browser/skin/urlbar/startcap-rtl.png"); } @@ -53,7 +53,7 @@ background-image: url("chrome://browser/skin/urlbar/startcap-focused.png"); } -.searchbar-textbox[focused="true"] > .searchbar-engine-button[chromedir="rtl"] { +.searchbar-textbox[focused="true"] > .searchbar-engine-button:-moz-locale-dir(rtl) { background-image: url("chrome://browser/skin/urlbar/startcap-focused-rtl.png"); } @@ -61,7 +61,7 @@ background-image: url("chrome://browser/skin/urlbar/startcap-focused-graphite.png"); } -.searchbar-textbox[focused="true"] > .searchbar-engine-button[chromedir="rtl"]:-moz-system-metric(mac-graphite-theme) { +.searchbar-textbox[focused="true"] > .searchbar-engine-button:-moz-locale-dir(rtl):-moz-system-metric(mac-graphite-theme) { background-image: url("chrome://browser/skin/urlbar/startcap-focused-graphite-rtl.png"); } @@ -70,8 +70,8 @@ background-image: url("chrome://browser/skin/urlbar/startcap-active.png") !important; } -.searchbar-engine-button:hover:active[chromedir="rtl"], -.searchbar-engine-button[open="true"][chromedir="rtl"] { +.searchbar-engine-button:hover:active:-moz-locale-dir(rtl), +.searchbar-engine-button[open="true"]:-moz-locale-dir(rtl) { background-image: url("chrome://browser/skin/urlbar/startcap-active-rtl.png") !important; } @@ -80,8 +80,8 @@ background-image: url("chrome://browser/skin/urlbar/startcap-active-focused.png") !important; } -.searchbar-textbox[focused="true"] > .searchbar-engine-button[chromedir="rtl"]:active, -.searchbar-textbox[focused="true"] > .searchbar-engine-button[open="true"][chromedir="rtl"] { +.searchbar-textbox[focused="true"] > .searchbar-engine-button:-moz-locale-dir(rtl):active, +.searchbar-textbox[focused="true"] > .searchbar-engine-button[open="true"]:-moz-locale-dir(rtl) { background-image: url("chrome://browser/skin/urlbar/startcap-active-focused-rtl.png") !important; } @@ -90,8 +90,8 @@ background-image: url("chrome://browser/skin/urlbar/startcap-active-focused-graphite.png") !important; } -.searchbar-textbox[focused="true"] > .searchbar-engine-button[chromedir="rtl"]:active:-moz-system-metric(mac-graphite-theme), -.searchbar-textbox[focused="true"] > .searchbar-engine-button[open="true"][chromedir="rtl"]:-moz-system-metric(mac-graphite-theme) { +.searchbar-textbox[focused="true"] > .searchbar-engine-button:-moz-locale-dir(rtl):active:-moz-system-metric(mac-graphite-theme), +.searchbar-textbox[focused="true"] > .searchbar-engine-button[open="true"]:-moz-locale-dir(rtl):-moz-system-metric(mac-graphite-theme) { background-image: url("chrome://browser/skin/urlbar/startcap-active-focused-graphite-rtl.png") !important; } @@ -118,7 +118,7 @@ -moz-padding-end: 5px; } -.search-go-container[chromedir="rtl"] { +.search-go-container:-moz-locale-dir(rtl) { background-image: url("chrome://browser/skin/urlbar/endcap-rtl.png"); } @@ -126,7 +126,7 @@ background-image: url("chrome://browser/skin/urlbar/endcap-focused.png"); } -.searchbar-textbox[focused="true"] > .search-go-container[chromedir="rtl"] { +.searchbar-textbox[focused="true"] > .search-go-container:-moz-locale-dir(rtl) { background: url("chrome://browser/skin/urlbar/endcap-focused-rtl.png") no-repeat left top; } @@ -134,7 +134,7 @@ background-image: url("chrome://browser/skin/urlbar/endcap-focused-graphite.png"); } -.searchbar-textbox[focused="true"] > .search-go-container[chromedir="rtl"]:-moz-system-metric(mac-graphite-theme) { +.searchbar-textbox[focused="true"] > .search-go-container:-moz-locale-dir(rtl):-moz-system-metric(mac-graphite-theme) { background-image: url("chrome://browser/skin/urlbar/endcap-focused-graphite-rtl.png"); } diff --git a/browser/themes/winstripe/browser/browser-aero.css b/browser/themes/winstripe/browser/browser-aero.css index c56d77198b51..8b4176cbfef1 100644 --- a/browser/themes/winstripe/browser/browser-aero.css +++ b/browser/themes/winstripe/browser/browser-aero.css @@ -18,20 +18,20 @@ /* ::::: Identity Indicator Styling ::::: */ -#urlbar[chromedir="ltr"]:-moz-system-metric(windows-default-theme) { +#urlbar:-moz-locale-dir(ltr):-moz-system-metric(windows-default-theme) { -moz-margin-start: 9px; } -#identity-box[chromedir="ltr"]:-moz-system-metric(windows-default-theme) { +#identity-box:-moz-locale-dir(ltr):-moz-system-metric(windows-default-theme) { -moz-margin-start: -7px; } -#identity-box[chromedir="ltr"]:-moz-system-metric(windows-default-theme) { +#identity-box:-moz-locale-dir(ltr):-moz-system-metric(windows-default-theme) { -moz-border-radius: 11px 0 2px 11px / 15px 0 2px 15px; } -/* Match #identity-box[chromedir="ltr"]'s -moz-margin-start */ -#identity-popup[chromedir="ltr"]:-moz-system-metric(windows-default-theme) { +/* Match #identity-box:-moz-locale-dir(ltr)'s -moz-margin-start */ +#identity-popup:-moz-locale-dir(ltr):-moz-system-metric(windows-default-theme) { -moz-margin-start: 7px; } diff --git a/browser/themes/winstripe/browser/browser.css b/browser/themes/winstripe/browser/browser.css index aad9b4beab69..1b0af9a5a714 100644 --- a/browser/themes/winstripe/browser/browser.css +++ b/browser/themes/winstripe/browser/browser.css @@ -248,16 +248,16 @@ toolbar[iconsize="large"][mode="icons"] #back-button:not([disabled="true"]):hove /* unified back button with keyhole icons, RTL version */ -toolbar[iconsize="large"][mode="icons"] #back-button[chromedir="rtl"] { +toolbar[iconsize="large"][mode="icons"] #back-button:-moz-locale-dir(rtl) { -moz-image-region: rect(0px 516px 34px 480px); } -toolbar[iconsize="large"][mode="icons"] #back-button[chromedir="rtl"]:not([disabled="true"]):hover { +toolbar[iconsize="large"][mode="icons"] #back-button:-moz-locale-dir(rtl):not([disabled="true"]):hover { -moz-image-region: rect(34px 516px 68px 480px); } -toolbar[iconsize="large"][mode="icons"] #back-button[chromedir="rtl"][disabled="true"] { +toolbar[iconsize="large"][mode="icons"] #back-button:-moz-locale-dir(rtl)[disabled="true"] { -moz-image-region: rect(68px 516px 102px 480px); } -toolbar[iconsize="large"][mode="icons"] #back-button[chromedir="rtl"]:not([disabled="true"]):hover:active { +toolbar[iconsize="large"][mode="icons"] #back-button:-moz-locale-dir(rtl):not([disabled="true"]):hover:active { -moz-image-region: rect(102px 516px 136px 480px); } @@ -284,16 +284,16 @@ toolbar[iconsize="large"][mode="icons"] #forward-button:not([disabled="true"]):h /* unified forward button with keyhole icons, RTL version */ -toolbar[iconsize="large"][mode="icons"] #forward-button[chromedir="rtl"] { +toolbar[iconsize="large"][mode="icons"] #forward-button:-moz-locale-dir(rtl) { -moz-image-region: rect(3px 480px 31px 454px); } -toolbar[iconsize="large"][mode="icons"] #forward-button[chromedir="rtl"]:not([disabled="true"]):hover { +toolbar[iconsize="large"][mode="icons"] #forward-button:-moz-locale-dir(rtl):not([disabled="true"]):hover { -moz-image-region: rect(37px 480px 65px 454px); } -toolbar[iconsize="large"][mode="icons"] #forward-button[chromedir="rtl"][disabled="true"] { +toolbar[iconsize="large"][mode="icons"] #forward-button:-moz-locale-dir(rtl)[disabled="true"] { -moz-image-region: rect(71px 480px 99px 454px); } -toolbar[iconsize="large"][mode="icons"] #forward-button[chromedir="rtl"]:not([disabled="true"]):hover:active { +toolbar[iconsize="large"][mode="icons"] #forward-button:-moz-locale-dir(rtl):not([disabled="true"]):hover:active { -moz-image-region: rect(105px 480px 133px 454px); } @@ -331,16 +331,16 @@ toolbar[iconsize="large"][mode="icons"] #back-forward-dropmarker:not([disabled=" /* unified dropmarker with keyhole icons, RTL version */ -toolbar[iconsize="large"][mode="icons"] #back-forward-dropmarker[chromedir="rtl"] { +toolbar[iconsize="large"][mode="icons"] #back-forward-dropmarker:-moz-locale-dir(rtl) { -moz-image-region: rect(3px 454px 31px 438px); } -toolbar[iconsize="large"][mode="icons"] #back-forward-dropmarker[chromedir="rtl"]:not([disabled="true"]):hover { +toolbar[iconsize="large"][mode="icons"] #back-forward-dropmarker:-moz-locale-dir(rtl):not([disabled="true"]):hover { -moz-image-region: rect(37px 454px 65px 438px); } -toolbar[iconsize="large"][mode="icons"] #back-forward-dropmarker[chromedir="rtl"][disabled="true"] { +toolbar[iconsize="large"][mode="icons"] #back-forward-dropmarker:-moz-locale-dir(rtl)[disabled="true"] { -moz-image-region: rect(71px 454px 99px 438px); } -toolbar[iconsize="large"][mode="icons"] #back-forward-dropmarker[chromedir="rtl"]:not([disabled="true"]):hover:active { +toolbar[iconsize="large"][mode="icons"] #back-forward-dropmarker:-moz-locale-dir(rtl):not([disabled="true"]):hover:active { -moz-image-region: rect(105px 454px 133px 438px); } @@ -368,16 +368,16 @@ toolbar[iconsize="small"][mode="icons"] #back-button:not([disabled="true"]):hove /* unified back button with keyhole icons, small icons mode, RTL version */ -toolbar[iconsize="small"][mode="icons"] #back-button[chromedir="rtl"] { +toolbar[iconsize="small"][mode="icons"] #back-button:-moz-locale-dir(rtl) { -moz-image-region: rect(0px 362px 24px 338px); } -toolbar[iconsize="small"][mode="icons"] #back-button[chromedir="rtl"]:not([disabled="true"]):hover { +toolbar[iconsize="small"][mode="icons"] #back-button:-moz-locale-dir(rtl):not([disabled="true"]):hover { -moz-image-region: rect(24px 362px 48px 338px); } -toolbar[iconsize="small"][mode="icons"] #back-button[chromedir="rtl"][disabled="true"] { +toolbar[iconsize="small"][mode="icons"] #back-button:-moz-locale-dir(rtl)[disabled="true"] { -moz-image-region: rect(48px 362px 72px 338px); } -toolbar[iconsize="small"][mode="icons"] #back-button[chromedir="rtl"]:not([disabled="true"]):hover:active { +toolbar[iconsize="small"][mode="icons"] #back-button:-moz-locale-dir(rtl):not([disabled="true"]):hover:active { -moz-image-region: rect(72px 362px 96px 338px); } @@ -398,16 +398,16 @@ toolbar[iconsize="small"][mode="icons"] #forward-button:not([disabled="true"]):h /* unified forward button with keyhole icons, small icons mode, RTL version */ -toolbar[iconsize="small"][mode="icons"] #forward-button[chromedir="rtl"] { +toolbar[iconsize="small"][mode="icons"] #forward-button:-moz-locale-dir(rtl) { -moz-image-region: rect(0px 338px 24px 314px); } -toolbar[iconsize="small"][mode="icons"] #forward-button[chromedir="rtl"]:not([disabled="true"]):hover { +toolbar[iconsize="small"][mode="icons"] #forward-button:-moz-locale-dir(rtl):not([disabled="true"]):hover { -moz-image-region: rect(24px 338px 48px 314px); } -toolbar[iconsize="small"][mode="icons"] #forward-button[chromedir="rtl"][disabled="true"] { +toolbar[iconsize="small"][mode="icons"] #forward-button:-moz-locale-dir(rtl)[disabled="true"] { -moz-image-region: rect(48px 338px 72px 314px); } -toolbar[iconsize="small"][mode="icons"] #forward-button[chromedir="rtl"]:not([disabled="true"]):hover:active { +toolbar[iconsize="small"][mode="icons"] #forward-button:-moz-locale-dir(rtl):not([disabled="true"]):hover:active { -moz-image-region: rect(72px 338px 96px 314px); } @@ -429,16 +429,16 @@ toolbar[iconsize="small"][mode="icons"] #back-forward-dropmarker:not([disabled=" /* unified dropmarker with keyhole icons, small icons mode, RTL version */ -toolbar[iconsize="small"][mode="icons"] #back-forward-dropmarker[chromedir="rtl"] { +toolbar[iconsize="small"][mode="icons"] #back-forward-dropmarker:-moz-locale-dir(rtl) { -moz-image-region: rect(0px 314px 24px 301px); } -toolbar[iconsize="small"][mode="icons"] #back-forward-dropmarker[chromedir="rtl"]:not([disabled="true"]):hover { +toolbar[iconsize="small"][mode="icons"] #back-forward-dropmarker:-moz-locale-dir(rtl):not([disabled="true"]):hover { -moz-image-region: rect(24px 314px 48px 301px); } -toolbar[iconsize="small"][mode="icons"] #back-forward-dropmarker[chromedir="rtl"][disabled="true"] { +toolbar[iconsize="small"][mode="icons"] #back-forward-dropmarker:-moz-locale-dir(rtl)[disabled="true"] { -moz-image-region: rect(48px 314px 72px 301px); } -toolbar[iconsize="small"][mode="icons"] #back-forward-dropmarker[chromedir="rtl"]:not([disabled="true"]):hover:active { +toolbar[iconsize="small"][mode="icons"] #back-forward-dropmarker:-moz-locale-dir(rtl):not([disabled="true"]):hover:active { -moz-image-region: rect(72px 314px 96px 301px); } @@ -460,17 +460,17 @@ toolbar[iconsize="small"][mode="icons"] #back-forward-dropmarker[chromedir="rtl" -moz-image-region: rect(96px 24px 120px 0px); } -#back-button[chromedir="rtl"] { +#back-button:-moz-locale-dir(rtl) { -moz-image-region: rect(0px 48px 24px 24px); } -#back-button[chromedir="rtl"]:not([disabled="true"]):hover, -#back-button[chromedir="rtl"][buttonover="true"] { +#back-button:-moz-locale-dir(rtl):not([disabled="true"]):hover, +#back-button:-moz-locale-dir(rtl)[buttonover="true"] { -moz-image-region: rect(24px 48px 48px 24px); } -#back-button[chromedir="rtl"][disabled="true"] { +#back-button:-moz-locale-dir(rtl)[disabled="true"] { -moz-image-region: rect(48px 48px 72px 24px); } -#back-button[chromedir="rtl"]:not([disabled="true"]):hover:active { +#back-button:-moz-locale-dir(rtl):not([disabled="true"]):hover:active { -moz-image-region: rect(96px 48px 120px 24px); } @@ -490,17 +490,17 @@ toolbar[iconsize="small"][mode="icons"] #back-forward-dropmarker[chromedir="rtl" -moz-image-region: rect(96px 48px 120px 24px); } -#forward-button[chromedir="rtl"] { +#forward-button:-moz-locale-dir(rtl) { -moz-image-region: rect(0px 24px 24px 0px); } -#forward-button[chromedir="rtl"]:not([disabled="true"]):hover, -#forward-button[chromedir="rtl"][buttonover="true"] { +#forward-button:-moz-locale-dir(rtl):not([disabled="true"]):hover, +#forward-button:-moz-locale-dir(rtl)[buttonover="true"] { -moz-image-region: rect(24px 24px 48px 0px); } -#forward-button[chromedir="rtl"][disabled="true"] { +#forward-button:-moz-locale-dir(rtl)[disabled="true"] { -moz-image-region: rect(48px 24px 72px 0px); } -#forward-button[chromedir="rtl"]:not([disabled="true"]):hover:active { +#forward-button:-moz-locale-dir(rtl):not([disabled="true"]):hover:active { -moz-image-region: rect(96px 24px 120px 0px); } @@ -727,21 +727,21 @@ toolbar[iconsize="small"] #back-button:not([disabled="true"]):hover:active { -moz-image-region: rect(64px 16px 80px 0px); } -toolbar[iconsize="small"] #back-button[chromedir="rtl"] { +toolbar[iconsize="small"] #back-button:-moz-locale-dir(rtl) { -moz-image-region: rect(0px 32px 16px 16px); } -toolbar[iconsize="small"] #back-button[chromedir="rtl"]:not([disabled="true"]):hover, -toolbar[iconsize="small"] #back-button[chromedir="rtl"][buttonover="true"] { +toolbar[iconsize="small"] #back-button:-moz-locale-dir(rtl):not([disabled="true"]):hover, +toolbar[iconsize="small"] #back-button:-moz-locale-dir(rtl)[buttonover="true"] { -moz-image-region: rect(16px 32px 32px 16px); } -toolbar[iconsize="small"] #back-button[chromedir="rtl"][disabled="true"] { +toolbar[iconsize="small"] #back-button:-moz-locale-dir(rtl)[disabled="true"] { -moz-image-region: rect(32px 32px 48px 16px); } -toolbar[iconsize="small"] #back-button[chromedir="rtl"]:not([disabled="true"]):hover:active { +toolbar[iconsize="small"] #back-button:-moz-locale-dir(rtl):not([disabled="true"]):hover:active { -moz-image-region: rect(64px 32px 80px 16px); } .unified-nav-back[_moz-menuactive], -menupopup[chromedir="rtl"] > .unified-nav-forward[_moz-menuactive] { +menupopup:-moz-locale-dir(rtl) > .unified-nav-forward[_moz-menuactive] { list-style-image: url("chrome://browser/skin/menu-back.png") !important; } @@ -764,21 +764,21 @@ toolbar[iconsize="small"] #forward-button:not([disabled="true"]):hover:active { -moz-image-region: rect(64px 32px 80px 16px); } -toolbar[iconsize="small"] #forward-button[chromedir="rtl"] { +toolbar[iconsize="small"] #forward-button:-moz-locale-dir(rtl) { -moz-image-region: rect(0px 16px 16px 0px); } -toolbar[iconsize="small"] #forward-button[chromedir="rtl"]:not([disabled="true"]):hover, -toolbar[iconsize="small"] #forward-button[chromedir="rtl"][buttonover="true"] { +toolbar[iconsize="small"] #forward-button:-moz-locale-dir(rtl):not([disabled="true"]):hover, +toolbar[iconsize="small"] #forward-button:-moz-locale-dir(rtl)[buttonover="true"] { -moz-image-region: rect(16px 16px 32px 0px); } -toolbar[iconsize="small"] #forward-button[chromedir="rtl"][disabled="true"] { +toolbar[iconsize="small"] #forward-button:-moz-locale-dir(rtl)[disabled="true"] { -moz-image-region: rect(32px 16px 48px 0px); } -toolbar[iconsize="small"] #forward-button[chromedir="rtl"]:not([disabled="true"]):hover:active { +toolbar[iconsize="small"] #forward-button:-moz-locale-dir(rtl):not([disabled="true"]):hover:active { -moz-image-region: rect(64px 16px 80px 0px); } .unified-nav-forward[_moz-menuactive], -menupopup[chromedir="rtl"] > .unified-nav-back[_moz-menuactive] { +menupopup:-moz-locale-dir(rtl) > .unified-nav-back[_moz-menuactive] { list-style-image: url("chrome://browser/skin/menu-forward.png") !important; } @@ -1101,7 +1101,7 @@ toolbar[iconsize="small"] #paste-button:not([disabled="true"]):hover:active { direction: ltr !important; } -#PopupAutoComplete[chromedir="rtl"] > tree > treerows { +#PopupAutoComplete:-moz-locale-dir(rtl) > tree > treerows { direction: rtl; } @@ -1508,7 +1508,7 @@ tabpanels { -moz-border-radius-topright: 2px; } -.tabbrowser-arrowscrollbox > .scrollbutton-up[chromedir="rtl"] { +.tabbrowser-arrowscrollbox > .scrollbutton-up:-moz-locale-dir(rtl) { border-left-style: solid; border-right-style: none; -moz-border-radius-topleft: 2px; @@ -1527,16 +1527,16 @@ tabpanels { list-style-image: url("chrome://browser/skin/tabbrowser/tab-arrow-right.png"); } -.tabbrowser-arrowscrollbox > .scrollbutton-down[chromedir="rtl"], -.tabs-container > .tabs-newtab-button[chromedir="rtl"], -.tabs-container > stack[chromedir="rtl"] > .tabs-alltabs-button { +.tabbrowser-arrowscrollbox > .scrollbutton-down:-moz-locale-dir(rtl), +.tabs-container > .tabs-newtab-button:-moz-locale-dir(rtl), +.tabs-container > stack:-moz-locale-dir(rtl) > .tabs-alltabs-button { border-left-style: none; border-right-style: solid; -moz-border-radius-topleft: 0px; -moz-border-radius-topright: 2px; } -.tabbrowser-arrowscrollbox > .scrollbutton-down[chromedir="rtl"] { +.tabbrowser-arrowscrollbox > .scrollbutton-down:-moz-locale-dir(rtl) { list-style-image: url("chrome://browser/skin/tabbrowser/tab-arrow-left.png"); } @@ -1592,7 +1592,7 @@ tabpanels { opacity: 0.0; } -stack[chromedir="rtl"] > hbox > .tabs-alltabs-box-animate { +stack:-moz-locale-dir(rtl) > hbox > .tabs-alltabs-box-animate { background-image: url("chrome://browser/skin/tabbrowser/alltabs-box-overflow-start-bkgnd-animate.png"); } @@ -1643,7 +1643,7 @@ stack[chromedir="rtl"] > hbox > .tabs-alltabs-box-animate { -moz-border-radius-topleft: 2px; } -.tabs-container > .tabs-closebutton[chromedir="rtl"] { +.tabs-container > .tabs-closebutton:-moz-locale-dir(rtl) { border-left: none; border-right: 1px solid threedshadow; -moz-border-radius-topleft: 0px; @@ -1660,7 +1660,7 @@ toolbarbutton.chevron { list-style-image: url("chrome://global/skin/toolbar/chevron.gif") !important; } -toolbarbutton.chevron[chromedir="rtl"] { +toolbarbutton.chevron:-moz-locale-dir(rtl) { list-style-image: url("chrome://global/skin/toolbar/chevron-rtl.gif") !important; } @@ -1712,13 +1712,13 @@ toolbar[mode="text"] > #window-controls > toolbarbutton > .toolbarbutton-text { -moz-image-region: rect(0, 26px, 11px, 13px); } -#urlbar[chromedir="ltr"] > .autocomplete-history-dropmarker { +#urlbar:-moz-locale-dir(ltr) > .autocomplete-history-dropmarker { border-left: 1px solid; -moz-border-left-colors: transparent; } -#urlbar[chromedir="ltr"] > .autocomplete-history-dropmarker:hover , -#urlbar[chromedir="ltr"] > .autocomplete-history-dropmarker[open="true"] { +#urlbar:-moz-locale-dir(ltr) > .autocomplete-history-dropmarker:hover , +#urlbar:-moz-locale-dir(ltr) > .autocomplete-history-dropmarker[open="true"] { -moz-border-left-colors: ButtonShadow; } @@ -1802,7 +1802,7 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] { /* ::::: Identity Indicator Styling ::::: */ /* Location bar visuals*/ -#urlbar[chromedir="ltr"]:-moz-system-metric(windows-default-theme) { +#urlbar:-moz-locale-dir(ltr):-moz-system-metric(windows-default-theme) { -moz-margin-start: 6px; } @@ -1818,10 +1818,10 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] { -moz-box-shadow: 1px 1px 0 rgba(255,255,255,.3) inset, 0 -1px 0 rgba(255,255,255,.2) inset; } -#identity-box[chromedir="rtl"] { +#identity-box:-moz-locale-dir(ltr) { -moz-border-start-style: solid; } -#identity-box[chromedir="ltr"]:-moz-system-metric(windows-default-theme) { +#identity-box:-moz-locale-dir(ltr):-moz-system-metric(windows-default-theme) { -moz-border-radius: 6px 0 2px 6px / 15px 0 2px 15px; margin: -1px 0; -moz-margin-start: -4px; @@ -1980,7 +1980,7 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] { } /* Bug 413060, comment 14: Match #identity-box's -moz-margin-start, less 1px */ -#identity-popup[chromedir="ltr"]:-moz-system-metric(windows-default-theme) { +#identity-popup:-moz-locale-dir(ltr):-moz-system-metric(windows-default-theme) { -moz-margin-start: 3px; } diff --git a/browser/themes/winstripe/browser/places/organizer.css b/browser/themes/winstripe/browser/places/organizer.css index f2b5d494c1fe..6eb2e9d9c161 100644 --- a/browser/themes/winstripe/browser/places/organizer.css +++ b/browser/themes/winstripe/browser/places/organizer.css @@ -20,36 +20,36 @@ } #back-button, -#forward-button[chromedir="rtl"] { +#forward-button:-moz-locale-dir(rtl) { -moz-image-region: rect(0px, 24px, 24px, 0px); } #back-button:not([disabled="true"]):hover, -#forward-button:not([disabled="true"]):hover[chromedir="rtl"] { +#forward-button:not([disabled="true"]):hover:-moz-locale-dir(rtl) { -moz-image-region: rect(24px, 24px, 48px, 0px); } #back-button[disabled="true"], -#forward-button[chromedir="rtl"][disabled="true"] { +#forward-button:-moz-locale-dir(rtl)[disabled="true"] { -moz-image-region: rect(48px, 24px, 72px, 0px) !important; } #back-button:not([disabled="true"]):hover:active, -#forward-button:not([disabled="true"]):hover:active[chromedir="rtl"] { +#forward-button:not([disabled="true"]):hover:active:-moz-locale-dir(rtl) { -moz-image-region: rect(72px, 24px, 96px, 0px); } #forward-button, -#back-button[chromedir="rtl"] { +#back-button:-moz-locale-dir(rtl) { -moz-image-region: rect(0px, 48px, 24px, 24px); } #forward-button:not([disabled="true"]):hover, -#back-button:not([disabled="true"]):hover[chromedir="rtl"] { +#back-button:not([disabled="true"]):hover:-moz-locale-dir(rtl) { -moz-image-region: rect(24px, 48px, 48px, 24px); } #forward-button[disabled="true"], -#back-button[chromedir="rtl"][disabled="true"] { +#back-button:-moz-locale-dir(rtl)[disabled="true"] { -moz-image-region: rect(48px, 48px, 72px, 24px) !important; } #forward-button:not([disabled="true"]):hover:active, -#back-button:not([disabled="true"]):hover:active[chromedir="rtl"] { +#back-button:not([disabled="true"]):hover:active:-moz-locale-dir(rtl) { -moz-image-region: rect(72px, 48px, 96px, 24px); } @@ -94,7 +94,7 @@ background: url(chrome://global/skin/arrow/arrow-dn.gif) right center no-repeat; } -#placesMenu[chromedir="rtl"] > menu > label { +#placesMenu:-moz-locale-dir(rtl) > menu > label { background-position: left center; } diff --git a/browser/themes/winstripe/browser/searchbar.css b/browser/themes/winstripe/browser/searchbar.css index 7684ba79fa6d..6656a4b5044a 100644 --- a/browser/themes/winstripe/browser/searchbar.css +++ b/browser/themes/winstripe/browser/searchbar.css @@ -45,7 +45,7 @@ 0 -1px 0 rgba(255,255,255,.4) inset; } -.searchbar-engine-button:-moz-system-metric(windows-default-theme)[chromedir="ltr"] { +.searchbar-engine-button:-moz-system-metric(windows-default-theme):-moz-locale-dir(ltr) { -moz-border-right-colors: rgba(0,0,0,.05); } @@ -68,7 +68,7 @@ background: transparent url(chrome://browser/skin/Search-addengines.png) no-repeat right center; } -.searchbar-engine-button[addengines="true"][chromedir="rtl"] > .button-box { +.searchbar-engine-button[addengines="true"]:-moz-locale-dir(rtl) > .button-box { background-position: left center; } @@ -94,7 +94,7 @@ -moz-image-region: rect(0px 16px 16px 0px); } -.search-go-button[chromedir="rtl"] { +.search-go-button:-moz-locale-dir(rtl) { -moz-transform: scaleX(-1); } diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index 37197b9228ec..ea075f5599e1 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -105,8 +105,8 @@ class nsIBoxObject; // IID for the nsIDocument interface #define NS_IDOCUMENT_IID \ - { 0x46003091, 0x7f99, 0x420f, \ - { 0x95, 0xbc, 0x28, 0xd7, 0xd5, 0x01, 0x5a, 0x41 } } +{ 0xe0ca6723, 0x1efa, 0x4819, \ + { 0x84, 0xbb, 0xfa, 0x48, 0x39, 0xe8, 0xef, 0x19 } } // Flag for AddStyleSheet(). #define NS_STYLESHEET_FROM_CATALOG (1 << 0) @@ -1156,6 +1156,15 @@ public: */ virtual void MaybePreLoadImage(nsIURI* uri) = 0; + /** + * Returns true if the locale used for the document specifies a direction of + * right to left. For chrome documents, this comes from the chrome registry. + * This is used to determine the current state for the :-moz-locale-dir pseudoclass + * so once can know whether a document is expected to be rendered left-to-right + * or right-to-left. + */ + virtual PRBool IsDocumentRightToLeft() { return PR_FALSE; } + protected: ~nsIDocument() { diff --git a/content/base/src/nsGkAtomList.h b/content/base/src/nsGkAtomList.h index d2b6957323c2..ac97d1d4043d 100644 --- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -503,6 +503,7 @@ GK_ATOM(listing, "listing") GK_ATOM(listitem, "listitem") GK_ATOM(listrows, "listrows") GK_ATOM(load, "load") +GK_ATOM(localedir, "localedir") GK_ATOM(localName, "local-name") GK_ATOM(longdesc, "longdesc") #ifdef MOZ_MEDIA diff --git a/content/xul/content/src/nsXULElement.cpp b/content/xul/content/src/nsXULElement.cpp index 3bb92cfc1c7a..6ed33863613c 100644 --- a/content/xul/content/src/nsXULElement.cpp +++ b/content/xul/content/src/nsXULElement.cpp @@ -1119,6 +1119,15 @@ nsXULElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName, SetTitlebarColor(color, aName == nsGkAtoms::activetitlebarcolor); } + // if the localedir changed on the root element, reset the document direction + if (aName == nsGkAtoms::localedir && + document && document->GetRootContent() == this) { + nsCOMPtr xuldoc = do_QueryInterface(document); + if (xuldoc) { + xuldoc->ResetDocumentDirection(); + } + } + if (aName == nsGkAtoms::src && document) { LoadSrc(); } @@ -1365,6 +1374,15 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, PRBool aNotify) SetTitlebarColor(NS_RGBA(0, 0, 0, 0), aName == nsGkAtoms::activetitlebarcolor); } + // if the localedir changed on the root element, reset the document direction + if (aName == nsGkAtoms::localedir && + doc && doc->GetRootContent() == this) { + nsCOMPtr xuldoc = do_QueryInterface(doc); + if (xuldoc) { + xuldoc->ResetDocumentDirection(); + } + } + // If the accesskey attribute is removed, unregister it here // Also see nsXULLabelFrame, nsBoxFrame and nsTextBoxFrame's AttributeChanged if (aName == nsGkAtoms::accesskey || aName == nsGkAtoms::control) { @@ -1793,8 +1811,7 @@ nsXULElement::GetAttributeChangeHint(const nsIAtom* aAttribute, retval = NS_STYLE_HINT_FRAMECHANGE; } else { // if left or top changes we reflow. This will happen in xul - // containers that manage positioned children such as a - // bulletinboard. + // containers that manage positioned children such as a stack. if (nsGkAtoms::left == aAttribute || nsGkAtoms::top == aAttribute) retval = NS_STYLE_HINT_REFLOW; } diff --git a/content/xul/document/public/nsIXULDocument.h b/content/xul/document/public/nsIXULDocument.h index bcc30d03a723..a6b04e85d3d7 100644 --- a/content/xul/document/public/nsIXULDocument.h +++ b/content/xul/document/public/nsIXULDocument.h @@ -122,6 +122,11 @@ public: * Callback notifying when a document could not be parsed properly. */ virtual PRBool OnDocumentParserError() = 0; + + /** + * Reset the document direction so that it is recomputed. + */ + virtual void ResetDocumentDirection() = 0; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsIXULDocument, NS_IXULDOCUMENT_IID) diff --git a/content/xul/document/src/Makefile.in b/content/xul/document/src/Makefile.in index f7db62fb4941..f205e1b8772f 100644 --- a/content/xul/document/src/Makefile.in +++ b/content/xul/document/src/Makefile.in @@ -95,7 +95,10 @@ include $(topsrcdir)/config/rules.mk LOCAL_INCLUDES = -I$(srcdir)/../../../base/src \ -I$(srcdir)/../../content/src \ -I$(srcdir)/../../templates/src \ + -I$(srcdir)/../../../../layout/base \ + -I$(srcdir)/../../../../layout/generic \ -I$(srcdir)/../../../../layout/style \ + -I$(srcdir)/../../../../layout/xul/base/src \ -I$(srcdir)/../../../xml/document/src \ -I$(srcdir)/../../../events/src \ $(NULL) diff --git a/content/xul/document/src/nsXULDocument.cpp b/content/xul/document/src/nsXULDocument.cpp index 51535642bf01..b3be0dd04bdb 100644 --- a/content/xul/document/src/nsXULDocument.cpp +++ b/content/xul/document/src/nsXULDocument.cpp @@ -126,6 +126,7 @@ #include "nsXULPopupManager.h" #include "nsCCUncollectableMarker.h" #include "nsURILoader.h" +#include "nsCSSFrameConstructor.h" //---------------------------------------------------------------------- // @@ -222,6 +223,7 @@ nsRefMapEntry::RemoveContent(nsIContent* aContent) nsXULDocument::nsXULDocument(void) : nsXMLDocument("application/vnd.mozilla.xul+xml"), + mDocDirection(Direction_Uninitialized), mState(eState_Master), mResolutionPhase(nsForwardReference::eStart) { @@ -260,6 +262,10 @@ nsXULDocument::~nsXULDocument() delete mTemplateBuilderTable; + nsContentUtils::UnregisterPrefCallback("intl.uidirection.", + nsXULDocument::DirectionChanged, + this); + if (--gRefCnt == 0) { NS_IF_RELEASE(gRDFService); @@ -1989,6 +1995,10 @@ nsXULDocument::Init() } } + nsContentUtils::RegisterPrefCallback("intl.uidirection.", + nsXULDocument::DirectionChanged, + this); + #ifdef PR_LOGGING if (! gXULLog) gXULLog = PR_NewLogModule("nsXULDocument"); @@ -4627,6 +4637,100 @@ nsXULDocument::GetFocusController(nsIFocusController** aFocusController) *aFocusController = nsnull; } +PRBool +nsXULDocument::IsDocumentRightToLeft() +{ + if (mDocDirection == Direction_Uninitialized) { + mDocDirection = Direction_LeftToRight; // default to ltr on failure + + // setting the localedir attribute on the root element forces a + // specific direction for the document. + nsIContent* content = GetRootContent(); + if (content) { + static nsIContent::AttrValuesArray strings[] = + {&nsGkAtoms::ltr, &nsGkAtoms::rtl, nsnull}; + switch (content->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::localedir, + strings, eCaseMatters)) { + case 0: mDocDirection = Direction_LeftToRight; return PR_FALSE; + case 1: mDocDirection = Direction_RightToLeft; return PR_TRUE; + default: break;// otherwise, not a valid value, so fall through + } + } + + // otherwise, get the locale from the chrome registry and + // look up the intl.uidirection. preference + nsCOMPtr reg = + do_GetService(NS_CHROMEREGISTRY_CONTRACTID); + if (reg) { + nsCAutoString package; + PRBool isChrome; + if (NS_SUCCEEDED(mDocumentURI->SchemeIs("chrome", &isChrome)) && + isChrome) { + mDocumentURI->GetHostPort(package); + } + else { + // use the 'global' package for about and resource uris. + // otherwise, just default to left-to-right. + PRBool isAbout, isResource; + if (NS_SUCCEEDED(mDocumentURI->SchemeIs("about", &isAbout)) && + isAbout) { + package.AssignLiteral("global"); + } + else if (NS_SUCCEEDED(mDocumentURI->SchemeIs("resource", &isResource)) && + isResource) { + package.AssignLiteral("global"); + } + else { + return PR_FALSE; + } + } + + nsCAutoString locale; + reg->GetSelectedLocale(package, locale); + if (locale.Length() >= 2) { + // first check the intl.uidirection. preference, + // and if that is not set, check the same preference but + // with just the first two characters of the locale. If + // that isn't set, default to left-to-right. + nsCAutoString prefString = + NS_LITERAL_CSTRING("intl.uidirection.") + locale; + nsAdoptingCString dir = nsContentUtils::GetCharPref(prefString.get()); + if (dir.IsEmpty()) { + PRInt32 hyphen = prefString.FindChar('-'); + if (hyphen >= 1) { + nsCAutoString shortPref(Substring(prefString, 0, hyphen)); + dir = nsContentUtils::GetCharPref(shortPref.get()); + } + } + + mDocDirection = dir.EqualsLiteral("rtl") ? + Direction_RightToLeft : Direction_LeftToRight; + } + } + } + + return (mDocDirection == Direction_RightToLeft); +} + +int +nsXULDocument::DirectionChanged(const char* aPrefName, void* aData) +{ + // reset the direction and reflow the document. This will happen if + // the direction isn't actually being used, but that doesn't really + // matter too much + nsXULDocument* doc = (nsXULDocument *)aData; + if (doc) + doc->ResetDocumentDirection(); + + nsIPresShell *shell = doc->GetPrimaryShell(); + if (shell) { + shell->FrameConstructor()-> + PostRestyleEvent(doc->GetRootContent(), eReStyle_Self, NS_STYLE_HINT_NONE); + } + + return 0; +} + NS_IMETHODIMP nsXULDocument::GetBoxObjectFor(nsIDOMElement* aElement, nsIBoxObject** aResult) { diff --git a/content/xul/document/src/nsXULDocument.h b/content/xul/document/src/nsXULDocument.h index 447aa843ecca..48c26ccd080e 100644 --- a/content/xul/document/src/nsXULDocument.h +++ b/content/xul/document/src/nsXULDocument.h @@ -182,6 +182,10 @@ public: virtual void EndUpdate(nsUpdateType aUpdateType); + virtual PRBool IsDocumentRightToLeft(); + + virtual void ResetDocumentDirection() { mDocDirection = Direction_Uninitialized; } + static PRBool MatchAttribute(nsIContent* aContent, PRInt32 aNameSpaceID, @@ -244,7 +248,8 @@ protected: return kNameSpaceID_XUL; } -protected: + static NS_HIDDEN_(int) DirectionChanged(const char* aPrefName, void* aData); + // pseudo constants static PRInt32 gRefCnt; @@ -326,6 +331,17 @@ protected: nsCOMPtr mTooltipNode; // [OWNER] element triggering the tooltip + /** + * document direction for use with the -moz-locale-dir property + */ + enum DocumentDirection { + Direction_Uninitialized, // not determined yet + Direction_LeftToRight, + Direction_RightToLeft + }; + + DocumentDirection mDocDirection; + /** * Context stack, which maintains the state of the Builder and allows * it to be interrupted. diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index 4c340b795fe4..e30a329af8b7 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -3313,6 +3313,14 @@ CSSParserImpl::ParsePseudoClassWithIdentArg(nsCSSSelector& aSelector, return eSelectorParsingStatus_Error; } + // -moz-locale-dir can only have values of 'ltr' or 'rtl'. + if (aPseudo == nsCSSPseudoClasses::mozLocaleDir) { + if (!mToken.mIdent.EqualsLiteral("ltr") && + !mToken.mIdent.EqualsLiteral("rtl")) { + return eSelectorParsingStatus_Error; + } + } + // Add the pseudo with the language parameter aSelector.AddPseudoClass(aPseudo, mToken.mIdent.get()); diff --git a/layout/style/nsCSSPseudoClassList.h b/layout/style/nsCSSPseudoClassList.h index 113b67fbb45f..d61c97bddd3a 100644 --- a/layout/style/nsCSSPseudoClassList.h +++ b/layout/style/nsCSSPseudoClassList.h @@ -104,6 +104,10 @@ CSS_PSEUDO_CLASS(mozIsHTML, ":-moz-is-html") // Matches anything when the specified look-and-feel metric is set CSS_PSEUDO_CLASS(mozSystemMetric, ":-moz-system-metric") +// -moz-locale-dir(ltr) and -moz-locale-dir(rtl) may be used +// to match based on the locale's chrome direction +CSS_PSEUDO_CLASS(mozLocaleDir, ":-moz-locale-dir") + #ifdef MOZ_MATHML CSS_PSEUDO_CLASS(mozMathIncrementScriptLevel, ":-moz-math-increment-script-level") #endif diff --git a/layout/style/nsCSSPseudoClasses.cpp b/layout/style/nsCSSPseudoClasses.cpp index bff32293bc67..a37e17f1585f 100644 --- a/layout/style/nsCSSPseudoClasses.cpp +++ b/layout/style/nsCSSPseudoClasses.cpp @@ -73,7 +73,8 @@ nsCSSPseudoClasses::HasStringArg(nsIAtom* aAtom) { return aAtom == nsCSSPseudoClasses::lang || aAtom == nsCSSPseudoClasses::mozEmptyExceptChildrenWithLocalname || - aAtom == nsCSSPseudoClasses::mozSystemMetric; + aAtom == nsCSSPseudoClasses::mozSystemMetric || + aAtom == nsCSSPseudoClasses::mozLocaleDir; } PRBool diff --git a/layout/style/nsCSSRuleProcessor.cpp b/layout/style/nsCSSRuleProcessor.cpp index 30323316a7f3..a25fcafc9e76 100644 --- a/layout/style/nsCSSRuleProcessor.cpp +++ b/layout/style/nsCSSRuleProcessor.cpp @@ -1558,6 +1558,27 @@ static PRBool SelectorMatches(RuleProcessorData &data, else if (nsCSSPseudoClasses::mozIsHTML == pseudoClass->mAtom) { result = data.mIsHTMLContent && data.mContent->IsInHTMLDocument(); } + else if (nsCSSPseudoClasses::mozLocaleDir == pseudoClass->mAtom) { + nsIDocument* doc = data.mContent ? data.mContent->GetDocument() : + data.mPresContext->Document(); + + if (doc) { + PRBool docIsRTL = doc && doc->IsDocumentRightToLeft(); + + nsDependentString dirString(pseudoClass->u.mString); + NS_ASSERTION(dirString.EqualsLiteral("ltr") || dirString.EqualsLiteral("rtl"), + "invalid value for -moz-locale-dir"); + + if (dirString.EqualsLiteral("rtl")) { + result = docIsRTL; + } else if (dirString.EqualsLiteral("ltr")) { + result = !docIsRTL; + } + } + else { + result = PR_FALSE; + } + } #ifdef MOZ_MATHML else if (nsCSSPseudoClasses::mozMathIncrementScriptLevel == pseudoClass->mAtom) { stateToCheck = NS_EVENT_STATE_INCREMENT_SCRIPT_LEVEL; @@ -2069,6 +2090,14 @@ nsCSSRuleProcessor::HasAttributeDependentStyle(AttributeRuleProcessorData* aData // XXXbz now that :link and :visited are also states, do we need a // similar optimization in HasStateDependentStyle? + // check for the localedir attribute on root XUL elements + if (aData->mAttribute == nsGkAtoms::localedir && + aData->mNameSpaceID == kNameSpaceID_XUL && + aData->mContent == aData->mContent->GetOwnerDoc()->GetRootContent()) + { + data.change = nsReStyleHint(data.change | eReStyle_Self); + } + RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext); // We do the same thing for attributes that we do for state selectors diff --git a/layout/style/test/test_selectors.html b/layout/style/test/test_selectors.html index 63b72a8b2612..d7a477066e21 100644 --- a/layout/style/test/test_selectors.html +++ b/layout/style/test/test_selectors.html @@ -632,6 +632,16 @@ function run() { test_selector_in_html("html|a:not(*|a)", single_a, empty_set, set_single, xul_default_ns + html_ns); + // Test -moz-locale-dir + test_parseable(":-moz-locale-dir(ltr)"); + test_parseable(":-moz-locale-dir(rtl)"); + + test_balanced_unparseable(":-moz-locale-dir(other)"); + test_balanced_unparseable(":-moz-locale-dir()"); + test_balanced_unparseable(":-moz-locale-dir('ltr')"); + test_balanced_unparseable(":-moz-locale-dir(ltr, other)"); + test_balanced_unparseable(":-moz-locale-dir"); + run_deferred_tests(); } diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index a5bae40372b3..4bd02803f00e 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -910,6 +910,11 @@ pref("intl.locale.matchOS", false); pref("intl.fallbackCharsetList.ISO-8859-1", "windows-1252"); pref("font.language.group", "chrome://global/locale/intl.properties"); +// these locales have right-to-left UI +pref("intl.uidirection.ar", "rtl"); +pref("intl.uidirection.he", "rtl"); +pref("intl.uidirection.fa", "rtl"); + pref("font.mathfont-family", "STIXNonUnicode, STIXSize1, STIXGeneral, Standard Symbols L, DejaVu Sans, Cambria Math"); // Some CJK fonts have bad underline offset, their CJK character glyphs are overlapped (or adjoined) to its underline. diff --git a/toolkit/components/console/content/console.xul b/toolkit/components/console/content/console.xul index 0492b1855877..9a8a78e50cad 100644 --- a/toolkit/components/console/content/console.xul +++ b/toolkit/components/console/content/console.xul @@ -45,7 +45,6 @@ %console; - %global; ]> - + - + diff --git a/toolkit/components/help/content/help.xul b/toolkit/components/help/content/help.xul index fab7524a2eb7..cf3a766cfae4 100644 --- a/toolkit/components/help/content/help.xul +++ b/toolkit/components/help/content/help.xul @@ -46,8 +46,6 @@ %brandDTD; %helpDTD; - - %globalDTD; ]> - + + tooltiptext="&backButton.tooltip;"> + observes="canGoForward"> %helpDTD; - - %globalDTD; ]> @@ -52,13 +50,11 @@ label="&backButton.label;" accesskey="&backButton.accesskey;" observes="canGoBack" - chromedir="&locale.dir;" oncommand="goBack()"/> %printPreviewDTD; - -%globalDTD; ]> - - - - diff --git a/toolkit/content/tests/chrome/Makefile.in b/toolkit/content/tests/chrome/Makefile.in index eb3b95defd48..24415d55f440 100644 --- a/toolkit/content/tests/chrome/Makefile.in +++ b/toolkit/content/tests/chrome/Makefile.in @@ -42,6 +42,9 @@ VPATH = @srcdir@ relativesrcdir = toolkit/content/tests/chrome include $(DEPTH)/config/autoconf.mk + +DIRS = rtltest + include $(topsrcdir)/config/rules.mk _TEST_FILES = findbar_window.xul \ @@ -86,6 +89,7 @@ _TEST_FILES = findbar_window.xul \ test_keys.xul \ window_keys.xul \ test_showcaret.xul \ + test_righttoleft.xul \ $(NULL) # test_panel_focus.xul won't work if the Full Keyboard Access preference is set to diff --git a/toolkit/content/tests/chrome/rtltest/Makefile.in b/toolkit/content/tests/chrome/rtltest/Makefile.in new file mode 100644 index 000000000000..6bfec3fc2036 --- /dev/null +++ b/toolkit/content/tests/chrome/rtltest/Makefile.in @@ -0,0 +1,49 @@ +# +# ***** 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 mozilla.org code. +# +# The Initial Developer of the Original Code is +# Mozilla Foundation. +# Portions created by the Initial Developer are Copyright (C) 2009 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either of 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 ***** + +DEPTH = ../../../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ +relativesrcdir = toolkit/content/tests/chrome/rtltest + +include $(DEPTH)/config/autoconf.mk +include $(topsrcdir)/config/rules.mk + +libs:: righttoleft.manifest dirtest.xul + $(INSTALL) @srcdir@/righttoleft.manifest $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)/ + $(INSTALL) @srcdir@/dirtest.xul $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)/content/ diff --git a/toolkit/content/tests/chrome/rtltest/dirtest.xul b/toolkit/content/tests/chrome/rtltest/dirtest.xul new file mode 100644 index 000000000000..b75d41eaa3ad --- /dev/null +++ b/toolkit/content/tests/chrome/rtltest/dirtest.xul @@ -0,0 +1,25 @@ + + + + + + + +hbox, vbox { background-color: white; } +hbox:-moz-locale-dir(ltr) { background-color: yellow; } +vbox:-moz-locale-dir(rtl) { background-color: green; } + + + +