diff --git a/browser/base/content/test/general/browser_remoteTroubleshoot.js b/browser/base/content/test/general/browser_remoteTroubleshoot.js index 5c939dbd0a3f..5e3cd752cce8 100644 --- a/browser/base/content/test/general/browser_remoteTroubleshoot.js +++ b/browser/base/content/test/general/browser_remoteTroubleshoot.js @@ -37,8 +37,8 @@ function promiseNewChannelResponse(uri) { add_task(function*() { // We haven't set a permission yet - so even the "good" URI should fail. let got = yield promiseNewChannelResponse(TEST_URI_GOOD); - // Should have no data. - Assert.ok(got.message === undefined, "should have failed to get any data"); + // Should return an error. + Assert.ok(got.message.errno === 2, "should have failed with errno 2, no such channel"); // Add a permission manager entry for our URI. Services.perms.add(TEST_URI_GOOD, @@ -76,9 +76,9 @@ add_task(function*() { Assert.ok(!got.message.modifiedPreferences, "should not have a modifiedPreferences key"); Assert.ok(!got.message.crashes, "should not have crash info"); - // Now a http:// URI - should get nothing even with the permission setup. + // Now a http:// URI - should receive an error got = yield promiseNewChannelResponse(TEST_URI_BAD); - Assert.ok(got.message === undefined, "should have failed to get any data"); + Assert.ok(got.message.errno === 2, "should have failed with errno 2, no such channel"); // Check that the page can send an object as well if it's in the whitelist let webchannelWhitelistPref = "webchannel.allowObject.urlWhitelist"; diff --git a/browser/base/content/test/general/browser_web_channel.html b/browser/base/content/test/general/browser_web_channel.html index f117ccca2c08..f856de15a91f 100644 --- a/browser/base/content/test/general/browser_web_channel.html +++ b/browser/base/content/test/general/browser_web_channel.html @@ -36,6 +36,12 @@ case "object": test_object(); break; + case "error_thrown": + test_error_thrown(); + break; + case "error_invalid_channel": + test_error_invalid_channel(); + break; default: throw new Error(`INVALID TEST NAME ${testName}`); } @@ -172,6 +178,44 @@ window.dispatchEvent(stringMessage); } + function test_error_thrown() { + var event = new window.CustomEvent("WebChannelMessageToChrome", { + detail: JSON.stringify({ + id: "error", + message: { + command: "oops" + } + }) + }); + + // echo the response back to chrome - chrome will check it is the + // expected error. + window.addEventListener("WebChannelMessageToContent", function(e) { + echoEventToChannel(e, "echo"); + }, true); + + window.dispatchEvent(event); + } + + function test_error_invalid_channel() { + var event = new window.CustomEvent("WebChannelMessageToChrome", { + detail: JSON.stringify({ + id: "invalid-channel", + message: { + command: "oops" + } + }) + }); + + // echo the response back to chrome - chrome will check it is the + // expected error. + window.addEventListener("WebChannelMessageToContent", function(e) { + echoEventToChannel(e, "echo"); + }, true); + + window.dispatchEvent(event); + } + function echoEventToChannel(e, channelId) { var echoedEvent = new window.CustomEvent("WebChannelMessageToChrome", { detail: JSON.stringify({ diff --git a/browser/base/content/test/general/browser_web_channel.js b/browser/base/content/test/general/browser_web_channel.js index 37015c90694b..b90fe6ccb959 100644 --- a/browser/base/content/test/general/browser_web_channel.js +++ b/browser/base/content/test/general/browser_web_channel.js @@ -396,7 +396,68 @@ var gTests = [ channel.stopListening(); }); } - } + }, + { + desc: "WebChannel errors handling the message are delivered back to content", + run: function* () { + const ERRNO_UNKNOWN_ERROR = 999; // WebChannel.jsm doesn't export this. + + // The channel where we purposely fail responding to a command. + let channel = new WebChannel("error", Services.io.newURI(HTTP_PATH, null, null)); + // The channel where we see the response when the content sees the error + let echoChannel = new WebChannel("echo", Services.io.newURI(HTTP_PATH, null, null)); + + let testDonePromise = new Promise((resolve, reject) => { + // listen for the confirmation that content saw the error. + echoChannel.listen((id, message, sender) => { + is(id, "echo"); + is(message.error, "oh no"); + is(message.errno, ERRNO_UNKNOWN_ERROR); + resolve(); + }); + + // listen for a message telling us to simulate an error. + channel.listen((id, message, sender) => { + is(id, "error"); + is(message.command, "oops"); + throw new Error("oh no"); + }); + }); + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: HTTP_PATH + HTTP_ENDPOINT + "?error_thrown" + }, function* () { + yield testDonePromise; + channel.stopListening(); + echoChannel.stopListening(); + }); + } + }, + { + desc: "WebChannel errors due to an invalid channel are delivered back to content", + run: function* () { + const ERRNO_NO_SUCH_CHANNEL = 2; // WebChannel.jsm doesn't export this. + // The channel where we see the response when the content sees the error + let echoChannel = new WebChannel("echo", Services.io.newURI(HTTP_PATH, null, null)); + + let testDonePromise = new Promise((resolve, reject) => { + // listen for the confirmation that content saw the error. + echoChannel.listen((id, message, sender) => { + is(id, "echo"); + is(message.error, "No Such Channel"); + is(message.errno, ERRNO_NO_SUCH_CHANNEL); + resolve(); + }); + }); + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: HTTP_PATH + HTTP_ENDPOINT + "?error_invalid_channel" + }, function* () { + yield testDonePromise; + echoChannel.stopListening(); + }); + } + }, ]; // gTests function test() { diff --git a/browser/themes/shared/aboutNetError.css b/browser/themes/shared/aboutNetError.css index 7141c0cec9d9..7c3a6d02ba29 100644 --- a/browser/themes/shared/aboutNetError.css +++ b/browser/themes/shared/aboutNetError.css @@ -110,10 +110,6 @@ span#hostname { #automaticallyReportInFuture { cursor: pointer; - display: inline-block; - padding-inline-start: 2.3em; - text-indent: -2.3em; - line-height: 16px } #errorCode:not([href]) { diff --git a/browser/themes/shared/downloads/allDownloadsViewOverlay.inc.css b/browser/themes/shared/downloads/allDownloadsViewOverlay.inc.css index 30793cfff406..e36c20348e15 100644 --- a/browser/themes/shared/downloads/allDownloadsViewOverlay.inc.css +++ b/browser/themes/shared/downloads/allDownloadsViewOverlay.inc.css @@ -96,7 +96,6 @@ -moz-appearance: none; padding: 2px !important; border-radius: 50%; - color: graytext; } .downloadButton > .button-box > .button-icon { @@ -120,10 +119,6 @@ background-color: -moz-fieldtext; } -@itemFocused@ > .downloadButtonArea > .downloadButton > .button-box { - color: inherit; -} - @itemFocused@ > .downloadButtonArea > .downloadButton:hover > .button-box { background-color: HighlightText; color: Highlight; diff --git a/browser/themes/shared/downloads/downloads.inc.css b/browser/themes/shared/downloads/downloads.inc.css index c95f071885d2..9ffecdd243d1 100644 --- a/browser/themes/shared/downloads/downloads.inc.css +++ b/browser/themes/shared/downloads/downloads.inc.css @@ -260,7 +260,7 @@ richlistitem[type="download"] > .downloadMainArea { border: none; background: transparent; padding: 8px; - color: graytext; + color: inherit; } .downloadButton > .button-box > .button-icon { @@ -307,10 +307,6 @@ richlistitem[type="download"] > .downloadMainArea { color: white; } -@item@[verdict="Malware"]:hover > .downloadButtonArea > .downloadButton { - color: inherit; -} - /*** Button icons ***/ .downloadIconCancel > .button-box > .button-icon { diff --git a/devtools/client/inspector/markup/test/browser_markup_html_edit_01.js b/devtools/client/inspector/markup/test/browser_markup_html_edit_01.js index 9679a5f47055..e4c271498a31 100644 --- a/devtools/client/inspector/markup/test/browser_markup_html_edit_01.js +++ b/devtools/client/inspector/markup/test/browser_markup_html_edit_01.js @@ -6,6 +6,8 @@ // Test outerHTML edition via the markup-view +requestLongerTimeout(2); + loadHelperScript("helper_outerhtml_test_runner.js"); const TEST_DATA = [{ diff --git a/devtools/client/preferences/devtools.js b/devtools/client/preferences/devtools.js index 4bcea2ab42ab..4178ce77f8bc 100644 --- a/devtools/client/preferences/devtools.js +++ b/devtools/client/preferences/devtools.js @@ -70,6 +70,9 @@ pref("devtools.fontinspector.enabled", true); // Enable the Layout View pref("devtools.layoutview.enabled", false); +// Grid highlighter preferences +pref("devtools.gridinspector.showInfiniteLines", false); + // By how many times eyedropper will magnify pixels pref("devtools.eyedropper.zoom", 6); diff --git a/devtools/client/responsive.html/browser/tunnel.js b/devtools/client/responsive.html/browser/tunnel.js index 26f03d46c8a4..024ee5f7a82f 100644 --- a/devtools/client/responsive.html/browser/tunnel.js +++ b/devtools/client/responsive.html/browser/tunnel.js @@ -314,7 +314,8 @@ function copyPermanentKey(outer, inner) { // what SessionStore uses to identify each browser. let outerMM = outer[FRAME_LOADER].messageManager; let onHistoryEntry = message => { - let history = message.data.data.history; + let data = message.data.data; + let history = data.history || data.historychange; if (!history || !history.entries) { // Wait for a message that contains history data return; diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp index 8e003825260e..1f552954a278 100644 --- a/dom/base/Element.cpp +++ b/dom/base/Element.cpp @@ -1736,18 +1736,6 @@ Element::BindToTree(nsIDocument* aDocument, nsIContent* aParent, } } - // It would be cleanest to mark nodes as dirty when (a) they're created and - // (b) they're unbound from a tree. However, we can't easily do (a) right now, - // because IsStyledByServo() is not always easy to check at node creation time, - // and the bits have different meaning in the non-IsStyledByServo case. - // - // So for now, we just mark nodes as dirty when they're inserted into a - // document or shadow tree. - if (IsStyledByServo() && IsInComposedDoc()) { - MOZ_ASSERT(!HasServoData()); - SetIsDirtyForServo(); - } - // XXXbz script execution during binding can trigger some of these // postcondition asserts.... But we do want that, since things will // generally be quite broken when that happens. @@ -3922,3 +3910,12 @@ Element::UpdateIntersectionObservation(DOMIntersectionObserver* aObserver, int32 } return false; } + +void +Element::ClearServoData() { +#ifdef MOZ_STYLO + Servo_Element_ClearData(this); +#else + MOZ_CRASH("Accessing servo node data in non-stylo build"); +#endif +} diff --git a/dom/base/Element.h b/dom/base/Element.h index e1119dd92cfe..fee4fdc32c08 100644 --- a/dom/base/Element.h +++ b/dom/base/Element.h @@ -16,6 +16,7 @@ #include "mozilla/dom/FragmentOrElement.h" // for base class #include "nsChangeHint.h" // for enum #include "mozilla/EventStates.h" // for member +#include "mozilla/ServoTypes.h" #include "mozilla/dom/DirectionalityUtils.h" #include "nsIDOMElement.h" #include "nsILinkHandler.h" @@ -164,6 +165,14 @@ public: "Bad NodeType in aNodeInfo"); SetIsElement(); } + + ~Element() + { +#ifdef MOZ_STYLO + NS_ASSERTION(!HasServoData(), "expected ServoData to be cleared earlier"); +#endif + } + #endif // MOZILLA_INTERNAL_API NS_DECLARE_STATIC_IID_ACCESSOR(NS_ELEMENT_IID) @@ -391,6 +400,40 @@ public: Directionality GetComputedDirectionality() const; + inline Element* GetFlattenedTreeParentElement() const; + + bool HasDirtyDescendantsForServo() const + { + MOZ_ASSERT(IsStyledByServo()); + return HasFlag(NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO); + } + + void SetHasDirtyDescendantsForServo() { + MOZ_ASSERT(IsStyledByServo()); + SetFlags(NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO); + } + + void UnsetHasDirtyDescendantsForServo() { + MOZ_ASSERT(IsStyledByServo()); + UnsetFlags(NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO); + } + + inline void NoteDirtyDescendantsForServo(); + +#ifdef DEBUG + inline bool DirtyDescendantsBitIsPropagatedForServo(); +#endif + + bool HasServoData() { +#ifdef MOZ_STYLO + return !!mServoData.Get(); +#else + MOZ_CRASH("Accessing servo node data in non-stylo build"); +#endif + } + + void ClearServoData(); + protected: /** * Method to get the _intrinsic_ content state of this element. This is the @@ -1391,6 +1434,10 @@ private: // Data members EventStates mState; +#ifdef MOZ_STYLO + // Per-node data managed by Servo. + mozilla::ServoCell mServoData; +#endif }; class RemoveFromBindingManagerRunnable : public mozilla::Runnable @@ -1488,7 +1535,7 @@ inline const mozilla::dom::Element* nsINode::AsElement() const inline void nsINode::UnsetRestyleFlagsIfGecko() { - if (IsElement() && !IsStyledByServo()) { + if (IsElement() && !AsElement()->IsStyledByServo()) { UnsetFlags(ELEMENT_ALL_RESTYLE_FLAGS); } } diff --git a/dom/base/ElementInlines.h b/dom/base/ElementInlines.h index c68bd012ebfb..c6b2c2917923 100644 --- a/dom/base/ElementInlines.h +++ b/dom/base/ElementInlines.h @@ -8,6 +8,7 @@ #define mozilla_dom_ElementInlines_h #include "mozilla/dom/Element.h" +#include "nsIContentInlines.h" #include "nsIDocument.h" namespace mozilla { @@ -25,6 +26,46 @@ Element::UnregisterActivityObserver() OwnerDoc()->UnregisterActivityObserver(this); } +inline Element* +Element::GetFlattenedTreeParentElement() const +{ + nsINode* parentNode = GetFlattenedTreeParentNode(); + if MOZ_LIKELY(parentNode && parentNode->IsElement()) { + return parentNode->AsElement(); + } + + return nullptr; +} + +inline void +Element::NoteDirtyDescendantsForServo() +{ + Element* curr = this; + while (curr && !curr->HasDirtyDescendantsForServo()) { + curr->SetHasDirtyDescendantsForServo(); + curr = curr->GetFlattenedTreeParentElement(); + } + + MOZ_ASSERT(DirtyDescendantsBitIsPropagatedForServo()); +} + +#ifdef DEBUG +inline bool +Element::DirtyDescendantsBitIsPropagatedForServo() +{ + Element* curr = this; + while (curr) { + if (!curr->HasDirtyDescendantsForServo()) { + return false; + } + nsINode* parentNode = curr->GetParentNode(); + curr = curr->GetFlattenedTreeParentElement(); + MOZ_ASSERT_IF(!curr, parentNode == OwnerDoc()); + } + return true; +} +#endif + } // namespace dom } // namespace mozilla diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp index 487908a6a863..79d45402b6f2 100644 --- a/dom/base/FragmentOrElement.cpp +++ b/dom/base/FragmentOrElement.cpp @@ -2344,51 +2344,3 @@ FragmentOrElement::SetIsElementInStyleScopeFlagOnShadowTree(bool aInStyleScope) shadowRoot = shadowRoot->GetOlderShadowRoot(); } } - -#ifdef DEBUG -static void -AssertDirtyDescendantsBitPropagated(nsINode* aNode) -{ - MOZ_ASSERT(aNode->HasDirtyDescendantsForServo()); - nsINode* parent = aNode->GetFlattenedTreeParentNode(); - if (!parent->IsContent()) { - MOZ_ASSERT(parent == aNode->OwnerDoc()); - MOZ_ASSERT(parent->HasDirtyDescendantsForServo()); - } else { - AssertDirtyDescendantsBitPropagated(parent); - } -} -#else -static void AssertDirtyDescendantsBitPropagated(nsINode* aNode) {} -#endif - -void -nsIContent::MarkAncestorsAsHavingDirtyDescendantsForServo() -{ - MOZ_ASSERT(IsInComposedDoc()); - - // Get the parent in the flattened tree. - nsINode* parent = GetFlattenedTreeParentNode(); - - // Loop until we hit a base case. - while (true) { - - // Base case: the document. - if (!parent->IsContent()) { - MOZ_ASSERT(parent == OwnerDoc()); - parent->SetHasDirtyDescendantsForServo(); - return; - } - - // Base case: the parent is already marked, and therefore - // so are all its ancestors. - if (parent->HasDirtyDescendantsForServo()) { - AssertDirtyDescendantsBitPropagated(parent); - return; - } - - // Mark the parent and iterate. - parent->SetHasDirtyDescendantsForServo(); - parent = parent->GetFlattenedTreeParentNode(); - } -} diff --git a/dom/base/nsGenericDOMDataNode.cpp b/dom/base/nsGenericDOMDataNode.cpp index 13bec9b234d5..c36c589b207d 100644 --- a/dom/base/nsGenericDOMDataNode.cpp +++ b/dom/base/nsGenericDOMDataNode.cpp @@ -552,18 +552,6 @@ nsGenericDOMDataNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent, UpdateEditableState(false); - // It would be cleanest to mark nodes as dirty when (a) they're created and - // (b) they're unbound from a tree. However, we can't easily do (a) right now, - // because IsStyledByServo() is not always easy to check at node creation time, - // and the bits have different meaning in the non-IsStyledByServo case. - // - // So for now, we just mark nodes as dirty when they're inserted into a - // document or shadow tree. - if (IsStyledByServo() && IsInComposedDoc()) { - MOZ_ASSERT(!HasServoData()); - SetIsDirtyForServo(); - } - NS_POSTCONDITION(aDocument == GetUncomposedDoc(), "Bound to wrong document"); NS_POSTCONDITION(aParent == GetParent(), "Bound to wrong parent"); NS_POSTCONDITION(aBindingParent == GetBindingParent(), @@ -595,16 +583,6 @@ nsGenericDOMDataNode::UnbindFromTree(bool aDeep, bool aNullParent) } ClearInDocument(); - // Computed styled data isn't useful for detached nodes, and we'll need to - // recomputed it anyway if we ever insert the nodes back into a document. - if (IsStyledByServo()) { - ClearServoData(); - } else { -#ifdef MOZ_STYLO - MOZ_ASSERT(!HasServoData()); -#endif - } - if (aNullParent || !mParent->IsInShadowTree()) { UnsetFlags(NODE_IS_IN_SHADOW_TREE); diff --git a/dom/base/nsIContent.h b/dom/base/nsIContent.h index dc18c12d5c0e..766c92a19611 100644 --- a/dom/base/nsIContent.h +++ b/dom/base/nsIContent.h @@ -938,14 +938,6 @@ public: */ mozilla::dom::Element* GetEditingHost(); - - /** - * Set NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO all the way up the flattened - * parent chain to the document. If an ancestor is found with the bit already - * set, this method asserts that all of its ancestors also have the bit set. - */ - void MarkAncestorsAsHavingDirtyDescendantsForServo(); - /** * Determining language. Look at the nearest ancestor element that has a lang * attribute in the XML namespace or is an HTML/SVG element and has a lang in diff --git a/dom/base/nsINode.cpp b/dom/base/nsINode.cpp index f798bdda021e..49d9b203b175 100644 --- a/dom/base/nsINode.cpp +++ b/dom/base/nsINode.cpp @@ -152,10 +152,6 @@ nsINode::~nsINode() { MOZ_ASSERT(!HasSlots(), "nsNodeUtils::LastRelease was not called?"); MOZ_ASSERT(mSubtreeRoot == this, "Didn't restore state properly?"); -#ifdef MOZ_STYLO - NS_ASSERTION(!HasServoData(), "expected ServoNodeData to be cleared earlier"); - ClearServoData(); -#endif } void* @@ -1400,15 +1396,6 @@ nsINode::UnoptimizableCCNode() const AsElement()->IsInNamespace(kNameSpaceID_XBL)); } -void -nsINode::ClearServoData() { -#ifdef MOZ_STYLO - Servo_Node_ClearNodeData(this); -#else - MOZ_CRASH("Accessing servo node data in non-stylo build"); -#endif -} - /* static */ bool nsINode::Traverse(nsINode *tmp, nsCycleCollectionTraversalCallback &cb) diff --git a/dom/base/nsINode.h b/dom/base/nsINode.h index 4a181032e088..a6f104232fed 100644 --- a/dom/base/nsINode.h +++ b/dom/base/nsINode.h @@ -8,7 +8,6 @@ #define nsINode_h___ #include "mozilla/Likely.h" -#include "mozilla/ServoTypes.h" #include "mozilla/UniquePtr.h" #include "nsCOMPtr.h" // for member, local #include "nsGkAtoms.h" // for nsGkAtoms::baseURIProperty @@ -186,14 +185,13 @@ enum { // These two bits are shared by Gecko's and Servo's restyle systems for // different purposes. They should not be accessed directly, and access to // them should be properly guarded by asserts. + // + // FIXME(bholley): These should move to Element, and we only need one now. NODE_SHARED_RESTYLE_BIT_1 = NODE_FLAG_BIT(21), NODE_SHARED_RESTYLE_BIT_2 = NODE_FLAG_BIT(22), - // Whether this node is dirty for Servo's style system. - NODE_IS_DIRTY_FOR_SERVO = NODE_SHARED_RESTYLE_BIT_1, - // Whether this node has dirty descendants for Servo's style system. - NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO = NODE_SHARED_RESTYLE_BIT_2, + NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO = NODE_SHARED_RESTYLE_BIT_1, // Remaining bits are node type specific. NODE_TYPE_SPECIFIC_BITS_OFFSET = 23 @@ -981,48 +979,6 @@ public: bool IsStyledByServo() const { return false; } #endif - bool IsDirtyForServo() const - { - MOZ_ASSERT(IsStyledByServo()); - return HasFlag(NODE_IS_DIRTY_FOR_SERVO); - } - - bool HasDirtyDescendantsForServo() const - { - MOZ_ASSERT(IsStyledByServo()); - return HasFlag(NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO); - } - - void SetIsDirtyForServo() { - MOZ_ASSERT(IsStyledByServo()); - SetFlags(NODE_IS_DIRTY_FOR_SERVO); - } - - void SetHasDirtyDescendantsForServo() { - MOZ_ASSERT(IsStyledByServo()); - SetFlags(NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO); - } - - void SetIsDirtyAndHasDirtyDescendantsForServo() { - MOZ_ASSERT(IsStyledByServo()); - SetFlags(NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO | NODE_IS_DIRTY_FOR_SERVO); - } - - void UnsetIsDirtyForServo() { - MOZ_ASSERT(IsStyledByServo()); - UnsetFlags(NODE_IS_DIRTY_FOR_SERVO); - } - - void UnsetHasDirtyDescendantsForServo() { - MOZ_ASSERT(IsStyledByServo()); - UnsetFlags(NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO); - } - - void UnsetIsDirtyAndHasDirtyDescendantsForServo() { - MOZ_ASSERT(IsStyledByServo()); - UnsetFlags(NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO | NODE_IS_DIRTY_FOR_SERVO); - } - inline void UnsetRestyleFlagsIfGecko(); /** @@ -2061,16 +2017,6 @@ public: #undef TOUCH_EVENT #undef EVENT - bool HasServoData() { -#ifdef MOZ_STYLO - return !!mServoData.Get(); -#else - MOZ_CRASH("Accessing servo node data in non-stylo build"); -#endif - } - - void ClearServoData(); - protected: static bool Traverse(nsINode *tmp, nsCycleCollectionTraversalCallback &cb); static void Unlink(nsINode *tmp); @@ -2108,11 +2054,6 @@ protected: // Storage for more members that are usually not needed; allocated lazily. nsSlots* mSlots; - -#ifdef MOZ_STYLO - // Per-node data managed by Servo. - mozilla::ServoCell mServoData; -#endif }; inline nsIDOMNode* GetAsDOMNode(nsINode* aNode) diff --git a/dom/html/nsGenericHTMLElement.cpp b/dom/html/nsGenericHTMLElement.cpp index 6312af10f81d..9f8cf7f544fa 100644 --- a/dom/html/nsGenericHTMLElement.cpp +++ b/dom/html/nsGenericHTMLElement.cpp @@ -2942,11 +2942,14 @@ IsOrHasAncestorWithDisplayNone(Element* aElement, nsIPresShell* aPresShell) return false; } + // XXXbholley: This could be done more directly with Servo's style system. StyleSetHandle styleSet = aPresShell->StyleSet(); RefPtr sc; for (int32_t i = elementsToCheck.Length() - 1; i >= 0; --i) { if (sc) { - sc = styleSet->ResolveStyleFor(elementsToCheck[i], sc); + sc = styleSet->ResolveStyleFor(elementsToCheck[i], sc, + ConsumeStyleBehavior::DontConsume, + LazyComputeBehavior::Assert); } else { sc = nsComputedDOMStyle::GetStyleContextForElementNoFlush(elementsToCheck[i], nullptr, aPresShell); diff --git a/dom/workers/test/sharedWorker_sharedWorker.js b/dom/workers/test/sharedWorker_sharedWorker.js index 5e8e93392b11..22f219026d11 100644 --- a/dom/workers/test/sharedWorker_sharedWorker.js +++ b/dom/workers/test/sharedWorker_sharedWorker.js @@ -72,10 +72,9 @@ onconnect = function(event) { throw new Error("'connect' event has data: " + event.data); } - // The expression closures should trigger a warning in debug builds, but NOT - // fire error events at us. If we ever actually remove expression closures - // (in bug 1083458), we'll need something else to test this case. - (function() "Expected console warning: expression closures are deprecated"); + // Statement after return should trigger a warning, but NOT fire error events + // at us. + (function() { return; 1; }); event.ports[0].onmessage = function(event) { if (!(event instanceof MessageEvent)) { diff --git a/dom/workers/test/test_sharedWorker.html b/dom/workers/test/test_sharedWorker.html index 3d3d4e2c6c88..0cd0bf80072d 100644 --- a/dom/workers/test/test_sharedWorker.html +++ b/dom/workers/test/test_sharedWorker.html @@ -22,7 +22,7 @@ const sentMessage = "ping"; const errorFilename = href.substring(0, href.lastIndexOf("/") + 1) + filename; - const errorLine = 91; + const errorLine = 90; const errorColumn = 0; var worker = new SharedWorker(filename); diff --git a/dom/xbl/nsXBLBinding.cpp b/dom/xbl/nsXBLBinding.cpp index 6ae17c4c02e3..08ab6b53b54c 100644 --- a/dom/xbl/nsXBLBinding.cpp +++ b/dom/xbl/nsXBLBinding.cpp @@ -426,7 +426,6 @@ nsXBLBinding::GenerateAnonymousContent() nsIPresShell* presShell = mBoundElement->OwnerDoc()->GetShell(); ServoStyleSet* servoSet = presShell->StyleSet()->GetAsServo(); if (servoSet) { - mBoundElement->SetHasDirtyDescendantsForServo(); servoSet->StyleNewChildren(mBoundElement); } } diff --git a/image/ImageCacheKey.cpp b/image/ImageCacheKey.cpp index 577eb80ba0e9..da194fa554ea 100644 --- a/image/ImageCacheKey.cpp +++ b/image/ImageCacheKey.cpp @@ -141,21 +141,8 @@ ImageCacheKey::ComputeHash(ImageURL* aURI, nsAutoCString suffix; aAttrs.CreateSuffix(suffix); - if (aBlobSerial) { - // For blob URIs, we hash the serial number of the underlying blob, so that - // different blob URIs which point to the same blob share a cache entry. We - // also include the ref portion of the URI to support media fragments which - // requires us to create different Image objects even if the source data is - // the same. - nsAutoCString ref; - aURI->GetRef(ref); - return HashGeneric(*aBlobSerial, HashString(ref + suffix + ptr)); - } - - // For non-blob URIs, we hash the URI spec. - nsAutoCString spec; - aURI->GetSpec(spec); - return HashString(spec + suffix + ptr); + return AddToHash(0, aURI->ComputeHash(aBlobSerial), + HashString(suffix), HashString(ptr)); } /* static */ void* diff --git a/image/ImageURL.h b/image/ImageURL.h index 0ca6e458c4a9..fa60ff79eb6e 100644 --- a/image/ImageURL.h +++ b/image/ImageURL.h @@ -9,10 +9,14 @@ #include "nsIURI.h" #include "MainThreadUtils.h" #include "nsNetUtil.h" +#include "mozilla/HashFunctions.h" +#include "nsHashKeys.h" namespace mozilla { namespace image { +class ImageCacheKey; + /** ImageURL * * nsStandardURL is not threadsafe, so this class is created to hold only the @@ -113,6 +117,22 @@ public: } private: + friend class ImageCacheKey; + + uint32_t ComputeHash(const Maybe& aBlobSerial) const + { + if (aBlobSerial) { + // For blob URIs, we hash the serial number of the underlying blob, so that + // different blob URIs which point to the same blob share a cache entry. We + // also include the ref portion of the URI to support media fragments which + // requires us to create different Image objects even if the source data is + // the same. + return HashGeneric(*aBlobSerial, HashString(mRef)); + } + // For non-blob URIs, we hash the URI spec. + return HashString(mSpec); + } + // Since this is a basic storage class, no duplication of spec parsing is // included in the functionality. Instead, the class depends upon the // parsing implementation in the nsIURI class used in object construction. diff --git a/js/src/jit-test/tests/SIMD/bug1273483.js b/js/src/jit-test/tests/SIMD/bug1273483.js index 3c9386b4f466..55fb09ace2d5 100644 --- a/js/src/jit-test/tests/SIMD/bug1273483.js +++ b/js/src/jit-test/tests/SIMD/bug1273483.js @@ -3,7 +3,7 @@ if (typeof SIMD === 'undefined') Int8x16 = SIMD.Int8x16; var Int32x4 = SIMD.Int32x4; -function testSwizzleForType(type) type(); +function testSwizzleForType(type) { return type(); } testSwizzleForType(Int8x16); -function testSwizzleInt32x4() testSwizzleForType(Int32x4); +function testSwizzleInt32x4() { return testSwizzleForType(Int32x4); } testSwizzleInt32x4(); diff --git a/js/src/jit-test/tests/TypedObject/jit-write-references-2.js b/js/src/jit-test/tests/TypedObject/jit-write-references-2.js index eec2f0d92b3b..33c67ee707c0 100644 --- a/js/src/jit-test/tests/TypedObject/jit-write-references-2.js +++ b/js/src/jit-test/tests/TypedObject/jit-write-references-2.js @@ -10,7 +10,8 @@ var ValueStruct = new T.StructType({ }) var v = new ValueStruct; new class get extends Number {}; -function writeValue(o, v) - o.f = v +function writeValue(o, v) { + return o.f = v; +} for (var i = 0; i < 5; i++) writeValue(v, {}, "helo") diff --git a/js/src/jit-test/tests/arguments/defaults-destructuring-expression-closure.js b/js/src/jit-test/tests/arguments/defaults-destructuring-expression-closure.js index 018da2273800..750289e44e4b 100644 --- a/js/src/jit-test/tests/arguments/defaults-destructuring-expression-closure.js +++ b/js/src/jit-test/tests/arguments/defaults-destructuring-expression-closure.js @@ -1,9 +1,9 @@ -function f1(a, bIs, cIs, dIs, {b}={b: 3}, c=4, [d]=[5]) ( +function f1(a, bIs, cIs, dIs, {b}={b: 3}, c=4, [d]=[5]) { assertEq(a, 1), assertEq(b, bIs), assertEq(c, cIs), assertEq(d, dIs) -); +} assertEq(f1.length, 4); f1(1, 3, 4, 5); f1(1, 42, 43, 44, {b: 42}, 43, [44]); diff --git a/js/src/jit-test/tests/arguments/destructuring-exprbody.js b/js/src/jit-test/tests/arguments/destructuring-exprbody.js index 5e764d6a0ed3..5f3f04ecb746 100644 --- a/js/src/jit-test/tests/arguments/destructuring-exprbody.js +++ b/js/src/jit-test/tests/arguments/destructuring-exprbody.js @@ -1,6 +1,6 @@ // See bug 763313 load(libdir + "iteration.js"); -function f([a]) a +function f([a]) { return a; } var i = 0; var o = {[Symbol.iterator]: function () { i++; return { next: function () { i++; return {value: 42, done: false}; }}}}; diff --git a/js/src/jit-test/tests/asm.js/testCall.js b/js/src/jit-test/tests/asm.js/testCall.js index 5d15fe257514..e1e14cb47d6e 100644 --- a/js/src/jit-test/tests/asm.js/testCall.js +++ b/js/src/jit-test/tests/asm.js/testCall.js @@ -58,7 +58,7 @@ assertThrowsInstanceOf(rec, InternalError); var rec = asmLink(asmCompile(USE_ASM+"function rec(i) { i=i|0; if (!i) return 0; return ((rec((i-1)|0)|0)+1)|0 } return rec")); assertEq(rec(100), 100); assertEq(rec(1000), 1000); -assertThrowsInstanceOf(function() rec(100000000000), InternalError); +assertThrowsInstanceOf(() => rec(100000000000), InternalError); assertEq(rec(2000), 2000); assertAsmTypeFail(USE_ASM+"function f(){return 0} function g() { var i=0; i=f() } return g"); diff --git a/js/src/jit-test/tests/auto-regress/bug1264823.js b/js/src/jit-test/tests/auto-regress/bug1264823.js index 67856c6c97ec..83af21451c68 100644 --- a/js/src/jit-test/tests/auto-regress/bug1264823.js +++ b/js/src/jit-test/tests/auto-regress/bug1264823.js @@ -6,6 +6,8 @@ loadFile(""); loadFile(` function lalala() {} new Map([[1, 2]]).forEach(lalala) `); -function loadFile(lfVarx) oomTest(function() { - eval(lfVarx) -}) +function loadFile(lfVarx) { + return oomTest(function() { + eval(lfVarx) + }); +} diff --git a/js/src/jit-test/tests/auto-regress/bug1317460.js b/js/src/jit-test/tests/auto-regress/bug1317460.js index 87da637e7a1c..ccd6aacf1258 100644 --- a/js/src/jit-test/tests/auto-regress/bug1317460.js +++ b/js/src/jit-test/tests/auto-regress/bug1317460.js @@ -3,7 +3,7 @@ g = newGlobal(); g.parent = this; g.eval("(" + function() { - Debugger(parent).onExceptionUnwind = function() 0; + Debugger(parent).onExceptionUnwind = function() { return 0; }; } + ")()"); async function f() { t; diff --git a/js/src/jit-test/tests/auto-regress/bug488034.js b/js/src/jit-test/tests/auto-regress/bug488034.js index 08aac5829c71..fa816d1a295a 100644 --- a/js/src/jit-test/tests/auto-regress/bug488034.js +++ b/js/src/jit-test/tests/auto-regress/bug488034.js @@ -3,5 +3,5 @@ // (function(){ var x; - eval("var x; ((function ()x)())"); + eval("var x; ((function () { return x; })())"); })() diff --git a/js/src/jit-test/tests/auto-regress/bug488421.js b/js/src/jit-test/tests/auto-regress/bug488421.js index 1fcad0c186bb..c81684420a04 100644 --- a/js/src/jit-test/tests/auto-regress/bug488421.js +++ b/js/src/jit-test/tests/auto-regress/bug488421.js @@ -4,7 +4,7 @@ function f(foo) { var x; - eval("this.__defineGetter__(\"y\", function ()x)"); + eval("this.__defineGetter__(\"y\", function () { return x; })"); } f(""); try { diff --git a/js/src/jit-test/tests/auto-regress/bug490191.js b/js/src/jit-test/tests/auto-regress/bug490191.js index b56ee11db5e7..d198832cbd51 100644 --- a/js/src/jit-test/tests/auto-regress/bug490191.js +++ b/js/src/jit-test/tests/auto-regress/bug490191.js @@ -5,9 +5,9 @@ function f(param) { var w; return eval("\ (function(){\ - this.__defineGetter__(\"y\", function()({\ + this.__defineGetter__(\"y\", function() { return ({\ x: function(){ return w }()\ - }))\ + }); })\ });\ "); } diff --git a/js/src/jit-test/tests/auto-regress/bug563034.js b/js/src/jit-test/tests/auto-regress/bug563034.js index 9dfa8c7b4350..cb4d7b6be2da 100644 --- a/js/src/jit-test/tests/auto-regress/bug563034.js +++ b/js/src/jit-test/tests/auto-regress/bug563034.js @@ -3,7 +3,7 @@ // function f(a) { function g() { - yield function () a; + yield function () { return a; }; } return g(); } diff --git a/js/src/jit-test/tests/auto-regress/bug630770.js b/js/src/jit-test/tests/auto-regress/bug630770.js index 745fd526d6c9..495a29b2a307 100644 --- a/js/src/jit-test/tests/auto-regress/bug630770.js +++ b/js/src/jit-test/tests/auto-regress/bug630770.js @@ -2,4 +2,4 @@ // Flags: // options('strict') -Function("function y(x,x)d") +Function("function y(x,x) { return d; }") diff --git a/js/src/jit-test/tests/auto-regress/bug650658.js b/js/src/jit-test/tests/auto-regress/bug650658.js index c4065a973953..b706ecb9dd0f 100644 --- a/js/src/jit-test/tests/auto-regress/bug650658.js +++ b/js/src/jit-test/tests/auto-regress/bug650658.js @@ -5,5 +5,6 @@ // AddRegExpCases(/a*b/, "xxx", 0, null ); AddRegExpCases(/x\d\dy/, "abcx45ysss235", 3,[] ); -function AddRegExpCases(regexp, pattern, index, matches_array ) - (matches_array.length, regexp) +function AddRegExpCases(regexp, pattern, index, matches_array ) { + return (matches_array.length, regexp); +} diff --git a/js/src/jit-test/tests/auto-regress/bug659779.js b/js/src/jit-test/tests/auto-regress/bug659779.js index 22ff561b3a63..1001a7d5ca5f 100644 --- a/js/src/jit-test/tests/auto-regress/bug659779.js +++ b/js/src/jit-test/tests/auto-regress/bug659779.js @@ -7,8 +7,8 @@ function TestCase(n, d, e, a) { this.description=d gTestcases[gTc++]=this } -TestCase.prototype.dump=function () + toPrinted(this.description) -function toPrinted(value) value=value; +TestCase.prototype.dump=function () { return + toPrinted(this.description); }; +function toPrinted(value) { return value=value; } function reportCompare (expected, actual, description) { new TestCase("unknown-test-name", description, expected, actual) } diff --git a/js/src/jit-test/tests/auto-regress/bug730806.js b/js/src/jit-test/tests/auto-regress/bug730806.js index 4ceb5274e213..9c5ed54b7e37 100644 --- a/js/src/jit-test/tests/auto-regress/bug730806.js +++ b/js/src/jit-test/tests/auto-regress/bug730806.js @@ -1,10 +1,11 @@ // Binary: cache/js-opt-32-2dc40eb83023-linux // Flags: -m -n -a // -function toPrinted(value) - value = value.replace(/\\n/g, 'NL') - .replace(/\\r/g, 'CR') - .replace(/[^\x20-\x7E]+/g, escapeString); +function toPrinted(value) { + return value = value.replace(/\\n/g, 'NL') + .replace(/\\r/g, 'CR') + .replace(/[^\x20-\x7E]+/g, escapeString); +} function escapeString (str) { var a, b, c, d; diff --git a/js/src/jit-test/tests/auto-regress/bug756236.js b/js/src/jit-test/tests/auto-regress/bug756236.js index b25859b697af..5c6b3a51a9c2 100644 --- a/js/src/jit-test/tests/auto-regress/bug756236.js +++ b/js/src/jit-test/tests/auto-regress/bug756236.js @@ -4,8 +4,9 @@ gczeal(4); function startTest() {} -function TestCase(n, d, e, a) - dump = (function () {}); +function TestCase(n, d, e, a) { + return dump = (function () {}); +} if (typeof document != "object" || !document.location.href.match(/jsreftest.html/)) {} function writeHeaderToLog( string ) {} var SECTION = "11.4.5"; diff --git a/js/src/jit-test/tests/auto-regress/bug778557.js b/js/src/jit-test/tests/auto-regress/bug778557.js index 0537be6c12f5..ed64a98fe4e4 100644 --- a/js/src/jit-test/tests/auto-regress/bug778557.js +++ b/js/src/jit-test/tests/auto-regress/bug778557.js @@ -2,6 +2,6 @@ // Flags: // x = Set; -eval("function y()(Iterator)", this); +eval("function y() { return Iterator; }", this); x.__iterator__ = y; new Iterator(x) diff --git a/js/src/jit-test/tests/baseline/bug1216140.js b/js/src/jit-test/tests/baseline/bug1216140.js index bdce8ab164fb..9aede5c0266e 100644 --- a/js/src/jit-test/tests/baseline/bug1216140.js +++ b/js/src/jit-test/tests/baseline/bug1216140.js @@ -1,4 +1,4 @@ -function newFunc(x) Function(x)() +function newFunc(x) { return Function(x)(); } newFunc(` var BUGNUMBER = 8[ anonymous = true ]--; () => BUGNUMBER; diff --git a/js/src/jit-test/tests/baseline/bug1238815.js b/js/src/jit-test/tests/baseline/bug1238815.js index e64955ee1a11..3d4ee3faeb3e 100644 --- a/js/src/jit-test/tests/baseline/bug1238815.js +++ b/js/src/jit-test/tests/baseline/bug1238815.js @@ -4,7 +4,9 @@ // Baseline should not attempt to compile the script. i = 1; -function test(s) eval("line0 = Error.lineNumber\ndebugger\n" + s); +function test(s) { + return eval("line0 = Error.lineNumber\ndebugger\n" + s); +} function repeat(s) { return Array(65 << 13).join(s) } diff --git a/js/src/jit-test/tests/baseline/bug852801.js b/js/src/jit-test/tests/baseline/bug852801.js index 3dad6f25c7de..771c4f55bdf8 100644 --- a/js/src/jit-test/tests/baseline/bug852801.js +++ b/js/src/jit-test/tests/baseline/bug852801.js @@ -14,8 +14,9 @@ function printStatus (msg) { print (STATUS + lines[i]); } function printBugNumber (num) {} -function toPrinted(value) -function escapeString (str) {} +function toPrinted(value) { + return function escapeString (str) {}; +} function reportCompare (expected, actual, description) { var actual_t = typeof actual; var output = ""; @@ -32,9 +33,10 @@ function reportCompare (expected, actual, description) { return testcase.passed; } function reportMatch (expectedRegExp, actual, description) {} -function enterFunc (funcName) -function BigO(data) { - function LinearRegression(data) { } +function enterFunc (funcName) { + return function BigO(data) { + function LinearRegression(data) { } + }; } function compareSource(expect, actual, summary) {} function optionsInit() { @@ -44,9 +46,10 @@ function optionsClear() {} function optionsPush() {} optionsInit(); optionsClear(); -function getTestCaseResult(expected, actual) -function test() { - for ( gTc=0; gTc < gTestcases.length; gTc++ ) {} +function getTestCaseResult(expected, actual) { + return function test() { + for ( gTc=0; gTc < gTestcases.length; gTc++ ) {} + }; } var lfcode = new Array(); lfcode.push("4"); @@ -62,7 +65,7 @@ addThis();\n\ addThis();\n\ tryThis(1);\n\ function tryThis(x)\n\ -addThis();\n\ +{ return addThis(); }\n\ test();\n\ function addThis() {\n\ actualvalues[UBound] = actual;\n\ diff --git a/js/src/jit-test/tests/basic/bug1135718.js b/js/src/jit-test/tests/basic/bug1135718.js index 312c2ce35df2..515457cdfb16 100644 --- a/js/src/jit-test/tests/basic/bug1135718.js +++ b/js/src/jit-test/tests/basic/bug1135718.js @@ -1,7 +1,8 @@ setJitCompilerOption("ion.warmup.trigger", 30); -function ArrayCallback(state) - this.state = state; +function ArrayCallback(state) { + return this.state = state; +} ArrayCallback.prototype.isUpperCase = function(v, index, array) { return this.state ? true : (v == v.toUpperCase()); }; diff --git a/js/src/jit-test/tests/basic/bug560234b.js b/js/src/jit-test/tests/basic/bug560234b.js index b130d7500d8b..08dda05a5b0d 100644 --- a/js/src/jit-test/tests/basic/bug560234b.js +++ b/js/src/jit-test/tests/basic/bug560234b.js @@ -1,6 +1,6 @@ function f(a) { function g() { - yield function () a; + yield function () { return a; }; } if (a == 8) return g(); diff --git a/js/src/jit-test/tests/basic/bug650148.js b/js/src/jit-test/tests/basic/bug650148.js index bf96509e27cb..3a52cc77c78b 100644 --- a/js/src/jit-test/tests/basic/bug650148.js +++ b/js/src/jit-test/tests/basic/bug650148.js @@ -8,6 +8,7 @@ test(); function test() { [ {0xBe: /l/|| 'Error' ? s++ : summary } ] } -function foo(code) - Function(code)(); +function foo(code) { + return Function(code)(); +} foo("for each (y in this);"); diff --git a/js/src/jit-test/tests/basic/bug651966.js b/js/src/jit-test/tests/basic/bug651966.js index d2f9a522d484..35e0c1049bde 100644 --- a/js/src/jit-test/tests/basic/bug651966.js +++ b/js/src/jit-test/tests/basic/bug651966.js @@ -26,7 +26,7 @@ function f2() { x } = x, (x._) function - x()({}) + x(){ return ({}); } } try { f2(); } catch (e) {} diff --git a/js/src/jit-test/tests/basic/bug657225.js b/js/src/jit-test/tests/basic/bug657225.js index 40f0dbf962ca..510b7685150b 100644 --- a/js/src/jit-test/tests/basic/bug657225.js +++ b/js/src/jit-test/tests/basic/bug657225.js @@ -1,5 +1,5 @@ -function reportCompare(expected, actual, description) + ++actual + "'"; +function reportCompare(expected, actual, description) { return + ++actual + "'"; } var summary = 'Object.prototype.toLocaleString() should track Object.prototype.toString() '; var o = { toString: function () {} diff --git a/js/src/jit-test/tests/basic/bug673766.js b/js/src/jit-test/tests/basic/bug673766.js index 0d1d36f5d413..d1bdc3d45ce6 100644 --- a/js/src/jit-test/tests/basic/bug673766.js +++ b/js/src/jit-test/tests/basic/bug673766.js @@ -13,7 +13,7 @@ try { valueOf: gc } - []) } catch (prop) {} -function addThis() reportCompare(expect, actual, 'ok'); +function addThis() { return reportCompare(expect, actual, 'ok'); } Object.defineProperty(Object.prototype, "name", { set: function (newValue) {} }); diff --git a/js/src/jit-test/tests/basic/bug709634.js b/js/src/jit-test/tests/basic/bug709634.js index 57de9720aa79..78691ca98d81 100644 --- a/js/src/jit-test/tests/basic/bug709634.js +++ b/js/src/jit-test/tests/basic/bug709634.js @@ -1,5 +1,5 @@ -Function.prototype.toString = function () f(this, true); +Function.prototype.toString = function () { return f(this, true); }; function f(obj) { f.caller.p } diff --git a/js/src/jit-test/tests/basic/bug728086.js b/js/src/jit-test/tests/basic/bug728086.js index 39692c670cf2..9d7a771026ca 100644 --- a/js/src/jit-test/tests/basic/bug728086.js +++ b/js/src/jit-test/tests/basic/bug728086.js @@ -13,8 +13,9 @@ function reportCompare (expected, actual, description) { var testcase = new TestCase("unknown-test-name", description, expected, actual); reportFailure (description + " : " + output); } -function enterFunc (funcName) - callStack.push(funcName); +function enterFunc (funcName) { + return callStack.push(funcName); +} try { reportCompare(expectCompile, actualCompile, summary + ': compile actual'); diff --git a/js/src/jit-test/tests/basic/bug738841.js b/js/src/jit-test/tests/basic/bug738841.js index 9a81341aa680..3429aea5b35c 100644 --- a/js/src/jit-test/tests/basic/bug738841.js +++ b/js/src/jit-test/tests/basic/bug738841.js @@ -40,7 +40,7 @@ try { try { var f = function() { { - print(new function(q)("", s)) + print(new function(q) { return ("", s); }) let u } }; diff --git a/js/src/jit-test/tests/basic/bug744285.js b/js/src/jit-test/tests/basic/bug744285.js index f5a9e4f36b27..2adf3b9c700a 100644 --- a/js/src/jit-test/tests/basic/bug744285.js +++ b/js/src/jit-test/tests/basic/bug744285.js @@ -47,7 +47,7 @@ function check(b, desc) { assertEq(Object.getPrototypeOf(a), ca == "[object Object]" ? Object.prototype : Array.prototype, path) pb = ownProperties(b).filter(isCloneable) pa = ownProperties(a) - function byName(a, b) 0 + function byName(a, b) { return 0; } byName (pa.length, pb.length, "should see the same number of properties " + path) for (var i = 0; i < pa.length; i++) { diff --git a/js/src/jit-test/tests/basic/bug808067.js b/js/src/jit-test/tests/basic/bug808067.js index 74f721ec90c0..34abc2a11db7 100644 --- a/js/src/jit-test/tests/basic/bug808067.js +++ b/js/src/jit-test/tests/basic/bug808067.js @@ -1,5 +1,6 @@ -function TestCase(n, d, e, a) - this.reason = ''; +function TestCase(n, d, e, a) { + return this.reason = ''; +} function reportCompare (expected, actual, description) { var output = ""; var testcase = new TestCase("unknown-test-name", description, expected, actual); diff --git a/js/src/jit-test/tests/basic/bug832203.js b/js/src/jit-test/tests/basic/bug832203.js index 3889edc9c82f..d850819b0dc1 100644 --- a/js/src/jit-test/tests/basic/bug832203.js +++ b/js/src/jit-test/tests/basic/bug832203.js @@ -6,6 +6,6 @@ function test(str, f) {\ var x = f(eval(str));\ assertEq(x, f(g1.eval(str)));\ }\ -test('new RegExp(\"1\")', function(r) assertEq('a1'.search(r), 1));\ +test('new RegExp(\"1\")', function(r) { return assertEq('a1'.search(r), 1); });\ " + " })();"); eval("(function() { " + "" + " })();"); diff --git a/js/src/jit-test/tests/basic/bug951213.js b/js/src/jit-test/tests/basic/bug951213.js index 0607980da9b5..37454491dd5a 100644 --- a/js/src/jit-test/tests/basic/bug951213.js +++ b/js/src/jit-test/tests/basic/bug951213.js @@ -4,5 +4,5 @@ function foo(x, y) { this.g = x + y; } var a = 0; -var b = { valueOf: function() Object.defineProperty(Object.prototype, 'g', {}) }; +var b = { valueOf: function() { return Object.defineProperty(Object.prototype, 'g', {}); } }; var c = new foo(a, b); diff --git a/js/src/jit-test/tests/basic/decompile-script.js b/js/src/jit-test/tests/basic/decompile-script.js index 523bc71fab37..b5926d79c125 100644 --- a/js/src/jit-test/tests/basic/decompile-script.js +++ b/js/src/jit-test/tests/basic/decompile-script.js @@ -2,5 +2,5 @@ function example(a, b, c) { var complicated = 3; perform_some_operations(); } -var myfun = function (a, b) a + b; +var myfun = function (a, b) { return a + b; } assertEq(decompileThis(), snarf(thisFilename())); diff --git a/js/src/jit-test/tests/basic/function-tosource-getset.js b/js/src/jit-test/tests/basic/function-tosource-getset.js index 36c6d010e78c..5553d4176a14 100644 --- a/js/src/jit-test/tests/basic/function-tosource-getset.js +++ b/js/src/jit-test/tests/basic/function-tosource-getset.js @@ -1,7 +1,7 @@ -var o = {get prop() a + b, set prop(x) a + b}; +var o = {get prop() { a + b; }, set prop(x) { a + b; }}; var prop = Object.getOwnPropertyDescriptor(o, "prop"); -assertEq(prop.get.toString(), "function get prop() a + b"); -assertEq(prop.get.toSource(), "(function get prop() a + b)"); -assertEq(prop.set.toString(), "function set prop(x) a + b"); -assertEq(prop.set.toSource(), "(function set prop(x) a + b)"); -assertEq(o.toSource(), "({get prop () a + b, set prop (x) a + b})"); +assertEq(prop.get.toString(), "function get prop() { a + b; }"); +assertEq(prop.get.toSource(), "(function get prop() { a + b; })"); +assertEq(prop.set.toString(), "function set prop(x) { a + b; }"); +assertEq(prop.set.toSource(), "(function set prop(x) { a + b; })"); +assertEq(o.toSource(), "({get prop () { a + b; }, set prop (x) { a + b; }})"); diff --git a/js/src/jit-test/tests/basic/shapelessCalleeTest.js b/js/src/jit-test/tests/basic/shapelessCalleeTest.js index fe10e9b42836..6d12e7c9d8d8 100644 --- a/js/src/jit-test/tests/basic/shapelessCalleeTest.js +++ b/js/src/jit-test/tests/basic/shapelessCalleeTest.js @@ -43,17 +43,17 @@ function shapelessCalleeTest() { var a = []; - var helper = function (i, a) a[i] = i; - shapelessArgCalleeLoop(helper, helper, function (i, a) a[i] = -i, a); + var helper = function (i, a) { a[i] = i; }; + shapelessArgCalleeLoop(helper, helper, function (i, a) { a[i] = -i; }, a); - helper = function (i, a) a[10 + i] = i; - shapelessVarCalleeLoop(helper, helper, function (i, a) a[10 + i] = -i, a); + helper = function (i, a) { a[10 + i] = i; }; + shapelessVarCalleeLoop(helper, helper, function (i, a) { a[10 + i] = -i; }, a); - helper = function (i, a) a[20 + i] = i; - shapelessLetCalleeLoop(helper, helper, function (i, a) a[20 + i] = -i, a); + helper = function (i, a) { a[20 + i] = i; }; + shapelessLetCalleeLoop(helper, helper, function (i, a) { a[20 + i] = -i; }, a); - helper = function (i, a) a[30 + i] = i; - shapelessUnknownCalleeLoop(null, helper, helper, function (i, a) a[30 + i] = -i, a); + helper = function (i, a) { a[30 + i] = i; }; + shapelessUnknownCalleeLoop(null, helper, helper, function (i, a) { a[30 + i] = -i; }, a); try { helper = {hack: 42}; diff --git a/js/src/jit-test/tests/basic/spread-call-funapply.js b/js/src/jit-test/tests/basic/spread-call-funapply.js index 9362d2a2d615..a285d4e8276c 100644 --- a/js/src/jit-test/tests/basic/spread-call-funapply.js +++ b/js/src/jit-test/tests/basic/spread-call-funapply.js @@ -53,7 +53,7 @@ function checkNormal(f) { assertEqArray(f.apply(null, ...[[undefined]]), [undefined, undefined, undefined]); } -checkNormal(function(a, b, c) [a, b, c]); +checkNormal(function(a, b, c) { return [a, b, c]; }); checkNormal((a, b, c) => [a, b, c]); function checkDefault(f) { @@ -67,7 +67,7 @@ function checkDefault(f) { assertEqArray(f.apply(null, ...[[undefined]]), [-1, -2, -3]); } -checkDefault(function(a = -1, b = -2, c = -3) [a, b, c]); +checkDefault(function(a = -1, b = -2, c = -3) { return [a, b, c]; }); checkDefault((a = -1, b = -2, c = -3) => [a, b, c]); function checkRest(f) { @@ -84,5 +84,5 @@ function checkRest(f) { assertEqArray(f.apply(null, ...new Map([[["a", "A"], ["b", "B"]]])).map(([k, v]) => k + v), ["aA", "bB"]); } -checkRest(function(...x) x); +checkRest(function(...x) { return x; }); checkRest((...x) => x); diff --git a/js/src/jit-test/tests/basic/spread-call-funcall.js b/js/src/jit-test/tests/basic/spread-call-funcall.js index bcb3c0024f1f..97edfb6599bb 100644 --- a/js/src/jit-test/tests/basic/spread-call-funcall.js +++ b/js/src/jit-test/tests/basic/spread-call-funcall.js @@ -7,5 +7,5 @@ function check(f) { assertEqArray(f.call(...[null, 1, ...[2, 3], 4, ...[5, 6]]), [1, 2, 3, 4, 5, 6]); } -check(function(...x) x); +check(function(...x) { return x; }); check((...x) => x); diff --git a/js/src/jit-test/tests/basic/spread-call-length.js b/js/src/jit-test/tests/basic/spread-call-length.js index 3356c913a8f0..1d84d046d865 100644 --- a/js/src/jit-test/tests/basic/spread-call-length.js +++ b/js/src/jit-test/tests/basic/spread-call-length.js @@ -44,8 +44,8 @@ function checkLength(f, makeFn) { assertEq(makeFn("...arg")(f, gen()), 3); } -checkLength(function(x) arguments.length, makeCall); -checkLength(function(x) arguments.length, makeFunCall); +checkLength(function(x) { return arguments.length; }, makeCall); +checkLength(function(x) { return arguments.length; }, makeFunCall); function lengthClass(x) { this.length = arguments.length; } diff --git a/js/src/jit-test/tests/basic/spread-call-not-iterable.js b/js/src/jit-test/tests/basic/spread-call-not-iterable.js index f1e16cc0e646..969d99bccfa6 100644 --- a/js/src/jit-test/tests/basic/spread-call-not-iterable.js +++ b/js/src/jit-test/tests/basic/spread-call-not-iterable.js @@ -14,13 +14,13 @@ var foo = {} foo[Symbol.iterator] = 10; assertThrowsInstanceOf(() => Math.sin(...foo), TypeError); -foo[Symbol.iterator] = function() undefined; +foo[Symbol.iterator] = function() { return undefined; }; assertThrowsInstanceOf(() => Math.sin(...foo), TypeError); -foo[Symbol.iterator] = function() this; +foo[Symbol.iterator] = function() { return this; }; assertThrowsInstanceOf(() => Math.sin(...foo), TypeError); -foo[Symbol.iterator] = function() this; +foo[Symbol.iterator] = function() { return this; }; foo.next = function() { throw 10; }; assertThrowsValue(() => Math.sin(...foo), 10); diff --git a/js/src/jit-test/tests/basic/spread-call-recursion.js b/js/src/jit-test/tests/basic/spread-call-recursion.js index 58450d885264..5d7caa341aac 100644 --- a/js/src/jit-test/tests/basic/spread-call-recursion.js +++ b/js/src/jit-test/tests/basic/spread-call-recursion.js @@ -9,9 +9,9 @@ function check(f) { } } -let f = function() f(...a) + 1; +let f = function() { return f(...a) + 1; }; let g = () => g(...a) + 1; -let h = function() new h(...a) + 1; +let h = function() { return new h(...a) + 1; }; check(f); check(g); diff --git a/js/src/jit-test/tests/basic/spread-call.js b/js/src/jit-test/tests/basic/spread-call.js index 927c6d0f412f..0b54178a0cd2 100644 --- a/js/src/jit-test/tests/basic/spread-call.js +++ b/js/src/jit-test/tests/basic/spread-call.js @@ -57,8 +57,8 @@ function checkNormal(f, makeFn) { assertEqArray(makeFn("...[undefined]")(f), [undefined, undefined, undefined]); } -checkNormal(function(a, b, c) [a, b, c], makeCall); -checkNormal(function(a, b, c) [a, b, c], makeFunCall); +checkNormal(function(a, b, c) { return [a, b, c]; }, makeCall); +checkNormal(function(a, b, c) { return [a, b, c]; }, makeFunCall); checkNormal((a, b, c) => [a, b, c], makeCall); checkNormal((a, b, c) => [a, b, c], makeFunCall); function normalClass(a, b, c) { @@ -78,8 +78,8 @@ function checkDefault(f, makeFn) { assertEqArray(makeFn("...[undefined]")(f), [-1, -2, -3]); } -checkDefault(function(a = -1, b = -2, c = -3) [a, b, c], makeCall); -checkDefault(function(a = -1, b = -2, c = -3) [a, b, c], makeFunCall); +checkDefault(function(a = -1, b = -2, c = -3) { return [a, b, c]; }, makeCall); +checkDefault(function(a = -1, b = -2, c = -3) { return [a, b, c]; }, makeFunCall); checkDefault((a = -1, b = -2, c = -3) => [a, b, c], makeCall); checkDefault((a = -1, b = -2, c = -3) => [a, b, c], makeFunCall); function defaultClass(a = -1, b = -2, c = -3) { @@ -99,8 +99,8 @@ function checkRest(f, makeFn) { assertEqArray(makeFn("...[undefined]")(f), [undefined]); } -checkRest(function(...x) x, makeCall); -checkRest(function(...x) x, makeFunCall); +checkRest(function(...x) { return x; }, makeCall); +checkRest(function(...x) { return x; }, makeFunCall); checkRest((...x) => x, makeCall); checkRest((...x) => x, makeFunCall); function restClass(...x) { diff --git a/js/src/jit-test/tests/basic/testBrandedVsGeneric.js b/js/src/jit-test/tests/basic/testBrandedVsGeneric.js index f0a244bcccd0..48b9aaed9250 100644 --- a/js/src/jit-test/tests/basic/testBrandedVsGeneric.js +++ b/js/src/jit-test/tests/basic/testBrandedVsGeneric.js @@ -1,12 +1,12 @@ const C = function (a, b, c) { return function C() { - this.m1 = function () a; - this.m2 = function () b; - this.m3 = function () c; + this.m1 = function () { return a; }; + this.m2 = function () { return b; }; + this.m3 = function () { return c; }; } }(2,3,4); var c = new C(); -var d = function (e) {return {m0: function () e}}(5); +var d = function (e) {return {m0: function () { return e; }}}(5); for (var i = 0; i < 5; i++) d.m0(); C.call(d); diff --git a/js/src/jit-test/tests/basic/testBug740442.js b/js/src/jit-test/tests/basic/testBug740442.js index 37333b8f8ddd..143ce2da968b 100644 --- a/js/src/jit-test/tests/basic/testBug740442.js +++ b/js/src/jit-test/tests/basic/testBug740442.js @@ -1,6 +1,7 @@ function g1() {} -function g2() -function Int8Array () {} +function g2() { + return function Int8Array () {}; +} function f1(other) { eval("gc(); h = g1"); for(var i=0; i<20; i++) { diff --git a/js/src/jit-test/tests/basic/testBug783441.js b/js/src/jit-test/tests/basic/testBug783441.js index 088ecc8b176d..b1d6af68ab63 100644 --- a/js/src/jit-test/tests/basic/testBug783441.js +++ b/js/src/jit-test/tests/basic/testBug783441.js @@ -1 +1 @@ -assertEq((function(x, y, x) { return (function() x+y)(); })(1,2,5), 7); +assertEq((function(x, y, x) { return (function() { return x+y; })(); })(1,2,5), 7); diff --git a/js/src/jit-test/tests/basic/testCallProtoMethod.js b/js/src/jit-test/tests/basic/testCallProtoMethod.js index cd0be83cc8c4..8907871ba09c 100644 --- a/js/src/jit-test/tests/basic/testCallProtoMethod.js +++ b/js/src/jit-test/tests/basic/testCallProtoMethod.js @@ -3,7 +3,7 @@ function testCallProtoMethod() { X.prototype.getName = function () { return "X"; } function Y() { this.x = 2; } - Y.prototype.getName = function() "Y"; + Y.prototype.getName = function() { return "Y"; }; var a = [new X, new X, new X, new X, new Y]; var s = ''; diff --git a/js/src/jit-test/tests/basic/testDynamicUsage.js b/js/src/jit-test/tests/basic/testDynamicUsage.js index 04cd51b71dbe..49ee874c1fe3 100644 --- a/js/src/jit-test/tests/basic/testDynamicUsage.js +++ b/js/src/jit-test/tests/basic/testDynamicUsage.js @@ -4,9 +4,9 @@ assertEq((function() { var x; x = 3; return (function() { return x } )() })(), 3 assertEq((function() { x = 3; var x; return (function() { return x } )() })(), 3); assertEq((function() { var x; var g = function() { return x }; x = 3; return g() })(), 3); -assertEq((function() { function f() { return 3 }; assertEq(f(), 3); return (function() f())() })(), 3); +assertEq((function() { function f() { return 3 }; assertEq(f(), 3); return (function() { return f(); })(); })(), 3); assertEq((function() { function f() { return 3 }; assertEq(f(), 3); return eval('f()') })(), 3); -assertEq((function() { function f() { return 3 }; (function() f())(); return f() })(), 3); +assertEq((function() { function f() { return 3 }; (function() { return f(); })(); return f() })(), 3); assertEq((function() { var x = 3; return eval("x") })(), 3); assertEq((function() { var x; x = 3; return eval("x") })(), 3); @@ -26,39 +26,39 @@ assertEq((function(x) { return eval("x") })(3), 3); assertEq((function(x) { x = 3; return eval("x") })(4), 3); assertEq((function(a) { var [x,y] = a; (function() { x += y })(); return x })([1,2]), 3); -assertEq((function(a) { var [x,y] = a; x += y; return (function() x)() })([1,2]), 3); -assertEq((function(a) { var [[l, x],[m, y]] = a; x += y; return (function() x)() })([[0,1],[0,2]]), 3); +assertEq((function(a) { var [x,y] = a; x += y; return (function() { return x; })() })([1,2]), 3); +assertEq((function(a) { var [[l, x],[m, y]] = a; x += y; return (function() { return x; })() })([[0,1],[0,2]]), 3); assertEq((function(a) { var [x,y] = a; eval('x += y'); return x })([1,2]), 3); assertEq((function(a) { var [x,y] = a; x += y; return eval('x') })([1,2]), 3); assertEq((function(a) { var [x,y] = a; (function() { x += y })(); return x })([1,2]), 3); -assertEq((function(a) { var [x,y] = a; x += y; return (function() x)() })([1,2]), 3); +assertEq((function(a) { var [x,y] = a; x += y; return (function() { return x; })() })([1,2]), 3); assertEq((function(a,x,y) { [x,y] = a; (function() { eval('x += y') })(); return x })([1,2]), 3); -assertEq((function(a,x,y) { [x,y] = a; x += y; return (function() eval('x'))() })([1,2]), 3); +assertEq((function(a,x,y) { [x,y] = a; x += y; return (function() { return eval('x'); })() })([1,2]), 3); -assertEq((function() { var [x,y] = [1,2]; x += y; return (function() x)() })(), 3); -assertEq((function() { var [x,y] = [1,2]; (function() x += y)(); return x })(), 3); -assertEq((function() { { let [x,y] = [1,2]; x += y; return (function() x)() } })(), 3); -assertEq((function() { { let [x,y] = [1,2]; (function() x += y)(); return x } })(), 3); +assertEq((function() { var [x,y] = [1,2]; x += y; return (function() { return x; })() })(), 3); +assertEq((function() { var [x,y] = [1,2]; (function() { return x += y; })(); return x })(), 3); +assertEq((function() { { let [x,y] = [1,2]; x += y; return (function() { return x; })() } })(), 3); +assertEq((function() { { let [x,y] = [1,2]; (function() { return x += y; })(); return x } })(), 3); assertEq((function([x,y]) { (function() { x += y })(); return x })([1,2]), 3); -assertEq((function([x,y]) { x += y; return (function() x)() })([1,2]), 3); +assertEq((function([x,y]) { x += y; return (function() { return x; })() })([1,2]), 3); assertEq((function([[l,x],[m,y]]) { (function() { x += y })(); return x })([[0,1],[0,2]]), 3); -assertEq((function([[l,x],[m,y]]) { x += y; return (function() x)() })([[0,1],[0,2]]), 3); +assertEq((function([[l,x],[m,y]]) { x += y; return (function() { return x; })() })([[0,1],[0,2]]), 3); assertEq((function([x,y]) { (function() { eval('x += y') })(); return x })([1,2]), 3); -assertEq((function([x,y]) { x += y; return (function() eval('x'))() })([1,2]), 3); +assertEq((function([x,y]) { x += y; return (function() { return eval('x'); })() })([1,2]), 3); assertEq((function() { try { throw [1,2] } catch([x,y]) { eval('x += y'); return x }})(), 3); assertEq((function() { try { throw [1,2] } catch([x,y]) { x += y; return eval('x') }})(), 3); assertEq((function() { try { throw [1,2] } catch([x,y]) { (function() { x += y })(); return x }})(), 3); -assertEq((function() { try { throw [1,2] } catch([x,y]) { x += y; return (function() x)() }})(), 3); +assertEq((function() { try { throw [1,2] } catch([x,y]) { x += y; return (function() { return x; })() }})(), 3); assertEq((function() { try { throw [1,2] } catch([x,y]) { (function() { eval('x += y') })(); return x }})(), 3); -assertEq((function() { try { throw [1,2] } catch([x,y]) { x += y; return (function() eval('x'))() }})(), 3); +assertEq((function() { try { throw [1,2] } catch([x,y]) { x += y; return (function() { return eval('x'); })() }})(), 3); assertEq((function(a) { let [x,y] = a; (function() { x += y })(); return x })([1,2]), 3); -assertEq((function(a) { let [x,y] = a; x += y; return (function() x)() })([1,2]), 3); +assertEq((function(a) { let [x,y] = a; x += y; return (function() { return x; })() })([1,2]), 3); assertEq((function(a) { { let [x,y] = a; (function() { x += y })(); return x } })([1,2]), 3); -assertEq((function(a) { { let [x,y] = a; x += y; return (function() x)() } })([1,2]), 3); +assertEq((function(a) { { let [x,y] = a; x += y; return (function() { return x; })() } })([1,2]), 3); assertEq((function(a) { { let [[l, x],[m, y]] = a; (function() { x += y })(); return x } })([[0,1],[0,2]]), 3); -assertEq((function(a) { { let [[l, x],[m, y]] = a; x += y; return (function() x)() } })([[0,1],[0,2]]), 3); +assertEq((function(a) { { let [[l, x],[m, y]] = a; x += y; return (function() { return x; })() } })([[0,1],[0,2]]), 3); assertEq((function() { let x = 3; return (function() { return x })() })(), 3); assertEq((function() { let g = function() { return x }; let x = 3; return g() })(), 3); @@ -69,7 +69,7 @@ assertEq((function() { { let x = 2; x = 3; return (function() { return x })() } assertEq((function() { { let x = 1; { let x = 3; (function() { assertEq(x,3) })() } return x } })(), 1); assertEq((function() { try { throw 3 } catch (e) { (function(){assertEq(e,3)})(); return e } })(), 3); -assertEq((function() { try { throw 3 } catch (e) { assertEq(e, 3); return (function() e)() } })(), 3); +assertEq((function() { try { throw 3 } catch (e) { assertEq(e, 3); return (function() { return e; })() } })(), 3); assertEq((function() { try { throw 3 } catch (e) { (function(){eval('assertEq(e,3)')})(); return e } })(), 3); assertEq((function() { var x; function f() { return x } function f() { return 3 }; return f() })(), 3); diff --git a/js/src/jit-test/tests/debug/Debugger-findScripts-12.js b/js/src/jit-test/tests/debug/Debugger-findScripts-12.js index e3adee20630c..728e63a26342 100644 --- a/js/src/jit-test/tests/debug/Debugger-findScripts-12.js +++ b/js/src/jit-test/tests/debug/Debugger-findScripts-12.js @@ -20,8 +20,9 @@ var dbg = new Debugger(g1, g2, g3); function script(func) { var gw = dbg.addDebuggee(func.global); var script = gw.makeDebuggeeValue(func).script; - script.toString = function () - "[Debugger.Script for " + func.name + " in " + uneval(func.global) + "]"; + script.toString = function () { + return "[Debugger.Script for " + func.name + " in " + uneval(func.global) + "]"; + }; return script; } diff --git a/js/src/jit-test/tests/debug/bug-1240090.js b/js/src/jit-test/tests/debug/bug-1240090.js index 8749a03f3761..028b5b78e5d6 100644 --- a/js/src/jit-test/tests/debug/bug-1240090.js +++ b/js/src/jit-test/tests/debug/bug-1240090.js @@ -1,7 +1,7 @@ gczeal(2); g = newGlobal(); dbg = Debugger(g); -dbg.onNewScript = function() function() this; +dbg.onNewScript = function() { return function() { return this; } }; schedulegc(10); g.eval("setLazyParsingDisabled(true)"); g.evaluate("function one() {}"); diff --git a/js/src/jit-test/tests/debug/bug1240803.js b/js/src/jit-test/tests/debug/bug1240803.js index 84f6d17e592c..1e0a41c29b1d 100644 --- a/js/src/jit-test/tests/debug/bug1240803.js +++ b/js/src/jit-test/tests/debug/bug1240803.js @@ -15,7 +15,7 @@ if (!('oomAfterAllocations' in this)) setBreakpoint; } } - g.eval("" + function f(d) toggle(d)) + g.eval("" + function f(d) { return toggle(d); }) g.eval("(" + function() { f(false); f(true); diff --git a/js/src/jit-test/tests/debug/bug1252453.js b/js/src/jit-test/tests/debug/bug1252453.js index 79f56528f2f0..626d9be62480 100644 --- a/js/src/jit-test/tests/debug/bug1252453.js +++ b/js/src/jit-test/tests/debug/bug1252453.js @@ -13,7 +13,7 @@ file = lfcode.shift(); loadFile(file); function loadFile(lfVarx) { try { - function newFunc(x) Function(x)(); + function newFunc(x) { return Function(x)(); } newFunc(lfVarx)(); } catch (lfVare) { print(lfVare) diff --git a/js/src/jit-test/tests/debug/bug1252464.js b/js/src/jit-test/tests/debug/bug1252464.js index 48c6f8ec075d..d5c976c5f385 100644 --- a/js/src/jit-test/tests/debug/bug1252464.js +++ b/js/src/jit-test/tests/debug/bug1252464.js @@ -3,7 +3,7 @@ g = newGlobal(); dbg = Debugger(g); hits = 0; -dbg.onNewScript = function () hits++; +dbg.onNewScript = function () { return hits++; }; assertEq(g.eval("eval('2 + 3')"), 5); this.gczeal(hits,1); dbg = Debugger(g); diff --git a/js/src/jit-test/tests/debug/bug1275001.js b/js/src/jit-test/tests/debug/bug1275001.js index b8bdc5556079..e25ac7ac3908 100644 --- a/js/src/jit-test/tests/debug/bug1275001.js +++ b/js/src/jit-test/tests/debug/bug1275001.js @@ -20,7 +20,7 @@ function check(expr, expected = expr) { for ([end, err] of[[".random_prop", " is undefined" ]]) statement = "o = {};" + expr + end; cases = [ - function() ieval("var undef;" + statement), + function() { return ieval("var undef;" + statement); }, Function(statement) ] for (f of cases) diff --git a/js/src/jit-test/tests/gc/bug-1016016.js b/js/src/jit-test/tests/gc/bug-1016016.js index 441794c6acf3..7fb6e64d12c5 100644 --- a/js/src/jit-test/tests/gc/bug-1016016.js +++ b/js/src/jit-test/tests/gc/bug-1016016.js @@ -1,7 +1,8 @@ // |jit-test| error:ReferenceError toPrinted(this.reason); -function toPrinted(value) - value = String(value); +function toPrinted(value) { + return value = String(value); +} var lfcode = new Array(); lfcode.push = loadFile; lfcode.push("enableTrackAllocations();"); diff --git a/js/src/jit-test/tests/gc/bug-1136597.js b/js/src/jit-test/tests/gc/bug-1136597.js index 2a9e9d190535..f4092b66d64b 100644 --- a/js/src/jit-test/tests/gc/bug-1136597.js +++ b/js/src/jit-test/tests/gc/bug-1136597.js @@ -8,8 +8,9 @@ var evalInFrame = (function (global) { })(this); var gTestcases = new Array(); var gTc = gTestcases.length; -function TestCase() - gTestcases[gTc++] = this; +function TestCase() { + return gTestcases[gTc++] = this; +} function checkCollation(extensionCoValue, usageValue) { var collator = new Intl.Collator(["de-DE"]); collator.resolvedOptions().collation; diff --git a/js/src/jit-test/tests/gc/bug-1155455.js b/js/src/jit-test/tests/gc/bug-1155455.js index 6516d2105d88..5ca127696871 100644 --- a/js/src/jit-test/tests/gc/bug-1155455.js +++ b/js/src/jit-test/tests/gc/bug-1155455.js @@ -5,8 +5,9 @@ var g = newGlobal(); gczeal(10, 2) var dbg = Debugger(g); dbg.onDebuggerStatement = function (frame1) { - function hit(frame2) - hit[0] = "mutated"; + function hit(frame2) { + return hit[0] = "mutated"; + } var s = frame1.script; var offs = s.getLineOffsets(g.line0 + 2); for (var i = 0; i < offs.length; i++) diff --git a/js/src/jit-test/tests/gc/bug-1252103.js b/js/src/jit-test/tests/gc/bug-1252103.js index 7c2bc361b473..88ed32e36f88 100644 --- a/js/src/jit-test/tests/gc/bug-1252103.js +++ b/js/src/jit-test/tests/gc/bug-1252103.js @@ -15,7 +15,7 @@ function foo() { LineType = new TO.StructType({ PointType }) - function testBasic() new LineType; + function testBasic() { return new LineType; } testBasic(); } evaluate("foo()"); diff --git a/js/src/jit-test/tests/gc/bug-1261329.js b/js/src/jit-test/tests/gc/bug-1261329.js index 6a4a30761847..88527ce51c70 100644 --- a/js/src/jit-test/tests/gc/bug-1261329.js +++ b/js/src/jit-test/tests/gc/bug-1261329.js @@ -2,9 +2,9 @@ if (!('oomTest' in this)) quit(); print = function() {} -function k() dissrc(print); -function j() k(); -function h() j(); -function f() h(); +function k() { return dissrc(print); } +function j() { return k(); } +function h() { return j(); } +function f() { return h(); } f(); oomTest(() => f()) diff --git a/js/src/jit-test/tests/gc/bug-1263871.js b/js/src/jit-test/tests/gc/bug-1263871.js index 96bbf50b992c..1aabb5ffdb72 100644 --- a/js/src/jit-test/tests/gc/bug-1263871.js +++ b/js/src/jit-test/tests/gc/bug-1263871.js @@ -4,5 +4,6 @@ if (!('oomTest' in this)) lfLogBuffer = `this[''] = function() {}`; loadFile(lfLogBuffer); loadFile(lfLogBuffer); -function loadFile(lfVarx) - oomTest(function() parseModule(lfVarx)) +function loadFile(lfVarx) { + return oomTest(function() { return parseModule(lfVarx); }); +} diff --git a/js/src/jit-test/tests/gc/bug-1305220.js b/js/src/jit-test/tests/gc/bug-1305220.js index 30d3fa26038e..a8e58be71d46 100644 --- a/js/src/jit-test/tests/gc/bug-1305220.js +++ b/js/src/jit-test/tests/gc/bug-1305220.js @@ -15,8 +15,8 @@ evalcx("\ g.h = function() {\ g.oomAfterAllocations(1);\ };\ - g.eval(\"\" + function f() g());\ - g.eval(\"\" + function g() h());\ + g.eval(\"\" + function f() { return g(); });\ + g.eval(\"\" + function g() { return h(); });\ g.eval(\"(\" + function() {\ f();\ } + \")()\");\ diff --git a/js/src/jit-test/tests/gc/bug-1310589.js b/js/src/jit-test/tests/gc/bug-1310589.js index 67292283209f..e332263d86b7 100644 --- a/js/src/jit-test/tests/gc/bug-1310589.js +++ b/js/src/jit-test/tests/gc/bug-1310589.js @@ -12,7 +12,7 @@ for (var i = 0; i < 4; ++i) { function f1() {} } Object.defineProperty(a, 12, {}).push(1); -toString = (function() a.reverse()) +toString = (function() { return a.reverse(); }) oomTest(Date.prototype.toJSON) function f1000(){} function f1001(){} diff --git a/js/src/jit-test/tests/gc/bug-906243.js b/js/src/jit-test/tests/gc/bug-906243.js index 78264917bf0e..d4088d10f967 100644 --- a/js/src/jit-test/tests/gc/bug-906243.js +++ b/js/src/jit-test/tests/gc/bug-906243.js @@ -1,7 +1,7 @@ // |jit-test| need-for-each a2 = [] -g = function() r +g = function() { return r; }; Object.defineProperty(a2, 0, { set: function() {} }) diff --git a/js/src/jit-test/tests/gc/bug-945275.js b/js/src/jit-test/tests/gc/bug-945275.js index 42e63a55c777..26cdb23d3cc9 100644 --- a/js/src/jit-test/tests/gc/bug-945275.js +++ b/js/src/jit-test/tests/gc/bug-945275.js @@ -4,7 +4,7 @@ function TestCase(n) { } gczeal(7,1); eval("\ -function reportCompare() new TestCase;\ +function reportCompare() { return new TestCase; };\ reportCompare();\ Object.defineProperty(Object.prototype, 'name', {});\ reportCompare();\ diff --git a/js/src/jit-test/tests/gc/bug-957114.js b/js/src/jit-test/tests/gc/bug-957114.js index f245786b96e5..5c61c8210bb4 100644 --- a/js/src/jit-test/tests/gc/bug-957114.js +++ b/js/src/jit-test/tests/gc/bug-957114.js @@ -7,7 +7,7 @@ function TestCase(n) { this.reason = ''; this.passed = ''; } -function test() new TestCase; +function test() { return new TestCase; } test(); Object.defineProperty(Object.prototype, "name", {}); test(); diff --git a/js/src/jit-test/tests/gc/bug-961877.js b/js/src/jit-test/tests/gc/bug-961877.js index 697f6c197c59..37b146feafdf 100644 --- a/js/src/jit-test/tests/gc/bug-961877.js +++ b/js/src/jit-test/tests/gc/bug-961877.js @@ -4,7 +4,7 @@ gczeal(2,300); evaluate("\ var toFloat32 = (function() {\ var f32 = new Float32Array(1);\ - function f(x) f32[0] = x;\ + function f(x) { return f32[0] = x; }\ return f;\ })();\ for (var i = 0; i < 64; ++i) {\ diff --git a/js/src/jit-test/tests/gc/bug-981295.js b/js/src/jit-test/tests/gc/bug-981295.js index 691c06bde904..0f570bf73d2c 100644 --- a/js/src/jit-test/tests/gc/bug-981295.js +++ b/js/src/jit-test/tests/gc/bug-981295.js @@ -1,7 +1,7 @@ var NotEarlyErrorString = "NotEarlyError"; var NotEarlyError = new Error(NotEarlyErrorString); var juneDate = new Date(2000, 5, 20, 0, 0, 0, 0); -for (var i = 0; i < function(x) myObj(Date.prototype.toString.apply(x)); void i) { +for (var i = 0; i < function(x) { return myObj(Date.prototype.toString.apply(x)); }; void i) { eval(a.text.replace(/@/g, "")) } gcslice(2601); diff --git a/js/src/jit-test/tests/gc/oomInDtoa.js b/js/src/jit-test/tests/gc/oomInDtoa.js index f006d36b0035..4a7113e098d3 100644 --- a/js/src/jit-test/tests/gc/oomInDtoa.js +++ b/js/src/jit-test/tests/gc/oomInDtoa.js @@ -1,4 +1,4 @@ if (!('oomTest' in this)) quit(); -oomTest(function() 1e300) +oomTest(function() { return 1e300; }) diff --git a/js/src/jit-test/tests/ion/bug1215600.js b/js/src/jit-test/tests/ion/bug1215600.js index 662e64bd9c3f..8bb350916956 100644 --- a/js/src/jit-test/tests/ion/bug1215600.js +++ b/js/src/jit-test/tests/ion/bug1215600.js @@ -12,7 +12,7 @@ function loadFile(lfVarx) { if (lfVarx.length != 1) switch (lfRunTypeId) { case 3: - function newFunc(x) Function(x)() + function newFunc(x) { return Function(x)(); } newFunc(lfVarx) case 5: for (lfLocal in this); diff --git a/js/src/jit-test/tests/ion/bug1264948.js b/js/src/jit-test/tests/ion/bug1264948.js index 833188aaab54..cb76e22cb7a1 100644 --- a/js/src/jit-test/tests/ion/bug1264948.js +++ b/js/src/jit-test/tests/ion/bug1264948.js @@ -10,8 +10,9 @@ loadFile(` whatever.push; } testGC(o) - function writeObject() - o.f = v + function writeObject() { + return o.f = v; + } writeObject({function() { } }) for (var i ; i < 5 ; ++i) try {} catch (StringStruct) {} diff --git a/js/src/jit-test/tests/ion/bug1284491.js b/js/src/jit-test/tests/ion/bug1284491.js index f04653a18afe..94e096af0dc4 100644 --- a/js/src/jit-test/tests/ion/bug1284491.js +++ b/js/src/jit-test/tests/ion/bug1284491.js @@ -11,5 +11,5 @@ loadFile(` SwitchTest(); `) function loadFile(lfVarx) { - oomTest(function() eval(lfVarx)) + oomTest(function() { return eval(lfVarx); }) } diff --git a/js/src/jit-test/tests/ion/bug1299007.js b/js/src/jit-test/tests/ion/bug1299007.js index fb7f15184d5c..e3c90645a134 100644 --- a/js/src/jit-test/tests/ion/bug1299007.js +++ b/js/src/jit-test/tests/ion/bug1299007.js @@ -16,8 +16,8 @@ function h() { evalInFrame(0, "a.push") evalInFrame(1, "a.pushy") } -function g() h() -function f() g() +function g() { return h(); } +function f() { return g(); } f() evaluate(` g() diff --git a/js/src/jit-test/tests/ion/bug691747.js b/js/src/jit-test/tests/ion/bug691747.js index 94c37ff59de0..117899d69dc9 100644 --- a/js/src/jit-test/tests/ion/bug691747.js +++ b/js/src/jit-test/tests/ion/bug691747.js @@ -1,4 +1,4 @@ -function reportCompare(actual) - ++actual + "'"; +function reportCompare(actual) { return - ++actual + "'"; } var UBound = 0; var actualvalues = []; for (var li = 0; li < 6; ++li) addThis(); diff --git a/js/src/jit-test/tests/ion/bug724944.js b/js/src/jit-test/tests/ion/bug724944.js index 2433f12cd3e9..0b73ca7a7744 100644 --- a/js/src/jit-test/tests/ion/bug724944.js +++ b/js/src/jit-test/tests/ion/bug724944.js @@ -1,5 +1,6 @@ -function TestCase(n, d, e, a) -function writeHeaderToLog( string ) {} +function TestCase(n, d, e, a) { + return function writeHeaderToLog( string ) {}; +} var SECTION = "15.1.2.5-2"; for ( var CHARCODE = 0; CHARCODE < 256; CHARCODE += 16 ) { new TestCase( SECTION, unescape( "%" + (ToHexString(CHARCODE)).substring(0,1) ) ); diff --git a/js/src/jit-test/tests/ion/bug729573.js b/js/src/jit-test/tests/ion/bug729573.js index 6ad21c4eb098..f8cf3318dfbc 100644 --- a/js/src/jit-test/tests/ion/bug729573.js +++ b/js/src/jit-test/tests/ion/bug729573.js @@ -1,5 +1,6 @@ -function TestCase(n, d, e, a) -function writeHeaderToLog( string ) {} +function TestCase(n, d, e, a) { + return function writeHeaderToLog( string ) {}; +} var SECTION = "11.7.2"; for ( power = 0; power <= 32; power++ ) { shiftexp = Math.pow( 2, power ); diff --git a/js/src/jit-test/tests/ion/bug729788.js b/js/src/jit-test/tests/ion/bug729788.js index 8eae68ceb81f..8297e2a1ea90 100644 --- a/js/src/jit-test/tests/ion/bug729788.js +++ b/js/src/jit-test/tests/ion/bug729788.js @@ -8,7 +8,7 @@ function YearFromTime(t) { } function MonthFromTime(t) { DayWithinYear(t) - function DayWithinYear(t) Day(t) - YearFromTime() + function DayWithinYear(t) { return Day(t) - YearFromTime(); } function WeekDay(t) { weekday = Day(t) + 4 return (weekday < 0 ? weekday : weekday); diff --git a/js/src/jit-test/tests/ion/bug732851.js b/js/src/jit-test/tests/ion/bug732851.js index b704bfe1c1b3..6e249c716d7c 100644 --- a/js/src/jit-test/tests/ion/bug732851.js +++ b/js/src/jit-test/tests/ion/bug732851.js @@ -2,8 +2,9 @@ var OMIT = {}; var WRITABLES = [true, false, OMIT]; { var desc = {}; - function put(field, value) - desc[field] = value; + function put(field, value) { + return desc[field] = value; + } WRITABLES.forEach(function(writable) { put("writable", writable) }); diff --git a/js/src/jit-test/tests/ion/bug732859.js b/js/src/jit-test/tests/ion/bug732859.js index c68e9af02446..bde07e7baf79 100644 --- a/js/src/jit-test/tests/ion/bug732859.js +++ b/js/src/jit-test/tests/ion/bug732859.js @@ -1,5 +1,6 @@ -function TestCase(n, d, e, a) -function writeHeaderToLog( string ) {} +function TestCase(n, d, e, a) { + return function writeHeaderToLog( string ) {}; +} var SECTION = "15.1.2.4"; for ( var CHARCODE = 128; CHARCODE < 256; CHARCODE++ ) { new TestCase( SECTION, "%"+ToHexString(CHARCODE), escape(String.fromCharCode(CHARCODE))); diff --git a/js/src/jit-test/tests/ion/bug756780.js b/js/src/jit-test/tests/ion/bug756780.js index a82163cec109..a252d2c24c19 100644 --- a/js/src/jit-test/tests/ion/bug756780.js +++ b/js/src/jit-test/tests/ion/bug756780.js @@ -4,5 +4,6 @@ var status = ''; var statusmessages = new Array(); addThis(); addThis(); -function addThis() - statusmessages[i] = status; +function addThis() { + return statusmessages[i] = status; +} diff --git a/js/src/jit-test/tests/ion/bug819865.js b/js/src/jit-test/tests/ion/bug819865.js index 7c0f4d4aa111..db198594ef11 100644 --- a/js/src/jit-test/tests/ion/bug819865.js +++ b/js/src/jit-test/tests/ion/bug819865.js @@ -1,2 +1,2 @@ -(function x() (x == x))(); +(function x() { return (x == x); })(); diff --git a/js/src/jit-test/tests/ion/bug852140.js b/js/src/jit-test/tests/ion/bug852140.js index 9d9986996b2b..159e2d57e4a5 100644 --- a/js/src/jit-test/tests/ion/bug852140.js +++ b/js/src/jit-test/tests/ion/bug852140.js @@ -1,7 +1,8 @@ function reportCompare (expected, actual) { if (expected != actual) {} } -function exitFunc (funcName) - reportCompare(undefined, ''); +function exitFunc (funcName) { + return reportCompare(undefined, ''); +} reportCompare('', ''); exitFunc(); diff --git a/js/src/jit-test/tests/ion/bug852174.js b/js/src/jit-test/tests/ion/bug852174.js index 8d28781bb11a..2adc718a9d57 100644 --- a/js/src/jit-test/tests/ion/bug852174.js +++ b/js/src/jit-test/tests/ion/bug852174.js @@ -1,9 +1,12 @@ -function eval() - isPrototypeOf[Iterator.length] -function DoWhile_3() - eval(); +function eval() { + return isPrototypeOf[Iterator.length]; +} +function DoWhile_3() { + return eval(); +} DoWhile_3(); -function f() - DoWhile_3(f - 0); +function f() { + return DoWhile_3(f - 0); +} for (var i in f()); diff --git a/js/src/jit-test/tests/ion/bug862100.js b/js/src/jit-test/tests/ion/bug862100.js index d50b28abda83..4ba973c040f5 100644 --- a/js/src/jit-test/tests/ion/bug862100.js +++ b/js/src/jit-test/tests/ion/bug862100.js @@ -9,6 +9,6 @@ evaluate("\ function TestCase(n, d, e, a) {}\ test_negation(-2147483648, 2147483648);\ test_negation(2147483647, -2147483647);\ -function test_negation(value, expected)\ +function test_negation(value, expected) {\ reportCompare(expected, '', '-(' + value + ') == ' + expected);\ -"); +}"); diff --git a/js/src/jit-test/tests/ion/bug862357.js b/js/src/jit-test/tests/ion/bug862357.js index df96dc83b08b..2a44c525d5d4 100644 --- a/js/src/jit-test/tests/ion/bug862357.js +++ b/js/src/jit-test/tests/ion/bug862357.js @@ -1,6 +1,7 @@ // |jit-test| error: ReferenceError -function TestCase(e, a) - this.passed = (e == a); +function TestCase(e, a) { + return this.passed = (e == a); +} function reportCompare (expected, actual) { var expected_t = typeof expected; var actual_t = typeof actual; diff --git a/js/src/jit-test/tests/ion/recover-lambdas-bug1118911.js b/js/src/jit-test/tests/ion/recover-lambdas-bug1118911.js index 7c27d395438e..d1e43cb71755 100644 --- a/js/src/jit-test/tests/ion/recover-lambdas-bug1118911.js +++ b/js/src/jit-test/tests/ion/recover-lambdas-bug1118911.js @@ -1,7 +1,8 @@ function test() { - function f() - k.apply(this, arguments); + function f() { + return k.apply(this, arguments); + } if (undefined >> undefined !== 0) {} for (var [ v , c ] in this.tracemonkey) { } } diff --git a/js/src/jit-test/tests/jaeger/bug549396.js b/js/src/jit-test/tests/jaeger/bug549396.js index 9fbefe4f8623..f0d61475b7fd 100644 --- a/js/src/jit-test/tests/jaeger/bug549396.js +++ b/js/src/jit-test/tests/jaeger/bug549396.js @@ -1 +1 @@ -x = this.__defineSetter__("x", function(z) function() { z }) +x = this.__defineSetter__("x", function(z) { return function() { z }; }) diff --git a/js/src/jit-test/tests/jaeger/bug819035.js b/js/src/jit-test/tests/jaeger/bug819035.js index c1efd3875349..846310b2a2c9 100644 --- a/js/src/jit-test/tests/jaeger/bug819035.js +++ b/js/src/jit-test/tests/jaeger/bug819035.js @@ -8,7 +8,7 @@ (function () { (function r(t) { t !== u, - sum(t, function (v) r(v) ); + sum(t, function (v) { return r(v); } ); })(arguments); })(a); }) ( diff --git a/js/src/jit-test/tests/jaeger/loops/bug659452.js b/js/src/jit-test/tests/jaeger/loops/bug659452.js index cf5015c7270f..6cc3f4d46585 100644 --- a/js/src/jit-test/tests/jaeger/loops/bug659452.js +++ b/js/src/jit-test/tests/jaeger/loops/bug659452.js @@ -1,5 +1,5 @@ test(); function test() { - var t = function () function printStatus() {}; + var t = function () { return function printStatus() {}; }; for (var j = 0; j < 10; j++) t["-1"] } diff --git a/js/src/jit-test/tests/jaeger/recompile/bug647199.js b/js/src/jit-test/tests/jaeger/recompile/bug647199.js index b9d330f8fc16..d8ad7994a6f5 100644 --- a/js/src/jit-test/tests/jaeger/recompile/bug647199.js +++ b/js/src/jit-test/tests/jaeger/recompile/bug647199.js @@ -2,7 +2,7 @@ TryInWhile( new TryObject( "hello", ThrowException, true ) ); function TryObject( value, throwFunction, result ) { this.thrower=throwFunction } -function ThrowException() TryInWhile(1); +function ThrowException() { return TryInWhile(1); } function TryInWhile( object ) { try { object.thrower() diff --git a/js/src/jit-test/tests/jaeger/recompile/bug658212.js b/js/src/jit-test/tests/jaeger/recompile/bug658212.js index a18764923486..e462770b5623 100644 --- a/js/src/jit-test/tests/jaeger/recompile/bug658212.js +++ b/js/src/jit-test/tests/jaeger/recompile/bug658212.js @@ -3,10 +3,13 @@ function TestCase(n, d, e, a) { this.description = d gTestcases[gTc] = this } -TestCase.prototype.dump=function () + + + +TestCase.prototype.dump=function () { return + + + + this.description + + - + + '\n';function printStatus (msg) -function toPrinted(value) { + + + '\n'; +}; +function printStatus (msg) { + return function toPrinted(value) { + }; } function reportCompare(expected, actual, description) { new TestCase("unknown-test-name", description, expected, actual) diff --git a/js/src/jit-test/tests/jaeger/recompile/bug658561.js b/js/src/jit-test/tests/jaeger/recompile/bug658561.js index ad10b3dac310..a8c0937c0063 100644 --- a/js/src/jit-test/tests/jaeger/recompile/bug658561.js +++ b/js/src/jit-test/tests/jaeger/recompile/bug658561.js @@ -1,5 +1,5 @@ var s1 = 'xx'; for (var x = 0; x < 10 ; ++x ) { - new function() s1++; + new function() { return s1++; }; gc(); } diff --git a/js/src/jit-test/tests/jaeger/recompile/bug658777.js b/js/src/jit-test/tests/jaeger/recompile/bug658777.js index 9bc6854f4355..7f6ec16e15f5 100644 --- a/js/src/jit-test/tests/jaeger/recompile/bug658777.js +++ b/js/src/jit-test/tests/jaeger/recompile/bug658777.js @@ -1,4 +1,4 @@ -function Employee(name, dept) this.name = name || ""; +function Employee(name, dept) { return this.name = name || ""; } function WorkerBee(name, dept, projs) { this.base = Employee this.base(name, dept) diff --git a/js/src/jit-test/tests/jaeger/recompile/bug659766.js b/js/src/jit-test/tests/jaeger/recompile/bug659766.js index 012447ba438d..fac969288bb7 100644 --- a/js/src/jit-test/tests/jaeger/recompile/bug659766.js +++ b/js/src/jit-test/tests/jaeger/recompile/bug659766.js @@ -5,8 +5,8 @@ function TestCase(n, d, e, a) { this.reason='' gTestcases[gTc++]=this } -TestCase.prototype.dump=function () + toPrinted(this.description) + toPrinted(this.reason) + '\n'; -function toPrinted(value) value=value.replace(/\\n/g, 'NL').replace(/[^\x20-\x7E]+/g, escapeString); +TestCase.prototype.dump=function () { return + toPrinted(this.description) + toPrinted(this.reason) + '\n'; }; +function toPrinted(value) { return value=value.replace(/\\n/g, 'NL').replace(/[^\x20-\x7E]+/g, escapeString); } function escapeString (str) { try { err @@ -18,7 +18,7 @@ function jsTestDriverEnd() { } var SECTION = "dowhile-007"; DoWhile(); -function DoWhile( object ) result1=false; +function DoWhile( object ) { return result1=false; } new TestCase( SECTION, "break one: ", diff --git a/js/src/jit-test/tests/jaeger/recompile/bug661859.js b/js/src/jit-test/tests/jaeger/recompile/bug661859.js index b99e301a139e..f0ca2400f550 100644 --- a/js/src/jit-test/tests/jaeger/recompile/bug661859.js +++ b/js/src/jit-test/tests/jaeger/recompile/bug661859.js @@ -1,4 +1,4 @@ -function TestCase(n, d, e, a) this.expect = e; +function TestCase(n, d, e, a) { return this.expect = e; } function reportCompare(expected, actual, description) { typeof actual } @@ -15,7 +15,7 @@ function notInlined(f) { } function test(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z) { try { - p = [1].some(notInlined(function (y) test())) ? 4 : 0x0041; + p = [1].some(notInlined(function (y) { return test(); })) ? 4 : 0x0041; } catch (ex) {} reportCompare(expect, actual, summary) } diff --git a/js/src/jit-test/tests/modules/bug-1233915.js b/js/src/jit-test/tests/modules/bug-1233915.js index 98370ab6f1a1..cef016f5da4f 100644 --- a/js/src/jit-test/tests/modules/bug-1233915.js +++ b/js/src/jit-test/tests/modules/bug-1233915.js @@ -2,8 +2,9 @@ g = newGlobal(); g.parent = this; g.eval("(" + function() { Debugger(parent) - .onExceptionUnwind = function(frame) - frame.eval("") + .onExceptionUnwind = function(frame) { + return frame.eval(""); + }; } + ")()"); m = parseModule(` s1 `); m.declarationInstantiation(); diff --git a/js/src/jit-test/tests/modules/bug-1245518.js b/js/src/jit-test/tests/modules/bug-1245518.js index 3ba79645b739..0621d68c2162 100644 --- a/js/src/jit-test/tests/modules/bug-1245518.js +++ b/js/src/jit-test/tests/modules/bug-1245518.js @@ -8,7 +8,7 @@ evalInFrame = function(global) { } }(this); m = parseModule(` - function g() this.hours = 0; + function g() { return this.hours = 0; } evalInFrame.call(0, 0, "g()") `); m.declarationInstantiation(); diff --git a/js/src/jit-test/tests/parser/bug-1263355-16.js b/js/src/jit-test/tests/parser/bug-1263355-16.js index 2bb173c8a395..df66d9593b94 100644 --- a/js/src/jit-test/tests/parser/bug-1263355-16.js +++ b/js/src/jit-test/tests/parser/bug-1263355-16.js @@ -3,8 +3,9 @@ let m = parseModule(` var i = 0; addThis(); -function addThis() - statusmessages[i] = Number; +function addThis() { + return statusmessages[i] = Number; +} `); m.declarationInstantiation(); m.evaluation(); diff --git a/js/src/jit-test/tests/pic/arguments.js b/js/src/jit-test/tests/pic/arguments.js index ffe75e8db035..0ca82f690d9f 100644 --- a/js/src/jit-test/tests/pic/arguments.js +++ b/js/src/jit-test/tests/pic/arguments.js @@ -18,6 +18,6 @@ function g(arg) { return r; } -assertEq(g((function () arguments).call(null, 1, 2, 3)), 3); +assertEq(g((function () { return arguments; }).call(null, 1, 2, 3)), 3); assertEq(g(new Float32Array(3)), 0.0); assertEq(g([1, 2, 3, 4]), 4); diff --git a/js/src/jit-test/tests/pic/bug558099.js b/js/src/jit-test/tests/pic/bug558099.js index b3a5a6e5ab46..46396f2130d1 100644 --- a/js/src/jit-test/tests/pic/bug558099.js +++ b/js/src/jit-test/tests/pic/bug558099.js @@ -1,6 +1,6 @@ // |jit-test| need-for-each -(function()[function() function() function() function() function() function() {}]); +(function() { return [function() { return function() { return function() { return function() { return function() { return function() {}; }; }; }; }; }]; }); foo = [{ text: "(function(){if(d){(1)}})", s: function() {}, @@ -47,9 +47,9 @@ foo = [{ if (a.test()) {} } } ()); -s = [function() function() function() function() function() function() {}] -[function() function() function() function() {}]; -(function() { [function() function() {}] }); +s = [function() { return function() { return function() { return function() { return function() { return function() {}; }; }; }; }; }] +[function() { return function() { return function() { return function() {}; }; }; }]; +(function() { [function() { return function() {}; }] }); (function() {}); (eval("\ (function(){\ diff --git a/js/src/jit-test/tests/profiler/bug1164448.js b/js/src/jit-test/tests/profiler/bug1164448.js index 3c66985fa281..33dfea804942 100644 --- a/js/src/jit-test/tests/profiler/bug1164448.js +++ b/js/src/jit-test/tests/profiler/bug1164448.js @@ -2,8 +2,9 @@ print = function(s) { return s.toString(); } var gTestcases = new Array(); -function TestCase(n, d, e, a) - gTestcases[gTc++] = this; +function TestCase(n, d, e, a) { + return gTestcases[gTc++] = this; +} dump = print; for ( gTc=0; gTc < gTestcases.length; gTc++ ) {} function jsTestDriverEnd() { diff --git a/js/src/jit-test/tests/profiler/bug1242840.js b/js/src/jit-test/tests/profiler/bug1242840.js index 31fe1c27fba8..8e7e6a0ee1a3 100644 --- a/js/src/jit-test/tests/profiler/bug1242840.js +++ b/js/src/jit-test/tests/profiler/bug1242840.js @@ -10,7 +10,7 @@ oomTest(() => { case 0: let x case 1: - (function() x)() + (function() { return x; })() } } }) diff --git a/js/src/jit-test/tests/profiler/bug1261324.js b/js/src/jit-test/tests/profiler/bug1261324.js index 366e79e44866..9eb1de281f41 100644 --- a/js/src/jit-test/tests/profiler/bug1261324.js +++ b/js/src/jit-test/tests/profiler/bug1261324.js @@ -18,7 +18,7 @@ function assertThrowsInstanceOf(f) { function testThrow(thunk) { for (i = 0; i < 20; i++) { iter = thunk() - assertThrowsInstanceOf(function() iter.throw()) + assertThrowsInstanceOf(function() { return iter.throw(); }) } } testThrow(function*() {}) diff --git a/js/src/jit-test/tests/profiler/test-bug1026485.js b/js/src/jit-test/tests/profiler/test-bug1026485.js index 22865f526562..705c8089a3c7 100644 --- a/js/src/jit-test/tests/profiler/test-bug1026485.js +++ b/js/src/jit-test/tests/profiler/test-bug1026485.js @@ -1,6 +1,7 @@ -function TestCase(n, d, e, a) - TestCase.prototype.dump = function () {} +function TestCase(n, d, e, a) { + return TestCase.prototype.dump = function () {}; +} enableSPSProfiling(); new TestCase(typeof Number(new Number())); new TestCase(typeof Number(new Number(Number.NaN))); diff --git a/js/src/jit/BaselineCacheIR.cpp b/js/src/jit/BaselineCacheIR.cpp index 434e6e2a6294..bc56e8628655 100644 --- a/js/src/jit/BaselineCacheIR.cpp +++ b/js/src/jit/BaselineCacheIR.cpp @@ -512,14 +512,6 @@ class MOZ_RAII BaselineCacheIRCompiler : public CacheIRCompiler *failure = &failurePaths.back(); return true; } - void emitEnterTypeMonitorIC() { - allocator.discardStack(masm); - EmitEnterTypeMonitorIC(masm); - } - void emitReturnFromIC() { - allocator.discardStack(masm); - EmitReturnFromIC(masm); - } }; void @@ -604,6 +596,8 @@ BaselineCacheIRCompiler::compile() allocator.nextOp(); } while (reader.more()); + masm.assumeUnreachable("Should have returned from IC"); + // Done emitting the main IC code. Now emit the failure paths. for (size_t i = 0; i < failurePaths.length(); i++) { emitFailurePath(i); @@ -1057,7 +1051,6 @@ BaselineCacheIRCompiler::emitLoadFixedSlotResult() masm.load32(stubAddress(reader.stubOffset()), scratch); masm.loadValue(BaseIndex(obj, scratch, TimesOne), R0); - emitEnterTypeMonitorIC(); return true; } @@ -1071,7 +1064,6 @@ BaselineCacheIRCompiler::emitLoadDynamicSlotResult() masm.load32(stubAddress(reader.stubOffset()), scratch); masm.loadPtr(Address(obj, NativeObject::offsetOfSlots()), obj); masm.loadValue(BaseIndex(obj, scratch, TimesOne), R0); - emitEnterTypeMonitorIC(); return true; } @@ -1142,8 +1134,6 @@ BaselineCacheIRCompiler::emitCallScriptedGetterResult() masm.callJit(code); leaveStubFrame(masm, true); - - emitEnterTypeMonitorIC(); return true; } @@ -1180,8 +1170,6 @@ BaselineCacheIRCompiler::emitCallNativeGetterResult() return false; leaveStubFrame(masm); - - emitEnterTypeMonitorIC(); return true; } @@ -1192,16 +1180,9 @@ BaselineCacheIRCompiler::emitLoadUnboxedPropertyResult() AutoScratchRegister scratch(allocator, masm); JSValueType fieldType = reader.valueType(); - Address fieldOffset(stubAddress(reader.stubOffset())); masm.load32(fieldOffset, scratch); masm.loadUnboxedProperty(BaseIndex(obj, scratch, TimesOne), fieldType, R0); - - if (fieldType == JSVAL_TYPE_OBJECT) - emitEnterTypeMonitorIC(); - else - emitReturnFromIC(); - return true; } @@ -1234,18 +1215,12 @@ BaselineCacheIRCompiler::emitLoadTypedObjectResult() masm.load32(fieldOffset, scratch2); masm.addPtr(scratch2, scratch1); - // Only monitor the result if the type produced by this stub might vary. - bool monitorLoad; if (SimpleTypeDescrKeyIsScalar(typeDescr)) { Scalar::Type type = ScalarTypeFromSimpleTypeDescrKey(typeDescr); - monitorLoad = type == Scalar::Uint32; - masm.loadFromTypedArray(type, Address(scratch1, 0), R0, /* allowDouble = */ true, scratch2, nullptr); } else { ReferenceTypeDescr::Type type = ReferenceTypeFromSimpleTypeDescrKey(typeDescr); - monitorLoad = type != ReferenceTypeDescr::TYPE_STRING; - switch (type) { case ReferenceTypeDescr::TYPE_ANY: masm.loadValue(Address(scratch1, 0), R0); @@ -1273,10 +1248,6 @@ BaselineCacheIRCompiler::emitLoadTypedObjectResult() } } - if (monitorLoad) - emitEnterTypeMonitorIC(); - else - emitReturnFromIC(); return true; } @@ -1284,11 +1255,6 @@ bool BaselineCacheIRCompiler::emitLoadUndefinedResult() { masm.moveValue(UndefinedValue(), R0); - - // Normally for this op, the result would have to be monitored by TI. - // However, since this stub ALWAYS returns UndefinedValue(), and we can be sure - // that undefined is already registered with the type-set, this can be avoided. - emitReturnFromIC(); return true; } @@ -1308,10 +1274,6 @@ BaselineCacheIRCompiler::emitLoadInt32ArrayLengthResult() // Guard length fits in an int32. masm.branchTest32(Assembler::Signed, scratch, scratch, failure->label()); masm.tagValue(JSVAL_TYPE_INT32, scratch, R0); - - // The int32 type was monitored when attaching the stub, so we can - // just return. - emitReturnFromIC(); return true; } @@ -1321,10 +1283,6 @@ BaselineCacheIRCompiler::emitLoadUnboxedArrayLengthResult() Register obj = allocator.useRegister(masm, reader.objOperandId()); masm.load32(Address(obj, UnboxedArrayObject::offsetOfLength()), R0.scratchReg()); masm.tagValue(JSVAL_TYPE_INT32, R0.scratchReg(), R0); - - // The int32 type was monitored when attaching the stub, so we can - // just return. - emitReturnFromIC(); return true; } @@ -1351,7 +1309,22 @@ BaselineCacheIRCompiler::emitLoadArgumentsObjectLengthResult() // because this stub always returns int32. masm.rshiftPtr(Imm32(ArgumentsObject::PACKED_BITS_COUNT), scratch); masm.tagValue(JSVAL_TYPE_INT32, scratch, R0); - emitReturnFromIC(); + return true; +} + +bool +BaselineCacheIRCompiler::emitTypeMonitorResult() +{ + allocator.discardStack(masm); + EmitEnterTypeMonitorIC(masm); + return true; +} + +bool +BaselineCacheIRCompiler::emitReturnFromIC() +{ + allocator.discardStack(masm); + EmitReturnFromIC(masm); return true; } diff --git a/js/src/jit/CacheIR.cpp b/js/src/jit/CacheIR.cpp index dc9a870075c5..f540fd8c8853 100644 --- a/js/src/jit/CacheIR.cpp +++ b/js/src/jit/CacheIR.cpp @@ -245,6 +245,21 @@ EmitReadSlotResult(CacheIRWriter& writer, JSObject* obj, JSObject* holder, } } +static void +EmitReadSlotReturn(CacheIRWriter& writer, JSObject*, JSObject* holder, Shape* shape) +{ + // Slot access. + if (holder) { + MOZ_ASSERT(shape); + writer.typeMonitorResult(); + } else { + // Normally for this op, the result would have to be monitored by TI. + // However, since this stub ALWAYS returns UndefinedValue(), and we can be sure + // that undefined is already registered with the type-set, this can be avoided. + writer.returnFromIC(); + } +} + static void EmitCallGetterResult(CacheIRWriter& writer, JSObject* obj, JSObject* holder, Shape* shape, ObjOperandId objId) @@ -264,6 +279,7 @@ EmitCallGetterResult(CacheIRWriter& writer, JSObject* obj, JSObject* holder, JSFunction* target = &shape->getterValue().toObject().as(); MOZ_ASSERT(target->isNative()); writer.callNativeGetterResult(objId, target); + writer.typeMonitorResult(); return; } @@ -272,6 +288,7 @@ EmitCallGetterResult(CacheIRWriter& writer, JSObject* obj, JSObject* holder, JSFunction* target = &shape->getterValue().toObject().as(); MOZ_ASSERT(target->hasJITCode()); writer.callScriptedGetterResult(objId, target); + writer.typeMonitorResult(); } bool @@ -303,6 +320,7 @@ GetPropIRGenerator::tryAttachNative(CacheIRWriter& writer, HandleObject obj, Obj } } EmitReadSlotResult(writer, obj, holder, shape, objId); + EmitReadSlotReturn(writer, obj, holder, shape); break; case CanAttachCallGetter: EmitCallGetterResult(writer, obj, holder, shape, objId); @@ -381,6 +399,11 @@ GetPropIRGenerator::tryAttachUnboxed(CacheIRWriter& writer, HandleObject obj, Ob writer.guardGroup(objId, obj->group()); writer.loadUnboxedPropertyResult(objId, property->type, UnboxedPlainObject::offsetOfData() + property->offset); + if (property->type == JSVAL_TYPE_OBJECT) + writer.typeMonitorResult(); + else + writer.returnFromIC(); + emitted_ = true; preliminaryObjectAction_ = PreliminaryObjectAction::Unlink; return true; @@ -405,6 +428,7 @@ GetPropIRGenerator::tryAttachUnboxedExpando(CacheIRWriter& writer, HandleObject emitted_ = true; EmitReadSlotResult(writer, obj, obj, shape, objId); + EmitReadSlotReturn(writer, obj, obj, shape); return true; } @@ -442,6 +466,22 @@ GetPropIRGenerator::tryAttachTypedObject(CacheIRWriter& writer, HandleObject obj writer.guardNoDetachedTypedObjects(); writer.guardShape(objId, shape); writer.loadTypedObjectResult(objId, fieldOffset, layout, typeDescr); + + // Only monitor the result if the type produced by this stub might vary. + bool monitorLoad = false; + if (SimpleTypeDescrKeyIsScalar(typeDescr)) { + Scalar::Type type = ScalarTypeFromSimpleTypeDescrKey(typeDescr); + monitorLoad = type == Scalar::Uint32; + } else { + ReferenceTypeDescr::Type type = ReferenceTypeFromSimpleTypeDescrKey(typeDescr); + monitorLoad = type != ReferenceTypeDescr::TYPE_STRING; + } + + if (monitorLoad) + writer.typeMonitorResult(); + else + writer.returnFromIC(); + emitted_ = true; return true; } @@ -462,6 +502,7 @@ GetPropIRGenerator::tryAttachObjectLength(CacheIRWriter& writer, HandleObject ob writer.guardClass(objId, GuardClassKind::Array); writer.loadInt32ArrayLengthResult(objId); + writer.returnFromIC(); emitted_ = true; return true; } @@ -469,6 +510,7 @@ GetPropIRGenerator::tryAttachObjectLength(CacheIRWriter& writer, HandleObject ob if (obj->is()) { writer.guardClass(objId, GuardClassKind::UnboxedArray); writer.loadUnboxedArrayLengthResult(objId); + writer.returnFromIC(); emitted_ = true; return true; } @@ -481,6 +523,7 @@ GetPropIRGenerator::tryAttachObjectLength(CacheIRWriter& writer, HandleObject ob writer.guardClass(objId, GuardClassKind::UnmappedArguments); } writer.loadArgumentsObjectLengthResult(objId); + writer.returnFromIC(); emitted_ = true; return true; } @@ -517,6 +560,7 @@ GetPropIRGenerator::tryAttachModuleNamespace(CacheIRWriter& writer, HandleObject ObjOperandId envId = writer.loadObject(env); EmitLoadSlotResult(writer, envId, env, shape); + writer.typeMonitorResult(); return true; } @@ -565,6 +609,7 @@ GetPropIRGenerator::tryAttachPrimitive(CacheIRWriter& writer, ValOperandId valId ObjOperandId protoId = writer.loadObject(proto); writer.guardShape(protoId, proto->lastProperty()); EmitLoadSlotResult(writer, protoId, proto, shape); + writer.typeMonitorResult(); emitted_ = true; return true; diff --git a/js/src/jit/CacheIR.h b/js/src/jit/CacheIR.h index 2942f08abec0..3cb3a858b1de 100644 --- a/js/src/jit/CacheIR.h +++ b/js/src/jit/CacheIR.h @@ -102,7 +102,10 @@ class ObjOperandId : public OperandId _(LoadArgumentsObjectLengthResult) \ _(CallScriptedGetterResult) \ _(CallNativeGetterResult) \ - _(LoadUndefinedResult) + _(LoadUndefinedResult) \ + \ + _(TypeMonitorResult) \ + _(ReturnFromIC) enum class CacheOp { #define DEFINE_OP(op) op, @@ -347,6 +350,13 @@ class MOZ_RAII CacheIRWriter writeOpWithOperandId(CacheOp::CallNativeGetterResult, obj); addStubWord(uintptr_t(getter), StubField::GCType::JSObject); } + + void typeMonitorResult() { + writeOp(CacheOp::TypeMonitorResult); + } + void returnFromIC() { + writeOp(CacheOp::ReturnFromIC); + } }; class CacheIRStubInfo; diff --git a/js/src/jit/Ion.h b/js/src/jit/Ion.h index ee2911c31336..018eea5cb56f 100644 --- a/js/src/jit/Ion.h +++ b/js/src/jit/Ion.h @@ -30,6 +30,7 @@ enum MethodStatus enum AbortReason { AbortReason_Alloc, + AbortReason_Inlining, AbortReason_PreliminaryObjects, AbortReason_Disable, AbortReason_Error, diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index b90e80a464ef..5971f1d66614 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -5256,8 +5256,13 @@ IonBuilder::inlineScriptedCall(CallInfo& callInfo, JSFunction* target) // the inlining was aborted for a non-exception reason. if (inlineBuilder.abortReason_ == AbortReason_Disable) { calleeScript->setUninlineable(); - current = backup.restore(); - return InliningStatus_NotInlined; + if (!JitOptions.disableInlineBacktracking) { + current = backup.restore(); + return InliningStatus_NotInlined; + } + abortReason_ = AbortReason_Inlining; + } else if (inlineBuilder.abortReason_ == AbortReason_Inlining) { + abortReason_ = AbortReason_Inlining; } else if (inlineBuilder.abortReason_ == AbortReason_Alloc) { abortReason_ = AbortReason_Alloc; } else if (inlineBuilder.abortReason_ == AbortReason_PreliminaryObjects) { @@ -5286,8 +5291,12 @@ IonBuilder::inlineScriptedCall(CallInfo& callInfo, JSFunction* target) if (returns.empty()) { // Inlining of functions that have no exit is not supported. calleeScript->setUninlineable(); - current = backup.restore(); - return InliningStatus_NotInlined; + if (!JitOptions.disableInlineBacktracking) { + current = backup.restore(); + return InliningStatus_NotInlined; + } + abortReason_ = AbortReason_Inlining; + return InliningStatus_Error; } MDefinition* retvalDefn = patchInlinedReturns(callInfo, returns, returnBlock); if (!retvalDefn) diff --git a/js/src/jit/JitOptions.cpp b/js/src/jit/JitOptions.cpp index d0d45f16ed8c..eb5a6c1c2242 100644 --- a/js/src/jit/JitOptions.cpp +++ b/js/src/jit/JitOptions.cpp @@ -75,6 +75,9 @@ DefaultJitOptions::DefaultJitOptions() // RangeAnalysis results. SET_DEFAULT(checkRangeAnalysis, false); + // Toggles whether IonBuilder fallbacks to a call if we fail to inline. + SET_DEFAULT(disableInlineBacktracking, true); + // Toggles whether Alignment Mask Analysis is globally disabled. SET_DEFAULT(disableAma, false); diff --git a/js/src/jit/JitOptions.h b/js/src/jit/JitOptions.h index 9629f26eb290..076980b4e55b 100644 --- a/js/src/jit/JitOptions.h +++ b/js/src/jit/JitOptions.h @@ -47,6 +47,7 @@ struct DefaultJitOptions #endif bool checkRangeAnalysis; bool runExtraChecks; + bool disableInlineBacktracking; bool disableAma; bool disableEaa; bool disableEagerSimdUnbox; diff --git a/js/src/tests/ecma_3/FunExpr/regress-545980.js b/js/src/tests/ecma_3/FunExpr/regress-545980.js index 1ecf1c9b6c6d..5e29def49446 100644 --- a/js/src/tests/ecma_3/FunExpr/regress-545980.js +++ b/js/src/tests/ecma_3/FunExpr/regress-545980.js @@ -27,7 +27,7 @@ function run_test() { var timer = new Timer; var next = query.slice(1); - timer.initWithCallback({ notify: function() doSearch(next) }); + timer.initWithCallback({ notify: function() { return doSearch(next); } }); } }); })("title"); diff --git a/js/src/tests/ecma_5/strict/13.1.js b/js/src/tests/ecma_5/strict/13.1.js index c5f2acb917ba..137a36d10c1c 100644 --- a/js/src/tests/ecma_5/strict/13.1.js +++ b/js/src/tests/ecma_5/strict/13.1.js @@ -86,11 +86,11 @@ assertEq(testLenientAndStrict('Function("x","y","\'use strict\'")', * The parameter lists of function expressions should not contain * duplicate identifiers. */ -assertEq(testLenientAndStrict('(function (x,x) 2)', +assertEq(testLenientAndStrict('(function (x,x) {})', parsesSuccessfully, parseRaisesException(SyntaxError)), true); -assertEq(testLenientAndStrict('(function (x,y) 2)', +assertEq(testLenientAndStrict('(function (x,y) {})', parsesSuccessfully, parsesSuccessfully), true); @@ -173,19 +173,19 @@ assertEq(testLenientAndStrict('(function eval(){"use strict";})', parseRaisesException(SyntaxError), parseRaisesException(SyntaxError)), true); -assertEq(testLenientAndStrict('(function f(eval) 2)', +assertEq(testLenientAndStrict('(function f(eval) {})', parsesSuccessfully, parseRaisesException(SyntaxError)), true); -assertEq(testLenientAndStrict('(function f([eval]) 2)', +assertEq(testLenientAndStrict('(function f([eval]) {})', parsesSuccessfully, parseRaisesException(SyntaxError)), true); -assertEq(testLenientAndStrict('(function f({x:eval}) 2)', +assertEq(testLenientAndStrict('(function f({x:eval}) {})', parsesSuccessfully, parseRaisesException(SyntaxError)), true); -assertEq(testLenientAndStrict('(function eval() 2)', +assertEq(testLenientAndStrict('(function eval() {})', parsesSuccessfully, parseRaisesException(SyntaxError)), true); @@ -277,19 +277,19 @@ assertEq(testLenientAndStrict('(function arguments(){"use strict";})', parseRaisesException(SyntaxError), parseRaisesException(SyntaxError)), true); -assertEq(testLenientAndStrict('(function f(arguments) 2)', +assertEq(testLenientAndStrict('(function f(arguments) {})', parsesSuccessfully, parseRaisesException(SyntaxError)), true); -assertEq(testLenientAndStrict('(function f([arguments]) 2)', +assertEq(testLenientAndStrict('(function f([arguments]) {})', parsesSuccessfully, parseRaisesException(SyntaxError)), true); -assertEq(testLenientAndStrict('(function f({x:arguments}) 2)', +assertEq(testLenientAndStrict('(function f({x:arguments}) {})', parsesSuccessfully, parseRaisesException(SyntaxError)), true); -assertEq(testLenientAndStrict('(function arguments() 2)', +assertEq(testLenientAndStrict('(function arguments() {})', parsesSuccessfully, parseRaisesException(SyntaxError)), true); diff --git a/js/src/tests/ecma_6/Class/newTargetEval.js b/js/src/tests/ecma_6/Class/newTargetEval.js index e3940bbf973a..ff639e4a662a 100644 --- a/js/src/tests/ecma_6/Class/newTargetEval.js +++ b/js/src/tests/ecma_6/Class/newTargetEval.js @@ -10,7 +10,7 @@ assertThrowsInstanceOf(() => eval('new.target'), SyntaxError); // new.target is invalid inside indirect eval. let ieval = eval; try { - (function () ieval('new.target'))(); + (function () { return ieval('new.target'); })(); assertEq(false, true); } catch (e if e instanceof SyntaxError) { } diff --git a/js/src/tests/js1_8/extensions/regress-452913.js b/js/src/tests/js1_8/extensions/regress-452913.js index 6b0551422d8d..464d403ddfff 100644 --- a/js/src/tests/js1_8/extensions/regress-452913.js +++ b/js/src/tests/js1_8/extensions/regress-452913.js @@ -12,7 +12,7 @@ var expect = ''; printBugNumber(BUGNUMBER); printStatus (summary); -(this.__defineGetter__("x", function (x)'foo'.replace(/o/g, [1].push))); +(this.__defineGetter__("x", function (x) { return 'foo'.replace(/o/g, [1].push); })); for(let y in [,,,]) for(let y in [,,,]) x = x; reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_8/extensions/regress-454744.js b/js/src/tests/js1_8/extensions/regress-454744.js index 3b22acb9f370..e3ddc217f421 100644 --- a/js/src/tests/js1_8/extensions/regress-454744.js +++ b/js/src/tests/js1_8/extensions/regress-454744.js @@ -22,7 +22,7 @@ function test() try { - this.__defineGetter__('x', function() 2); for (var j=0;j<4;++j) { x=1; } + this.__defineGetter__('x', function() { return 2; }); for (var j=0;j<4;++j) { x=1; } } catch(ex) { diff --git a/js/src/tests/js1_8/extensions/regress-469625.js b/js/src/tests/js1_8/extensions/regress-469625.js index 549dc9068e8a..fc94d00ff7d1 100644 --- a/js/src/tests/js1_8/extensions/regress-469625.js +++ b/js/src/tests/js1_8/extensions/regress-469625.js @@ -25,7 +25,7 @@ function test() expect = 'TypeError: [].__proto__ is not a function'; - Array.prototype.__proto__ = function () 3; + Array.prototype.__proto__ = function () { return 3; }; try { diff --git a/js/src/tests/js1_8/regress/regress-452491.js b/js/src/tests/js1_8/regress/regress-452491.js index 13d56986531e..349f544426f8 100644 --- a/js/src/tests/js1_8/regress/regress-452491.js +++ b/js/src/tests/js1_8/regress/regress-452491.js @@ -20,7 +20,7 @@ function test() printStatus (summary); - for (var j=0;j<5;++j) (new (function(q) q)).a; + for (var j=0;j<5;++j) (new (function(q) { return q; })).a; reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_8/regress/regress-459389.js b/js/src/tests/js1_8/regress/regress-459389.js index 9f84d9250994..e63e064a0ccc 100644 --- a/js/src/tests/js1_8/regress/regress-459389.js +++ b/js/src/tests/js1_8/regress/regress-459389.js @@ -53,8 +53,9 @@ var url=new SNI.Ads.Url(); this.addParameter=url.addParameter; this.getParameter=url.getParameter; } -function DartAd() -AdUrl.prototype=new Ad(); +function DartAd() { + return AdUrl.prototype=new Ad(); +} function AdUrl() { } function AdRestriction() { var p=new SNI.MetaData.Parameter(); diff --git a/js/src/tests/js1_8/regress/regress-464096.js b/js/src/tests/js1_8/regress/regress-464096.js index 8e699ebb6837..77f00ebfff8e 100644 --- a/js/src/tests/js1_8/regress/regress-464096.js +++ b/js/src/tests/js1_8/regress/regress-464096.js @@ -22,7 +22,7 @@ function test() for (let f in [1,1]); - Object.prototype.__defineGetter__('x', function() gc()); + Object.prototype.__defineGetter__('x', function() { return gc(); }); (function() { for each (let j in [1,1,1,1,1]) { var y = .2; } })(); diff --git a/js/src/tests/js1_8/regress/regress-465220.js b/js/src/tests/js1_8/regress/regress-465220.js index ca4154fe6a4b..79911c5057e9 100644 --- a/js/src/tests/js1_8/regress/regress-465220.js +++ b/js/src/tests/js1_8/regress/regress-465220.js @@ -25,7 +25,7 @@ function test() try { - var o = {toString: function()(i > 2) ? this : "foo"}; + var o = {toString: function() { return (i > 2) ? this : "foo"; }}; var s = ""; for (var i = 0; i < 5; i++) s += o + o; diff --git a/js/src/tests/js1_8/regress/regress-465460-01.js b/js/src/tests/js1_8/regress/regress-465460-01.js index 2a21de49561a..365b779ca84e 100644 --- a/js/src/tests/js1_8/regress/regress-465460-01.js +++ b/js/src/tests/js1_8/regress/regress-465460-01.js @@ -23,7 +23,7 @@ function test() expect = '11111'; - (function(d) { for (let j = 0; j < 5; ++j) { actual += ('' + d); } })({valueOf: function()1}); + (function(d) { for (let j = 0; j < 5; ++j) { actual += ('' + d); } })({valueOf: function() { return 1; }}); reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_8/regress/regress-467495-01.js b/js/src/tests/js1_8/regress/regress-467495-01.js index 2f6014c283e2..88354f6fadf2 100644 --- a/js/src/tests/js1_8/regress/regress-467495-01.js +++ b/js/src/tests/js1_8/regress/regress-467495-01.js @@ -20,7 +20,7 @@ function test() printBugNumber(BUGNUMBER); printStatus (summary); - (function() { x = 0; function x() 4; var x; const y = 1; })(); + (function() { x = 0; function x() { return 4; }; var x; const y = 1; })(); reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_8_1/extensions/regress-452498-196.js b/js/src/tests/js1_8_1/extensions/regress-452498-196.js index 69d5a3586ae7..1e10246e1a42 100644 --- a/js/src/tests/js1_8_1/extensions/regress-452498-196.js +++ b/js/src/tests/js1_8_1/extensions/regress-452498-196.js @@ -34,7 +34,7 @@ function test() (function (){ var x; - eval("var x; (function ()x)"); + eval("var x; (function () { return x; })"); } )(); diff --git a/js/src/tests/js1_8_1/regress/regress-452498-027.js b/js/src/tests/js1_8_1/regress/regress-452498-027.js index 3583fa03ba25..8e9ef9612c74 100644 --- a/js/src/tests/js1_8_1/regress/regress-452498-027.js +++ b/js/src/tests/js1_8_1/regress/regress-452498-027.js @@ -24,7 +24,7 @@ function test() // ------- Comment #27 From Brendan Eich - function f(x){function g(y)x+y;return g} + function f(x){function g(y) { return x+y; } return g} g = f(2); actual = String(g(3)); diff --git a/js/src/tests/js1_8_1/regress/regress-452498-079.js b/js/src/tests/js1_8_1/regress/regress-452498-079.js index d8b3a1f1d921..eb7d77a987c8 100644 --- a/js/src/tests/js1_8_1/regress/regress-452498-079.js +++ b/js/src/tests/js1_8_1/regress/regress-452498-079.js @@ -24,7 +24,7 @@ function test() // ------- Comment #79 From Jason Orendorff - x; var x; function x() 0 + x; var x; function x() { return 0; } // Assertion failure: !(pn->pn_dflags & flag), at ../jsparse.h:635 diff --git a/js/src/tests/js1_8_1/regress/regress-452498-102.js b/js/src/tests/js1_8_1/regress/regress-452498-102.js index 0aa60e4ec4cc..8dc86a35a306 100644 --- a/js/src/tests/js1_8_1/regress/regress-452498-102.js +++ b/js/src/tests/js1_8_1/regress/regress-452498-102.js @@ -24,7 +24,7 @@ function test() // ===== - (function(){function x(){} function x()y})(); + (function(){function x(){} function x() { return y; }})(); // Assertion failure: JOF_OPTYPE(op) == JOF_ATOM, at ../jsemit.cpp:1710 diff --git a/js/src/tests/js1_8_1/regress/regress-452498-121.js b/js/src/tests/js1_8_1/regress/regress-452498-121.js index 99cecd79ba99..9165330afe8c 100644 --- a/js/src/tests/js1_8_1/regress/regress-452498-121.js +++ b/js/src/tests/js1_8_1/regress/regress-452498-121.js @@ -23,7 +23,7 @@ function test() // ------- Comment #121 From Gary Kwong [:nth10sd] // without -j - x = function()x; + x = function() { return x; }; // Assertion failure: !(pn->pn_dflags & flag), at ../jsparse.h:651 diff --git a/js/src/tests/js1_8_1/regress/regress-452498-160.js b/js/src/tests/js1_8_1/regress/regress-452498-160.js index 6498a0b5aaac..2caf6a75d6a3 100644 --- a/js/src/tests/js1_8_1/regress/regress-452498-160.js +++ b/js/src/tests/js1_8_1/regress/regress-452498-160.js @@ -22,12 +22,12 @@ function test() printStatus (summary); // crash [@ js_Interpret] - (eval("(function(){ this.watch(\"x\", function () { new function ()y } ); const y = undefined });"))(); + (eval("(function(){ this.watch(\"x\", function () { new function () { return y; } } ); const y = undefined });"))(); x = NaN; reportCompare(expect, actual, summary + ': 2'); // Assertion failure: JOF_OPTYPE(op) == JOF_ATOM, at ../jsemit.cpp:5916 - ({ set z(v){}, set y(v)--x, set w(v)--w }); + ({ set z(v){}, set y(v) { return --x; }, set w(v) { return --w; } }); reportCompare(expect, actual, summary + ': 3'); exitFunc ('test'); diff --git a/js/src/tests/js1_8_5/regress/regress-607863.js b/js/src/tests/js1_8_5/regress/regress-607863.js index 75d9ae09f190..14a4ce3d3a4e 100644 --- a/js/src/tests/js1_8_5/regress/regress-607863.js +++ b/js/src/tests/js1_8_5/regress/regress-607863.js @@ -6,7 +6,7 @@ */ var sandbox = evalcx(''); -var foreign = evalcx('({ get f() this, set x(v) { result = this } })', sandbox); +var foreign = evalcx('({ get f() { return this; }, set x(v) { result = this } })', sandbox); var local = Object.create(foreign); reportCompare(local, local.f, "this should be set correctly in getters"); diff --git a/js/src/tests/js1_8_5/regress/regress-646820-1.js b/js/src/tests/js1_8_5/regress/regress-646820-1.js index 535878d50976..6a03ec4f1ed7 100644 --- a/js/src/tests/js1_8_5/regress/regress-646820-1.js +++ b/js/src/tests/js1_8_5/regress/regress-646820-1.js @@ -2,7 +2,7 @@ // http://creativecommons.org/licenses/publicdomain/ (function () { - var [x, y] = [1, function () x]; + var [x, y] = [1, function () { return x; }]; assertEq(y(), 1); })(); diff --git a/js/src/tests/js1_8_5/regress/regress-646820-2.js b/js/src/tests/js1_8_5/regress/regress-646820-2.js index a6c9d5a818df..e75c4d37ccd0 100644 --- a/js/src/tests/js1_8_5/regress/regress-646820-2.js +++ b/js/src/tests/js1_8_5/regress/regress-646820-2.js @@ -3,7 +3,7 @@ (function () { var obj = {prop: 1}; - var [x, {prop: y}] = [function () y, obj]; + var [x, {prop: y}] = [function () { return y; }, obj]; assertEq(y, 1); assertEq(x(), 1); })(); diff --git a/js/src/tests/js1_8_5/regress/regress-646820-3.js b/js/src/tests/js1_8_5/regress/regress-646820-3.js index 392a4345d1ab..26a5aa814c5a 100644 --- a/js/src/tests/js1_8_5/regress/regress-646820-3.js +++ b/js/src/tests/js1_8_5/regress/regress-646820-3.js @@ -2,7 +2,7 @@ // http://creativecommons.org/licenses/publicdomain/ (function () { - var [x, y] = [function () y, 13]; + var [x, y] = [function () { return y; }, 13]; assertEq(x(), 13); })(); diff --git a/layout/base/RestyleManagerBase.h b/layout/base/RestyleManagerBase.h index f81f5e73f5b5..69da7446fa43 100644 --- a/layout/base/RestyleManagerBase.h +++ b/layout/base/RestyleManagerBase.h @@ -81,6 +81,8 @@ public: // itself. nsresult ProcessRestyledFrames(nsStyleChangeList& aChangeList); + bool IsInStyleRefresh() const { return mInStyleRefresh; } + protected: void ContentStateChangedInternal(Element* aElement, EventStates aStateMask, diff --git a/layout/base/RestyleManagerHandle.h b/layout/base/RestyleManagerHandle.h index 8be04d12c11d..82fa63639a20 100644 --- a/layout/base/RestyleManagerHandle.h +++ b/layout/base/RestyleManagerHandle.h @@ -17,6 +17,7 @@ namespace mozilla { class RestyleManager; class ServoRestyleManager; +class RestyleManagerBase; namespace dom { class Element; } // namespace dom @@ -95,6 +96,14 @@ public: const RestyleManager* GetAsGecko() const { return IsGecko() ? AsGecko() : nullptr; } const ServoRestyleManager* GetAsServo() const { return IsServo() ? AsServo() : nullptr; } + const mozilla::RestyleManagerBase* AsBase() const { + return reinterpret_cast(mValue & ~SERVO_BIT); + } + + mozilla::RestyleManagerBase* AsBase() { + return reinterpret_cast(mValue & ~SERVO_BIT); + } + // These inline methods are defined in RestyleManagerHandleInlines.h. inline MozExternalRefCountType AddRef(); inline MozExternalRefCountType Release(); diff --git a/layout/base/ServoRestyleManager.cpp b/layout/base/ServoRestyleManager.cpp index 470d65b7c41e..6d137962f74b 100644 --- a/layout/base/ServoRestyleManager.cpp +++ b/layout/base/ServoRestyleManager.cpp @@ -18,6 +18,7 @@ namespace mozilla { ServoRestyleManager::ServoRestyleManager(nsPresContext* aPresContext) : RestyleManagerBase(aPresContext) + , mReentrantChanges(nullptr) { } @@ -35,6 +36,19 @@ ServoRestyleManager::PostRestyleEvent(Element* aElement, return; // Nothing to do. } + // We allow posting change hints during restyling, but not restyle hints + // themselves, since those would require us to re-traverse the tree. + MOZ_ASSERT_IF(mInStyleRefresh, aRestyleHint == 0); + + // Processing change hints sometimes causes new change hints to be generated. + // Doing this after the gecko post-traversal is problematic, so instead we just + // queue them up for special handling. + if (mReentrantChanges) { + MOZ_ASSERT(aRestyleHint == 0); + mReentrantChanges->AppendElement(ReentrantChange { aElement, aMinChangeHint }); + return; + } + // XXX This is a temporary hack to make style attribute change works. // In the future, we should be able to use this hint directly. if (aRestyleHint & eRestyle_StyleAttribute) { @@ -42,12 +56,8 @@ ServoRestyleManager::PostRestyleEvent(Element* aElement, aRestyleHint |= eRestyle_Self | eRestyle_Subtree; } - // Note that unlike in Servo, we don't mark elements as dirty until we process - // the restyle hints in ProcessPendingRestyles. if (aRestyleHint || aMinChangeHint) { - ServoElementSnapshot* snapshot = SnapshotForElement(aElement); - snapshot->AddExplicitRestyleHint(aRestyleHint); - snapshot->AddExplicitChangeHint(aMinChangeHint); + Servo_NoteExplicitHints(aElement, aRestyleHint, aMinChangeHint); } PostRestyleEventInternal(false); @@ -73,123 +83,67 @@ ServoRestyleManager::PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint, NS_WARNING("stylo: ServoRestyleManager::PostRebuildAllStyleDataEvent not implemented"); } -static void -MarkSelfAndDescendantsAsNotDirtyForServo(nsIContent* aContent) +/* static */ void +ServoRestyleManager::ClearServoDataFromSubtree(Element* aElement) { - aContent->UnsetIsDirtyForServo(); + aElement->ClearServoData(); - if (aContent->HasDirtyDescendantsForServo()) { - aContent->UnsetHasDirtyDescendantsForServo(); - - StyleChildrenIterator it(aContent); - for (nsIContent* n = it.GetNextChild(); n; n = it.GetNextChild()) { - MarkSelfAndDescendantsAsNotDirtyForServo(n); + StyleChildrenIterator it(aElement); + for (nsIContent* n = it.GetNextChild(); n; n = it.GetNextChild()) { + if (n->IsElement()) { + ClearServoDataFromSubtree(n->AsElement()); } } + + aElement->UnsetHasDirtyDescendantsForServo(); } /* static */ void -ServoRestyleManager::ClearServoDataFromSubtree(nsIContent* aContent) +ServoRestyleManager::ClearDirtyDescendantsFromSubtree(Element* aElement) { - aContent->ClearServoData(); - aContent->SetIsDirtyForServo(); - aContent->UnsetHasDirtyDescendantsForServo(); - - AllChildrenIterator it(aContent, nsIContent::eAllChildren); + StyleChildrenIterator it(aElement); for (nsIContent* n = it.GetNextChild(); n; n = it.GetNextChild()) { - ClearServoDataFromSubtree(n); + if (n->IsElement()) { + ClearDirtyDescendantsFromSubtree(n->AsElement()); + } } + + aElement->UnsetHasDirtyDescendantsForServo(); } void -ServoRestyleManager::RecreateStyleContexts(nsIContent* aContent, +ServoRestyleManager::RecreateStyleContexts(Element* aElement, nsStyleContext* aParentContext, ServoStyleSet* aStyleSet, nsStyleChangeList& aChangeListToProcess) { - MOZ_ASSERT(aContent->IsElement() || aContent->IsNodeOfType(nsINode::eTEXT)); + nsIFrame* primaryFrame = aElement->GetPrimaryFrame(); - nsIFrame* primaryFrame = aContent->GetPrimaryFrame(); - if (!primaryFrame && !aContent->IsDirtyForServo()) { - // This happens when, for example, a display: none child of a - // HAS_DIRTY_DESCENDANTS content is reached as part of the traversal. - MarkSelfAndDescendantsAsNotDirtyForServo(aContent); + // FIXME(bholley): Once we transfer ownership of the styles to the frame, we + // can fast-reject without the FFI call by checking mServoData for null. + nsChangeHint changeHint = Servo_CheckChangeHint(aElement); + if (changeHint) { + aChangeListToProcess.AppendChange(primaryFrame, aElement, changeHint); + } + + // If our change hint is reconstruct, we delegate to the frame constructor, + // which consumes the new style and expects the old style to be on the frame. + // + // XXXbholley: We should teach the frame constructor how to clear the dirty + // descendants bit to avoid the traversal here. + if (changeHint & nsChangeHint_ReconstructFrame) { + ClearDirtyDescendantsFromSubtree(aElement); return; } - // Work on text before. - if (!aContent->IsElement()) { - if (primaryFrame) { - RefPtr oldStyleContext = primaryFrame->StyleContext(); - RefPtr newContext = - aStyleSet->ResolveStyleForText(aContent, aParentContext); - - for (nsIFrame* f = primaryFrame; f; - f = GetNextContinuationWithSameStyle(f, oldStyleContext)) { - f->SetStyleContext(newContext); - } - } - - aContent->UnsetIsDirtyForServo(); - return; - } - - Element* element = aContent->AsElement(); - if (element->IsDirtyForServo()) { - RefPtr computedValues = - Servo_ComputedValues_Get(aContent).Consume(); - MOZ_ASSERT(computedValues); - - nsChangeHint changeHint = nsChangeHint(0); - - // Add an explicit change hint if appropriate. - ServoElementSnapshot* snapshot; - if (mModifiedElements.Get(element, &snapshot)) { - changeHint |= snapshot->ExplicitChangeHint(); - } - - // Add the stored change hint if there's a frame. If there isn't a frame, - // generate a ReconstructFrame change hint if the new display value - // (which we can get from the ComputedValues stored on the node) is not - // none. - if (primaryFrame) { - changeHint |= primaryFrame->StyleContext()->ConsumeStoredChangeHint(); - } else { - const nsStyleDisplay* currentDisplay = - Servo_GetStyleDisplay(computedValues); - if (currentDisplay->mDisplay != StyleDisplay::None) { - changeHint |= nsChangeHint_ReconstructFrame; - } - } - - // Add the new change hint to the list of elements to process if - // we need to do any work. - if (changeHint) { - aChangeListToProcess.AppendChange(primaryFrame, element, changeHint); - } - - // The frame reconstruction step (if needed) will ask for the descendants' - // style correctly. If not needed, we're done too. - // - // Note that we must leave the old style on an existing frame that is - // about to be reframed, since some frame constructor code wants to - // inspect the old style to work out what to do. - if (changeHint & nsChangeHint_ReconstructFrame) { - // Since we might still have some dirty bits set on descendants, - // inconsistent with the clearing of HasDirtyDescendants we will do as - // we return from these recursive RecreateStyleContexts calls, we - // explicitly clear them here. Otherwise we will trigger assertions - // when we soon process the frame reconstruction. - MarkSelfAndDescendantsAsNotDirtyForServo(element); - return; - } - - // If there is no frame, and we didn't generate a ReconstructFrame change - // hint, then we don't need to do any more work. - if (!primaryFrame) { - aContent->UnsetIsDirtyForServo(); - return; - } + // If we have a frame and a non-zero + non-reconstruct change hint, we need to + // attach a new style context. + bool recreateContext = primaryFrame && changeHint; + if (recreateContext) { + RefPtr computedValues + = Servo_ResolveStyle(aElement, aStyleSet->mRawSet.get(), + ConsumeStyleBehavior::Consume, + LazyComputeBehavior::Assert).Consume(); // Hold the old style context alive, because it could become a dangling // pointer during the replacement. In practice it's not a huge deal (on @@ -219,69 +173,68 @@ ServoRestyleManager::RecreateStyleContexts(nsIContent* aContent, for (CSSPseudoElementType pseudoType : pseudosToRestyle) { nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(pseudoType); - if (nsIFrame* pseudoFrame = FrameForPseudoElement(element, pseudoTag)) { + if (nsIFrame* pseudoFrame = FrameForPseudoElement(aElement, pseudoTag)) { // TODO: we could maybe make this more performant via calling into // Servo just once to know which pseudo-elements we've got to restyle? RefPtr pseudoContext = - aStyleSet->ProbePseudoElementStyle(element, pseudoType, newContext); + aStyleSet->ProbePseudoElementStyle(aElement, pseudoType, newContext); + MOZ_ASSERT(pseudoContext, "should have taken the ReconstructFrame path above"); + pseudoFrame->SetStyleContext(pseudoContext); - // If pseudoContext is null here, it means the frame is going away, so - // our change hint computation should have already indicated we need - // to reframe. - MOZ_ASSERT_IF(!pseudoContext, - changeHint & nsChangeHint_ReconstructFrame); - if (pseudoContext) { - pseudoFrame->SetStyleContext(pseudoContext); - - // We only care restyling text nodes, since other type of nodes - // (images), are still not supported. If that eventually changes, we - // may have to write more code here... Or not, I don't think too - // many inherited properties can affect those other frames. - StyleChildrenIterator it(pseudoFrame->GetContent()); - for (nsIContent* n = it.GetNextChild(); n; n = it.GetNextChild()) { - if (n->IsNodeOfType(nsINode::eTEXT)) { - RefPtr childContext = - aStyleSet->ResolveStyleForText(n, pseudoContext); - MOZ_ASSERT(n->GetPrimaryFrame(), - "How? This node is created at FC time!"); - n->GetPrimaryFrame()->SetStyleContext(childContext); - } + // We only care restyling text nodes, since other type of nodes + // (images), are still not supported. If that eventually changes, we + // may have to write more code here... Or not, I don't think too + // many inherited properties can affect those other frames. + StyleChildrenIterator it(pseudoFrame->GetContent()); + for (nsIContent* n = it.GetNextChild(); n; n = it.GetNextChild()) { + if (n->IsNodeOfType(nsINode::eTEXT)) { + RefPtr childContext = + aStyleSet->ResolveStyleForText(n, pseudoContext); + MOZ_ASSERT(n->GetPrimaryFrame(), + "How? This node is created at FC time!"); + n->GetPrimaryFrame()->SetStyleContext(childContext); } } } } - - aContent->UnsetIsDirtyForServo(); } - if (aContent->HasDirtyDescendantsForServo()) { - MOZ_ASSERT(primaryFrame, - "Frame construction should be scheduled, and it takes the " - "correct style for the children, so no need to be here."); - StyleChildrenIterator it(aContent); + bool traverseElementChildren = aElement->HasDirtyDescendantsForServo(); + bool traverseTextChildren = recreateContext; + if (traverseElementChildren || traverseTextChildren) { + StyleChildrenIterator it(aElement); for (nsIContent* n = it.GetNextChild(); n; n = it.GetNextChild()) { - if (n->IsElement() || n->IsNodeOfType(nsINode::eTEXT)) { - RecreateStyleContexts(n, primaryFrame->StyleContext(), + if (traverseElementChildren && n->IsElement()) { + MOZ_ASSERT(primaryFrame, + "Frame construction should be scheduled, and it takes the " + "correct style for the children, so no need to be here."); + RecreateStyleContexts(n->AsElement(), primaryFrame->StyleContext(), aStyleSet, aChangeListToProcess); + } else if (traverseTextChildren && n->IsNodeOfType(nsINode::eTEXT)) { + RecreateStyleContextsForText(n, primaryFrame->StyleContext(), + aStyleSet); } } - aContent->UnsetHasDirtyDescendantsForServo(); } + + aElement->UnsetHasDirtyDescendantsForServo(); } -static void -MarkChildrenAsDirtyForServo(nsIContent* aContent) +void +ServoRestyleManager::RecreateStyleContextsForText(nsIContent* aTextNode, + nsStyleContext* aParentContext, + ServoStyleSet* aStyleSet) { - StyleChildrenIterator it(aContent); + nsIFrame* primaryFrame = aTextNode->GetPrimaryFrame(); + if (primaryFrame) { + RefPtr oldStyleContext = primaryFrame->StyleContext(); + RefPtr newContext = + aStyleSet->ResolveStyleForText(aTextNode, aParentContext); - nsIContent* n = it.GetNextChild(); - bool hadChildren = bool(n); - for (; n; n = it.GetNextChild()) { - n->SetIsDirtyForServo(); - } - - if (hadChildren) { - aContent->SetHasDirtyDescendantsForServo(); + for (nsIFrame* f = primaryFrame; f; + f = GetNextContinuationWithSameStyle(f, oldStyleContext)) { + f->SetStyleContext(newContext); + } } } @@ -315,43 +268,6 @@ ServoRestyleManager::FrameForPseudoElement(const nsIContent* aContent, return nullptr; } -/* static */ void -ServoRestyleManager::NoteRestyleHint(Element* aElement, nsRestyleHint aHint) -{ - const nsRestyleHint HANDLED_RESTYLE_HINTS = eRestyle_Self | - eRestyle_Subtree | - eRestyle_LaterSiblings | - eRestyle_SomeDescendants; - // NB: For Servo, at least for now, restyling and running selector-matching - // against the subtree is necessary as part of restyling the element, so - // processing eRestyle_Self will perform at least as much work as - // eRestyle_Subtree. - if (aHint & (eRestyle_Self | eRestyle_Subtree)) { - aElement->SetIsDirtyForServo(); - aElement->MarkAncestorsAsHavingDirtyDescendantsForServo(); - // NB: Servo gives us a eRestyle_SomeDescendants when it expects us to run - // selector matching on all the descendants. There's a bug on Servo to align - // meanings here (#12710) to avoid this potential source of confusion. - } else if (aHint & eRestyle_SomeDescendants) { - MarkChildrenAsDirtyForServo(aElement); - aElement->MarkAncestorsAsHavingDirtyDescendantsForServo(); - } - - if (aHint & eRestyle_LaterSiblings) { - aElement->MarkAncestorsAsHavingDirtyDescendantsForServo(); - for (nsIContent* cur = aElement->GetNextSibling(); cur; - cur = cur->GetNextSibling()) { - cur->SetIsDirtyForServo(); - } - } - - // TODO: Handle all other nsRestyleHint values. - if (aHint & ~HANDLED_RESTYLE_HINTS) { - NS_WARNING(nsPrintfCString("stylo: Unhandled restyle hint %s", - RestyleManagerBase::RestyleHintToString(aHint).get()).get()); - } -} - void ServoRestyleManager::ProcessPendingRestyles() { @@ -374,66 +290,48 @@ ServoRestyleManager::ProcessPendingRestyles() ServoStyleSet* styleSet = StyleSet(); nsIDocument* doc = PresContext()->Document(); Element* root = doc->GetRootElement(); - if (root) { - // ProcessPendingRestyles can generate new restyles (e.g. from the - // frame constructor if it decides that a ReconstructFrame change must - // apply to the parent of the element that generated that hint). So - // we loop while mModifiedElements still has some restyles in it, clearing - // it after each RecreateStyleContexts call below. - while (!mModifiedElements.IsEmpty()) { - for (auto iter = mModifiedElements.Iter(); !iter.Done(); iter.Next()) { - ServoElementSnapshot* snapshot = iter.UserData(); - Element* element = iter.Key(); - // The element is no longer in the document, so don't bother computing - // a final restyle hint for it. - // - // XXXheycam RestyleTracker checks that the element's GetComposedDoc() - // matches the document we're restyling. Do we need to do that too? - if (!element->IsInComposedDoc()) { - continue; - } + // XXXbholley: Should this be while() per bug 1316247? + if (HasPendingRestyles()) { + MOZ_ASSERT(root); + mInStyleRefresh = true; + styleSet->StyleDocument(); - // TODO: avoid the ComputeRestyleHint call if we already have the highest - // explicit restyle hint? - nsRestyleHint hint = styleSet->ComputeRestyleHint(element, snapshot); - hint |= snapshot->ExplicitRestyleHint(); + // First do any queued-up frame creation. (see bugs 827239 and 997506). + // + // XXXEmilio I'm calling this to avoid random behavior changes, since we + // delay frame construction after styling we should re-check once our + // model is more stable whether we can skip this call. + // + // Note this has to be *after* restyling, because otherwise frame + // construction will find unstyled nodes, and that's not funny. + PresContext()->FrameConstructor()->CreateNeededFrames(); - if (hint) { - NoteRestyleHint(element, hint); - } + // Recreate style contexts and queue up change hints. + nsStyleChangeList currentChanges; + RecreateStyleContexts(root, nullptr, styleSet, currentChanges); + + // Process the change hints. + // + // Unfortunately, the frame constructor can generate new change hints while + // processing existing ones. We redirect those into a secondary queue and + // iterate until there's nothing left. + ReentrantChangeList newChanges; + mReentrantChanges = &newChanges; + while (!currentChanges.IsEmpty()) { + ProcessRestyledFrames(currentChanges); + MOZ_ASSERT(currentChanges.IsEmpty()); + for (ReentrantChange& change: newChanges) { + currentChanges.AppendChange(change.mContent->GetPrimaryFrame(), + change.mContent, change.mHint); } - - if (!root->IsDirtyForServo() && !root->HasDirtyDescendantsForServo()) { - mModifiedElements.Clear(); - break; - } - - mInStyleRefresh = true; - styleSet->StyleDocument(/* aLeaveDirtyBits = */ true); - - // First do any queued-up frame creation. (see bugs 827239 and 997506). - // - // XXXEmilio I'm calling this to avoid random behavior changes, since we - // delay frame construction after styling we should re-check once our - // model is more stable whether we can skip this call. - // - // Note this has to be *after* restyling, because otherwise frame - // construction will find unstyled nodes, and that's not funny. - PresContext()->FrameConstructor()->CreateNeededFrames(); - - nsStyleChangeList changeList; - RecreateStyleContexts(root, nullptr, styleSet, changeList); - - mModifiedElements.Clear(); - ProcessRestyledFrames(changeList); - - mInStyleRefresh = false; + newChanges.Clear(); } - } + mReentrantChanges = nullptr; - MOZ_ASSERT(!doc->IsDirtyForServo()); - doc->UnsetHasDirtyDescendantsForServo(); + styleSet->AssertTreeIsClean(); + mInStyleRefresh = false; + } IncrementRestyleGeneration(); } @@ -454,31 +352,6 @@ ServoRestyleManager::RestyleForInsertOrChange(nsINode* aContainer, void ServoRestyleManager::ContentInserted(nsINode* aContainer, nsIContent* aChild) { - if (aContainer == aContainer->OwnerDoc()) { - // If we're getting this notification for the insertion of a root element, - // that means either: - // (a) We initialized the PresShell before the root element existed, or - // (b) The root element was removed and it or another root is being - // inserted. - // - // Either way the whole tree is dirty, so we should style the document. - MOZ_ASSERT(aChild == aChild->OwnerDoc()->GetRootElement()); - MOZ_ASSERT(aChild->IsDirtyForServo()); - StyleSet()->StyleDocument(/* aLeaveDirtyBits = */ false); - return; - } - - if (!aContainer->HasServoData()) { - // This can happen with display:none. Bug 1297249 tracks more investigation - // and assertions here. - return; - } - - // Style the new subtree because we will most likely need it during subsequent - // frame construction. Bug 1298281 tracks deferring this work in the lazy - // frame construction case. - StyleSet()->StyleNewSubtree(aChild); - RestyleForInsertOrChange(aContainer, aChild); } @@ -499,22 +372,6 @@ void ServoRestyleManager::ContentAppended(nsIContent* aContainer, nsIContent* aFirstNewContent) { - if (!aContainer->HasServoData()) { - // This can happen with display:none. Bug 1297249 tracks more investigation - // and assertions here. - return; - } - - // Style the new subtree because we will most likely need it during subsequent - // frame construction. Bug 1298281 tracks deferring this work in the lazy - // frame construction case. - if (aFirstNewContent->GetNextSibling()) { - aContainer->SetHasDirtyDescendantsForServo(); - StyleSet()->StyleNewChildren(aContainer); - } else { - StyleSet()->StyleNewSubtree(aFirstNewContent); - } - RestyleForAppend(aContainer, aFirstNewContent); } @@ -561,10 +418,12 @@ ServoRestyleManager::ContentStateChanged(nsIContent* aContent, &restyleHint); EventStates previousState = aElement->StyleState() ^ aChangedBits; - ServoElementSnapshot* snapshot = SnapshotForElement(aElement); - snapshot->AddState(previousState); + ServoElementSnapshot* snapshot = Servo_Element_GetSnapshot(aElement); + if (snapshot) { + snapshot->AddState(previousState); + PostRestyleEvent(aElement, restyleHint, changeHint); + } - PostRestyleEvent(aElement, restyleHint, changeHint); return NS_OK; } @@ -574,8 +433,10 @@ ServoRestyleManager::AttributeWillChange(Element* aElement, nsIAtom* aAttribute, int32_t aModType, const nsAttrValue* aNewValue) { - ServoElementSnapshot* snapshot = SnapshotForElement(aElement); - snapshot->AddAttrs(aElement); + ServoElementSnapshot* snapshot = Servo_Element_GetSnapshot(aElement); + if (snapshot) { + snapshot->AddAttrs(aElement); + } } void @@ -583,7 +444,10 @@ ServoRestyleManager::AttributeChanged(Element* aElement, int32_t aNameSpaceID, nsIAtom* aAttribute, int32_t aModType, const nsAttrValue* aOldValue) { - MOZ_ASSERT(SnapshotForElement(aElement)->HasAttrs()); +#ifdef DEBUG + ServoElementSnapshot* snapshot = Servo_Element_GetSnapshot(aElement); + MOZ_ASSERT_IF(snapshot, snapshot->HasAttrs()); +#endif if (aAttribute == nsGkAtoms::style) { PostRestyleEvent(aElement, eRestyle_StyleAttribute, nsChangeHint(0)); } @@ -596,12 +460,4 @@ ServoRestyleManager::ReparentStyleContext(nsIFrame* aFrame) return NS_OK; } -ServoElementSnapshot* -ServoRestyleManager::SnapshotForElement(Element* aElement) -{ - // NB: aElement is the argument for the construction of the snapshot in the - // not found case. - return mModifiedElements.LookupOrAdd(aElement, aElement); -} - } // namespace mozilla diff --git a/layout/base/ServoRestyleManager.h b/layout/base/ServoRestyleManager.h index 817ac0c46249..e242023de955 100644 --- a/layout/base/ServoRestyleManager.h +++ b/layout/base/ServoRestyleManager.h @@ -9,6 +9,7 @@ #include "mozilla/EventStates.h" #include "mozilla/RestyleManagerBase.h" +#include "mozilla/ServoBindings.h" #include "mozilla/ServoElementSnapshot.h" #include "nsChangeHint.h" #include "nsHashKeys.h" @@ -79,8 +80,8 @@ public: bool HasPendingRestyles() { - return !mModifiedElements.IsEmpty() || - PresContext()->Document()->HasDirtyDescendantsForServo(); + Element* root = PresContext()->Document()->GetRootElement(); + return root && root->HasDirtyDescendantsForServo(); } @@ -94,37 +95,33 @@ public: nsIAtom* aPseudoTagOrNull); /** - * Clears the ServoNodeData from all content nodes in the subtree rooted - * at aContent, and sets the IsDirtyForServo bit and clears the - * HasDirtyDescendantsForServo bit on them too. + * Clears the ServoElementData and HasDirtyDescendants from all elements + * in the subtree rooted at aElement. */ - static void ClearServoDataFromSubtree(nsIContent* aContent); - -protected: - ~ServoRestyleManager() {} - -private: - ServoElementSnapshot* SnapshotForElement(Element* aElement); + static void ClearServoDataFromSubtree(Element* aElement); /** - * The element-to-element snapshot table to compute restyle hints. + * Clears HasDirtyDescendants from all elements in the subtree rooted at + * aElement. */ - nsClassHashtable, ServoElementSnapshot> - mModifiedElements; + static void ClearDirtyDescendantsFromSubtree(Element* aElement); +protected: + ~ServoRestyleManager() { MOZ_ASSERT(!mReentrantChanges); } + +private: /** * Traverses a tree of content that Servo has just restyled, recreating style * contexts for their frames with the new style data. */ - void RecreateStyleContexts(nsIContent* aContent, + void RecreateStyleContexts(Element* aElement, nsStyleContext* aParentContext, ServoStyleSet* aStyleSet, nsStyleChangeList& aChangeList); - /** - * Marks the tree with the appropriate dirty flags for the given restyle hint. - */ - static void NoteRestyleHint(Element* aElement, nsRestyleHint aRestyleHint); + void RecreateStyleContextsForText(nsIContent* aTextNode, + nsStyleContext* aParentContext, + ServoStyleSet* aStyleSet); inline ServoStyleSet* StyleSet() const { @@ -133,6 +130,19 @@ private: "style backend"); return PresContext()->StyleSet()->AsServo(); } + + // We use a separate data structure from nsStyleChangeList because we need a + // frame to create nsStyleChangeList entries, and the primary frame may not be + // attached yet. + struct ReentrantChange { + nsCOMPtr mContent; + nsChangeHint mHint; + }; + typedef AutoTArray ReentrantChangeList; + + // Only non-null while processing change hints. See the comment in + // ProcessPendingRestyles. + ReentrantChangeList* mReentrantChanges; }; } // namespace mozilla diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index e1d671f527ba..8df2e6a2500c 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -2429,7 +2429,9 @@ nsCSSFrameConstructor::ConstructDocElementFrame(Element* aDocEle // do so for the construction of a style context for an element.) RefPtr styleContext; styleContext = mPresShell->StyleSet()->ResolveStyleFor(aDocElement, - nullptr); + nullptr, + ConsumeStyleBehavior::Consume, + LazyComputeBehavior::Allow); const nsStyleDisplay* display = styleContext->StyleDisplay(); @@ -2464,11 +2466,19 @@ nsCSSFrameConstructor::ConstructDocElementFrame(Element* aDocEle // don't do so for the construction of a style context for an // element.) styleContext = mPresShell->StyleSet()->ResolveStyleFor(aDocElement, - nullptr); + nullptr, + ConsumeStyleBehavior::Consume, + LazyComputeBehavior::Allow); display = styleContext->StyleDisplay(); } } + // We delay traversing the entire document until here, since we per above we + // may invalidate the root style when we load doc stylesheets. + if (ServoStyleSet* set = mPresShell->StyleSet()->GetAsServo()) { + set->StyleDocument(); + } + // --------- IF SCROLLABLE WRAP IN SCROLLFRAME -------- NS_ASSERTION(!display->IsScrollableOverflow() || @@ -5022,10 +5032,14 @@ nsCSSFrameConstructor::ResolveStyleContext(nsStyleContext* aParentStyleContext, if (aState) { result = styleSet->ResolveStyleFor(aContent->AsElement(), aParentStyleContext, + ConsumeStyleBehavior::Consume, + LazyComputeBehavior::Assert, aState->mTreeMatchContext); } else { result = styleSet->ResolveStyleFor(aContent->AsElement(), - aParentStyleContext); + aParentStyleContext, + ConsumeStyleBehavior::Consume, + LazyComputeBehavior::Assert); } } else { NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT), @@ -5713,6 +5727,11 @@ nsCSSFrameConstructor::AddFrameConstructionItemsInternal(nsFrameConstructorState aState.AddPendingBinding(newPendingBinding.forget()); } + if (aContent->IsStyledByServo()) { + NS_WARNING("stylo: Skipping Unsupported binding re-resolve. This needs fixing."); + resolveStyle = false; + } + if (resolveStyle) { styleContext = ResolveStyleContext(styleContext->GetParent(), aContent, &aState); @@ -7342,9 +7361,28 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer, if (aAllowLazyConstruction && MaybeConstructLazily(CONTENTAPPEND, aContainer, aFirstNewContent)) { + if (aContainer->IsStyledByServo()) { + aContainer->AsElement()->NoteDirtyDescendantsForServo(); + } return NS_OK; } + // We couldn't construct lazily. Make Servo eagerly traverse the subtree. + if (ServoStyleSet* set = mPresShell->StyleSet()->GetAsServo()) { + // We use the same codepaths to handle both of the following cases: + // (a) Newly-appended content for which lazy frame construction is disallowed. + // (b) Lazy frame construction driven by the restyle manager. + // We need the styles for (a). In the case of (b), the Servo traversal has + // already happened, so we don't need to do it again. + if (!RestyleManager()->AsBase()->IsInStyleRefresh()) { + if (aFirstNewContent->GetNextSibling()) { + set->StyleNewChildren(aContainer); + } else { + set->StyleNewSubtree(aFirstNewContent); + } + } + } + LAYOUT_PHASE_TEMP_EXIT(); InsertionPoint insertion = GetRangeInsertionPoint(aContainer, aFirstNewContent, nullptr, @@ -7787,10 +7825,25 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer, if (aAllowLazyConstruction && MaybeConstructLazily(CONTENTINSERT, aContainer, aStartChild)) { + if (aContainer->IsStyledByServo()) { + aContainer->AsElement()->NoteDirtyDescendantsForServo(); + } return NS_OK; } } + // We couldn't construct lazily. Make Servo eagerly traverse the subtree. + if (ServoStyleSet* set = mPresShell->StyleSet()->GetAsServo()) { + // We use the same codepaths to handle both of the following cases: + // (a) Newly-appended content for which lazy frame construction is disallowed. + // (b) Lazy frame construction driven by the restyle manager. + // We need the styles for (a). In the case of (b), the Servo traversal has + // already happened, so we don't need to do it again. + if (!RestyleManager()->AsBase()->IsInStyleRefresh()) { + set->StyleNewSubtree(aStartChild); + } + } + InsertionPoint insertion; if (isSingleInsert) { // See if we have an XBL insertion point. If so, then that's our @@ -9255,7 +9308,9 @@ nsCSSFrameConstructor::MaybeRecreateFramesForElement(Element* aElement) // The parent has a frame, so try resolving a new context. RefPtr newContext = mPresShell->StyleSet()-> - ResolveStyleFor(aElement, oldContext->GetParent()); + ResolveStyleFor(aElement, oldContext->GetParent(), + ConsumeStyleBehavior::Consume, + LazyComputeBehavior::Assert); if (oldDisplay == StyleDisplay::None) { ChangeUndisplayedContent(aElement, newContext); @@ -10627,14 +10682,15 @@ nsCSSFrameConstructor::AddFCItemsForAnonymousContent( // This happens when a native anonymous node is used to implement a // pseudo-element. Allowing Servo to traverse these nodes would be wasted // work, so assert that we didn't do that. - MOZ_ASSERT_IF(content->IsStyledByServo(), !content->HasServoData()); + MOZ_ASSERT_IF(content->IsStyledByServo(), + !content->IsElement() || !content->AsElement()->HasServoData()); styleContext = aAnonymousItems[i].mStyleContext.forget(); } else { // If we don't have an explicit style context, that means we need the // ordinary computed values. Make sure we eagerly cascaded them when the // anonymous nodes were created. MOZ_ASSERT_IF(content->IsStyledByServo() && content->IsElement(), - content->HasServoData()); + content->AsElement()->HasServoData()); styleContext = ResolveStyleContext(aFrame, content, &aState); } diff --git a/layout/base/nsChangeHint.h b/layout/base/nsChangeHint.h index 318b848407cb..0f064eca40ea 100644 --- a/layout/base/nsChangeHint.h +++ b/layout/base/nsChangeHint.h @@ -17,6 +17,8 @@ struct nsCSSSelector; // Defines for various style related constants enum nsChangeHint { + nsChangeHint_Empty = 0, + // change was visual only (e.g., COLOR=) // Invalidates all descendant frames (including following // placeholders to out-of-flow frames). diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp index 135e49375eaa..3f9a2928a81d 100644 --- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -6,6 +6,7 @@ /* container for a document and its presentation */ +#include "mozilla/ServoRestyleManager.h" #include "mozilla/ServoStyleSet.h" #include "nsAutoPtr.h" #include "nscore.h" @@ -4469,6 +4470,15 @@ NS_IMETHODIMP nsDocumentViewer::SetPageMode(bool aPageMode, nsIPrintSettings* aP mViewManager = nullptr; mWindow = nullptr; + // We're creating a new presentation context for an existing document. + // Drop any associated Servo data. +#ifdef MOZ_STYLO + Element* root = mDocument->GetRootElement(); + if (root && root->IsStyledByServo()) { + ServoRestyleManager::ClearServoDataFromSubtree(root); + } +#endif + NS_ENSURE_STATE(mDocument); if (aPageMode) { diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index 49aa879892f0..1fcf085ddbe5 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -1384,7 +1384,9 @@ GetPropagatedScrollbarStylesForViewport(nsPresContext* aPresContext, // Check the style on the document root element StyleSetHandle styleSet = aPresContext->StyleSet(); RefPtr rootStyle; - rootStyle = styleSet->ResolveStyleFor(docElement, nullptr); + rootStyle = styleSet->ResolveStyleFor(docElement, nullptr, + ConsumeStyleBehavior::DontConsume, + LazyComputeBehavior::Allow); if (CheckOverflow(rootStyle->StyleDisplay(), aStyles)) { // tell caller we stole the overflow style from the root element return docElement; @@ -1412,7 +1414,9 @@ GetPropagatedScrollbarStylesForViewport(nsPresContext* aPresContext, } RefPtr bodyStyle; - bodyStyle = styleSet->ResolveStyleFor(bodyElement->AsElement(), rootStyle); + bodyStyle = styleSet->ResolveStyleFor(bodyElement->AsElement(), rootStyle, + ConsumeStyleBehavior::DontConsume, + LazyComputeBehavior::Allow); if (CheckOverflow(bodyStyle->StyleDisplay(), aStyles)) { // tell caller we stole the overflow style from the body element diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 512003fae61b..d2d260c2130f 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -1692,17 +1692,6 @@ PresShell::Initialize(nscoord aWidth, nscoord aHeight) mPresContext->SetVisibleArea(nsRect(0, 0, aWidth, aHeight)); - if (mStyleSet->IsServo() && mDocument->GetRootElement()) { - // If we have the root element already, go ahead style it along with any - // descendants. - // - // Some things, like nsDocumentViewer::GetPageMode, recreate the PresShell - // while keeping the content tree alive (see bug 1292280) - so we - // unconditionally mark the root as dirty. - mDocument->GetRootElement()->SetIsDirtyForServo(); - mStyleSet->AsServo()->StyleDocument(/* aLeaveDirtyBits = */ false); - } - // Get the root frame from the frame manager // XXXbz it would be nice to move this somewhere else... like frame manager // Init(), say. But we need to make sure our views are all set up by the diff --git a/layout/generic/nsFrameSetFrame.cpp b/layout/generic/nsFrameSetFrame.cpp index 87cb31fd06e9..32ecaf8f2102 100644 --- a/layout/generic/nsFrameSetFrame.cpp +++ b/layout/generic/nsFrameSetFrame.cpp @@ -302,7 +302,9 @@ nsHTMLFramesetFrame::Init(nsIContent* aContent, RefPtr kidSC; kidSC = shell->StyleSet()->ResolveStyleFor(child->AsElement(), - mStyleContext); + mStyleContext, + ConsumeStyleBehavior::DontConsume, + LazyComputeBehavior::Allow); if (child->IsHTMLElement(nsGkAtoms::frameset)) { frame = NS_NewHTMLFramesetFrame(shell, kidSC); diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index af4a8df87b41..cb341552730a 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -2058,7 +2058,9 @@ nsImageFrame::GetCursor(const nsPoint& aPoint, // specified will inherit the style from the image. RefPtr areaStyle = PresContext()->PresShell()->StyleSet()-> - ResolveStyleFor(area->AsElement(), StyleContext()); + ResolveStyleFor(area->AsElement(), StyleContext(), + ConsumeStyleBehavior::DontConsume, + LazyComputeBehavior::Allow); FillCursorInformationFromStyle(areaStyle->StyleUserInterface(), aCursor); if (NS_STYLE_CURSOR_AUTO == aCursor.mCursor) { diff --git a/layout/style/ServoBindingList.h b/layout/style/ServoBindingList.h index c4b484f7770e..5641e2c150a6 100644 --- a/layout/style/ServoBindingList.h +++ b/layout/style/ServoBindingList.h @@ -18,8 +18,8 @@ * before including this file. */ -// Node data -SERVO_BINDING_FUNC(Servo_Node_ClearNodeData, void, RawGeckoNodeBorrowed node) +// Element data +SERVO_BINDING_FUNC(Servo_Element_ClearData, void, RawGeckoElementBorrowed node) // Styleset and Stylesheet management SERVO_BINDING_FUNC(Servo_StyleSheet_Empty, RawServoStyleSheetStrong, @@ -133,8 +133,6 @@ SERVO_BINDING_FUNC(Servo_CSSSupports, bool, const nsACString* name, const nsACString* value) // Computed style data -SERVO_BINDING_FUNC(Servo_ComputedValues_Get, ServoComputedValuesStrong, - RawGeckoNodeBorrowed node) SERVO_BINDING_FUNC(Servo_ComputedValues_GetForAnonymousBox, ServoComputedValuesStrong, ServoComputedValuesBorrowedOrNull parent_style_or_null, @@ -156,14 +154,26 @@ SERVO_BINDING_FUNC(Servo_Initialize, void) // Shut down Servo components. Should be called exactly once at shutdown. SERVO_BINDING_FUNC(Servo_Shutdown, void) -// Restyle hints -SERVO_BINDING_FUNC(Servo_ComputeRestyleHint, nsRestyleHint, - RawGeckoElementBorrowed element, ServoElementSnapshot* snapshot, - RawServoStyleSetBorrowed set) +// Gets the snapshot for the element. This will return null if the element +// has never been styled, since snapshotting in that case is wasted work. +SERVO_BINDING_FUNC(Servo_Element_GetSnapshot, ServoElementSnapshot*, + RawGeckoElementBorrowed element) + +// Restyle and change hints. +SERVO_BINDING_FUNC(Servo_NoteExplicitHints, void, RawGeckoElementBorrowed element, + nsRestyleHint restyle_hint, nsChangeHint change_hint) +SERVO_BINDING_FUNC(Servo_CheckChangeHint, nsChangeHint, RawGeckoElementBorrowed element) +SERVO_BINDING_FUNC(Servo_ResolveStyle, ServoComputedValuesStrong, + RawGeckoElementBorrowed element, RawServoStyleSetBorrowed set, + mozilla::ConsumeStyleBehavior consume, mozilla::LazyComputeBehavior compute) // Restyle the given subtree. -SERVO_BINDING_FUNC(Servo_RestyleSubtree, void, - RawGeckoNodeBorrowed node, RawServoStyleSetBorrowed set) +SERVO_BINDING_FUNC(Servo_TraverseSubtree, void, + RawGeckoElementBorrowed root, RawServoStyleSetBorrowed set, + mozilla::SkipRootBehavior skip_root) + +// Assert that the tree has no pending or unconsumed restyles. +SERVO_BINDING_FUNC(Servo_AssertTreeIsClean, void, RawGeckoElementBorrowed root) // Style-struct management. #define STYLE_STRUCT(name, checkdata_cb) \ diff --git a/layout/style/ServoBindingTypes.h b/layout/style/ServoBindingTypes.h index 380990e6dd26..bda3b050d2bc 100644 --- a/layout/style/ServoBindingTypes.h +++ b/layout/style/ServoBindingTypes.h @@ -18,6 +18,7 @@ struct RawServoDeclarationBlock; struct RawServoStyleRule; namespace mozilla { + class ServoElementSnapshot; namespace dom { class Element; class StyleChildrenIterator; @@ -29,6 +30,7 @@ class nsIDocument; class nsINode; using mozilla::dom::StyleChildrenIterator; +using mozilla::ServoElementSnapshot; typedef nsINode RawGeckoNode; typedef mozilla::dom::Element RawGeckoElement; @@ -85,6 +87,7 @@ DECL_NULLABLE_BORROWED_REF_TYPE_FOR(RawServoDeclarationBlockStrong) DECL_OWNED_REF_TYPE_FOR(RawServoStyleSet) DECL_NULLABLE_OWNED_REF_TYPE_FOR(StyleChildrenIterator) DECL_OWNED_REF_TYPE_FOR(StyleChildrenIterator) +DECL_OWNED_REF_TYPE_FOR(ServoElementSnapshot) // We don't use BorrowedMut because the nodes may alias // Servo itself doesn't directly read or mutate these; @@ -98,6 +101,7 @@ DECL_NULLABLE_BORROWED_REF_TYPE_FOR(RawGeckoElement) DECL_BORROWED_REF_TYPE_FOR(RawGeckoDocument) DECL_NULLABLE_BORROWED_REF_TYPE_FOR(RawGeckoDocument) DECL_BORROWED_MUT_REF_TYPE_FOR(StyleChildrenIterator) +DECL_BORROWED_MUT_REF_TYPE_FOR(ServoElementSnapshot) DECL_BORROWED_REF_TYPE_FOR(nsCSSValue) DECL_BORROWED_MUT_REF_TYPE_FOR(nsCSSValue) diff --git a/layout/style/ServoBindings.cpp b/layout/style/ServoBindings.cpp index ae6fec61f7ae..acf75a9fa97b 100644 --- a/layout/style/ServoBindings.cpp +++ b/layout/style/ServoBindings.cpp @@ -97,8 +97,7 @@ Gecko_GetNextSibling(RawGeckoNodeBorrowed aNode) RawGeckoElementBorrowedOrNull Gecko_GetParentElement(RawGeckoElementBorrowed aElement) { - nsINode* parentNode = aElement->GetFlattenedTreeParentNode(); - return parentNode->IsElement() ? parentNode->AsElement() : nullptr; + return aElement->GetFlattenedTreeParentElement(); } RawGeckoElementBorrowedOrNull @@ -275,45 +274,18 @@ Gecko_CalcStyleDifference(nsStyleContext* aOldStyleContext, return result; } -void -Gecko_StoreStyleDifference(RawGeckoNodeBorrowed aNode, nsChangeHint aChangeHintToStore) +ServoElementSnapshotOwned +Gecko_CreateElementSnapshot(RawGeckoElementBorrowed aElement) { -#ifdef MOZ_STYLO - MOZ_ASSERT(aNode->IsElement()); - MOZ_ASSERT(aNode->IsDirtyForServo(), - "Change hint stored in a not-dirty node"); + return new ServoElementSnapshot(aElement); +} - const Element* aElement = aNode->AsElement(); - nsIFrame* primaryFrame = aElement->GetPrimaryFrame(); - if (!primaryFrame) { - // If there's no primary frame, that means that either this content is - // undisplayed (so we only need to check at the restyling phase for the - // display value on the element), or is a display: contents element. - // - // In this second case, we should store it in the frame constructor display - // contents map. Note that while this operation looks hairy, this would be - // thread-safe because the content should be there already (we'd only need - // to read the map and modify our entry). - // - // That being said, we still don't support display: contents anyway, so it's - // probably not worth it to do all the roundtrip just yet until we have a - // more concrete plan. - return; - } - - if ((aChangeHintToStore & nsChangeHint_ReconstructFrame) && - aNode->IsInNativeAnonymousSubtree()) - { - NS_WARNING("stylo: Removing forbidden frame reconstruction hint on native " - "anonymous content. Fix this in bug 1297857!"); - aChangeHintToStore &= ~nsChangeHint_ReconstructFrame; - } - - primaryFrame->StyleContext()->StoreChangeHint(aChangeHintToStore); -#else - MOZ_CRASH("stylo: Shouldn't call Gecko_StoreStyleDifference in " - "non-stylo build"); -#endif +void +Gecko_DropElementSnapshot(ServoElementSnapshotOwned aSnapshot) +{ + MOZ_ASSERT(NS_IsMainThread(), + "ServoAttrSnapshots can only be dropped on the main thread"); + delete aSnapshot; } RawServoDeclarationBlockStrongBorrowedOrNull @@ -581,7 +553,7 @@ ClassOrClassList(Implementor* aElement, nsIAtom** aClass, nsIAtom*** aClassList) } SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_, RawGeckoElementBorrowed) -SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_Snapshot, ServoElementSnapshot*) +SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_Snapshot, const ServoElementSnapshot*) #undef SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS diff --git a/layout/style/ServoBindings.h b/layout/style/ServoBindings.h index 01963090a879..73c694356c43 100644 --- a/layout/style/ServoBindings.h +++ b/layout/style/ServoBindings.h @@ -138,7 +138,7 @@ nsIAtom* Gecko_GetElementId(RawGeckoElementBorrowed element); SERVO_DECLARE_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_, RawGeckoElementBorrowed) SERVO_DECLARE_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_Snapshot, - ServoElementSnapshot*) + const ServoElementSnapshot*) #undef SERVO_DECLARE_ELEMENT_ATTR_MATCHING_FUNCTIONS @@ -220,17 +220,16 @@ void Gecko_SetNodeFlags(RawGeckoNodeBorrowed node, uint32_t flags); void Gecko_UnsetNodeFlags(RawGeckoNodeBorrowed node, uint32_t flags); // Incremental restyle. -// TODO: We would avoid a few ffi calls if we decide to make an API like the -// former CalcAndStoreStyleDifference, but that would effectively mean breaking -// some safety guarantees in the servo side. -// // Also, we might want a ComputedValues to ComputedValues API for animations? // Not if we do them in Gecko... nsStyleContext* Gecko_GetStyleContext(RawGeckoNodeBorrowed node, nsIAtom* aPseudoTagOrNull); nsChangeHint Gecko_CalcStyleDifference(nsStyleContext* oldstyle, ServoComputedValuesBorrowed newstyle); -void Gecko_StoreStyleDifference(RawGeckoNodeBorrowed node, nsChangeHint change); + +// Element snapshot. +ServoElementSnapshotOwned Gecko_CreateElementSnapshot(RawGeckoElementBorrowed element); +void Gecko_DropElementSnapshot(ServoElementSnapshotOwned snapshot); // `array` must be an nsTArray // If changing this signature, please update the diff --git a/layout/style/ServoElementSnapshot.cpp b/layout/style/ServoElementSnapshot.cpp index 2b1dd840db7d..29999ffe3749 100644 --- a/layout/style/ServoElementSnapshot.cpp +++ b/layout/style/ServoElementSnapshot.cpp @@ -11,18 +11,22 @@ namespace mozilla { -ServoElementSnapshot::ServoElementSnapshot(Element* aElement) +ServoElementSnapshot::ServoElementSnapshot(const Element* aElement) : mContains(Flags(0)) , mState(0) - , mExplicitRestyleHint(nsRestyleHint(0)) - , mExplicitChangeHint(nsChangeHint(0)) { + MOZ_COUNT_CTOR(ServoElementSnapshot); mIsHTMLElementInHTMLDocument = aElement->IsHTMLElement() && aElement->IsInHTMLDocument(); mIsInChromeDocument = nsContentUtils::IsChromeDoc(aElement->OwnerDoc()); } +ServoElementSnapshot::~ServoElementSnapshot() +{ + MOZ_COUNT_DTOR(ServoElementSnapshot); +} + void ServoElementSnapshot::AddAttrs(Element* aElement) { diff --git a/layout/style/ServoElementSnapshot.h b/layout/style/ServoElementSnapshot.h index 638b2fd311b2..7a064d9e110d 100644 --- a/layout/style/ServoElementSnapshot.h +++ b/layout/style/ServoElementSnapshot.h @@ -67,7 +67,8 @@ class ServoElementSnapshot public: typedef ServoElementSnapshotFlags Flags; - explicit ServoElementSnapshot(Element* aElement); + explicit ServoElementSnapshot(const Element* aElement); + ~ServoElementSnapshot(); bool HasAttrs() { return HasAny(Flags::Attributes); } @@ -89,20 +90,6 @@ public: */ void AddAttrs(Element* aElement); - void AddExplicitChangeHint(nsChangeHint aMinChangeHint) - { - mExplicitChangeHint |= aMinChangeHint; - } - - void AddExplicitRestyleHint(nsRestyleHint aRestyleHint) - { - mExplicitRestyleHint |= aRestyleHint; - } - - nsRestyleHint ExplicitRestyleHint() { return mExplicitRestyleHint; } - - nsChangeHint ExplicitChangeHint() { return mExplicitChangeHint; } - /** * Needed methods for attribute matching. */ @@ -158,8 +145,6 @@ private: Flags mContains; nsTArray mAttrs; ServoStateType mState; - nsRestyleHint mExplicitRestyleHint; - nsChangeHint mExplicitChangeHint; bool mIsHTMLElementInHTMLDocument; bool mIsInChromeDocument; }; diff --git a/layout/style/ServoStyleSet.cpp b/layout/style/ServoStyleSet.cpp index 7bba9fd85f9a..f9450c73b8a8 100644 --- a/layout/style/ServoStyleSet.cpp +++ b/layout/style/ServoStyleSet.cpp @@ -89,20 +89,26 @@ ServoStyleSet::EndUpdate() already_AddRefed ServoStyleSet::ResolveStyleFor(Element* aElement, - nsStyleContext* aParentContext) + nsStyleContext* aParentContext, + ConsumeStyleBehavior aConsume, + LazyComputeBehavior aMayCompute) { return GetContext(aElement, aParentContext, nullptr, - CSSPseudoElementType::NotPseudo); + CSSPseudoElementType::NotPseudo, aConsume, aMayCompute); } already_AddRefed ServoStyleSet::GetContext(nsIContent* aContent, nsStyleContext* aParentContext, nsIAtom* aPseudoTag, - CSSPseudoElementType aPseudoType) + CSSPseudoElementType aPseudoType, + ConsumeStyleBehavior aConsume, + LazyComputeBehavior aMayCompute) { + MOZ_ASSERT(aContent->IsElement()); + Element* element = aContent->AsElement(); RefPtr computedValues = - Servo_ComputedValues_Get(aContent).Consume(); + Servo_ResolveStyle(element, mRawSet.get(), aConsume, aMayCompute).Consume(); MOZ_ASSERT(computedValues); return GetContext(computedValues.forget(), aParentContext, aPseudoTag, aPseudoType); } @@ -126,12 +132,14 @@ ServoStyleSet::GetContext(already_AddRefed aComputedValues, already_AddRefed ServoStyleSet::ResolveStyleFor(Element* aElement, nsStyleContext* aParentContext, + ConsumeStyleBehavior aConsume, + LazyComputeBehavior aMayCompute, TreeMatchContext& aTreeMatchContext) { // aTreeMatchContext is used to speed up selector matching, // but if the element already has a ServoComputedValues computed in // advance, then we shouldn't need to use it. - return ResolveStyleFor(aElement, aParentContext); + return ResolveStyleFor(aElement, aParentContext, aConsume, aMayCompute); } already_AddRefed @@ -437,58 +445,39 @@ ServoStyleSet::HasStateDependentStyle(dom::Element* aElement, return nsRestyleHint(0); } -nsRestyleHint -ServoStyleSet::ComputeRestyleHint(dom::Element* aElement, - ServoElementSnapshot* aSnapshot) -{ - return Servo_ComputeRestyleHint(aElement, aSnapshot, mRawSet.get()); -} - -static void -ClearDirtyBits(nsIContent* aContent) -{ - bool traverseDescendants = aContent->HasDirtyDescendantsForServo(); - aContent->UnsetIsDirtyAndHasDirtyDescendantsForServo(); - if (!traverseDescendants) { - return; - } - - StyleChildrenIterator it(aContent); - for (nsIContent* n = it.GetNextChild(); n; n = it.GetNextChild()) { - ClearDirtyBits(n); - } -} - void -ServoStyleSet::StyleDocument(bool aLeaveDirtyBits) +ServoStyleSet::StyleDocument() { // Grab the root. nsIDocument* doc = mPresContext->Document(); - nsIContent* root = doc->GetRootElement(); + Element* root = doc->GetRootElement(); MOZ_ASSERT(root); - // Restyle the document, clearing the dirty bits if requested. - Servo_RestyleSubtree(root, mRawSet.get()); - if (!aLeaveDirtyBits) { - ClearDirtyBits(root); - doc->UnsetHasDirtyDescendantsForServo(); - } + // Restyle the document. + Servo_TraverseSubtree(root, mRawSet.get(), SkipRootBehavior::DontSkip); } void ServoStyleSet::StyleNewSubtree(nsIContent* aContent) { - MOZ_ASSERT(aContent->IsDirtyForServo()); - if (aContent->IsElement() || aContent->IsNodeOfType(nsINode::eTEXT)) { - Servo_RestyleSubtree(aContent, mRawSet.get()); + if (aContent->IsElement()) { + Servo_TraverseSubtree(aContent->AsElement(), mRawSet.get(), SkipRootBehavior::DontSkip); } - ClearDirtyBits(aContent); } void ServoStyleSet::StyleNewChildren(nsIContent* aParent) { - MOZ_ASSERT(aParent->HasDirtyDescendantsForServo()); - Servo_RestyleSubtree(aParent, mRawSet.get()); - ClearDirtyBits(aParent); + MOZ_ASSERT(aParent->IsElement()); + Servo_TraverseSubtree(aParent->AsElement(), mRawSet.get(), SkipRootBehavior::Skip); } + +#ifdef DEBUG +void +ServoStyleSet::AssertTreeIsClean() +{ + if (Element* root = mPresContext->Document()->GetRootElement()) { + Servo_AssertTreeIsClean(root); + } +} +#endif diff --git a/layout/style/ServoStyleSet.h b/layout/style/ServoStyleSet.h index 26b515afdafc..e4424952102b 100644 --- a/layout/style/ServoStyleSet.h +++ b/layout/style/ServoStyleSet.h @@ -56,11 +56,15 @@ public: already_AddRefed ResolveStyleFor(dom::Element* aElement, - nsStyleContext* aParentContext); + nsStyleContext* aParentContext, + ConsumeStyleBehavior aConsume, + LazyComputeBehavior aMayCompute); already_AddRefed ResolveStyleFor(dom::Element* aElement, nsStyleContext* aParentContext, + ConsumeStyleBehavior aConsume, + LazyComputeBehavior aMayCompute, TreeMatchContext& aTreeMatchContext); already_AddRefed @@ -117,20 +121,11 @@ public: dom::Element* aElement, mozilla::CSSPseudoElementType aPseudoType, dom::Element* aPseudoElement, EventStates aStateMask); - /** - * Computes a restyle hint given a element and a previous element snapshot. - */ - nsRestyleHint ComputeRestyleHint(dom::Element* aElement, - ServoElementSnapshot* aSnapshot); - /** * Performs a Servo traversal to compute style for all dirty nodes in the * document. The root element must be non-null. - * - * If aLeaveDirtyBits is true, the dirty/dirty-descendant bits are not - * cleared. */ - void StyleDocument(bool aLeaveDirtyBits); + void StyleDocument(); /** * Eagerly styles a subtree of dirty nodes that were just appended to the @@ -152,6 +147,12 @@ public: */ void StyleNewChildren(nsIContent* aParent); +#ifdef DEBUG + void AssertTreeIsClean(); +#else + void AssertTreeIsClean() {} +#endif + private: already_AddRefed GetContext(already_AddRefed, nsStyleContext* aParentContext, @@ -161,7 +162,9 @@ private: already_AddRefed GetContext(nsIContent* aContent, nsStyleContext* aParentContext, nsIAtom* aPseudoTag, - CSSPseudoElementType aPseudoType); + CSSPseudoElementType aPseudoType, + ConsumeStyleBehavior aConsume, + LazyComputeBehavior aMayCompute); nsPresContext* mPresContext; UniquePtr mRawSet; diff --git a/layout/style/ServoTypes.h b/layout/style/ServoTypes.h index 6d1324b887e1..00f78bbe13e8 100644 --- a/layout/style/ServoTypes.h +++ b/layout/style/ServoTypes.h @@ -35,6 +35,29 @@ struct ServoCell { ServoCell() : value() {}; }; +// Indicates whether a style resolution should be considered to consume the style +// for the construction of a layout frame, or whether the caller is just +// peeking. +enum class ConsumeStyleBehavior { + Consume, + DontConsume, +}; + +// Indicates whether the Servo style system should expect the style on an element +// to have already been resolved (i.e. via a parallel traversal), or whether it +// may be lazily computed. +enum class LazyComputeBehavior { + Allow, + Assert, +}; + +// Indicates whether the Servo style system should skip processing on the root +// element and start processing with its children. +enum class SkipRootBehavior { + Skip, + DontSkip, +}; + } // namespace mozilla #endif // mozilla_ServoTypes_h diff --git a/layout/style/StyleSetHandle.h b/layout/style/StyleSetHandle.h index ad75f75ae48d..f2484f2ea5a9 100644 --- a/layout/style/StyleSetHandle.h +++ b/layout/style/StyleSetHandle.h @@ -9,6 +9,7 @@ #include "mozilla/EventStates.h" #include "mozilla/RefPtr.h" +#include "mozilla/ServoTypes.h" #include "mozilla/SheetType.h" #include "mozilla/StyleBackendType.h" #include "mozilla/StyleSheet.h" @@ -114,10 +115,14 @@ public: inline nsresult EndUpdate(); inline already_AddRefed ResolveStyleFor(dom::Element* aElement, - nsStyleContext* aParentContext); + nsStyleContext* aParentContext, + ConsumeStyleBehavior aConsume, + LazyComputeBehavior aMayCompute); inline already_AddRefed ResolveStyleFor(dom::Element* aElement, nsStyleContext* aParentContext, + ConsumeStyleBehavior aConsume, + LazyComputeBehavior aMayCompute, TreeMatchContext& aTreeMatchContext); inline already_AddRefed ResolveStyleForText(nsIContent* aTextNode, diff --git a/layout/style/StyleSetHandleInlines.h b/layout/style/StyleSetHandleInlines.h index 2bb32101faa7..990077cdf7a6 100644 --- a/layout/style/StyleSetHandleInlines.h +++ b/layout/style/StyleSetHandleInlines.h @@ -79,17 +79,21 @@ StyleSetHandle::Ptr::EndUpdate() // resolve a style context already_AddRefed StyleSetHandle::Ptr::ResolveStyleFor(dom::Element* aElement, - nsStyleContext* aParentContext) + nsStyleContext* aParentContext, + ConsumeStyleBehavior aConsume, + LazyComputeBehavior aMayCompute) { - FORWARD(ResolveStyleFor, (aElement, aParentContext)); + FORWARD(ResolveStyleFor, (aElement, aParentContext, aConsume, aMayCompute)); } already_AddRefed StyleSetHandle::Ptr::ResolveStyleFor(dom::Element* aElement, nsStyleContext* aParentContext, + ConsumeStyleBehavior aConsume, + LazyComputeBehavior aMayCompute, TreeMatchContext& aTreeMatchContext) { - FORWARD(ResolveStyleFor, (aElement, aParentContext, aTreeMatchContext)); + FORWARD(ResolveStyleFor, (aElement, aParentContext, aConsume, aMayCompute, aTreeMatchContext)); } already_AddRefed diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index 4f91532960dd..d00ebd702039 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -495,7 +495,8 @@ nsComputedDOMStyle::GetStyleContextForElementNoFlush(Element* aElement, sc = styleSet->ResolvePseudoElementStyle(aElement, type, parentContext, pseudoElement); } else { - sc = styleSet->ResolveStyleFor(aElement, parentContext); + sc = styleSet->ResolveStyleFor(aElement, parentContext, ConsumeStyleBehavior::DontConsume, + LazyComputeBehavior::Allow); } if (aStyleType == eDefaultOnly) { diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index 55367ec9cbd7..118143f6097f 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -563,8 +563,8 @@ static nscoord CalcLengthWith(const nsCSSValue& aValue, if (rootFrame) { rootStyle = rootFrame->StyleContext(); } else { - rootStyle = aPresContext->StyleSet()->ResolveStyleFor(docElement, - nullptr); + rootStyle = aPresContext->StyleSet()->AsGecko()->ResolveStyleFor(docElement, + nullptr); } rootStyleFont = rootStyle->StyleFont(); } diff --git a/layout/style/nsStyleContext.cpp b/layout/style/nsStyleContext.cpp index 7ad260f1bbe1..dc4e641a9248 100644 --- a/layout/style/nsStyleContext.cpp +++ b/layout/style/nsStyleContext.cpp @@ -91,12 +91,6 @@ nsStyleContext::nsStyleContext(nsStyleContext* aParent, , mCachedResetData(nullptr) , mBits(((uint64_t)aPseudoType) << NS_STYLE_CONTEXT_TYPE_SHIFT) , mRefCnt(0) -#ifdef MOZ_STYLO - , mStoredChangeHint(nsChangeHint(0)) -#ifdef DEBUG - , mConsumedChangeHint(false) -#endif -#endif #ifdef DEBUG , mFrameRefCnt(0) , mComputingStruct(nsStyleStructID_None) @@ -796,7 +790,7 @@ nsStyleContext::ApplyStyleFixups(bool aSkipParentDisplayBasedStyleFixup) mozilla::dom::Element* docElement = presContext->Document()->GetRootElement(); if (docElement) { RefPtr rootStyle = - presContext->StyleSet()->ResolveStyleFor(docElement, nullptr); + presContext->StyleSet()->AsGecko()->ResolveStyleFor(docElement, nullptr); auto dir = rootStyle->StyleVisibility()->mDirection; if (dir != StyleVisibility()->mDirection) { nsStyleVisibility* uniqueVisibility = GET_UNIQUE_STYLE_DATA(Visibility); diff --git a/layout/style/nsStyleContext.h b/layout/style/nsStyleContext.h index b0b4896a3db5..65d8502b4b22 100644 --- a/layout/style/nsStyleContext.h +++ b/layout/style/nsStyleContext.h @@ -512,45 +512,6 @@ public: mozilla::NonOwningStyleContextSource StyleSource() const { return mSource.AsRaw(); } -#ifdef MOZ_STYLO - // NOTE: It'd be great to assert here that the previous change hint is always - // consumed. - // - // This is not the case right now, since the changes of childs of frames that - // go through frame construction are not consumed. - void StoreChangeHint(nsChangeHint aHint) - { - MOZ_ASSERT(!IsShared()); - mStoredChangeHint = aHint; -#ifdef DEBUG - mConsumedChangeHint = false; -#endif - } - - nsChangeHint ConsumeStoredChangeHint() - { - MOZ_ASSERT(!mConsumedChangeHint, "Re-consuming the same change hint!"); - nsChangeHint result = mStoredChangeHint; - mStoredChangeHint = nsChangeHint(0); -#ifdef DEBUG - mConsumedChangeHint = true; -#endif - return result; - } -#else - void StoreChangeHint(nsChangeHint aHint) - { - MOZ_CRASH("stylo: Called nsStyleContext::StoreChangeHint in a non MOZ_STYLO " - "build."); - } - - nsChangeHint ConsumeStoredChangeHint() - { - MOZ_CRASH("stylo: Called nsStyleContext::ComsumeStoredChangeHint in a non " - "MOZ_STYLO build."); - } -#endif - private: // Private destructor, to discourage deletion outside of Release(): ~nsStyleContext(); @@ -809,15 +770,6 @@ private: uint32_t mRefCnt; - // For now we store change hints on the style context during parallel traversal. - // We should improve this - see bug 1289861. -#ifdef MOZ_STYLO - nsChangeHint mStoredChangeHint; -#ifdef DEBUG - bool mConsumedChangeHint; -#endif -#endif - #ifdef DEBUG uint32_t mFrameRefCnt; // number of frames that use this // as their style context diff --git a/layout/style/nsStyleSet.h b/layout/style/nsStyleSet.h index 879d0add394e..defeeb2e57bb 100644 --- a/layout/style/nsStyleSet.h +++ b/layout/style/nsStyleSet.h @@ -17,6 +17,7 @@ #include "mozilla/EnumeratedArray.h" #include "mozilla/LinkedList.h" #include "mozilla/MemoryReporting.h" +#include "mozilla/ServoTypes.h" #include "mozilla/SheetType.h" #include "nsIStyleRuleProcessor.h" @@ -112,11 +113,30 @@ class nsStyleSet final ResolveStyleFor(mozilla::dom::Element* aElement, nsStyleContext* aParentContext); + already_AddRefed + ResolveStyleFor(mozilla::dom::Element* aElement, + nsStyleContext* aParentContext, + mozilla::ConsumeStyleBehavior, + mozilla::LazyComputeBehavior) + { + return ResolveStyleFor(aElement, aParentContext); + } + already_AddRefed ResolveStyleFor(mozilla::dom::Element* aElement, nsStyleContext* aParentContext, TreeMatchContext& aTreeMatchContext); + already_AddRefed + ResolveStyleFor(mozilla::dom::Element* aElement, + nsStyleContext* aParentContext, + mozilla::ConsumeStyleBehavior aConsume, + mozilla::LazyComputeBehavior aMayCompute, + TreeMatchContext& aTreeMatchContext) + { + return ResolveStyleFor(aElement, aParentContext, aTreeMatchContext); + } + // Get a style context (with the given parent) for the // sequence of style rules in the |aRules| array. already_AddRefed diff --git a/layout/xul/nsListBoxBodyFrame.cpp b/layout/xul/nsListBoxBodyFrame.cpp index 8c4a5e2fdda9..903c7a9f5ea5 100644 --- a/layout/xul/nsListBoxBodyFrame.cpp +++ b/layout/xul/nsListBoxBodyFrame.cpp @@ -702,7 +702,9 @@ nsListBoxBodyFrame::ComputeIntrinsicISize(nsBoxLayoutState& aBoxLayoutState) RefPtr styleContext; nsPresContext *presContext = aBoxLayoutState.PresContext(); styleContext = presContext->StyleSet()-> - ResolveStyleFor(firstRowContent->AsElement(), nullptr); + ResolveStyleFor(firstRowContent->AsElement(), nullptr, + ConsumeStyleBehavior::DontConsume, + LazyComputeBehavior::Allow); nscoord width = 0; nsMargin margin(0,0,0,0); diff --git a/layout/xul/nsSplitterFrame.cpp b/layout/xul/nsSplitterFrame.cpp index 7879a176d369..5148adea4d3d 100644 --- a/layout/xul/nsSplitterFrame.cpp +++ b/layout/xul/nsSplitterFrame.cpp @@ -286,7 +286,9 @@ nsSplitterFrame::Init(nsIContent* aContent, NS_LITERAL_STRING("vertical"), false); nsStyleContext* parentStyleContext = StyleContext()->GetParent(); RefPtr newContext = PresContext()->StyleSet()-> - ResolveStyleFor(aContent->AsElement(), parentStyleContext); + ResolveStyleFor(aContent->AsElement(), parentStyleContext, + ConsumeStyleBehavior::Consume, + LazyComputeBehavior::Allow); SetStyleContextWithoutNotification(newContext); } } diff --git a/netwerk/base/PrivateBrowsingChannel.h b/netwerk/base/PrivateBrowsingChannel.h index 0fe96bd1a29f..10c66450234f 100644 --- a/netwerk/base/PrivateBrowsingChannel.h +++ b/netwerk/base/PrivateBrowsingChannel.h @@ -14,6 +14,7 @@ #include "nsIInterfaceRequestorUtils.h" #include "nsIInterfaceRequestor.h" #include "nsNetUtil.h" +#include "mozilla/Unused.h" namespace mozilla { namespace net { @@ -71,10 +72,20 @@ public: return; } + auto channel = static_cast(this); + nsCOMPtr loadContext; - NS_QueryNotificationCallbacks(static_cast(this), loadContext); + NS_QueryNotificationCallbacks(channel, loadContext); if (loadContext) { mPrivateBrowsing = loadContext->UsePrivateBrowsing(); + return; + } + + nsCOMPtr loadInfo; + Unused << channel->GetLoadInfo(getter_AddRefs(loadInfo)); + if (loadInfo) { + NeckoOriginAttributes attrs = loadInfo->GetOriginAttributes(); + mPrivateBrowsing = attrs.mPrivateBrowsingId > 0; } } diff --git a/netwerk/ipc/NeckoParent.cpp b/netwerk/ipc/NeckoParent.cpp index 1dd6bea7e454..ff04913e406c 100644 --- a/netwerk/ipc/NeckoParent.cpp +++ b/netwerk/ipc/NeckoParent.cpp @@ -159,18 +159,22 @@ NeckoParent::GetValidatedOriginAttributes(const SerializedLoadContext& aSerializ nsIPrincipal* aRequestingPrincipal, DocShellOriginAttributes& aAttrs) { - if (!aSerialized.IsNotNull()) { - if (UsingNeckoIPCSecurity()) { - CrashWithReason("GetValidatedOriginAttributes | SerializedLoadContext from child is null"); - return "SerializedLoadContext from child is null"; + if (!UsingNeckoIPCSecurity()) { + if (!aSerialized.IsNotNull()) { + // If serialized is null, we cannot validate anything. We have to assume + // that this requests comes from a SystemPrincipal. + aAttrs = DocShellOriginAttributes(NECKO_NO_APP_ID, false); + } else { + aAttrs = aSerialized.mOriginAttributes; } - - // If serialized is null, we cannot validate anything. We have to assume - // that this requests comes from a SystemPrincipal. - aAttrs = DocShellOriginAttributes(NECKO_NO_APP_ID, false); return nullptr; } + if (!aSerialized.IsNotNull()) { + CrashWithReason("GetValidatedOriginAttributes | SerializedLoadContext from child is null"); + return "SerializedLoadContext from child is null"; + } + nsTArray contextArray = static_cast(aContent)->GetManagedTabContext(); @@ -213,12 +217,6 @@ NeckoParent::GetValidatedOriginAttributes(const SerializedLoadContext& aSerializ } } - if (!UsingNeckoIPCSecurity()) { - // We are running some tests - aAttrs = aSerialized.mOriginAttributes; - return nullptr; - } - nsAutoCString errorString; errorString.Append("GetValidatedOriginAttributes | App does not have permission -"); errorString.Append(debugString); diff --git a/python/mozboot/mozboot/base.py b/python/mozboot/mozboot/base.py index 0eb257bd3524..522ef217a585 100644 --- a/python/mozboot/mozboot/base.py +++ b/python/mozboot/mozboot/base.py @@ -75,8 +75,9 @@ We recommend the following tools for installing Python: RUST_NOT_IN_PATH = ''' You have some rust files in %(cargo_bin)s, but they're not part of the -standard PATH. +standard PATH.''' +RUST_PATH_ADVICE = ''' To make these available, please add this directory to the PATH variable in your shell initialization script, which may be called ~/.bashrc or ~/.bash_profile or ~/.profile. Edit this and add the following line: @@ -514,6 +515,12 @@ class BaseBootstrapper(object): return our >= MODERN_RUST_VERSION, our + def cargo_home(self): + cargo_home = os.environ.get('CARGO_HOME', + os.path.expanduser(os.path.join('~', '.cargo'))) + cargo_bin = os.path.join(cargo_home, 'bin') + return cargo_home, cargo_bin + def ensure_rust_modern(self): modern, version = self.is_rust_modern() @@ -523,16 +530,14 @@ class BaseBootstrapper(object): if not version: # Rust wasn't in PATH. Try the standard path. - cargo_home = os.environ.get('CARGO_HOME', - os.path.expanduser(os.path.join('~', '.cargo'))) - cargo_bin = os.path.join(cargo_home, 'bin') + cargo_home, cargo_bin = self.cargo_home() try_rustc = os.path.join(cargo_bin, 'rustc' + rust.exe_suffix()) try_cargo = os.path.join(cargo_bin, 'cargo' + rust.exe_suffix()) have_rustc = os.path.exists(try_rustc) have_cargo = os.path.exists(try_cargo) if have_rustc or have_cargo: - print(RUST_NOT_IN_PATH % { 'cargo_bin': cargo_bin, - 'cargo_home': cargo_home }) + print(RUST_NOT_IN_PATH % { 'cargo_bin': cargo_bin }) + print(RUST_PATH_ADVICE % { 'cargo_home': cargo_home }) sys.exit(1) rustup = self.which('rustup') @@ -550,17 +555,16 @@ class BaseBootstrapper(object): print('Your version of Rust (%s) is too old. Will try to upgrade.' % version) self.upgrade_rust(rustup) + + modern, after = self.is_rust_modern() + if not modern: + print(RUST_UPGRADE_FAILED % (MODERN_RUST_VERSION, after)) + sys.exit(1) else: # No rustc or rustup. print('Will try to install Rust.') self.install_rust() - modern, after = self.is_rust_modern() - - if not modern: - print(RUST_UPGRADE_FAILED % (MODERN_RUST_VERSION, after)) - sys.exit(1) - def upgrade_rust(self, rustup): """Upgrade Rust. @@ -591,7 +595,10 @@ class BaseBootstrapper(object): '--default-toolchain', 'stable', '--default-host', platform, ]) + cargo_home, cargo_bin = self.cargo_home() print('Rust installation complete.') + print('You should now have rustc and cargo in %s' % cargo_bin) + print(RUST_PATH_ADVICE % { 'cargo_home': cargo_home }) finally: try: os.remove(rustup_init) diff --git a/toolkit/components/extensions/test/mochitest/mochitest-common.ini b/toolkit/components/extensions/test/mochitest/mochitest-common.ini index 6e45f293f69e..8719c959007e 100644 --- a/toolkit/components/extensions/test/mochitest/mochitest-common.ini +++ b/toolkit/components/extensions/test/mochitest/mochitest-common.ini @@ -51,6 +51,8 @@ skip-if = os == 'android' # Android does not currently support windows. [test_ext_contentscript_create_iframe.html] [test_ext_contentscript_devtools_metadata.html] [test_ext_contentscript_exporthelpers.html] +[test_ext_contentscript_incognito.html] +skip-if = os == 'android' # Android does not multiple windows. [test_ext_contentscript_css.html] [test_ext_contentscript_about_blank.html] [test_ext_contentscript_teardown.html] diff --git a/toolkit/components/extensions/test/mochitest/test_ext_contentscript_incognito.html b/toolkit/components/extensions/test/mochitest/test_ext_contentscript_incognito.html new file mode 100644 index 000000000000..a2f38dce655c --- /dev/null +++ b/toolkit/components/extensions/test/mochitest/test_ext_contentscript_incognito.html @@ -0,0 +1,89 @@ + + + + Test for content script private browsing ID + + + + + + + + + + + + + diff --git a/toolkit/components/extensions/test/mochitest/test_ext_webrequest_suspend.html b/toolkit/components/extensions/test/mochitest/test_ext_webrequest_suspend.html index 09f4b1f7fced..4ad67cc957c1 100644 --- a/toolkit/components/extensions/test/mochitest/test_ext_webrequest_suspend.html +++ b/toolkit/components/extensions/test/mochitest/test_ext_webrequest_suspend.html @@ -64,6 +64,76 @@ add_task(function* test_suspend() { yield extension.unload(); }); + +// Test that requests that were canceled while suspended for a blocking +// listener are correctly resumed. +add_task(function* test_error_resume() { + let chromeScript = SpecialPowers.loadChromeScript(() => { + const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; + Cu.import("resource://gre/modules/Services.jsm"); + + let observer = channel => { + if (channel instanceof Ci.nsIHttpChannel && channel.URI.spec === "http://example.com/") { + Services.obs.removeObserver(observer, "http-on-modify-request"); + + // Wait until the next tick to make sure this runs after WebRequest observers. + Promise.resolve().then(() => { + channel.cancel(Cr.NS_BINDING_ABORTED); + }); + } + }; + + Services.obs.addObserver(observer, "http-on-modify-request", false); + }); + + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + permissions: [ + "webRequest", + "webRequestBlocking", + ], + }, + + background() { + browser.webRequest.onBeforeSendHeaders.addListener( + details => { + browser.test.log(`onBeforeSendHeaders({url: ${details.url}})`); + + if (details.url === "http://example.com/") { + browser.test.sendMessage("got-before-send-headers"); + } + }, + {urls: [""]}, + ["blocking"]); + + browser.webRequest.onErrorOccurred.addListener( + details => { + browser.test.log(`onErrorOccurred({url: ${details.url}})`); + + if (details.url === "http://example.com/") { + browser.test.sendMessage("got-error-occurred"); + } + }, + {urls: [""]}); + }, + }); + + yield extension.startup(); + + try { + yield fetch("http://example.com/"); + ok(false, "Fetch should have failed."); + } catch (e) { + ok(true, "Got expected error."); + } + + yield extension.awaitMessage("got-before-send-headers"); + yield extension.awaitMessage("got-error-occurred"); + + yield extension.unload(); + chromeScript.destroy(); +}); + diff --git a/toolkit/modules/WebChannel.jsm b/toolkit/modules/WebChannel.jsm index 4093a554cf23..8c47b95e8e5f 100644 --- a/toolkit/modules/WebChannel.jsm +++ b/toolkit/modules/WebChannel.jsm @@ -9,6 +9,8 @@ this.EXPORTED_SYMBOLS = ["WebChannel", "WebChannelBroker"]; +const ERRNO_MISSING_PRINCIPAL = 1; +const ERRNO_NO_SUCH_CHANNEL = 2; const ERRNO_UNKNOWN_ERROR = 999; const ERROR_UNKNOWN = "UNKNOWN_ERROR"; @@ -83,7 +85,7 @@ var WebChannelBroker = Object.create({ if (data && data.id) { if (!event.principal) { - this._sendErrorEventToContent(data.id, sendingContext, "Message principal missing"); + this._sendErrorEventToContent(data.id, sendingContext, ERRNO_MISSING_PRINCIPAL, "Message principal missing"); } else { let validChannelFound = false; data.message = data.message || {}; @@ -98,7 +100,7 @@ var WebChannelBroker = Object.create({ // if no valid origins send an event that there is no such valid channel if (!validChannelFound) { - this._sendErrorEventToContent(data.id, sendingContext, "No Such Channel"); + this._sendErrorEventToContent(data.id, sendingContext, ERRNO_NO_SUCH_CHANNEL, "No Such Channel"); } } } else { @@ -127,7 +129,7 @@ var WebChannelBroker = Object.create({ * Error message * @private */ - _sendErrorEventToContent: function(id, sendingContext, errorMsg) { + _sendErrorEventToContent: function(id, sendingContext, errorNo, errorMsg) { let { browser: targetBrowser, eventTarget, principal: targetPrincipal } = sendingContext; errorMsg = errorMsg || "Web Channel Broker error"; @@ -135,7 +137,10 @@ var WebChannelBroker = Object.create({ if (targetBrowser && targetBrowser.messageManager) { targetBrowser.messageManager.sendAsyncMessage("WebChannelMessageToContent", { id: id, - error: errorMsg, + message: { + errno: errorNo, + error: errorMsg, + }, }, { eventTarget: eventTarget }, targetPrincipal); } else { Cu.reportError("Failed to send a WebChannel error. Target invalid."); diff --git a/toolkit/modules/addons/WebRequest.jsm b/toolkit/modules/addons/WebRequest.jsm index 9ac5bd6eaedb..68e974f32c03 100644 --- a/toolkit/modules/addons/WebRequest.jsm +++ b/toolkit/modules/addons/WebRequest.jsm @@ -780,22 +780,18 @@ HttpObserverManager = { responseHeaders.applyChanges(result.responseHeaders); } } + + if (kind === "opening") { + yield this.runChannelListener(channel, loadContext, "modify"); + } else if (kind === "modify") { + yield this.runChannelListener(channel, loadContext, "afterModify"); + } } catch (e) { Cu.reportError(e); } - if (kind === "opening") { - return this.runChannelListener(channel, loadContext, "modify"); - } else if (kind === "modify") { - return this.runChannelListener(channel, loadContext, "afterModify"); - } - - // Only resume the channel if either it was suspended by this call, - // and this callback is not part of the opening-modify-afterModify - // chain, or if this is an afterModify callback. This allows us to - // chain the aforementioned handlers without repeatedly suspending - // and resuming the request. - if (shouldResume || kind === "afterModify") { + // Only resume the channel if either it was suspended by this call. + if (shouldResume) { this.maybeResume(channel); } }), diff --git a/toolkit/themes/linux/global/notification.css b/toolkit/themes/linux/global/notification.css index b0002f94bb0a..bf67213987e9 100644 --- a/toolkit/themes/linux/global/notification.css +++ b/toolkit/themes/linux/global/notification.css @@ -68,7 +68,7 @@ notification[type="critical"] { %include ../../shared/popupnotification.inc.css -.popup-notification-button:focus { +.popup-notification-button:-moz-focusring { outline: 1px -moz-dialogtext dotted; outline-offset: -5px; } diff --git a/toolkit/themes/osx/global/notification.css b/toolkit/themes/osx/global/notification.css index 5bdb0cd88a9c..3ba750a09b36 100644 --- a/toolkit/themes/osx/global/notification.css +++ b/toolkit/themes/osx/global/notification.css @@ -105,7 +105,7 @@ notification[type="info"]:not([value="translation"]) .close-icon:not(:hover) { %include ../../shared/popupnotification.inc.css -.popup-notification-button:focus { +.popup-notification-button:-moz-focusring { outline: 2px -moz-mac-focusring solid; outline-offset: -2px; } diff --git a/toolkit/themes/windows/global/notification.css b/toolkit/themes/windows/global/notification.css index 270d4fd75940..e9e18db43ced 100644 --- a/toolkit/themes/windows/global/notification.css +++ b/toolkit/themes/windows/global/notification.css @@ -68,7 +68,7 @@ notification[type="critical"] { %include ../../shared/popupnotification.inc.css -.popup-notification-button:focus { +.popup-notification-button:-moz-focusring { outline: 1px -moz-dialogtext dotted; outline-offset: -1px; }