diff -Nru firefox-18.0.1+build1/browser/app/blocklist.xml firefox-18.0.2+build1/browser/app/blocklist.xml --- firefox-18.0.1+build1/browser/app/blocklist.xml 2013-01-16 17:54:46.000000000 +0000 +++ firefox-18.0.2+build1/browser/app/blocklist.xml 2013-02-01 17:53:52.000000000 +0000 @@ -1,5 +1,5 @@ - + @@ -214,15 +214,23 @@ + + + + + + + + - + @@ -286,7 +294,7 @@ - + @@ -588,21 +596,21 @@ - + - + - + @@ -660,6 +668,22 @@ + + + + + + + + + + + + + + + + diff -Nru firefox-18.0.1+build1/browser/base/content/test/Makefile.in firefox-18.0.2+build1/browser/base/content/test/Makefile.in --- firefox-18.0.1+build1/browser/base/content/test/Makefile.in 2013-01-16 17:54:46.000000000 +0000 +++ firefox-18.0.2+build1/browser/base/content/test/Makefile.in 2013-02-01 17:53:52.000000000 +0000 @@ -182,7 +182,7 @@ browser_pinnedTabs.js \ browser_plainTextLinks.js \ browser_pluginnotification.js \ - browser_clickToPlayPluginScriptAccessPopup.js \ + browser_CTPScriptPlugin.js \ browser_pluginplaypreview.js \ browser_relatedTabs.js \ browser_sanitize-passwordDisabledHosts.js \ diff -Nru firefox-18.0.1+build1/browser/base/content/test/browser_CTPScriptPlugin.js firefox-18.0.2+build1/browser/base/content/test/browser_CTPScriptPlugin.js --- firefox-18.0.1+build1/browser/base/content/test/browser_CTPScriptPlugin.js 1970-01-01 00:00:00.000000000 +0000 +++ firefox-18.0.2+build1/browser/base/content/test/browser_CTPScriptPlugin.js 2013-02-01 17:53:52.000000000 +0000 @@ -0,0 +1,127 @@ +const gHttpTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); +const EXPECTED_PLUGINSCRIPTED_EVENT_COUNT = 6; + +var gTestBrowser = null; +var gNextTestList = []; +var gNextTest = null; +var gPluginScriptedFired = false; +var gPluginScriptedFiredCount = 0; + +Components.utils.import("resource://gre/modules/Services.jsm"); + +function test() { + waitForExplicitFinish(); + registerCleanupFunction(function() { + Services.prefs.clearUserPref("plugins.click_to_play"); + gTestBrowser.removeEventListener("load", pageLoad, true); + gTestBrowser.removeEventListener("PluginScripted", pluginScripted, true); + }); + Services.prefs.setBoolPref("plugins.click_to_play", true); + + gBrowser.selectedTab = gBrowser.addTab(); + gTestBrowser = gBrowser.selectedBrowser; + gTestBrowser.addEventListener("load", pageLoad, true); + gTestBrowser.addEventListener("PluginScripted", pluginScripted, true); + + // This list is iterated in reverse order, since it uses Array.pop to get the next test. + gNextTestList = [ + // Doesn't show a popup since not the first instance of a small plugin + { func: testExpectNoPopupPart1, + url: gHttpTestRoot + "plugin_test_scriptedPopup1.html" }, + // Doesn't show a popup since not the first instance of a small plugin + { func: testExpectNoPopupPart1, + url: gHttpTestRoot + "plugin_test_scriptedPopup2.html" }, + // Shows a popup since it is the first instance of a small plugin + { func: testExpectPopupPart1, + url: gHttpTestRoot + "plugin_test_scriptedPopup3.html" }, + { func: testExpectNoPopupPart1, + url: gHttpTestRoot + "plugin_test_scriptedNoPopup1.html" }, + { func: testExpectNoPopupPart1, + url: gHttpTestRoot + "plugin_test_scriptedNoPopup2.html" }, + { func: testExpectNoPopupPart1, + url: gHttpTestRoot + "plugin_test_scriptedNoPopup3.html" } + ]; + + prepareTest(testNoEventFired, gHttpTestRoot + "plugin_test_noScriptNoPopup.html"); +} + +function getCurrentTestLocation() { + var loc = gTestBrowser.contentWindow.location.toString(); + return loc.replace(gHttpTestRoot, ""); +} + +function runNextTest() { + var nextTest = gNextTestList.pop(); + if (nextTest) { + gPluginScriptedFired = false; + prepareTest(nextTest.func, nextTest.url); + } + else { + finishTest(); + } +} + +function finishTest() { + is(gPluginScriptedFiredCount, EXPECTED_PLUGINSCRIPTED_EVENT_COUNT, "PluginScripted event count is correct"); + gBrowser.removeCurrentTab(); + window.focus(); + finish(); +} + +function pluginScripted() { + gPluginScriptedFired = true; + gPluginScriptedFiredCount++; +} + +function pageLoad() { + // The plugin events are async dispatched and can come after the load event + // This just allows the events to fire before we then go on to test the states + executeSoon(gNextTest); +} + +function prepareTest(nextTest, url) { + gNextTest = nextTest; + gTestBrowser.contentWindow.location = url; +} + +function testNoEventFired() { + var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(notification, "should have a click-to-play notification (" + getCurrentTestLocation() + ")"); + ok(notification.dismissed, "notification should not be showing (" + getCurrentTestLocation() + ")"); + ok(!gPluginScriptedFired, "PluginScripted should not have fired (" + getCurrentTestLocation() + ")"); + + runNextTest(); +} + +function testExpectNoPopupPart1() { + var condition = function() gPluginScriptedFired; + waitForCondition(condition, testExpectNoPopupPart2, "waited too long for PluginScripted event (" + getCurrentTestLocation() + ")"); +} + +function testExpectNoPopupPart2() { + var condition = function() gTestBrowser._pluginScriptedState == PLUGIN_SCRIPTED_STATE_DONE; + waitForCondition(condition, testExpectNoPopupPart3, "waited too long for PluginScripted event handling (" + getCurrentTestLocation() + ")"); +} + +function testExpectNoPopupPart3() { + var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(notification, "should have a click-to-play notification (" + getCurrentTestLocation() + ")"); + ok(notification.dismissed, "notification should not be showing (" + getCurrentTestLocation() + ")"); + + runNextTest(); +} + +function testExpectPopupPart1() { + var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(notification, "should have a click-to-play notification (" + getCurrentTestLocation() + ")"); + + var condition = function() !notification.dismissed; + waitForCondition(condition, testExpectPopupPart2, "waited too long for popup notification to show (" + getCurrentTestLocation() + ")"); +} + +function testExpectPopupPart2() { + var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(!notification.dismissed, "notification should be showing (" + getCurrentTestLocation() + ")"); + + runNextTest(); +} diff -Nru firefox-18.0.1+build1/browser/base/content/test/browser_clickToPlayPluginScriptAccessPopup.js firefox-18.0.2+build1/browser/base/content/test/browser_clickToPlayPluginScriptAccessPopup.js --- firefox-18.0.1+build1/browser/base/content/test/browser_clickToPlayPluginScriptAccessPopup.js 2013-01-16 17:54:46.000000000 +0000 +++ firefox-18.0.2+build1/browser/base/content/test/browser_clickToPlayPluginScriptAccessPopup.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,127 +0,0 @@ -const gHttpTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); -const EXPECTED_PLUGINSCRIPTED_EVENT_COUNT = 6; - -var gTestBrowser = null; -var gNextTestList = []; -var gNextTest = null; -var gPluginScriptedFired = false; -var gPluginScriptedFiredCount = 0; - -Components.utils.import("resource://gre/modules/Services.jsm"); - -function test() { - waitForExplicitFinish(); - registerCleanupFunction(function() { - Services.prefs.clearUserPref("plugins.click_to_play"); - gTestBrowser.removeEventListener("load", pageLoad, true); - gTestBrowser.removeEventListener("PluginScripted", pluginScripted, true); - }); - Services.prefs.setBoolPref("plugins.click_to_play", true); - - gBrowser.selectedTab = gBrowser.addTab(); - gTestBrowser = gBrowser.selectedBrowser; - gTestBrowser.addEventListener("load", pageLoad, true); - gTestBrowser.addEventListener("PluginScripted", pluginScripted, true); - - // This list is iterated in reverse order, since it uses Array.pop to get the next test. - gNextTestList = [ - // Doesn't show a popup since not the first instance of a small plugin - { func: testExpectNoPopupPart1, - url: gHttpTestRoot + "plugin_test_scriptedPopup1.html" }, - // Doesn't show a popup since not the first instance of a small plugin - { func: testExpectNoPopupPart1, - url: gHttpTestRoot + "plugin_test_scriptedPopup2.html" }, - // Shows a popup since it is the first instance of a small plugin - { func: testExpectPopupPart1, - url: gHttpTestRoot + "plugin_test_scriptedPopup3.html" }, - { func: testExpectNoPopupPart1, - url: gHttpTestRoot + "plugin_test_scriptedNoPopup1.html" }, - { func: testExpectNoPopupPart1, - url: gHttpTestRoot + "plugin_test_scriptedNoPopup2.html" }, - { func: testExpectNoPopupPart1, - url: gHttpTestRoot + "plugin_test_scriptedNoPopup3.html" } - ]; - - prepareTest(testNoEventFired, gHttpTestRoot + "plugin_test_noScriptNoPopup.html"); -} - -function getCurrentTestLocation() { - var loc = gTestBrowser.contentWindow.location.toString(); - return loc.replace(gHttpTestRoot, ""); -} - -function runNextTest() { - var nextTest = gNextTestList.pop(); - if (nextTest) { - gPluginScriptedFired = false; - prepareTest(nextTest.func, nextTest.url); - } - else { - finishTest(); - } -} - -function finishTest() { - is(gPluginScriptedFiredCount, EXPECTED_PLUGINSCRIPTED_EVENT_COUNT, "PluginScripted event count is correct"); - gBrowser.removeCurrentTab(); - window.focus(); - finish(); -} - -function pluginScripted() { - gPluginScriptedFired = true; - gPluginScriptedFiredCount++; -} - -function pageLoad() { - // The plugin events are async dispatched and can come after the load event - // This just allows the events to fire before we then go on to test the states - executeSoon(gNextTest); -} - -function prepareTest(nextTest, url) { - gNextTest = nextTest; - gTestBrowser.contentWindow.location = url; -} - -function testNoEventFired() { - var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); - ok(notification, "should have a click-to-play notification (" + getCurrentTestLocation() + ")"); - ok(notification.dismissed, "notification should not be showing (" + getCurrentTestLocation() + ")"); - ok(!gPluginScriptedFired, "PluginScripted should not have fired (" + getCurrentTestLocation() + ")"); - - runNextTest(); -} - -function testExpectNoPopupPart1() { - var condition = function() gPluginScriptedFired; - waitForCondition(condition, testExpectNoPopupPart2, "waited too long for PluginScripted event (" + getCurrentTestLocation() + ")"); -} - -function testExpectNoPopupPart2() { - var condition = function() gTestBrowser._pluginScriptedState == PLUGIN_SCRIPTED_STATE_DONE; - waitForCondition(condition, testExpectNoPopupPart3, "waited too long for PluginScripted event handling (" + getCurrentTestLocation() + ")"); -} - -function testExpectNoPopupPart3() { - var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); - ok(notification, "should have a click-to-play notification (" + getCurrentTestLocation() + ")"); - ok(notification.dismissed, "notification should not be showing (" + getCurrentTestLocation() + ")"); - - runNextTest(); -} - -function testExpectPopupPart1() { - var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); - ok(notification, "should have a click-to-play notification (" + getCurrentTestLocation() + ")"); - - var condition = function() !notification.dismissed; - waitForCondition(condition, testExpectPopupPart2, "waited too long for popup notification to show (" + getCurrentTestLocation() + ")"); -} - -function testExpectPopupPart2() { - var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); - ok(!notification.dismissed, "notification should be showing (" + getCurrentTestLocation() + ")"); - - runNextTest(); -} diff -Nru firefox-18.0.1+build1/browser/config/version.txt firefox-18.0.2+build1/browser/config/version.txt --- firefox-18.0.1+build1/browser/config/version.txt 2013-01-16 17:54:47.000000000 +0000 +++ firefox-18.0.2+build1/browser/config/version.txt 2013-02-01 17:53:53.000000000 +0000 @@ -1 +1 @@ -18.0.1 +18.0.2 diff -Nru firefox-18.0.1+build1/config/milestone.txt firefox-18.0.2+build1/config/milestone.txt --- firefox-18.0.1+build1/config/milestone.txt 2013-01-16 17:54:49.000000000 +0000 +++ firefox-18.0.2+build1/config/milestone.txt 2013-02-01 17:53:54.000000000 +0000 @@ -10,4 +10,4 @@ # hardcoded milestones in the tree from these two files. #-------------------------------------------------------- -18.0.1 +18.0.2 diff -Nru firefox-18.0.1+build1/debian/changelog firefox-18.0.2+build1/debian/changelog --- firefox-18.0.1+build1/debian/changelog 2013-01-16 22:43:33.000000000 +0000 +++ firefox-18.0.2+build1/debian/changelog 2013-02-01 18:23:14.000000000 +0000 @@ -1,3 +1,10 @@ +firefox (18.0.2+build1-0ubuntu0.12.04.1) precise-security; urgency=low + + * New upstream stable release (FIREFOX_18_0_2_BUILD1) + - see USN-1618-4 + + -- Chris Coulson Fri, 01 Feb 2013 18:22:01 +0000 + firefox (18.0.1+build1-0ubuntu0.12.04.1) precise-security; urgency=low * New upstream stable release (FIREFOX_18_0_1_BUILD1) diff -Nru firefox-18.0.1+build1/ipc/glue/GeckoChildProcessHost.cpp firefox-18.0.2+build1/ipc/glue/GeckoChildProcessHost.cpp --- firefox-18.0.1+build1/ipc/glue/GeckoChildProcessHost.cpp 2013-01-16 17:55:48.000000000 +0000 +++ firefox-18.0.2+build1/ipc/glue/GeckoChildProcessHost.cpp 2013-02-01 17:54:01.000000000 +0000 @@ -459,7 +459,7 @@ nsCString path; greDir->GetNativePath(path); # if defined(OS_LINUX) || defined(OS_BSD) -# if defined(MOZ_WIDGET_ANDROID) || defined(OS_BSD) +# if defined(MOZ_WIDGET_ANDROID) path += "/lib"; # endif // MOZ_WIDGET_ANDROID const char *ld_library_path = PR_GetEnv("LD_LIBRARY_PATH"); diff -Nru firefox-18.0.1+build1/js/src/config/milestone.txt firefox-18.0.2+build1/js/src/config/milestone.txt --- firefox-18.0.1+build1/js/src/config/milestone.txt 2013-01-16 17:55:04.000000000 +0000 +++ firefox-18.0.2+build1/js/src/config/milestone.txt 2013-02-01 17:54:01.000000000 +0000 @@ -10,4 +10,4 @@ # hardcoded milestones in the tree from these two files. #-------------------------------------------------------- -18.0.1 +18.0.2 diff -Nru firefox-18.0.1+build1/js/src/ion/CodeGenerator.cpp firefox-18.0.2+build1/js/src/ion/CodeGenerator.cpp --- firefox-18.0.1+build1/js/src/ion/CodeGenerator.cpp 2013-01-16 17:55:05.000000000 +0000 +++ firefox-18.0.2+build1/js/src/ion/CodeGenerator.cpp 2013-02-01 17:54:01.000000000 +0000 @@ -2753,10 +2753,21 @@ masm.or32(Imm32(JSITER_ACTIVE), Address(niTemp, offsetof(NativeIterator, flags))); // Chain onto the active iterator stack. - masm.loadJSContext(temp1); - masm.loadPtr(Address(temp1, offsetof(JSContext, enumerators)), temp2); - masm.storePtr(temp2, Address(niTemp, offsetof(NativeIterator, next))); - masm.storePtr(output, Address(temp1, offsetof(JSContext, enumerators))); + masm.movePtr(ImmWord(GetIonContext()->compartment), temp1); + masm.loadPtr(Address(temp1, offsetof(JSCompartment, enumerators)), temp1); + + // ni->next = list + masm.storePtr(temp1, Address(niTemp, NativeIterator::offsetOfNext())); + + // ni->prev = list->prev + masm.loadPtr(Address(temp1, NativeIterator::offsetOfPrev()), temp2); + masm.storePtr(temp2, Address(niTemp, NativeIterator::offsetOfPrev())); + + // list->prev->next = ni + masm.storePtr(niTemp, Address(temp2, NativeIterator::offsetOfNext())); + + // list->prev = ni + masm.storePtr(niTemp, Address(temp1, NativeIterator::offsetOfPrev())); masm.bind(ool->rejoin()); return true; @@ -2838,6 +2849,7 @@ const Register obj = ToRegister(lir->object()); const Register temp1 = ToRegister(lir->temp1()); const Register temp2 = ToRegister(lir->temp2()); + const Register temp3 = ToRegister(lir->temp3()); typedef bool (*pf)(JSContext *, HandleObject); static const VMFunction Info = FunctionInfo(CloseIterator); @@ -2858,10 +2870,17 @@ masm.loadPtr(Address(temp1, offsetof(NativeIterator, props_array)), temp2); masm.storePtr(temp2, Address(temp1, offsetof(NativeIterator, props_cursor))); - // Advance enumerators list. - masm.loadJSContext(temp2); - masm.loadPtr(Address(temp1, offsetof(NativeIterator, next)), temp1); - masm.storePtr(temp1, Address(temp2, offsetof(JSContext, enumerators))); + // Unlink from the iterator list. + const Register next = temp2; + const Register prev = temp3; + masm.loadPtr(Address(temp1, NativeIterator::offsetOfNext()), next); + masm.loadPtr(Address(temp1, NativeIterator::offsetOfPrev()), prev); + masm.storePtr(prev, Address(next, NativeIterator::offsetOfPrev())); + masm.storePtr(next, Address(prev, NativeIterator::offsetOfNext())); +#ifdef DEBUG + masm.storePtr(ImmWord(uintptr_t(0)), Address(temp1, NativeIterator::offsetOfNext())); + masm.storePtr(ImmWord(uintptr_t(0)), Address(temp1, NativeIterator::offsetOfPrev())); +#endif masm.bind(ool->rejoin()); return true; diff -Nru firefox-18.0.1+build1/js/src/ion/LIR-Common.h firefox-18.0.2+build1/js/src/ion/LIR-Common.h --- firefox-18.0.1+build1/js/src/ion/LIR-Common.h 2013-01-16 17:55:05.000000000 +0000 +++ firefox-18.0.2+build1/js/src/ion/LIR-Common.h 2013-02-01 17:54:01.000000000 +0000 @@ -2913,16 +2913,17 @@ } }; -class LIteratorEnd : public LInstructionHelper<0, 1, 2> +class LIteratorEnd : public LInstructionHelper<0, 1, 3> { public: LIR_HEADER(IteratorEnd); LIteratorEnd(const LAllocation &iterator, const LDefinition &temp1, - const LDefinition &temp2) { + const LDefinition &temp2, const LDefinition &temp3) { setOperand(0, iterator); setTemp(0, temp1); setTemp(1, temp2); + setTemp(2, temp3); } const LAllocation *object() { return getOperand(0); @@ -2933,6 +2934,9 @@ const LDefinition *temp2() { return getTemp(1); } + const LDefinition *temp3() { + return getTemp(2); + } MIteratorEnd *mir() const { return mir_->toIteratorEnd(); } diff -Nru firefox-18.0.1+build1/js/src/ion/Lowering.cpp firefox-18.0.2+build1/js/src/ion/Lowering.cpp --- firefox-18.0.1+build1/js/src/ion/Lowering.cpp 2013-01-16 17:55:05.000000000 +0000 +++ firefox-18.0.2+build1/js/src/ion/Lowering.cpp 2013-02-01 17:54:01.000000000 +0000 @@ -1793,7 +1793,7 @@ bool LIRGenerator::visitIteratorEnd(MIteratorEnd *ins) { - LIteratorEnd *lir = new LIteratorEnd(useRegister(ins->iterator()), temp(), temp()); + LIteratorEnd *lir = new LIteratorEnd(useRegister(ins->iterator()), temp(), temp(), temp()); return add(lir, ins) && assignSafepoint(lir, ins); } diff -Nru firefox-18.0.1+build1/js/src/jscntxt.cpp firefox-18.0.2+build1/js/src/jscntxt.cpp --- firefox-18.0.1+build1/js/src/jscntxt.cpp 2013-01-16 17:55:06.000000000 +0000 +++ firefox-18.0.2+build1/js/src/jscntxt.cpp 2013-02-01 17:54:02.000000000 +0000 @@ -397,8 +397,6 @@ JSRuntime *rt = cx->runtime; JS_AbortIfWrongThread(rt); - JS_ASSERT(!cx->enumerators); - #ifdef JS_THREADSAFE JS_ASSERT(cx->outstandingRequests == 0); #endif @@ -1211,7 +1209,6 @@ #ifdef MOZ_TRACE_JSCALLS functionCallback(NULL), #endif - enumerators(NULL), innermostGenerator_(NULL), #ifdef DEBUG stackIterAssertionEnabled(true), diff -Nru firefox-18.0.1+build1/js/src/jscntxt.h firefox-18.0.2+build1/js/src/jscntxt.h --- firefox-18.0.1+build1/js/src/jscntxt.h 2013-01-16 17:55:06.000000000 +0000 +++ firefox-18.0.2+build1/js/src/jscntxt.h 2013-02-01 17:54:02.000000000 +0000 @@ -1497,9 +1497,6 @@ DSTOffsetCache dstOffsetCache; - /* List of currently active non-escaping enumerators (for-in). */ - js::PropertyIteratorObject *enumerators; - private: /* Innermost-executing generator or null if no generator are executing. */ JSGenerator *innermostGenerator_; diff -Nru firefox-18.0.1+build1/js/src/jscompartment.cpp firefox-18.0.2+build1/js/src/jscompartment.cpp --- firefox-18.0.1+build1/js/src/jscompartment.cpp 2013-01-16 17:55:06.000000000 +0000 +++ firefox-18.0.2+build1/js/src/jscompartment.cpp 2013-02-01 17:54:02.000000000 +0000 @@ -74,7 +74,8 @@ debugModeBits(rt->debugMode ? DebugFromC : 0), watchpointMap(NULL), scriptCountsMap(NULL), - debugScriptMap(NULL) + debugScriptMap(NULL), + enumerators(NULL) #ifdef JS_ION , ionCompartment_(NULL) #endif @@ -91,6 +92,7 @@ js_delete(watchpointMap); js_delete(scriptCountsMap); js_delete(debugScriptMap); + js_free(enumerators); } bool @@ -130,6 +132,10 @@ } #endif + enumerators = NativeIterator::allocateSentinel(cx); + if (!enumerators) + return false; + return debuggees.init(); } @@ -627,6 +633,15 @@ } } + NativeIterator *ni = enumerators->next(); + while (ni != enumerators) { + JSObject *iterObj = ni->iterObj(); + NativeIterator *next = ni->next(); + if (JS_IsAboutToBeFinalized(iterObj)) + ni->unlink(); + ni = next; + } + active = false; } diff -Nru firefox-18.0.1+build1/js/src/jscompartment.h firefox-18.0.2+build1/js/src/jscompartment.h --- firefox-18.0.1+build1/js/src/jscompartment.h 2013-01-16 17:55:06.000000000 +0000 +++ firefox-18.0.2+build1/js/src/jscompartment.h 2013-02-01 17:54:02.000000000 +0000 @@ -26,6 +26,8 @@ class IonCompartment; } +struct NativeIterator; + /* * A single-entry cache for some base-10 double-to-string conversions. This * helps date-format-xparb.js. It also avoids skewing the results for @@ -444,6 +446,12 @@ js::DebugScriptMap *debugScriptMap; + /* + * List of potentially active iterators that may need deleted property + * suppression. + */ + js::NativeIterator *enumerators; + #ifdef JS_ION private: js::ion::IonCompartment *ionCompartment_; diff -Nru firefox-18.0.1+build1/js/src/jsinterp.cpp firefox-18.0.2+build1/js/src/jsinterp.cpp --- firefox-18.0.1+build1/js/src/jsinterp.cpp 2013-01-16 17:55:06.000000000 +0000 +++ firefox-18.0.2+build1/js/src/jsinterp.cpp 2013-02-01 17:54:02.000000000 +0000 @@ -279,13 +279,11 @@ struct CheckStackBalance { JSContext *cx; StackFrame *fp; - RootedObject enumerators; CheckStackBalance(JSContext *cx) - : cx(cx), fp(cx->fp()), enumerators(cx, cx->enumerators) + : cx(cx), fp(cx->fp()) {} ~CheckStackBalance() { JS_ASSERT(fp == cx->fp()); - JS_ASSERT_IF(!fp->isGeneratorFrame(), enumerators == cx->enumerators); } } check(cx); #endif diff -Nru firefox-18.0.1+build1/js/src/jsiter.cpp firefox-18.0.2+build1/js/src/jsiter.cpp --- firefox-18.0.1+build1/js/src/jsiter.cpp 2013-01-16 17:55:06.000000000 +0000 +++ firefox-18.0.2+build1/js/src/jsiter.cpp 2013-02-01 17:54:02.000000000 +0000 @@ -445,13 +445,30 @@ ni->props_array[i].init(str); } } + ni->next_ = NULL; + ni->prev_ = NULL; + return ni; +} + +NativeIterator * +NativeIterator::allocateSentinel(JSContext *cx) +{ + NativeIterator *ni = (NativeIterator *)js_malloc(sizeof(NativeIterator)); + if (!ni) + return NULL; + + PodZero(ni); + + ni->next_ = ni; + ni->prev_ = ni; return ni; } inline void -NativeIterator::init(RawObject obj, unsigned flags, uint32_t slength, uint32_t key) +NativeIterator::init(RawObject obj, RawObject iterObj, unsigned flags, uint32_t slength, uint32_t key) { this->obj.init(obj); + this->iterObj_ = iterObj; this->flags = flags; this->shapes_array = (Shape **) this->props_end; this->shapes_length = slength; @@ -463,8 +480,7 @@ { /* Register non-escaping native enumerators (for-in) with the current context. */ if (ni->flags & JSITER_ENUMERATE) { - ni->next = cx->enumerators; - cx->enumerators = iterobj; + ni->link(cx->compartment->enumerators); JS_ASSERT(!(ni->flags & JSITER_ACTIVE)); ni->flags |= JSITER_ACTIVE; @@ -490,7 +506,7 @@ NativeIterator *ni = NativeIterator::allocateIterator(cx, slength, keys); if (!ni) return false; - ni->init(obj, flags, slength, key); + ni->init(obj, iterobj, flags, slength, key); if (slength) { /* @@ -544,7 +560,7 @@ NativeIterator *ni = NativeIterator::allocateIterator(cx, 0, keys); if (!ni) return false; - ni->init(obj, flags, 0, 0); + ni->init(obj, iterobj, flags, 0, 0); iterobj->setNativeIterator(ni); vp.setObject(*iterobj); @@ -1022,8 +1038,7 @@ NativeIterator *ni = obj->asPropertyIterator().getNativeIterator(); if (ni->flags & JSITER_ENUMERATE) { - JS_ASSERT(cx->enumerators == obj); - cx->enumerators = ni->next; + ni->unlink(); JS_ASSERT(ni->flags & JSITER_ACTIVE); ni->flags &= ~JSITER_ACTIVE; @@ -1059,10 +1074,8 @@ { if (obj->isPropertyIterator()) { NativeIterator *ni = obj->asPropertyIterator().getNativeIterator(); - if (ni->flags & JSITER_ENUMERATE) { - JS_ASSERT(cx->enumerators == obj); - cx->enumerators = ni->next; - } + if (ni->flags & JSITER_ENUMERATE) + ni->unlink(); } } @@ -1087,10 +1100,11 @@ static bool SuppressDeletedPropertyHelper(JSContext *cx, HandleObject obj, StringPredicate predicate) { - PropertyIteratorObject *iterobj = cx->enumerators; - while (iterobj) { + NativeIterator *enumeratorList = cx->compartment->enumerators; + NativeIterator *ni = enumeratorList->next(); + + while (ni != enumeratorList) { again: - NativeIterator *ni = iterobj->getNativeIterator(); /* This only works for identified surpressed keys, not values. */ if (ni->isKeyIter() && ni->obj == obj && ni->props_cursor < ni->props_end) { /* Check whether id is still to come. */ @@ -1098,6 +1112,12 @@ HeapPtr *props_end = ni->end(); for (HeapPtr *idp = props_cursor; idp < props_end; ++idp) { if (predicate(*idp)) { + /* + * Root the iterobj. This loop can GC, so we want to make sure that if + * the GC removes any elements from the list, it won't remove this one. + */ + AutoObjectRooter iterRoot(cx, ni->iterObj()); + /* * Check whether another property along the prototype chain * became visible as a result of this deletion. @@ -1160,7 +1180,7 @@ } } } - iterobj = ni->next; + ni = ni->next(); } return true; } @@ -1478,7 +1498,6 @@ /* Initialize JSGenerator. */ gen->obj.init(obj); gen->state = JSGEN_NEWBORN; - gen->enumerators = NULL; gen->fp = genfp; gen->prevGenerator = NULL; @@ -1572,13 +1591,9 @@ gen->regs = cx->regs(); cx->enterGenerator(gen); /* OOM check above. */ - PropertyIteratorObject *enumerators = cx->enumerators; - cx->enumerators = gen->enumerators; ok = RunScript(cx, fp->script(), fp); - gen->enumerators = cx->enumerators; - cx->enumerators = enumerators; cx->leaveGenerator(gen); } @@ -1790,7 +1805,7 @@ NativeIterator *ni = NativeIterator::allocateIterator(cx, 0, blank); if (!ni) return false; - ni->init(NULL, 0 /* flags */, 0, 0); + ni->init(NULL, NULL, 0 /* flags */, 0, 0); iteratorProto->asPropertyIterator().setNativeIterator(ni); diff -Nru firefox-18.0.1+build1/js/src/jsiter.h firefox-18.0.2+build1/js/src/jsiter.h --- firefox-18.0.1+build1/js/src/jsiter.h 2013-01-16 17:55:06.000000000 +0000 +++ firefox-18.0.2+build1/js/src/jsiter.h 2013-02-01 17:54:02.000000000 +0000 @@ -30,7 +30,8 @@ struct NativeIterator { - HeapPtrObject obj; + HeapPtrObject obj; // Object being iterated. + JSObject *iterObj_; // Internal iterator object. HeapPtr *props_array; HeapPtr *props_cursor; HeapPtr *props_end; @@ -38,9 +39,16 @@ uint32_t shapes_length; uint32_t shapes_key; uint32_t flags; - PropertyIteratorObject *next; /* Forms cx->enumerators list, garbage otherwise. */ - bool isKeyIter() const { return (flags & JSITER_FOREACH) == 0; } + private: + /* While in compartment->enumerators, these form a doubly linked list. */ + NativeIterator *next_; + NativeIterator *prev_; + + public: + bool isKeyIter() const { + return (flags & JSITER_FOREACH) == 0; + } inline HeapPtr *begin() const { return props_array; @@ -54,20 +62,57 @@ return end() - begin(); } + JSObject *iterObj() const { + return iterObj_; + } HeapPtr *current() const { JS_ASSERT(props_cursor < props_end); return props_cursor; } + NativeIterator *next() { + return next_; + } + + static inline size_t offsetOfNext() { + return offsetof(NativeIterator, next_); + } + static inline size_t offsetOfPrev() { + return offsetof(NativeIterator, prev_); + } + void incCursor() { props_cursor = props_cursor + 1; } + void link(NativeIterator *other) { + /* A NativeIterator cannot appear in the enumerator list twice. */ + JS_ASSERT(!next_ && !prev_); + JS_ASSERT(flags & JSITER_ENUMERATE); + + this->next_ = other; + this->prev_ = other->prev_; + other->prev_->next_ = this; + other->prev_ = this; + } + void unlink() { + JS_ASSERT(flags & JSITER_ENUMERATE); + next_->prev_ = prev_; + prev_->next_ = next_; + next_ = NULL; + prev_ = NULL; + } + + static NativeIterator *allocateSentinel(JSContext *cx); static NativeIterator *allocateIterator(JSContext *cx, uint32_t slength, const js::AutoIdVector &props); - void init(RawObject obj, unsigned flags, uint32_t slength, uint32_t key); + void init(RawObject obj, RawObject iterObj, unsigned flags, uint32_t slength, uint32_t key); void mark(JSTracer *trc); + + static void destroy(NativeIterator *iter) { + js_free(iter); + } }; class PropertyIteratorObject : public JSObject @@ -297,7 +342,6 @@ js::HeapPtrObject obj; JSGeneratorState state; js::FrameRegs regs; - js::PropertyIteratorObject *enumerators; JSGenerator *prevGenerator; js::StackFrame *fp; js::HeapValue stackSnapshot[1]; diff -Nru firefox-18.0.1+build1/js/src/methodjit/Compiler.cpp firefox-18.0.2+build1/js/src/methodjit/Compiler.cpp --- firefox-18.0.1+build1/js/src/methodjit/Compiler.cpp 2013-01-16 17:55:06.000000000 +0000 +++ firefox-18.0.2+build1/js/src/methodjit/Compiler.cpp 2013-02-01 17:54:02.000000000 +0000 @@ -6273,10 +6273,21 @@ masm.store32(T1, flagsAddr); /* Chain onto the active iterator stack. */ - masm.loadPtr(FrameAddress(offsetof(VMFrame, cx)), T1); - masm.loadPtr(Address(T1, offsetof(JSContext, enumerators)), T2); - masm.storePtr(T2, Address(nireg, offsetof(NativeIterator, next))); - masm.storePtr(ioreg, Address(T1, offsetof(JSContext, enumerators))); + masm.move(ImmPtr(cx->compartment), T1); + masm.loadPtr(Address(T1, offsetof(JSCompartment, enumerators)), T1); + + /* ni->next = list */ + masm.storePtr(T1, Address(nireg, NativeIterator::offsetOfNext())); + + /* ni->prev = list->prev */ + masm.loadPtr(Address(T1, NativeIterator::offsetOfPrev()), T2); + masm.storePtr(T2, Address(nireg, NativeIterator::offsetOfPrev())); + + /* list->prev->next = ni */ + masm.storePtr(nireg, Address(T2, NativeIterator::offsetOfNext())); + + /* list->prev = ni */ + masm.storePtr(nireg, Address(T1, NativeIterator::offsetOfPrev())); frame.freeReg(nireg); frame.freeReg(T1); @@ -6427,13 +6438,22 @@ masm.loadPtr(Address(T1, offsetof(NativeIterator, props_array)), T2); masm.storePtr(T2, Address(T1, offsetof(NativeIterator, props_cursor))); - /* Advance enumerators list. */ - masm.loadPtr(FrameAddress(offsetof(VMFrame, cx)), T2); - masm.loadPtr(Address(T1, offsetof(NativeIterator, next)), T1); - masm.storePtr(T1, Address(T2, offsetof(JSContext, enumerators))); + /* Unlink from the iterator list. */ + RegisterID prev = T2; + RegisterID next = frame.allocReg(); + + masm.loadPtr(Address(T1, NativeIterator::offsetOfNext()), next); + masm.loadPtr(Address(T1, NativeIterator::offsetOfPrev()), prev); + masm.storePtr(prev, Address(next, NativeIterator::offsetOfPrev())); + masm.storePtr(next, Address(prev, NativeIterator::offsetOfNext())); +#ifdef DEBUG + masm.storePtr(ImmPtr(NULL), Address(T1, NativeIterator::offsetOfNext())); + masm.storePtr(ImmPtr(NULL), Address(T1, NativeIterator::offsetOfPrev())); +#endif frame.freeReg(T1); frame.freeReg(T2); + frame.freeReg(next); stubcc.leave(); OOL_STUBCALL(stubs::EndIter, REJOIN_FALLTHROUGH); diff -Nru firefox-18.0.1+build1/l10n/changesets firefox-18.0.2+build1/l10n/changesets --- firefox-18.0.1+build1/l10n/changesets 2013-01-16 18:04:17.000000000 +0000 +++ firefox-18.0.2+build1/l10n/changesets 2013-02-01 18:02:41.000000000 +0000 @@ -1,89 +1,89 @@ -ach 66:5440426d1861 -af 325:4a86dd956b11 -ak 273:846d5e1ae843 -ar 844:d936fe095196 -as 237:f5e92c5eb28e -ast 681:928f2cd2d978 -be 956:e84875286597 -bg 513:884c26bde4c9 -bn-BD 481:d8702f224fc6 -bn-IN 328:6a67f918bd5c -br 571:f6c483d531e4 -bs 288:708fdd6c0516 -ca 1451:c13806036318 -cs 2211:866fb736ca49 -csb 213:02879e34ff44 -cy 336:8d5bfcbade7f -da 998:340068f3b3bf -de 3317:f93169689291 -el 773:fde93c33e4e0 -en-GB 907:4b992dd738cd -en-ZA 261:18599fd40544 -eo 511:5a2a2f5245c4 -es-AR 1546:b9d5f7f3c99c -es-CL 433:c08e4a1b500c -es-ES 1955:62dc50960f07 -es-MX 409:523f18c59c4b -et 1005:734cc10a2559 -eu 794:578c6ce7bf5a -fa 586:730ad00b7ee8 -ff 81:41fb0464f29c -fi 1205:0e349b38aa32 -fr 4150:f3944ce7f1f7 -fy-NL 1432:0d2a485c9b3a -ga-IE 934:032cab1d929e -gd 844:7fa007c05211 -gl 1083:2df5ffdbdca7 -gu-IN 604:3269fdac5a59 -he 863:7ca846ed6b94 -hi-IN 428:3cf25c94d1de -hr 1133:423ba573f442 -hu 1081:3eb7c38fde2e -hy-AM 459:d5fe31f142bf -id 876:07d350791005 -is 677:1928cc756812 -it 2580:f34138fb297a -ja 1196:a4654182ff67 -ja-JP-mac 1021:62c0e6ac3ee0 -kk 367:4ec02507f366 -km 120:e2e62d396613 -kn 395:0eed6ed2b9ad -ko 1049:b6761fb94729 -ku 301:4232c5bf2282 -lg 273:31ba296be1d4 -lij 295:b40c19f4532d -lt 1866:1ded65264276 -lv 451:77a2e7b4bc21 -mai 313:10a34b7a3075 -mk 352:a11924c5dcb4 -ml 464:4128200c0204 -mr 390:da80b9ef6e02 -nb-NO 1614:efa081b3c151 -nl 3324:ed95d790ab07 -nn-NO 911:85c5522ac527 -nso 262:fa6d4060b637 -or 335:86d3d6a16b40 -pa-IN 1014:650b7df6185e -pl 4067:bc72e1696295 -pt-BR 1057:e1253338357d -pt-PT 2082:5cfe9cd4bfee -rm 693:cdf62db4478f -ro 723:77e665571ed2 -ru 2062:2c52205bf69f -si 785:397ebdf1ccc5 -sk 1112:264fad7ef482 -sl 957:7ea0d507c7e0 -son 279:16e681783631 -sq 1111:71b08d168f64 -sr 447:51a22c5a4c54 -sv-SE 2588:5b25a0df5d9d -ta 271:a353d7252b31 -ta-LK 497:f48bc0dd0d55 -te 328:65f9f2ec0864 -th 543:fbe8cd554942 -tr 1036:faa8d97104cd -uk 1569:ecae9cd9d584 -vi 496:8bbeae249e45 -zh-CN 1286:2db5e8f93ebe -zh-TW 1263:d4deb73c4458 -zu 243:c08195350056 +ach 67:11f6d1fe2c10 +af 326:b2d53b010c8a +ak 274:eda5c9c215d4 +ar 845:ac60a1f626cc +as 238:2038628dc36e +ast 682:a2d9d42f792a +be 959:9873bc8c614f +bg 514:a7f57eda8ed7 +bn-BD 482:22530e054990 +bn-IN 329:88e4028d1a2f +br 572:91989a3de488 +bs 289:806fdd88114c +ca 1456:1b8960b3a6c4 +cs 2214:2c218ea6434f +csb 214:0a7fb80026da +cy 337:a9694cf16cbb +da 999:64aa8f190572 +de 3320:f9587b1ae214 +el 774:ef982375e338 +en-GB 910:533e9e85d39b +en-ZA 262:ef50b6a03cfe +eo 512:fc47703cf657 +es-AR 1549:3359423d0543 +es-CL 434:7abd8b5fa42a +es-ES 1958:4f32d2d93da6 +es-MX 410:fce845da15a0 +et 1006:c6ccc731b7b0 +eu 795:ae28682f47f1 +fa 587:33d9b9544b8f +ff 82:1a6d2eafb177 +fi 1208:3d2c38266c9a +fr 4153:a8d4ab3386a3 +fy-NL 1433:665ea352061a +ga-IE 935:fc960ef408a8 +gd 845:8ad311afe0d4 +gl 1086:41216f1e60e2 +gu-IN 605:305f4507fd2a +he 864:136d6b0965ce +hi-IN 429:248d2e5590c3 +hr 1134:1f579ed5cb9a +hu 1084:dd5e58c78bf5 +hy-AM 460:78bbf78e5eb2 +id 877:ada4f8049425 +is 678:aeaa6251e963 +it 2583:cba636a5653d +ja 1199:4aac05d0b096 +ja-JP-mac 1024:bb359802197e +kk 368:920d64e5ccc1 +km 121:124f5c3ecd0b +kn 396:15c4b42bc5fc +ko 1050:dddcbfd6be7f +ku 302:e6a25872feb8 +lg 274:14853333ec00 +lij 296:b39443b8861b +lt 1869:31fe8afe0450 +lv 452:9241944cbf9c +mai 314:54e84cfaf7df +mk 353:280e1dbb12ad +ml 465:9b1f4270a14a +mr 391:d5804a652735 +nb-NO 1617:56b3169a7065 +nl 3327:0ad395ba66ed +nn-NO 912:5efe6fcaff57 +nso 263:8c2624fe7366 +or 336:4436e1e5fc74 +pa-IN 1015:2d92c24e9b2a +pl 4070:9c10b70b47c1 +pt-BR 1058:aaf54b131453 +pt-PT 2085:3e94fafe79f3 +rm 694:69ca948fb6a0 +ro 724:98db332c5168 +ru 2065:a149470429a5 +si 786:ee5cd5cb8b93 +sk 1115:e53645b48700 +sl 958:b12f61268e34 +son 280:edc375bb1d87 +sq 1112:8d31d365294c +sr 448:92ca73ac5859 +sv-SE 2591:00dc8a9e01bd +ta 272:3769bb25f63e +ta-LK 498:af2d8a406a8e +te 329:e5e24570de5c +th 544:cf8a5bee7e5f +tr 1039:a173404c156e +uk 1572:7bd30a991519 +vi 497:c12f1af9e295 +zh-CN 1289:51c1ded09e50 +zh-TW 1266:776877689e89 +zu 244:a1de574933d7 diff -Nru firefox-18.0.1+build1/toolkit/mozapps/installer/packager.mk firefox-18.0.2+build1/toolkit/mozapps/installer/packager.mk --- firefox-18.0.1+build1/toolkit/mozapps/installer/packager.mk 2013-01-16 17:55:40.000000000 +0000 +++ firefox-18.0.2+build1/toolkit/mozapps/installer/packager.mk 2013-02-01 17:54:15.000000000 +0000 @@ -247,7 +247,11 @@ JAVA_CLASSPATH = $(ANDROID_SDK)/android.jar include $(MOZILLA_DIR)/config/android-common.mk +ifdef MOZ_SIGN_CMD +JARSIGNER := $(MOZ_SIGN_CMD) -f jar +else JARSIGNER ?= echo +endif DIST_FILES =