diff --git a/accessible/src/base/DocManager.cpp b/accessible/src/base/DocManager.cpp index 91ebd3f564d..7a2db75fd95 100644 --- a/accessible/src/base/DocManager.cpp +++ b/accessible/src/base/DocManager.cpp @@ -15,9 +15,9 @@ #include "Logging.h" #endif +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() #include "nsCURILoader.h" #include "nsDocShellLoadTypes.h" -#include "nsDOMEvent.h" #include "nsIChannel.h" #include "nsIDOMDocument.h" #include "nsEventListenerManager.h" diff --git a/accessible/src/generic/RootAccessible.cpp b/accessible/src/generic/RootAccessible.cpp index 82ffbdf4e4a..d7e77522582 100644 --- a/accessible/src/generic/RootAccessible.cpp +++ b/accessible/src/generic/RootAccessible.cpp @@ -28,6 +28,7 @@ #include "nsIAccessibleRelation.h" #include "nsIDocShellTreeItem.h" #include "nsIDocShellTreeOwner.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/EventTarget.h" #include "nsIDOMDataContainerEvent.h" #include "nsIDOMXULMultSelectCntrlEl.h" @@ -39,7 +40,6 @@ #include "nsIWebBrowserChrome.h" #include "nsReadableUtils.h" #include "nsFocusManager.h" -#include "nsDOMEvent.h" #ifdef MOZ_XUL #include "nsIXULDocument.h" @@ -234,7 +234,7 @@ NS_IMETHODIMP RootAccessible::HandleEvent(nsIDOMEvent* aDOMEvent) { MOZ_ASSERT(aDOMEvent); - nsDOMEvent* event = aDOMEvent->InternalDOMEvent(); + Event* event = aDOMEvent->InternalDOMEvent(); nsCOMPtr origTargetNode = do_QueryInterface(event->GetOriginalTarget()); if (!origTargetNode) return NS_OK; @@ -266,7 +266,7 @@ void RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent) { MOZ_ASSERT(aDOMEvent); - nsDOMEvent* event = aDOMEvent->InternalDOMEvent(); + Event* event = aDOMEvent->InternalDOMEvent(); nsCOMPtr origTargetNode = do_QueryInterface(event->GetOriginalTarget()); nsAutoString eventType; diff --git a/accessible/src/jsat/AccessFu.jsm b/accessible/src/jsat/AccessFu.jsm index 1b542c412e1..6de780f761e 100644 --- a/accessible/src/jsat/AccessFu.jsm +++ b/accessible/src/jsat/AccessFu.jsm @@ -309,7 +309,7 @@ this.AccessFu = { case 'Accessibility:Focus': this._focused = JSON.parse(aData); if (this._focused) { - this.showCurrent(true); + this.autoMove({ forcePresent: true, noOpIfOnScreen: true }); } break; case 'Accessibility:MoveByGranularity': @@ -353,10 +353,11 @@ this.AccessFu = { // We delay this for half a second so the awesomebar could close, // and we could use the current coordinates for the content item. // XXX TODO figure out how to avoid magic wait here. - Utils.win.setTimeout( - function () { - this.showCurrent(false); - }.bind(this), 500); + this.autoMove({ + delay: 500, + forcePresent: true, + noOpIfOnScreen: true, + moveMethod: 'moveFirst' }); } break; } @@ -372,9 +373,9 @@ this.AccessFu = { } }, - showCurrent: function showCurrent(aMove) { + autoMove: function autoMove(aOptions) { let mm = Utils.getMessageManager(Utils.CurrentBrowser); - mm.sendAsyncMessage('AccessFu:ShowCurrent', { move: aMove }); + mm.sendAsyncMessage('AccessFu:AutoMove', aOptions); }, announce: function announce(aAnnouncement) { diff --git a/accessible/src/jsat/ContentControl.jsm b/accessible/src/jsat/ContentControl.jsm new file mode 100644 index 00000000000..c5b0622dffb --- /dev/null +++ b/accessible/src/jsat/ContentControl.jsm @@ -0,0 +1,269 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +let Ci = Components.interfaces; +let Cu = Components.utils; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, 'Services', + 'resource://gre/modules/Services.jsm'); +XPCOMUtils.defineLazyModuleGetter(this, 'Utils', + 'resource://gre/modules/accessibility/Utils.jsm'); +XPCOMUtils.defineLazyModuleGetter(this, 'Logger', + 'resource://gre/modules/accessibility/Utils.jsm'); +XPCOMUtils.defineLazyModuleGetter(this, 'Roles', + 'resource://gre/modules/accessibility/Constants.jsm'); +XPCOMUtils.defineLazyModuleGetter(this, 'TraversalRules', + 'resource://gre/modules/accessibility/TraversalRules.jsm'); +XPCOMUtils.defineLazyModuleGetter(this, 'Presentation', + 'resource://gre/modules/accessibility/Presentation.jsm'); + +this.EXPORTED_SYMBOLS = ['ContentControl']; + +this.ContentControl = function ContentControl(aContentScope) { + this._contentScope = Cu.getWeakReference(aContentScope); + this._vcCache = new WeakMap(); + this._childMessageSenders = new WeakMap(); +}; + +this.ContentControl.prototype = { + messagesOfInterest: ['AccessFu:MoveCursor', + 'AccessFu:ClearCursor', + 'AccessFu:MoveToPoint', + 'AccessFu:AutoMove'], + + start: function ContentControl_start() { + let cs = this._contentScope.get(); + for (let message of this.messagesOfInterest) { + cs.addMessageListener(message, this); + } + }, + + stop: function ContentControl_stop() { + let cs = this._contentScope.get(); + for (let message of this.messagesOfInterest) { + cs.removeMessageListener(message, this); + } + }, + + get document() { + return this._contentScope.get().content.document; + }, + + get window() { + return this._contentScope.get().content; + }, + + get vc() { + return Utils.getVirtualCursor(this.document); + }, + + receiveMessage: function ContentControl_receiveMessage(aMessage) { + Logger.debug(() => { + return ['ContentControl.receiveMessage', + this.document.location.toString(), + JSON.stringify(aMessage.json)]; + }); + + try { + switch (aMessage.name) { + case 'AccessFu:MoveCursor': + this.handleMove(aMessage); + break; + case 'AccessFu:ClearCursor': + this.handleClear(aMessage); + break; + case 'AccessFu:MoveToPoint': + this.handleMoveToPoint(aMessage); + break; + case 'AccessFu:AutoMove': + this.handleAutoMove(aMessage); + break; + default: + break; + } + } catch (x) { + Logger.logException( + x, 'Error handling message: ' + JSON.stringify(aMessage.json)); + } + }, + + handleMove: function ContentControl_handleMove(aMessage) { + let origin = aMessage.json.origin; + let action = aMessage.json.action; + let vc = this.vc; + + if (origin != 'child' && this.sendToChild(vc, aMessage)) { + // Forwarded succesfully to child cursor. + return; + } + + let moved = vc[action](TraversalRules[aMessage.json.rule]); + + if (moved) { + if (origin === 'child') { + // We just stepped out of a child, clear child cursor. + Utils.getMessageManager(aMessage.target).sendAsyncMessage( + 'AccessFu:ClearCursor', {}); + } else { + // We potentially landed on a new child cursor. If so, we want to + // either be on the first or last item in the child doc. + let childAction = action; + if (action === 'moveNext') { + childAction = 'moveFirst'; + } else if (action === 'movePrevious') { + childAction = 'moveLast'; + } + + // Attempt to forward move to a potential child cursor in our + // new position. + this.sendToChild(vc, aMessage, { action: childAction}); + } + } else if (!this._childMessageSenders.has(aMessage.target)) { + // We failed to move, and the message is not from a child, so forward + // to parent. + this.sendToParent(aMessage); + } + }, + + handleMoveToPoint: function ContentControl_handleMoveToPoint(aMessage) { + let [x, y] = [aMessage.json.x, aMessage.json.y]; + let rule = TraversalRules[aMessage.json.rule]; + let vc = this.vc; + let win = this.window; + + let dpr = win.devicePixelRatio; + this.vc.moveToPoint(rule, x * dpr, y * dpr, true); + + let delta = Utils.isContentProcess ? + { x: x - win.mozInnerScreenX, y: y - win.mozInnerScreenY } : {}; + this.sendToChild(vc, aMessage, delta); + }, + + handleClear: function ContentControl_handleClear(aMessage) { + this.sendToChild(this.vc, aMessage); + this.vc.position = null; + }, + + handleAutoMove: function ContentControl_handleAutoMove(aMessage) { + this.autoMove(null, aMessage.json); + }, + + getChildCursor: function ContentControl_getChildCursor(aAccessible) { + let acc = aAccessible || this.vc.position; + if (Utils.isAliveAndVisible(acc) && acc.role === Roles.INTERNAL_FRAME) { + let domNode = acc.DOMNode; + let mm = this._childMessageSenders.get(domNode, null); + if (!mm) { + mm = Utils.getMessageManager(domNode); + mm.addWeakMessageListener('AccessFu:MoveCursor', this); + this._childMessageSenders.set(domNode, mm); + } + + return mm; + } + + return null; + }, + + sendToChild: function ContentControl_sendToChild(aVirtualCursor, + aMessage, + aReplacer) { + let mm = this.getChildCursor(aVirtualCursor.position); + if (!mm) { + return false; + } + + // XXX: This is a silly way to make a deep copy + let newJSON = JSON.parse(JSON.stringify(aMessage.json)); + newJSON.origin = 'parent'; + for (let attr in aReplacer) { + newJSON[attr] = aReplacer[attr]; + } + + mm.sendAsyncMessage(aMessage.name, newJSON); + return true; + }, + + sendToParent: function ContentControl_sendToParent(aMessage) { + // XXX: This is a silly way to make a deep copy + let newJSON = JSON.parse(JSON.stringify(aMessage.json)); + newJSON.origin = 'child'; + aMessage.target.sendAsyncMessage(aMessage.name, newJSON); + }, + + /** + * Move cursor and/or present its location. + * aOptions could have any of these fields: + * - delay: in ms, before actual move is performed. Another autoMove call + * would cancel it. Useful if we want to wait for a possible trailing + * focus move. Default 0. + * - noOpIfOnScreen: if accessible is alive and visible, don't do anything. + * - forcePresent: present cursor location, whether we move or don't. + * - moveToFocused: if there is a focused accessible move to that. This takes + * precedence over given anchor. + * - moveMethod: pivot move method to use, default is 'moveNext', + */ + autoMove: function ContentControl_autoMove(aAnchor, aOptions = {}) { + let win = this.window; + win.clearTimeout(this._autoMove); + + let moveFunc = () => { + let vc = this.vc; + let acc = aAnchor; + let rule = aOptions.onScreenOnly ? + TraversalRules.SimpleOnScreen : TraversalRules.Simple; + let forcePresentFunc = () => { + if (aOptions.forcePresent) { + this._contentScope.get().sendAsyncMessage( + 'AccessFu:Present', Presentation.pivotChanged( + vc.position, null, Ci.nsIAccessiblePivot.REASON_NONE, + vc.startOffset, vc.endOffset)); + } + }; + + if (aOptions.noOpIfOnScreen && + Utils.isAliveAndVisible(vc.position, true)) { + forcePresentFunc(); + return; + } + + if (aOptions.moveToFocused) { + acc = Utils.AccRetrieval.getAccessibleFor( + this.document.activeElement) || acc; + } + + let moved = false; + let moveMethod = aOptions.moveMethod || 'moveNext'; // default is moveNext + let moveFirstOrLast = moveMethod in ['moveFirst', 'moveLast']; + if (!moveFirstOrLast || acc) { + // We either need next/previous or there is an anchor we need to use. + moved = vc[moveFirstOrLast ? 'moveNext' : moveMethod](rule, acc, true); + } + if (moveFirstOrLast && !moved) { + // We move to first/last after no anchor move happened or succeeded. + moved = vc[moveMethod](rule); + } + + let sentToChild = this.sendToChild(vc, { + name: 'AccessFu:AutoMove', + json: aOptions + }); + + if (!moved && !sentToChild) { + forcePresentFunc(); + } + }; + + if (aOptions.delay) { + this._autoMove = win.setTimeout(moveFunc, aOptions.delay); + } else { + moveFunc(); + } + }, + + QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference, + Ci.nsIMessageListener + ]) +}; \ No newline at end of file diff --git a/accessible/src/jsat/EventManager.jsm b/accessible/src/jsat/EventManager.jsm index 9aa035925d6..15ede982712 100644 --- a/accessible/src/jsat/EventManager.jsm +++ b/accessible/src/jsat/EventManager.jsm @@ -98,18 +98,11 @@ this.EventManager.prototype = { case 'wheel': { let attempts = 0; - let vc = Utils.getVirtualCursor(this.contentScope.content.document); - let intervalId = this.contentScope.content.setInterval(() => { - if (!Utils.isAliveAndVisible(vc.position, true)) { - this.contentScope.content.clearInterval(intervalId); - let delta = aEvent.deltaX || aEvent.deltaY; - this.contentScope.content.setTimeout(() => { - vc[delta > 0 ? 'moveNext' : 'movePrevious'](TraversalRules.SimpleOnScreen); - }, 100); - } else if (++attempts > 5) { - this.contentScope.content.clearInterval(intervalId); - } - }, 150); + let delta = aEvent.deltaX || aEvent.deltaY; + this.contentScope.contentControl.autoMove( + null, + { moveMethod: delta > 0 ? 'moveNext' : 'movePrevious', + onScreenOnly: true, noOpIfOnScreen: true, delay: 500 }); break; } case 'scroll': @@ -162,11 +155,6 @@ this.EventManager.prototype = { let reason = event.reason; let oldAccessible = event.oldAccessible; - if (oldAccessible && oldAccessible.role == Roles.INTERNAL_FRAME) { - let mm = Utils.getMessageManager(oldAccessible.DOMNode); - mm.sendAsyncMessage('AccessFu:ClearCursor', {}); - } - if (this.editState.editing) { aEvent.accessibleDocument.takeFocus(); } @@ -195,8 +183,7 @@ this.EventManager.prototype = { } case Events.SCROLLING_START: { - let vc = Utils.getVirtualCursor(this.contentScope.content.document); - vc.moveNext(TraversalRules.Simple, aEvent.accessible, true); + this.contentScope.contentControl.autoMove(aEvent.accessible); break; } case Events.TEXT_CARET_MOVED: @@ -253,18 +240,25 @@ this.EventManager.prototype = { } case Events.HIDE: { + let evt = aEvent.QueryInterface(Ci.nsIAccessibleHideEvent); let {liveRegion, isPolite} = this._handleLiveRegion( - aEvent.QueryInterface(Ci.nsIAccessibleHideEvent), - ['removals', 'all']); - // Only handle hide if it is a relevant live region. - if (!liveRegion) { - break; + evt, ['removals', 'all']); + if (liveRegion) { + // Hide for text is handled by the EVENT_TEXT_REMOVED handler. + if (aEvent.accessible.role === Roles.TEXT_LEAF) { + break; + } + this._queueLiveEvent(Events.HIDE, liveRegion, isPolite); + } else { + let vc = Utils.getVirtualCursor(this.contentScope.content.document); + if (vc.position && + (Utils.getState(vc.position).contains(States.DEFUNCT) || + Utils.isInSubtree(vc.position, aEvent.accessible))) { + this.contentScope.contentControl.autoMove( + evt.targetPrevSibling || evt.targetParent, + { moveToFocused: true, delay: 500 }); + } } - // Hide for text is handled by the EVENT_TEXT_REMOVED handler. - if (aEvent.accessible.role === Roles.TEXT_LEAF) { - break; - } - this._queueLiveEvent(Events.HIDE, liveRegion, isPolite); break; } case Events.TEXT_INSERTED: @@ -285,18 +279,14 @@ this.EventManager.prototype = { let acc = aEvent.accessible; let doc = aEvent.accessibleDocument; if (acc.role != Roles.DOCUMENT && doc.role != Roles.CHROME_WINDOW) { - this.contentScope.content.clearTimeout(this._autoMove); - let vc = Utils.getVirtualCursor(this.contentScope.content.document); - vc.moveNext(TraversalRules.Simple, acc, true); - } - break; + this.contentScope.contentControl.autoMove(acc); + } + break; } case Events.DOCUMENT_LOAD_COMPLETE: { - this._autoMove = this.contentScope.content.setTimeout(() => { - Utils.getVirtualCursor(this.contentScope.content.document) - .moveNext(TraversalRules.Simple, aEvent.accessible, true); - }, 500); + this.contentScope.contentControl.autoMove( + aEvent.accessible, { delay: 500 }); break; } } diff --git a/accessible/src/jsat/Utils.jsm b/accessible/src/jsat/Utils.jsm index 5d61708c5f2..03b8e8be48b 100644 --- a/accessible/src/jsat/Utils.jsm +++ b/accessible/src/jsat/Utils.jsm @@ -247,6 +247,24 @@ this.Utils = { return new Rect(objX.value, objY.value, objW.value, objH.value); }, + isInSubtree: function isInSubtree(aAccessible, aSubTreeRoot) { + let acc = aAccessible; + while (acc) { + if (acc == aSubTreeRoot) { + return true; + } + + try { + acc = acc.parent; + } catch (x) { + Logger.debug('Failed to get parent:', x); + acc = null; + } + } + + return false; + }, + inHiddenSubtree: function inHiddenSubtree(aAccessible) { for (let acc=aAccessible; acc; acc=acc.parent) { let hidden = Utils.getAttributes(acc).hidden; @@ -565,8 +583,13 @@ PivotContext.prototype = { _getAncestry: function _getAncestry(aAccessible) { let ancestry = []; let parent = aAccessible; - while (parent && (parent = parent.parent)) { - ancestry.push(parent); + try { + while (parent && (parent = parent.parent)) { + ancestry.push(parent); + } + } catch (e) { + // A defunct accessible will raise an exception geting parent. + Logger.debug('Failed to get parent:', x); } return ancestry.reverse(); }, diff --git a/accessible/src/jsat/content-script.js b/accessible/src/jsat/content-script.js index c3d5fc82978..7ba86e201b4 100644 --- a/accessible/src/jsat/content-script.js +++ b/accessible/src/jsat/content-script.js @@ -20,118 +20,15 @@ XPCOMUtils.defineLazyModuleGetter(this, 'Utils', 'resource://gre/modules/accessibility/Utils.jsm'); XPCOMUtils.defineLazyModuleGetter(this, 'EventManager', 'resource://gre/modules/accessibility/EventManager.jsm'); +XPCOMUtils.defineLazyModuleGetter(this, 'ContentControl', + 'resource://gre/modules/accessibility/ContentControl.jsm'); XPCOMUtils.defineLazyModuleGetter(this, 'Roles', 'resource://gre/modules/accessibility/Constants.jsm'); Logger.debug('content-script.js'); let eventManager = null; - -function clearCursor(aMessage) { - try { - Utils.getVirtualCursor(content.document).position = null; - forwardToChild(aMessage); - } catch (x) { - Logger.logException(x); - } -} - -function moveCursor(aMessage) { - if (Logger.logLevel >= Logger.DEBUG) { - Logger.debug(aMessage.name, JSON.stringify(aMessage.json, null, ' ')); - } - - let vc = Utils.getVirtualCursor(content.document); - let origin = aMessage.json.origin; - let action = aMessage.json.action; - let rule = TraversalRules[aMessage.json.rule]; - - function moveCursorInner() { - try { - if (origin == 'parent' && - !Utils.isAliveAndVisible(vc.position)) { - // We have a bad position in this frame, move vc to last or first item. - if (action == 'moveNext') { - return vc.moveFirst(rule); - } else if (action == 'movePrevious') { - return vc.moveLast(rule); - } - } - - return vc[action](rule); - } catch (x) { - if (action == 'moveNext' || action == 'movePrevious') { - // If we are trying to move next/prev put the vc on the focused item. - let acc = Utils.AccRetrieval. - getAccessibleFor(content.document.activeElement); - return vc.moveNext(rule, acc, true); - } else { - throw x; - } - } - - return false; - } - - try { - if (origin != 'child' && - forwardToChild(aMessage, moveCursor, vc.position)) { - // We successfully forwarded the move to the child document. - return; - } - - if (moveCursorInner()) { - // If we moved, try forwarding the message to the new position, - // it may be a frame with a vc of its own. - forwardToChild(aMessage, moveCursor, vc.position); - } else { - // If we did not move, we probably reached the end or start of the - // document, go back to parent content and move us out of the iframe. - if (origin == 'parent') { - vc.position = null; - } - forwardToParent(aMessage); - } - } catch (x) { - Logger.logException(x, 'Cursor move failed'); - } -} - -function moveToPoint(aMessage) { - if (Logger.logLevel >= Logger.DEBUG) { - Logger.debug(aMessage.name, JSON.stringify(aMessage.json, null, ' ')); - } - - let vc = Utils.getVirtualCursor(content.document); - let details = aMessage.json; - let rule = TraversalRules[details.rule]; - - try { - let dpr = content.devicePixelRatio; - vc.moveToPoint(rule, details.x * dpr, details.y * dpr, true); - forwardToChild(aMessage, moveToPoint, vc.position); - } catch (x) { - Logger.logException(x, 'Failed move to point'); - } -} - -function showCurrent(aMessage) { - Logger.debug(() => { - return [aMessage.name, JSON.stringify(aMessage.json, null, ' ')]; - }); - - let vc = Utils.getVirtualCursor(content.document); - - if (!forwardToChild(vc, showCurrent, aMessage)) { - if (!vc.position && aMessage.json.move) { - vc.moveFirst(TraversalRules.Simple); - } else { - sendAsyncMessage('AccessFu:Present', Presentation.pivotChanged( - vc.position, null, Ci.nsIAccessiblePivot.REASON_NONE, - vc.startOffset, vc.endOffset)); - } - } -} +let contentControl = null; function forwardToParent(aMessage) { // XXX: This is a silly way to make a deep copy @@ -385,22 +282,23 @@ addMessageListener( if (m.json.buildApp) Utils.MozBuildApp = m.json.buildApp; - addMessageListener('AccessFu:MoveToPoint', moveToPoint); - addMessageListener('AccessFu:MoveCursor', moveCursor); - addMessageListener('AccessFu:ShowCurrent', showCurrent); addMessageListener('AccessFu:Activate', activateCurrent); addMessageListener('AccessFu:ContextMenu', activateContextMenu); addMessageListener('AccessFu:Scroll', scroll); addMessageListener('AccessFu:AdjustRange', adjustRange); addMessageListener('AccessFu:MoveCaret', moveCaret); addMessageListener('AccessFu:MoveByGranularity', moveByGranularity); - addMessageListener('AccessFu:ClearCursor', clearCursor); if (!eventManager) { eventManager = new EventManager(this); } eventManager.start(); + if (!contentControl) { + contentControl = new ContentControl(this); + } + contentControl.start(); + sendAsyncMessage('AccessFu:ContentStarted'); }); @@ -409,17 +307,14 @@ addMessageListener( function(m) { Logger.debug('AccessFu:Stop'); - removeMessageListener('AccessFu:MoveToPoint', moveToPoint); - removeMessageListener('AccessFu:MoveCursor', moveCursor); - removeMessageListener('AccessFu:ShowCurrent', showCurrent); removeMessageListener('AccessFu:Activate', activateCurrent); removeMessageListener('AccessFu:ContextMenu', activateContextMenu); removeMessageListener('AccessFu:Scroll', scroll); removeMessageListener('AccessFu:MoveCaret', moveCaret); removeMessageListener('AccessFu:MoveByGranularity', moveByGranularity); - removeMessageListener('AccessFu:ClearCursor', clearCursor); eventManager.stop(); + contentControl.stop(); }); sendAsyncMessage('AccessFu:Ready'); diff --git a/accessible/src/jsat/moz.build b/accessible/src/jsat/moz.build index 970ecc6de30..987c5687600 100644 --- a/accessible/src/jsat/moz.build +++ b/accessible/src/jsat/moz.build @@ -9,6 +9,7 @@ JS_MODULES_PATH = 'modules/accessibility' EXTRA_JS_MODULES += [ 'AccessFu.jsm', 'Constants.jsm', + 'ContentControl.jsm', 'EventManager.jsm', 'OutputGenerator.jsm', 'Presentation.jsm', diff --git a/accessible/tests/mochitest/jsat/doc_content_integration.html b/accessible/tests/mochitest/jsat/doc_content_integration.html index 8f60db9d8ba..81d55c3c835 100644 --- a/accessible/tests/mochitest/jsat/doc_content_integration.html +++ b/accessible/tests/mochitest/jsat/doc_content_integration.html @@ -12,18 +12,56 @@ '' + ''; + function showAlert() { + document.getElementById('alert').hidden = false; + } + + function hideAlert() { + document.getElementById('alert').hidden = true; + } +
Phone status bar
-
- +
+
+ +
+ diff --git a/accessible/tests/mochitest/jsat/jsatcommon.js b/accessible/tests/mochitest/jsat/jsatcommon.js index 639df5e8b22..7d3aaceb6a6 100644 --- a/accessible/tests/mochitest/jsat/jsatcommon.js +++ b/accessible/tests/mochitest/jsat/jsatcommon.js @@ -216,13 +216,17 @@ AccessFuContentTest.prototype = { if (this.currentPair) { if (this.currentPair[0] instanceof Function) { this.currentPair[0](this.mms[0]); - } else { + } else if (this.currentPair[0]) { this.mms[0].sendAsyncMessage(this.currentPair[0].name, - this.currentPair[0].json); + this.currentPair[0].json); } + + if (!this.currentPair[1]) { + this.pump(); + } } else if (this.finishedCallback) { for (var mm of this.mms) { - mm.sendAsyncMessage('AccessFu:Stop'); + mm.sendAsyncMessage('AccessFu:Stop'); } this.finishedCallback(); } diff --git a/accessible/tests/mochitest/jsat/test_content_integration.html b/accessible/tests/mochitest/jsat/test_content_integration.html index c6e2347bfb8..184cbc27428 100644 --- a/accessible/tests/mochitest/jsat/test_content_integration.html +++ b/accessible/tests/mochitest/jsat/test_content_integration.html @@ -125,10 +125,10 @@ // Move cursor with focus in outside document [simpleMoveNext, { speak: 'Phone status bar Traversal Rule test document' }], - [ focusFunc('button', false), { speak: 'Home button' }], + [ focusFunc('button#home', false), { speak: 'Home button' }], // Blur button and reset cursor - [focusFunc('button', true), null], + [focusFunc('button#home', true), null], [clearCursor, null], // Set focus on element outside of embedded frame while cursor is in frame @@ -136,12 +136,53 @@ { speak: 'Phone status bar Traversal Rule test document' }], [simpleMoveNext, { speak: 'wow heading level 1 such app' }], - [focusFunc('button', false), { speak: 'Home button' }] + [focusFunc('button#home', false), { speak: 'Home button' }] + + // Blur button and reset cursor + [focusFunc('button#home', true), null], + [clearCursor, null], // XXX: Set focus on iframe itself. // XXX: Set focus on element in iframe when cursor is outside of it. // XXX: Set focus on element in iframe when cursor is in iframe. - ]); + + // Open dialog in outer doc, while cursor is also in outer doc + [simpleMoveNext, + { speak: 'Phone status bar Traversal Rule test document' }], + [doc.defaultView.showAlert, + { speak: 'This is an alert! heading level 1 dialog' }], + + [function () { doc.defaultView.hideAlert() }, + { speak: 'wow heading level 1 such app' }], + + [clearCursor, null], + + // Open dialog in outer doc, while cursor is in inner frame + [simpleMoveNext, + { speak: 'Phone status bar Traversal Rule test document' }], + [simpleMoveNext, + { speak: 'wow heading level 1 such app' }], + [doc.defaultView.showAlert, + { speak: 'This is an alert! heading level 1 dialog' }], + + // XXX: Place cursor back where it was. + [doc.defaultView.hideAlert, + { speak: 'many option not checked check button such app' }], + + [clearCursor, null], + + // Open dialog, then focus on something when closing + [simpleMoveNext, + { speak: 'Phone status bar Traversal Rule test document' }], + [doc.defaultView.showAlert, + { speak: 'This is an alert! heading level 1 dialog' }], + + [function () { + doc.defaultView.hideAlert(); + doc.querySelector('button#home').focus(); + }, + { speak: 'Home button Traversal Rule test document' }] + ]); contentTest.start(function () { closeBrowserWindow(); @@ -150,7 +191,7 @@ }); iframe.src = 'data:text/html;charset=utf-8,' + doc.defaultView.frameContents; - doc.querySelector('#windows').appendChild(iframe); + doc.getElementById('appframe').appendChild(iframe); } SimpleTest.waitForExplicitFinish(); diff --git a/b2g/app/Makefile.in b/b2g/app/Makefile.in index e5c1683bc87..bf5568895bd 100644 --- a/b2g/app/Makefile.in +++ b/b2g/app/Makefile.in @@ -28,8 +28,6 @@ LIBS += \ endif endif -STL_FLAGS= - LIBS += $(JEMALLOC_LIBS) LIBS += \ diff --git a/b2g/app/moz.build b/b2g/app/moz.build index 37fa6189b5f..58c21fc4b22 100644 --- a/b2g/app/moz.build +++ b/b2g/app/moz.build @@ -41,3 +41,5 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': ] LDFLAGS += ['-Wl,--export-dynamic'] + +DISABLE_STL_WRAPPING = True diff --git a/browser/app/Makefile.in b/browser/app/Makefile.in index ad0ecbab38c..f69dc7f3587 100644 --- a/browser/app/Makefile.in +++ b/browser/app/Makefile.in @@ -26,8 +26,6 @@ endif #} LIBXUL_SDK # Build a binary bootstrapping with XRE_main -STL_FLAGS= - LIBS += \ $(XPCOM_STANDALONE_GLUE_LDOPTS) \ $(NULL) @@ -55,7 +53,6 @@ NSDISTMODE = copy include $(topsrcdir)/config/config.mk ifeq ($(OS_ARCH),WINNT) -RCINCLUDE = splash.rc # Rebuild firefox.exe if the manifest changes - it's included by splash.rc. # (this dependency should really be just for firefox.exe, not other targets) # Note the manifest file exists in the tree, so we use the explicit filename diff --git a/browser/app/moz.build b/browser/app/moz.build index 07fed1c0380..e8ff06ba896 100644 --- a/browser/app/moz.build +++ b/browser/app/moz.build @@ -39,6 +39,7 @@ if CONFIG['_MSC_VER']: WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup'] if CONFIG['OS_ARCH'] == 'WINNT': + RCINCLUDE = 'splash.rc' DEFINES['MOZ_PHOENIX'] = True # Control the default heap size. @@ -51,3 +52,5 @@ if CONFIG['OS_ARCH'] == 'WINNT': # Set it to 256k. See bug 127069. if CONFIG['OS_ARCH'] == 'WINNT' and not CONFIG['GNU_CC']: LDFLAGS += ['/HEAP:0x40000'] + +DISABLE_STL_WRAPPING = True diff --git a/browser/base/content/test/general/browser_get_user_media.js b/browser/base/content/test/general/browser_get_user_media.js index 334167b70d3..7a7e2cbca7b 100644 --- a/browser/base/content/test/general/browser_get_user_media.js +++ b/browser/base/content/test/general/browser_get_user_media.js @@ -81,17 +81,31 @@ function promiseMessage(aMessage, aAction) { function promisePopupNotification(aName, aShown) { let deferred = Promise.defer(); - // If aShown is true, the notification is expected to be opened by - // default and we wait for the panel to be populated; for dismissed - // notifications, we are happy as soon as we find the icon. - waitForCondition(() => PopupNotifications.getNotification(aName) && - (!aShown || PopupNotifications.panel.firstChild), + waitForCondition(() => PopupNotifications.getNotification(aName), () => { - ok(!!PopupNotifications.getNotification(aName), - aName + " notification appeared"); - if (aShown) - ok(PopupNotifications.panel.firstChild, "notification panel populated"); - deferred.resolve(); + let notification = PopupNotifications.getNotification(aName); + ok(!!notification, aName + " notification appeared"); + + if (!notification || !aShown) { + deferred.resolve(); + return; + } + + // If aShown is true, the notification is expected to be opened by + // default, so we check that the panel has been populated. + if (PopupNotifications.panel.firstChild) { + ok(true, "notification panel populated"); + deferred.resolve(); + } + else { + todo(false, "We shouldn't have to force re-open the panel, see bug 976544"); + notification.reshow(); + waitForCondition(() => PopupNotifications.panel.firstChild, + () => { + ok(PopupNotifications.panel.firstChild, "notification panel populated"); + deferred.resolve(); + }, "timeout waiting for notification to be reshown"); + } }, "timeout waiting for popup notification " + aName); return deferred.promise; diff --git a/browser/components/customizableui/content/panelUI.js b/browser/components/customizableui/content/panelUI.js index 3902a34c586..935c740ab58 100644 --- a/browser/components/customizableui/content/panelUI.js +++ b/browser/components/customizableui/content/panelUI.js @@ -154,6 +154,10 @@ const PanelUI = { this.panel.addEventListener("popupshown", function onPopupShown() { this.removeEventListener("popupshown", onPopupShown); + // As an optimization for the customize mode transition, we preload + // about:customizing in the background once the menu panel is first + // shown. + gCustomizationTabPreloader.ensurePreloading(); deferred.resolve(); }); }); diff --git a/browser/components/customizableui/src/CustomizableWidgets.jsm b/browser/components/customizableui/src/CustomizableWidgets.jsm index 0ae0cc6af01..9a35add5a92 100644 --- a/browser/components/customizableui/src/CustomizableWidgets.jsm +++ b/browser/components/customizableui/src/CustomizableWidgets.jsm @@ -416,6 +416,11 @@ const CustomizableWidgets = [{ let zoomResetButton = node.childNodes[2]; let window = aDocument.defaultView; function updateZoomResetButton() { + let updateDisplay = true; + // Label should always show 100% in customize mode, so don't update: + if (aDocument.documentElement.hasAttribute("customizing")) { + updateDisplay = false; + } //XXXgijs in some tests we get called very early, and there's no docShell on the // tabbrowser. This breaks the zoom toolkit code (see bug 897410). Don't let that happen: let zoomFactor = 100; @@ -423,7 +428,7 @@ const CustomizableWidgets = [{ zoomFactor = Math.floor(window.ZoomManager.zoom * 100); } catch (e) {} zoomResetButton.setAttribute("label", CustomizableUI.getLocalizedProperty( - buttons[1], "label", [zoomFactor] + buttons[1], "label", [updateDisplay ? zoomFactor : 100] )); }; @@ -508,6 +513,18 @@ const CustomizableWidgets = [{ container.removeEventListener("TabSelect", updateZoomResetButton); }.bind(this), + onCustomizeStart: function(aWindow) { + if (aWindow.document == aDocument) { + updateZoomResetButton(); + } + }, + + onCustomizeEnd: function(aWindow) { + if (aWindow.document == aDocument) { + updateZoomResetButton(); + } + }, + onWidgetDrag: function(aWidgetId, aArea) { if (aWidgetId != this.id) return; diff --git a/browser/components/customizableui/src/CustomizeMode.jsm b/browser/components/customizableui/src/CustomizeMode.jsm index f728543469c..8b5a1079277 100644 --- a/browser/components/customizableui/src/CustomizeMode.jsm +++ b/browser/components/customizableui/src/CustomizeMode.jsm @@ -195,6 +195,7 @@ CustomizeMode.prototype = { // Hide the palette before starting the transition for increased perf. this.visiblePalette.hidden = true; + this.visiblePalette.removeAttribute("showing"); // Disable the button-text fade-out mask // during the transition for increased perf. @@ -262,6 +263,12 @@ CustomizeMode.prototype = { // Show the palette now that the transition has finished. this.visiblePalette.hidden = false; + window.setTimeout(() => { + // Force layout reflow to ensure the animation runs, + // and make it async so it doesn't affect the timing. + this.visiblePalette.clientTop; + this.visiblePalette.setAttribute("showing", "true"); + }, 0); this.paletteSpacer.hidden = true; this._updateEmptyPaletteNotice(); @@ -269,6 +276,16 @@ CustomizeMode.prototype = { panelContents.removeAttribute("customize-transitioning"); CustomizableUI.dispatchToolboxEvent("customizationready", {}, window); + this._enableOutlinesTimeout = window.setTimeout(() => { + this.document.getElementById("nav-bar").setAttribute("showoutline", "true"); + this.panelUIContents.setAttribute("showoutline", "true"); + delete this._enableOutlinesTimeout; + }, 0); + + // It's possible that we didn't enter customize mode via the menu panel, + // meaning we didn't kick off about:customizing preloading. If that's + // the case, let's kick it off for the next time we load this mode. + window.gCustomizationTabPreloader.ensurePreloading(); if (!this._wantToBeInCustomizeMode) { this.exit(); } @@ -302,6 +319,13 @@ CustomizeMode.prototype = { this._handler.isExitingCustomizeMode = true; + if (this._enableOutlinesTimeout) { + this.window.clearTimeout(this._enableOutlinesTimeout); + } else { + this.document.getElementById("nav-bar").removeAttribute("showoutline"); + this.panelUIContents.removeAttribute("showoutline"); + } + this._removeExtraToolbarsIfEmpty(); CustomizableUI.removeListener(this); @@ -321,6 +345,7 @@ CustomizeMode.prototype = { // Hide the palette before starting the transition for increased perf. this.paletteSpacer.hidden = false; this.visiblePalette.hidden = true; + this.visiblePalette.removeAttribute("showing"); this.paletteEmptyNotice.hidden = true; // Disable the button-text fade-out mask @@ -340,10 +365,34 @@ CustomizeMode.prototype = { yield this._doTransition(false); + let browser = document.getElementById("browser"); + if (this.browser.selectedBrowser.currentURI.spec == kAboutURI) { + let custBrowser = this.browser.selectedBrowser; + if (custBrowser.canGoBack) { + // If there's history to this tab, just go back. + // Note that this throws an exception if the previous document has a + // problematic URL (e.g. about:idontexist) + try { + custBrowser.goBack(); + } catch (ex) { + ERROR(ex); + } + } else { + // If we can't go back, we're removing the about:customization tab. + // We only do this if we're the top window for this window (so not + // a dialog window, for example). + if (window.getTopWin(true) == window) { + let customizationTab = this.browser.selectedTab; + if (this.browser.browsers.length == 1) { + window.BrowserOpenTab(); + } + this.browser.removeTab(customizationTab); + } + } + } + browser.parentNode.selectedPanel = browser; let customizer = document.getElementById("customization-container"); customizer.hidden = true; - let browser = document.getElementById("browser"); - browser.parentNode.selectedPanel = browser; window.gNavToolbox.removeEventListener("toolbarvisibilitychange", this); @@ -398,31 +447,6 @@ CustomizeMode.prototype = { mainView.setAttribute("context", this._mainViewContext); } - if (this.browser.selectedBrowser.currentURI.spec == kAboutURI) { - let custBrowser = this.browser.selectedBrowser; - if (custBrowser.canGoBack) { - // If there's history to this tab, just go back. - // Note that this throws an exception if the previous document has a - // problematic URL (e.g. about:idontexist) - try { - custBrowser.goBack(); - } catch (ex) { - ERROR(ex); - } - } else { - // If we can't go back, we're removing the about:customization tab. - // We only do this if we're the top window for this window (so not - // a dialog window, for example). - if (window.getTopWin(true) == window) { - let customizationTab = this.browser.selectedTab; - if (this.browser.browsers.length == 1) { - window.BrowserOpenTab(); - } - this.browser.removeTab(customizationTab); - } - } - } - if (this.document.documentElement._lightweightTheme) this.document.documentElement._lightweightTheme.enable(); diff --git a/browser/components/nsBrowserGlue.js b/browser/components/nsBrowserGlue.js index 82b2949ec0c..c299a6e7dc6 100644 --- a/browser/components/nsBrowserGlue.js +++ b/browser/components/nsBrowserGlue.js @@ -472,7 +472,6 @@ BrowserGlue.prototype = { PageThumbs.init(); NewTabUtils.init(); BrowserNewTabPreloader.init(); - CustomizationTabPreloader.init(); SignInToWebsiteUX.init(); PdfJs.init(); #ifdef NIGHTLY_BUILD diff --git a/browser/components/places/content/controller.js b/browser/components/places/content/controller.js index 262fe8b105a..9f31db66faa 100644 --- a/browser/components/places/content/controller.js +++ b/browser/components/places/content/controller.js @@ -291,8 +291,8 @@ PlacesController.prototype = { * @param aIsMoveCommand * True if the command for which this method is called only moves the * selected items to another container, false otherwise. - * @returns true if all nodes in the selection can be removed, - * false otherwise. + * @return true if all nodes in the selection can be removed, + * false otherwise. */ _hasRemovableSelection: function PC__hasRemovableSelection(aIsMoveCommand) { var ranges = this._view.removableSelectionRanges; @@ -356,9 +356,9 @@ PlacesController.prototype = { * Looks at the data on the clipboard to see if it is paste-able. * Paste-able data is: * - in a format that the view can receive - * @returns true if: - clipboard data is of a TYPE_X_MOZ_PLACE_* flavor, - - clipboard data is of type TEXT_UNICODE and - is a valid URI. + * @return true if: - clipboard data is of a TYPE_X_MOZ_PLACE_* flavor, + * - clipboard data is of type TEXT_UNICODE and + * is a valid URI. */ _isClipboardDataPasteable: function PC__isClipboardDataPasteable() { // if the clipboard contains TYPE_X_MOZ_PLACE_* data, it is definitely @@ -413,10 +413,10 @@ PlacesController.prototype = { * "separator" node is a separator line * "host" node is a host * - * @returns an array of objects corresponding the selected nodes. Each - * object has each of the properties above set if its corresponding - * node matches the rule. In addition, the annotations names for each - * node are set on its corresponding object as properties. + * @return an array of objects corresponding the selected nodes. Each + * object has each of the properties above set if its corresponding + * node matches the rule. In addition, the annotations names for each + * node are set on its corresponding object as properties. * Notes: * 1) This can be slow, so don't call it anywhere performance critical! * 2) A single-object array corresponding the root node is returned if @@ -503,8 +503,8 @@ PlacesController.prototype = { * the context menu item * @param aMetaData * meta data about the selection - * @returns true if the conditions (see buildContextMenu) are satisfied - * and the item can be displayed, false otherwise. + * @return true if the conditions (see buildContextMenu) are satisfied + * and the item can be displayed, false otherwise. */ _shouldShowMenuItem: function PC__shouldShowMenuItem(aMenuItem, aMetaData) { var selectiontype = aMenuItem.getAttribute("selectiontype"); @@ -782,7 +782,7 @@ PlacesController.prototype = { * Node to check for containment. * @param pastFolders * List of folders the calling function has already traversed - * @returns true if the node should be skipped, false otherwise. + * @return true if the node should be skipped, false otherwise. */ _shouldSkipNode: function PC_shouldSkipNode(node, pastFolders) { /** @@ -791,7 +791,7 @@ PlacesController.prototype = { * The node to check for containment for * @param parent * The parent container to check for containment in - * @returns true if node is a member of parent's children, false otherwise. + * @return true if node is a member of parent's children, false otherwise. */ function isContainedBy(node, parent) { var cursor = node.parent; @@ -1008,7 +1008,6 @@ PlacesController.prototype = { */ setDataTransfer: function PC_setDataTransfer(aEvent) { let dt = aEvent.dataTransfer; - let doCopy = ["copyLink", "copy", "link"].indexOf(dt.effectAllowed) != -1; let result = this._view.result; let didSuppressNotifications = result.suppressNotifications; @@ -1016,7 +1015,7 @@ PlacesController.prototype = { result.suppressNotifications = true; function addData(type, index, overrideURI) { - let wrapNode = PlacesUtils.wrapNode(node, type, overrideURI, doCopy); + let wrapNode = PlacesUtils.wrapNode(node, type, overrideURI); dt.mozSetDataAt(type, wrapNode, index); } @@ -1116,11 +1115,10 @@ PlacesController.prototype = { let livemarkInfo = this.getCachedLivemarkInfo(node); let overrideURI = livemarkInfo ? livemarkInfo.feedURI.spec : null; - let resolveShortcuts = !PlacesControllerDragHelper.canMoveNode(node); contents.forEach(function (content) { content.entries.push( - PlacesUtils.wrapNode(node, content.type, overrideURI, resolveShortcuts) + PlacesUtils.wrapNode(node, content.type, overrideURI) ); }); }, this); @@ -1262,6 +1260,13 @@ PlacesController.prototype = { if (ip.index != PlacesUtils.bookmarks.DEFAULT_INDEX) insertionIndex = ip.index + i; + // If this is not a copy, check for safety that we can move the source, + // otherwise report an error and fallback to a copy. + if (action != "copy" && !PlacesControllerDragHelper.canMoveUnwrappedNode(items[i])) { + Components.utils.reportError("Tried to move an unmovable Places node, " + + "reverting to a copy operation."); + action = "copy"; + } transactions.push( PlacesUIUtils.makeTransaction(items[i], type, ip.itemId, insertionIndex, action == "copy") @@ -1304,7 +1309,7 @@ PlacesController.prototype = { * @param aNode * a places result node. * @return true if there's a cached mozILivemarkInfo object for - * aNode, false otherwise. + * aNode, false otherwise. */ hasCachedLivemarkInfo: function PC_hasCachedLivemarkInfo(aNode) this._cachedLivemarkInfoObjects.has(aNode), @@ -1338,8 +1343,8 @@ let PlacesControllerDragHelper = { * mouse is dragging over one of its submenus * @param node * The container node - * @returns true if the user is dragging over a node within the hierarchy of - * the container, false otherwise. + * @return true if the user is dragging over a node within the hierarchy of + * the container, false otherwise. */ draggingOverChildNode: function PCDH_draggingOverChildNode(node) { let currentNode = this.currentDropTarget; @@ -1352,7 +1357,7 @@ let PlacesControllerDragHelper = { }, /** - * @returns The current active drag session. Returns null if there is none. + * @return The current active drag session. Returns null if there is none. */ getSession: function PCDH__getSession() { return this.dragService.getCurrentSession(); @@ -1438,13 +1443,28 @@ let PlacesControllerDragHelper = { return true; }, + /** + * Determines if an unwrapped node can be moved. + * + * @param aUnwrappedNode + * A node unwrapped by PlacesUtils.unwrapNodes(). + * @return True if the node can be moved, false otherwise. + */ + canMoveUnwrappedNode: function (aUnwrappedNode) { + return aUnwrappedNode.id > 0 && + !PlacesUtils.isRootItem(aUnwrappedNode.id) && + aUnwrappedNode.parent != PlacesUtils.placesRootId && + aUnwrappedNode.parent != PlacesUtils.tagsFolderId && + aUnwrappedNode.grandParentId != PlacesUtils.tagsFolderId && + !aUnwrappedNode.parentReadOnly; + }, /** * Determines if a node can be moved. * * @param aNode * A nsINavHistoryResultNode node. - * @returns True if the node can be moved, false otherwise. + * @return True if the node can be moved, false otherwise. */ canMoveNode: function PCDH_canMoveNode(aNode) { @@ -1478,7 +1498,7 @@ let PlacesControllerDragHelper = { * A bookmark folder id. * @param [optional] aParentId * The parent id of the folder. - * @returns True if the container can be moved to the target. + * @return True if the container can be moved to the target. */ canMoveContainer: function PCDH_canMoveContainer(aId, aParentId) { @@ -1555,6 +1575,13 @@ let PlacesControllerDragHelper = { transactions.push(tagTxn); } else { + // If this is not a copy, check for safety that we can move the source, + // otherwise report an error and fallback to a copy. + if (!doCopy && !PlacesControllerDragHelper.canMoveUnwrappedNode(unwrapped)) { + Components.utils.reportError("Tried to move an unmovable Places node, " + + "reverting to a copy operation."); + doCopy = true; + } transactions.push(PlacesUIUtils.makeTransaction(unwrapped, flavor, insertionPoint.itemId, index, doCopy)); diff --git a/browser/components/places/content/editBookmarkOverlay.js b/browser/components/places/content/editBookmarkOverlay.js index 03f71ac5fa1..e1105df3766 100644 --- a/browser/components/places/content/editBookmarkOverlay.js +++ b/browser/components/places/content/editBookmarkOverlay.js @@ -857,6 +857,8 @@ var gEditItemOverlay = { var txn = new PlacesCreateFolderTransaction(defaultLabel, ip.itemId, ip.index); PlacesUtils.transactionManager.doTransaction(txn); this._folderTree.focus(); + this._folderTree.selectItems([ip.itemId]); + PlacesUtils.asContainer(this._folderTree.selectedNode).containerOpen = true; this._folderTree.selectItems([this._lastNewItem]); this._folderTree.startEditing(this._folderTree.view.selection.currentIndex, this._folderTree.columns.getFirstColumn()); diff --git a/browser/components/places/content/places.js b/browser/components/places/content/places.js index 704014fde33..bcfca1391ad 100644 --- a/browser/components/places/content/places.js +++ b/browser/components/places/content/places.js @@ -62,7 +62,7 @@ var PlacesOrganizer = { for (let container of hierarchy) { switch (typeof container) { case "number": - this._places.selectItems([container]); + this._places.selectItems([container], false); break; case "string": if (container.substr(0, 6) == "place:") @@ -327,7 +327,7 @@ var PlacesOrganizer = { openFlatContainer: function PO_openFlatContainerFlatContainer(aContainer) { if (aContainer.itemId != -1) - this._places.selectItems([aContainer.itemId]); + this._places.selectItems([aContainer.itemId], false); else if (PlacesUtils.nodeIsQuery(aContainer)) this._places.selectPlaceURI(aContainer.uri); }, diff --git a/browser/components/places/content/tree.xml b/browser/components/places/content/tree.xml index 94e48b5569d..6ec5420cddf 100644 --- a/browser/components/places/content/tree.xml +++ b/browser/components/places/content/tree.xml @@ -45,7 +45,7 @@ @@ -453,8 +453,6 @@ // // If the sole selection is the bookmarks toolbar folder, we insert // into it even if it is not opened - var itemId = - PlacesUtils.getConcreteItemId(resultView.nodeForTreeIndex(max.value)); if (selection.count == 1 && resultView.isContainer(max.value) && !this.flatList) orientation = Ci.nsITreeView.DROP_ON; @@ -546,13 +544,16 @@ deferred.resolve(aLibrary), aLeftPaneRoot); + } + return deferred.promise; +} + +/** + * Waits for a clipboard operation to complete, looking for the expected type. + * + * @see waitForClipboard + * + * @param aPopulateClipboardFn + * Function to populate the clipboard. + * @param aFlavor + * Data flavor to expect. + */ +function promiseClipboard(aPopulateClipboardFn, aFlavor) { + let deferred = Promise.defer(); + waitForClipboard(function (aData) !!aData, + aPopulateClipboardFn, + function () { deferred.resolve(); }, + aFlavor); + return deferred.promise; +} + /** * Waits for completion of a clear history operation, before * proceeding with aCallback. diff --git a/browser/components/places/tests/chrome/chrome.ini b/browser/components/places/tests/chrome/chrome.ini index 31cb5e7c98c..a313e5edd0c 100644 --- a/browser/components/places/tests/chrome/chrome.ini +++ b/browser/components/places/tests/chrome/chrome.ini @@ -9,4 +9,5 @@ support-files = head.js [test_bug549491.xul] [test_bug631374_tags_selector_scroll.xul] [test_editBookmarkOverlay_tags_liveUpdate.xul] +[test_selectItems_on_nested_tree.xul] [test_treeview_date.xul] diff --git a/browser/components/places/tests/chrome/test_selectItems_on_nested_tree.xul b/browser/components/places/tests/chrome/test_selectItems_on_nested_tree.xul new file mode 100644 index 00000000000..28d9598876f --- /dev/null +++ b/browser/components/places/tests/chrome/test_selectItems_on_nested_tree.xul @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + diff --git a/browser/devtools/netmonitor/test/browser_net_statistics-01.js b/browser/devtools/netmonitor/test/browser_net_statistics-01.js index 2c7da1cc8d8..f73b6a2a494 100644 --- a/browser/devtools/netmonitor/test/browser_net_statistics-01.js +++ b/browser/devtools/netmonitor/test/browser_net_statistics-01.js @@ -40,12 +40,15 @@ function test() { is($("#empty-cache-chart").childNodes.length, 1, "There should be a real empty cache chart created now."); - is($all(".pie-chart-container:not([placeholder=true])").length, 2, - "Two real pie chart appear to be rendered correctly."); - is($all(".table-chart-container:not([placeholder=true])").length, 2, - "Two real table chart appear to be rendered correctly."); + Task.spawn(function*() { + yield until(() => $all(".pie-chart-container:not([placeholder=true])").length == 2); + ok(true, "Two real pie charts appear to be rendered correctly."); - teardown(aMonitor).then(finish); + yield until(() => $all(".table-chart-container:not([placeholder=true])").length == 2); + ok(true, "Two real table charts appear to be rendered correctly.") + + teardown(aMonitor).then(finish); + }); }); }); @@ -55,3 +58,15 @@ function test() { "The current frontend mode is correct."); }); } + +function waitForTick() { + let deferred = promise.defer(); + executeSoon(deferred.resolve); + return deferred.promise; +} + +function until(predicate) { + return Task.spawn(function*() { + while (!predicate()) yield waitForTick(); + }); +} diff --git a/browser/metro/base/content/ContentAreaObserver.js b/browser/metro/base/content/ContentAreaObserver.js index d7e430f425f..9ba7b0a1597 100644 --- a/browser/metro/base/content/ContentAreaObserver.js +++ b/browser/metro/base/content/ContentAreaObserver.js @@ -117,8 +117,9 @@ var ContentAreaObserver = { let newWidth = width || this.width; let newHeight = height || this.height; - if (newHeight == oldHeight && newWidth == oldWidth) + if (newHeight == oldHeight && newWidth == oldWidth) { return; + } this.styles["window-width"].width = newWidth + "px"; this.styles["window-width"].maxWidth = newWidth + "px"; @@ -132,28 +133,15 @@ var ContentAreaObserver = { }, updateContentArea: function cao_updateContentArea (width, height) { - if (Browser.selectedBrowser) { - let notificationBox = Browser.getNotificationBox(); - - // If a notification and navbar are visible together, - // make the notification appear above the navbar. - if (ContextUI.navbarVisible && !notificationBox.notificationsHidden && - notificationBox.allNotifications.length != 0) { - let navbarHeight = Elements.navbar.getBoundingClientRect().height; - notificationBox.style.paddingBottom = navbarHeight + "px"; - } else { - notificationBox.style.paddingBottom = ""; - } - } - let oldHeight = parseInt(this.styles["content-height"].height); let oldWidth = parseInt(this.styles["content-width"].width); let newWidth = width || this.width; let newHeight = height || this.contentHeight; - if (newHeight == oldHeight && newWidth == oldWidth) + if (newHeight == oldHeight && newWidth == oldWidth) { return; + } this.styles["content-height"].height = newHeight + "px"; this.styles["content-height"].maxHeight = newHeight + "px"; @@ -171,8 +159,9 @@ var ContentAreaObserver = { let newWidth = width || this.width; let newHeight = height || this.viewableHeight; - if (newHeight == oldHeight && newWidth == oldWidth) + if (newHeight == oldHeight && newWidth == oldWidth) { return; + } this.styles["viewable-height"].height = newHeight + "px"; this.styles["viewable-height"].maxHeight = newHeight + "px"; diff --git a/browser/metro/base/content/ContextUI.js b/browser/metro/base/content/ContextUI.js index fcb4fde6f24..0c9fd9636a2 100644 --- a/browser/metro/base/content/ContextUI.js +++ b/browser/metro/base/content/ContextUI.js @@ -22,6 +22,7 @@ var ContextUI = { Elements.browsers.addEventListener('URLChanged', this, true); Elements.browsers.addEventListener("AlertActive", this, true); Elements.browsers.addEventListener("AlertClose", this, true); + Elements.tabList.addEventListener('TabSelect', this, true); Elements.panelUI.addEventListener('ToolPanelShown', this, false); Elements.panelUI.addEventListener('ToolPanelHidden', this, false); @@ -175,6 +176,7 @@ var ContextUI = { // Display the nav bar displayNavbar: function () { Elements.navbar.show(); + Elements.chromeState.setAttribute("navbar", "visible"); ContentAreaObserver.updateContentArea(); }, @@ -189,6 +191,7 @@ var ContextUI = { if (!BrowserUI.isStartTabVisible) { Elements.autocomplete.closePopup(); Elements.navbar.dismiss(); + Elements.chromeState.removeAttribute("navbar"); ContentAreaObserver.updateContentArea(); } }, @@ -365,6 +368,7 @@ var ContextUI = { break; case "AlertActive": case "AlertClose": + case "TabSelect": ContentAreaObserver.updateContentArea(); break; case "MozFlyoutPanelShowing": diff --git a/browser/metro/base/content/bindings.css b/browser/metro/base/content/bindings.css index ae410f4c65f..ced50744e1a 100644 --- a/browser/metro/base/content/bindings.css +++ b/browser/metro/base/content/bindings.css @@ -52,6 +52,9 @@ autoscroller { notificationbox { -moz-binding: url('chrome://browser/content/bindings/notification.xml#notificationbox'); } +notification { + -moz-binding: url('chrome://browser/content/bindings/notification.xml#notification'); +} circularprogressindicator { -moz-binding: url('chrome://browser/content/bindings/circularprogress.xml#circular-progress-indicator'); diff --git a/browser/metro/base/content/bindings/notification.xml b/browser/metro/base/content/bindings/notification.xml index e7f8937a43b..897d5c6243d 100644 --- a/browser/metro/base/content/bindings/notification.xml +++ b/browser/metro/base/content/bindings/notification.xml @@ -41,6 +41,46 @@ this.removeEventListener("AlertClose", this.handleEvent, true); ]]> + + + + = 0; n--) { + if (notifications[n].priority < priority) + break; + insertPos = notifications[n]; + } + if (!insertPos) { + aItem.style.position = "fixed"; + aItem.style.top = "100%"; + aItem.style.marginTop = "-15px"; + aItem.style.opacity = "0"; + } + let label = aItem.label; + this.insertBefore(aItem, insertPos); + aItem.label = label; + + if (!insertPos) + this._showNotification(aItem, true, true); + + // Fire event for accessibility APIs + var event = document.createEvent("Events"); + event.initEvent("AlertActive", true, true); + aItem.dispatchEvent(event); + + return aItem; + ]]> + + @@ -76,5 +116,43 @@ - + + + + + + + + + diff --git a/browser/metro/base/content/browser-ui.js b/browser/metro/base/content/browser-ui.js index 31e65574a13..35bc704e797 100644 --- a/browser/metro/base/content/browser-ui.js +++ b/browser/metro/base/content/browser-ui.js @@ -32,6 +32,7 @@ let Elements = {}; ["urlbarState", "bcast_urlbarState"], ["loadingState", "bcast_loadingState"], ["windowState", "bcast_windowState"], + ["chromeState", "bcast_chromeState"], ["mainKeyset", "mainKeyset"], ["stack", "stack"], ["tabList", "tabs"], diff --git a/browser/metro/base/content/browser.js b/browser/metro/base/content/browser.js index f282233125b..017b8fbe22d 100644 --- a/browser/metro/base/content/browser.js +++ b/browser/metro/base/content/browser.js @@ -1356,6 +1356,12 @@ Tab.prototype = { this.updateViewport(); this._delayUpdateThumbnail(); break; + case "AlertClose": { + if (this == Browser.selectedTab) { + this.updateViewport(); + } + break; + } } }, @@ -1462,6 +1468,7 @@ Tab.prototype = { Elements.browsers.insertBefore(notification, aInsertBefore); notification.dir = "reverse"; + notification.addEventListener("AlertClose", this); // let the content area manager know about this browser. ContentAreaObserver.onBrowserCreated(browser); @@ -1483,6 +1490,7 @@ Tab.prototype = { _destroyBrowser: function _destroyBrowser() { if (this._browser) { let notification = this._notification; + notification.removeEventListener("AlertClose", this); let browser = this._browser; browser.active = false; diff --git a/browser/metro/base/content/browser.xul b/browser/metro/base/content/browser.xul index b6b97e7b288..7f7e5fafc52 100644 --- a/browser/metro/base/content/browser.xul +++ b/browser/metro/base/content/browser.xul @@ -69,6 +69,8 @@ viewstate=""/> + @@ -399,6 +401,8 @@ Desktop browser's sync prefs. + diff --git a/browser/metro/base/content/downloads.js b/browser/metro/base/content/downloads.js index 9a77ff61ac1..48788b86f62 100644 --- a/browser/metro/base/content/downloads.js +++ b/browser/metro/base/content/downloads.js @@ -549,12 +549,27 @@ var MetroDownloadsView = { switch (aEvent.type) { case 'TabClose': { let browser = aEvent.originalTarget.linkedBrowser; - dump("DownloadNotificationsView handleEvent, got TabClose event for browser: "+browser+"\n"); - let notn = this._getNotificationWithValue("download-progress"); - if (notn && notn.defaultView == browser.contentWindow) { - let nextTab = Browser.getNextTab(aEvent.originalTarget); - let box = Browser.getNotificationBox(nextTab.linkedBrowser); - box.insertBefore(notn, box.firstChild); + let tab = Browser.getTabForBrowser(browser); + let notificationBox = Browser.getNotificationBox(browser); + + // move any download-related notification before the tab and its notificationBox goes away + // The 3 possible values should be mutually exclusive + for(let name of ["download-progress", + "save-download", + "download-complete"]) { + let notn = notificationBox.getNotificationWithValue(name); + if (!notn) { + continue; + } + + let nextTab = Browser.getNextTab(tab); + let nextBox = nextTab && Browser.getNotificationBox(nextTab.browser); + if (nextBox) { + // move notification to the next tab + nextBox.adoptNotification(notn); + } else { + // Alas, no browser to move the notifications to. + } } break; } diff --git a/browser/metro/base/tests/mochitest/browser_downloads.js b/browser/metro/base/tests/mochitest/browser_downloads.js index 68cab8e2a7f..913bc7bb033 100644 --- a/browser/metro/base/tests/mochitest/browser_downloads.js +++ b/browser/metro/base/tests/mochitest/browser_downloads.js @@ -341,4 +341,49 @@ gTests.push({ including correct values for state variables (e.g. _downloadCount, _downloadsInProgress) \ and the existence of the downloaded file."); } +}); + +/** + * Make sure download notifications are moved when we close tabs. + */ +gTests.push({ + desc: "Download notifications in closed tabs", + setUp: function() { + // put up a couple notifications on the initial tab + let notificationBox = Browser.getNotificationBox(); + notificationBox.appendNotification("not important", "low-priority-thing", "", notificationBox.PRIORITY_INFO_LOW, []); + notificationBox.appendNotification("so important", "high-priority-thing", "", notificationBox.PRIORITY_CRITICAL_HIGH, []); + + // open a new tab where we'll conduct the test + yield addTab("about:mozilla"); + }, + run: function(){ + let notificationBox = Browser.getNotificationBox(); + let notn = MetroDownloadsView.showNotification("download-progress", "test message", [], + notificationBox.PRIORITY_WARNING_LOW); + Browser.closeTab(Browser.selectedTab); + + yield waitForEvent(Elements.tabList, "TabRemove"); + + // expected behavior when a tab is closed while a download notification is showing: + // * the notification remains visible as long as a next tab/browser exists + // * normal rules about priority apply + // * notifications - including any pre-existing ones - display in expected order + let nextBox = Browser.getNotificationBox(); + let currentNotification; + + ok(nextBox.getNotificationWithValue("download-progress"), "notification was moved to next tab"); + + currentNotification = nextBox.currentNotification; + is(currentNotification.value, "high-priority-thing", "high priority notification is current"); + currentNotification.close(); + + currentNotification = nextBox.currentNotification; + is(currentNotification.value, "download-progress", "download notification is next"); + currentNotification.close(); + + currentNotification = nextBox.currentNotification; + is(currentNotification.value, "low-priority-thing", "low priority notification is next"); + currentNotification.close(); + } }); \ No newline at end of file diff --git a/browser/metro/base/tests/mochitest/browser_notifications.js b/browser/metro/base/tests/mochitest/browser_notifications.js new file mode 100644 index 00000000000..2213406a6e3 --- /dev/null +++ b/browser/metro/base/tests/mochitest/browser_notifications.js @@ -0,0 +1,95 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +function test() { + runTests(); +} + +function cleanup() { + let notificationBox = Browser.getNotificationBox(); + notificationBox && notificationBox.removeAllNotifications(true); +} + +const XHTML_NS = "http://www.w3.org/1999/xhtml"; + +function createTestNotification(aLabel, aID) { + let notificationBox = Browser.getNotificationBox(); + let notn = notificationBox.appendNotification(aLabel || "some label", aID || "test-notification", + "", notificationBox.PRIORITY_INFO_LOW, []); + return notn; +} + +gTests.push({ + desc: "Verify notification bindings are correct", + run: function () { + let notificationBox = Browser.getNotificationBox(); + let notn = createTestNotification(); + + let binding = notn && getComputedStyle(notn).MozBinding; + is(binding, + "url(\"chrome://browser/content/bindings/notification.xml#notification\")", + "notification has expected binding"); + + is(getComputedStyle(notificationBox).MozBinding, + "url(\"chrome://browser/content/bindings/notification.xml#notificationbox\")", + "notificationbox has expected binding"); + }, + tearDown: cleanup +}); + +gTests.push({ + desc: "Check label property handling", + run: function () { + let notn = createTestNotification("the label"); + is(notn.label, "the label"); + + let doc = notn.ownerDocument; + let fragment = doc.createDocumentFragment(); + try { + let boldLabel = doc.createElementNS(XHTML_NS, "b"); + boldLabel.innerHTML = 'The label'; + fragment.appendChild(boldLabel); + notn.label = fragment; + } catch (ex) { + ok(!ex, "Exception creating notification label with markup: "+ex.message); + } + + // expect to get a documentFragment back when the label has markup + let labelNode = notn.label; + is(labelNode.nodeType, + Components.interfaces.nsIDOMNode.DOCUMENT_FRAGMENT_NODE, + "notification label getter returns documentFragment nodeType "+Components.interfaces.nsIDOMNode.DOCUMENT_FRAGMENT_NODE+", when value contains markup"); + ok(labelNode !== fragment, + "label fragment is a newly created fragment, not the one we assigned in the setter"); + ok(labelNode.querySelector("b > .foo"), + "label fragment has the expected elements in it"); + }, + tearDown: cleanup +}); + +gTests.push({ + desc: "Check adoptNotification does what we expect", + setUp: function() { + yield addTab("about:start"); + yield addTab("about:mozilla"); + }, + run: function () { + let browser = getBrowser(); + let notn = createTestNotification("label", "adopt-notification"); + let firstBox = Browser.getNotificationBox(); + let nextTab = Browser.getNextTab(Browser.getTabForBrowser(browser)); + let nextBox = Browser.getNotificationBox(nextTab.browser); + + ok(firstBox.getNotificationWithValue("adopt-notification"), "notificationbox has our notification intially"); + nextBox.adoptNotification(notn); + + ok(!firstBox.getNotificationWithValue("adopt-notification"), "after adoptNotification, original notificationbox no longer has our notification"); + ok(nextBox.getNotificationWithValue("adopt-notification"), "next notificationbox has our notification"); + }, + // leave browser in clean state for next tests + tearDown: cleanUpOpenedTabs +}); + diff --git a/browser/metro/base/tests/mochitest/head.js b/browser/metro/base/tests/mochitest/head.js index 12da0251e92..181f0d5dbf6 100644 --- a/browser/metro/base/tests/mochitest/head.js +++ b/browser/metro/base/tests/mochitest/head.js @@ -310,10 +310,16 @@ function addTab(aUrl) { function cleanUpOpenedTabs() { let tab; while(tab = gOpenedTabs.shift()) { + cleanupNotificationsForBrowser(tab.browser); Browser.closeTab(Browser.getTabFromChrome(tab.chromeTab), { forceClose: true }) } } +function cleanupNotificationsForBrowser(aBrowser) { + let notificationBox = Browser.getNotificationBox(aBrowser); + notificationBox && notificationBox.removeAllNotifications(true); +} + /** * Waits a specified number of miliseconds for a specified event to be * fired on a specified element. diff --git a/browser/metro/base/tests/mochitest/metro.ini b/browser/metro/base/tests/mochitest/metro.ini index bbdf812eb2d..5cc0d8cde8e 100644 --- a/browser/metro/base/tests/mochitest/metro.ini +++ b/browser/metro/base/tests/mochitest/metro.ini @@ -54,6 +54,7 @@ support-files = [browser_link_click.js] [browser_menu_hoverstate.js] [browser_mouse_events.js] +[browser_notifications.js] [browser_onscreen_keyboard.js] [browser_prefs_ui.js] [browser_private_browsing.js] diff --git a/browser/metro/shell/commandexecutehandler/Makefile.in b/browser/metro/shell/commandexecutehandler/Makefile.in index c5559bb1ef4..4436b3fdc76 100644 --- a/browser/metro/shell/commandexecutehandler/Makefile.in +++ b/browser/metro/shell/commandexecutehandler/Makefile.in @@ -5,7 +5,6 @@ include $(topsrcdir)/config/config.mk DIST_PROGRAM = CommandExecuteHandler$(BIN_SUFFIX) -RCINCLUDE = CommandExecuteHandler.rc # Don't link against mozglue.dll MOZ_GLUE_LDFLAGS = diff --git a/browser/metro/shell/commandexecutehandler/moz.build b/browser/metro/shell/commandexecutehandler/moz.build index cd2ac7912ba..e29b41b1e15 100644 --- a/browser/metro/shell/commandexecutehandler/moz.build +++ b/browser/metro/shell/commandexecutehandler/moz.build @@ -18,3 +18,5 @@ for var in ('UNICODE', '_UNICODE', 'NS_NO_XPCOM'): DEFINES[var] = True NO_PGO = True + +RCINCLUDE = 'CommandExecuteHandler.rc' diff --git a/browser/metro/theme/browser.css b/browser/metro/theme/browser.css index 9e957133b23..f892d6ce021 100644 --- a/browser/metro/theme/browser.css +++ b/browser/metro/theme/browser.css @@ -251,10 +251,6 @@ documenttab[selected] .documenttab-selection:-moz-locale-dir(rtl) { /* Start UI ----------------------------------------------------------------- */ -#content-viewport[startpage] .active-tab-notificationbox { - padding-bottom: @toolbar_height@; -} - #urlbar-autocomplete[viewstate="snapped"], #urlbar-autocomplete[viewstate="portrait"]{ -moz-box-orient: vertical; @@ -505,6 +501,11 @@ documenttab[selected] .documenttab-selection:-moz-locale-dir(rtl) { visibility: hidden; } +#content-viewport[navbar="visible"] .active-tab-notificationbox:not([count="0"]):not([notificationsVisible="false"]) { + padding-bottom: @toolbar_height@; +} + + /* Progress meter ---------------------------------------------------------- */ #progress-container { diff --git a/browser/modules/CustomizationTabPreloader.jsm b/browser/modules/CustomizationTabPreloader.jsm index bc4c9d61021..1ccdaa0d136 100644 --- a/browser/modules/CustomizationTabPreloader.jsm +++ b/browser/modules/CustomizationTabPreloader.jsm @@ -21,12 +21,6 @@ const CUSTOMIZATION_URL = "about:customizing"; // The interval between swapping in a preload docShell and kicking off the // next preload in the background. const PRELOADER_INTERVAL_MS = 600; -// The initial delay before we start preloading our first customization page. The -// timer is started after the first 'browser-delayed-startup' has been sent. -const PRELOADER_INIT_DELAY_MS = 7000; - -const TOPIC_TIMER_CALLBACK = "timer-callback"; -const TOPIC_DELAYED_STARTUP = "browser-delayed-startup-finished"; function createTimer(obj, delay) { let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); @@ -42,10 +36,6 @@ function clearTimer(timer) { } this.CustomizationTabPreloader = { - init: function() { - CustomizationTabPreloaderInternal.init(); - }, - uninit: function () { CustomizationTabPreloaderInternal.uninit(); }, @@ -53,28 +43,23 @@ this.CustomizationTabPreloader = { newTab: function (aTab) { return CustomizationTabPreloaderInternal.newTab(aTab); }, + + /** + * ensurePreloading starts the preloading of the about:customizing + * content page. This function is idempotent (until a call to uninit), + * so multiple calls to it are fine. + */ + ensurePreloading: function() { + CustomizationTabPreloaderInternal.ensurePreloading(); + }, }; Object.freeze(CustomizationTabPreloader); this.CustomizationTabPreloaderInternal = { _browser: null, - _timer: null, - _observing: false, - - init: function () { - Services.obs.addObserver(this, TOPIC_DELAYED_STARTUP, false); - this._observing = true; - }, uninit: function () { - this._timer = clearTimer(this._timer); - - if (this._observing) { - Services.obs.removeObserver(this, TOPIC_DELAYED_STARTUP); - this._observing = false; - } - HostFrame.destroy(); if (this._browser) { @@ -92,23 +77,10 @@ this.CustomizationTabPreloaderInternal = { return false; }, - observe: function (aSubject, aTopic, aData) { - if (aTopic == TOPIC_DELAYED_STARTUP) { - Services.obs.removeObserver(this, TOPIC_DELAYED_STARTUP); - this._observing = false; - this._startTimer(); - } else if (aTopic == TOPIC_TIMER_CALLBACK) { - this._timer = null; - this._startPreloader(); + ensurePreloading: function () { + if (!this._browser) { + this._browser = new HiddenBrowser(); } - }, - - _startTimer: function () { - this._timer = createTimer(this, PRELOADER_INIT_DELAY_MS); - }, - - _startPreloader: function () { - this._browser = new HiddenBrowser(); } }; diff --git a/browser/themes/linux/jar.mn b/browser/themes/linux/jar.mn index 0ca5f412119..c34e129263b 100644 --- a/browser/themes/linux/jar.mn +++ b/browser/themes/linux/jar.mn @@ -160,7 +160,8 @@ browser.jar: * skin/classic/browser/devtools/dark-theme.css (../shared/devtools/dark-theme.css) * skin/classic/browser/devtools/light-theme.css (../shared/devtools/light-theme.css) skin/classic/browser/devtools/filters.svg (../shared/devtools/filters.svg) - skin/classic/browser/devtools/controls.png (../shared/devtools/controls.png) + skin/classic/browser/devtools/controls.png (../shared/devtools/images/controls.png) + skin/classic/browser/devtools/controls@2x.png (../shared/devtools/images/controls@2x.png) * skin/classic/browser/devtools/widgets.css (devtools/widgets.css) skin/classic/browser/devtools/commandline-icon.png (devtools/commandline-icon.png) skin/classic/browser/devtools/command-paintflashing.png (../shared/devtools/images/command-paintflashing.png) diff --git a/browser/themes/linux/menuPanel.png b/browser/themes/linux/menuPanel.png index 5821f40bd93..0fc16291d31 100644 Binary files a/browser/themes/linux/menuPanel.png and b/browser/themes/linux/menuPanel.png differ diff --git a/browser/themes/osx/jar.mn b/browser/themes/osx/jar.mn index b6c1f008ea1..1566895454f 100644 --- a/browser/themes/osx/jar.mn +++ b/browser/themes/osx/jar.mn @@ -273,7 +273,8 @@ browser.jar: * skin/classic/browser/devtools/dark-theme.css (../shared/devtools/dark-theme.css) * skin/classic/browser/devtools/light-theme.css (../shared/devtools/light-theme.css) skin/classic/browser/devtools/filters.svg (../shared/devtools/filters.svg) - skin/classic/browser/devtools/controls.png (../shared/devtools/controls.png) + skin/classic/browser/devtools/controls.png (../shared/devtools/images/controls.png) + skin/classic/browser/devtools/controls@2x.png (../shared/devtools/images/controls@2x.png) * skin/classic/browser/devtools/widgets.css (devtools/widgets.css) skin/classic/browser/devtools/commandline-icon.png (devtools/commandline-icon.png) skin/classic/browser/devtools/command-paintflashing.png (../shared/devtools/images/command-paintflashing.png) diff --git a/browser/themes/osx/menuPanel.png b/browser/themes/osx/menuPanel.png index 30111cb8493..8b6aa254b23 100644 Binary files a/browser/themes/osx/menuPanel.png and b/browser/themes/osx/menuPanel.png differ diff --git a/browser/themes/osx/menuPanel@2x.png b/browser/themes/osx/menuPanel@2x.png index 684a1afd159..1cc200c52e5 100644 Binary files a/browser/themes/osx/menuPanel@2x.png and b/browser/themes/osx/menuPanel@2x.png differ diff --git a/browser/themes/shared/browser.inc b/browser/themes/shared/browser.inc index ecb77a83db8..ecb51c76a0d 100644 --- a/browser/themes/shared/browser.inc +++ b/browser/themes/shared/browser.inc @@ -2,3 +2,4 @@ %define primaryToolbarButtons #back-button, #forward-button, #home-button, #print-button, #downloads-button, #bookmarks-menu-button, #new-tab-button, #new-window-button, #cut-button, #copy-button, #paste-button, #fullscreen-button, #zoom-out-button, #zoom-reset-button, #zoom-in-button, #sync-button, #feed-button, #tabview-button, #webrtc-status-button, #social-share-button, #open-file-button, #find-button, #developer-button, #preferences-button, #privatebrowsing-button, #save-page-button, #switch-to-metro-button, #add-ons-button, #history-panelmenu, #nav-bar-overflow-button, #PanelUI-menu-button, #characterencoding-button, #email-link-button %define inAnyPanel :-moz-any(:not([cui-areatype="toolbar"]),.overflowedItem) +%define nestedButtons #zoom-out-button, #zoom-in-button, #cut-button, #copy-button, #paste-button diff --git a/browser/themes/shared/customizableui/customizeMode.inc.css b/browser/themes/shared/customizableui/customizeMode.inc.css index ee5a04141d8..b7ee75d5970 100644 --- a/browser/themes/shared/customizableui/customizeMode.inc.css +++ b/browser/themes/shared/customizableui/customizeMode.inc.css @@ -56,11 +56,16 @@ #main-window[customize-entered] .customization-target:not(#PanelUI-contents):hover::before, #main-window[customize-entered] .customization-target[customizing-dragovertarget]:not(#PanelUI-contents)::before, /* nav-bar and panel outlines are always shown */ -#main-window[customize-entered] #nav-bar-customization-target.customization-target::before { +#nav-bar[showoutline=true] > #nav-bar-customization-target.customization-target::before { outline-color: rgb(102,102,102); } -#main-window[customize-entered] .panel-customization-placeholder { +#nav-bar[showoutline=true] > #nav-bar-customization-target.customization-target::before { + transition: outline-color 250ms linear; +} + +#PanelUI-contents[showoutline=true] > .panel-customization-placeholder { + transition: outline-color 250ms linear; outline-color: #bbb; } @@ -171,6 +176,15 @@ toolbarpaletteitem[place="panel"] { transition: transform .3s ease-in-out; } +#customization-palette { + transition: opacity .3s ease-in-out; + opacity: 0; +} + +#customization-palette[showing="true"] { + opacity: 1; +} + toolbarpaletteitem[notransition].panel-customization-placeholder, toolbarpaletteitem[notransition][place="toolbar"], toolbarpaletteitem[notransition][place="palette"], diff --git a/browser/themes/shared/devtools/controls.png b/browser/themes/shared/devtools/controls.png deleted file mode 100644 index ebba41cd794..00000000000 Binary files a/browser/themes/shared/devtools/controls.png and /dev/null differ diff --git a/browser/themes/shared/devtools/dark-theme.css b/browser/themes/shared/devtools/dark-theme.css index 93918e31694..88288d71c07 100644 --- a/browser/themes/shared/devtools/dark-theme.css +++ b/browser/themes/shared/devtools/dark-theme.css @@ -21,40 +21,9 @@ color: #f5f7fa; } -.theme-twisty { - cursor: pointer; - width: 14px; - height: 14px; - background-repeat: no-repeat; - background-image: url("chrome://browser/skin/devtools/controls.png"); - background-position: -28px -14px; -} - -.theme-twisty:-moz-focusring { - outline-style: none; -} - -.theme-twisty[open] { - background-position: -42px -14px; -} - -.theme-checkbox { - display: inline-block; - border: 0; - width: 14px; - height: 14px; - padding: 0; - outline: none; - background-image: url("chrome://browser/skin/devtools/controls.png"); - background-position: -28px 0; -} - -.theme-checkbox[checked] { - background-position: -42px 0; -} - .theme-selected { - background: #26394D; + background-color: #1d4f73; + color: #f5f7fa; /* Light foreground text */ } .theme-bg-darker { @@ -254,6 +223,46 @@ div.CodeMirror span.eval-text { min-height: 1.4em; } +/* Twisty and checkbox controls */ +.theme-twisty, .theme-checkbox { + width: 14px; + height: 14px; + background-repeat: no-repeat; + background-image: url("chrome://browser/skin/devtools/controls.png"); + background-size: 56px 28px; +} + +.theme-twisty { + cursor: pointer; + background-position: -28px -14px; +} + +.theme-twisty:-moz-focusring { + outline-style: none; +} + +.theme-twisty[open] { + background-position: -42px -14px; +} + +.theme-checkbox { + display: inline-block; + border: 0; + padding: 0; + outline: none; + background-position: -28px 0; +} + +.theme-checkbox[checked] { + background-position: -42px 0; +} + +@media (min-resolution: 2dppx) { + .theme-twisty, .theme-checkbox { + background-image: url("chrome://browser/skin/devtools/controls@2x.png"); + } +} + /* XUL panel styling (see browser/devtools/shared/widgets/Tooltip.js) */ .theme-tooltip-panel .panel-arrowcontent { diff --git a/browser/themes/shared/devtools/images/controls.png b/browser/themes/shared/devtools/images/controls.png new file mode 100644 index 00000000000..569c266e4e4 Binary files /dev/null and b/browser/themes/shared/devtools/images/controls.png differ diff --git a/browser/themes/shared/devtools/images/controls@2x.png b/browser/themes/shared/devtools/images/controls@2x.png new file mode 100644 index 00000000000..fb062516db8 Binary files /dev/null and b/browser/themes/shared/devtools/images/controls@2x.png differ diff --git a/browser/themes/shared/devtools/light-theme.css b/browser/themes/shared/devtools/light-theme.css index 85a2c875285..83ecf5c46ee 100644 --- a/browser/themes/shared/devtools/light-theme.css +++ b/browser/themes/shared/devtools/light-theme.css @@ -21,40 +21,9 @@ color: #f5f7fa; } -.theme-twisty { - cursor: pointer; - width: 14px; - height: 14px; - background-repeat: no-repeat; - background-image: url("chrome://browser/skin/devtools/controls.png"); - background-position: 0 -14px; -} - -.theme-twisty:-moz-focusring { - outline-style: none; -} - -.theme-twisty[open] { - background-position: -14px -14px; -} - -.theme-checkbox { - display: inline-block; - border: 0; - width: 14px; - height: 14px; - padding: 0; - outline: none; - background-image: url("chrome://browser/skin/devtools/controls.png"); - background-position: 0 0; -} - -.theme-checkbox[checked] { - background-position: -14px 0; -} - .theme-selected { - background-color: #CCC; + background-color: #4c9ed9; + color: #f5f7fa; /* Light foreground text */ } .theme-bg-darker { @@ -253,6 +222,56 @@ div.CodeMirror span.eval-text { min-height: 1.4em; } +/* Twisty and checkbox controls */ + +.theme-twisty, .theme-checkbox { + width: 14px; + height: 14px; + background-repeat: no-repeat; + background-image: url("chrome://browser/skin/devtools/controls.png"); + background-size: 56px 28px; +} + +.theme-twisty { + cursor: pointer; + background-position: 0 -14px; +} + +.theme-twisty:-moz-focusring { + outline-style: none; +} + +.theme-twisty[open] { + background-position: -14px -14px; +} + +/* Use white twisty when next to a selected item in markup view */ +.theme-selected ~ .theme-twisty { + background-position: -28px -14px; +} + +.theme-selected ~ .theme-twisty[open] { + background-position: -42px -14px; +} + +.theme-checkbox { + display: inline-block; + border: 0; + padding: 0; + outline: none; + background-position: 0 0; +} + +.theme-checkbox[checked] { + background-position: -14px 0; +} + +@media (min-resolution: 2dppx) { + .theme-twisty, .theme-checkbox { + background-image: url("chrome://browser/skin/devtools/controls@2x.png"); + } +} + /* XUL panel styling (see browser/devtools/shared/widgets/Tooltip.js) */ .theme-tooltip-panel .panel-arrowcontent { diff --git a/browser/themes/shared/devtools/markup-view.css b/browser/themes/shared/devtools/markup-view.css index bd924344924..90b36e8e952 100644 --- a/browser/themes/shared/devtools/markup-view.css +++ b/browser/themes/shared/devtools/markup-view.css @@ -14,3 +14,22 @@ .styleinspector-propertyeditor { border: 1px solid #CCC; } + + +/* Selected nodes in the tree should have light selected text. + theme-selected doesn't work in this case since the text is a + sibling of the class, not a child. */ +.theme-selected ~ .editor, +.theme-selected ~ .editor .theme-fg-color1, +.theme-selected ~ .editor .theme-fg-color2, +.theme-selected ~ .editor .theme-fg-color3, +.theme-selected ~ .editor .theme-fg-color4, +.theme-selected ~ .editor .theme-fg-color5, +.theme-selected ~ .editor .theme-fg-color6, +.theme-selected ~ .editor .theme-fg-color7 { + color: #f5f7fa; /* Light foreground text */ +} + +.tag-line { + padding-left: 2px; +} diff --git a/browser/themes/windows/browser-aero.css b/browser/themes/windows/browser-aero.css index 1464cd54601..b721ff099cc 100644 --- a/browser/themes/windows/browser-aero.css +++ b/browser/themes/windows/browser-aero.css @@ -8,7 +8,6 @@ %define glassActiveBorderColor rgb(37, 44, 51) %define glassInactiveBorderColor rgb(102, 102, 102) -%define nestedButtons #zoom-out-button, #zoom-in-button, #cut-button, #copy-button, #paste-button %include downloads/indicator-aero.css diff --git a/browser/themes/windows/browser.css b/browser/themes/windows/browser.css index f91ce570399..3c9cc88ffcd 100644 --- a/browser/themes/windows/browser.css +++ b/browser/themes/windows/browser.css @@ -801,6 +801,12 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon { } %endif +#main-window[tabsintitlebar]:not([inFullscreen]) :-moz-any(#TabsToolbar, #toolbar-menubar) > #bookmarks-menu-button > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon:-moz-system-metric(windows-classic):not(:-moz-lwtheme), +#main-window[tabsintitlebar]:not([inFullscreen]) :-moz-any(#TabsToolbar, #toolbar-menubar) > toolbarpaletteitem > #bookmarks-menu-button > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon:-moz-system-metric(windows-classic):not(:-moz-lwtheme), +#main-window[tabsintitlebar]:not([inFullscreen]) :-moz-any(#TabsToolbar, #toolbar-menubar) > toolbarpaletteitem > toolbaritem > :-moz-any(@nestedButtons@):-moz-system-metric(windows-classic):not(:-moz-lwtheme), +#main-window[tabsintitlebar]:not([inFullscreen]) :-moz-any(#TabsToolbar, #toolbar-menubar) > toolbaritem > :-moz-any(@nestedButtons@):-moz-system-metric(windows-classic):not(:-moz-lwtheme), +#main-window[tabsintitlebar]:not([inFullscreen]) :-moz-any(#TabsToolbar, #toolbar-menubar) > toolbarpaletteitem > :-moz-any(@primaryToolbarButtons@):-moz-system-metric(windows-classic):not(:-moz-lwtheme), +#main-window[tabsintitlebar]:not([inFullscreen]) :-moz-any(#TabsToolbar, #toolbar-menubar) > :-moz-any(@primaryToolbarButtons@):-moz-system-metric(windows-classic):not(:-moz-lwtheme), #home-button.bookmark-item:-moz-lwtheme-brighttext { list-style-image: url("chrome://browser/skin/Toolbar-inverted.png"); } @@ -1640,6 +1646,8 @@ toolbarbutton[type="socialmark"] > .toolbarbutton-icon { background-origin: border-box; } +#main-window[tabsintitlebar]:not([inFullscreen]) .tabbrowser-arrowscrollbox > .scrollbutton-up:-moz-system-metric(windows-classic):not(:-moz-lwtheme), +#main-window[tabsintitlebar]:not([inFullscreen]) .tabbrowser-arrowscrollbox > .scrollbutton-down:-moz-system-metric(windows-classic):not(:-moz-lwtheme), .tabbrowser-arrowscrollbox > .scrollbutton-up:-moz-lwtheme-brighttext, .tabbrowser-arrowscrollbox > .scrollbutton-down:-moz-lwtheme-brighttext { list-style-image: url(chrome://browser/skin/tabbrowser/tab-arrow-left-inverted.png); @@ -1683,6 +1691,9 @@ toolbarbutton[type="socialmark"] > .toolbarbutton-icon { -moz-image-region: auto; } +#main-window[tabsintitlebar]:not([inFullscreen]) .tabs-newtab-button:-moz-system-metric(windows-classic):not(:-moz-lwtheme), +#main-window[tabsintitlebar]:not([inFullscreen]) #TabsToolbar > #new-tab-button:-moz-system-metric(windows-classic):not(:-moz-lwtheme), +#main-window[tabsintitlebar]:not([inFullscreen]) #TabsToolbar > toolbarpaletteitem > #new-tab-button:-moz-system-metric(windows-classic):not(:-moz-lwtheme), .tabs-newtab-button:-moz-lwtheme-brighttext, #TabsToolbar > #new-tab-button:-moz-lwtheme-brighttext, #TabsToolbar > toolbarpaletteitem > #new-tab-button:-moz-lwtheme-brighttext { @@ -1697,6 +1708,7 @@ toolbarbutton[type="socialmark"] > .toolbarbutton-icon { list-style-image: url("chrome://browser/skin/toolbarbutton-dropdown-arrow.png"); } +#main-window[tabsintitlebar]:not([inFullscreen]) #alltabs-button:-moz-system-metric(windows-classic):not(:-moz-lwtheme), #alltabs-button:-moz-lwtheme-brighttext { list-style-image: url("chrome://browser/skin/toolbarbutton-dropdown-arrow-inverted.png"); } diff --git a/browser/themes/windows/jar.mn b/browser/themes/windows/jar.mn index 62cda8ff4aa..c0c4b2a9681 100644 --- a/browser/themes/windows/jar.mn +++ b/browser/themes/windows/jar.mn @@ -189,7 +189,8 @@ browser.jar: * skin/classic/browser/devtools/dark-theme.css (../shared/devtools/dark-theme.css) * skin/classic/browser/devtools/light-theme.css (../shared/devtools/light-theme.css) skin/classic/browser/devtools/filters.svg (../shared/devtools/filters.svg) - skin/classic/browser/devtools/controls.png (../shared/devtools/controls.png) + skin/classic/browser/devtools/controls.png (../shared/devtools/images/controls.png) + skin/classic/browser/devtools/controls@2x.png (../shared/devtools/images/controls@2x.png) * skin/classic/browser/devtools/widgets.css (devtools/widgets.css) skin/classic/browser/devtools/commandline-icon.png (devtools/commandline-icon.png) skin/classic/browser/devtools/alerticon-warning.png (devtools/alerticon-warning.png) @@ -510,7 +511,8 @@ browser.jar: * skin/classic/aero/browser/devtools/dark-theme.css (../shared/devtools/dark-theme.css) * skin/classic/aero/browser/devtools/light-theme.css (../shared/devtools/light-theme.css) skin/classic/aero/browser/devtools/filters.svg (../shared/devtools/filters.svg) - skin/classic/aero/browser/devtools/controls.png (../shared/devtools/controls.png) + skin/classic/aero/browser/devtools/controls.png (../shared/devtools/images/controls.png) + skin/classic/aero/browser/devtools/controls@2x.png (../shared/devtools/images/controls@2x.png) * skin/classic/aero/browser/devtools/widgets.css (devtools/widgets.css) skin/classic/aero/browser/devtools/commandline-icon.png (devtools/commandline-icon.png) skin/classic/aero/browser/devtools/command-paintflashing.png (../shared/devtools/images/command-paintflashing.png) diff --git a/browser/themes/windows/menuPanel-aero.png b/browser/themes/windows/menuPanel-aero.png index eeeca15ac80..2145b4db604 100644 Binary files a/browser/themes/windows/menuPanel-aero.png and b/browser/themes/windows/menuPanel-aero.png differ diff --git a/browser/themes/windows/menuPanel.png b/browser/themes/windows/menuPanel.png index 5821f40bd93..0fc16291d31 100644 Binary files a/browser/themes/windows/menuPanel.png and b/browser/themes/windows/menuPanel.png differ diff --git a/build/stlport/Makefile.in b/build/stlport/Makefile.in index 8093271d4e9..f0ea7da915b 100644 --- a/build/stlport/Makefile.in +++ b/build/stlport/Makefile.in @@ -3,7 +3,6 @@ # You can obtain one at http://mozilla.org/MPL/2.0/. MODULES = stlport -STL_FLAGS = # Force to build a static library, instead of a fake library, without # installing it in dist/lib. diff --git a/build/stlport/moz.build b/build/stlport/moz.build index 0a0be7c8be8..3d632754f69 100644 --- a/build/stlport/moz.build +++ b/build/stlport/moz.build @@ -52,3 +52,4 @@ LOCAL_INCLUDES += [ 'stlport', ] +DISABLE_STL_WRAPPING = True diff --git a/build/unix/stdc++compat/Makefile.in b/build/unix/stdc++compat/Makefile.in index b9ef76d1b6e..615af1b49f5 100644 --- a/build/unix/stdc++compat/Makefile.in +++ b/build/unix/stdc++compat/Makefile.in @@ -2,7 +2,6 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. -STL_FLAGS = NO_EXPAND_LIBS = 1 include $(topsrcdir)/config/rules.mk diff --git a/build/unix/stdc++compat/moz.build b/build/unix/stdc++compat/moz.build index 739879e83b1..d9247607920 100644 --- a/build/unix/stdc++compat/moz.build +++ b/build/unix/stdc++compat/moz.build @@ -17,3 +17,5 @@ if CONFIG['MOZ_LIBSTDCXX_HOST_VERSION']: FORCE_STATIC_LIB = True NO_PGO = True + +DISABLE_STL_WRAPPING = True diff --git a/config/config.mk b/config/config.mk index 50b9d9f340d..4873ef332e5 100644 --- a/config/config.mk +++ b/config/config.mk @@ -590,7 +590,7 @@ endif endif COMPILE_CFLAGS = $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_CPPFLAGS) $(OS_COMPILE_CFLAGS) $(CFLAGS) $(MOZBUILD_CFLAGS) $(EXTRA_COMPILE_FLAGS) -COMPILE_CXXFLAGS = $(STL_FLAGS) $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_CPPFLAGS) $(OS_COMPILE_CXXFLAGS) $(CXXFLAGS) $(MOZBUILD_CXXFLAGS) $(EXTRA_COMPILE_FLAGS) +COMPILE_CXXFLAGS = $(if $(DISABLE_STL_WRAPPING),,$(STL_FLAGS)) $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_CPPFLAGS) $(OS_COMPILE_CXXFLAGS) $(CXXFLAGS) $(MOZBUILD_CXXFLAGS) $(EXTRA_COMPILE_FLAGS) COMPILE_CMFLAGS = $(OS_COMPILE_CMFLAGS) $(MOZBUILD_CMFLAGS) $(EXTRA_COMPILE_FLAGS) COMPILE_CMMFLAGS = $(OS_COMPILE_CMMFLAGS) $(MOZBUILD_CMMFLAGS) $(EXTRA_COMPILE_FLAGS) ASFLAGS += $(EXTRA_ASSEMBLER_FLAGS) @@ -900,7 +900,7 @@ DEFINES += -DUNICODE -D_UNICODE LOCAL_INCLUDES += -I'$(MOZ_DIRECTX_SDK_PATH)/include' endif -STL_FLAGS= +DISABLE_STL_WRAPPING := 1 # Skip most Mozilla-specific include locations. INCLUDES = -I. $(LOCAL_INCLUDES) -I$(DEPTH)/dist/include endif diff --git a/content/base/public/Element.h b/content/base/public/Element.h index b55b851c829..ccd90ea6429 100644 --- a/content/base/public/Element.h +++ b/content/base/public/Element.h @@ -1088,7 +1088,8 @@ protected: * Add/remove this element to the documents id cache */ void AddToIdTable(nsIAtom* aId); - void RemoveFromIdTable(); + void RemoveFromIdTable(); // checks HasID() and uses DoGetID() + void RemoveFromIdTable(nsIAtom* aId); /** * Functions to carry out event default actions for links of all types diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index 10a2a8d26d0..f0409a8c721 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -19,6 +19,7 @@ #include "nsPIDOMWindow.h" // for use in inline functions #include "nsPropertyTable.h" // for member #include "nsTHashtable.h" // for member +#include "nsWeakReference.h" #include "mozilla/dom/DocumentBinding.h" #include "mozilla/WeakPtr.h" #include "Units.h" @@ -79,7 +80,6 @@ class nsWindowSizes; class nsSmallVoidArray; class nsDOMCaretPosition; class nsViewportInfo; -class nsDOMEvent; class nsIGlobalObject; class nsCSSSelectorList; @@ -102,6 +102,7 @@ class DOMImplementation; class DOMStringList; class Element; struct ElementRegistrationOptions; +class Event; class EventTarget; class FrameRequestCallback; class HTMLBodyElement; @@ -2003,8 +2004,8 @@ public: enum ElementCallbackType { eCreated, - eEnteredView, - eLeftView, + eAttached, + eDetached, eAttributeChanged }; @@ -2065,8 +2066,8 @@ public: already_AddRefed ImportNode(nsINode& aNode, bool aDeep, mozilla::ErrorResult& rv) const; nsINode* AdoptNode(nsINode& aNode, mozilla::ErrorResult& rv); - already_AddRefed CreateEvent(const nsAString& aEventType, - mozilla::ErrorResult& rv) const; + already_AddRefed + CreateEvent(const nsAString& aEventType, mozilla::ErrorResult& rv) const; already_AddRefed CreateRange(mozilla::ErrorResult& rv); already_AddRefed CreateNodeIterator(nsINode& aRoot, uint32_t aWhatToShow, diff --git a/content/base/public/nsINode.h b/content/base/public/nsINode.h index ef09fa1f284..ed6618a6ac1 100644 --- a/content/base/public/nsINode.h +++ b/content/base/public/nsINode.h @@ -15,7 +15,6 @@ #include "nsNodeInfoManager.h" // for use in NodePrincipal() #include "nsPropertyTable.h" // for typedefs #include "nsTObserverArray.h" // for member -#include "nsWindowMemoryReporter.h" // for NS_DECL_SIZEOF_EXCLUDING_THIS #include "mozilla/ErrorResult.h" #include "mozilla/MemoryReporting.h" #include "mozilla/dom/EventTarget.h" // for base class @@ -244,13 +243,21 @@ private: // ever passed to Mutated(). enum { eMaxMutations = 300 }; - + // sMutationCount is a global mutation counter which is decreased by one at // every mutation. It is capped at 0 to avoid wrapping. // Its value is always between 0 and 300, inclusive. static uint32_t sMutationCount; }; +// This should be used for any nsINode sub-class that has fields of its own +// that it needs to measure; any sub-class that doesn't use it will inherit +// SizeOfExcludingThis from its super-class. SizeOfIncludingThis() need not be +// defined, it is inherited from nsINode. +// This macro isn't actually specific to nodes, and bug 956400 will move it into MFBT. +#define NS_DECL_SIZEOF_EXCLUDING_THIS \ + virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; + // Categories of node properties // 0 is global. #define DOM_USER_DATA 1 diff --git a/content/base/src/Element.cpp b/content/base/src/Element.cpp index d0d57d61e86..95bce4bd6fa 100644 --- a/content/base/src/Element.cpp +++ b/content/base/src/Element.cpp @@ -719,23 +719,29 @@ void Element::RemoveFromIdTable() { if (HasID()) { - if (HasFlag(NODE_IS_IN_SHADOW_TREE)) { - ShadowRoot* containingShadow = GetContainingShadow(); - // Check for containingShadow because it may have - // been deleted during unlinking. - if (containingShadow) { - containingShadow->RemoveFromIdTable(this, DoGetID()); - } - } else { - nsIDocument* doc = GetCurrentDoc(); - if (doc) { - nsIAtom* id = DoGetID(); - // id can be null during mutation events evilness. Also, XUL elements - // loose their proto attributes during cc-unlink, so this can happen - // during cc-unlink too. - if (id) { - doc->RemoveFromIdTable(this, DoGetID()); - } + RemoveFromIdTable(DoGetID()); + } +} + +void +Element::RemoveFromIdTable(nsIAtom* aId) +{ + NS_ASSERTION(HasID(), "Node doesn't have an ID?"); + if (HasFlag(NODE_IS_IN_SHADOW_TREE)) { + ShadowRoot* containingShadow = GetContainingShadow(); + // Check for containingShadow because it may have + // been deleted during unlinking. + if (containingShadow) { + containingShadow->RemoveFromIdTable(this, aId); + } + } else { + nsIDocument* doc = GetCurrentDoc(); + if (doc && (!IsInAnonymousSubtree() || doc->IsXUL())) { + // id can be null during mutation events evilness. Also, XUL elements + // loose their proto attributes during cc-unlink, so this can happen + // during cc-unlink too. + if (aId) { + doc->RemoveFromIdTable(this, aId); } } } @@ -1158,8 +1164,8 @@ Element::BindToTree(nsIDocument* aDocument, nsIContent* aParent, SetInDocument(); if (GetCustomElementData()) { - // Enqueue an enteredView callback for the custom element. - aDocument->EnqueueLifecycleCallback(nsIDocument::eEnteredView, this); + // Enqueue an attached callback for the custom element. + aDocument->EnqueueLifecycleCallback(nsIDocument::eAttached, this); } // Unset this flag since we now really are in a document. @@ -1321,8 +1327,8 @@ Element::UnbindFromTree(bool aDeep, bool aNullParent) document->ClearBoxObjectFor(this); if (GetCustomElementData()) { - // Enqueue a leftView callback for the custom element. - document->EnqueueLifecycleCallback(nsIDocument::eLeftView, this); + // Enqueue a detached callback for the custom element. + document->EnqueueLifecycleCallback(nsIDocument::eDetached, this); } } diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 1826ac98a72..be3c5b020c6 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -193,6 +193,7 @@ #include "nsIAppsService.h" #include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/DocumentFragment.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/HTMLBodyElement.h" #include "mozilla/dom/HTMLInputElement.h" #include "mozilla/dom/NodeFilterBinding.h" @@ -203,7 +204,6 @@ #include "nsDOMCaretPosition.h" #include "nsIDOMHTMLTextAreaElement.h" #include "nsViewportInfo.h" -#include "nsDOMEvent.h" #include "nsIContentPermissionPrompt.h" #include "mozilla/StaticPtr.h" #include "nsITextControlElement.h" @@ -221,6 +221,7 @@ #include "nsIMutableArray.h" #include "nsContentPermissionHelper.h" #include "mozilla/dom/DOMStringList.h" +#include "nsWindowMemoryReporter.h" using namespace mozilla; using namespace mozilla::dom; @@ -330,11 +331,11 @@ CustomElementCallback::Call() static_cast(mCallback.get())->Call(mThisObject, rv); mOwnerData->mElementIsBeingCreated = false; break; - case nsIDocument::eEnteredView: - static_cast(mCallback.get())->Call(mThisObject, rv); + case nsIDocument::eAttached: + static_cast(mCallback.get())->Call(mThisObject, rv); break; - case nsIDocument::eLeftView: - static_cast(mCallback.get())->Call(mThisObject, rv); + case nsIDocument::eDetached: + static_cast(mCallback.get())->Call(mThisObject, rv); break; case nsIDocument::eAttributeChanged: static_cast(mCallback.get())->Call(mThisObject, @@ -1749,16 +1750,16 @@ CustomDefinitionsTraverse(CustomElementHashKey* aKey, cb->NoteXPCOMChild(aDefinition->mCallbacks->mCreatedCallback.Value()); } - if (callbacks->mEnteredViewCallback.WasPassed()) { + if (callbacks->mAttachedCallback.WasPassed()) { NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, - "mCustomDefinitions->mCallbacks->mEnteredViewCallback"); - cb->NoteXPCOMChild(aDefinition->mCallbacks->mEnteredViewCallback.Value()); + "mCustomDefinitions->mCallbacks->mAttachedCallback"); + cb->NoteXPCOMChild(aDefinition->mCallbacks->mAttachedCallback.Value()); } - if (callbacks->mLeftViewCallback.WasPassed()) { + if (callbacks->mDetachedCallback.WasPassed()) { NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, - "mCustomDefinitions->mCallbacks->mLeftViewCallback"); - cb->NoteXPCOMChild(aDefinition->mCallbacks->mLeftViewCallback.Value()); + "mCustomDefinitions->mCallbacks->mDetachedCallback"); + cb->NoteXPCOMChild(aDefinition->mCallbacks->mDetachedCallback.Value()); } return PL_DHASH_NEXT; @@ -5570,15 +5571,15 @@ nsDocument::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType, } break; - case nsIDocument::eEnteredView: - if (definition->mCallbacks->mEnteredViewCallback.WasPassed()) { - func = definition->mCallbacks->mEnteredViewCallback.Value(); + case nsIDocument::eAttached: + if (definition->mCallbacks->mAttachedCallback.WasPassed()) { + func = definition->mCallbacks->mAttachedCallback.Value(); } break; - case nsIDocument::eLeftView: - if (definition->mCallbacks->mLeftViewCallback.WasPassed()) { - func = definition->mCallbacks->mLeftViewCallback.Value(); + case nsIDocument::eDetached: + if (definition->mCallbacks->mDetachedCallback.WasPassed()) { + func = definition->mCallbacks->mDetachedCallback.Value(); } break; @@ -5921,12 +5922,12 @@ nsDocument::RegisterElement(JSContext* aCx, const nsAString& aType, EnqueueLifecycleCallback(nsIDocument::eCreated, elem, nullptr, definition); if (elem->GetCurrentDoc()) { // Normally callbacks can not be enqueued until the created - // callback has been invoked, however, the entered view callback + // callback has been invoked, however, the attached callback // in element upgrade is an exception so pretend the created // callback has been invoked. elem->GetCustomElementData()->mCreatedCallbackInvoked = true; - EnqueueLifecycleCallback(nsIDocument::eEnteredView, elem, nullptr, definition); + EnqueueLifecycleCallback(nsIDocument::eAttached, elem, nullptr, definition); } } } @@ -7648,7 +7649,7 @@ nsDocument::CreateEvent(const nsAString& aEventType, nsIDOMEvent** aReturn) return rv.ErrorCode(); } -already_AddRefed +already_AddRefed nsIDocument::CreateEvent(const nsAString& aEventType, ErrorResult& rv) const { nsIPresShell *shell = GetShell(); diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index 068b27b0437..44260585f4b 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -313,7 +313,7 @@ private: // The this value to use for invocation of the callback. nsRefPtr mThisObject; nsRefPtr mCallback; - // The type of callback (eCreated, eEnteredView, etc.) + // The type of callback (eCreated, eAttached, etc.) nsIDocument::ElementCallbackType mType; // Arguments to be passed to the callback, // used by the attribute changed callback. diff --git a/content/base/src/nsFrameMessageManager.cpp b/content/base/src/nsFrameMessageManager.cpp index df889d57fec..fded1caf70a 100644 --- a/content/base/src/nsFrameMessageManager.cpp +++ b/content/base/src/nsFrameMessageManager.cpp @@ -23,6 +23,7 @@ #include "nsIXULRuntime.h" #include "nsIScriptError.h" #include "nsIConsoleService.h" +#include "nsIMemoryReporter.h" #include "nsIProtocolHandler.h" #include "nsIScriptSecurityManager.h" #include "nsIJSRuntimeService.h" diff --git a/content/base/src/nsINode.cpp b/content/base/src/nsINode.cpp index a478082b410..ba76cd344e7 100644 --- a/content/base/src/nsINode.cpp +++ b/content/base/src/nsINode.cpp @@ -18,6 +18,9 @@ #include "mozilla/Likely.h" #include "mozilla/MemoryReporting.h" #include "mozilla/Telemetry.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/Event.h" +#include "mozilla/dom/ShadowRoot.h" #include "nsAsyncDOMEvent.h" #include "nsAttrValueOrString.h" #include "nsBindingManager.h" @@ -41,7 +44,6 @@ #include "nsFocusManager.h" #include "nsFrameManager.h" #include "nsFrameSelection.h" -#include "mozilla/dom/Element.h" #include "nsGenericHTMLElement.h" #include "nsGkAtoms.h" #include "nsIAnonymousContentCreator.h" @@ -96,11 +98,9 @@ #include "nsCSSParser.h" #include "HTMLLegendElement.h" #include "nsWrapperCacheInlines.h" -#include "mozilla/dom/ShadowRoot.h" #include "WrapperFactory.h" #include "DocumentType.h" #include -#include "nsDOMEvent.h" #include "nsGlobalWindow.h" #include "nsDOMMutationObserver.h" @@ -2633,7 +2633,7 @@ nsINode::GetAttributes() } bool -EventTarget::DispatchEvent(nsDOMEvent& aEvent, +EventTarget::DispatchEvent(Event& aEvent, ErrorResult& aRv) { bool result = false; diff --git a/content/base/src/nsObjectLoadingContent.cpp b/content/base/src/nsObjectLoadingContent.cpp index 8e4dd833ddc..adfd7c4aae8 100644 --- a/content/base/src/nsObjectLoadingContent.cpp +++ b/content/base/src/nsObjectLoadingContent.cpp @@ -69,18 +69,18 @@ #include "nsIContentSecurityPolicy.h" #include "nsIChannelPolicy.h" #include "nsChannelPolicy.h" -#include "mozilla/dom/Element.h" #include "GeckoProfiler.h" #include "nsObjectFrame.h" #include "nsDOMClassInfo.h" #include "nsWrapperCacheInlines.h" #include "nsDOMJSUtils.h" -#include "nsDOMEvent.h" #include "nsWidgetsCID.h" #include "nsContentCID.h" #include "mozilla/BasicEvents.h" #include "mozilla/dom/BindingUtils.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/Event.h" #include "mozilla/Telemetry.h" #ifdef XP_WIN @@ -307,7 +307,7 @@ nsPluginCrashedEvent::Run() } ErrorResult rv; - nsRefPtr event = + nsRefPtr event = doc->CreateEvent(NS_LITERAL_STRING("datacontainerevents"), rv); nsCOMPtr containerEvent(do_QueryObject(event)); if (!containerEvent) { diff --git a/content/html/content/src/HTMLInputElement.cpp b/content/html/content/src/HTMLInputElement.cpp index 38f663c3a25..1784e545733 100644 --- a/content/html/content/src/HTMLInputElement.cpp +++ b/content/html/content/src/HTMLInputElement.cpp @@ -2140,7 +2140,15 @@ HTMLInputElement::GetValueIfStepped(int32_t aStep, return NS_OK; } - if (GetValidityState(VALIDITY_STATE_STEP_MISMATCH) && + // If the current value isn't aligned on a step, then shift the value to the + // nearest step that will cause the addition of aStep steps (further below) + // to |value| to hit the required value. + // (Instead of using GetValidityState(VALIDITY_STATE_STEP_MISMATCH) we have + // to check HasStepMismatch and pass true as its aUseZeroIfValueNaN argument + // since we need to treat the value "" as zero for stepping purposes even + // though we don't suffer from a step mismatch when our value is the empty + // string.) + if (HasStepMismatch(true) && value != minimum && value != maximum) { if (aStep > 0) { value -= NS_floorModulo(value - GetStepBase(), step); @@ -2778,7 +2786,7 @@ HTMLInputElement::SetValueInternal(const nsAString& aValue, if (!mParserCreating) { SanitizeValue(value); } - // else SanitizeValue will be called by DoneCreatingElement + // else DoneCreatingElement calls us again once mParserCreating is false if (aSetValueChanged) { SetValueChanged(true); @@ -2803,7 +2811,10 @@ HTMLInputElement::SetValueInternal(const nsAString& aValue, numberControlFrame->SetValueOfAnonTextControl(value); } } - OnValueChanged(!mParserCreating); + if (!mParserCreating) { + OnValueChanged(true); + } + // else DoneCreatingElement calls us again once mParserCreating is false } if (mType == NS_FORM_INPUT_COLOR) { @@ -3641,12 +3652,20 @@ HTMLInputElement::StepNumberControlForUserEvent(int32_t aDirection) // want to wipe out what they typed if they try to increment/decrement the // value. Better is to highlight the value as being invalid so that they // can correct what they typed. - // We pass 'true' for UpdateValidityUIBits' aIsFocused argument regardless - // because we need the UI to update _now_ or the user will wonder why the - // step behavior isn't functioning. - UpdateValidityUIBits(true); - UpdateState(true); - return; + // We only do this if there actually is a value typed in by/displayed to + // the user. (IsValid() can return false if the 'required' attribute is + // set and the value is the empty string.) + nsNumberControlFrame* numberControlFrame = + do_QueryFrame(GetPrimaryFrame()); + if (numberControlFrame && + !numberControlFrame->AnonTextControlIsEmpty()) { + // We pass 'true' for UpdateValidityUIBits' aIsFocused argument + // regardless because we need the UI to update _now_ or the user will + // wonder why the step behavior isn't functioning. + UpdateValidityUIBits(true); + UpdateState(true); + return; + } } Decimal newValue = Decimal::nan(); // unchanged if value will not change @@ -6433,7 +6452,7 @@ HTMLInputElement::IsRangeUnderflow() const } bool -HTMLInputElement::HasStepMismatch() const +HTMLInputElement::HasStepMismatch(bool aUseZeroIfValueNaN) const { if (!DoesStepApply()) { return false; @@ -6441,8 +6460,12 @@ HTMLInputElement::HasStepMismatch() const Decimal value = GetValueAsDecimal(); if (value.isNaN()) { - // The element can't suffer from step mismatch if it's value isn't a number. - return false; + if (aUseZeroIfValueNaN) { + value = 0; + } else { + // The element can't suffer from step mismatch if it's value isn't a number. + return false; + } } Decimal step = GetStep(); diff --git a/content/html/content/src/HTMLInputElement.h b/content/html/content/src/HTMLInputElement.h index 6393c1359f1..0648a5d9c08 100644 --- a/content/html/content/src/HTMLInputElement.h +++ b/content/html/content/src/HTMLInputElement.h @@ -256,7 +256,7 @@ public: bool HasPatternMismatch() const; bool IsRangeOverflow() const; bool IsRangeUnderflow() const; - bool HasStepMismatch() const; + bool HasStepMismatch(bool aUseZeroIfValueNaN = false) const; bool HasBadInput() const; void UpdateTooLongValidityState(); void UpdateValueMissingValidityState(); diff --git a/content/html/content/src/UndoManager.cpp b/content/html/content/src/UndoManager.cpp index e1761cfbf79..e8e4550ab00 100644 --- a/content/html/content/src/UndoManager.cpp +++ b/content/html/content/src/UndoManager.cpp @@ -6,8 +6,8 @@ #include "mozilla/dom/UndoManager.h" #include "mozilla/dom/DOMTransactionBinding.h" +#include "mozilla/dom/Event.h" #include "nsDOMClassInfoID.h" -#include "nsDOMEvent.h" #include "nsIClassInfo.h" #include "nsIDOMDocument.h" #include "nsIXPCScriptable.h" @@ -1142,7 +1142,7 @@ UndoManager::DispatchTransactionEvent(JSContext* aCx, const nsAString& aType, return; } - nsRefPtr event = mHostNode->OwnerDoc()->CreateEvent( + nsRefPtr event = mHostNode->OwnerDoc()->CreateEvent( NS_LITERAL_STRING("domtransaction"), aRv); if (aRv.Failed()) { return; diff --git a/content/html/content/test/forms/test_input_number_key_events.html b/content/html/content/test/forms/test_input_number_key_events.html index 9f9777da8f1..0106039a03d 100644 --- a/content/html/content/test/forms/test_input_number_key_events.html +++ b/content/html/content/test/forms/test_input_number_key_events.html @@ -71,6 +71,18 @@ function getStepBase(element) { Number(element.getAttribute("value") || "NaN") || 0; } +function hasStepMismatch(element) { + var value = element.value; + if (value == "") { + value = 0; + } + var step = getStep(element); + if (step == "any") { + return false; + } + return ((value - getStepBase(element)) % step) != 0; +} + function floorModulo(x, y) { return (x - y * Math.floor(x / y)); } @@ -101,7 +113,7 @@ function expectedValueAfterStepUpOrDown(stepFactor, element) { return value; } - if (element.validity.stepMismatch && + if (hasStepMismatch(element) && value != minimum && value != maximum) { if (stepFactor > 0) { value -= floorModulo(value - getStepBase(element), step); @@ -138,8 +150,8 @@ function test() { var elem = document.getElementById("input"); elem.focus(); - elem.min = -3; - elem.max = 3; + elem.min = -5; + elem.max = 5; elem.step = 2; var defaultValue = 0; var oldVal, expectedVal; @@ -203,6 +215,22 @@ function test() { sendString("abc"); synthesizeKey(key, {}); is(elem.value, "", "Test " + key + " does nothing when the input is invalid"); + + // Test that no value does not block UI initiated stepping: + oldVal = elem.value = ""; + elem.setAttribute("required", "required"); + elem.select(); + expectedVal = expectedValAfterKeyEvent(key, elem); + synthesizeKey(key, {}); + is(elem.value, expectedVal, "Test " + key + " for number control with value set to the empty string and with the 'required' attribute set"); + + // Same again: + expectedVal = expectedValAfterKeyEvent(key, elem); + synthesizeKey(key, {}); + is(elem.value, expectedVal, "Test repeat of " + key + " for number control"); + + // Reset 'required' attribute: + elem.removeAttribute("required"); } } diff --git a/content/html/document/src/nsHTMLDocument.h b/content/html/document/src/nsHTMLDocument.h index 9797e7dd82c..7d261d5788c 100644 --- a/content/html/document/src/nsHTMLDocument.h +++ b/content/html/document/src/nsHTMLDocument.h @@ -20,7 +20,6 @@ #include "nsICommandManager.h" #include "mozilla/dom/HTMLSharedElement.h" -#include "nsDOMEvent.h" class nsIEditor; class nsIParser; diff --git a/content/media/AudioNodeEngine.h b/content/media/AudioNodeEngine.h index 5b893cc2eea..66c32c778c9 100644 --- a/content/media/AudioNodeEngine.h +++ b/content/media/AudioNodeEngine.h @@ -255,20 +255,29 @@ public: * *aFinished is set to false by the caller. If the callee sets it to true, * we'll finish the stream and not call this again. */ - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) { MOZ_ASSERT(mInputCount <= 1 && mOutputCount <= 1); *aOutput = aInput; } + /** + * Produce the next block of audio samples, before input is provided. + * ProcessBlock() will be called later, and it then should not change + * aOutput. This is used only for DelayNodeEngine in a feedback loop. + */ + virtual void ProduceBlockBeforeInput(AudioChunk* aOutput) + { + NS_NOTREACHED("ProduceBlockBeforeInput called on wrong engine\n"); + } /** * Produce the next block of audio samples, given input samples in the aInput * array. There is one input sample per active port in aInput, in order. - * This is the multi-input/output version of ProduceAudioBlock. Only one kind - * of ProduceAudioBlock is called on each node, depending on whether the + * This is the multi-input/output version of ProcessBlock. Only one kind + * of ProcessBlock is called on each node, depending on whether the * number of inputs and outputs are both 1 or not. * * aInput is always guaranteed to not contain more input AudioChunks than the @@ -279,10 +288,10 @@ public: * corresponding AudioNode, in which case it will be interpreted as a channel * of silence. */ - virtual void ProduceAudioBlocksOnPorts(AudioNodeStream* aStream, - const OutputChunks& aInput, - OutputChunks& aOutput, - bool* aFinished) + virtual void ProcessBlocksOnPorts(AudioNodeStream* aStream, + const OutputChunks& aInput, + OutputChunks& aOutput, + bool* aFinished) { MOZ_ASSERT(mInputCount > 1 || mOutputCount > 1); // Only produce one output port, and drop all other input ports. diff --git a/content/media/AudioNodeExternalInputStream.cpp b/content/media/AudioNodeExternalInputStream.cpp index 5fdf8a134c5..daeaad7c7b2 100644 --- a/content/media/AudioNodeExternalInputStream.cpp +++ b/content/media/AudioNodeExternalInputStream.cpp @@ -324,8 +324,8 @@ ConvertSegmentToAudioBlock(AudioSegment* aSegment, AudioChunk* aBlock) } void -AudioNodeExternalInputStream::ProduceOutput(GraphTime aFrom, GraphTime aTo, - uint32_t aFlags) +AudioNodeExternalInputStream::ProcessInput(GraphTime aFrom, GraphTime aTo, + uint32_t aFlags) { // According to spec, number of outputs is always 1. mLastChunks.SetLength(1); diff --git a/content/media/AudioNodeExternalInputStream.h b/content/media/AudioNodeExternalInputStream.h index 9710a229279..06134d3752f 100644 --- a/content/media/AudioNodeExternalInputStream.h +++ b/content/media/AudioNodeExternalInputStream.h @@ -25,7 +25,7 @@ public: AudioNodeExternalInputStream(AudioNodeEngine* aEngine, TrackRate aSampleRate); ~AudioNodeExternalInputStream(); - virtual void ProduceOutput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) MOZ_OVERRIDE; + virtual void ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) MOZ_OVERRIDE; private: // For storing pointers and data about input tracks, like the last TrackTick which diff --git a/content/media/AudioNodeStream.cpp b/content/media/AudioNodeStream.cpp index a59bae6963b..1e77f7f2df5 100644 --- a/content/media/AudioNodeStream.cpp +++ b/content/media/AudioNodeStream.cpp @@ -399,7 +399,7 @@ AudioNodeStream::UpMixDownMixChunk(const AudioChunk* aChunk, // The MediaStreamGraph guarantees that this is actually one block, for // AudioNodeStreams. void -AudioNodeStream::ProduceOutput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) +AudioNodeStream::ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) { EnsureTrack(AUDIO_TRACK, mSampleRate); // No more tracks will be coming @@ -426,17 +426,10 @@ AudioNodeStream::ProduceOutput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) ObtainInputBlock(inputChunks[i], i); } bool finished = false; -#ifdef DEBUG - for (uint16_t i = 0; i < outputCount; ++i) { - // Alter mDuration so we can detect if ProduceAudioBlock fails to set - // chunks. - mLastChunks[i].mDuration--; - } -#endif if (maxInputs <= 1 && mEngine->OutputCount() <= 1) { - mEngine->ProduceAudioBlock(this, inputChunks[0], &mLastChunks[0], &finished); + mEngine->ProcessBlock(this, inputChunks[0], &mLastChunks[0], &finished); } else { - mEngine->ProduceAudioBlocksOnPorts(this, inputChunks, mLastChunks, &finished); + mEngine->ProcessBlocksOnPorts(this, inputChunks, mLastChunks, &finished); } for (uint16_t i = 0; i < outputCount; ++i) { NS_ASSERTION(mLastChunks[i].GetDuration() == WEBAUDIO_BLOCK_SIZE, diff --git a/content/media/AudioNodeStream.h b/content/media/AudioNodeStream.h index 634d85ebf01..3c15e7830f1 100644 --- a/content/media/AudioNodeStream.h +++ b/content/media/AudioNodeStream.h @@ -33,6 +33,9 @@ class AudioNodeEngine; * integrates audio processing with the MediaStreamGraph. */ class AudioNodeStream : public ProcessedMediaStream { + typedef dom::ChannelCountMode ChannelCountMode; + typedef dom::ChannelInterpretation ChannelInterpretation; + public: typedef mozilla::dom::AudioContext AudioContext; @@ -56,8 +59,8 @@ public: mMuted(false) { MOZ_ASSERT(NS_IsMainThread()); - mChannelCountMode = dom::ChannelCountMode::Max; - mChannelInterpretation = dom::ChannelInterpretation::Speakers; + mChannelCountMode = ChannelCountMode::Max; + mChannelInterpretation = ChannelInterpretation::Speakers; // AudioNodes are always producing data mHasCurrentData = true; MOZ_COUNT_CTOR(AudioNodeStream); @@ -79,8 +82,13 @@ public: // This consumes the contents of aData. aData will be emptied after this returns. void SetRawArrayData(nsTArray& aData); void SetChannelMixingParameters(uint32_t aNumberOfChannels, - dom::ChannelCountMode aChannelCountMoe, - dom::ChannelInterpretation aChannelInterpretation); + ChannelCountMode aChannelCountMoe, + ChannelInterpretation aChannelInterpretation); + ChannelInterpretation GetChannelInterpretation() + { + return mChannelInterpretation; + } + void SetAudioParamHelperStream() { MOZ_ASSERT(!mAudioParamStream, "Can only do this once"); @@ -93,9 +101,9 @@ public: void SetStreamTimeParameterImpl(uint32_t aIndex, MediaStream* aRelativeToStream, double aStreamTime); void SetChannelMixingParametersImpl(uint32_t aNumberOfChannels, - dom::ChannelCountMode aChannelCountMoe, - dom::ChannelInterpretation aChannelInterpretation); - virtual void ProduceOutput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) MOZ_OVERRIDE; + ChannelCountMode aChannelCountMoe, + ChannelInterpretation aChannelInterpretation); + virtual void ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) MOZ_OVERRIDE; TrackTicks GetCurrentPosition(); bool IsAudioParamStream() const { @@ -171,8 +179,8 @@ protected: // The number of input channels that this stream requires. 0 means don't care. uint32_t mNumberOfInputChannels; // The mixing modes - dom::ChannelCountMode mChannelCountMode; - dom::ChannelInterpretation mChannelInterpretation; + ChannelCountMode mChannelCountMode; + ChannelInterpretation mChannelInterpretation; // Whether the stream should be marked as finished as soon // as the current time range has been computed block by block. bool mMarkAsFinishedAfterThisBlock; diff --git a/content/media/AudioSegment.h b/content/media/AudioSegment.h index 563f0f76437..a09e96bbaa4 100644 --- a/content/media/AudioSegment.h +++ b/content/media/AudioSegment.h @@ -99,6 +99,7 @@ struct AudioChunk { mDuration = aDuration; mVolume = 1.0f; } + int ChannelCount() const { return mChannelData.Length(); } TrackTicks mDuration; // in frames within the buffer nsRefPtr mBuffer; // the buffer object whose lifetime is managed; null means data is all zeroes diff --git a/content/media/MediaStreamGraph.cpp b/content/media/MediaStreamGraph.cpp index 9ea8cc57859..3a14b850700 100644 --- a/content/media/MediaStreamGraph.cpp +++ b/content/media/MediaStreamGraph.cpp @@ -1102,7 +1102,7 @@ MediaStreamGraphImpl::ProduceDataForStreamsBlockByBlock(uint32_t aStreamIndex, for (uint32_t i = aStreamIndex; i < mStreams.Length(); ++i) { ProcessedMediaStream* ps = mStreams[i]->AsProcessedStream(); if (ps) { - ps->ProduceOutput(t, next, (next == aTo) ? ProcessedMediaStream::ALLOW_FINISH : 0); + ps->ProcessInput(t, next, (next == aTo) ? ProcessedMediaStream::ALLOW_FINISH : 0); } } t = next; @@ -1211,7 +1211,7 @@ MediaStreamGraphImpl::RunThread() // Play stream contents. bool allBlockedForever = true; - // True when we've done ProduceOutput for all processed streams. + // True when we've done ProcessInput for all processed streams. bool doneAllProducing = false; // Figure out what each stream wants to do for (uint32_t i = 0; i < mStreams.Length(); ++i) { @@ -1237,8 +1237,8 @@ MediaStreamGraphImpl::RunThread() ticksProcessed += TimeToTicksRoundDown(n->SampleRate(), mStateComputedTime - prevComputedTime); doneAllProducing = true; } else { - ps->ProduceOutput(prevComputedTime, mStateComputedTime, - ProcessedMediaStream::ALLOW_FINISH); + ps->ProcessInput(prevComputedTime, mStateComputedTime, + ProcessedMediaStream::ALLOW_FINISH); NS_WARN_IF_FALSE(stream->mBuffer.GetEnd() >= GraphTimeToStreamTime(stream, mStateComputedTime), "Stream did not produce enough data"); diff --git a/content/media/MediaStreamGraph.h b/content/media/MediaStreamGraph.h index cbff7e4c3ad..299fff48d70 100644 --- a/content/media/MediaStreamGraph.h +++ b/content/media/MediaStreamGraph.h @@ -906,7 +906,7 @@ protected: /** * This stream processes zero or more input streams in parallel to produce * its output. The details of how the output is produced are handled by - * subclasses overriding the ProduceOutput method. + * subclasses overriding the ProcessInput method. */ class ProcessedMediaStream : public MediaStream { public: @@ -962,7 +962,7 @@ public: * This will be called on streams that have finished. Most stream types should * just return immediately if IsFinishedOnGraphThread(), but some may wish to * update internal state (see AudioNodeStream). - * ProduceOutput is allowed to call FinishOnGraphThread only if ALLOW_FINISH + * ProcessInput is allowed to call FinishOnGraphThread only if ALLOW_FINISH * is in aFlags. (This flag will be set when aTo >= mStateComputedTime, i.e. * when we've producing the last block of data we need to produce.) Otherwise * we can get into a situation where we've determined the stream should not @@ -972,7 +972,7 @@ public: enum { ALLOW_FINISH = 0x01 }; - virtual void ProduceOutput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) = 0; + virtual void ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) = 0; void SetAutofinishImpl(bool aAutofinish) { mAutofinish = aAutofinish; } /** @@ -1065,7 +1065,7 @@ public: * Dispatches a runnable that will run on the main thread after all * main-thread stream state has been next updated. * Should only be called during MediaStreamListener callbacks or during - * ProcessedMediaStream::ProduceOutput(). + * ProcessedMediaStream::ProcessInput(). */ void DispatchToMainThreadAfterStreamStateUpdate(already_AddRefed aRunnable) { diff --git a/content/media/TrackUnionStream.h b/content/media/TrackUnionStream.h index 18dad814887..c3abb6ccbab 100644 --- a/content/media/TrackUnionStream.h +++ b/content/media/TrackUnionStream.h @@ -39,7 +39,7 @@ public: } ProcessedMediaStream::RemoveInput(aPort); } - virtual void ProduceOutput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) MOZ_OVERRIDE + virtual void ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) MOZ_OVERRIDE { if (IsFinishedOnGraphThread()) { return; diff --git a/content/media/mediasource/MediaSource.cpp b/content/media/mediasource/MediaSource.cpp index 04499bc3817..624ee6f2c0b 100644 --- a/content/media/mediasource/MediaSource.cpp +++ b/content/media/mediasource/MediaSource.cpp @@ -30,9 +30,9 @@ class JSObject; #ifdef PR_LOGGING PRLogModuleInfo* gMediaSourceLog; -#define LOG(type, msg) PR_LOG(gMediaSourceLog, type, msg) +#define MSE_DEBUG(...) PR_LOG(gMediaSourceLog, PR_LOG_DEBUG, (__VA_ARGS__)) #else -#define LOG(type, msg) +#define MSE_DEBUG(...) #endif // Arbitrary limit. @@ -40,6 +40,47 @@ static const unsigned int MAX_SOURCE_BUFFERS = 16; namespace mozilla { +static const char* const gMediaSourceTypes[6] = { + "video/webm", + "audio/webm", + "video/mp4", + "audio/mp4", + "audio/mpeg", + nullptr +}; + +static nsresult +IsTypeSupported(const nsAString& aType) +{ + if (aType.IsEmpty()) { + return NS_ERROR_DOM_INVALID_ACCESS_ERR; + } + // TODO: Further restrict this to formats in the spec. + nsContentTypeParser parser(aType); + nsAutoString mimeType; + nsresult rv = parser.GetType(mimeType); + if (NS_FAILED(rv)) { + return NS_ERROR_DOM_NOT_SUPPORTED_ERR; + } + bool found = false; + for (uint32_t i = 0; gMediaSourceTypes[i]; ++i) { + if (mimeType.EqualsASCII(gMediaSourceTypes[i])) { + found = true; + break; + } + } + if (!found) { + return NS_ERROR_DOM_NOT_SUPPORTED_ERR; + } + // Check aType against HTMLMediaElement list of MIME types. Since we've + // already restricted the container format, this acts as a specific check + // of any specified "codecs" parameter of aType. + if (dom::HTMLMediaElement::GetCanPlay(aType) == CANPLAY_NO) { + return NS_ERROR_DOM_NOT_SUPPORTED_ERR; + } + return NS_OK; +} + namespace dom { /* static */ already_AddRefed @@ -103,7 +144,9 @@ MediaSource::SetDuration(double aDuration, ErrorResult& aRv) already_AddRefed MediaSource::AddSourceBuffer(const nsAString& aType, ErrorResult& aRv) { - if (!IsTypeSupportedInternal(aType, aRv)) { + nsresult rv = mozilla::IsTypeSupported(aType); + if (NS_FAILED(rv)) { + aRv.Throw(rv); return nullptr; } if (mSourceBuffers->Length() >= MAX_SOURCE_BUFFERS) { @@ -116,15 +159,15 @@ MediaSource::AddSourceBuffer(const nsAString& aType, ErrorResult& aRv) } nsContentTypeParser parser(aType); nsAutoString mimeType; - nsresult rv = parser.GetType(mimeType); + rv = parser.GetType(mimeType); if (NS_FAILED(rv)) { aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); return nullptr; } nsRefPtr sourceBuffer = new SourceBuffer(this, NS_ConvertUTF16toUTF8(mimeType)); mSourceBuffers->Append(sourceBuffer); - LOG(PR_LOG_DEBUG, ("%p AddSourceBuffer(Type=%s) -> %p", this, - NS_ConvertUTF16toUTF8(mimeType).get(), sourceBuffer.get())); + MSE_DEBUG("%p AddSourceBuffer(Type=%s) -> %p", this, + NS_ConvertUTF16toUTF8(mimeType).get(), sourceBuffer.get()); return sourceBuffer.forget(); } @@ -165,21 +208,45 @@ MediaSource::EndOfStream(const Optional& aError, Er aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); return; } - EndOfStreamInternal(aError, aRv); + + SetReadyState(MediaSourceReadyState::Ended); + mSourceBuffers->Ended(); + if (!aError.WasPassed()) { + // TODO: + // Run duration change algorithm. + // DurationChange(highestDurationOfSourceBuffers, aRv); + // if (aRv.Failed()) { + // return; + // } + // Notify media element that all data is now available. + return; + } + switch (aError.Value()) { + case MediaSourceEndOfStreamError::Network: + // TODO: If media element has a readyState of: + // HAVE_NOTHING -> run resource fetch algorithm + // > HAVE_NOTHING -> run "interrupted" steps of resource fetch + break; + case MediaSourceEndOfStreamError::Decode: + // TODO: If media element has a readyState of: + // HAVE_NOTHING -> run "unsupported" steps of resource fetch + // > HAVE_NOTHING -> run "corrupted" steps of resource fetch + break; + default: + aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); + } } /* static */ bool -MediaSource::IsTypeSupported(const GlobalObject& aGlobal, - const nsAString& aType) +MediaSource::IsTypeSupported(const GlobalObject&, const nsAString& aType) { - ErrorResult unused; - return IsTypeSupportedInternal(aType, unused); + return NS_SUCCEEDED(mozilla::IsTypeSupported(aType)); } bool MediaSource::Attach(MediaSourceDecoder* aDecoder) { - LOG(PR_LOG_DEBUG, ("%p Attaching decoder %p owner %p", this, aDecoder, aDecoder->GetOwner())); + MSE_DEBUG("%p Attaching decoder %p owner %p", this, aDecoder, aDecoder->GetOwner()); MOZ_ASSERT(aDecoder); if (mReadyState != MediaSourceReadyState::Closed) { return false; @@ -193,7 +260,7 @@ MediaSource::Attach(MediaSourceDecoder* aDecoder) void MediaSource::Detach() { - LOG(PR_LOG_DEBUG, ("%p Detaching decoder %p owner %p", this, mDecoder.get(), mDecoder->GetOwner())); + MSE_DEBUG("%p Detaching decoder %p owner %p", this, mDecoder.get(), mDecoder->GetOwner()); MOZ_ASSERT(mDecoder); mDecoder->DetachMediaSource(); mDecoder = nullptr; @@ -253,14 +320,14 @@ MediaSource::SetReadyState(MediaSourceReadyState aState) void MediaSource::DispatchSimpleEvent(const char* aName) { - LOG(PR_LOG_DEBUG, ("%p Dispatching event %s to MediaSource", this, aName)); + MSE_DEBUG("%p Dispatching event %s to MediaSource", this, aName); DispatchTrustedEvent(NS_ConvertUTF8toUTF16(aName)); } void MediaSource::QueueAsyncSimpleEvent(const char* aName) { - LOG(PR_LOG_DEBUG, ("%p Queuing event %s to MediaSource", this, aName)); + MSE_DEBUG("%p Queuing event %s to MediaSource", this, aName); nsCOMPtr event = new AsyncEventRunner(this, aName); NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); } @@ -283,82 +350,6 @@ MediaSource::DurationChange(double aNewDuration, ErrorResult& aRv) // TODO: Update media element's duration and run element's duration change algorithm. } -void -MediaSource::EndOfStreamInternal(const Optional& aError, ErrorResult& aRv) -{ - SetReadyState(MediaSourceReadyState::Ended); - mSourceBuffers->Ended(); - if (!aError.WasPassed()) { - // TODO: - // Run duration change algorithm. - // DurationChange(highestDurationOfSourceBuffers, aRv); - // if (aRv.Failed()) { - // return; - // } - // Notify media element that all data is now available. - return; - } - switch (aError.Value()) { - case MediaSourceEndOfStreamError::Network: - // TODO: If media element has a readyState of: - // HAVE_NOTHING -> run resource fetch algorithm - // > HAVE_NOTHING -> run "interrupted" steps of resource fetch - break; - case MediaSourceEndOfStreamError::Decode: - // TODO: If media element has a readyState of: - // HAVE_NOTHING -> run "unsupported" steps of resource fetch - // > HAVE_NOTHING -> run "corrupted" steps of resource fetch - break; - default: - aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); - } -} - -static const char* const gMediaSourceTypes[6] = { - "video/webm", - "audio/webm", - "video/mp4", - "audio/mp4", - "audio/mpeg", - nullptr -}; - -/* static */ bool -MediaSource::IsTypeSupportedInternal(const nsAString& aType, ErrorResult& aRv) -{ - if (aType.IsEmpty()) { - aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); - return false; - } - // TODO: Further restrict this to formats in the spec. - nsContentTypeParser parser(aType); - nsAutoString mimeType; - nsresult rv = parser.GetType(mimeType); - if (NS_FAILED(rv)) { - aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); - return false; - } - bool found = false; - for (uint32_t i = 0; gMediaSourceTypes[i]; ++i) { - if (mimeType.EqualsASCII(gMediaSourceTypes[i])) { - found = true; - break; - } - } - if (!found) { - aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); - return false; - } - // Check aType against HTMLMediaElement list of MIME types. Since we've - // already restricted the container format, this acts as a specific check - // of any specified "codecs" parameter of aType. - if (HTMLMediaElement::GetCanPlay(aType) == CANPLAY_NO) { - aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); - return false; - } - return true; -} - nsPIDOMWindow* MediaSource::GetParentObject() const { diff --git a/content/media/mediasource/MediaSource.h b/content/media/mediasource/MediaSource.h index beb56a6327c..8e1e5132aee 100644 --- a/content/media/mediasource/MediaSource.h +++ b/content/media/mediasource/MediaSource.h @@ -60,8 +60,7 @@ public: void RemoveSourceBuffer(SourceBuffer& aSourceBuffer, ErrorResult& aRv); void EndOfStream(const Optional& aError, ErrorResult& aRv); - static bool IsTypeSupported(const GlobalObject& aGlobal, - const nsAString& aType); + static bool IsTypeSupported(const GlobalObject&, const nsAString& aType); /** End WebIDL Methods. */ NS_DECL_ISUPPORTS_INHERITED @@ -98,9 +97,6 @@ private: void QueueAsyncSimpleEvent(const char* aName); void DurationChange(double aNewDuration, ErrorResult& aRv); - void EndOfStreamInternal(const Optional& aError, ErrorResult& aRv); - - static bool IsTypeSupportedInternal(const nsAString& aType, ErrorResult& aRv); double mDuration; diff --git a/content/media/mediasource/MediaSourceDecoder.cpp b/content/media/mediasource/MediaSourceDecoder.cpp index 9c2d1e6c76d..9e1e18706fe 100644 --- a/content/media/mediasource/MediaSourceDecoder.cpp +++ b/content/media/mediasource/MediaSourceDecoder.cpp @@ -23,9 +23,9 @@ #ifdef PR_LOGGING extern PRLogModuleInfo* gMediaSourceLog; -#define LOG(type, msg) PR_LOG(gMediaSourceLog, type, msg) +#define MSE_DEBUG(...) PR_LOG(gMediaSourceLog, PR_LOG_DEBUG, (__VA_ARGS__)) #else -#define LOG(type, msg) +#define MSE_DEBUG(...) #endif namespace mozilla { @@ -202,7 +202,7 @@ MediaSourceDecoder::CreateSubDecoder(const nsACString& aType) ReentrantMonitorAutoEnter mon(GetReentrantMonitor()); mDecoders.AppendElement(decoder); mReaders.AppendElement(reader); - LOG(PR_LOG_DEBUG, ("Registered subdecoder %p subreader %p", decoder.get(), reader.get())); + MSE_DEBUG("Registered subdecoder %p subreader %p", decoder.get(), reader.get()); mon.NotifyAll(); decoder->SetReader(reader.forget()); @@ -221,7 +221,7 @@ MediaSourceReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags) MediaDecoderReader* reader = readers[i]; MediaInfo mi; nsresult rv = reader->ReadMetadata(&mi, aTags); - LOG(PR_LOG_DEBUG, ("ReadMetadata on SB reader %p", reader)); + MSE_DEBUG("ReadMetadata on SB reader %p", reader); if (NS_FAILED(rv)) { return rv; } diff --git a/content/media/mediasource/SourceBuffer.cpp b/content/media/mediasource/SourceBuffer.cpp index 70fac92df35..6e74013ffe5 100644 --- a/content/media/mediasource/SourceBuffer.cpp +++ b/content/media/mediasource/SourceBuffer.cpp @@ -26,9 +26,9 @@ class JSObject; #ifdef PR_LOGGING extern PRLogModuleInfo* gMediaSourceLog; -#define LOG(type, msg) PR_LOG(gMediaSourceLog, type, msg) +#define MSE_DEBUG(...) PR_LOG(gMediaSourceLog, PR_LOG_DEBUG, (__VA_ARGS__)) #else -#define LOG(type, msg) +#define MSE_DEBUG(...) #endif namespace mozilla { @@ -289,14 +289,14 @@ SourceBuffer::WrapObject(JSContext* aCx, JS::Handle aScope) void SourceBuffer::DispatchSimpleEvent(const char* aName) { - LOG(PR_LOG_DEBUG, ("%p Dispatching event %s to SourceBuffer", this, aName)); + MSE_DEBUG("%p Dispatching event %s to SourceBuffer", this, aName); DispatchTrustedEvent(NS_ConvertUTF8toUTF16(aName)); } void SourceBuffer::QueueAsyncSimpleEvent(const char* aName) { - LOG(PR_LOG_DEBUG, ("%p Queuing event %s to SourceBuffer", this, aName)); + MSE_DEBUG("%p Queuing event %s to SourceBuffer", this, aName); nsCOMPtr event = new AsyncEventRunner(this, aName); NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); } @@ -339,7 +339,7 @@ SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aR } // TODO: Run coded frame eviction algorithm. // TODO: Test buffer full flag. - LOG(PR_LOG_DEBUG, ("%p Append(ArrayBuffer=%u)", this, aLength)); + MSE_DEBUG("%p Append(ArrayBuffer=%u)", this, aLength); StartUpdating(); // XXX: For future reference: NDA call must run on the main thread. mDecoder->NotifyDataArrived(reinterpret_cast(aData), diff --git a/content/media/mediasource/SourceBufferList.cpp b/content/media/mediasource/SourceBufferList.cpp index ccd27e9d545..778fc98677b 100644 --- a/content/media/mediasource/SourceBufferList.cpp +++ b/content/media/mediasource/SourceBufferList.cpp @@ -22,9 +22,9 @@ class JSObject; #ifdef PR_LOGGING extern PRLogModuleInfo* gMediaSourceLog; -#define LOG(type, msg) PR_LOG(gMediaSourceLog, type, msg) +#define MSE_DEBUG(...) PR_LOG(gMediaSourceLog, PR_LOG_DEBUG, (__VA_ARGS__)) #else -#define LOG(type, msg) +#define MSE_DEBUG(...) #endif namespace mozilla { @@ -122,14 +122,14 @@ SourceBufferList::Ended() void SourceBufferList::DispatchSimpleEvent(const char* aName) { - LOG(PR_LOG_DEBUG, ("%p Dispatching event %s to SourceBufferList", this, aName)); + MSE_DEBUG("%p Dispatching event %s to SourceBufferList", this, aName); DispatchTrustedEvent(NS_ConvertUTF8toUTF16(aName)); } void SourceBufferList::QueueAsyncSimpleEvent(const char* aName) { - LOG(PR_LOG_DEBUG, ("%p Queuing event %s to SourceBufferList", this, aName)); + MSE_DEBUG("%p Queuing event %s to SourceBufferList", this, aName); nsCOMPtr event = new AsyncEventRunner(this, aName); NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); } diff --git a/content/media/mediasource/SourceBufferResource.cpp b/content/media/mediasource/SourceBufferResource.cpp index 0ea3f69b17b..f53361e7621 100644 --- a/content/media/mediasource/SourceBufferResource.cpp +++ b/content/media/mediasource/SourceBufferResource.cpp @@ -16,9 +16,9 @@ #ifdef PR_LOGGING extern PRLogModuleInfo* gMediaSourceLog; -#define LOG(type, msg) PR_LOG(gMediaSourceLog, type, msg) +#define MSE_DEBUG(...) PR_LOG(gMediaSourceLog, PR_LOG_DEBUG, (__VA_ARGS__)) #else -#define LOG(type, msg) +#define MSE_DEBUG(...) #endif namespace mozilla { @@ -33,7 +33,7 @@ nsresult SourceBufferResource::Close() { ReentrantMonitorAutoEnter mon(mMonitor); - LOG(PR_LOG_DEBUG, ("%p SBR::Close", this)); + MSE_DEBUG("%p SBR::Close", this); //MOZ_ASSERT(!mClosed); mClosed = true; mon.NotifyAll(); @@ -49,20 +49,20 @@ SourceBufferResource::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes) while (blockingRead && !mEnded && mOffset + aCount > static_cast(GetLength())) { - LOG(PR_LOG_DEBUG, ("%p SBR::Read waiting for data", this)); + MSE_DEBUG("%p SBR::Read waiting for data", this); mon.Wait(); } uint32_t available = GetLength() - mOffset; uint32_t count = std::min(aCount, available); if (!PR_GetEnv("MOZ_QUIET")) { - LOG(PR_LOG_DEBUG, ("%p SBR::Read aCount=%u length=%u offset=%u " - "available=%u count=%u, blocking=%d bufComplete=%d", - this, aCount, GetLength(), mOffset, available, count, - blockingRead, mEnded)); + MSE_DEBUG("%p SBR::Read aCount=%u length=%u offset=%u " + "available=%u count=%u, blocking=%d bufComplete=%d", + this, aCount, GetLength(), mOffset, available, count, + blockingRead, mEnded); } if (available == 0) { - LOG(PR_LOG_DEBUG, ("%p SBR::Read EOF", this)); + MSE_DEBUG("%p SBR::Read EOF", this); *aBytes = 0; return NS_OK; } @@ -160,7 +160,7 @@ SourceBufferResource::Ended() SourceBufferResource::~SourceBufferResource() { MOZ_COUNT_DTOR(SourceBufferResource); - LOG(PR_LOG_DEBUG, ("%p SBR::~SBR", this)); + MSE_DEBUG("%p SBR::~SBR", this); } SourceBufferResource::SourceBufferResource(nsIPrincipal* aPrincipal, @@ -173,7 +173,7 @@ SourceBufferResource::SourceBufferResource(nsIPrincipal* aPrincipal, , mEnded(false) { MOZ_COUNT_CTOR(SourceBufferResource); - LOG(PR_LOG_DEBUG, ("%p SBR::SBR()", this)); + MSE_DEBUG("%p SBR::SBR()", this); } } // namespace mozilla diff --git a/content/media/webaudio/AnalyserNode.cpp b/content/media/webaudio/AnalyserNode.cpp index da764314f6b..61c54aa18ac 100644 --- a/content/media/webaudio/AnalyserNode.cpp +++ b/content/media/webaudio/AnalyserNode.cpp @@ -57,10 +57,10 @@ public: MOZ_ASSERT(NS_IsMainThread()); } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) MOZ_OVERRIDE + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) MOZ_OVERRIDE { *aOutput = aInput; diff --git a/content/media/webaudio/AudioBufferSourceNode.cpp b/content/media/webaudio/AudioBufferSourceNode.cpp index 3257b0a07f9..6a11e072533 100644 --- a/content/media/webaudio/AudioBufferSourceNode.cpp +++ b/content/media/webaudio/AudioBufferSourceNode.cpp @@ -423,10 +423,10 @@ public: UpdateResampler(outRate, aChannels); } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) { if (!mBuffer || !mBufferEnd) { aOutput->SetNull(WEBAUDIO_BLOCK_SIZE); diff --git a/content/media/webaudio/AudioDestinationNode.cpp b/content/media/webaudio/AudioDestinationNode.cpp index 9ce18c21d23..e03eff993ee 100644 --- a/content/media/webaudio/AudioDestinationNode.cpp +++ b/content/media/webaudio/AudioDestinationNode.cpp @@ -52,10 +52,10 @@ public: } } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) MOZ_OVERRIDE + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) MOZ_OVERRIDE { // Do this just for the sake of political correctness; this output // will not go anywhere. @@ -165,10 +165,10 @@ public: { } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) MOZ_OVERRIDE + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) MOZ_OVERRIDE { *aOutput = aInput; aOutput->mVolume *= mVolume; diff --git a/content/media/webaudio/AudioProcessingEvent.cpp b/content/media/webaudio/AudioProcessingEvent.cpp index 977abe929fa..7fa885d9dae 100644 --- a/content/media/webaudio/AudioProcessingEvent.cpp +++ b/content/media/webaudio/AudioProcessingEvent.cpp @@ -11,19 +11,19 @@ namespace mozilla { namespace dom { -NS_IMPL_CYCLE_COLLECTION_INHERITED_3(AudioProcessingEvent, nsDOMEvent, +NS_IMPL_CYCLE_COLLECTION_INHERITED_3(AudioProcessingEvent, Event, mInputBuffer, mOutputBuffer, mNode) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(AudioProcessingEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) -NS_IMPL_ADDREF_INHERITED(AudioProcessingEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(AudioProcessingEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(AudioProcessingEvent, Event) +NS_IMPL_RELEASE_INHERITED(AudioProcessingEvent, Event) AudioProcessingEvent::AudioProcessingEvent(ScriptProcessorNode* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, aEvent) + : Event(aOwner, aPresContext, aEvent) , mPlaybackTime(0.0) , mNode(aOwner) { diff --git a/content/media/webaudio/AudioProcessingEvent.h b/content/media/webaudio/AudioProcessingEvent.h index 78762ed9407..471476d7623 100644 --- a/content/media/webaudio/AudioProcessingEvent.h +++ b/content/media/webaudio/AudioProcessingEvent.h @@ -7,14 +7,14 @@ #ifndef AudioProcessingEvent_h_ #define AudioProcessingEvent_h_ -#include "nsDOMEvent.h" #include "AudioBuffer.h" #include "ScriptProcessorNode.h" +#include "mozilla/dom/Event.h" namespace mozilla { namespace dom { -class AudioProcessingEvent : public nsDOMEvent +class AudioProcessingEvent : public Event { public: AudioProcessingEvent(ScriptProcessorNode* aOwner, @@ -22,8 +22,8 @@ public: WidgetEvent* aEvent); NS_DECL_ISUPPORTS_INHERITED - NS_FORWARD_TO_NSDOMEVENT - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AudioProcessingEvent, nsDOMEvent) + NS_FORWARD_TO_EVENT + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AudioProcessingEvent, Event) virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aScope) MOZ_OVERRIDE; diff --git a/content/media/webaudio/BiquadFilterNode.cpp b/content/media/webaudio/BiquadFilterNode.cpp index da6cfd5e4bd..b7baade5c37 100644 --- a/content/media/webaudio/BiquadFilterNode.cpp +++ b/content/media/webaudio/BiquadFilterNode.cpp @@ -137,10 +137,10 @@ public: } } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) MOZ_OVERRIDE + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) MOZ_OVERRIDE { float inputBuffer[WEBAUDIO_BLOCK_SIZE]; diff --git a/content/media/webaudio/ChannelMergerNode.cpp b/content/media/webaudio/ChannelMergerNode.cpp index 606e060adb2..ac8bd934cd4 100644 --- a/content/media/webaudio/ChannelMergerNode.cpp +++ b/content/media/webaudio/ChannelMergerNode.cpp @@ -23,10 +23,10 @@ public: MOZ_ASSERT(NS_IsMainThread()); } - virtual void ProduceAudioBlocksOnPorts(AudioNodeStream* aStream, - const OutputChunks& aInput, - OutputChunks& aOutput, - bool* aFinished) MOZ_OVERRIDE + virtual void ProcessBlocksOnPorts(AudioNodeStream* aStream, + const OutputChunks& aInput, + OutputChunks& aOutput, + bool* aFinished) MOZ_OVERRIDE { MOZ_ASSERT(aInput.Length() >= 1, "Should have one or more input ports"); diff --git a/content/media/webaudio/ChannelSplitterNode.cpp b/content/media/webaudio/ChannelSplitterNode.cpp index 2436f539ee2..47424aef6c6 100644 --- a/content/media/webaudio/ChannelSplitterNode.cpp +++ b/content/media/webaudio/ChannelSplitterNode.cpp @@ -23,10 +23,10 @@ public: MOZ_ASSERT(NS_IsMainThread()); } - virtual void ProduceAudioBlocksOnPorts(AudioNodeStream* aStream, - const OutputChunks& aInput, - OutputChunks& aOutput, - bool* aFinished) MOZ_OVERRIDE + virtual void ProcessBlocksOnPorts(AudioNodeStream* aStream, + const OutputChunks& aInput, + OutputChunks& aOutput, + bool* aFinished) MOZ_OVERRIDE { MOZ_ASSERT(aInput.Length() == 1, "Should only have one input port"); diff --git a/content/media/webaudio/ConvolverNode.cpp b/content/media/webaudio/ConvolverNode.cpp index cea23389aaa..e6b457fb5dc 100644 --- a/content/media/webaudio/ConvolverNode.cpp +++ b/content/media/webaudio/ConvolverNode.cpp @@ -101,10 +101,10 @@ public: mNormalize, mSampleRate); } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) { if (!mReverb) { *aOutput = aInput; diff --git a/content/media/webaudio/DelayBuffer.cpp b/content/media/webaudio/DelayBuffer.cpp new file mode 100644 index 00000000000..be6eaf43ba9 --- /dev/null +++ b/content/media/webaudio/DelayBuffer.cpp @@ -0,0 +1,249 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "DelayBuffer.h" + +#include "mozilla/PodOperations.h" +#include "AudioChannelFormat.h" +#include "AudioNodeEngine.h" + +namespace mozilla { + +void +DelayBuffer::Write(const AudioChunk& aInputChunk) +{ + // We must have a reference to the buffer if there are channels + MOZ_ASSERT(aInputChunk.IsNull() == !aInputChunk.mChannelData.Length()); + + if (!EnsureBuffer()) { + return; + } + + if (mCurrentChunk == mLastReadChunk) { + mLastReadChunk = -1; // invalidate cache + } + mChunks[mCurrentChunk] = aInputChunk; +} + +void +DelayBuffer::Read(const double aPerFrameDelays[WEBAUDIO_BLOCK_SIZE], + AudioChunk* aOutputChunk, + ChannelInterpretation aChannelInterpretation) +{ + int chunkCount = mChunks.Length(); + if (!chunkCount) { + aOutputChunk->SetNull(WEBAUDIO_BLOCK_SIZE); + return; + } + + // Find the maximum number of contributing channels to determine the output + // channel count that retains all signal information. Buffered blocks will + // be upmixed if necessary. + // + // First find the range of "delay" offsets backwards from the current + // position. Note that these may be negative for frames that are after the + // current position (including i). + double minDelay = aPerFrameDelays[0]; + double maxDelay = minDelay; + for (unsigned i = 1; i < WEBAUDIO_BLOCK_SIZE; ++i) { + minDelay = std::min(minDelay, aPerFrameDelays[i] - i); + maxDelay = std::max(maxDelay, aPerFrameDelays[i] - i); + } + + // Now find the chunks touched by this range and check their channel counts. + int oldestChunk = ChunkForDelay(int(maxDelay) + 1); + int youngestChunk = ChunkForDelay(minDelay); + + uint32_t channelCount = 0; + for (int i = oldestChunk; true; i = (i + 1) % chunkCount) { + channelCount = GetAudioChannelsSuperset(channelCount, + mChunks[i].ChannelCount()); + if (i == youngestChunk) { + break; + } + } + + if (channelCount) { + AllocateAudioBlock(channelCount, aOutputChunk); + ReadChannels(aPerFrameDelays, aOutputChunk, + 0, channelCount, aChannelInterpretation); + } else { + aOutputChunk->SetNull(WEBAUDIO_BLOCK_SIZE); + } + + // Remember currentDelayFrames for the next ProcessBlock call + mCurrentDelay = aPerFrameDelays[WEBAUDIO_BLOCK_SIZE - 1]; +} + +void +DelayBuffer::ReadChannel(const double aPerFrameDelays[WEBAUDIO_BLOCK_SIZE], + const AudioChunk* aOutputChunk, uint32_t aChannel, + ChannelInterpretation aChannelInterpretation) +{ + if (!mChunks.Length()) { + float* outputChannel = static_cast + (const_cast(aOutputChunk->mChannelData[aChannel])); + PodZero(outputChannel, WEBAUDIO_BLOCK_SIZE); + return; + } + + ReadChannels(aPerFrameDelays, aOutputChunk, + aChannel, 1, aChannelInterpretation); +} + +void +DelayBuffer::ReadChannels(const double aPerFrameDelays[WEBAUDIO_BLOCK_SIZE], + const AudioChunk* aOutputChunk, + uint32_t aFirstChannel, uint32_t aNumChannelsToRead, + ChannelInterpretation aChannelInterpretation) +{ + uint32_t totalChannelCount = aOutputChunk->mChannelData.Length(); + uint32_t readChannelsEnd = aFirstChannel + aNumChannelsToRead; + MOZ_ASSERT(readChannelsEnd <= totalChannelCount); + + if (mUpmixChannels.Length() != totalChannelCount) { + mLastReadChunk = -1; // invalidate cache + } + + float* const* outputChannels = reinterpret_cast + (const_cast(aOutputChunk->mChannelData.Elements())); + for (uint32_t channel = aFirstChannel; + channel < readChannelsEnd; ++channel) { + PodZero(outputChannels[channel], WEBAUDIO_BLOCK_SIZE); + } + + for (unsigned i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) { + double currentDelay = aPerFrameDelays[i]; + MOZ_ASSERT(currentDelay >= 0.0); + MOZ_ASSERT(currentDelay <= static_cast(mMaxDelayTicks)); + + // Interpolate two input frames in case the read position does not match + // an integer index. + // Use the larger delay, for the older frame, first, as this is more + // likely to use the cached upmixed channel arrays. + int floorDelay = int(currentDelay); + double interpolationFactor = currentDelay - floorDelay; + int positions[2]; + positions[1] = PositionForDelay(floorDelay) + i; + positions[0] = positions[1] - 1; + + for (unsigned tick = 0; tick < ArrayLength(positions); ++tick) { + int readChunk = ChunkForPosition(positions[tick]); + // mVolume is not set on default initialized chunks so handle null + // chunks specially. + if (!mChunks[readChunk].IsNull()) { + int readOffset = OffsetForPosition(positions[tick]); + UpdateUpmixChannels(readChunk, totalChannelCount, + aChannelInterpretation); + double multiplier = interpolationFactor * mChunks[readChunk].mVolume; + for (uint32_t channel = aFirstChannel; + channel < readChannelsEnd; ++channel) { + outputChannels[channel][i] += multiplier * + static_cast(mUpmixChannels[channel])[readOffset]; + } + } + + interpolationFactor = 1.0 - interpolationFactor; + } + } +} + +void +DelayBuffer::Read(double aDelayTicks, AudioChunk* aOutputChunk, + ChannelInterpretation aChannelInterpretation) +{ + const bool firstTime = mCurrentDelay < 0.0; + double currentDelay = firstTime ? aDelayTicks : mCurrentDelay; + + double computedDelay[WEBAUDIO_BLOCK_SIZE]; + + for (unsigned i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) { + // If the value has changed, smoothly approach it + currentDelay += (aDelayTicks - currentDelay) * mSmoothingRate; + computedDelay[i] = currentDelay; + } + + Read(computedDelay, aOutputChunk, aChannelInterpretation); +} + +bool +DelayBuffer::EnsureBuffer() +{ + if (mChunks.Length() == 0) { + // The length of the buffer is at least one block greater than the maximum + // delay so that writing an input block does not overwrite the block that + // would subsequently be read at maximum delay. Also round up to the next + // block size, so that no block of writes will need to wrap. + const int chunkCount = (mMaxDelayTicks + 2 * WEBAUDIO_BLOCK_SIZE - 1) >> + WEBAUDIO_BLOCK_SIZE_BITS; + if (!mChunks.SetLength(chunkCount)) { + return false; + } + + mLastReadChunk = -1; + } + return true; +} + +int +DelayBuffer::PositionForDelay(int aDelay) { + // Adding mChunks.Length() keeps integers positive for defined and + // appropriate bitshift, remainder, and bitwise operations. + return ((mCurrentChunk + mChunks.Length()) * WEBAUDIO_BLOCK_SIZE) - aDelay; +} + +int +DelayBuffer::ChunkForPosition(int aPosition) +{ + MOZ_ASSERT(aPosition >= 0); + return (aPosition >> WEBAUDIO_BLOCK_SIZE_BITS) % mChunks.Length(); +} + +int +DelayBuffer::OffsetForPosition(int aPosition) +{ + MOZ_ASSERT(aPosition >= 0); + return aPosition & (WEBAUDIO_BLOCK_SIZE - 1); +} + +int +DelayBuffer::ChunkForDelay(int aDelay) +{ + return ChunkForPosition(PositionForDelay(aDelay)); +} + +void +DelayBuffer::UpdateUpmixChannels(int aNewReadChunk, uint32_t aChannelCount, + ChannelInterpretation aChannelInterpretation) +{ + if (aNewReadChunk == mLastReadChunk) { + MOZ_ASSERT(mUpmixChannels.Length() == aChannelCount); + return; + } + + static const float silenceChannel[WEBAUDIO_BLOCK_SIZE] = {}; + + mLastReadChunk = aNewReadChunk; + // Missing assignment operator is bug 976927 + mUpmixChannels.ReplaceElementsAt(0, mUpmixChannels.Length(), + mChunks[aNewReadChunk].mChannelData); + MOZ_ASSERT(mUpmixChannels.Length() <= aChannelCount); + if (mUpmixChannels.Length() < aChannelCount) { + if (aChannelInterpretation == ChannelInterpretation::Speakers) { + AudioChannelsUpMix(&mUpmixChannels, aChannelCount, silenceChannel); + MOZ_ASSERT(mUpmixChannels.Length() == aChannelCount, + "We called GetAudioChannelsSuperset to avoid this"); + } else { + // Fill up the remaining channels with zeros + for (uint32_t channel = mUpmixChannels.Length(); + channel < aChannelCount; ++channel) { + mUpmixChannels.AppendElement(silenceChannel); + } + } + } +} + +} // mozilla diff --git a/content/media/webaudio/DelayBuffer.h b/content/media/webaudio/DelayBuffer.h new file mode 100644 index 00000000000..fff74dc9980 --- /dev/null +++ b/content/media/webaudio/DelayBuffer.h @@ -0,0 +1,96 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef DelayBuffer_h_ +#define DelayBuffer_h_ + +#include "nsTArray.h" +#include "AudioSegment.h" +#include "mozilla/dom/AudioNodeBinding.h" // for ChannelInterpretation + +namespace mozilla { + +class DelayBuffer { + typedef dom::ChannelInterpretation ChannelInterpretation; + +public: + // See WebAudioUtils::ComputeSmoothingRate() for frame to frame exponential + // |smoothingRate| multiplier. + DelayBuffer(int aMaxDelayTicks, double aSmoothingRate) + : mSmoothingRate(aSmoothingRate) + , mCurrentDelay(-1.0) + , mMaxDelayTicks(aMaxDelayTicks) + , mCurrentChunk(0) + // mLastReadChunk is initialized in EnsureBuffer + { + } + + // Write a WEBAUDIO_BLOCK_SIZE block for aChannelCount channels. + void Write(const AudioChunk& aInputChunk); + + // Read a block with an array of delays, in ticks, for each sample frame. + // Each delay must be > 0 and < MaxDelayTicks(). + void Read(const double aPerFrameDelays[WEBAUDIO_BLOCK_SIZE], + AudioChunk* aOutputChunk, + ChannelInterpretation aChannelInterpretation); + // Read a block with a constant delay, which will be smoothed with the + // previous delay. The delay must be > 0 and < MaxDelayTicks(). + void Read(double aDelayTicks, AudioChunk* aOutputChunk, + ChannelInterpretation aChannelInterpretation); + + // Read into one of the channels of aOutputChunk, given an array of + // delays in ticks. This is useful when delays are different on different + // channels. aOutputChunk must have already been allocated with at least as + // many channels as were in any of the blocks passed to Write(). + void ReadChannel(const double aPerFrameDelays[WEBAUDIO_BLOCK_SIZE], + const AudioChunk* aOutputChunk, uint32_t aChannel, + ChannelInterpretation aChannelInterpretation); + + // Advance the buffer pointer + void NextBlock() + { + mCurrentChunk = (mCurrentChunk + 1) % mChunks.Length(); + } + + void Reset() { + mChunks.Clear(); + mCurrentDelay = -1.0; + }; + + int MaxDelayTicks() const { return mMaxDelayTicks; } + +private: + void ReadChannels(const double aPerFrameDelays[WEBAUDIO_BLOCK_SIZE], + const AudioChunk* aOutputChunk, + uint32_t aFirstChannel, uint32_t aNumChannelsToRead, + ChannelInterpretation aChannelInterpretation); + bool EnsureBuffer(); + int PositionForDelay(int aDelay); + int ChunkForPosition(int aPosition); + int OffsetForPosition(int aPosition); + int ChunkForDelay(int aDelay); + void UpdateUpmixChannels(int aNewReadChunk, uint32_t channelCount, + ChannelInterpretation aChannelInterpretation); + + // Circular buffer for capturing delayed samples. + FallibleTArray mChunks; + // Cache upmixed channel arrays. + nsAutoTArray mUpmixChannels; + double mSmoothingRate; + // Current delay, in fractional ticks + double mCurrentDelay; + // Maximum delay, in ticks + int mMaxDelayTicks; + // The current position in the circular buffer. The next write will be to + // this chunk, and the next read may begin before this chunk. + int mCurrentChunk; + // The chunk owning the pointers in mUpmixChannels + int mLastReadChunk; +}; + +} // mozilla + +#endif // DelayBuffer_h_ diff --git a/content/media/webaudio/DelayNode.cpp b/content/media/webaudio/DelayNode.cpp index b54f8b0bcca..97607af1f3f 100644 --- a/content/media/webaudio/DelayNode.cpp +++ b/content/media/webaudio/DelayNode.cpp @@ -10,7 +10,7 @@ #include "AudioNodeStream.h" #include "AudioDestinationNode.h" #include "WebAudioUtils.h" -#include "DelayProcessor.h" +#include "DelayBuffer.h" #include "PlayingRefChangeHandler.h" namespace mozilla { @@ -30,16 +30,17 @@ class DelayNodeEngine : public AudioNodeEngine typedef PlayingRefChangeHandler PlayingRefChanged; public: DelayNodeEngine(AudioNode* aNode, AudioDestinationNode* aDestination, - int aMaxDelayFrames) + int aMaxDelayTicks) : AudioNodeEngine(aNode) , mSource(nullptr) , mDestination(static_cast (aDestination->Stream())) // Keep the default value in sync with the default value in DelayNode::DelayNode. , mDelay(0.f) // Use a smoothing range of 20ms - , mProcessor(aMaxDelayFrames, - WebAudioUtils::ComputeSmoothingRate(0.02, - mDestination->SampleRate())) + , mBuffer(aMaxDelayTicks, + WebAudioUtils::ComputeSmoothingRate(0.02, + mDestination->SampleRate())) + , mLastOutputPosition(-1) , mLeftOverData(INT32_MIN) { } @@ -72,18 +73,14 @@ public: } } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) MOZ_OVERRIDE { MOZ_ASSERT(mSource == aStream, "Invalid source stream"); MOZ_ASSERT(aStream->SampleRate() == mDestination->SampleRate()); - const uint32_t numChannels = aInput.IsNull() ? - mProcessor.BufferChannelCount() : - aInput.mChannelData.Length(); - if (!aInput.IsNull()) { if (mLeftOverData <= 0) { nsRefPtr refchanged = @@ -91,14 +88,14 @@ public: aStream->Graph()-> DispatchToMainThreadAfterStreamStateUpdate(refchanged.forget()); } - mLeftOverData = mProcessor.MaxDelayFrames(); + mLeftOverData = mBuffer.MaxDelayTicks(); } else if (mLeftOverData > 0) { mLeftOverData -= WEBAUDIO_BLOCK_SIZE; } else { if (mLeftOverData != INT32_MIN) { mLeftOverData = INT32_MIN; // Delete our buffered data now we no longer need it - mProcessor.Reset(); + mBuffer.Reset(); nsRefPtr refchanged = new PlayingRefChanged(aStream, PlayingRefChanged::RELEASE); @@ -109,56 +106,60 @@ public: return; } - AllocateAudioBlock(numChannels, aOutput); + mBuffer.Write(aInput); - AudioChunk input = aInput; - if (!aInput.IsNull() && aInput.mVolume != 1.0f) { - // Pre-multiply the input's volume - AllocateAudioBlock(numChannels, &input); - for (uint32_t i = 0; i < numChannels; ++i) { - const float* src = static_cast(aInput.mChannelData[i]); - float* dest = static_cast(const_cast(input.mChannelData[i])); - AudioBlockCopyChannelWithScale(src, aInput.mVolume, dest); - } + UpdateOutputBlock(aOutput); + mBuffer.NextBlock(); + } + + void UpdateOutputBlock(AudioChunk* aOutput) + { + TrackTicks tick = mSource->GetCurrentPosition(); + if (tick == mLastOutputPosition) { + return; // mLastChunks is already set on the stream } - const float* const* inputChannels = input.IsNull() ? nullptr : - reinterpret_cast(input.mChannelData.Elements()); - float* const* outputChannels = reinterpret_cast - (const_cast(aOutput->mChannelData.Elements())); - - - bool inCycle = aStream->AsProcessedStream()->InCycle(); - double sampleRate = aStream->SampleRate(); + mLastOutputPosition = tick; + bool inCycle = mSource->AsProcessedStream()->InCycle(); + double minDelay = inCycle ? static_cast(WEBAUDIO_BLOCK_SIZE) : 0.0; + double maxDelay = mBuffer.MaxDelayTicks(); + double sampleRate = mSource->SampleRate(); + ChannelInterpretation channelInterpretation = + mSource->GetChannelInterpretation(); if (mDelay.HasSimpleValue()) { // If this DelayNode is in a cycle, make sure the delay value is at least // one block. - float delayFrames = mDelay.GetValue() * sampleRate; - float delayFramesClamped = inCycle ? std::max(static_cast(WEBAUDIO_BLOCK_SIZE), delayFrames) : - delayFrames; - mProcessor.Process(delayFramesClamped, inputChannels, outputChannels, - numChannels, WEBAUDIO_BLOCK_SIZE); + double delayFrames = mDelay.GetValue() * sampleRate; + double delayFramesClamped = clamped(delayFrames, minDelay, maxDelay); + mBuffer.Read(delayFramesClamped, aOutput, channelInterpretation); } else { // Compute the delay values for the duration of the input AudioChunk // If this DelayNode is in a cycle, make sure the delay value is at least // one block. double computedDelay[WEBAUDIO_BLOCK_SIZE]; - TrackTicks tick = aStream->GetCurrentPosition(); for (size_t counter = 0; counter < WEBAUDIO_BLOCK_SIZE; ++counter) { - float delayAtTick = mDelay.GetValueAtTime(tick, counter) * sampleRate; - float delayAtTickClamped = inCycle ? std::max(static_cast(WEBAUDIO_BLOCK_SIZE), delayAtTick) : - delayAtTick; + double delayAtTick = mDelay.GetValueAtTime(tick, counter) * sampleRate; + double delayAtTickClamped = clamped(delayAtTick, minDelay, maxDelay); computedDelay[counter] = delayAtTickClamped; } - mProcessor.Process(computedDelay, inputChannels, outputChannels, - numChannels, WEBAUDIO_BLOCK_SIZE); + mBuffer.Read(computedDelay, aOutput, channelInterpretation); + } + } + + virtual void ProduceBlockBeforeInput(AudioChunk* aOutput) MOZ_OVERRIDE + { + if (mLeftOverData <= 0) { + aOutput->SetNull(WEBAUDIO_BLOCK_SIZE); + } else { + UpdateOutputBlock(aOutput); } } AudioNodeStream* mSource; AudioNodeStream* mDestination; AudioParamTimeline mDelay; - DelayProcessor mProcessor; + DelayBuffer mBuffer; + TrackTicks mLastOutputPosition; // How much data we have in our buffer which needs to be flushed out when our inputs // finish. int32_t mLeftOverData; diff --git a/content/media/webaudio/DelayProcessor.cpp b/content/media/webaudio/DelayProcessor.cpp deleted file mode 100644 index 3d36e749e5d..00000000000 --- a/content/media/webaudio/DelayProcessor.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "DelayProcessor.h" - -#include "mozilla/PodOperations.h" -#include "AudioSegment.h" - -namespace mozilla { - -void -DelayProcessor::Process(const double *aPerFrameDelays, - const float* const* aInputChannels, - float* const* aOutputChannels, - int aChannelCount, int aFramesToProcess) -{ - if (!EnsureBuffer(aChannelCount)) { - for (int channel = 0; channel < aChannelCount; ++channel) { - PodZero(aOutputChannels[channel], aFramesToProcess); - } - return; - } - - for (int channel = 0; channel < aChannelCount; ++channel) { - double currentDelayFrames = mCurrentDelay; - int writeIndex = mWriteIndex; - - float* buffer = mBuffer[channel].Elements(); - const uint32_t bufferLength = mBuffer[channel].Length(); - const float* input = aInputChannels ? aInputChannels[channel] : nullptr; - float* output = aOutputChannels[channel]; - - for (int i = 0; i < aFramesToProcess; ++i) { - currentDelayFrames = clamped(aPerFrameDelays[i], - 0.0, static_cast(mMaxDelayFrames)); - - // Write the input sample to the correct location in our buffer - buffer[writeIndex] = input ? input[i] : 0.0f; - - // Now, determine the correct read position. We adjust the read position to be - // from currentDelayFrames frames in the past. We also interpolate the two input - // frames in case the read position does not match an integer index. - double readPosition = writeIndex + bufferLength - currentDelayFrames; - if (readPosition >= bufferLength) { - readPosition -= bufferLength; - } - MOZ_ASSERT(readPosition >= 0.0, "Why are we reading before the beginning of the buffer?"); - - // Here is a the reason why readIndex1 and readIndex will never be out - // of bounds. The maximum value for bufferLength is - // 180 * AudioContext.samplerate (see AudioContext::CreateDelay). The - // maximum value for mCurrentDelay is 180.0, so initially readPosition - // cannot be more than bufferLength + a fraction less than 1. Then we - // take care of that case by subtracting bufferLength from it if needed. - // So, if |bufferLength-readPosition<1.0|, readIndex1 will end up being - // zero. If |1.0<=bufferLength-readPosition<2.0|, readIndex1 will be - // bufferLength-1 and readIndex2 will be 0. - int readIndex1 = int(readPosition); - int readIndex2 = (readIndex1 + 1) % bufferLength; - double interpolationFactor = readPosition - readIndex1; - - output[i] = (1.0 - interpolationFactor) * buffer[readIndex1] + - interpolationFactor * buffer[readIndex2]; - writeIndex = (writeIndex + 1) % bufferLength; - } - - // Remember currentDelayFrames and writeIndex for the next ProduceAudioBlock - // call when processing the last channel. - if (channel == aChannelCount - 1) { - mCurrentDelay = currentDelayFrames; - mWriteIndex = writeIndex; - } - } -} - -void -DelayProcessor::Process(double aDelayFrames, const float* const* aInputChannels, - float* const* aOutputChannels, int aChannelCount, - int aFramesToProcess) -{ - const bool firstTime = !mBuffer.Length(); - double currentDelay = firstTime ? aDelayFrames : mCurrentDelay; - - nsAutoTArray computedDelay; - computedDelay.SetLength(aFramesToProcess); - - for (int i = 0; i < aFramesToProcess; ++i) { - // If the value has changed, smoothly approach it - currentDelay += (aDelayFrames - currentDelay) * mSmoothingRate; - computedDelay[i] = currentDelay; - } - - Process(computedDelay.Elements(), aInputChannels, aOutputChannels, - aChannelCount, aFramesToProcess); -} - -bool -DelayProcessor::EnsureBuffer(uint32_t aNumberOfChannels) -{ - if (aNumberOfChannels == 0) { - return false; - } - if (mBuffer.Length() == 0) { - if (!mBuffer.SetLength(aNumberOfChannels)) { - return false; - } - // The length of the buffer is one greater than the maximum delay so that - // writing an input frame does not overwrite the frame that would - // subsequently be read at maximum delay. - const int numFrames = mMaxDelayFrames + 1; - for (uint32_t channel = 0; channel < aNumberOfChannels; ++channel) { - if (!mBuffer[channel].SetLength(numFrames)) { - return false; - } - PodZero(mBuffer[channel].Elements(), numFrames); - } - } else if (mBuffer.Length() != aNumberOfChannels) { - // TODO: Handle changes in the channel count - return false; - } - return true; -} - -} // mozilla diff --git a/content/media/webaudio/DelayProcessor.h b/content/media/webaudio/DelayProcessor.h deleted file mode 100644 index 291b83f3abf..00000000000 --- a/content/media/webaudio/DelayProcessor.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef DelayProcessor_h_ -#define DelayProcessor_h_ - -#include "nsTArray.h" - -namespace mozilla { - -class DelayProcessor { -public: - // See WebAudioUtils::ComputeSmoothingRate() for frame to frame exponential - // |smoothingRate| multiplier. - DelayProcessor(int aMaxDelayFrames, double aSmoothingRate) - : mSmoothingRate(aSmoothingRate) - , mCurrentDelay(0.) - , mMaxDelayFrames(aMaxDelayFrames) - , mWriteIndex(0) - { - } - - // Process with an array of delays, in frames, for each frame. - void Process(const double *aPerFrameDelays, - const float* const* aInputChannels, - float* const* aOutputChannels, - int aChannelCount, int aFramesToProcess); - - // Process with a constant delay, which will be smoothed with the previous - // delay. - void Process(double aDelayFrames, const float* const* aInputChannels, - float* const* aOutputChannels, int aChannelCount, - int aFramesToProcess); - - void Reset() { mBuffer.Clear(); }; - - int MaxDelayFrames() const { return mMaxDelayFrames; } - int BufferChannelCount() const { return mBuffer.Length(); } - -private: - bool EnsureBuffer(uint32_t aNumberOfChannels); - - // Circular buffer for capturing delayed samples. - AutoFallibleTArray, 2> mBuffer; - double mSmoothingRate; - // Current delay, in fractional frames - double mCurrentDelay; - // Maximum delay, in frames - int mMaxDelayFrames; - // Write index for the buffer, to write the frames to the correct index of the buffer - // given the current delay. - int mWriteIndex; -}; - -} // mozilla - -#endif // DelayProcessor_h_ diff --git a/content/media/webaudio/DynamicsCompressorNode.cpp b/content/media/webaudio/DynamicsCompressorNode.cpp index 5ea9fb89da0..050e9d372b1 100644 --- a/content/media/webaudio/DynamicsCompressorNode.cpp +++ b/content/media/webaudio/DynamicsCompressorNode.cpp @@ -93,10 +93,10 @@ public: } } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) MOZ_OVERRIDE + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) MOZ_OVERRIDE { if (aInput.IsNull()) { // Just output silence diff --git a/content/media/webaudio/GainNode.cpp b/content/media/webaudio/GainNode.cpp index 39c3cf09d13..3d93ff37403 100644 --- a/content/media/webaudio/GainNode.cpp +++ b/content/media/webaudio/GainNode.cpp @@ -58,10 +58,10 @@ public: } } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) { MOZ_ASSERT(mSource == aStream, "Invalid source stream"); diff --git a/content/media/webaudio/MediaStreamAudioDestinationNode.cpp b/content/media/webaudio/MediaStreamAudioDestinationNode.cpp index 475ce3a0962..fd55614fb88 100644 --- a/content/media/webaudio/MediaStreamAudioDestinationNode.cpp +++ b/content/media/webaudio/MediaStreamAudioDestinationNode.cpp @@ -36,10 +36,10 @@ public: MOZ_ASSERT(mOutputStream); } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) MOZ_OVERRIDE + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) MOZ_OVERRIDE { *aOutput = aInput; StreamBuffer::Track* track = mOutputStream->EnsureTrack(MEDIA_STREAM_DEST_TRACK_ID, diff --git a/content/media/webaudio/OfflineAudioCompletionEvent.cpp b/content/media/webaudio/OfflineAudioCompletionEvent.cpp index 6c01c512cbb..10e953ab31c 100644 --- a/content/media/webaudio/OfflineAudioCompletionEvent.cpp +++ b/content/media/webaudio/OfflineAudioCompletionEvent.cpp @@ -11,19 +11,19 @@ namespace mozilla { namespace dom { -NS_IMPL_CYCLE_COLLECTION_INHERITED_1(OfflineAudioCompletionEvent, nsDOMEvent, +NS_IMPL_CYCLE_COLLECTION_INHERITED_1(OfflineAudioCompletionEvent, Event, mRenderedBuffer) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(OfflineAudioCompletionEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) -NS_IMPL_ADDREF_INHERITED(OfflineAudioCompletionEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(OfflineAudioCompletionEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(OfflineAudioCompletionEvent, Event) +NS_IMPL_RELEASE_INHERITED(OfflineAudioCompletionEvent, Event) OfflineAudioCompletionEvent::OfflineAudioCompletionEvent(AudioContext* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, aEvent) + : Event(aOwner, aPresContext, aEvent) { SetIsDOMBinding(); } diff --git a/content/media/webaudio/OfflineAudioCompletionEvent.h b/content/media/webaudio/OfflineAudioCompletionEvent.h index 6d64d3d1d50..af1449a48b8 100644 --- a/content/media/webaudio/OfflineAudioCompletionEvent.h +++ b/content/media/webaudio/OfflineAudioCompletionEvent.h @@ -7,15 +7,15 @@ #ifndef OfflineAudioCompletionEvent_h_ #define OfflineAudioCompletionEvent_h_ -#include "nsDOMEvent.h" #include "AudioBuffer.h" +#include "mozilla/dom/Event.h" namespace mozilla { namespace dom { class AudioContext; -class OfflineAudioCompletionEvent : public nsDOMEvent +class OfflineAudioCompletionEvent : public Event { public: OfflineAudioCompletionEvent(AudioContext* aOwner, @@ -23,8 +23,8 @@ public: WidgetEvent* aEvent); NS_DECL_ISUPPORTS_INHERITED - NS_FORWARD_TO_NSDOMEVENT - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(OfflineAudioCompletionEvent, nsDOMEvent) + NS_FORWARD_TO_EVENT + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(OfflineAudioCompletionEvent, Event) virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aScope) MOZ_OVERRIDE; diff --git a/content/media/webaudio/OscillatorNode.cpp b/content/media/webaudio/OscillatorNode.cpp index d3b731239c2..26bbaf134e9 100644 --- a/content/media/webaudio/OscillatorNode.cpp +++ b/content/media/webaudio/OscillatorNode.cpp @@ -410,10 +410,10 @@ public: aOutput->SetNull(WEBAUDIO_BLOCK_SIZE); } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) MOZ_OVERRIDE + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) MOZ_OVERRIDE { MOZ_ASSERT(mSource == aStream, "Invalid source stream"); diff --git a/content/media/webaudio/PannerNode.cpp b/content/media/webaudio/PannerNode.cpp index 02ad7623fe0..95a89465ab4 100644 --- a/content/media/webaudio/PannerNode.cpp +++ b/content/media/webaudio/PannerNode.cpp @@ -133,10 +133,10 @@ public: } } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool *aFinished) MOZ_OVERRIDE + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool *aFinished) MOZ_OVERRIDE { if (aInput.IsNull()) { // mLeftOverData != INT_MIN means that the panning model was HRTF and a @@ -279,8 +279,6 @@ void PannerNodeEngine::HRTFPanningFunction(const AudioChunk& aInput, AudioChunk* aOutput) { - int numChannels = aInput.mChannelData.Length(); - // The output of this node is always stereo, no matter what the inputs are. AllocateAudioBlock(2, aOutput); @@ -289,20 +287,9 @@ PannerNodeEngine::HRTFPanningFunction(const AudioChunk& aInput, AudioChunk input = aInput; // Gain is applied before the delay and convolution of the HRTF - if (!input.IsNull()) { - float gain = ComputeConeGain() * ComputeDistanceGain() * aInput.mVolume; - if (gain != 1.0f) { - AllocateAudioBlock(numChannels, &input); - for (int i = 0; i < numChannels; ++i) { - const float* src = static_cast(aInput.mChannelData[i]); - float* dest = - static_cast(const_cast(input.mChannelData[i])); - AudioBlockCopyChannelWithScale(src, gain, dest); - } - } - } + input.mVolume *= ComputeConeGain() * ComputeDistanceGain(); - mHRTFPanner->pan(azimuth, elevation, &input, aOutput, WEBAUDIO_BLOCK_SIZE); + mHRTFPanner->pan(azimuth, elevation, &input, aOutput); } void diff --git a/content/media/webaudio/ScriptProcessorNode.cpp b/content/media/webaudio/ScriptProcessorNode.cpp index 1e5b1b8541b..69405fcfc29 100644 --- a/content/media/webaudio/ScriptProcessorNode.cpp +++ b/content/media/webaudio/ScriptProcessorNode.cpp @@ -239,10 +239,10 @@ public: mSource = aSource; } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) MOZ_OVERRIDE + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) MOZ_OVERRIDE { MutexAutoLock lock(NodeMutex()); diff --git a/content/media/webaudio/WaveShaperNode.cpp b/content/media/webaudio/WaveShaperNode.cpp index 71e041d2cb1..43a5d5fb765 100644 --- a/content/media/webaudio/WaveShaperNode.cpp +++ b/content/media/webaudio/WaveShaperNode.cpp @@ -202,10 +202,10 @@ public: } } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) { uint32_t channelCount = aInput.mChannelData.Length(); if (!mCurve.Length() || !channelCount) { diff --git a/content/media/webaudio/blink/HRTFPanner.cpp b/content/media/webaudio/blink/HRTFPanner.cpp index 8bc86b6ccfd..1c02e0294b7 100644 --- a/content/media/webaudio/blink/HRTFPanner.cpp +++ b/content/media/webaudio/blink/HRTFPanner.cpp @@ -27,11 +27,10 @@ #include "FFTConvolver.h" #include "HRTFDatabase.h" -#include "WebAudioUtils.h" using namespace std; using namespace mozilla; -using mozilla::dom::WebAudioUtils; +using dom::ChannelInterpretation; namespace WebCore { @@ -40,7 +39,7 @@ namespace WebCore { const double MaxDelayTimeSeconds = 0.002; const int UninitializedAzimuth = -1; -const unsigned RenderingQuantum = 128; +const unsigned RenderingQuantum = WEBAUDIO_BLOCK_SIZE; HRTFPanner::HRTFPanner(float sampleRate, mozilla::TemporaryRef databaseLoader) : m_databaseLoader(databaseLoader) @@ -55,10 +54,7 @@ HRTFPanner::HRTFPanner(float sampleRate, mozilla::TemporaryRefIsNull() ? 0 : inputBus->mChannelData.Length(); MOZ_ASSERT(numInputChannels <= 2); - MOZ_ASSERT(framesToProcess <= inputBus->mDuration); + MOZ_ASSERT(inputBus->mDuration == WEBAUDIO_BLOCK_SIZE); - bool isOutputGood = outputBus && outputBus->mChannelData.Length() == 2 && framesToProcess <= outputBus->mDuration; + bool isOutputGood = outputBus && outputBus->mChannelData.Length() == 2 && outputBus->mDuration == WEBAUDIO_BLOCK_SIZE; MOZ_ASSERT(isOutputGood); if (!isOutputGood) { @@ -151,11 +146,7 @@ void HRTFPanner::pan(double desiredAzimuth, double elevation, const AudioChunk* // Normally, we'll just be dealing with mono sources. // If we have a stereo input, implement stereo panning with left source processed by left HRTF, and right source by right HRTF. - // Get source and destination pointers. - const float* sourceL = numInputChannels > 0 ? - static_cast(inputBus->mChannelData[0]) : nullptr; - const float* sourceR = numInputChannels > 1 ? - static_cast(inputBus->mChannelData[1]) : sourceL; + // Get destination pointers. float* destinationL = static_cast(const_cast(outputBus->mChannelData[0])); float* destinationR = @@ -197,95 +188,94 @@ void HRTFPanner::pan(double desiredAzimuth, double elevation, const AudioChunk* } } - // This algorithm currently requires that we process in power-of-two size chunks at least RenderingQuantum. - MOZ_ASSERT(framesToProcess && 0 == (framesToProcess & (framesToProcess - 1))); - MOZ_ASSERT(framesToProcess >= RenderingQuantum); + // Get the HRTFKernels and interpolated delays. + HRTFKernel* kernelL1; + HRTFKernel* kernelR1; + HRTFKernel* kernelL2; + HRTFKernel* kernelR2; + double frameDelayL1; + double frameDelayR1; + double frameDelayL2; + double frameDelayR2; + database->getKernelsFromAzimuthElevation(azimuthBlend, m_azimuthIndex1, m_elevation1, kernelL1, kernelR1, frameDelayL1, frameDelayR1); + database->getKernelsFromAzimuthElevation(azimuthBlend, m_azimuthIndex2, m_elevation2, kernelL2, kernelR2, frameDelayL2, frameDelayR2); - const unsigned framesPerSegment = RenderingQuantum; - const unsigned numberOfSegments = framesToProcess / framesPerSegment; + bool areKernelsGood = kernelL1 && kernelR1 && kernelL2 && kernelR2; + MOZ_ASSERT(areKernelsGood); + if (!areKernelsGood) { + outputBus->SetNull(outputBus->mDuration); + return; + } - for (unsigned segment = 0; segment < numberOfSegments; ++segment) { - // Get the HRTFKernels and interpolated delays. - HRTFKernel* kernelL1; - HRTFKernel* kernelR1; - HRTFKernel* kernelL2; - HRTFKernel* kernelR2; - double frameDelayL1; - double frameDelayR1; - double frameDelayL2; - double frameDelayR2; - database->getKernelsFromAzimuthElevation(azimuthBlend, m_azimuthIndex1, m_elevation1, kernelL1, kernelR1, frameDelayL1, frameDelayR1); - database->getKernelsFromAzimuthElevation(azimuthBlend, m_azimuthIndex2, m_elevation2, kernelL2, kernelR2, frameDelayL2, frameDelayR2); + MOZ_ASSERT(frameDelayL1 / sampleRate() < MaxDelayTimeSeconds && frameDelayR1 / sampleRate() < MaxDelayTimeSeconds); + MOZ_ASSERT(frameDelayL2 / sampleRate() < MaxDelayTimeSeconds && frameDelayR2 / sampleRate() < MaxDelayTimeSeconds); - bool areKernelsGood = kernelL1 && kernelR1 && kernelL2 && kernelR2; - MOZ_ASSERT(areKernelsGood); - if (!areKernelsGood) { - outputBus->SetNull(outputBus->mDuration); - return; + // Crossfade inter-aural delays based on transitions. + double frameDelaysL[WEBAUDIO_BLOCK_SIZE]; + double frameDelaysR[WEBAUDIO_BLOCK_SIZE]; + { + float x = m_crossfadeX; + float incr = m_crossfadeIncr; + for (unsigned i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) { + frameDelaysL[i] = (1 - x) * frameDelayL1 + x * frameDelayL2; + frameDelaysR[i] = (1 - x) * frameDelayR1 + x * frameDelayR2; + x += incr; + } + } + + // First run through delay lines for inter-aural time difference. + m_delayLine.Write(*inputBus); + // "Speakers" means a mono input is read into both outputs (with possibly + // different delays). + m_delayLine.ReadChannel(frameDelaysL, outputBus, 0, + ChannelInterpretation::Speakers); + m_delayLine.ReadChannel(frameDelaysR, outputBus, 1, + ChannelInterpretation::Speakers); + m_delayLine.NextBlock(); + + bool needsCrossfading = m_crossfadeIncr; + + // Have the convolvers render directly to the final destination if we're not cross-fading. + float* convolutionDestinationL1 = needsCrossfading ? m_tempL1.Elements() : destinationL; + float* convolutionDestinationR1 = needsCrossfading ? m_tempR1.Elements() : destinationR; + float* convolutionDestinationL2 = needsCrossfading ? m_tempL2.Elements() : destinationL; + float* convolutionDestinationR2 = needsCrossfading ? m_tempR2.Elements() : destinationR; + + // Now do the convolutions. + // Note that we avoid doing convolutions on both sets of convolvers if we're not currently cross-fading. + + if (m_crossfadeSelection == CrossfadeSelection1 || needsCrossfading) { + m_convolverL1.process(kernelL1->fftFrame(), destinationL, convolutionDestinationL1, WEBAUDIO_BLOCK_SIZE); + m_convolverR1.process(kernelR1->fftFrame(), destinationR, convolutionDestinationR1, WEBAUDIO_BLOCK_SIZE); + } + + if (m_crossfadeSelection == CrossfadeSelection2 || needsCrossfading) { + m_convolverL2.process(kernelL2->fftFrame(), destinationL, convolutionDestinationL2, WEBAUDIO_BLOCK_SIZE); + m_convolverR2.process(kernelR2->fftFrame(), destinationR, convolutionDestinationR2, WEBAUDIO_BLOCK_SIZE); + } + + if (needsCrossfading) { + // Apply linear cross-fade. + float x = m_crossfadeX; + float incr = m_crossfadeIncr; + for (unsigned i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) { + destinationL[i] = (1 - x) * convolutionDestinationL1[i] + x * convolutionDestinationL2[i]; + destinationR[i] = (1 - x) * convolutionDestinationR1[i] + x * convolutionDestinationR2[i]; + x += incr; } + // Update cross-fade value from local. + m_crossfadeX = x; - MOZ_ASSERT(frameDelayL1 / sampleRate() < MaxDelayTimeSeconds && frameDelayR1 / sampleRate() < MaxDelayTimeSeconds); - MOZ_ASSERT(frameDelayL2 / sampleRate() < MaxDelayTimeSeconds && frameDelayR2 / sampleRate() < MaxDelayTimeSeconds); - - // Crossfade inter-aural delays based on transitions. - double frameDelayL = (1 - m_crossfadeX) * frameDelayL1 + m_crossfadeX * frameDelayL2; - double frameDelayR = (1 - m_crossfadeX) * frameDelayR1 + m_crossfadeX * frameDelayR2; - - // Calculate the source and destination pointers for the current segment. - unsigned offset = segment * framesPerSegment; - const float* segmentSourceL = sourceL ? sourceL + offset : nullptr; - const float* segmentSourceR = sourceR ? sourceR + offset : nullptr; - float* segmentDestinationL = destinationL + offset; - float* segmentDestinationR = destinationR + offset; - - // First run through delay lines for inter-aural time difference. - m_delayLineL.Process(frameDelayL, &segmentSourceL, &segmentDestinationL, 1, framesPerSegment); - m_delayLineR.Process(frameDelayR, &segmentSourceR, &segmentDestinationR, 1, framesPerSegment); - - bool needsCrossfading = m_crossfadeIncr; - - // Have the convolvers render directly to the final destination if we're not cross-fading. - float* convolutionDestinationL1 = needsCrossfading ? m_tempL1.Elements() : segmentDestinationL; - float* convolutionDestinationR1 = needsCrossfading ? m_tempR1.Elements() : segmentDestinationR; - float* convolutionDestinationL2 = needsCrossfading ? m_tempL2.Elements() : segmentDestinationL; - float* convolutionDestinationR2 = needsCrossfading ? m_tempR2.Elements() : segmentDestinationR; - - // Now do the convolutions. - // Note that we avoid doing convolutions on both sets of convolvers if we're not currently cross-fading. - - if (m_crossfadeSelection == CrossfadeSelection1 || needsCrossfading) { - m_convolverL1.process(kernelL1->fftFrame(), segmentDestinationL, convolutionDestinationL1, framesPerSegment); - m_convolverR1.process(kernelR1->fftFrame(), segmentDestinationR, convolutionDestinationR1, framesPerSegment); - } - - if (m_crossfadeSelection == CrossfadeSelection2 || needsCrossfading) { - m_convolverL2.process(kernelL2->fftFrame(), segmentDestinationL, convolutionDestinationL2, framesPerSegment); - m_convolverR2.process(kernelR2->fftFrame(), segmentDestinationR, convolutionDestinationR2, framesPerSegment); - } - - if (needsCrossfading) { - // Apply linear cross-fade. - float x = m_crossfadeX; - float incr = m_crossfadeIncr; - for (unsigned i = 0; i < framesPerSegment; ++i) { - segmentDestinationL[i] = (1 - x) * convolutionDestinationL1[i] + x * convolutionDestinationL2[i]; - segmentDestinationR[i] = (1 - x) * convolutionDestinationR1[i] + x * convolutionDestinationR2[i]; - x += incr; - } - // Update cross-fade value from local. - m_crossfadeX = x; - - if (m_crossfadeIncr > 0 && fabs(m_crossfadeX - 1) < m_crossfadeIncr) { - // We've fully made the crossfade transition from 1 -> 2. - m_crossfadeSelection = CrossfadeSelection2; - m_crossfadeX = 1; - m_crossfadeIncr = 0; - } else if (m_crossfadeIncr < 0 && fabs(m_crossfadeX) < -m_crossfadeIncr) { - // We've fully made the crossfade transition from 2 -> 1. - m_crossfadeSelection = CrossfadeSelection1; - m_crossfadeX = 0; - m_crossfadeIncr = 0; - } + if (m_crossfadeIncr > 0 && fabs(m_crossfadeX - 1) < m_crossfadeIncr) { + // We've fully made the crossfade transition from 1 -> 2. + m_crossfadeSelection = CrossfadeSelection2; + m_crossfadeX = 1; + m_crossfadeIncr = 0; + } else if (m_crossfadeIncr < 0 && fabs(m_crossfadeX) < -m_crossfadeIncr) { + // We've fully made the crossfade transition from 2 -> 1. + m_crossfadeSelection = CrossfadeSelection1; + m_crossfadeX = 0; + m_crossfadeIncr = 0; } } } @@ -299,7 +289,7 @@ int HRTFPanner::maxTailFrames() const // tailTime of the DelayKernel and the tailTime of the FFTConvolver. // The FFTConvolver has a tail time of fftSize(), including latency of // fftSize()/2. - return m_delayLineL.MaxDelayFrames() + fftSize(); + return m_delayLine.MaxDelayTicks() + fftSize(); } } // namespace WebCore diff --git a/content/media/webaudio/blink/HRTFPanner.h b/content/media/webaudio/blink/HRTFPanner.h index 6c725a8a521..5ea8a429ad6 100644 --- a/content/media/webaudio/blink/HRTFPanner.h +++ b/content/media/webaudio/blink/HRTFPanner.h @@ -26,7 +26,7 @@ #define HRTFPanner_h #include "FFTConvolver.h" -#include "DelayProcessor.h" +#include "DelayBuffer.h" namespace mozilla { struct AudioChunk; @@ -43,8 +43,8 @@ public: HRTFPanner(float sampleRate, mozilla::TemporaryRef databaseLoader); ~HRTFPanner(); - // framesToProcess must be a power of 2 and greater than 128 - void pan(double azimuth, double elevation, const AudioChunk* inputBus, AudioChunk* outputBus, mozilla::TrackTicks framesToProcess); + // chunk durations must be 128 + void pan(double azimuth, double elevation, const AudioChunk* inputBus, AudioChunk* outputBus); void reset(); size_t fftSize() const { return m_convolverL1.fftSize(); } @@ -99,8 +99,7 @@ private: FFTConvolver m_convolverL2; FFTConvolver m_convolverR2; - mozilla::DelayProcessor m_delayLineL; - mozilla::DelayProcessor m_delayLineR; + mozilla::DelayBuffer m_delayLine; AudioFloatArray m_tempL1; AudioFloatArray m_tempR1; diff --git a/content/media/webaudio/moz.build b/content/media/webaudio/moz.build index 84f634eec5b..cb5a206c4f3 100644 --- a/content/media/webaudio/moz.build +++ b/content/media/webaudio/moz.build @@ -62,8 +62,8 @@ UNIFIED_SOURCES += [ 'ChannelMergerNode.cpp', 'ChannelSplitterNode.cpp', 'ConvolverNode.cpp', + 'DelayBuffer.cpp', 'DelayNode.cpp', - 'DelayProcessor.cpp', 'DynamicsCompressorNode.cpp', 'FFTBlock.cpp', 'GainNode.cpp', diff --git a/content/media/webaudio/test/mochitest.ini b/content/media/webaudio/test/mochitest.ini index 7735d075c55..ae7e68dfb16 100644 --- a/content/media/webaudio/test/mochitest.ini +++ b/content/media/webaudio/test/mochitest.ini @@ -79,6 +79,7 @@ support-files = [test_decodeMultichannel.html] [test_delayNode.html] [test_delayNodeAtMax.html] +[test_delayNodeChannelChanges.html] [test_delayNodeCycles.html] [test_delayNodeSmallMaxDelay.html] [test_delayNodeTailIncrease.html] diff --git a/content/media/webaudio/test/test_delayNodeChannelChanges.html b/content/media/webaudio/test/test_delayNodeChannelChanges.html new file mode 100644 index 00000000000..a95625a9ab6 --- /dev/null +++ b/content/media/webaudio/test/test_delayNodeChannelChanges.html @@ -0,0 +1,97 @@ + + + + test DelayNode channel count changes + + + + + +
+
+
+ + diff --git a/content/svg/content/src/SVGTransform.cpp b/content/svg/content/src/SVGTransform.cpp index a45e1adf66e..53ad781372b 100644 --- a/content/svg/content/src/SVGTransform.cpp +++ b/content/svg/content/src/SVGTransform.cpp @@ -12,6 +12,7 @@ #include "nsError.h" #include "nsSVGAnimatedTransformList.h" #include "nsSVGAttrTearoffTable.h" +#include "mozilla/DebugOnly.h" namespace { const double kRadPerDegree = 2.0 * M_PI / 360.0; diff --git a/content/xml/content/src/nsXMLElement.cpp b/content/xml/content/src/nsXMLElement.cpp index 6d04b07d782..bfd9bcc840d 100644 --- a/content/xml/content/src/nsXMLElement.cpp +++ b/content/xml/content/src/nsXMLElement.cpp @@ -84,7 +84,7 @@ nsXMLElement::NodeInfoChanged(nsINodeInfo* aOldNodeInfo) const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(aOldNodeInfo->GetIDAttributeAtom()); if (attrVal) { - doc->RemoveFromIdTable(this, attrVal->GetAtomValue()); + RemoveFromIdTable(attrVal->GetAtomValue()); } } @@ -104,7 +104,7 @@ nsXMLElement::NodeInfoChanged(nsINodeInfo* aOldNodeInfo) NS_ASSERTION(attrVal->Type() == nsAttrValue::eAtom, "Should be atom by now"); if (doc) { - doc->AddToIdTable(this, attrVal->GetAtomValue()); + AddToIdTable(attrVal->GetAtomValue()); } } } @@ -133,28 +133,3 @@ nsXMLElement::ParseAttribute(int32_t aNamespaceID, return false; } - -nsresult -nsXMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, - nsIContent* aBindingParent, - bool aCompileEventHandlers) -{ - nsresult rv = Element::BindToTree(aDocument, aParent, - aBindingParent, - aCompileEventHandlers); - NS_ENSURE_SUCCESS(rv, rv); - - if (aDocument && HasID() && !GetBindingParent()) { - aDocument->AddToIdTable(this, DoGetID()); - } - - return NS_OK; -} - -void -nsXMLElement::UnbindFromTree(bool aDeep, bool aNullParent) -{ - RemoveFromIdTable(); - - return Element::UnbindFromTree(aDeep, aNullParent); -} diff --git a/content/xml/content/src/nsXMLElement.h b/content/xml/content/src/nsXMLElement.h index 6f570e7679b..a497699c184 100644 --- a/content/xml/content/src/nsXMLElement.h +++ b/content/xml/content/src/nsXMLElement.h @@ -37,10 +37,6 @@ public: // nsIContent interface methods virtual nsIAtom *GetIDAttributeName() const MOZ_OVERRIDE; virtual nsIAtom* DoGetID() const MOZ_OVERRIDE; - virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, - nsIContent* aBindingParent, - bool aCompileEventHandlers) MOZ_OVERRIDE; - virtual void UnbindFromTree(bool aDeep, bool aNullParent) MOZ_OVERRIDE; virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, bool aNotify) MOZ_OVERRIDE; virtual bool ParseAttribute(int32_t aNamespaceID, diff --git a/content/xul/content/src/nsXULElement.cpp b/content/xul/content/src/nsXULElement.cpp index f73dd865e81..4ab593ef8ae 100644 --- a/content/xul/content/src/nsXULElement.cpp +++ b/content/xul/content/src/nsXULElement.cpp @@ -58,7 +58,7 @@ #include "nsIXULTemplateBuilder.h" #include "nsLayoutCID.h" #include "nsContentCID.h" -#include "nsDOMEvent.h" +#include "mozilla/dom/Event.h" #include "nsRDFCID.h" #include "nsStyleConsts.h" #include "nsXPIDLString.h" @@ -1185,7 +1185,7 @@ nsXULElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor) // handling. nsCOMPtr domEvent = aVisitor.mDOMEvent; while (domEvent) { - nsDOMEvent* event = domEvent->InternalDOMEvent(); + Event* event = domEvent->InternalDOMEvent(); NS_ENSURE_STATE(!SameCOMIdentity(event->GetOriginalTarget(), commandContent)); nsCOMPtr commandEvent = diff --git a/content/xul/content/src/nsXULPopupListener.cpp b/content/xul/content/src/nsXULPopupListener.cpp index 4f124a14785..f9dd3c09895 100644 --- a/content/xul/content/src/nsXULPopupListener.cpp +++ b/content/xul/content/src/nsXULPopupListener.cpp @@ -32,6 +32,7 @@ #include "nsHTMLReflowState.h" #include "nsIObjectLoadingContent.h" #include "mozilla/Preferences.h" +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() #include "mozilla/dom/EventTarget.h" #include "mozilla/dom/FragmentOrElement.h" @@ -43,7 +44,6 @@ #include "nsViewManager.h" #include "nsError.h" #include "nsMenuFrame.h" -#include "nsDOMEvent.h" using namespace mozilla; using namespace mozilla::dom; diff --git a/content/xul/document/src/XULDocument.cpp b/content/xul/document/src/XULDocument.cpp index 6129fe2c4fc..7df19b79a21 100644 --- a/content/xul/document/src/XULDocument.cpp +++ b/content/xul/document/src/XULDocument.cpp @@ -1720,6 +1720,7 @@ XULDocument::AddElementToDocumentPre(Element* aElement) // elements from prototypes. nsIAtom* id = aElement->GetID(); if (id) { + // FIXME: Shouldn't BindToTree take care of this? nsAutoScriptBlocker scriptBlocker; AddToIdTable(aElement, id); } @@ -1853,6 +1854,7 @@ XULDocument::RemoveSubtreeFromDocument(nsIContent* aContent) RemoveElementFromRefMap(aElement); nsIAtom* id = aElement->GetID(); if (id) { + // FIXME: Shouldn't UnbindFromTree take care of this? nsAutoScriptBlocker scriptBlocker; RemoveFromIdTable(aElement, id); } diff --git a/dom/base/Console.cpp b/dom/base/Console.cpp index 77678d04e07..f22ae0f9f93 100644 --- a/dom/base/Console.cpp +++ b/dom/base/Console.cpp @@ -1090,6 +1090,10 @@ Console::ProcessArguments(JSContext* aCx, } ++start; + if (start == end) { + output.Append('%'); + break; + } if (*start == '%') { output.Append(*start); @@ -1111,13 +1115,23 @@ Console::ProcessArguments(JSContext* aCx, integer = integer * 10 + *start - '0'; tmp.Append(*start); ++start; - } while (*start >= '0' && *start <= '9'); + } while (*start >= '0' && *start <= '9' && start != end); + } + + if (start == end) { + output.Append(tmp); + break; } if (*start == '.') { tmp.Append(*start); ++start; + if (start == end) { + output.Append(tmp); + break; + } + // '.' must be followed by a number. if (*start < '0' || *start > '9') { output.Append(tmp); @@ -1130,7 +1144,12 @@ Console::ProcessArguments(JSContext* aCx, mantissa = mantissa * 10 + *start - '0'; tmp.Append(*start); ++start; - } while (*start >= '0' && *start <= '9'); + } while (*start >= '0' && *start <= '9' && start != end); + + if (start == end) { + output.Append(tmp); + break; + } } char ch = *start; diff --git a/dom/base/MessagePort.cpp b/dom/base/MessagePort.cpp index 435569a6af9..80c5e44a95a 100644 --- a/dom/base/MessagePort.cpp +++ b/dom/base/MessagePort.cpp @@ -4,6 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "MessagePort.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/MessageChannel.h" #include "mozilla/dom/MessagePortBinding.h" #include "mozilla/dom/StructuredCloneTags.h" @@ -11,7 +12,6 @@ #include "nsContentUtils.h" #include "nsEventDispatcher.h" #include "nsPresContext.h" -#include "nsDOMEvent.h" #include "nsIDocument.h" #include "nsIDOMFile.h" @@ -55,24 +55,16 @@ class PostMessageRunnable : public nsRunnable NS_DECL_NSIRUNNABLE PostMessageRunnable() - : mMessage(nullptr) - , mMessageLen(0) { } ~PostMessageRunnable() { - // Ensure that the buffer is freed - if (mMessage) { - JSAutoStructuredCloneBuffer buffer; - buffer.adopt(mMessage, mMessageLen); - } } - void SetJSData(JSAutoStructuredCloneBuffer& aBuffer) + JSAutoStructuredCloneBuffer& Buffer() { - NS_ASSERTION(!mMessage && mMessageLen == 0, "Don't call twice!"); - aBuffer.steal(&mMessage, &mMessageLen); + return mBuffer; } bool StoreISupports(nsISupports* aSupports) @@ -89,8 +81,7 @@ class PostMessageRunnable : public nsRunnable private: nsRefPtr mPort; - uint64_t* mMessage; - size_t mMessageLen; + JSAutoStructuredCloneBuffer mBuffer; nsTArray > mSupportsArray; }; @@ -225,12 +216,6 @@ PostMessageRunnable::Run() { MOZ_ASSERT(mPort); - // Ensure that the buffer is freed even if we fail to post the message - JSAutoStructuredCloneBuffer buffer; - buffer.adopt(mMessage, mMessageLen); - mMessage = nullptr; - mMessageLen = 0; - // Get the JSContext for the target window nsCOMPtr sgo = do_QueryInterface(mPort->GetOwner()); NS_ENSURE_STATE(sgo); @@ -247,7 +232,7 @@ PostMessageRunnable::Run() scInfo.mEvent = this; scInfo.mPort = mPort; - if (!buffer.read(cx, &messageData, &kPostMessageCallbacks, &scInfo)) { + if (!mBuffer.read(cx, &messageData, &kPostMessageCallbacks, &scInfo)) { return NS_ERROR_DOM_DATA_CLONE_ERR; } } @@ -259,7 +244,7 @@ PostMessageRunnable::Run() } ErrorResult error; - nsRefPtr event = + nsRefPtr event = doc->CreateEvent(NS_LITERAL_STRING("MessageEvent"), error); if (error.Failed()) { return NS_OK; @@ -364,7 +349,6 @@ MessagePort::PostMessageMoz(JSContext* aCx, JS::Handle aMessage, // We *must* clone the data here, or the JS::Value could be modified // by script - JSAutoStructuredCloneBuffer buffer; StructuredCloneInfo scInfo; scInfo.mEvent = event; scInfo.mPort = this; @@ -388,14 +372,12 @@ MessagePort::PostMessageMoz(JSContext* aCx, JS::Handle aMessage, transferable.setObject(*array); } - if (!buffer.write(aCx, aMessage, transferable, &kPostMessageCallbacks, - &scInfo)) { + if (!event->Buffer().write(aCx, aMessage, transferable, + &kPostMessageCallbacks, &scInfo)) { aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR); return; } - event->SetJSData(buffer); - if (!mEntangledPort) { return; } diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index 9ffe2b18555..542688a2e25 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -35,7 +35,7 @@ #include "mozilla/ClearOnShutdown.h" #include "mozilla/StaticPtr.h" #include "Connection.h" -#include "nsDOMEvent.h" +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() #include "nsGlobalWindow.h" #ifdef MOZ_B2G_RIL #include "mozilla/dom/IccManager.h" diff --git a/dom/base/nsDOMClassInfoID.h b/dom/base/nsDOMClassInfoID.h index decb36846ae..98f6da1a85e 100644 --- a/dom/base/nsDOMClassInfoID.h +++ b/dom/base/nsDOMClassInfoID.h @@ -54,18 +54,18 @@ DOMCI_CASTABLE_NODECL_INTERFACE(mozilla::dom::Element, mozilla::dom::Element,\ /* If this is ever removed, the IID for EventTarget can go away */ \ DOMCI_CASTABLE_NODECL_INTERFACE(mozilla::dom::EventTarget, \ mozilla::dom::EventTarget, 2, _extra) \ -DOMCI_CASTABLE_INTERFACE(nsDOMEvent, nsIDOMEvent, 3, _extra) \ +DOMCI_CASTABLE_NODECL_INTERFACE(mozilla::dom::Event, nsIDOMEvent, 3, _extra) \ DOMCI_CASTABLE_INTERFACE(nsIDocument, nsIDocument, 4, _extra) \ DOMCI_CASTABLE_INTERFACE(nsDocument, nsIDocument, 5, _extra) \ DOMCI_CASTABLE_INTERFACE(nsGenericHTMLElement, nsIContent, 6, _extra) \ DOMCI_CASTABLE_INTERFACE(nsHTMLDocument, nsIDocument, 7, _extra) \ DOMCI_CASTABLE_INTERFACE(nsStyledElement, nsStyledElement, 8, _extra) \ DOMCI_CASTABLE_INTERFACE(nsSVGElement, nsIContent, 9, _extra) \ -/* NOTE: When removing the casts below, remove the nsDOMEventBase class */ \ +/* NOTE: When removing the casts below, remove the dom::EventBase class */ \ DOMCI_CASTABLE_NODECL_INTERFACE(mozilla::dom::MouseEvent, \ - nsDOMEventBase, 10, _extra) \ + mozilla::dom::EventBase, 10, _extra) \ DOMCI_CASTABLE_NODECL_INTERFACE(mozilla::dom::UIEvent, \ - nsDOMEventBase, 11, _extra) \ + mozilla::dom::EventBase, 11, _extra) \ DOMCI_CASTABLE_INTERFACE(nsGlobalWindow, nsIDOMEventTarget, 12, _extra) // Make sure all classes mentioned in DOMCI_CASTABLE_INTERFACES @@ -78,6 +78,7 @@ DOMCI_CASTABLE_INTERFACES(unused) namespace mozilla { namespace dom { class Element; +class Event; class EventTarget; class MouseEvent; class UIEvent; diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 053e14cdb7e..9cefbefb444 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -35,6 +35,7 @@ #include "nsIScriptTimeoutHandler.h" #include "nsIController.h" #include "nsScriptNameSpaceManager.h" +#include "nsWindowMemoryReporter.h" // Helper Classes #include "nsJSUtils.h" @@ -5572,7 +5573,7 @@ bool nsGlobalWindow::DispatchResizeEvent(const nsIntSize& aSize) { ErrorResult res; - nsRefPtr domEvent = + nsRefPtr domEvent = mDoc->CreateEvent(NS_LITERAL_STRING("CustomEvent"), res); if (res.Failed()) { return false; @@ -7529,8 +7530,6 @@ class PostMessageEvent : public nsRunnable bool aTrustedCaller) : mSource(aSource), mCallerOrigin(aCallerOrigin), - mMessage(nullptr), - mMessageLen(0), mTargetWindow(aTargetWindow), mProvidedPrincipal(aProvidedPrincipal), mTrustedCaller(aTrustedCaller) @@ -7540,14 +7539,12 @@ class PostMessageEvent : public nsRunnable ~PostMessageEvent() { - NS_ASSERTION(!mMessage, "Message should have been deserialized!"); MOZ_COUNT_DTOR(PostMessageEvent); } - void SetJSData(JSAutoStructuredCloneBuffer& aBuffer) + JSAutoStructuredCloneBuffer& Buffer() { - NS_ASSERTION(!mMessage && mMessageLen == 0, "Don't call twice!"); - aBuffer.steal(&mMessage, &mMessageLen); + return mBuffer; } bool StoreISupports(nsISupports* aSupports) @@ -7557,10 +7554,9 @@ class PostMessageEvent : public nsRunnable } private: + JSAutoStructuredCloneBuffer mBuffer; nsRefPtr mSource; nsString mCallerOrigin; - uint64_t* mMessage; - size_t mMessageLen; nsRefPtr mTargetWindow; nsCOMPtr mProvidedPrincipal; bool mTrustedCaller; @@ -7708,12 +7704,6 @@ PostMessageEvent::Run() // If we bailed before this point we're going to leak mMessage, but // that's probably better than crashing. - // Ensure that the buffer is freed even if we fail to post the message - JSAutoStructuredCloneBuffer buffer; - buffer.adopt(mMessage, mMessageLen); - mMessage = nullptr; - mMessageLen = 0; - nsRefPtr targetWindow; if (mTargetWindow->IsClosedOrClosing() || !(targetWindow = mTargetWindow->GetCurrentInnerWindowInternal()) || @@ -7756,7 +7746,7 @@ PostMessageEvent::Run() scInfo.event = this; scInfo.window = targetWindow; - if (!buffer.read(cx, &messageData, &kPostMessageCallbacks, &scInfo)) { + if (!mBuffer.read(cx, &messageData, &kPostMessageCallbacks, &scInfo)) { return NS_ERROR_DOM_DATA_CLONE_ERR; } } @@ -7937,7 +7927,6 @@ nsGlobalWindow::PostMessageMoz(JSContext* aCx, JS::Handle aMessage, // We *must* clone the data here, or the JS::Value could be modified // by script - JSAutoStructuredCloneBuffer buffer; StructuredCloneInfo scInfo; scInfo.event = event; scInfo.window = this; @@ -7946,14 +7935,12 @@ nsGlobalWindow::PostMessageMoz(JSContext* aCx, JS::Handle aMessage, JS::Rooted message(aCx, aMessage); JS::Rooted transfer(aCx, aTransfer); if (NS_FAILED(callerPrin->Subsumes(principal, &scInfo.subsumes)) || - !buffer.write(aCx, message, transfer, &kPostMessageCallbacks, - &scInfo)) { + !event->Buffer().write(aCx, message, transfer, &kPostMessageCallbacks, + &scInfo)) { aError.Throw(NS_ERROR_DOM_DATA_CLONE_ERR); return; } - event->SetJSData(buffer); - aError = NS_DispatchToCurrentThread(event); } @@ -13059,7 +13046,7 @@ NS_IMETHODIMP nsGlobalChromeWindow::BeginWindowMove(nsIDOMEvent *aMouseDownEvent, nsIDOMElement* aPanel) { NS_ENSURE_TRUE(aMouseDownEvent, NS_ERROR_FAILURE); - nsDOMEvent* mouseDownEvent = aMouseDownEvent->InternalDOMEvent(); + Event* mouseDownEvent = aMouseDownEvent->InternalDOMEvent(); NS_ENSURE_TRUE(mouseDownEvent, NS_ERROR_FAILURE); nsCOMPtr panel = do_QueryInterface(aPanel); @@ -13071,7 +13058,7 @@ nsGlobalChromeWindow::BeginWindowMove(nsIDOMEvent *aMouseDownEvent, nsIDOMElemen } void -nsGlobalWindow::BeginWindowMove(nsDOMEvent& aMouseDownEvent, Element* aPanel, +nsGlobalWindow::BeginWindowMove(Event& aMouseDownEvent, Element* aPanel, ErrorResult& aError) { nsCOMPtr widget; diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index 0d6f2abc482..de7e40bc0db 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -975,7 +975,7 @@ public: void NotifyDefaultButtonLoaded(mozilla::dom::Element& aDefaultButton, mozilla::ErrorResult& aError); nsIMessageBroadcaster* GetMessageManager(mozilla::ErrorResult& aError); - void BeginWindowMove(nsDOMEvent& aMouseDownEvent, + void BeginWindowMove(mozilla::dom::Event& aMouseDownEvent, mozilla::dom::Element* aPanel, mozilla::ErrorResult& aError); diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 330679921ce..b159953bd7b 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -181,7 +181,7 @@ static uint32_t sCCollectedWaitingForGC; static uint32_t sLikelyShortLivingObjectsNeedingGC; static bool sPostGCEventsToConsole; static bool sPostGCEventsToObserver; -static uint32_t sCCTimerFireCount = 0; +static int32_t sCCTimerFireCount = 0; static uint32_t sMinForgetSkippableTime = UINT32_MAX; static uint32_t sMaxForgetSkippableTime = 0; static uint32_t sTotalForgetSkippableTime = 0; @@ -2000,9 +2000,15 @@ struct CycleCollectorStats void FinishCycleCollectionSlice() { + if (mBeginSliceTime.IsNull()) { + // We already called this method from EndCycleCollectionCallback for this slice. + return; + } + uint32_t sliceTime = TimeUntilNow(mBeginSliceTime); mMaxSliceTime = std::max(mMaxSliceTime, sliceTime); mTotalSliceTime += sliceTime; + mBeginSliceTime = TimeStamp(); MOZ_ASSERT(mExtraForgetSkippableCalls == 0, "Forget to reset extra forget skippable calls?"); } @@ -2063,15 +2069,11 @@ CycleCollectorStats::PrepareForCycleCollectionSlice(int32_t aExtraForgetSkippabl mBeginSliceTime = TimeStamp::Now(); // Before we begin the cycle collection, make sure there is no active GC. - TimeStamp endGCTime; if (sCCLockedOut) { mAnyLockedOut = true; FinishAnyIncrementalGC(); - endGCTime = TimeStamp::Now(); - uint32_t gcTime = TimeBetween(mBeginSliceTime, endGCTime); + uint32_t gcTime = TimeBetween(mBeginSliceTime, TimeStamp::Now()); mMaxGCDuration = std::max(mMaxGCDuration, gcTime); - } else { - endGCTime = mBeginSliceTime; } mExtraForgetSkippableCalls = aExtraForgetSkippableCalls; @@ -2122,7 +2124,7 @@ nsJSContext::CycleCollectNow(nsICycleCollectorListener *aListener, //static void -nsJSContext::RunCycleCollectorSlice(int64_t aSliceTime) +nsJSContext::RunCycleCollectorSlice() { if (!NS_IsMainThread()) { return; @@ -2133,7 +2135,7 @@ nsJSContext::RunCycleCollectorSlice(int64_t aSliceTime) // Ideally, the slice time would be decreased by the amount of // time spent on PrepareForCycleCollection(). gCCStats.PrepareForCycleCollectionSlice(); - nsCycleCollector_collectSlice(aSliceTime); + nsCycleCollector_collectSlice(ICCSliceTime()); gCCStats.FinishCycleCollectionSlice(); } @@ -2158,7 +2160,7 @@ ICCTimerFired(nsITimer* aTimer, void* aClosure) } } - nsJSContext::RunCycleCollectorSlice(ICCSliceTime()); + nsJSContext::RunCycleCollectorSlice(); } //static @@ -2197,7 +2199,9 @@ nsJSContext::EndCycleCollectionCallback(CycleCollectorResults &aResults) nsJSContext::KillICCTimer(); - // Update timing information for the current slice before we log it. + // Update timing information for the current slice before we log it, if + // we previously called PrepareForCycleCollectionSlice(). During shutdown + // CCs, this won't happen. gCCStats.FinishCycleCollectionSlice(); sCCollectedWaitingForGC += aResults.mFreedRefCounted + aResults.mFreedGCed; @@ -2416,8 +2420,9 @@ CCTimerFired(nsITimer *aTimer, void *aClosure) // During early timer fires, we only run forgetSkippable. During the first // late timer fire, we decide if we are going to have a second and final - // late timer fire, where we may begin to run the CC. - uint32_t numEarlyTimerFires = ccDelay / NS_CC_SKIPPABLE_DELAY - 2; + // late timer fire, where we may begin to run the CC. Should run at least one + // early timer fire to allow cleanup before the CC. + int32_t numEarlyTimerFires = std::max((int32_t)ccDelay / NS_CC_SKIPPABLE_DELAY - 2, 1); bool isLateTimerFire = sCCTimerFireCount > numEarlyTimerFires; uint32_t suspected = nsCycleCollector_suspectedCount(); if (isLateTimerFire && ShouldTriggerCC(suspected)) { @@ -2432,7 +2437,7 @@ CCTimerFired(nsITimer *aTimer, void *aClosure) // We are in the final timer fire and still meet the conditions for // triggering a CC. Let RunCycleCollectorSlice finish the current IGC, if // any because that will allow us to include the GC time in the CC pause. - nsJSContext::RunCycleCollectorSlice(ICCSliceTime()); + nsJSContext::RunCycleCollectorSlice(); } } else if ((sPreviousSuspectedCount + 100) <= suspected) { // Only do a forget skippable if there are more than a few new objects. @@ -2500,6 +2505,13 @@ nsJSContext::PokeGC(JS::gcreason::Reason aReason, int aDelay) return; } + if (sICCTimer) { + // Make sure GC is called after the current CC completes. + // No need to set sNeedsFullCC because we are currently running a CC. + sNeedsGCAfterCC = true; + return; + } + CallCreateInstance("@mozilla.org/timer;1", &sGCTimer); if (!sGCTimer) { diff --git a/dom/base/nsJSEnvironment.h b/dom/base/nsJSEnvironment.h index f356ccdd09e..e862f7897b9 100644 --- a/dom/base/nsJSEnvironment.h +++ b/dom/base/nsJSEnvironment.h @@ -110,10 +110,8 @@ public: static void CycleCollectNow(nsICycleCollectorListener *aListener = nullptr, int32_t aExtraForgetSkippableCalls = 0); - // If aSliceTime is negative, the CC will run to completion. If aSliceTime - // is 0, only a minimum quantum of work will be done. Otherwise, aSliceTime - // will be used as the time budget for the slice, in ms. - static void RunCycleCollectorSlice(int64_t aSliceTime); + // Run a cycle collector slice, using a heuristic to decide how long to run it. + static void RunCycleCollectorSlice(); static void BeginCycleCollectionCallback(); static void EndCycleCollectionCallback(mozilla::CycleCollectorResults &aResults); diff --git a/dom/base/nsScreen.cpp b/dom/base/nsScreen.cpp index 9c634dee32f..320ab29a4ea 100644 --- a/dom/base/nsScreen.cpp +++ b/dom/base/nsScreen.cpp @@ -4,6 +4,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/Hal.h" +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() +#include "mozilla/dom/ScreenBinding.h" #include "nsScreen.h" #include "nsIDocument.h" #include "nsIDocShell.h" @@ -12,9 +14,7 @@ #include "nsCOMPtr.h" #include "nsIDocShellTreeItem.h" #include "nsLayoutUtils.h" -#include "nsDOMEvent.h" #include "nsJSUtils.h" -#include "mozilla/dom/ScreenBinding.h" #include "nsDeviceContext.h" using namespace mozilla; diff --git a/dom/base/nsWindowMemoryReporter.h b/dom/base/nsWindowMemoryReporter.h index 301497c9910..214b55f2a62 100644 --- a/dom/base/nsWindowMemoryReporter.h +++ b/dom/base/nsWindowMemoryReporter.h @@ -19,13 +19,6 @@ #include "mozilla/TimeStamp.h" #include "nsArenaMemoryStats.h" -// This should be used for any nsINode sub-class that has fields of its own -// that it needs to measure; any sub-class that doesn't use it will inherit -// SizeOfExcludingThis from its super-class. SizeOfIncludingThis() need not be -// defined, it is inherited from nsINode. -#define NS_DECL_SIZEOF_EXCLUDING_THIS \ - virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; - class nsWindowSizes { #define FOR_EACH_SIZE(macro) \ macro(DOM, mDOMElementNodesSize) \ diff --git a/dom/base/test/mochitest.ini b/dom/base/test/mochitest.ini index dc0c690802a..b99215cd2ec 100644 --- a/dom/base/test/mochitest.ini +++ b/dom/base/test/mochitest.ini @@ -10,6 +10,7 @@ support-files = [test_appname_override.html] [test_bug913761.html] [test_bug978522.html] +[test_bug979109.html] [test_clearTimeoutIntervalNoArg.html] [test_consoleEmptyStack.html] [test_constructor-assignment.html] diff --git a/dom/base/test/test_bug979109.html b/dom/base/test/test_bug979109.html new file mode 100644 index 00000000000..dc3ee58149f --- /dev/null +++ b/dom/base/test/test_bug979109.html @@ -0,0 +1,32 @@ + + + + + + Test for Bug 979109 + + + + +Mozilla Bug 979109 + + + diff --git a/dom/battery/BatteryManager.cpp b/dom/battery/BatteryManager.cpp index 1653e7695c5..b6138f4156c 100644 --- a/dom/battery/BatteryManager.cpp +++ b/dom/battery/BatteryManager.cpp @@ -8,7 +8,6 @@ #include "BatteryManager.h" #include "nsIDOMClassInfo.h" #include "Constants.h" -#include "nsDOMEvent.h" #include "mozilla/Preferences.h" #include "nsDOMEventTargetHelper.h" #include "mozilla/dom/BatteryManagerBinding.h" diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index 5d65ffd151f..0b8d1acd1b7 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -373,7 +373,6 @@ DOMInterfaces = { }, 'Event': { - 'nativeType': 'nsDOMEvent', 'implicitJSContext': [ 'defaultPrevented', 'preventDefault' ], }, diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 00e482a7ecc..e0d20f50389 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -12072,7 +12072,7 @@ class CGEventClass(CGBindingImplClass): dropJS += " mozilla::DropJSObjects(this);\n" # Just override CGClass and do our own thing nativeType = self.descriptor.nativeType.split('::')[-1] - ctorParams = ("aOwner, nullptr, nullptr" if self.parentType == "nsDOMEvent" + ctorParams = ("aOwner, nullptr, nullptr" if self.parentType == "Event" else "aOwner") classImpl = """ NS_IMPL_CYCLE_COLLECTION_CLASS(${nativeType}) diff --git a/dom/devicestorage/nsDeviceStorage.cpp b/dom/devicestorage/nsDeviceStorage.cpp index 5d7ad44038c..d0e069db9fa 100644 --- a/dom/devicestorage/nsDeviceStorage.cpp +++ b/dom/devicestorage/nsDeviceStorage.cpp @@ -22,7 +22,6 @@ #include "mozilla/Services.h" #include "nsAutoPtr.h" -#include "nsDOMEvent.h" #include "nsServiceManagerUtils.h" #include "nsIFile.h" #include "nsIDirectoryEnumerator.h" diff --git a/dom/events/AnimationEvent.cpp b/dom/events/AnimationEvent.cpp index eb0a1f3abf2..706c3c41212 100644 --- a/dom/events/AnimationEvent.cpp +++ b/dom/events/AnimationEvent.cpp @@ -13,8 +13,8 @@ namespace dom { AnimationEvent::AnimationEvent(EventTarget* aOwner, nsPresContext* aPresContext, InternalAnimationEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, - aEvent ? aEvent : new InternalAnimationEvent(false, 0)) + : Event(aOwner, aPresContext, + aEvent ? aEvent : new InternalAnimationEvent(false, 0)) { if (aEvent) { mEventIsInternal = false; @@ -27,10 +27,10 @@ AnimationEvent::AnimationEvent(EventTarget* aOwner, NS_INTERFACE_MAP_BEGIN(AnimationEvent) NS_INTERFACE_MAP_ENTRY(nsIDOMAnimationEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) -NS_IMPL_ADDREF_INHERITED(AnimationEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(AnimationEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(AnimationEvent, Event) +NS_IMPL_RELEASE_INHERITED(AnimationEvent, Event) //static already_AddRefed diff --git a/dom/events/AnimationEvent.h b/dom/events/AnimationEvent.h index fafd671a9b7..1b63518fee5 100644 --- a/dom/events/AnimationEvent.h +++ b/dom/events/AnimationEvent.h @@ -5,17 +5,17 @@ #ifndef mozilla_dom_AnimationEvent_h_ #define mozilla_dom_AnimationEvent_h_ -#include "nsDOMEvent.h" -#include "nsIDOMAnimationEvent.h" #include "mozilla/EventForwards.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/AnimationEventBinding.h" +#include "nsIDOMAnimationEvent.h" class nsAString; namespace mozilla { namespace dom { -class AnimationEvent : public nsDOMEvent, +class AnimationEvent : public Event, public nsIDOMAnimationEvent { public: @@ -24,7 +24,7 @@ public: InternalAnimationEvent* aEvent); NS_DECL_ISUPPORTS_INHERITED - NS_FORWARD_TO_NSDOMEVENT + NS_FORWARD_TO_EVENT NS_DECL_NSIDOMANIMATIONEVENT static already_AddRefed diff --git a/dom/events/BeforeUnloadEvent.cpp b/dom/events/BeforeUnloadEvent.cpp index ea56fb4155b..c1feff04f2b 100644 --- a/dom/events/BeforeUnloadEvent.cpp +++ b/dom/events/BeforeUnloadEvent.cpp @@ -8,12 +8,12 @@ namespace mozilla { namespace dom { -NS_IMPL_ADDREF_INHERITED(BeforeUnloadEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(BeforeUnloadEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(BeforeUnloadEvent, Event) +NS_IMPL_RELEASE_INHERITED(BeforeUnloadEvent, Event) NS_INTERFACE_MAP_BEGIN(BeforeUnloadEvent) NS_INTERFACE_MAP_ENTRY(nsIDOMBeforeUnloadEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) NS_IMETHODIMP BeforeUnloadEvent::SetReturnValue(const nsAString& aReturnValue) diff --git a/dom/events/BeforeUnloadEvent.h b/dom/events/BeforeUnloadEvent.h index dd8ed0b4306..3824d090c1b 100644 --- a/dom/events/BeforeUnloadEvent.h +++ b/dom/events/BeforeUnloadEvent.h @@ -6,21 +6,21 @@ #ifndef mozilla_dom_BeforeUnloadEvent_h_ #define mozilla_dom_BeforeUnloadEvent_h_ -#include "nsIDOMBeforeUnloadEvent.h" -#include "nsDOMEvent.h" #include "mozilla/dom/BeforeUnloadEventBinding.h" +#include "mozilla/dom/Event.h" +#include "nsIDOMBeforeUnloadEvent.h" namespace mozilla { namespace dom { -class BeforeUnloadEvent : public nsDOMEvent, +class BeforeUnloadEvent : public Event, public nsIDOMBeforeUnloadEvent { public: BeforeUnloadEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, aEvent) + : Event(aOwner, aPresContext, aEvent) { } @@ -32,8 +32,8 @@ public: NS_DECL_ISUPPORTS_INHERITED - // Forward to nsDOMEvent - NS_FORWARD_TO_NSDOMEVENT + // Forward to Event + NS_FORWARD_TO_EVENT // nsIDOMBeforeUnloadEvent Interface NS_DECL_NSIDOMBEFOREUNLOADEVENT diff --git a/dom/events/ClipboardEvent.cpp b/dom/events/ClipboardEvent.cpp index f4d06309b87..a2286ce54bd 100644 --- a/dom/events/ClipboardEvent.cpp +++ b/dom/events/ClipboardEvent.cpp @@ -14,8 +14,8 @@ namespace dom { ClipboardEvent::ClipboardEvent(EventTarget* aOwner, nsPresContext* aPresContext, InternalClipboardEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, aEvent ? aEvent : - new InternalClipboardEvent(false, 0)) + : Event(aOwner, aPresContext, + aEvent ? aEvent : new InternalClipboardEvent(false, 0)) { if (aEvent) { mEventIsInternal = false; @@ -27,10 +27,10 @@ ClipboardEvent::ClipboardEvent(EventTarget* aOwner, NS_INTERFACE_MAP_BEGIN(ClipboardEvent) NS_INTERFACE_MAP_ENTRY(nsIDOMClipboardEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) -NS_IMPL_ADDREF_INHERITED(ClipboardEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(ClipboardEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(ClipboardEvent, Event) +NS_IMPL_RELEASE_INHERITED(ClipboardEvent, Event) nsresult ClipboardEvent::InitClipboardEvent(const nsAString& aType, @@ -53,7 +53,7 @@ ClipboardEvent::InitClipboardEvent(const nsAString& aType, bool aCanBubble, DataTransfer* aClipboardData, ErrorResult& aError) { - aError = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable); + aError = Event::InitEvent(aType, aCanBubble, aCancelable); if (aError.Failed()) { return; } diff --git a/dom/events/ClipboardEvent.h b/dom/events/ClipboardEvent.h index 802ea3013d7..8a0a8ad5ec6 100644 --- a/dom/events/ClipboardEvent.h +++ b/dom/events/ClipboardEvent.h @@ -6,16 +6,16 @@ #ifndef mozilla_dom_ClipboardEvent_h_ #define mozilla_dom_ClipboardEvent_h_ -#include "nsIDOMClipboardEvent.h" -#include "nsDOMEvent.h" #include "mozilla/EventForwards.h" #include "mozilla/dom/ClipboardEventBinding.h" +#include "mozilla/dom/Event.h" +#include "nsIDOMClipboardEvent.h" namespace mozilla { namespace dom { class DataTransfer; -class ClipboardEvent : public nsDOMEvent, +class ClipboardEvent : public Event, public nsIDOMClipboardEvent { public: @@ -28,7 +28,7 @@ public: NS_DECL_NSIDOMCLIPBOARDEVENT // Forward to base class - NS_FORWARD_TO_NSDOMEVENT + NS_FORWARD_TO_EVENT virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aScope) MOZ_OVERRIDE diff --git a/dom/events/CommandEvent.cpp b/dom/events/CommandEvent.cpp index 8d9a95eab4e..51f56c84dea 100644 --- a/dom/events/CommandEvent.cpp +++ b/dom/events/CommandEvent.cpp @@ -13,8 +13,9 @@ namespace dom { CommandEvent::CommandEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetCommandEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, aEvent ? aEvent : - new WidgetCommandEvent(false, nullptr, nullptr, nullptr)) + : Event(aOwner, aPresContext, + aEvent ? aEvent : + new WidgetCommandEvent(false, nullptr, nullptr, nullptr)) { mEvent->time = PR_Now(); if (aEvent) { @@ -26,10 +27,10 @@ CommandEvent::CommandEvent(EventTarget* aOwner, NS_INTERFACE_MAP_BEGIN(CommandEvent) NS_INTERFACE_MAP_ENTRY(nsIDOMCommandEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) -NS_IMPL_ADDREF_INHERITED(CommandEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(CommandEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(CommandEvent, Event) +NS_IMPL_RELEASE_INHERITED(CommandEvent, Event) NS_IMETHODIMP CommandEvent::GetCommand(nsAString& aCommand) @@ -49,7 +50,7 @@ CommandEvent::InitCommandEvent(const nsAString& aTypeArg, bool aCancelableArg, const nsAString& aCommand) { - nsresult rv = nsDOMEvent::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg); + nsresult rv = Event::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg); NS_ENSURE_SUCCESS(rv, rv); mEvent->AsCommandEvent()->command = do_GetAtom(aCommand); diff --git a/dom/events/CommandEvent.h b/dom/events/CommandEvent.h index 16854a313bc..f13a720e80c 100644 --- a/dom/events/CommandEvent.h +++ b/dom/events/CommandEvent.h @@ -6,15 +6,15 @@ #ifndef mozilla_dom_CommandEvent_h_ #define mozilla_dom_CommandEvent_h_ -#include "nsIDOMCommandEvent.h" -#include "nsDOMEvent.h" -#include "mozilla/dom/CommandEventBinding.h" #include "mozilla/EventForwards.h" +#include "mozilla/dom/CommandEventBinding.h" +#include "mozilla/dom/Event.h" +#include "nsIDOMCommandEvent.h" namespace mozilla { namespace dom { -class CommandEvent : public nsDOMEvent, +class CommandEvent : public Event, public nsIDOMCommandEvent { public: @@ -27,7 +27,7 @@ public: NS_DECL_NSIDOMCOMMANDEVENT // Forward to base class - NS_FORWARD_TO_NSDOMEVENT + NS_FORWARD_TO_EVENT virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aScope) MOZ_OVERRIDE diff --git a/dom/events/DataContainerEvent.cpp b/dom/events/DataContainerEvent.cpp index 1522065bedc..f338fcc95f2 100644 --- a/dom/events/DataContainerEvent.cpp +++ b/dom/events/DataContainerEvent.cpp @@ -13,27 +13,26 @@ namespace dom { DataContainerEvent::DataContainerEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, aEvent) + : Event(aOwner, aPresContext, aEvent) { } NS_IMPL_CYCLE_COLLECTION_CLASS(DataContainerEvent) -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DataContainerEvent, nsDOMEvent) +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DataContainerEvent, Event) tmp->mData.Clear(); NS_IMPL_CYCLE_COLLECTION_UNLINK_END -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(DataContainerEvent, - nsDOMEvent) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(DataContainerEvent, Event) tmp->mData.EnumerateRead(TraverseEntry, &cb); NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END -NS_IMPL_ADDREF_INHERITED(DataContainerEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(DataContainerEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(DataContainerEvent, Event) +NS_IMPL_RELEASE_INHERITED(DataContainerEvent, Event) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DataContainerEvent) NS_INTERFACE_MAP_ENTRY(nsIDOMDataContainerEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) NS_IMETHODIMP DataContainerEvent::GetData(const nsAString& aKey, nsIVariant** aData) diff --git a/dom/events/DataContainerEvent.h b/dom/events/DataContainerEvent.h index f8b621f4769..4cc42edd5b6 100644 --- a/dom/events/DataContainerEvent.h +++ b/dom/events/DataContainerEvent.h @@ -6,15 +6,15 @@ #ifndef mozilla_dom_DataContainerEvent_h_ #define mozilla_dom_DataContainerEvent_h_ -#include "nsIDOMDataContainerEvent.h" -#include "nsDOMEvent.h" -#include "nsInterfaceHashtable.h" #include "mozilla/dom/DataContainerEventBinding.h" +#include "mozilla/dom/Event.h" +#include "nsIDOMDataContainerEvent.h" +#include "nsInterfaceHashtable.h" namespace mozilla { namespace dom { -class DataContainerEvent : public nsDOMEvent, +class DataContainerEvent : public Event, public nsIDOMDataContainerEvent { public: @@ -24,9 +24,9 @@ public: NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DataContainerEvent, nsDOMEvent) + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DataContainerEvent, Event) - NS_FORWARD_TO_NSDOMEVENT + NS_FORWARD_TO_EVENT NS_DECL_NSIDOMDATACONTAINEREVENT diff --git a/dom/events/DeviceMotionEvent.cpp b/dom/events/DeviceMotionEvent.cpp index 60ce251dd99..b0d424fd342 100644 --- a/dom/events/DeviceMotionEvent.cpp +++ b/dom/events/DeviceMotionEvent.cpp @@ -14,16 +14,16 @@ namespace dom { * DeviceMotionEvent *****************************************************************************/ -NS_IMPL_CYCLE_COLLECTION_INHERITED_3(DeviceMotionEvent, nsDOMEvent, +NS_IMPL_CYCLE_COLLECTION_INHERITED_3(DeviceMotionEvent, Event, mAcceleration, mAccelerationIncludingGravity, mRotationRate) -NS_IMPL_ADDREF_INHERITED(DeviceMotionEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(DeviceMotionEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(DeviceMotionEvent, Event) +NS_IMPL_RELEASE_INHERITED(DeviceMotionEvent, Event) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DeviceMotionEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) void DeviceMotionEvent::InitDeviceMotionEvent( @@ -36,7 +36,7 @@ DeviceMotionEvent::InitDeviceMotionEvent( Nullable aInterval, ErrorResult& aRv) { - aRv = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable); + aRv = Event::InitEvent(aType, aCanBubble, aCancelable); if (aRv.Failed()) { return; } diff --git a/dom/events/DeviceMotionEvent.h b/dom/events/DeviceMotionEvent.h index df63cfd8c3e..13654ecc9b8 100644 --- a/dom/events/DeviceMotionEvent.h +++ b/dom/events/DeviceMotionEvent.h @@ -5,9 +5,9 @@ #ifndef mozilla_dom_DeviceMotionEvent_h_ #define mozilla_dom_DeviceMotionEvent_h_ -#include "nsDOMEvent.h" #include "mozilla/Attributes.h" #include "mozilla/dom/DeviceMotionEventBinding.h" +#include "mozilla/dom/Event.h" namespace mozilla { namespace dom { @@ -88,23 +88,23 @@ protected: Nullable mX, mY, mZ; }; -class DeviceMotionEvent MOZ_FINAL : public nsDOMEvent +class DeviceMotionEvent MOZ_FINAL : public Event { public: DeviceMotionEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, aEvent) + : Event(aOwner, aPresContext, aEvent) { } NS_DECL_ISUPPORTS_INHERITED - // Forward to nsDOMEvent - NS_FORWARD_TO_NSDOMEVENT + // Forward to Event + NS_FORWARD_TO_EVENT - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DeviceMotionEvent, nsDOMEvent) + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DeviceMotionEvent, Event) virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aScope) MOZ_OVERRIDE diff --git a/dom/events/nsDOMEvent.cpp b/dom/events/Event.cpp similarity index 81% rename from dom/events/nsDOMEvent.cpp rename to dom/events/Event.cpp index ee63fa6bd8c..543c5b5f186 100644 --- a/dom/events/nsDOMEvent.cpp +++ b/dom/events/Event.cpp @@ -3,62 +3,58 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "base/basictypes.h" - #include "AccessCheck.h" +#include "base/basictypes.h" #include "ipc/IPCMessageUtils.h" -#include "nsCOMPtr.h" -#include "nsError.h" -#include "nsDOMEvent.h" -#include "nsEventStateManager.h" -#include "nsIFrame.h" -#include "nsIContent.h" -#include "nsIPresShell.h" -#include "nsIDocument.h" +#include "mozilla/dom/Event.h" #include "mozilla/ContentEvents.h" #include "mozilla/InternalMutationEvent.h" #include "mozilla/MiscEvents.h" #include "mozilla/MouseEvents.h" +#include "mozilla/Preferences.h" #include "mozilla/TextEvents.h" #include "mozilla/TouchEvents.h" #include "nsContentUtils.h" -#include "nsJSEnvironment.h" -#include "mozilla/Preferences.h" -#include "nsLayoutUtils.h" -#include "nsIScrollableFrame.h" -#include "nsDOMEventTargetHelper.h" -#include "nsPIWindowRoot.h" -#include "nsGlobalWindow.h" +#include "nsCOMPtr.h" #include "nsDeviceContext.h" - -using namespace mozilla; -using namespace mozilla::dom; +#include "nsDOMEventTargetHelper.h" +#include "nsError.h" +#include "nsEventStateManager.h" +#include "nsGlobalWindow.h" +#include "nsIFrame.h" +#include "nsIContent.h" +#include "nsIDocument.h" +#include "nsIPresShell.h" +#include "nsIScrollableFrame.h" +#include "nsJSEnvironment.h" +#include "nsLayoutUtils.h" +#include "nsPIWindowRoot.h" namespace mozilla { namespace dom { + namespace workers { extern bool IsCurrentThreadRunningChromeWorker(); } // namespace workers -} // namespace dom -} // namespace mozilla static char *sPopupAllowedEvents; - -nsDOMEvent::nsDOMEvent(mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, WidgetEvent* aEvent) +Event::Event(EventTarget* aOwner, + nsPresContext* aPresContext, + WidgetEvent* aEvent) { ConstructorInit(aOwner, aPresContext, aEvent); } -nsDOMEvent::nsDOMEvent(nsPIDOMWindow* aParent) +Event::Event(nsPIDOMWindow* aParent) { ConstructorInit(static_cast(aParent), nullptr, nullptr); } void -nsDOMEvent::ConstructorInit(mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, WidgetEvent* aEvent) +Event::ConstructorInit(EventTarget* aOwner, + nsPresContext* aPresContext, + WidgetEvent* aEvent) { SetIsDOMBinding(); SetOwner(aOwner); @@ -80,13 +76,13 @@ nsDOMEvent::ConstructorInit(mozilla::dom::EventTarget* aOwner, (derived from WidgetEvent). To do this, it should take care to pass a non-nullptr aEvent to this ctor, e.g.: - nsDOMFooEvent::nsDOMFooEvent(..., WidgetEvent* aEvent) - : nsDOMEvent(..., aEvent ? aEvent : new nsFooEvent()) + FooEvent::FooEvent(..., WidgetEvent* aEvent) + : Event(..., aEvent ? aEvent : new WidgetEvent()) Then, to override the mEventIsInternal assignments done by the base ctor, it should do this in its own ctor: - nsDOMFooEvent::nsDOMFooEvent(..., WidgetEvent* aEvent) + FooEvent::FooEvent(..., WidgetEvent* aEvent) ... { ... @@ -107,7 +103,7 @@ nsDOMEvent::ConstructorInit(mozilla::dom::EventTarget* aOwner, } void -nsDOMEvent::InitPresContextData(nsPresContext* aPresContext) +Event::InitPresContextData(nsPresContext* aPresContext) { mPresContext = aPresContext; // Get the explicit original target (if it's anonymous make it null) @@ -120,31 +116,31 @@ nsDOMEvent::InitPresContextData(nsPresContext* aPresContext) } } -nsDOMEvent::~nsDOMEvent() +Event::~Event() { - NS_ASSERT_OWNINGTHREAD(nsDOMEvent); + NS_ASSERT_OWNINGTHREAD(Event); if (mEventIsInternal && mEvent) { delete mEvent; } } -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMEvent) +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Event) NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_ENTRY(nsIDOMEvent) NS_INTERFACE_MAP_END -NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMEvent) -NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMEvent) +NS_IMPL_CYCLE_COLLECTING_ADDREF(Event) +NS_IMPL_CYCLE_COLLECTING_RELEASE(Event) -NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMEvent) +NS_IMPL_CYCLE_COLLECTION_CLASS(Event) -NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDOMEvent) +NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Event) NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER NS_IMPL_CYCLE_COLLECTION_TRACE_END -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMEvent) +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Event) if (tmp->mEventIsInternal) { tmp->mEvent->target = nullptr; tmp->mEvent->currentTarget = nullptr; @@ -182,7 +178,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMEvent) NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER NS_IMPL_CYCLE_COLLECTION_UNLINK_END -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMEvent) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Event) if (tmp->mEventIsInternal) { NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEvent->target) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEvent->currentTarget) @@ -227,7 +223,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMEvent) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END bool -nsDOMEvent::IsChrome(JSContext* aCx) const +Event::IsChrome(JSContext* aCx) const { return mIsMainThreadEvent ? xpc::AccessCheck::isChrome(js::GetContextCompartment(aCx)) : @@ -235,7 +231,8 @@ nsDOMEvent::IsChrome(JSContext* aCx) const } // nsIDOMEventInterface -NS_METHOD nsDOMEvent::GetType(nsAString& aType) +NS_METHOD +Event::GetType(nsAString& aType) { if (!mIsMainThreadEvent || !mEvent->typeString.IsEmpty()) { aType = mEvent->typeString; @@ -263,26 +260,26 @@ GetDOMEventTarget(nsIDOMEventTarget* aTarget) } EventTarget* -nsDOMEvent::GetTarget() const +Event::GetTarget() const { return GetDOMEventTarget(mEvent->target); } NS_METHOD -nsDOMEvent::GetTarget(nsIDOMEventTarget** aTarget) +Event::GetTarget(nsIDOMEventTarget** aTarget) { NS_IF_ADDREF(*aTarget = GetTarget()); return NS_OK; } EventTarget* -nsDOMEvent::GetCurrentTarget() const +Event::GetCurrentTarget() const { return GetDOMEventTarget(mEvent->currentTarget); } NS_IMETHODIMP -nsDOMEvent::GetCurrentTarget(nsIDOMEventTarget** aCurrentTarget) +Event::GetCurrentTarget(nsIDOMEventTarget** aCurrentTarget) { NS_IF_ADDREF(*aCurrentTarget = GetCurrentTarget()); return NS_OK; @@ -292,7 +289,7 @@ nsDOMEvent::GetCurrentTarget(nsIDOMEventTarget** aCurrentTarget) // Get the actual event target node (may have been retargeted for mouse events) // already_AddRefed -nsDOMEvent::GetTargetFromFrame() +Event::GetTargetFromFrame() { if (!mPresContext) { return nullptr; } @@ -307,7 +304,7 @@ nsDOMEvent::GetTargetFromFrame() } EventTarget* -nsDOMEvent::GetExplicitOriginalTarget() const +Event::GetExplicitOriginalTarget() const { if (mExplicitOriginalTarget) { return mExplicitOriginalTarget; @@ -316,14 +313,14 @@ nsDOMEvent::GetExplicitOriginalTarget() const } NS_IMETHODIMP -nsDOMEvent::GetExplicitOriginalTarget(nsIDOMEventTarget** aRealEventTarget) +Event::GetExplicitOriginalTarget(nsIDOMEventTarget** aRealEventTarget) { NS_IF_ADDREF(*aRealEventTarget = GetExplicitOriginalTarget()); return NS_OK; } EventTarget* -nsDOMEvent::GetOriginalTarget() const +Event::GetOriginalTarget() const { if (mEvent->originalTarget) { return GetDOMEventTarget(mEvent->originalTarget); @@ -333,20 +330,20 @@ nsDOMEvent::GetOriginalTarget() const } NS_IMETHODIMP -nsDOMEvent::GetOriginalTarget(nsIDOMEventTarget** aOriginalTarget) +Event::GetOriginalTarget(nsIDOMEventTarget** aOriginalTarget) { NS_IF_ADDREF(*aOriginalTarget = GetOriginalTarget()); return NS_OK; } NS_IMETHODIMP_(void) -nsDOMEvent::SetTrusted(bool aTrusted) +Event::SetTrusted(bool aTrusted) { mEvent->mFlags.mIsTrusted = aTrusted; } bool -nsDOMEvent::Init(mozilla::dom::EventTarget* aGlobal) +Event::Init(mozilla::dom::EventTarget* aGlobal) { if (!mIsMainThreadEvent) { return nsContentUtils::ThreadsafeIsCallerChrome(); @@ -366,15 +363,15 @@ nsDOMEvent::Init(mozilla::dom::EventTarget* aGlobal) return trusted; } -//static -already_AddRefed -nsDOMEvent::Constructor(const mozilla::dom::GlobalObject& aGlobal, - const nsAString& aType, - const mozilla::dom::EventInit& aParam, - mozilla::ErrorResult& aRv) +// static +already_AddRefed +Event::Constructor(const GlobalObject& aGlobal, + const nsAString& aType, + const EventInit& aParam, + ErrorResult& aRv) { nsCOMPtr t = do_QueryInterface(aGlobal.GetAsSupports()); - nsRefPtr e = new nsDOMEvent(t, nullptr, nullptr); + nsRefPtr e = new Event(t, nullptr, nullptr); bool trusted = e->Init(t); aRv = e->InitEvent(aType, aParam.mBubbles, aParam.mCancelable); e->SetTrusted(trusted); @@ -382,7 +379,7 @@ nsDOMEvent::Constructor(const mozilla::dom::GlobalObject& aGlobal, } uint16_t -nsDOMEvent::EventPhase() const +Event::EventPhase() const { // Note, remember to check that this works also // if or when Bug 235441 is fixed. @@ -401,42 +398,42 @@ nsDOMEvent::EventPhase() const } NS_IMETHODIMP -nsDOMEvent::GetEventPhase(uint16_t* aEventPhase) +Event::GetEventPhase(uint16_t* aEventPhase) { *aEventPhase = EventPhase(); return NS_OK; } NS_IMETHODIMP -nsDOMEvent::GetBubbles(bool* aBubbles) +Event::GetBubbles(bool* aBubbles) { *aBubbles = Bubbles(); return NS_OK; } NS_IMETHODIMP -nsDOMEvent::GetCancelable(bool* aCancelable) +Event::GetCancelable(bool* aCancelable) { *aCancelable = Cancelable(); return NS_OK; } NS_IMETHODIMP -nsDOMEvent::GetTimeStamp(uint64_t* aTimeStamp) +Event::GetTimeStamp(uint64_t* aTimeStamp) { *aTimeStamp = TimeStamp(); return NS_OK; } NS_IMETHODIMP -nsDOMEvent::StopPropagation() +Event::StopPropagation() { mEvent->mFlags.mPropagationStopped = true; return NS_OK; } NS_IMETHODIMP -nsDOMEvent::StopImmediatePropagation() +Event::StopImmediatePropagation() { mEvent->mFlags.mPropagationStopped = true; mEvent->mFlags.mImmediatePropagationStopped = true; @@ -444,14 +441,14 @@ nsDOMEvent::StopImmediatePropagation() } NS_IMETHODIMP -nsDOMEvent::GetIsTrusted(bool *aIsTrusted) +Event::GetIsTrusted(bool* aIsTrusted) { *aIsTrusted = IsTrusted(); return NS_OK; } NS_IMETHODIMP -nsDOMEvent::PreventDefault() +Event::PreventDefault() { // This method is called only from C++ code which must handle default action // of this event. So, pass true always. @@ -460,7 +457,7 @@ nsDOMEvent::PreventDefault() } void -nsDOMEvent::PreventDefault(JSContext* aCx) +Event::PreventDefault(JSContext* aCx) { MOZ_ASSERT(aCx, "JS context must be specified"); @@ -472,7 +469,7 @@ nsDOMEvent::PreventDefault(JSContext* aCx) } void -nsDOMEvent::PreventDefaultInternal(bool aCalledByDefaultHandler) +Event::PreventDefaultInternal(bool aCalledByDefaultHandler) { if (!mEvent->mFlags.mCancelable) { return; @@ -511,7 +508,7 @@ nsDOMEvent::PreventDefaultInternal(bool aCalledByDefaultHandler) } void -nsDOMEvent::SetEventType(const nsAString& aEventTypeArg) +Event::SetEventType(const nsAString& aEventTypeArg) { if (mIsMainThreadEvent) { mEvent->userType = @@ -525,7 +522,9 @@ nsDOMEvent::SetEventType(const nsAString& aEventTypeArg) } NS_IMETHODIMP -nsDOMEvent::InitEvent(const nsAString& aEventTypeArg, bool aCanBubbleArg, bool aCancelableArg) +Event::InitEvent(const nsAString& aEventTypeArg, + bool aCanBubbleArg, + bool aCancelableArg) { // Make sure this event isn't already being dispatched. NS_ENSURE_TRUE(!mEvent->mFlags.mIsBeingDispatched, NS_OK); @@ -552,9 +551,9 @@ nsDOMEvent::InitEvent(const nsAString& aEventTypeArg, bool aCanBubbleArg, bool a } NS_IMETHODIMP -nsDOMEvent::DuplicatePrivateData() +Event::DuplicatePrivateData() { - NS_ASSERTION(mEvent, "No WidgetEvent for nsDOMEvent duplication!"); + NS_ASSERTION(mEvent, "No WidgetEvent for Event duplication!"); if (mEventIsInternal) { return NS_OK; } @@ -568,7 +567,7 @@ nsDOMEvent::DuplicatePrivateData() } NS_IMETHODIMP -nsDOMEvent::SetTarget(nsIDOMEventTarget* aTarget) +Event::SetTarget(nsIDOMEventTarget* aTarget) { #ifdef DEBUG { @@ -584,19 +583,19 @@ nsDOMEvent::SetTarget(nsIDOMEventTarget* aTarget) } NS_IMETHODIMP_(bool) -nsDOMEvent::IsDispatchStopped() +Event::IsDispatchStopped() { return mEvent->mFlags.mPropagationStopped; } NS_IMETHODIMP_(WidgetEvent*) -nsDOMEvent::GetInternalNSEvent() +Event::GetInternalNSEvent() { return mEvent; } -NS_IMETHODIMP_(nsDOMEvent*) -nsDOMEvent::InternalDOMEvent() +NS_IMETHODIMP_(Event*) +Event::InternalDOMEvent() { return this; } @@ -607,7 +606,7 @@ static bool PopupAllowedForEvent(const char *eventName) { if (!sPopupAllowedEvents) { - nsDOMEvent::PopupAllowedEventsChanged(); + Event::PopupAllowedEventsChanged(); if (!sPopupAllowedEvents) { return false; @@ -643,7 +642,7 @@ PopupAllowedForEvent(const char *eventName) // static PopupControlState -nsDOMEvent::GetEventPopupControlState(WidgetEvent* aEvent) +Event::GetEventPopupControlState(WidgetEvent* aEvent) { // generally if an event handler is running, new windows are disallowed. // check for exceptions: @@ -657,12 +656,14 @@ nsDOMEvent::GetEventPopupControlState(WidgetEvent* aEvent) if (nsEventStateManager::IsHandlingUserInput()) { switch(aEvent->message) { case NS_FORM_SELECTED : - if (::PopupAllowedForEvent("select")) + if (PopupAllowedForEvent("select")) { abuse = openControlled; + } break; case NS_FORM_CHANGE : - if (::PopupAllowedForEvent("change")) + if (PopupAllowedForEvent("change")) { abuse = openControlled; + } break; } } @@ -674,8 +675,9 @@ nsDOMEvent::GetEventPopupControlState(WidgetEvent* aEvent) if (nsEventStateManager::IsHandlingUserInput()) { switch(aEvent->message) { case NS_FORM_INPUT : - if (::PopupAllowedForEvent("input")) + if (PopupAllowedForEvent("input")) { abuse = openControlled; + } break; } } @@ -687,8 +689,9 @@ nsDOMEvent::GetEventPopupControlState(WidgetEvent* aEvent) if (nsEventStateManager::IsHandlingUserInput()) { switch(aEvent->message) { case NS_FORM_CHANGE : - if (::PopupAllowedForEvent("change")) + if (PopupAllowedForEvent("change")) { abuse = openControlled; + } break; case NS_XUL_COMMAND: abuse = openControlled; @@ -702,21 +705,24 @@ nsDOMEvent::GetEventPopupControlState(WidgetEvent* aEvent) switch(aEvent->message) { case NS_KEY_PRESS : // return key on focused button. see note at NS_MOUSE_CLICK. - if (key == nsIDOMKeyEvent::DOM_VK_RETURN) + if (key == nsIDOMKeyEvent::DOM_VK_RETURN) { abuse = openAllowed; - else if (::PopupAllowedForEvent("keypress")) + } else if (PopupAllowedForEvent("keypress")) { abuse = openControlled; + } break; case NS_KEY_UP : // space key on focused button. see note at NS_MOUSE_CLICK. - if (key == nsIDOMKeyEvent::DOM_VK_SPACE) + if (key == nsIDOMKeyEvent::DOM_VK_SPACE) { abuse = openAllowed; - else if (::PopupAllowedForEvent("keyup")) + } else if (PopupAllowedForEvent("keyup")) { abuse = openControlled; + } break; case NS_KEY_DOWN : - if (::PopupAllowedForEvent("keydown")) + if (PopupAllowedForEvent("keydown")) { abuse = openControlled; + } break; } } @@ -742,24 +748,28 @@ nsDOMEvent::GetEventPopupControlState(WidgetEvent* aEvent) aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) { switch(aEvent->message) { case NS_MOUSE_BUTTON_UP : - if (::PopupAllowedForEvent("mouseup")) + if (PopupAllowedForEvent("mouseup")) { abuse = openControlled; + } break; case NS_MOUSE_BUTTON_DOWN : - if (::PopupAllowedForEvent("mousedown")) + if (PopupAllowedForEvent("mousedown")) { abuse = openControlled; + } break; case NS_MOUSE_CLICK : /* Click events get special treatment because of their historical status as a more legitimate event handler. If click popups are enabled in the prefs, clear the popup status completely. */ - if (::PopupAllowedForEvent("click")) + if (PopupAllowedForEvent("click")) { abuse = openAllowed; + } break; case NS_MOUSE_DOUBLECLICK : - if (::PopupAllowedForEvent("dblclick")) + if (PopupAllowedForEvent("dblclick")) { abuse = openControlled; + } break; } } @@ -771,12 +781,14 @@ nsDOMEvent::GetEventPopupControlState(WidgetEvent* aEvent) if (nsEventStateManager::IsHandlingUserInput()) { switch(aEvent->message) { case NS_FORM_SUBMIT : - if (::PopupAllowedForEvent("submit")) + if (PopupAllowedForEvent("submit")) { abuse = openControlled; + } break; case NS_FORM_RESET : - if (::PopupAllowedForEvent("reset")) + if (PopupAllowedForEvent("reset")) { abuse = openControlled; + } break; } } @@ -790,7 +802,7 @@ nsDOMEvent::GetEventPopupControlState(WidgetEvent* aEvent) // static void -nsDOMEvent::PopupAllowedEventsChanged() +Event::PopupAllowedEventsChanged() { if (sPopupAllowedEvents) { nsMemory::Free(sPopupAllowedEvents); @@ -805,7 +817,7 @@ nsDOMEvent::PopupAllowedEventsChanged() // static void -nsDOMEvent::Shutdown() +Event::Shutdown() { if (sPopupAllowedEvents) { nsMemory::Free(sPopupAllowedEvents); @@ -813,9 +825,9 @@ nsDOMEvent::Shutdown() } nsIntPoint -nsDOMEvent::GetScreenCoords(nsPresContext* aPresContext, - WidgetEvent* aEvent, - LayoutDeviceIntPoint aPoint) +Event::GetScreenCoords(nsPresContext* aPresContext, + WidgetEvent* aEvent, + LayoutDeviceIntPoint aPoint) { if (nsEventStateManager::sIsPointerLocked) { return nsEventStateManager::sLastScreenPoint; @@ -844,17 +856,15 @@ nsDOMEvent::GetScreenCoords(nsPresContext* aPresContext, nsPresContext::AppUnitsToIntCSSPixels(offset.y * factor)); } -//static +// static CSSIntPoint -nsDOMEvent::GetPageCoords(nsPresContext* aPresContext, - WidgetEvent* aEvent, - LayoutDeviceIntPoint aPoint, - CSSIntPoint aDefaultPoint) +Event::GetPageCoords(nsPresContext* aPresContext, + WidgetEvent* aEvent, + LayoutDeviceIntPoint aPoint, + CSSIntPoint aDefaultPoint) { - CSSIntPoint pagePoint = nsDOMEvent::GetClientCoords(aPresContext, - aEvent, - aPoint, - aDefaultPoint); + CSSIntPoint pagePoint = + Event::GetClientCoords(aPresContext, aEvent, aPoint, aDefaultPoint); // If there is some scrolling, add scroll info to client point. if (aPresContext && aPresContext->GetPresShell()) { @@ -870,10 +880,10 @@ nsDOMEvent::GetPageCoords(nsPresContext* aPresContext, // static CSSIntPoint -nsDOMEvent::GetClientCoords(nsPresContext* aPresContext, - WidgetEvent* aEvent, - LayoutDeviceIntPoint aPoint, - CSSIntPoint aDefaultPoint) +Event::GetClientCoords(nsPresContext* aPresContext, + WidgetEvent* aEvent, + LayoutDeviceIntPoint aPoint, + CSSIntPoint aDefaultPoint) { if (nsEventStateManager::sIsPointerLocked) { return nsEventStateManager::sLastClientPoint; @@ -908,10 +918,11 @@ nsDOMEvent::GetClientCoords(nsPresContext* aPresContext, return CSSIntPoint::FromAppUnitsRounded(pt); } -// To be called ONLY by nsDOMEvent::GetType (which has the additional +// To be called ONLY by Event::GetType (which has the additional // logic for handling user-defined events). // static -const char* nsDOMEvent::GetEventName(uint32_t aEventType) +const char* +Event::GetEventName(uint32_t aEventType) { switch(aEventType) { #define ID_TO_EVENT(name_, _id, _type, _struct) \ @@ -925,12 +936,12 @@ const char* nsDOMEvent::GetEventName(uint32_t aEventType) // create and that are not user defined events since this function and // SetEventType are incomplete. (But fixing that requires fixing the // arrays in nsEventListenerManager too, since the events for which - // this is a problem generally *are* created by nsDOMEvent.) + // this is a problem generally *are* created by Event.) return nullptr; } bool -nsDOMEvent::DefaultPrevented(JSContext* aCx) const +Event::DefaultPrevented(JSContext* aCx) const { MOZ_ASSERT(aCx, "JS context must be specified"); @@ -948,7 +959,7 @@ nsDOMEvent::DefaultPrevented(JSContext* aCx) const } bool -nsDOMEvent::GetPreventDefault() const +Event::GetPreventDefault() const { if (mOwner) { if (nsIDocument* doc = mOwner->GetExtantDoc()) { @@ -962,7 +973,7 @@ nsDOMEvent::GetPreventDefault() const } NS_IMETHODIMP -nsDOMEvent::GetPreventDefault(bool* aReturn) +Event::GetPreventDefault(bool* aReturn) { NS_ENSURE_ARG_POINTER(aReturn); *aReturn = GetPreventDefault(); @@ -970,7 +981,7 @@ nsDOMEvent::GetPreventDefault(bool* aReturn) } NS_IMETHODIMP -nsDOMEvent::GetDefaultPrevented(bool* aReturn) +Event::GetDefaultPrevented(bool* aReturn) { NS_ENSURE_ARG_POINTER(aReturn); // This method must be called by only event handlers implemented by C++. @@ -981,7 +992,7 @@ nsDOMEvent::GetDefaultPrevented(bool* aReturn) } NS_IMETHODIMP_(void) -nsDOMEvent::Serialize(IPC::Message* aMsg, bool aSerializeInterfaceType) +Event::Serialize(IPC::Message* aMsg, bool aSerializeInterfaceType) { if (aSerializeInterfaceType) { IPC::WriteParam(aMsg, NS_LITERAL_STRING("event")); @@ -999,7 +1010,7 @@ nsDOMEvent::Serialize(IPC::Message* aMsg, bool aSerializeInterfaceType) } NS_IMETHODIMP_(bool) -nsDOMEvent::Deserialize(const IPC::Message* aMsg, void** aIter) +Event::Deserialize(const IPC::Message* aMsg, void** aIter) { nsString type; NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &type), false); @@ -1021,7 +1032,7 @@ nsDOMEvent::Deserialize(const IPC::Message* aMsg, void** aIter) } NS_IMETHODIMP_(void) -nsDOMEvent::SetOwner(mozilla::dom::EventTarget* aOwner) +Event::SetOwner(mozilla::dom::EventTarget* aOwner) { mOwner = nullptr; @@ -1057,12 +1068,18 @@ nsDOMEvent::SetOwner(mozilla::dom::EventTarget* aOwner) #endif } -nsresult NS_NewDOMEvent(nsIDOMEvent** aInstancePtrResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - WidgetEvent* aEvent) +} // namespace dom +} // namespace mozilla + +using namespace mozilla; +using namespace mozilla::dom; + +nsresult +NS_NewDOMEvent(nsIDOMEvent** aInstancePtrResult, + EventTarget* aOwner, + nsPresContext* aPresContext, + WidgetEvent* aEvent) { - nsRefPtr it = - new nsDOMEvent(aOwner, aPresContext, aEvent); + Event* it = new Event(aOwner, aPresContext, aEvent); return CallQueryInterface(it, aInstancePtrResult); } diff --git a/dom/events/nsDOMEvent.h b/dom/events/Event.h similarity index 70% rename from dom/events/nsDOMEvent.h rename to dom/events/Event.h index c08fb65a6e2..19c4f71fae5 100644 --- a/dom/events/nsDOMEvent.h +++ b/dom/events/Event.h @@ -3,8 +3,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef nsDOMEvent_h__ -#define nsDOMEvent_h__ +#ifndef mozilla_dom_Event_h_ +#define mozilla_dom_Event_h_ #include "mozilla/Attributes.h" #include "mozilla/BasicEvents.h" @@ -26,29 +26,31 @@ class nsPresContext; namespace mozilla { namespace dom { + class EventTarget; class ErrorEvent; -} -} // Dummy class so we can cast through it to get from nsISupports to -// nsDOMEvent subclasses with only two non-ambiguous static casts. -class nsDOMEventBase : public nsIDOMEvent +// Event subclasses with only two non-ambiguous static casts. +class EventBase : public nsIDOMEvent { }; -class nsDOMEvent : public nsDOMEventBase, - public nsWrapperCache +class Event : public EventBase, + public nsWrapperCache { public: - nsDOMEvent(mozilla::dom::EventTarget* aOwner, nsPresContext* aPresContext, - mozilla::WidgetEvent* aEvent); - nsDOMEvent(nsPIDOMWindow* aWindow); - virtual ~nsDOMEvent(); + Event(EventTarget* aOwner, + nsPresContext* aPresContext, + WidgetEvent* aEvent); + Event(nsPIDOMWindow* aWindow); + virtual ~Event(); + private: - void ConstructorInit(mozilla::dom::EventTarget* aOwner, + void ConstructorInit(EventTarget* aOwner, nsPresContext* aPresContext, - mozilla::WidgetEvent* aEvent); + WidgetEvent* aEvent); + public: void GetParentObject(nsIScriptGlobalObject** aParentObject) { @@ -59,7 +61,7 @@ public: } } - static nsDOMEvent* FromSupports(nsISupports* aSupports) + static Event* FromSupports(nsISupports* aSupports) { nsIDOMEvent* event = static_cast(aSupports); @@ -74,11 +76,11 @@ public: MOZ_ASSERT(target_qi == event, "Uh, fix QI!"); } #endif - return static_cast(event); + return static_cast(event); } NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsDOMEvent) + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Event) nsISupports* GetParentObject() { @@ -88,10 +90,10 @@ public: virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aScope) MOZ_OVERRIDE { - return mozilla::dom::EventBinding::Wrap(aCx, aScope, this); + return EventBinding::Wrap(aCx, aScope, this); } - virtual mozilla::dom::ErrorEvent* AsErrorEvent() + virtual ErrorEvent* AsErrorEvent() { return nullptr; } @@ -102,41 +104,37 @@ public: void InitPresContextData(nsPresContext* aPresContext); // Returns true if the event should be trusted. - bool Init(mozilla::dom::EventTarget* aGlobal); + bool Init(EventTarget* aGlobal); - static PopupControlState GetEventPopupControlState( - mozilla::WidgetEvent* aEvent); + static PopupControlState GetEventPopupControlState(WidgetEvent* aEvent); static void PopupAllowedEventsChanged(); static void Shutdown(); static const char* GetEventName(uint32_t aEventType); - static mozilla::CSSIntPoint - GetClientCoords(nsPresContext* aPresContext, - mozilla::WidgetEvent* aEvent, - mozilla::LayoutDeviceIntPoint aPoint, - mozilla::CSSIntPoint aDefaultPoint); - static mozilla::CSSIntPoint - GetPageCoords(nsPresContext* aPresContext, - mozilla::WidgetEvent* aEvent, - mozilla::LayoutDeviceIntPoint aPoint, - mozilla::CSSIntPoint aDefaultPoint); - static nsIntPoint - GetScreenCoords(nsPresContext* aPresContext, - mozilla::WidgetEvent* aEvent, - mozilla::LayoutDeviceIntPoint aPoint); + static CSSIntPoint GetClientCoords(nsPresContext* aPresContext, + WidgetEvent* aEvent, + LayoutDeviceIntPoint aPoint, + CSSIntPoint aDefaultPoint); + static CSSIntPoint GetPageCoords(nsPresContext* aPresContext, + WidgetEvent* aEvent, + LayoutDeviceIntPoint aPoint, + CSSIntPoint aDefaultPoint); + static nsIntPoint GetScreenCoords(nsPresContext* aPresContext, + WidgetEvent* aEvent, + LayoutDeviceIntPoint aPoint); - static already_AddRefed Constructor(const mozilla::dom::GlobalObject& aGlobal, - const nsAString& aType, - const mozilla::dom::EventInit& aParam, - mozilla::ErrorResult& aRv); + static already_AddRefed Constructor(const GlobalObject& aGlobal, + const nsAString& aType, + const EventInit& aParam, + ErrorResult& aRv); // Implemented as xpidl method // void GetType(nsString& aRetval) {} - mozilla::dom::EventTarget* GetTarget() const; - mozilla::dom::EventTarget* GetCurrentTarget() const; + EventTarget* GetTarget() const; + EventTarget* GetCurrentTarget() const; uint16_t EventPhase() const; @@ -196,13 +194,13 @@ public: } void InitEvent(const nsAString& aType, bool aBubbles, bool aCancelable, - mozilla::ErrorResult& aRv) + ErrorResult& aRv) { aRv = InitEvent(aType, aBubbles, aCancelable); } - mozilla::dom::EventTarget* GetOriginalTarget() const; - mozilla::dom::EventTarget* GetExplicitOriginalTarget() const; + EventTarget* GetOriginalTarget() const; + EventTarget* GetExplicitOriginalTarget() const; bool GetPreventDefault() const; @@ -228,15 +226,18 @@ protected: mozilla::WidgetEvent* mEvent; nsRefPtr mPresContext; - nsCOMPtr mExplicitOriginalTarget; + nsCOMPtr mExplicitOriginalTarget; nsCOMPtr mOwner; // nsPIDOMWindow for now. bool mEventIsInternal; bool mPrivateDataDuplicated; bool mIsMainThreadEvent; }; -#define NS_FORWARD_TO_NSDOMEVENT \ - NS_FORWARD_NSIDOMEVENT(nsDOMEvent::) +} // namespace dom +} // namespace mozilla + +#define NS_FORWARD_TO_EVENT \ + NS_FORWARD_NSIDOMEVENT(Event::) #define NS_FORWARD_NSIDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION(_to) \ NS_IMETHOD GetType(nsAString& aType){ return _to GetType(aType); } \ @@ -257,24 +258,24 @@ protected: NS_IMETHOD GetIsTrusted(bool* aIsTrusted) { return _to GetIsTrusted(aIsTrusted); } \ NS_IMETHOD SetTarget(nsIDOMEventTarget *aTarget) { return _to SetTarget(aTarget); } \ NS_IMETHOD_(bool) IsDispatchStopped(void) { return _to IsDispatchStopped(); } \ - NS_IMETHOD_(mozilla::WidgetEvent*) GetInternalNSEvent(void) { return _to GetInternalNSEvent(); } \ + NS_IMETHOD_(WidgetEvent*) GetInternalNSEvent(void) { return _to GetInternalNSEvent(); } \ NS_IMETHOD_(void) SetTrusted(bool aTrusted) { _to SetTrusted(aTrusted); } \ - NS_IMETHOD_(void) SetOwner(mozilla::dom::EventTarget* aOwner) { _to SetOwner(aOwner); } \ - NS_IMETHOD_(nsDOMEvent *) InternalDOMEvent(void) { return _to InternalDOMEvent(); } + NS_IMETHOD_(void) SetOwner(EventTarget* aOwner) { _to SetOwner(aOwner); } \ + NS_IMETHOD_(Event*) InternalDOMEvent() { return _to InternalDOMEvent(); } -#define NS_FORWARD_TO_NSDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION \ - NS_FORWARD_NSIDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION(nsDOMEvent::) +#define NS_FORWARD_TO_EVENT_NO_SERIALIZATION_NO_DUPLICATION \ + NS_FORWARD_NSIDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION(Event::) inline nsISupports* -ToSupports(nsDOMEvent* e) +ToSupports(mozilla::dom::Event* e) { return static_cast(e); } inline nsISupports* -ToCanonicalSupports(nsDOMEvent* e) +ToCanonicalSupports(mozilla::dom::Event* e) { return static_cast(e); } -#endif // nsDOMEvent_h__ +#endif // mozilla_dom_Event_h_ diff --git a/dom/events/EventTarget.h b/dom/events/EventTarget.h index 8ac04ba23f7..6ecf323fa0b 100644 --- a/dom/events/EventTarget.h +++ b/dom/events/EventTarget.h @@ -10,7 +10,6 @@ #include "nsWrapperCache.h" #include "nsIAtom.h" -class nsDOMEvent; class nsIDOMWindow; class nsIDOMEventListener; @@ -20,6 +19,7 @@ class ErrorResult; namespace dom { +class Event; class EventListener; class EventHandlerNonNull; template struct Nullable; @@ -48,7 +48,7 @@ public: EventListener* aCallback, bool aCapture, ErrorResult& aRv); - bool DispatchEvent(nsDOMEvent& aEvent, ErrorResult& aRv); + bool DispatchEvent(Event& aEvent, ErrorResult& aRv); // Note, this takes the type in onfoo form! EventHandlerNonNull* GetEventHandler(const nsAString& aType) diff --git a/dom/events/MessageEvent.cpp b/dom/events/MessageEvent.cpp index fd974df9aa4..9f78dce8ae0 100644 --- a/dom/events/MessageEvent.cpp +++ b/dom/events/MessageEvent.cpp @@ -18,34 +18,34 @@ namespace dom { NS_IMPL_CYCLE_COLLECTION_CLASS(MessageEvent) -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MessageEvent, nsDOMEvent) +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MessageEvent, Event) tmp->mData = JSVAL_VOID; NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindowSource) NS_IMPL_CYCLE_COLLECTION_UNLINK(mPortSource) NS_IMPL_CYCLE_COLLECTION_UNLINK(mPorts) NS_IMPL_CYCLE_COLLECTION_UNLINK_END -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MessageEvent, nsDOMEvent) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MessageEvent, Event) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindowSource) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPortSource) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPorts) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END -NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(MessageEvent, nsDOMEvent) +NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(MessageEvent, Event) NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mData) NS_IMPL_CYCLE_COLLECTION_TRACE_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MessageEvent) NS_INTERFACE_MAP_ENTRY(nsIDOMMessageEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) -NS_IMPL_ADDREF_INHERITED(MessageEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(MessageEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(MessageEvent, Event) +NS_IMPL_RELEASE_INHERITED(MessageEvent, Event) MessageEvent::MessageEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, aEvent) + : Event(aOwner, aPresContext, aEvent) , mData(JSVAL_VOID) { } @@ -156,8 +156,7 @@ MessageEvent::Constructor(const GlobalObject& aGlobal, ports.AppendElement(aParam.mPorts.Value().Value()[i].get()); } - event->mPorts = new MessagePortList(static_cast(event), - ports); + event->mPorts = new MessagePortList(static_cast(event), ports); } return event.forget(); @@ -172,7 +171,7 @@ MessageEvent::InitMessageEvent(const nsAString& aType, const nsAString& aLastEventId, nsIDOMWindow* aSource) { - nsresult rv = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable); + nsresult rv = Event::InitEvent(aType, aCanBubble, aCancelable); NS_ENSURE_SUCCESS(rv, rv); mData = aData; diff --git a/dom/events/MessageEvent.h b/dom/events/MessageEvent.h index 70f557cb1d2..a83814e4718 100644 --- a/dom/events/MessageEvent.h +++ b/dom/events/MessageEvent.h @@ -6,9 +6,9 @@ #ifndef mozilla_dom_MessageEvent_h_ #define mozilla_dom_MessageEvent_h_ -#include "nsIDOMMessageEvent.h" -#include "nsDOMEvent.h" +#include "mozilla/dom/Event.h" #include "nsCycleCollectionParticipant.h" +#include "nsIDOMMessageEvent.h" namespace mozilla { namespace dom { @@ -26,7 +26,7 @@ class OwningWindowProxyOrMessagePort; * See http://www.whatwg.org/specs/web-apps/current-work/#messageevent for * further details. */ -class MessageEvent : public nsDOMEvent, +class MessageEvent : public Event, public nsIDOMMessageEvent { public: @@ -36,13 +36,12 @@ public: ~MessageEvent(); NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(MessageEvent, - nsDOMEvent) + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(MessageEvent, Event) NS_DECL_NSIDOMMESSAGEEVENT // Forward to base class - NS_FORWARD_TO_NSDOMEVENT + NS_FORWARD_TO_EVENT virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aScope) MOZ_OVERRIDE; diff --git a/dom/events/MouseEvent.cpp b/dom/events/MouseEvent.cpp index a2029a702d0..9f5571bcc6c 100644 --- a/dom/events/MouseEvent.cpp +++ b/dom/events/MouseEvent.cpp @@ -324,9 +324,7 @@ MouseEvent::GetScreenX(int32_t* aScreenX) int32_t MouseEvent::ScreenX() { - return nsDOMEvent::GetScreenCoords(mPresContext, - mEvent, - mEvent->refPoint).x; + return Event::GetScreenCoords(mPresContext, mEvent, mEvent->refPoint).x; } NS_IMETHODIMP @@ -340,9 +338,7 @@ MouseEvent::GetScreenY(int32_t* aScreenY) int32_t MouseEvent::ScreenY() { - return nsDOMEvent::GetScreenCoords(mPresContext, - mEvent, - mEvent->refPoint).y; + return Event::GetScreenCoords(mPresContext, mEvent, mEvent->refPoint).y; } @@ -357,10 +353,8 @@ MouseEvent::GetClientX(int32_t* aClientX) int32_t MouseEvent::ClientX() { - return nsDOMEvent::GetClientCoords(mPresContext, - mEvent, - mEvent->refPoint, - mClientPoint).x; + return Event::GetClientCoords(mPresContext, mEvent, mEvent->refPoint, + mClientPoint).x; } NS_IMETHODIMP @@ -374,10 +368,8 @@ MouseEvent::GetClientY(int32_t* aClientY) int32_t MouseEvent::ClientY() { - return nsDOMEvent::GetClientCoords(mPresContext, - mEvent, - mEvent->refPoint, - mClientPoint).y; + return Event::GetClientCoords(mPresContext, mEvent, mEvent->refPoint, + mClientPoint).y; } bool diff --git a/dom/events/MutationEvent.cpp b/dom/events/MutationEvent.cpp index d3a784eda54..54773e71d39 100644 --- a/dom/events/MutationEvent.cpp +++ b/dom/events/MutationEvent.cpp @@ -15,18 +15,18 @@ namespace dom { MutationEvent::MutationEvent(EventTarget* aOwner, nsPresContext* aPresContext, InternalMutationEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, - aEvent ? aEvent : new InternalMutationEvent(false, 0)) + : Event(aOwner, aPresContext, + aEvent ? aEvent : new InternalMutationEvent(false, 0)) { mEventIsInternal = (aEvent == nullptr); } NS_INTERFACE_MAP_BEGIN(MutationEvent) NS_INTERFACE_MAP_ENTRY(nsIDOMMutationEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) -NS_IMPL_ADDREF_INHERITED(MutationEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(MutationEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(MutationEvent, Event) +NS_IMPL_RELEASE_INHERITED(MutationEvent, Event) already_AddRefed MutationEvent::GetRelatedNode() @@ -95,7 +95,7 @@ MutationEvent::InitMutationEvent(const nsAString& aTypeArg, const nsAString& aAttrNameArg, uint16_t aAttrChangeArg) { - nsresult rv = nsDOMEvent::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg); + nsresult rv = Event::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg); NS_ENSURE_SUCCESS(rv, rv); InternalMutationEvent* mutation = mEvent->AsMutationEvent(); diff --git a/dom/events/MutationEvent.h b/dom/events/MutationEvent.h index 4b18320abfa..869479a8678 100644 --- a/dom/events/MutationEvent.h +++ b/dom/events/MutationEvent.h @@ -6,16 +6,16 @@ #ifndef mozilla_dom_MutationEvent_h_ #define mozilla_dom_MutationEvent_h_ +#include "mozilla/EventForwards.h" +#include "mozilla/dom/Event.h" +#include "mozilla/dom/MutationEventBinding.h" #include "nsIDOMMutationEvent.h" #include "nsINode.h" -#include "nsDOMEvent.h" -#include "mozilla/dom/MutationEventBinding.h" -#include "mozilla/EventForwards.h" namespace mozilla { namespace dom { -class MutationEvent : public nsDOMEvent, +class MutationEvent : public Event, public nsIDOMMutationEvent { public: @@ -28,7 +28,7 @@ public: NS_DECL_NSIDOMMUTATIONEVENT // Forward to base class - NS_FORWARD_TO_NSDOMEVENT + NS_FORWARD_TO_EVENT virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aScope) MOZ_OVERRIDE diff --git a/dom/events/NotifyAudioAvailableEvent.cpp b/dom/events/NotifyAudioAvailableEvent.cpp index 4f43f3fc338..e6fa57d6d3f 100644 --- a/dom/events/NotifyAudioAvailableEvent.cpp +++ b/dom/events/NotifyAudioAvailableEvent.cpp @@ -20,7 +20,7 @@ NotifyAudioAvailableEvent::NotifyAudioAvailableEvent( float* aFrameBuffer, uint32_t aFrameBufferLength, float aTime) - : nsDOMEvent(aOwner, aPresContext, aEvent) + : Event(aOwner, aPresContext, aEvent) , mFrameBuffer(aFrameBuffer) , mFrameBufferLength(aFrameBufferLength) , mTime(aTime) @@ -33,13 +33,13 @@ NotifyAudioAvailableEvent::NotifyAudioAvailableEvent( } } -NS_IMPL_ADDREF_INHERITED(NotifyAudioAvailableEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(NotifyAudioAvailableEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(NotifyAudioAvailableEvent, Event) +NS_IMPL_RELEASE_INHERITED(NotifyAudioAvailableEvent, Event) NS_IMPL_CYCLE_COLLECTION_CLASS(NotifyAudioAvailableEvent) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(NotifyAudioAvailableEvent, - nsDOMEvent) + Event) if (tmp->mCachedArray) { tmp->mCachedArray = nullptr; DropJSObjects(tmp); @@ -47,17 +47,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(NotifyAudioAvailableEvent, NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(NotifyAudioAvailableEvent, - nsDOMEvent) + Event) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(NotifyAudioAvailableEvent, - nsDOMEvent) + Event) NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCachedArray) NS_IMPL_CYCLE_COLLECTION_TRACE_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(NotifyAudioAvailableEvent) NS_INTERFACE_MAP_ENTRY(nsIDOMNotifyAudioAvailableEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) NotifyAudioAvailableEvent::~NotifyAudioAvailableEvent() { @@ -117,7 +117,7 @@ NotifyAudioAvailableEvent::InitAudioAvailableEvent(const nsAString& aType, // that if we exit due to some error, the memory will be freed. Otherwise, // the framebuffer's memory will be freed when this event is destroyed. nsAutoArrayPtr frameBuffer(aFrameBuffer); - nsresult rv = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable); + nsresult rv = Event::InitEvent(aType, aCanBubble, aCancelable); NS_ENSURE_SUCCESS(rv, rv); mFrameBuffer = frameBuffer.forget(); diff --git a/dom/events/NotifyAudioAvailableEvent.h b/dom/events/NotifyAudioAvailableEvent.h index 6061288d4a4..74e183392b3 100644 --- a/dom/events/NotifyAudioAvailableEvent.h +++ b/dom/events/NotifyAudioAvailableEvent.h @@ -7,17 +7,17 @@ #ifndef mozilla_dom_NotifyAudioAvailableEvent_h_ #define mozilla_dom_NotifyAudioAvailableEvent_h_ -#include "nsIDOMNotifyAudioAvailableEvent.h" -#include "nsDOMEvent.h" -#include "nsCycleCollectionParticipant.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/NotifyAudioAvailableEventBinding.h" +#include "nsCycleCollectionParticipant.h" +#include "nsIDOMNotifyAudioAvailableEvent.h" class nsPresContext; namespace mozilla { namespace dom { -class NotifyAudioAvailableEvent : public nsDOMEvent, +class NotifyAudioAvailableEvent : public Event, public nsIDOMNotifyAudioAvailableEvent { public: @@ -31,10 +31,10 @@ public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED( - NotifyAudioAvailableEvent, nsDOMEvent) + NotifyAudioAvailableEvent, Event) NS_DECL_NSIDOMNOTIFYAUDIOAVAILABLEEVENT - NS_FORWARD_NSIDOMEVENT(nsDOMEvent::) + NS_FORWARD_NSIDOMEVENT(Event::) ~NotifyAudioAvailableEvent(); diff --git a/dom/events/NotifyPaintEvent.cpp b/dom/events/NotifyPaintEvent.cpp index 4d9dc9e8ded..29b9eef326f 100644 --- a/dom/events/NotifyPaintEvent.cpp +++ b/dom/events/NotifyPaintEvent.cpp @@ -19,7 +19,7 @@ NotifyPaintEvent::NotifyPaintEvent(EventTarget* aOwner, WidgetEvent* aEvent, uint32_t aEventType, nsInvalidateRequestList* aInvalidateRequests) -: nsDOMEvent(aOwner, aPresContext, aEvent) + : Event(aOwner, aPresContext, aEvent) { if (mEvent) { mEvent->message = aEventType; @@ -31,10 +31,10 @@ NotifyPaintEvent::NotifyPaintEvent(EventTarget* aOwner, NS_INTERFACE_MAP_BEGIN(NotifyPaintEvent) NS_INTERFACE_MAP_ENTRY(nsIDOMNotifyPaintEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) -NS_IMPL_ADDREF_INHERITED(NotifyPaintEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(NotifyPaintEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(NotifyPaintEvent, Event) +NS_IMPL_RELEASE_INHERITED(NotifyPaintEvent, Event) nsRegion NotifyPaintEvent::GetRegion() @@ -105,7 +105,7 @@ NotifyPaintEvent::GetPaintRequests(nsISupports** aResult) already_AddRefed NotifyPaintEvent::PaintRequests() { - nsDOMEvent* parent = this; + Event* parent = this; nsRefPtr requests = new nsPaintRequestList(parent); if (nsContentUtils::IsCallerChrome()) { @@ -127,7 +127,7 @@ NotifyPaintEvent::Serialize(IPC::Message* aMsg, IPC::WriteParam(aMsg, NS_LITERAL_STRING("notifypaintevent")); } - nsDOMEvent::Serialize(aMsg, false); + Event::Serialize(aMsg, false); uint32_t length = mInvalidateRequests.Length(); IPC::WriteParam(aMsg, length); @@ -140,7 +140,7 @@ NotifyPaintEvent::Serialize(IPC::Message* aMsg, NS_IMETHODIMP_(bool) NotifyPaintEvent::Deserialize(const IPC::Message* aMsg, void** aIter) { - NS_ENSURE_TRUE(nsDOMEvent::Deserialize(aMsg, aIter), false); + NS_ENSURE_TRUE(Event::Deserialize(aMsg, aIter), false); uint32_t length = 0; NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &length), false); diff --git a/dom/events/NotifyPaintEvent.h b/dom/events/NotifyPaintEvent.h index 9f5f0996a70..b067fc498ae 100644 --- a/dom/events/NotifyPaintEvent.h +++ b/dom/events/NotifyPaintEvent.h @@ -7,10 +7,10 @@ #define mozilla_dom_NotifyPaintEvent_h_ #include "mozilla/Attributes.h" -#include "nsIDOMNotifyPaintEvent.h" -#include "nsDOMEvent.h" -#include "nsPresContext.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/NotifyPaintEventBinding.h" +#include "nsIDOMNotifyPaintEvent.h" +#include "nsPresContext.h" class nsPaintRequestList; @@ -20,7 +20,7 @@ namespace dom { class DOMRect; class DOMRectList; -class NotifyPaintEvent : public nsDOMEvent, +class NotifyPaintEvent : public Event, public nsIDOMNotifyPaintEvent { @@ -36,10 +36,10 @@ public: NS_DECL_NSIDOMNOTIFYPAINTEVENT // Forward to base class - NS_FORWARD_TO_NSDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION + NS_FORWARD_TO_EVENT_NO_SERIALIZATION_NO_DUPLICATION NS_IMETHOD DuplicatePrivateData() MOZ_OVERRIDE { - return nsDOMEvent::DuplicatePrivateData(); + return Event::DuplicatePrivateData(); } NS_IMETHOD_(void) Serialize(IPC::Message* aMsg, bool aSerializeInterfaceType) MOZ_OVERRIDE; NS_IMETHOD_(bool) Deserialize(const IPC::Message* aMsg, void** aIter) MOZ_OVERRIDE; diff --git a/dom/events/ScrollAreaEvent.cpp b/dom/events/ScrollAreaEvent.cpp index 587fb54d3b4..89428dc68b0 100644 --- a/dom/events/ScrollAreaEvent.cpp +++ b/dom/events/ScrollAreaEvent.cpp @@ -70,7 +70,7 @@ ScrollAreaEvent::Serialize(IPC::Message* aMsg, IPC::WriteParam(aMsg, NS_LITERAL_STRING("scrollareaevent")); } - nsDOMEvent::Serialize(aMsg, false); + Event::Serialize(aMsg, false); IPC::WriteParam(aMsg, X()); IPC::WriteParam(aMsg, Y()); @@ -81,7 +81,7 @@ ScrollAreaEvent::Serialize(IPC::Message* aMsg, NS_IMETHODIMP_(bool) ScrollAreaEvent::Deserialize(const IPC::Message* aMsg, void** aIter) { - NS_ENSURE_TRUE(nsDOMEvent::Deserialize(aMsg, aIter), false); + NS_ENSURE_TRUE(Event::Deserialize(aMsg, aIter), false); float x, y, width, height; NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &x), false); diff --git a/dom/events/ScrollAreaEvent.h b/dom/events/ScrollAreaEvent.h index dbd56468f20..7f9c180b479 100644 --- a/dom/events/ScrollAreaEvent.h +++ b/dom/events/ScrollAreaEvent.h @@ -30,10 +30,10 @@ public: NS_FORWARD_NSIDOMUIEVENT(UIEvent::) - NS_FORWARD_TO_NSDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION + NS_FORWARD_TO_EVENT_NO_SERIALIZATION_NO_DUPLICATION NS_IMETHOD DuplicatePrivateData() { - return nsDOMEvent::DuplicatePrivateData(); + return Event::DuplicatePrivateData(); } NS_IMETHOD_(void) Serialize(IPC::Message* aMsg, bool aSerializeInterfaceType) MOZ_OVERRIDE; NS_IMETHOD_(bool) Deserialize(const IPC::Message* aMsg, void** aIter) MOZ_OVERRIDE; diff --git a/dom/events/SpeechRecognitionError.cpp b/dom/events/SpeechRecognitionError.cpp index 5befc62f2df..75e5c3f00ef 100644 --- a/dom/events/SpeechRecognitionError.cpp +++ b/dom/events/SpeechRecognitionError.cpp @@ -12,9 +12,10 @@ SpeechRecognitionError::SpeechRecognitionError( mozilla::dom::EventTarget* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent) -: nsDOMEvent(aOwner, aPresContext, aEvent), - mError() -{} + : Event(aOwner, aPresContext, aEvent) + , mError() +{ +} SpeechRecognitionError::~SpeechRecognitionError() {} @@ -40,7 +41,7 @@ SpeechRecognitionError::InitSpeechRecognitionError(const nsAString& aType, const nsAString& aMessage, ErrorResult& aRv) { - aRv = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable); + aRv = Event::InitEvent(aType, aCanBubble, aCancelable); NS_ENSURE_SUCCESS_VOID(aRv.ErrorCode()); mError = aError; diff --git a/dom/events/SpeechRecognitionError.h b/dom/events/SpeechRecognitionError.h index db1ea13b4cb..35cc2f10cf6 100644 --- a/dom/events/SpeechRecognitionError.h +++ b/dom/events/SpeechRecognitionError.h @@ -6,13 +6,13 @@ #ifndef SpeechRecognitionError_h__ #define SpeechRecognitionError_h__ -#include "nsDOMEvent.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/SpeechRecognitionErrorBinding.h" namespace mozilla { namespace dom { -class SpeechRecognitionError : public nsDOMEvent +class SpeechRecognitionError : public Event { public: SpeechRecognitionError(mozilla::dom::EventTarget* aOwner, diff --git a/dom/events/Touch.cpp b/dom/events/Touch.cpp index c5ef4f2ac87..f707d050924 100644 --- a/dom/events/Touch.cpp +++ b/dom/events/Touch.cpp @@ -106,13 +106,13 @@ Touch::InitializePoints(nsPresContext* aPresContext, WidgetEvent* aEvent) if (mPointsInitialized) { return; } - mClientPoint = nsDOMEvent::GetClientCoords( + mClientPoint = Event::GetClientCoords( aPresContext, aEvent, LayoutDeviceIntPoint::FromUntyped(mRefPoint), mClientPoint); - mPagePoint = nsDOMEvent::GetPageCoords( + mPagePoint = Event::GetPageCoords( aPresContext, aEvent, LayoutDeviceIntPoint::FromUntyped(mRefPoint), mClientPoint); - mScreenPoint = nsDOMEvent::GetScreenCoords(aPresContext, aEvent, + mScreenPoint = Event::GetScreenCoords(aPresContext, aEvent, LayoutDeviceIntPoint::FromUntyped(mRefPoint)); mPointsInitialized = true; } diff --git a/dom/events/TransitionEvent.cpp b/dom/events/TransitionEvent.cpp index dc016d633fa..24aa9cfdbc4 100644 --- a/dom/events/TransitionEvent.cpp +++ b/dom/events/TransitionEvent.cpp @@ -13,8 +13,8 @@ namespace dom { TransitionEvent::TransitionEvent(EventTarget* aOwner, nsPresContext* aPresContext, InternalTransitionEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, - aEvent ? aEvent : new InternalTransitionEvent(false, 0)) + : Event(aOwner, aPresContext, + aEvent ? aEvent : new InternalTransitionEvent(false, 0)) { if (aEvent) { mEventIsInternal = false; @@ -27,10 +27,10 @@ TransitionEvent::TransitionEvent(EventTarget* aOwner, NS_INTERFACE_MAP_BEGIN(TransitionEvent) NS_INTERFACE_MAP_ENTRY(nsIDOMTransitionEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) -NS_IMPL_ADDREF_INHERITED(TransitionEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(TransitionEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(TransitionEvent, Event) +NS_IMPL_RELEASE_INHERITED(TransitionEvent, Event) // static already_AddRefed diff --git a/dom/events/TransitionEvent.h b/dom/events/TransitionEvent.h index 5bab83b8e05..194f6ba4629 100644 --- a/dom/events/TransitionEvent.h +++ b/dom/events/TransitionEvent.h @@ -5,17 +5,17 @@ #ifndef mozilla_dom_TransitionEvent_h_ #define mozilla_dom_TransitionEvent_h_ -#include "nsDOMEvent.h" -#include "nsIDOMTransitionEvent.h" #include "mozilla/EventForwards.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/TransitionEventBinding.h" +#include "nsIDOMTransitionEvent.h" class nsAString; namespace mozilla { namespace dom { -class TransitionEvent : public nsDOMEvent, +class TransitionEvent : public Event, public nsIDOMTransitionEvent { public: @@ -24,7 +24,7 @@ public: InternalTransitionEvent* aEvent); NS_DECL_ISUPPORTS_INHERITED - NS_FORWARD_TO_NSDOMEVENT + NS_FORWARD_TO_EVENT NS_DECL_NSIDOMTRANSITIONEVENT static already_AddRefed diff --git a/dom/events/UIEvent.cpp b/dom/events/UIEvent.cpp index d40b93cc42d..f634ec38977 100644 --- a/dom/events/UIEvent.cpp +++ b/dom/events/UIEvent.cpp @@ -26,8 +26,8 @@ namespace dom { UIEvent::UIEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetGUIEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, - aEvent ? aEvent : new InternalUIEvent(false, 0)) + : Event(aOwner, aPresContext, + aEvent ? aEvent : new InternalUIEvent(false, 0)) , mClientPoint(0, 0) , mLayerPoint(0, 0) , mPagePoint(0, 0) @@ -94,15 +94,15 @@ UIEvent::Constructor(const GlobalObject& aGlobal, return e.forget(); } -NS_IMPL_CYCLE_COLLECTION_INHERITED_1(UIEvent, nsDOMEvent, +NS_IMPL_CYCLE_COLLECTION_INHERITED_1(UIEvent, Event, mView) -NS_IMPL_ADDREF_INHERITED(UIEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(UIEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(UIEvent, Event) +NS_IMPL_RELEASE_INHERITED(UIEvent, Event) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(UIEvent) NS_INTERFACE_MAP_ENTRY(nsIDOMUIEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) static nsIntPoint DevPixelsToCSSPixels(const LayoutDeviceIntPoint& aPoint, @@ -162,7 +162,7 @@ UIEvent::InitUIEvent(const nsAString& typeArg, nsCOMPtr view = do_QueryInterface(viewArg); NS_ENSURE_TRUE(view, NS_ERROR_INVALID_ARG); } - nsresult rv = nsDOMEvent::InitEvent(typeArg, canBubbleArg, cancelableArg); + nsresult rv = Event::InitEvent(typeArg, canBubbleArg, cancelableArg); NS_ENSURE_SUCCESS(rv, rv); mDetail = detailArg; @@ -186,10 +186,8 @@ UIEvent::PageX() const return mPagePoint.x; } - return nsDOMEvent::GetPageCoords(mPresContext, - mEvent, - mEvent->refPoint, - mClientPoint).x; + return Event::GetPageCoords(mPresContext, mEvent, mEvent->refPoint, + mClientPoint).x; } NS_IMETHODIMP @@ -207,10 +205,8 @@ UIEvent::PageY() const return mPagePoint.y; } - return nsDOMEvent::GetPageCoords(mPresContext, - mEvent, - mEvent->refPoint, - mClientPoint).y; + return Event::GetPageCoords(mPresContext, mEvent, mEvent->refPoint, + mClientPoint).y; } NS_IMETHODIMP @@ -360,21 +356,17 @@ UIEvent::IsChar() const NS_IMETHODIMP UIEvent::DuplicatePrivateData() { - mClientPoint = nsDOMEvent::GetClientCoords(mPresContext, - mEvent, - mEvent->refPoint, - mClientPoint); + mClientPoint = + Event::GetClientCoords(mPresContext, mEvent, mEvent->refPoint, + mClientPoint); mMovementPoint = GetMovementPoint(); mLayerPoint = GetLayerPoint(); - mPagePoint = nsDOMEvent::GetPageCoords(mPresContext, - mEvent, - mEvent->refPoint, - mClientPoint); + mPagePoint = + Event::GetPageCoords(mPresContext, mEvent, mEvent->refPoint, mClientPoint); // GetScreenPoint converts mEvent->refPoint to right coordinates. - nsIntPoint screenPoint = nsDOMEvent::GetScreenCoords(mPresContext, - mEvent, - mEvent->refPoint); - nsresult rv = nsDOMEvent::DuplicatePrivateData(); + nsIntPoint screenPoint = + Event::GetScreenCoords(mPresContext, mEvent, mEvent->refPoint); + nsresult rv = Event::DuplicatePrivateData(); if (NS_SUCCEEDED(rv)) { mEvent->refPoint = LayoutDeviceIntPoint::FromUntyped(screenPoint); } @@ -388,7 +380,7 @@ UIEvent::Serialize(IPC::Message* aMsg, bool aSerializeInterfaceType) IPC::WriteParam(aMsg, NS_LITERAL_STRING("uievent")); } - nsDOMEvent::Serialize(aMsg, false); + Event::Serialize(aMsg, false); int32_t detail = 0; GetDetail(&detail); @@ -398,7 +390,7 @@ UIEvent::Serialize(IPC::Message* aMsg, bool aSerializeInterfaceType) NS_IMETHODIMP_(bool) UIEvent::Deserialize(const IPC::Message* aMsg, void** aIter) { - NS_ENSURE_TRUE(nsDOMEvent::Deserialize(aMsg, aIter), false); + NS_ENSURE_TRUE(Event::Deserialize(aMsg, aIter), false); NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &mDetail), false); return true; } diff --git a/dom/events/UIEvent.h b/dom/events/UIEvent.h index 87d0db49b38..82f68634052 100644 --- a/dom/events/UIEvent.h +++ b/dom/events/UIEvent.h @@ -7,19 +7,19 @@ #define mozilla_dom_UIEvent_h_ #include "mozilla/Attributes.h" -#include "nsIDOMUIEvent.h" -#include "nsDOMEvent.h" -#include "nsLayoutUtils.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/UIEventBinding.h" -#include "nsPresContext.h" #include "nsDeviceContext.h" +#include "nsIDOMUIEvent.h" +#include "nsLayoutUtils.h" +#include "nsPresContext.h" class nsINode; namespace mozilla { namespace dom { -class UIEvent : public nsDOMEvent, +class UIEvent : public Event, public nsIDOMUIEvent { public: @@ -28,13 +28,13 @@ public: WidgetGUIEvent* aEvent); NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(UIEvent, nsDOMEvent) + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(UIEvent, Event) // nsIDOMUIEvent Interface NS_DECL_NSIDOMUIEVENT - // Forward to nsDOMEvent - NS_FORWARD_TO_NSDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION + // Forward to Event + NS_FORWARD_TO_EVENT_NO_SERIALIZATION_NO_DUPLICATION NS_IMETHOD DuplicatePrivateData() MOZ_OVERRIDE; NS_IMETHOD_(void) Serialize(IPC::Message* aMsg, bool aSerializeInterfaceType) MOZ_OVERRIDE; NS_IMETHOD_(bool) Deserialize(const IPC::Message* aMsg, void** aIter) MOZ_OVERRIDE; @@ -175,7 +175,7 @@ protected: #define NS_FORWARD_TO_UIEVENT \ NS_FORWARD_NSIDOMUIEVENT(UIEvent::) \ - NS_FORWARD_TO_NSDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION \ + NS_FORWARD_TO_EVENT_NO_SERIALIZATION_NO_DUPLICATION \ NS_IMETHOD DuplicatePrivateData() \ { \ return UIEvent::DuplicatePrivateData(); \ diff --git a/dom/events/XULCommandEvent.h b/dom/events/XULCommandEvent.h index 5d4702a26d9..c21d7c3185d 100644 --- a/dom/events/XULCommandEvent.h +++ b/dom/events/XULCommandEvent.h @@ -42,9 +42,9 @@ public: bool ShiftKey(); bool MetaKey(); - already_AddRefed GetSourceEvent() + already_AddRefed GetSourceEvent() { - nsRefPtr e = + nsRefPtr e = mSourceEvent ? mSourceEvent->InternalDOMEvent() : nullptr; return e.forget(); } @@ -55,7 +55,7 @@ public: int32_t aDetail, bool aCtrlKey, bool aAltKey, bool aShiftKey, bool aMetaKey, - nsDOMEvent* aSourceEvent, + Event* aSourceEvent, ErrorResult& aRv) { aRv = InitCommandEvent(aType, aCanBubble, aCancelable, aView, aDetail, diff --git a/dom/events/moz.build b/dom/events/moz.build index a53182737d7..14503654eeb 100644 --- a/dom/events/moz.build +++ b/dom/events/moz.build @@ -15,7 +15,6 @@ XPIDL_MODULE = 'content_events' EXPORTS += [ 'nsAsyncDOMEvent.h', - 'nsDOMEvent.h', 'nsDOMEventTargetHelper.h', 'nsDOMKeyNameList.h', 'nsEventDispatcher.h', @@ -41,6 +40,7 @@ EXPORTS.mozilla.dom += [ 'DataTransfer.h', 'DeviceMotionEvent.h', 'DragEvent.h', + 'Event.h', 'EventTarget.h', 'FocusEvent.h', 'KeyboardEvent.h', @@ -74,6 +74,7 @@ UNIFIED_SOURCES += [ 'DataTransfer.cpp', 'DeviceMotionEvent.cpp', 'DragEvent.cpp', + 'Event.cpp', 'EventTarget.cpp', 'FocusEvent.cpp', 'KeyboardEvent.cpp', @@ -85,7 +86,6 @@ UNIFIED_SOURCES += [ 'NotifyPaintEvent.cpp', 'nsAsyncDOMEvent.cpp', 'nsContentEventHandler.cpp', - 'nsDOMEvent.cpp', 'nsDOMEventTargetHelper.cpp', 'nsEventDispatcher.cpp', 'nsEventListenerManager.cpp', diff --git a/dom/events/nsAsyncDOMEvent.cpp b/dom/events/nsAsyncDOMEvent.cpp index 79bd7a1b547..aba5ae231c1 100644 --- a/dom/events/nsAsyncDOMEvent.cpp +++ b/dom/events/nsAsyncDOMEvent.cpp @@ -7,8 +7,8 @@ #include "nsIDOMEvent.h" #include "nsContentUtils.h" #include "nsEventDispatcher.h" -#include "nsDOMEvent.h" #include "mozilla/BasicEvents.h" +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() #include "mozilla/dom/EventTarget.h" using namespace mozilla; diff --git a/dom/events/nsEventDispatcher.cpp b/dom/events/nsEventDispatcher.cpp index f5b319bbb6d..af358db6617 100644 --- a/dom/events/nsEventDispatcher.cpp +++ b/dom/events/nsEventDispatcher.cpp @@ -610,7 +610,7 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget, aEvent->mFlags.mDispatchedAtLeastOnce = true; if (!externalDOMEvent && preVisitor.mDOMEvent) { - // An nsDOMEvent was created while dispatching the event. + // An dom::Event was created while dispatching the event. // Duplicate private data if someone holds a pointer to it. nsrefcnt rc = 0; NS_RELEASE2(preVisitor.mDOMEvent, rc); diff --git a/dom/events/nsEventListenerManager.cpp b/dom/events/nsEventListenerManager.cpp index 183ca62a0e7..fc367734646 100644 --- a/dom/events/nsEventListenerManager.cpp +++ b/dom/events/nsEventListenerManager.cpp @@ -13,7 +13,7 @@ #undef CreateEvent #include "nsISupports.h" -#include "nsDOMEvent.h" +#include "mozilla/dom/Event.h" #include "nsEventListenerManager.h" #include "nsIDOMEventListener.h" #include "nsGkAtoms.h" @@ -137,7 +137,7 @@ nsEventListenerManager::RemoveAllListeners() void nsEventListenerManager::Shutdown() { - nsDOMEvent::Shutdown(); + Event::Shutdown(); } NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsEventListenerManager, AddRef) @@ -809,7 +809,8 @@ nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerS JS::Rooted scope(cx, listener->GetEventScope()); - nsIAtom* attrName = aListenerStruct->mTypeAtom; + nsCOMPtr typeAtom = aListenerStruct->mTypeAtom; + nsIAtom* attrName = typeAtom; if (aListenerStruct->mHandlerIsString) { // OK, we didn't find an existing compiled event handler. Flag us @@ -850,6 +851,7 @@ nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerS body = &handlerBody; aElement = element; } + aListenerStruct = nullptr; uint32_t lineNo = 0; nsAutoCString url (NS_LITERAL_CSTRING("-moz-evil:lying-event-listener")); @@ -864,7 +866,7 @@ nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerS uint32_t argCount; const char **argNames; nsContentUtils::GetEventArgNames(aElement->GetNameSpaceID(), - aListenerStruct->mTypeAtom, + typeAtom, &argCount, &argNames); JSAutoCompartment ac(cx, context->GetWindowProxy()); @@ -894,11 +896,13 @@ nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerS JS::Rooted handlerFun(cx); result = nsJSUtils::CompileFunction(cx, JS::NullPtr(), options, - nsAtomCString(aListenerStruct->mTypeAtom), + nsAtomCString(typeAtom), argCount, argNames, *body, handlerFun.address()); NS_ENSURE_SUCCESS(result, result); handler = handlerFun; NS_ENSURE_TRUE(handler, NS_ERROR_FAILURE); + } else { + aListenerStruct = nullptr; } if (handler) { @@ -906,7 +910,6 @@ nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerS // Bind it JS::Rooted boundHandler(cx); context->BindCompiledEventHandler(mTarget, scope, handler, &boundHandler); - aListenerStruct = nullptr; // Note - We pass null for aIncumbentGlobal below. We could also pass the // compilation global, but since the handler is guaranteed to be scripted, // there's no need to use an override, since the JS engine will always give @@ -988,7 +991,7 @@ nsEventListenerManager::HandleEventInternal(nsPresContext* aPresContext, nsAutoTObserverArray::EndLimitedIterator iter(mListeners); Maybe popupStatePusher; if (mIsMainThreadELM) { - popupStatePusher.construct(nsDOMEvent::GetEventPopupControlState(aEvent)); + popupStatePusher.construct(Event::GetEventPopupControlState(aEvent)); } bool hasListener = false; diff --git a/dom/events/nsEventStateManager.cpp b/dom/events/nsEventStateManager.cpp index 13e62dfc089..2c35bd5a565 100644 --- a/dom/events/nsEventStateManager.cpp +++ b/dom/events/nsEventStateManager.cpp @@ -10,6 +10,7 @@ #include "mozilla/MouseEvents.h" #include "mozilla/TextEvents.h" #include "mozilla/TouchEvents.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/TabParent.h" #include "mozilla/dom/UIEvent.h" @@ -25,7 +26,6 @@ #include "nsIWidget.h" #include "nsPresContext.h" #include "nsIPresShell.h" -#include "nsDOMEvent.h" #include "nsGkAtoms.h" #include "nsIFormControl.h" #include "nsIComboboxControlFrame.h" @@ -5918,7 +5918,7 @@ nsEventStateManager::Prefs::OnChange(const char* aPrefName, void*) { nsDependentCString prefName(aPrefName); if (prefName.EqualsLiteral("dom.popup_allowed_events")) { - nsDOMEvent::PopupAllowedEventsChanged(); + Event::PopupAllowedEventsChanged(); } } diff --git a/dom/events/nsEventStateManager.h b/dom/events/nsEventStateManager.h index 2086d209b7b..4b15b7ca434 100644 --- a/dom/events/nsEventStateManager.h +++ b/dom/events/nsEventStateManager.h @@ -219,13 +219,13 @@ public: // Holds the point in screen coords that a mouse event was dispatched to, // before we went into pointer lock mode. This is constantly updated while // the pointer is not locked, but we don't update it while the pointer is - // locked. This is used by nsDOMEvent::GetScreenCoords() to make mouse + // locked. This is used by dom::Event::GetScreenCoords() to make mouse // events' screen coord appear frozen at the last mouse position while // the pointer is locked. static nsIntPoint sLastScreenPoint; // Holds the point in client coords of the last mouse event. Used by - // nsDOMEvent::GetClientCoords() to make mouse events' client coords appear + // dom::Event::GetClientCoords() to make mouse events' client coords appear // frozen at the last mouse position while the pointer is locked. static mozilla::CSSIntPoint sLastClientPoint; diff --git a/dom/events/nsJSEventListener.cpp b/dom/events/nsJSEventListener.cpp index 0ca3ce277da..d589699d8c3 100644 --- a/dom/events/nsJSEventListener.cpp +++ b/dom/events/nsJSEventListener.cpp @@ -21,7 +21,6 @@ #include "mozilla/Likely.h" #include "mozilla/dom/ErrorEvent.h" #include "mozilla/dom/UnionTypes.h" -#include "nsDOMEvent.h" #ifdef DEBUG diff --git a/dom/file/LockedFile.cpp b/dom/file/LockedFile.cpp index 390673dfaf0..b6d5bd18066 100644 --- a/dom/file/LockedFile.cpp +++ b/dom/file/LockedFile.cpp @@ -7,6 +7,7 @@ #include "LockedFile.h" #include "nsIAppShell.h" +#include "nsIDOMEvent.h" #include "nsIDOMFile.h" #include "nsIFileStorage.h" #include "nsISeekableStream.h" @@ -15,7 +16,6 @@ #include "nsEventDispatcher.h" #include "nsNetUtil.h" #include "nsDOMClassInfoID.h" -#include "nsDOMEvent.h" #include "nsJSUtils.h" #include "nsStringStream.h" #include "nsWidgetsCID.h" diff --git a/dom/indexedDB/AsyncConnectionHelper.h b/dom/indexedDB/AsyncConnectionHelper.h index b461777e601..7ec764ce698 100644 --- a/dom/indexedDB/AsyncConnectionHelper.h +++ b/dom/indexedDB/AsyncConnectionHelper.h @@ -17,8 +17,6 @@ #include "nsIEventTarget.h" #include "nsIRunnable.h" -#include "nsDOMEvent.h" - class mozIStorageConnection; BEGIN_INDEXEDDB_NAMESPACE diff --git a/dom/indexedDB/IDBEvents.cpp b/dom/indexedDB/IDBEvents.cpp index f84192838ad..2eb99cef895 100644 --- a/dom/indexedDB/IDBEvents.cpp +++ b/dom/indexedDB/IDBEvents.cpp @@ -84,7 +84,7 @@ IDBVersionChangeEvent::CreateRunnableInternal(mozilla::dom::EventTarget* aTarget uint64_t aOldVersion, uint64_t aNewVersion) { - nsRefPtr event = + nsRefPtr event = CreateInternal(aTarget, aType, aOldVersion, aNewVersion); NS_ENSURE_TRUE(event, nullptr); @@ -92,9 +92,9 @@ IDBVersionChangeEvent::CreateRunnableInternal(mozilla::dom::EventTarget* aTarget return runnable.forget(); } -NS_IMPL_ADDREF_INHERITED(IDBVersionChangeEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(IDBVersionChangeEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(IDBVersionChangeEvent, Event) +NS_IMPL_RELEASE_INHERITED(IDBVersionChangeEvent, Event) NS_INTERFACE_MAP_BEGIN(IDBVersionChangeEvent) NS_INTERFACE_MAP_ENTRY(IDBVersionChangeEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) diff --git a/dom/indexedDB/IDBEvents.h b/dom/indexedDB/IDBEvents.h index 90b8ba659b5..00deaefddcd 100644 --- a/dom/indexedDB/IDBEvents.h +++ b/dom/indexedDB/IDBEvents.h @@ -11,7 +11,7 @@ #include "nsIRunnable.h" -#include "nsDOMEvent.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/Nullable.h" #include "mozilla/dom/indexedDB/IDBObjectStore.h" #include "mozilla/dom/IDBVersionChangeEventBinding.h" @@ -46,11 +46,11 @@ CreateGenericEvent(mozilla::dom::EventTarget* aOwner, Bubbles aBubbles, Cancelable aCancelable); -class IDBVersionChangeEvent : public nsDOMEvent +class IDBVersionChangeEvent : public Event { public: NS_DECL_ISUPPORTS_INHERITED - NS_FORWARD_TO_NSDOMEVENT + NS_FORWARD_TO_EVENT NS_DECLARE_STATIC_IID_ACCESSOR(IDBVERSIONCHANGEEVENT_IID) virtual JSObject* WrapObject(JSContext* aCx, @@ -85,7 +85,7 @@ public: : mozilla::dom::Nullable(); } - inline static already_AddRefed + inline static already_AddRefed Create(mozilla::dom::EventTarget* aOwner, int64_t aOldVersion, int64_t aNewVersion) @@ -95,7 +95,7 @@ public: aOldVersion, aNewVersion); } - inline static already_AddRefed + inline static already_AddRefed CreateBlocked(mozilla::dom::EventTarget* aOwner, uint64_t aOldVersion, uint64_t aNewVersion) @@ -104,7 +104,7 @@ public: aOldVersion, aNewVersion); } - inline static already_AddRefed + inline static already_AddRefed CreateUpgradeNeeded(mozilla::dom::EventTarget* aOwner, uint64_t aOldVersion, uint64_t aNewVersion) @@ -136,7 +136,7 @@ public: protected: IDBVersionChangeEvent(mozilla::dom::EventTarget* aOwner) - : nsDOMEvent(aOwner, nullptr, nullptr) + : Event(aOwner, nullptr, nullptr) { SetIsDOMBinding(); } diff --git a/dom/indexedDB/OpenDatabaseHelper.cpp b/dom/indexedDB/OpenDatabaseHelper.cpp index 97b4e4b769d..8e5e44e4555 100644 --- a/dom/indexedDB/OpenDatabaseHelper.cpp +++ b/dom/indexedDB/OpenDatabaseHelper.cpp @@ -1672,7 +1672,7 @@ public: } // Otherwise fire a versionchange event. - nsRefPtr event = + nsRefPtr event = IDBVersionChangeEvent::Create(database, mOldVersion, mNewVersion); NS_ENSURE_TRUE(event, NS_ERROR_FAILURE); @@ -1684,7 +1684,7 @@ public: // then fire the blocked event. for (uint32_t index = 0; index < count; index++) { if (!mWaitingDatabases[index]->IsClosed()) { - nsRefPtr event = + nsRefPtr event = IDBVersionChangeEvent::CreateBlocked(mRequest, mOldVersion, mNewVersion); NS_ENSURE_TRUE(event, NS_ERROR_FAILURE); diff --git a/dom/indexedDB/ipc/IndexedDBChild.cpp b/dom/indexedDB/ipc/IndexedDBChild.cpp index 0c115e7fdd1..ae607556e27 100644 --- a/dom/indexedDB/ipc/IndexedDBChild.cpp +++ b/dom/indexedDB/ipc/IndexedDBChild.cpp @@ -141,7 +141,7 @@ public: return NS_OK; } - nsRefPtr event = + nsRefPtr event = IDBVersionChangeEvent::Create(mDatabase, mOldVersion, mNewVersion); MOZ_ASSERT(event); diff --git a/dom/interfaces/events/nsIDOMEvent.idl b/dom/interfaces/events/nsIDOMEvent.idl index f3eabd56c53..f3877bea387 100644 --- a/dom/interfaces/events/nsIDOMEvent.idl +++ b/dom/interfaces/events/nsIDOMEvent.idl @@ -8,7 +8,7 @@ interface nsIDOMEventTarget; [ptr] native WidgetEventPtr(mozilla::WidgetEvent); -[ptr] native nsDOMEventPtr(nsDOMEvent); +[ptr] native DOMEventPtr(mozilla::dom::Event); [ptr] native IPCMessagePtr(IPC::Message); [ptr] native ConstIPCMessagePtr(const IPC::Message); [ptr] native EventTargetPtr(mozilla::dom::EventTarget); @@ -18,7 +18,6 @@ interface nsIDOMEventTarget; #endif #include "mozilla/EventForwards.h" -class nsDOMEvent; class nsPresContext; class nsInvalidateRequestList; namespace IPC { @@ -26,6 +25,7 @@ class Message; } namespace mozilla { namespace dom { +class Event; class EventTarget; } // namespace dom } // namespace mozilla @@ -212,7 +212,7 @@ interface nsIDOMEvent : nsISupports in boolean aSerializeInterfaceType); [notxpcom] boolean Deserialize(in ConstIPCMessagePtr aMsg, out voidPtr aIter); [noscript,notxpcom] void SetOwner(in EventTargetPtr aOwner); - [notxpcom] nsDOMEventPtr InternalDOMEvent(); + [notxpcom] DOMEventPtr InternalDOMEvent(); }; dictionary EventInit diff --git a/dom/ipc/Blob.cpp b/dom/ipc/Blob.cpp index 08c8b6920b6..3842ac2373e 100644 --- a/dom/ipc/Blob.cpp +++ b/dom/ipc/Blob.cpp @@ -1080,10 +1080,6 @@ RemoteBlob::MaybeSetInputStream(const ConstructorParamsType& aParams) mInputStreamParams = aParams.optionalInputStreamParams().get_InputStreamParams(); } - else { - MOZ_ASSERT(aParams.blobParams().type() == - ChildBlobConstructorParams::TMysteryBlobConstructorParams); - } } template <> diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index 30321be37c7..effc52f34e9 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -172,14 +172,24 @@ static bool sNuwaForking = false; namespace mozilla { namespace dom { -class MemoryReportRequestChild : public PMemoryReportRequestChild +class MemoryReportRequestChild : public PMemoryReportRequestChild, + public nsIRunnable { public: - MemoryReportRequestChild(); + NS_DECL_ISUPPORTS + + MemoryReportRequestChild(uint32_t aGeneration, const nsAString& aDMDDumpIdent); virtual ~MemoryReportRequestChild(); + NS_IMETHOD Run(); +private: + uint32_t mGeneration; + nsString mDMDDumpIdent; }; -MemoryReportRequestChild::MemoryReportRequestChild() +NS_IMPL_ISUPPORTS1(MemoryReportRequestChild, nsIRunnable) + +MemoryReportRequestChild::MemoryReportRequestChild(uint32_t aGeneration, const nsAString& aDMDDumpIdent) +: mGeneration(aGeneration), mDMDDumpIdent(aDMDDumpIdent) { MOZ_COUNT_CTOR(MemoryReportRequestChild); } @@ -258,6 +268,16 @@ ConsoleListener::Observe(nsIConsoleMessage* aMessage) NS_ENSURE_SUCCESS(rv, rv); rv = scriptError->GetSourceLine(sourceLine); NS_ENSURE_SUCCESS(rv, rv); + + // Before we send the error to the parent process (which + // involves copying the memory), truncate any long lines. CSS + // errors in particular share the memory for long lines with + // repeated errors, but the IPC communication we're about to do + // will break that sharing, so we better truncate now. + if (sourceLine.Length() > 1000) { + sourceLine.Truncate(1000); + } + rv = scriptError->GetCategory(getter_Copies(category)); NS_ENSURE_SUCCESS(rv, rv); rv = scriptError->GetLineNumber(&lineNum); @@ -518,9 +538,13 @@ ContentChild::InitXPCOM() } PMemoryReportRequestChild* -ContentChild::AllocPMemoryReportRequestChild(const uint32_t& generation) +ContentChild::AllocPMemoryReportRequestChild(const uint32_t& generation, + const bool &minimizeMemoryUsage, + const nsString& aDMDDumpIdent) { - return new MemoryReportRequestChild(); + MemoryReportRequestChild *actor = new MemoryReportRequestChild(generation, aDMDDumpIdent); + actor->AddRef(); + return actor; } // This is just a wrapper for InfallibleTArray that implements @@ -567,25 +591,44 @@ NS_IMPL_ISUPPORTS1( bool ContentChild::RecvPMemoryReportRequestConstructor( PMemoryReportRequestChild* child, - const uint32_t& generation) + const uint32_t& generation, + const bool& minimizeMemoryUsage, + const nsString& aDMDDumpIdent) { + MemoryReportRequestChild *actor = static_cast(child); + nsresult rv; + + if (minimizeMemoryUsage) { + nsCOMPtr mgr = do_GetService("@mozilla.org/memory-reporter-manager;1"); + rv = mgr->MinimizeMemoryUsage(actor); + // mgr will eventually call actor->Run() + } else { + rv = actor->Run(); + } + + return !NS_WARN_IF(NS_FAILED(rv)); +} + +NS_IMETHODIMP MemoryReportRequestChild::Run() +{ + ContentChild *child = static_cast(Manager()); nsCOMPtr mgr = do_GetService("@mozilla.org/memory-reporter-manager;1"); InfallibleTArray reports; nsCString process; - GetProcessName(process); - AppendProcessId(process); + child->GetProcessName(process); + child->AppendProcessId(process); // Run the reporters. The callback will turn each measurement into a // MemoryReport. nsRefPtr wrappedReports = new MemoryReportsWrapper(&reports); nsRefPtr cb = new MemoryReportCallback(process); - mgr->GetReportsForThisProcess(cb, wrappedReports); + mgr->GetReportsForThisProcessExtended(cb, wrappedReports, mDMDDumpIdent); - child->Send__delete__(child, generation, reports); - return true; + bool sent = Send__delete__(this, mGeneration, reports); + return sent ? NS_OK : NS_ERROR_FAILURE; } bool @@ -602,19 +645,7 @@ ContentChild::RecvAudioChannelNotify() bool ContentChild::DeallocPMemoryReportRequestChild(PMemoryReportRequestChild* actor) { - delete actor; - return true; -} - -bool -ContentChild::RecvDumpMemoryInfoToTempDir(const nsString& aIdentifier, - const bool& aMinimizeMemoryUsage, - const bool& aDumpChildProcesses) -{ - nsCOMPtr dumper = do_GetService("@mozilla.org/memory-info-dumper;1"); - - dumper->DumpMemoryInfoToTempDir(aIdentifier, aMinimizeMemoryUsage, - aDumpChildProcesses); + static_cast(actor)->Release(); return true; } diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index c20518b22cf..7bd070b76c2 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -115,22 +115,21 @@ public: virtual bool DeallocPIndexedDBChild(PIndexedDBChild* aActor) MOZ_OVERRIDE; virtual PMemoryReportRequestChild* - AllocPMemoryReportRequestChild(const uint32_t& generation) MOZ_OVERRIDE; - + AllocPMemoryReportRequestChild(const uint32_t& generation, + const bool &minimizeMemoryUsage, + const nsString &aDMDDumpIdent) MOZ_OVERRIDE; virtual bool DeallocPMemoryReportRequestChild(PMemoryReportRequestChild* actor) MOZ_OVERRIDE; virtual bool RecvPMemoryReportRequestConstructor(PMemoryReportRequestChild* child, - const uint32_t& generation) MOZ_OVERRIDE; + const uint32_t& generation, + const bool &minimizeMemoryUsage, + const nsString &aDMDDumpIdent) MOZ_OVERRIDE; virtual bool RecvAudioChannelNotify() MOZ_OVERRIDE; - virtual bool - RecvDumpMemoryInfoToTempDir(const nsString& aIdentifier, - const bool& aMinimizeMemoryUsage, - const bool& aDumpChildProcesses) MOZ_OVERRIDE; virtual bool RecvDumpGCAndCCLogsToFile(const nsString& aIdentifier, const bool& aDumpAllTraces, diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 63cc8083959..cc2232b1d7e 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -2040,10 +2040,28 @@ ContentParent::Observe(nsISupports* aSubject, return NS_ERROR_NOT_AVAILABLE; } else if (!strcmp(aTopic, "child-memory-reporter-request")) { + bool isNuwa = false; #ifdef MOZ_NUWA_PROCESS - if (!IsNuwaProcess()) + isNuwa = IsNuwaProcess(); #endif - unused << SendPMemoryReportRequestConstructor((uint32_t)(uintptr_t)aData); + if (!isNuwa) { + unsigned generation; + int minimize, identOffset = -1; + nsDependentString msg(aData); + NS_ConvertUTF16toUTF8 cmsg(msg); + + if (sscanf(cmsg.get(), + "generation=%x minimize=%d DMDident=%n", + &generation, &minimize, &identOffset) < 2 + || identOffset < 0) { + return NS_ERROR_INVALID_ARG; + } + // The pre-%n part of the string should be all ASCII, so the byte + // offset in identOffset should be correct as a char offset. + MOZ_ASSERT(cmsg[identOffset - 1] == '='); + unused << SendPMemoryReportRequestConstructor( + generation, minimize, nsString(Substring(msg, identOffset))); + } } else if (!strcmp(aTopic, "child-gc-request")){ unused << SendGarbageCollect(); @@ -2504,7 +2522,9 @@ ContentParent::RecvPIndexedDBConstructor(PIndexedDBParent* aActor) } PMemoryReportRequestParent* -ContentParent::AllocPMemoryReportRequestParent(const uint32_t& generation) +ContentParent::AllocPMemoryReportRequestParent(const uint32_t& generation, + const bool &minimizeMemoryUsage, + const nsString &aDMDDumpIdent) { MemoryReportRequestParent* parent = new MemoryReportRequestParent(); return parent; diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index a9b5582bb7f..552f0bc306b 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -359,7 +359,9 @@ private: virtual bool DeallocPIndexedDBParent(PIndexedDBParent* aActor) MOZ_OVERRIDE; virtual PMemoryReportRequestParent* - AllocPMemoryReportRequestParent(const uint32_t& generation) MOZ_OVERRIDE; + AllocPMemoryReportRequestParent(const uint32_t& generation, + const bool &minimizeMemoryUsage, + const nsString &aDMDDumpIdent) MOZ_OVERRIDE; virtual bool DeallocPMemoryReportRequestParent(PMemoryReportRequestParent* actor) MOZ_OVERRIDE; virtual PTestShellParent* AllocPTestShellParent() MOZ_OVERRIDE; diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index e30fbfe65b5..dfb9f5370d1 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -273,7 +273,7 @@ child: */ async SetProcessPrivileges(ChildPrivileges privs); - PMemoryReportRequest(uint32_t generation); + PMemoryReportRequest(uint32_t generation, bool minimizeMemoryUsage, nsString DMDDumpIdent); /** * Notify the AudioChannelService in the child processes. @@ -282,20 +282,11 @@ child: async SpeakerManagerNotify(); - /** - * Do a memory info dump to a file in our temp directory. - * - * For documentation on the args, see - * MemoryInfoDumper::dumpMemoryInfoToTempDir. - */ - async DumpMemoryInfoToTempDir(nsString identifier, - bool minimizeMemoryUsage, - bool dumpChildProcesses); /** * Dump this process's GC and CC logs. * - * For documentation on the args, see - * MemoryInfoDumper::dumpGCAndCCLogsToFile. + * For documentation on the args, see dumpGCAndCCLogsToFile in + * nsIMemoryInfoDumper.idl */ async DumpGCAndCCLogsToFile(nsString identifier, bool dumpAllTraces, diff --git a/dom/mobileconnection/src/MobileConnection.cpp b/dom/mobileconnection/src/MobileConnection.cpp index ec3a0938bcf..f15cebacd39 100644 --- a/dom/mobileconnection/src/MobileConnection.cpp +++ b/dom/mobileconnection/src/MobileConnection.cpp @@ -11,7 +11,6 @@ #include "mozilla/dom/MozOtaStatusEvent.h" #include "mozilla/dom/USSDReceivedEvent.h" #include "mozilla/Preferences.h" -#include "nsDOMEvent.h" #include "nsIDOMClassInfo.h" #include "nsIDOMDOMRequest.h" #include "nsIPermissionManager.h" diff --git a/dom/network/src/Connection.cpp b/dom/network/src/Connection.cpp index 338e69691a8..d1708f1ae69 100644 --- a/dom/network/src/Connection.cpp +++ b/dom/network/src/Connection.cpp @@ -9,7 +9,6 @@ #include "mozilla/dom/MozConnectionBinding.h" #include "nsIDOMClassInfo.h" #include "mozilla/Preferences.h" -#include "nsDOMEvent.h" #include "Constants.h" /** diff --git a/dom/plugins/ipc/PluginModuleChild.cpp b/dom/plugins/ipc/PluginModuleChild.cpp index b71edc451b8..d8fe0ad2cac 100644 --- a/dom/plugins/ipc/PluginModuleChild.cpp +++ b/dom/plugins/ipc/PluginModuleChild.cpp @@ -144,6 +144,8 @@ PluginModuleChild::Init(const std::string& aPluginFilename, { PLUGIN_LOG_DEBUG_METHOD; + GetIPCChannel()->SetAbortOnError(true); + #ifdef XP_WIN COMMessageFilter::Initialize(this); #endif @@ -595,6 +597,8 @@ PluginModuleChild::AnswerNP_Shutdown(NPError *rv) ResetEventHooks(); #endif + GetIPCChannel()->SetAbortOnError(false); + return true; } diff --git a/dom/plugins/ipc/hangui/Makefile.in b/dom/plugins/ipc/hangui/Makefile.in index b4631dc739d..00bd5acfdf4 100644 --- a/dom/plugins/ipc/hangui/Makefile.in +++ b/dom/plugins/ipc/hangui/Makefile.in @@ -4,12 +4,6 @@ OS_LIBS = $(call EXPAND_LIBNAME,comctl32) -RCINCLUDE = HangUIDlg.rc - -STL_FLAGS = \ - -D_HAS_EXCEPTIONS=0 \ - $(NULL) - MOZ_GLUE_LDFLAGS = include $(topsrcdir)/config/rules.mk diff --git a/dom/plugins/ipc/hangui/moz.build b/dom/plugins/ipc/hangui/moz.build index 90b72b76243..0b2fc403a48 100644 --- a/dom/plugins/ipc/hangui/moz.build +++ b/dom/plugins/ipc/hangui/moz.build @@ -15,6 +15,11 @@ UNIFIED_SOURCES += [ include('/ipc/chromium/chromium-config.mozbuild') DEFINES['NS_NO_XPCOM'] = True +DEFINES['_HAS_EXCEPTIONS'] = 0 + +DISABLE_STL_WRAPPING = True if CONFIG['GNU_CC']: WIN32_EXE_LDFLAGS += ['-municode'] + +RCINCLUDE = 'HangUIDlg.rc' diff --git a/dom/plugins/test/mochitest/test_bug813906.html b/dom/plugins/test/mochitest/test_bug813906.html index 0cd95e15dc9..a059cc28b17 100644 --- a/dom/plugins/test/mochitest/test_bug813906.html +++ b/dom/plugins/test/mochitest/test_bug813906.html @@ -21,9 +21,6 @@ function f() { SimpleTest.waitForExplicitFinish(); setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED); -// When the document is torn down or is removed, we hit bug 621618 -SimpleTest.expectAssertions(1); - var frameLoadCount = 0; function frameLoaded() { frameLoadCount++; @@ -33,11 +30,7 @@ function frameLoaded() { } else if (frameLoadCount == 2) { isnot(SpecialPowers.wrap(window.frame1).location.href.indexOf('chrome://'), 0, 'plugin shouldnt be able to cause navigation to chrome URLs'); - - // Make sure we trigger bug 621618 before the test finishes so the assertion - // is attributed to this test. - document.body.removeChild(document.querySelector("svg")); - SimpleTest.executeSoon(function() { SimpleTest.finish(); }); + SimpleTest.finish(); } } diff --git a/dom/plugins/test/mochitest/test_bug852315.html b/dom/plugins/test/mochitest/test_bug852315.html index 2cbf8a2c208..b60a548b781 100644 --- a/dom/plugins/test/mochitest/test_bug852315.html +++ b/dom/plugins/test/mochitest/test_bug852315.html @@ -38,8 +38,11 @@ i.addEventListener("load", function loadfunc() { i.removeEventListener("load", loadfunc); i.src = "about:blank"; SimpleTest.executeSoon(function() { - ok(destroyran, "OnDestroy callback ran and did not crash"); - SimpleTest.finish(); + // Ensure this event doesn't race with CheckPluginStopEvent + SimpleTest.executeSoon(function() { + ok(destroyran, "OnDestroy callback ran and did not crash"); + SimpleTest.finish(); + }); }); }); document.body.appendChild(i); diff --git a/dom/plugins/test/testplugin/testplugin.mk b/dom/plugins/test/testplugin/testplugin.mk index 80a096afa0d..87fa2e37491 100644 --- a/dom/plugins/test/testplugin/testplugin.mk +++ b/dom/plugins/test/testplugin/testplugin.mk @@ -3,9 +3,6 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. -# Don't use STL wrappers; nptest isn't Gecko code -STL_FLAGS = - ifeq ($(MOZ_WIDGET_TOOLKIT),qt) include $(topsrcdir)/config/config.mk CXXFLAGS += $(MOZ_QT_CFLAGS) diff --git a/dom/plugins/test/testplugin/testplugin.mozbuild b/dom/plugins/test/testplugin/testplugin.mozbuild index ec506ba2fb0..97d41d69735 100644 --- a/dom/plugins/test/testplugin/testplugin.mozbuild +++ b/dom/plugins/test/testplugin/testplugin.mozbuild @@ -42,6 +42,9 @@ FORCE_SHARED_LIB = True # must link statically with the CRT; nptest isn't Gecko code USE_STATIC_LIBS = True +# Don't use STL wrappers; nptest isn't Gecko code +DISABLE_STL_WRAPPING = True + if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': RCFILE = 'nptest.rc' RESFILE = 'nptest.res' diff --git a/dom/power/WakeLock.cpp b/dom/power/WakeLock.cpp index a1842a2ba72..25b91faa817 100644 --- a/dom/power/WakeLock.cpp +++ b/dom/power/WakeLock.cpp @@ -5,10 +5,10 @@ #include "WakeLock.h" #include "mozilla/dom/ContentParent.h" +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() #include "mozilla/dom/MozWakeLockBinding.h" #include "mozilla/Hal.h" #include "mozilla/HalWakeLock.h" -#include "nsDOMEvent.h" #include "nsError.h" #include "nsIDocument.h" #include "nsIDOMWindow.h" diff --git a/dom/smil/TimeEvent.cpp b/dom/smil/TimeEvent.cpp index 65c0d37765c..a58375774b1 100644 --- a/dom/smil/TimeEvent.cpp +++ b/dom/smil/TimeEvent.cpp @@ -14,9 +14,9 @@ namespace dom { TimeEvent::TimeEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, - aEvent ? aEvent : new InternalUIEvent(false, 0)), - mDetail(0) + : Event(aOwner, aPresContext, + aEvent ? aEvent : new InternalUIEvent(false, 0)) + , mDetail(0) { SetIsDOMBinding(); if (aEvent) { @@ -44,15 +44,15 @@ TimeEvent::TimeEvent(EventTarget* aOwner, } } -NS_IMPL_CYCLE_COLLECTION_INHERITED_1(TimeEvent, nsDOMEvent, +NS_IMPL_CYCLE_COLLECTION_INHERITED_1(TimeEvent, Event, mView) -NS_IMPL_ADDREF_INHERITED(TimeEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(TimeEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(TimeEvent, Event) +NS_IMPL_RELEASE_INHERITED(TimeEvent, Event) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TimeEvent) NS_INTERFACE_MAP_ENTRY(nsIDOMTimeEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) NS_IMETHODIMP TimeEvent::GetView(nsIDOMWindow** aView) @@ -74,8 +74,8 @@ TimeEvent::InitTimeEvent(const nsAString& aTypeArg, nsIDOMWindow* aViewArg, int32_t aDetailArg) { - nsresult rv = nsDOMEvent::InitEvent(aTypeArg, false /*doesn't bubble*/, - false /*can't cancel*/); + nsresult rv = Event::InitEvent(aTypeArg, false /*doesn't bubble*/, + false /*can't cancel*/); NS_ENSURE_SUCCESS(rv, rv); mDetail = aDetailArg; diff --git a/dom/smil/TimeEvent.h b/dom/smil/TimeEvent.h index a3cd91ca98f..7f0d60b1414 100644 --- a/dom/smil/TimeEvent.h +++ b/dom/smil/TimeEvent.h @@ -6,14 +6,14 @@ #ifndef mozilla_dom_TimeEvent_h_ #define mozilla_dom_TimeEvent_h_ -#include "nsIDOMTimeEvent.h" -#include "nsDOMEvent.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/TimeEventBinding.h" +#include "nsIDOMTimeEvent.h" namespace mozilla { namespace dom { -class TimeEvent MOZ_FINAL : public nsDOMEvent, +class TimeEvent MOZ_FINAL : public Event, public nsIDOMTimeEvent { public: @@ -23,13 +23,13 @@ public: // nsISupports interface: NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TimeEvent, nsDOMEvent) + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TimeEvent, Event) // nsIDOMTimeEvent interface: NS_DECL_NSIDOMTIMEEVENT // Forward to base class - NS_FORWARD_TO_NSDOMEVENT + NS_FORWARD_TO_EVENT virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aScope) MOZ_OVERRIDE diff --git a/dom/speakermanager/SpeakerManager.cpp b/dom/speakermanager/SpeakerManager.cpp index d9ba574a0e8..109202add12 100644 --- a/dom/speakermanager/SpeakerManager.cpp +++ b/dom/speakermanager/SpeakerManager.cpp @@ -4,12 +4,12 @@ #include "SpeakerManager.h" #include "nsIDOMClassInfo.h" +#include "nsIDOMEvent.h" #include "nsIDOMEventListener.h" #include "SpeakerManagerService.h" #include "nsIPermissionManager.h" #include "nsIInterfaceRequestorUtils.h" #include "nsIDocShell.h" -#include "nsDOMEvent.h" #include "AudioChannelService.h" using namespace mozilla::dom; diff --git a/dom/src/notification/Notification.cpp b/dom/src/notification/Notification.cpp index 37504d05126..c9dbaa9b88b 100644 --- a/dom/src/notification/Notification.cpp +++ b/dom/src/notification/Notification.cpp @@ -10,7 +10,6 @@ #include "mozilla/Preferences.h" #include "TabChild.h" #include "nsContentUtils.h" -#include "nsDOMEvent.h" #include "nsIAlertsService.h" #include "nsIAppsService.h" #include "nsIContentPermissionPrompt.h" diff --git a/dom/src/offline/nsDOMOfflineResourceList.cpp b/dom/src/offline/nsDOMOfflineResourceList.cpp index b2833bf18fa..1c94faad604 100644 --- a/dom/src/offline/nsDOMOfflineResourceList.cpp +++ b/dom/src/offline/nsDOMOfflineResourceList.cpp @@ -4,6 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsDOMOfflineResourceList.h" +#include "nsIDOMEvent.h" #include "nsIScriptSecurityManager.h" #include "nsError.h" #include "mozilla/dom/DOMStringList.h" diff --git a/dom/src/offline/nsDOMOfflineResourceList.h b/dom/src/offline/nsDOMOfflineResourceList.h index 8a302673edb..715ef7ac3b7 100644 --- a/dom/src/offline/nsDOMOfflineResourceList.h +++ b/dom/src/offline/nsDOMOfflineResourceList.h @@ -19,7 +19,6 @@ #include "nsWeakReference.h" #include "nsCOMArray.h" #include "nsIDOMEventListener.h" -#include "nsDOMEvent.h" #include "nsIObserver.h" #include "nsIScriptContext.h" #include "nsCycleCollectionParticipant.h" diff --git a/dom/telephony/CallEvent.cpp b/dom/telephony/CallEvent.cpp index 5984f0372f9..472f590bf03 100644 --- a/dom/telephony/CallEvent.cpp +++ b/dom/telephony/CallEvent.cpp @@ -32,19 +32,19 @@ CallEvent::WrapObject(JSContext* aCx, JS::Handle aScope) NS_IMPL_CYCLE_COLLECTION_CLASS(CallEvent) -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(CallEvent, nsDOMEvent) +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(CallEvent, Event) NS_IMPL_CYCLE_COLLECTION_UNLINK(mCall) NS_IMPL_CYCLE_COLLECTION_UNLINK_END -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(CallEvent, nsDOMEvent) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(CallEvent, Event) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCall) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END -NS_IMPL_ADDREF_INHERITED(CallEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(CallEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(CallEvent, Event) +NS_IMPL_RELEASE_INHERITED(CallEvent, Event) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(CallEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) // WebIDL diff --git a/dom/telephony/CallEvent.h b/dom/telephony/CallEvent.h index a87c3721255..6135d1ff5cd 100644 --- a/dom/telephony/CallEvent.h +++ b/dom/telephony/CallEvent.h @@ -7,23 +7,22 @@ #ifndef mozilla_dom_telephony_callevent_h #define mozilla_dom_telephony_callevent_h +#include "mozilla/dom/Event.h" #include "mozilla/dom/telephony/TelephonyCommon.h" -#include "nsDOMEvent.h" - namespace mozilla { namespace dom { struct CallEventInit; -class CallEvent MOZ_FINAL : public nsDOMEvent +class CallEvent MOZ_FINAL : public Event { nsRefPtr mCall; public: NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(CallEvent, nsDOMEvent) - NS_FORWARD_TO_NSDOMEVENT + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(CallEvent, Event) + NS_FORWARD_TO_EVENT virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aScope) MOZ_OVERRIDE; @@ -44,7 +43,7 @@ private: CallEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, aEvent) + : Event(aOwner, aPresContext, aEvent) { SetIsDOMBinding(); } diff --git a/dom/tests/mochitest/webcomponents/test_document_register_lifecycle.html b/dom/tests/mochitest/webcomponents/test_document_register_lifecycle.html index ea6895be566..a1826883ba1 100644 --- a/dom/tests/mochitest/webcomponents/test_document_register_lifecycle.html +++ b/dom/tests/mochitest/webcomponents/test_document_register_lifecycle.html @@ -24,8 +24,8 @@ function testRegisterUnresolved() { var helloElem = document.getElementById("hello"); var createdCallbackCalled = false; - var enteredViewCallbackCalled = false; - var leftViewCallbackCalled = false; + var attachedCallbackCalled = false; + var detachedCallbackCalled = false; var p = Object.create(HTMLElement.prototype); p.createdCallback = function() { @@ -35,17 +35,17 @@ function testRegisterUnresolved() { createdCallbackCalled = true; }; - p.enteredViewCallback = function() { - is(createdCallbackCalled, true, "Created callback should be called before enteredView"); - is(enteredViewCallbackCalled, false, "enteredView callback should only be called once in this test."); + p.attachedCallback = function() { + is(createdCallbackCalled, true, "Created callback should be called before attached"); + is(attachedCallbackCalled, false, "attached callback should only be called once in this test."); is(this, helloElem, "The 'this' value should be the custom element."); - enteredViewCallbackCalled = true; + attachedCallbackCalled = true; }; - p.leftViewCallback = function() { - is(enteredViewCallbackCalled, true, "enteredView callback should be called before leftView"); - is(leftViewCallbackCalled, false, "leftView callback should only be called once in this test."); - leftViewCallbackCalled = true; + p.detachedCallback = function() { + is(attachedCallbackCalled, true, "attached callback should be called before detached"); + is(detachedCallbackCalled, false, "detached callback should only be called once in this test."); + detachedCallbackCalled = true; is(this, helloElem, "The 'this' value should be the custom element."); runNextTest(); }; @@ -57,7 +57,7 @@ function testRegisterUnresolved() { document.registerElement("x-hello", { prototype: p }); is(createdCallbackCalled, true, "created callback should be called when control returns to script from user agent code"); - // Remove element from document to trigger leftView callback. + // Remove element from document to trigger detached callback. container.removeChild(helloElem); } @@ -67,8 +67,8 @@ function testRegisterUnresolvedExtended() { var buttonElem = document.getElementById("extbutton"); var createdCallbackCalled = false; - var enteredViewCallbackCalled = false; - var leftViewCallbackCalled = false; + var attachedCallbackCalled = false; + var detachedCallbackCalled = false; var p = Object.create(HTMLButtonElement.prototype); p.createdCallback = function() { @@ -78,17 +78,17 @@ function testRegisterUnresolvedExtended() { createdCallbackCalled = true; }; - p.enteredViewCallback = function() { - is(createdCallbackCalled, true, "Created callback should be called before enteredView"); - is(enteredViewCallbackCalled, false, "enteredView callback should only be called once in this test."); + p.attachedCallback = function() { + is(createdCallbackCalled, true, "Created callback should be called before attached"); + is(attachedCallbackCalled, false, "attached callback should only be called once in this test."); is(this, buttonElem, "The 'this' value should be the custom element."); - enteredViewCallbackCalled = true; + attachedCallbackCalled = true; }; - p.leftViewCallback = function() { - is(enteredViewCallbackCalled, true, "enteredView callback should be called before leftView"); - is(leftViewCallbackCalled, false, "leftView callback should only be called once in this test."); - leftViewCallbackCalled = true; + p.detachedCallback = function() { + is(attachedCallbackCalled, true, "attached callback should be called before detached"); + is(detachedCallbackCalled, false, "detached callback should only be called once in this test."); + detachedCallbackCalled = true; is(this, buttonElem, "The 'this' value should be the custom element."); runNextTest(); }; @@ -100,7 +100,7 @@ function testRegisterUnresolvedExtended() { document.registerElement("x-button", { prototype: p, extends: "button" }); is(createdCallbackCalled, true, "created callback should be called when control returns to script from user agent code"); - // Remove element from document to trigger leftView callback. + // Remove element from document to trigger detached callback. container.removeChild(buttonElem); } @@ -174,8 +174,8 @@ function testInnerHTMLExtendedUpgrade() { // register -> create element -> insert into document -> remove from document function testRegisterResolved() { var createdCallbackCalled = false; - var enteredViewCallbackCalled = false; - var leftViewCallbackCalled = false; + var attachedCallbackCalled = false; + var detachedCallbackCalled = false; var createdCallbackThis; @@ -186,18 +186,18 @@ function testRegisterResolved() { createdCallbackCalled = true; }; - p.enteredViewCallback = function() { - is(createdCallbackCalled, true, "created callback should be called before enteredView callback."); - is(enteredViewCallbackCalled, false, "enteredView callback should only be called on in this test."); + p.attachedCallback = function() { + is(createdCallbackCalled, true, "created callback should be called before attached callback."); + is(attachedCallbackCalled, false, "attached callback should only be called on in this test."); is(this, createdElement, "The 'this' value should be the custom element."); - enteredViewCallbackCalled = true; + attachedCallbackCalled = true; }; - p.leftViewCallback = function() { - is(enteredViewCallbackCalled, true, "enteredView callback should be called before leftView"); - is(leftViewCallbackCalled, false, "leftView callback should only be called once in this test."); + p.detachedCallback = function() { + is(attachedCallbackCalled, true, "attached callback should be called before detached"); + is(detachedCallbackCalled, false, "detached callback should only be called once in this test."); is(this, createdElement, "The 'this' value should be the custom element."); - leftViewCallbackCalled = true; + detachedCallbackCalled = true; runNextTest(); }; @@ -212,10 +212,10 @@ function testRegisterResolved() { is(createdCallbackThis, createdElement, "The 'this' value in the created callback should be the custom element."); is(createdElement.__proto__, p, "Prototype of custom element should be the registered prototype."); - // Insert element into document to trigger enteredView callback. + // Insert element into document to trigger attached callback. container.appendChild(createdElement); - // Remove element from document to trigger leftView callback. + // Remove element from document to trigger detached callback. container.removeChild(createdElement); } @@ -319,11 +319,11 @@ function testUpgradeCandidate() { function testNotInDocEnterLeave() { var p = Object.create(HTMLElement.prototype); - p.enteredView = function() { - ok(false, "enteredView should not be called when not entering the document."); + p.attached = function() { + ok(false, "attached should not be called when not entering the document."); }; - p.leftView = function() { + p.detached = function() { ok(false, "leaveView should not be called when not leaving the document."); }; @@ -343,19 +343,19 @@ function testNotInDocEnterLeave() { } function testEnterLeaveView() { - var enteredViewCallbackCalled = false; - var leftViewCallbackCalled = false; + var attachedCallbackCalled = false; + var detachedCallbackCalled = false; var p = Object.create(HTMLElement.prototype); - p.enteredViewCallback = function() { - is(enteredViewCallbackCalled, false, "enteredView callback should only be called on in this test."); - enteredViewCallbackCalled = true; + p.attachedCallback = function() { + is(attachedCallbackCalled, false, "attached callback should only be called on in this test."); + attachedCallbackCalled = true; }; - p.leftViewCallback = function() { - is(enteredViewCallbackCalled, true, "enteredView callback should be called before leftView"); - is(leftViewCallbackCalled, false, "leftView callback should only be called once in this test."); - leftViewCallbackCalled = true; + p.detachedCallback = function() { + is(attachedCallbackCalled, true, "attached callback should be called before detached"); + is(detachedCallbackCalled, false, "detached callback should only be called once in this test."); + detachedCallbackCalled = true; runNextTest(); }; @@ -363,7 +363,7 @@ function testEnterLeaveView() { document.registerElement("x-element-in-div", { prototype: p }); var customElement = document.createElement("x-element-in-div"); div.appendChild(customElement); - is(enteredViewCallbackCalled, false, "Appending a custom element to a node that is not in the document should not call the enteredView callback."); + is(attachedCallbackCalled, false, "Appending a custom element to a node that is not in the document should not call the attached callback."); container.appendChild(div); container.removeChild(div); diff --git a/dom/tests/mochitest/webcomponents/test_document_register_stack.html b/dom/tests/mochitest/webcomponents/test_document_register_stack.html index 23d78149697..34f1086549a 100644 --- a/dom/tests/mochitest/webcomponents/test_document_register_stack.html +++ b/dom/tests/mochitest/webcomponents/test_document_register_stack.html @@ -24,7 +24,7 @@ function testChangeAttributeInCreatedCallback() { var p = Object.create(HTMLElement.prototype); p.createdCallback = function() { - is(createdCallbackCalled, false, "Created callback should be called before enteredView callback."); + is(createdCallbackCalled, false, "Created callback should be called before attached callback."); createdCallbackCalled = true; is(attributeChangedCallbackCalled, false, "Attribute changed callback should not have been called prior to setting the attribute."); this.setAttribute("foo", "bar"); @@ -46,11 +46,11 @@ function testChangeAttributeInCreatedCallback() { function testChangeAttributeInEnteredViewCallback() { var p = Object.create(HTMLElement.prototype); var attributeChangedCallbackCalled = false; - var enteredViewCallbackCalled = false; + var attachedCallbackCalled = false; - p.enteredViewCallback = function() { - is(enteredViewCallbackCalled, false, "enteredView callback should be called only once in this test."); - enteredViewCallbackCalled = true; + p.attachedCallback = function() { + is(attachedCallbackCalled, false, "attached callback should be called only once in this test."); + attachedCallbackCalled = true; is(attributeChangedCallbackCalled, false, "Attribute changed callback should not be called before changing attribute."); this.setAttribute("foo", "bar"); is(attributeChangedCallbackCalled, true, "Transition from user-agent implementation to script should result in attribute changed callback being called."); @@ -58,7 +58,7 @@ function testChangeAttributeInEnteredViewCallback() { }; p.attributeChangedCallback = function() { - is(enteredViewCallbackCalled, true, "enteredView callback should have been called prior to attribute changed callback."); + is(attachedCallbackCalled, true, "attached callback should have been called prior to attribute changed callback."); is(attributeChangedCallbackCalled, false, "attributeChanged callback should only be called once in this tests."); attributeChangedCallbackCalled = true; }; @@ -72,24 +72,24 @@ function testChangeAttributeInEnteredViewCallback() { function testLeaveViewInEnteredViewCallback() { var p = Object.create(HTMLElement.prototype); - var enteredViewCallbackCalled = false; - var leftViewCallbackCalled = false; + var attachedCallbackCalled = false; + var detachedCallbackCalled = false; var container = document.getElementById("container"); - p.enteredViewCallback = function() { + p.attachedCallback = function() { is(this.parentNode, container, "Parent node should the container in which the node was appended."); - is(enteredViewCallbackCalled, false, "enteredView callback should be called only once in this test."); - enteredViewCallbackCalled = true; - is(leftViewCallbackCalled, false, "leftView callback should not be called prior to removing element from document."); + is(attachedCallbackCalled, false, "attached callback should be called only once in this test."); + attachedCallbackCalled = true; + is(detachedCallbackCalled, false, "detached callback should not be called prior to removing element from document."); container.removeChild(this); - is(leftViewCallbackCalled, true, "Transition from user-agent implementation to script should run left view callback."); + is(detachedCallbackCalled, true, "Transition from user-agent implementation to script should run left view callback."); runNextTest(); }; - p.leftViewCallback = function() { - is(leftViewCallbackCalled, false, "The left view callback should only be called once in this test."); - is(enteredViewCallbackCalled, true, "The entered view callback should be called prior to left view callback."); - leftViewCallbackCalled = true; + p.detachedCallback = function() { + is(detachedCallbackCalled, false, "The detached callback should only be called once in this test."); + is(attachedCallbackCalled, true, "The attached callback should be called prior to detached callback."); + detachedCallbackCalled = true; }; document.registerElement("x-three", { prototype: p }); diff --git a/dom/time/TimeChangeObserver.cpp b/dom/time/TimeChangeObserver.cpp index 2d74a7786b4..96c76e7f348 100644 --- a/dom/time/TimeChangeObserver.cpp +++ b/dom/time/TimeChangeObserver.cpp @@ -13,7 +13,6 @@ #include "mozilla/Services.h" #include "mozilla/StaticPtr.h" #include "nsPIDOMWindow.h" -#include "nsDOMEvent.h" #include "nsContentUtils.h" #include "nsIObserverService.h" #include "nsIDocument.h" diff --git a/dom/voicemail/Voicemail.h b/dom/voicemail/Voicemail.h index 5da306ea22c..6eb77dcf9ae 100644 --- a/dom/voicemail/Voicemail.h +++ b/dom/voicemail/Voicemail.h @@ -9,7 +9,6 @@ #include "mozilla/Attributes.h" #include "mozilla/ErrorResult.h" -#include "nsDOMEvent.h" #include "nsDOMEventTargetHelper.h" #include "nsIVoicemailProvider.h" diff --git a/dom/webidl/WebComponents.webidl b/dom/webidl/WebComponents.webidl index 9ed3c109099..3dfb960bc10 100644 --- a/dom/webidl/WebComponents.webidl +++ b/dom/webidl/WebComponents.webidl @@ -11,14 +11,14 @@ */ callback LifecycleCreatedCallback = void(); -callback LifecycleEnteredViewCallback = void(); -callback LifecycleLeftViewCallback = void(); +callback LifecycleAttachedCallback = void(); +callback LifecycleDetachedCallback = void(); callback LifecycleAttributeChangedCallback = void(DOMString attrName, DOMString? oldValue, DOMString? newValue); dictionary LifecycleCallbacks { LifecycleCreatedCallback? createdCallback; - LifecycleEnteredViewCallback? enteredViewCallback; - LifecycleLeftViewCallback? leftViewCallback; + LifecycleAttachedCallback? attachedCallback; + LifecycleDetachedCallback? detachedCallback; LifecycleAttributeChangedCallback? attributeChangedCallback; }; diff --git a/dom/workers/MessagePort.cpp b/dom/workers/MessagePort.cpp index f476d79d0ab..800da33f31f 100644 --- a/dom/workers/MessagePort.cpp +++ b/dom/workers/MessagePort.cpp @@ -6,8 +6,8 @@ #include "MessagePort.h" #include "mozilla/dom/MessagePortBinding.h" -#include "nsDOMEvent.h" #include "nsEventDispatcher.h" +#include "nsIDOMEvent.h" #include "SharedWorker.h" #include "WorkerPrivate.h" diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp index b9e8d079cf7..30362e1cc4a 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -2583,7 +2583,7 @@ WorkerThreadPrimaryRunnable::Run() mThread->SetWorker(nullptr); - mWorkerPrivate->ScheduleDeletion(); + mWorkerPrivate->ScheduleDeletion(WorkerPrivate::WorkerRan); // It is no longer safe to touch mWorkerPrivate. mWorkerPrivate = nullptr; diff --git a/dom/workers/SharedWorker.cpp b/dom/workers/SharedWorker.cpp index 9722556a6a5..63e691fe228 100644 --- a/dom/workers/SharedWorker.cpp +++ b/dom/workers/SharedWorker.cpp @@ -10,9 +10,9 @@ #include "mozilla/Preferences.h" #include "mozilla/dom/SharedWorkerBinding.h" #include "nsContentUtils.h" -#include "nsDOMEvent.h" #include "nsEventDispatcher.h" #include "nsIClassInfoImpl.h" +#include "nsIDOMEvent.h" #include "MessagePort.h" #include "RuntimeService.h" diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index fd9047b71f6..f5921e84fd2 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -2349,7 +2349,7 @@ WorkerPrivateParent::NotifyPrivate(JSContext* aCx, Status aStatus) #endif // Worker never got a chance to run, go ahead and delete it. - self->ScheduleDeletion(); + self->ScheduleDeletion(WorkerPrivate::WorkerNeverRan); return true; } @@ -4251,13 +4251,13 @@ WorkerPrivate::IsOnCurrentThread(bool* aIsOnCurrentThread) } void -WorkerPrivate::ScheduleDeletion() +WorkerPrivate::ScheduleDeletion(WorkerRanOrNot aRanOrNot) { AssertIsOnWorkerThread(); MOZ_ASSERT(mChildWorkers.IsEmpty()); MOZ_ASSERT(mSyncLoopStack.IsEmpty()); - ClearMainEventQueue(); + ClearMainEventQueue(aRanOrNot); if (WorkerPrivate* parent = GetParent()) { nsRefPtr runnable = @@ -4474,18 +4474,27 @@ WorkerPrivate::ProcessAllControlRunnablesLocked() } void -WorkerPrivate::ClearMainEventQueue() +WorkerPrivate::ClearMainEventQueue(WorkerRanOrNot aRanOrNot) { AssertIsOnWorkerThread(); - nsIThread* currentThread = NS_GetCurrentThread(); - MOZ_ASSERT(currentThread); - MOZ_ASSERT(!mCancelAllPendingRunnables); mCancelAllPendingRunnables = true; - NS_ProcessPendingEvents(currentThread); - MOZ_ASSERT(!NS_HasPendingEvents(currentThread)); + if (WorkerNeverRan == aRanOrNot) { + for (uint32_t count = mPreStartRunnables.Length(), index = 0; + index < count; + index++) { + nsRefPtr runnable = mPreStartRunnables[index].forget(); + static_cast(runnable.get())->Run(); + } + } else { + nsIThread* currentThread = NS_GetCurrentThread(); + MOZ_ASSERT(currentThread); + + NS_ProcessPendingEvents(currentThread); + MOZ_ASSERT(!NS_HasPendingEvents(currentThread)); + } MOZ_ASSERT(mCancelAllPendingRunnables); mCancelAllPendingRunnables = false; @@ -5031,7 +5040,7 @@ WorkerPrivate::NotifyInternal(JSContext* aCx, Status aStatus) // If this is the first time our status has changed then we need to clear the // main event queue. if (previousStatus == Running) { - ClearMainEventQueue(); + ClearMainEventQueue(WorkerRan); } // If we've run the close handler, we don't need to do anything else. diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h index ce66719b3cc..263b5f3076e 100644 --- a/dom/workers/WorkerPrivate.h +++ b/dom/workers/WorkerPrivate.h @@ -915,8 +915,13 @@ public: void UpdateJSWorkerMemoryParameterInternal(JSContext* aCx, JSGCParamKey key, uint32_t aValue); + enum WorkerRanOrNot { + WorkerNeverRan = 0, + WorkerRan + }; + void - ScheduleDeletion(); + ScheduleDeletion(WorkerRanOrNot aRanOrNot); bool BlockAndCollectRuntimeStats(JS::RuntimeStats* aRtStats); @@ -1047,7 +1052,7 @@ private: LoadInfo& aLoadInfo); void - ClearMainEventQueue(); + ClearMainEventQueue(WorkerRanOrNot aRanOrNot); bool MayContinueRunning() diff --git a/dom/xbl/nsXBLEventHandler.cpp b/dom/xbl/nsXBLEventHandler.cpp index 44dbf147456..000759150af 100644 --- a/dom/xbl/nsXBLEventHandler.cpp +++ b/dom/xbl/nsXBLEventHandler.cpp @@ -4,13 +4,13 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsCOMPtr.h" -#include "nsDOMEvent.h" #include "nsIAtom.h" #include "nsIDOMEventListener.h" #include "nsIDOMKeyEvent.h" #include "nsIDOMMouseEvent.h" #include "nsXBLPrototypeHandler.h" #include "nsContentUtils.h" +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() #include "mozilla/dom/EventTarget.h" using namespace mozilla::dom; diff --git a/dom/xbl/nsXBLService.cpp b/dom/xbl/nsXBLService.cpp index fb6bd1f35c3..e6d41da056e 100644 --- a/dom/xbl/nsXBLService.cpp +++ b/dom/xbl/nsXBLService.cpp @@ -45,16 +45,16 @@ #include "nsIScriptSecurityManager.h" #include "nsIScriptError.h" #include "nsXBLSerialize.h" -#include "nsDOMEvent.h" #include "nsEventListenerManager.h" #ifdef MOZ_XUL #include "nsXULPrototypeCache.h" #endif #include "nsIDOMEventListener.h" -#include "mozilla/Preferences.h" -#include "mozilla/dom/Element.h" #include "mozilla/Attributes.h" +#include "mozilla/Preferences.h" +#include "mozilla/dom/Event.h" +#include "mozilla/dom/Element.h" using namespace mozilla; using namespace mozilla::dom; @@ -287,7 +287,7 @@ nsXBLStreamListener::HandleEvent(nsIDOMEvent* aEvent) // Get the binding document; note that we don't hold onto it in this object // to avoid creating a cycle - nsDOMEvent* event = aEvent->InternalDOMEvent(); + Event* event = aEvent->InternalDOMEvent(); EventTarget* target = event->GetCurrentTarget(); nsCOMPtr bindingDocument = do_QueryInterface(target); NS_ASSERTION(bindingDocument, "Event not targeted at document?!"); diff --git a/content/xbl/test/test_bug872273.xhtml b/dom/xbl/test/test_bug872273.xhtml similarity index 100% rename from content/xbl/test/test_bug872273.xhtml rename to dom/xbl/test/test_bug872273.xhtml diff --git a/editor/libeditor/base/IMETextTxn.cpp b/editor/libeditor/base/IMETextTxn.cpp index 7f9b9313b80..9eaf1843743 100644 --- a/editor/libeditor/base/IMETextTxn.cpp +++ b/editor/libeditor/base/IMETextTxn.cpp @@ -4,6 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "IMETextTxn.h" +#include "mozilla/DebugOnly.h" // for DebugOnly #include "mozilla/mozalloc.h" // for operator new #include "mozilla/TextEvents.h" // for TextRangeStyle #include "nsAString.h" // for nsAString_internal::Length, etc diff --git a/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp b/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp index fd498fb203c..d9cc265ae1f 100644 --- a/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp +++ b/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp @@ -65,7 +65,7 @@ #include "nsIDOMDragEvent.h" #include "nsIConstraintValidation.h" #include "mozilla/Attributes.h" -#include "nsDOMEvent.h" +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() using namespace mozilla; using namespace mozilla::dom; diff --git a/embedding/components/windowwatcher/src/nsAutoWindowStateHelper.cpp b/embedding/components/windowwatcher/src/nsAutoWindowStateHelper.cpp index a3cae9a111b..7b00e8149f6 100644 --- a/embedding/components/windowwatcher/src/nsAutoWindowStateHelper.cpp +++ b/embedding/components/windowwatcher/src/nsAutoWindowStateHelper.cpp @@ -5,7 +5,7 @@ #include "nsAutoWindowStateHelper.h" -#include "nsDOMEvent.h" +#include "mozilla/dom/Event.h" #include "nsIDocument.h" #include "nsIDOMEvent.h" #include "nsIDOMWindow.h" @@ -59,7 +59,7 @@ nsAutoWindowStateHelper::DispatchEventToChrome(const char *aEventName) } ErrorResult rv; - nsRefPtr event = doc->CreateEvent(NS_LITERAL_STRING("Events"), rv); + nsRefPtr event = doc->CreateEvent(NS_LITERAL_STRING("Events"), rv); if (rv.Failed()) { return false; } diff --git a/embedding/tests/winEmbed/Makefile.in b/embedding/tests/winEmbed/Makefile.in index c4895ada9f9..25534b1ac87 100644 --- a/embedding/tests/winEmbed/Makefile.in +++ b/embedding/tests/winEmbed/Makefile.in @@ -32,8 +32,6 @@ LIBS = \ $(XPCOM_STANDALONE_GLUE_LDOPTS) \ $(NULL) -STL_FLAGS= - OS_LIBS += $(call EXPAND_LIBNAME,ole32 comdlg32 shell32 version) include $(topsrcdir)/config/rules.mk diff --git a/embedding/tests/winEmbed/moz.build b/embedding/tests/winEmbed/moz.build index 9d68e125d9b..350d9e430c3 100644 --- a/embedding/tests/winEmbed/moz.build +++ b/embedding/tests/winEmbed/moz.build @@ -31,3 +31,5 @@ else: # # Set it to 256k. See bug 127069. LDFLAGS += ['/HEAP:0x40000'] + +DISABLE_STL_WRAPPING = True diff --git a/gfx/angle/src/libEGL/Makefile.in b/gfx/angle/src/libEGL/Makefile.in index 26ee6635b2b..be9fc078ab7 100644 --- a/gfx/angle/src/libEGL/Makefile.in +++ b/gfx/angle/src/libEGL/Makefile.in @@ -2,9 +2,6 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# ANGLE uses the STL, so we can't use our derpy STL wrappers. -STL_FLAGS = - ifndef GNU_CC # Enable unwind semantics for exception handlers in response to warning C4530. OS_CPPFLAGS += -EHsc diff --git a/gfx/angle/src/libEGL/moz.build b/gfx/angle/src/libEGL/moz.build index fd61d51afa3..6890cf70ede 100644 --- a/gfx/angle/src/libEGL/moz.build +++ b/gfx/angle/src/libEGL/moz.build @@ -45,3 +45,6 @@ DEFINES['ANGLE_COMPILE_OPTIMIZATION_LEVEL'] = 'D3DCOMPILE_OPTIMIZATION_LEVEL1' RCFILE = SRCDIR + '/libEGL.rc' DEFFILE = SRCDIR + '/libEGL.def' + +# ANGLE uses the STL, so we can't use our derpy STL wrappers. +DISABLE_STL_WRAPPING = True diff --git a/gfx/angle/src/libGLESv2/Makefile.in b/gfx/angle/src/libGLESv2/Makefile.in index 00002a2b6b0..ae8cc4f944c 100644 --- a/gfx/angle/src/libGLESv2/Makefile.in +++ b/gfx/angle/src/libGLESv2/Makefile.in @@ -2,9 +2,6 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# ANGLE uses the STL, so we can't use our derpy STL wrappers. -STL_FLAGS = - ifndef GNU_CC # Enable unwind semantics for exception handlers in response to warning C4530. OS_CPPFLAGS += -EHsc diff --git a/gfx/angle/src/libGLESv2/moz.build b/gfx/angle/src/libGLESv2/moz.build index 5b55b960288..790dac06390 100644 --- a/gfx/angle/src/libGLESv2/moz.build +++ b/gfx/angle/src/libGLESv2/moz.build @@ -199,3 +199,6 @@ DEFINES['ANGLE_COMPILE_OPTIMIZATION_LEVEL'] = 'D3DCOMPILE_OPTIMIZATION_LEVEL1' RCFILE = SRCDIR + '/libGLESv2.rc' DEFFILE = SRCDIR + '/libGLESv2.def' + +# ANGLE uses the STL, so we can't use our derpy STL wrappers. +DISABLE_STL_WRAPPING = True diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index 4388a209c30..022a1ed3b1e 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -186,18 +186,13 @@ Layer::~Layer() {} Animation* -Layer::AddAnimation(TimeStamp aStart, TimeDuration aDuration, float aIterations, - int aDirection, nsCSSProperty aProperty, const AnimationData& aData) +Layer::AddAnimation() { MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) AddAnimation", this)); + MOZ_ASSERT(!mPendingAnimations, "should have called ClearAnimations first"); + Animation* anim = mAnimations.AppendElement(); - anim->startTime() = aStart; - anim->duration() = aDuration; - anim->numIterations() = aIterations; - anim->direction() = aDirection; - anim->property() = aProperty; - anim->data() = aData; Mutated(); return anim; @@ -206,6 +201,8 @@ Layer::AddAnimation(TimeStamp aStart, TimeDuration aDuration, float aIterations, void Layer::ClearAnimations() { + mPendingAnimations = nullptr; + if (mAnimations.IsEmpty() && mAnimationData.IsEmpty()) { return; } @@ -216,6 +213,28 @@ Layer::ClearAnimations() Mutated(); } +Animation* +Layer::AddAnimationForNextTransaction() +{ + MOZ_ASSERT(mPendingAnimations, + "should have called ClearAnimationsForNextTransaction first"); + + Animation* anim = mPendingAnimations->AppendElement(); + + return anim; +} + +void +Layer::ClearAnimationsForNextTransaction() +{ + // Ensure we have a non-null mPendingAnimations to mark a future clear. + if (!mPendingAnimations) { + mPendingAnimations = new AnimationArray; + } + + mPendingAnimations->Clear(); +} + static nsCSSValueSharedList* CreateCSSValueList(const InfallibleTArray& aFunctions) { @@ -648,6 +667,13 @@ Layer::ApplyPendingUpdatesForThisTransaction() Mutated(); } mPendingTransform = nullptr; + + if (mPendingAnimations) { + MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PendingUpdatesForThisTransaction", this)); + mPendingAnimations->SwapElements(mAnimations); + mPendingAnimations = nullptr; + Mutated(); + } } const float diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 232c488cf54..56f04b6d648 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -942,17 +942,21 @@ public: } // Call AddAnimation to add a new animation to this layer from layout code. - // Caller must add segments to the returned animation. - // aStart represents the time at the *end* of the delay. - Animation* AddAnimation(mozilla::TimeStamp aStart, mozilla::TimeDuration aDuration, - float aIterations, int aDirection, - nsCSSProperty aProperty, const AnimationData& aData); + // Caller must fill in all the properties of the returned animation. + Animation* AddAnimation(); // ClearAnimations clears animations on this layer. void ClearAnimations(); // This is only called when the layer tree is updated. Do not call this from // layout code. To add an animation to this layer, use AddAnimation. void SetAnimations(const AnimationArray& aAnimations); + // These are a parallel to AddAnimation and clearAnimations, except + // they add pending animations that apply only when the next + // transaction is begun. (See also + // SetBaseTransformForNextTransaction.) + Animation* AddAnimationForNextTransaction(); + void ClearAnimationsForNextTransaction(); + /** * CONSTRUCTION PHASE ONLY * If a layer is "fixed position", this determines which point on the layer @@ -1413,6 +1417,8 @@ protected: float mPostYScale; gfx::Matrix4x4 mEffectiveTransform; AnimationArray mAnimations; + // See mPendingTransform above. + nsAutoPtr mPendingAnimations; InfallibleTArray mAnimationData; float mOpacity; gfx::CompositionOp mMixBlendMode; diff --git a/gfx/layers/composite/AsyncCompositionManager.cpp b/gfx/layers/composite/AsyncCompositionManager.cpp index bb6e778689a..0a506536952 100644 --- a/gfx/layers/composite/AsyncCompositionManager.cpp +++ b/gfx/layers/composite/AsyncCompositionManager.cpp @@ -413,10 +413,26 @@ SampleAnimations(Layer* aLayer, TimeStamp aPoint) Animation& animation = animations[i]; AnimData& animData = animationData[i]; + activeAnimations = true; + + TimeDuration elapsedDuration = aPoint - animation.startTime(); + // Skip animations that are yet to start. + // + // Currently, this should only happen when the refresh driver is under test + // control and is made to produce a time in the past or is restored from + // test control causing it to jump backwards in time. + // + // Since activeAnimations is true, this could mean we keep compositing + // unnecessarily during the delay, but so long as this only happens while + // the refresh driver is under test control that should be ok. + if (elapsedDuration.ToSeconds() < 0) { + continue; + } + double numIterations = animation.numIterations() != -1 ? animation.numIterations() : NS_IEEEPositiveInfinity(); double positionInIteration = - ElementAnimations::GetPositionInIteration(aPoint - animation.startTime(), + ElementAnimations::GetPositionInIteration(elapsedDuration, animation.duration(), numIterations, animation.direction()); @@ -437,8 +453,6 @@ SampleAnimations(Layer* aLayer, TimeStamp aPoint) double portion = animData.mFunctions[segmentIndex]->GetValue(positionInSegment); - activeAnimations = true; - // interpolate the property Animatable interpolatedValue; SampleValue(portion, animation, animData.mStartValues[segmentIndex], diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index e31a9db0e8c..4ec007faa7d 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -835,7 +835,7 @@ RasterImage::CopyFrame(uint32_t aWhichFrame, nsresult rv; - if (!ApplyDecodeFlags(aFlags)) + if (!ApplyDecodeFlags(aFlags, aWhichFrame)) return NS_ERROR_NOT_AVAILABLE; // If requested, synchronously flush any data we have lying around to the decoder @@ -896,7 +896,7 @@ RasterImage::GetFrame(uint32_t aWhichFrame, if (mInDecoder && (aFlags & imgIContainer::FLAG_SYNC_DECODE)) return nullptr; - if (!ApplyDecodeFlags(aFlags)) + if (!ApplyDecodeFlags(aFlags, aWhichFrame)) return nullptr; // If the caller requested a synchronous decode, do it @@ -1183,12 +1183,23 @@ RasterImage::InternalAddFrame(uint32_t framenum, } bool -RasterImage::ApplyDecodeFlags(uint32_t aNewFlags) +RasterImage::ApplyDecodeFlags(uint32_t aNewFlags, uint32_t aWhichFrame) { if (mFrameDecodeFlags == (aNewFlags & DECODE_FLAGS_MASK)) return true; // Not asking very much of us here. if (mDecoded) { + // If the requested frame is opaque and the current and new decode flags + // only differ in the premultiply alpha bit then we can use the existing + // frame, we don't need to discard and re-decode. + uint32_t currentNonAlphaFlags = + (mFrameDecodeFlags & DECODE_FLAGS_MASK) & ~FLAG_DECODE_NO_PREMULTIPLY_ALPHA; + uint32_t newNonAlphaFlags = + (aNewFlags & DECODE_FLAGS_MASK) & ~FLAG_DECODE_NO_PREMULTIPLY_ALPHA; + if (currentNonAlphaFlags == newNonAlphaFlags && FrameIsOpaque(aWhichFrame)) { + return true; + } + // if we can't discard, then we're screwed; we have no way // to re-decode. Similarly if we aren't allowed to do a sync // decode. @@ -2616,8 +2627,16 @@ RasterImage::Draw(gfxContext *aContext, NS_ENSURE_ARG_POINTER(aContext); - // We can only draw with the default decode flags - if (mFrameDecodeFlags != DECODE_FLAGS_DEFAULT) { + // We can only draw without discarding and redecoding in these cases: + // * We have the default decode flags. + // * We have exactly FLAG_DECODE_NO_PREMULTIPLY_ALPHA and the current frame + // is opaque. + bool haveDefaultFlags = (mFrameDecodeFlags == DECODE_FLAGS_DEFAULT); + bool haveSafeAlphaFlags = + (mFrameDecodeFlags == FLAG_DECODE_NO_PREMULTIPLY_ALPHA) && + FrameIsOpaque(FRAME_CURRENT); + + if (!(haveDefaultFlags || haveSafeAlphaFlags)) { if (!CanForciblyDiscardAndRedecode()) return NS_ERROR_NOT_AVAILABLE; ForceDiscard(); diff --git a/image/src/RasterImage.h b/image/src/RasterImage.h index d166451fc26..037c3e9bcb4 100644 --- a/image/src/RasterImage.h +++ b/image/src/RasterImage.h @@ -590,7 +590,7 @@ private: nsresult DoImageDataComplete(); - bool ApplyDecodeFlags(uint32_t aNewFlags); + bool ApplyDecodeFlags(uint32_t aNewFlags, uint32_t aWhichFrame); already_AddRefed GetCurrentImage(); void UpdateImageContainer(); diff --git a/image/src/SurfaceCache.cpp b/image/src/SurfaceCache.cpp index 972aa78242d..cad2efa2a17 100644 --- a/image/src/SurfaceCache.cpp +++ b/image/src/SurfaceCache.cpp @@ -15,6 +15,7 @@ #include "mozilla/Preferences.h" #include "mozilla/RefPtr.h" #include "mozilla/StaticPtr.h" +#include "nsIMemoryReporter.h" #include "gfx2DGlue.h" #include "gfxASurface.h" #include "gfxPattern.h" // Workaround for flaw in bug 921753 part 2. diff --git a/ipc/glue/MessageChannel.cpp b/ipc/glue/MessageChannel.cpp index a1aa053d9a1..745d4e5a30d 100644 --- a/ipc/glue/MessageChannel.cpp +++ b/ipc/glue/MessageChannel.cpp @@ -204,7 +204,8 @@ MessageChannel::MessageChannel(MessageListener *aListener) mDispatchingSyncMessage(false), mDispatchingUrgentMessageCount(0), mRemoteStackDepthGuess(false), - mSawInterruptOutMsg(false) + mSawInterruptOutMsg(false), + mAbortOnError(false) { MOZ_COUNT_CTOR(ipc::MessageChannel); @@ -1517,6 +1518,9 @@ MessageChannel::OnChannelErrorFromLink() NotifyWorkerThread(); if (ChannelClosing != mChannelState) { + if (mAbortOnError) { + NS_RUNTIMEABORT("Aborting on channel error."); + } mChannelState = ChannelError; mMonitor->Notify(); } diff --git a/ipc/glue/MessageChannel.h b/ipc/glue/MessageChannel.h index c5bcbde261a..784e4cb64b2 100644 --- a/ipc/glue/MessageChannel.h +++ b/ipc/glue/MessageChannel.h @@ -81,6 +81,11 @@ class MessageChannel : HasResultCodes // for process links only, not thread links. void CloseWithError(); + void SetAbortOnError(bool abort) + { + mAbortOnError = true; + } + // Asynchronously send a message to the other side of the channel bool Send(Message* aMsg); @@ -623,6 +628,10 @@ class MessageChannel : HasResultCodes #ifdef OS_WIN HANDLE mEvent; #endif + + // Should the channel abort the process from the I/O thread when + // a channel error occurs? + bool mAbortOnError; }; } // namespace ipc diff --git a/js/jsd/idl/jsdIDebuggerService.idl b/js/jsd/idl/jsdIDebuggerService.idl index 0a50b61341a..4c5b2230485 100644 --- a/js/jsd/idl/jsdIDebuggerService.idl +++ b/js/jsd/idl/jsdIDebuggerService.idl @@ -44,8 +44,12 @@ interface jsdIActivationCallback; /** * Debugger service. It is not a good idea to have more than one active client * of the debugger service. + * + * Note that all the APIs in this file are deprecated. All consumers of + * these interfaces should switch to using the new Debugger API, documented + * here: https://wiki.mozilla.org/Debugger */ -[scriptable, uuid(029b8f0a-aa84-47eb-a60f-1a4752b7ad06)] +[scriptable, uuid(39609752-2d73-4019-a324-a374dee16d3c)] interface jsdIDebuggerService : nsISupports { /** Internal use only. */ @@ -348,6 +352,16 @@ interface jsdIDebuggerService : nsISupports * @param fileName Filename to dump the heap into. */ void dumpHeap(in AUTF8String fileName); + + /** + * Suppress console warnings about using JSD, which is a deprecated API. + * + * This applies only to the next call to asyncOn; any subsequent calls + * will elicit the warning, unless you call 'acknowledgeDeprecation' + * before each of them, too. This arrangement ensures that one add-on's + * acknowledgement doesn't suppress warnings for other add-ons. + */ + void acknowledgeDeprecation(); }; /* callback interfaces */ diff --git a/js/jsd/jsd_xpc.cpp b/js/jsd/jsd_xpc.cpp index ca1c299b1b0..4c9d8a4b110 100644 --- a/js/jsd/jsd_xpc.cpp +++ b/js/jsd/jsd_xpc.cpp @@ -20,6 +20,7 @@ #include "nsICategoryManager.h" #include "nsIJSRuntimeService.h" #include "nsIThreadInternal.h" +#include "nsIScriptError.h" #include "nsTArray.h" #include "nsThreadUtils.h" #include "nsMemory.h" @@ -2463,11 +2464,30 @@ jsdService::AsyncOn (jsdIActivationCallback *activationCallback) { nsresult rv; + // Warn that JSD is deprecated, unless the caller has told us + // that they know already. + if (mDeprecationAcknowledged) { + mDeprecationAcknowledged = false; + } else if (!mWarnedAboutDeprecation) { + // In any case, warn only once. + mWarnedAboutDeprecation = true; + + // Ignore errors: simply being unable to print the message + // shouldn't (effectively) disable JSD. + nsContentUtils::ReportToConsoleNonLocalized( + NS_LITERAL_STRING("\ +The jsdIDebuggerService and its associated interfaces are deprecated. \ +Please use Debugger, via IJSDebugger, instead."), + nsIScriptError::warningFlag, + NS_LITERAL_CSTRING("JSD"), + nullptr); + } + nsCOMPtr xpc = do_GetService(nsIXPConnect::GetCID(), &rv); if (NS_FAILED(rv)) return rv; mActivationCallback = activationCallback; - + return xpc->SetDebugModeWhenPossible(true, true); } @@ -3039,6 +3059,13 @@ jsdService::ExitNestedEventLoop (uint32_t *_rval) return NS_OK; } +NS_IMETHODIMP +jsdService::AcknowledgeDeprecation() +{ + mDeprecationAcknowledged = true; + return NS_OK; +} + /* hook attribute get/set functions */ NS_IMETHODIMP diff --git a/js/jsd/jsd_xpc.h b/js/jsd/jsd_xpc.h index 013fd589047..e0639864608 100644 --- a/js/jsd/jsd_xpc.h +++ b/js/jsd/jsd_xpc.h @@ -262,7 +262,9 @@ class jsdService : public jsdIDebuggerService mNestedLoopLevel(0), mCx(0), mRuntime(0), mErrorHook(0), mBreakpointHook(0), mDebugHook(0), mDebuggerHook(0), mInterruptHook(0), mScriptHook(0), mThrowHook(0), - mTopLevelHook(0), mFunctionHook(0) + mTopLevelHook(0), mFunctionHook(0), + mWarnedAboutDeprecation(false), + mDeprecationAcknowledged(false) { } @@ -292,6 +294,14 @@ class jsdService : public jsdIDebuggerService nsCOMPtr mTopLevelHook; nsCOMPtr mFunctionHook; nsCOMPtr mActivationCallback; + + // True if we have ever printed a warning about JSD being deprecated. + // We only ever print the warning once. + bool mWarnedAboutDeprecation; + + // True if the next call to asyncOn should not produce a warning, + // because the consumer called jsdIDebuggerService::acknowledgeDeprecation. + bool mDeprecationAcknowledged; }; #endif /* JSDSERVICE_H___ */ diff --git a/js/src/builtin/Object.cpp b/js/src/builtin/Object.cpp index 7fd7c7e8881..a1ad7027973 100644 --- a/js/src/builtin/Object.cpp +++ b/js/src/builtin/Object.cpp @@ -145,7 +145,7 @@ js::ObjectToSource(JSContext *cx, HandleObject obj) int valcnt = 0; if (shape) { bool doGet = true; - if (obj2->isNative() && !IsImplicitDenseElement(shape)) { + if (obj2->isNative() && !IsImplicitDenseOrTypedArrayElement(shape)) { unsigned attrs = shape->attributes(); if (attrs & JSPROP_GETTER) { doGet = false; @@ -454,7 +454,7 @@ obj_lookupGetter(JSContext *cx, unsigned argc, Value *vp) return false; args.rval().setUndefined(); if (shape) { - if (pobj->isNative() && !IsImplicitDenseElement(shape)) { + if (pobj->isNative() && !IsImplicitDenseOrTypedArrayElement(shape)) { if (shape->hasGetterValue()) args.rval().set(shape->getterValue()); } @@ -490,7 +490,7 @@ obj_lookupSetter(JSContext *cx, unsigned argc, Value *vp) return false; args.rval().setUndefined(); if (shape) { - if (pobj->isNative() && !IsImplicitDenseElement(shape)) { + if (pobj->isNative() && !IsImplicitDenseOrTypedArrayElement(shape)) { if (shape->hasSetterValue()) args.rval().set(shape->setterValue()); } diff --git a/js/src/builtin/SIMD.cpp b/js/src/builtin/SIMD.cpp index 413d0f44b98..114e32dde44 100644 --- a/js/src/builtin/SIMD.cpp +++ b/js/src/builtin/SIMD.cpp @@ -874,63 +874,36 @@ Int32x4Select(JSContext *cx, unsigned argc, Value *vp) return true; } +#define DEFINE_SIMD_FLOAT32X4_FUNCTION(Name, Func, Operands, Flags, MIRId) \ +bool \ +js::simd_float32x4_##Name(JSContext *cx, unsigned argc, Value *vp) \ +{ \ + return Func(cx, argc, vp); \ +} +FLOAT32X4_FUNCTION_LIST(DEFINE_SIMD_FLOAT32X4_FUNCTION) +#undef DEFINE_SIMD_FLOAT32x4_FUNCTION + +#define DEFINE_SIMD_INT32X4_FUNCTION(Name, Func, Operands, Flags, MIRId) \ +bool \ +js::simd_int32x4_##Name(JSContext *cx, unsigned argc, Value *vp) \ +{ \ + return Func(cx, argc, vp); \ +} +INT32X4_FUNCTION_LIST(DEFINE_SIMD_INT32X4_FUNCTION) +#undef DEFINE_SIMD_INT32X4_FUNCTION + const JSFunctionSpec js::Float32x4Methods[] = { - JS_FN("abs", (Func, Float32x4>), 1, 0), - JS_FN("neg", (Func, Float32x4>), 1, 0), - JS_FN("reciprocal", (Func, Float32x4>), 1, 0), - JS_FN("reciprocalSqrt", (Func, Float32x4>), 1, 0), - JS_FN("sqrt", (Func, Float32x4>), 1, 0), - JS_FN("add", (Func, Float32x4>), 2, 0), - JS_FN("sub", (Func, Float32x4>), 2, 0), - JS_FN("div", (Func, Float32x4>), 2, 0), - JS_FN("mul", (Func, Float32x4>), 2, 0), - JS_FN("max", (Func, Float32x4>), 2, 0), - JS_FN("min", (Func, Float32x4>), 2, 0), - JS_FN("lessThan", (Func, Int32x4>), 2, 0), - JS_FN("lessThanOrEqual", (Func, Int32x4>), 2, 0), - JS_FN("greaterThan", (Func, Int32x4>), 2, 0), - JS_FN("greaterThanOrEqual", (Func, Int32x4>), 2, 0), - JS_FN("equal", (Func, Int32x4>), 2, 0), - JS_FN("notEqual", (Func, Int32x4>), 2, 0), - JS_FN("withX", (FuncWith, Float32x4>), 2, 0), - JS_FN("withY", (FuncWith, Float32x4>), 2, 0), - JS_FN("withZ", (FuncWith, Float32x4>), 2, 0), - JS_FN("withW", (FuncWith, Float32x4>), 2, 0), - JS_FN("shuffle", (FuncShuffle, Float32x4>), 2, 0), - JS_FN("shuffleMix", (FuncShuffle, Float32x4>), 3, 0), - JS_FN("scale", (FuncWith, Float32x4>), 2, 0), - JS_FN("clamp", Float32x4Clamp, 3, 0), - JS_FN("toInt32x4", (FuncConvert), 1, 0), - JS_FN("bitsToInt32x4", (FuncConvertBits), 1, 0), - JS_FN("zero", (FuncZero), 0, 0), - JS_FN("splat", (FuncSplat), 0, 0), +#define SIMD_FLOAT32X4_FUNCTION_ITEM(Name, Func, Operands, Flags, MIRId) \ + JS_FN(#Name, js::simd_float32x4_##Name, Operands, Flags), + FLOAT32X4_FUNCTION_LIST(SIMD_FLOAT32X4_FUNCTION_ITEM) +#undef SIMD_FLOAT32x4_FUNCTION_ITEM JS_FS_END }; const JSFunctionSpec js::Int32x4Methods[] = { - JS_FN("not", (Func, Int32x4>), 1, 0), - JS_FN("neg", (Func, Int32x4>), 1, 0), - JS_FN("add", (Func, Int32x4>), 2, 0), - JS_FN("sub", (Func, Int32x4>), 2, 0), - JS_FN("mul", (Func, Int32x4>), 2, 0), - JS_FN("xor", (Func, Int32x4>), 2, 0), - JS_FN("and", (Func, Int32x4>), 2, 0), - JS_FN("or", (Func, Int32x4>), 2, 0), - JS_FN("withX", (FuncWith, Int32x4>), 2, 0), - JS_FN("withY", (FuncWith, Int32x4>), 2, 0), - JS_FN("withZ", (FuncWith, Int32x4>), 2, 0), - JS_FN("withW", (FuncWith, Int32x4>), 2, 0), - JS_FN("withFlagX", (FuncWith, Int32x4>), 2, 0), - JS_FN("withFlagY", (FuncWith, Int32x4>), 2, 0), - JS_FN("withFlagZ", (FuncWith, Int32x4>), 2, 0), - JS_FN("withFlagW", (FuncWith, Int32x4>), 2, 0), - JS_FN("shuffle", (FuncShuffle, Int32x4>), 2, 0), - JS_FN("shuffleMix", (FuncShuffle, Int32x4>), 3, 0), - JS_FN("toFloat32x4", (FuncConvert), 1, 0), - JS_FN("bitsToFloat32x4", (FuncConvertBits), 1, 0), - JS_FN("zero", (FuncZero), 0, 0), - JS_FN("splat", (FuncSplat), 0, 0), - JS_FN("select", Int32x4Select, 3, 0), - JS_FN("bool", Int32x4Bool, 4, 0), +#define SIMD_INT32X4_FUNCTION_ITEM(Name, Func, Operands, Flags, MIRId) \ + JS_FN(#Name, js::simd_int32x4_##Name, Operands, Flags), + INT32X4_FUNCTION_LIST(SIMD_INT32X4_FUNCTION_ITEM) +#undef SIMD_INT32X4_FUNCTION_ITEM JS_FS_END }; diff --git a/js/src/builtin/SIMD.h b/js/src/builtin/SIMD.h index a81f743dcc3..2e2e7c9c5f6 100644 --- a/js/src/builtin/SIMD.h +++ b/js/src/builtin/SIMD.h @@ -18,6 +18,90 @@ * https://github.com/johnmccutchan/ecmascript_simd/blob/master/src/ecmascript_simd.js */ +#define FLOAT32X4_NULLARY_FUNCTION_LIST(V) \ + V(zero, (FuncZero), 0, 0, Zero) + +#define FLOAT32X4_UNARY_FUNCTION_LIST(V) \ + V(abs, (Func, Float32x4>), 1, 0, Abs) \ + V(bitsToInt32x4, (FuncConvertBits), 1, 0, BitsToInt32x4) \ + V(neg, (Func, Float32x4>), 1, 0, Neg) \ + V(reciprocal, (Func, Float32x4>), 1, 0, Reciprocal) \ + V(reciprocalSqrt, (Func, Float32x4>), 1, 0, ReciprocalSqrt) \ + V(splat, (FuncSplat), 1, 0, Splat) \ + V(sqrt, (Func, Float32x4>), 1, 0, Sqrt) \ + V(toInt32x4, (FuncConvert), 1, 0, ToInt32x4) + +#define FLOAT32X4_BINARY_FUNCTION_LIST(V) \ + V(add, (Func, Float32x4>), 2, 0, Add) \ + V(div, (Func, Float32x4>), 2, 0, Div) \ + V(equal, (Func, Int32x4>), 2, 0, Equal) \ + V(greaterThan, (Func, Int32x4>), 2, 0, GreaterThan) \ + V(greaterThanOrEqual, (Func, Int32x4>), 2, 0, GreaterThanOrEqual) \ + V(lessThan, (Func, Int32x4>), 2, 0, LessThan) \ + V(lessThanOrEqual, (Func, Int32x4>), 2, 0, LessThanOrEqual) \ + V(max, (Func, Float32x4>), 2, 0, Max) \ + V(min, (Func, Float32x4>), 2, 0, Min) \ + V(mul, (Func, Float32x4>), 2, 0, Mul) \ + V(notEqual, (Func, Int32x4>), 2, 0, NotEqual) \ + V(shuffle, (FuncShuffle, Float32x4>), 2, 0, Shuffle) \ + V(scale, (FuncWith, Float32x4>), 2, 0, Scale) \ + V(sub, (Func, Float32x4>), 2, 0, Sub) \ + V(withX, (FuncWith, Float32x4>), 2, 0, WithX) \ + V(withY, (FuncWith, Float32x4>), 2, 0, WithY) \ + V(withZ, (FuncWith, Float32x4>), 2, 0, WithZ) \ + V(withW, (FuncWith, Float32x4>), 2, 0, WithW) + +#define FLOAT32X4_TERNARY_FUNCTION_LIST(V) \ + V(clamp, Float32x4Clamp, 3, 0, Clamp) \ + V(shuffleMix, (FuncShuffle, Float32x4>), 3, 0, ShuffleMix) + +#define FLOAT32X4_FUNCTION_LIST(V) \ + FLOAT32X4_NULLARY_FUNCTION_LIST(V) \ + FLOAT32X4_UNARY_FUNCTION_LIST(V) \ + FLOAT32X4_BINARY_FUNCTION_LIST(V) \ + FLOAT32X4_TERNARY_FUNCTION_LIST(V) + +#define INT32X4_NULLARY_FUNCTION_LIST(V) \ + V(zero, (FuncZero), 0, 0, Zero) + +#define INT32X4_UNARY_FUNCTION_LIST(V) \ + V(bitsToFloat32x4, (FuncConvertBits), 1, 0, BitsToFloat32x4) \ + V(neg, (Func, Int32x4>), 1, 0, Neg) \ + V(not, (Func, Int32x4>), 1, 0, Not) \ + V(splat, (FuncSplat), 0, 0, Splat) \ + V(toFloat32x4, (FuncConvert), 1, 0, ToFloat32x4) + +#define INT32X4_BINARY_FUNCTION_LIST(V) \ + V(add, (Func, Int32x4>), 2, 0, Add) \ + V(and, (Func, Int32x4>), 2, 0, And) \ + V(mul, (Func, Int32x4>), 2, 0, Mul) \ + V(or, (Func, Int32x4>), 2, 0, Or) \ + V(sub, (Func, Int32x4>), 2, 0, Sub) \ + V(shuffle, (FuncShuffle, Int32x4>), 2, 0, Shuffle) \ + V(withFlagX, (FuncWith, Int32x4>), 2, 0, WithFlagX) \ + V(withFlagY, (FuncWith, Int32x4>), 2, 0, WithFlagY) \ + V(withFlagZ, (FuncWith, Int32x4>), 2, 0, WithFlagZ) \ + V(withFlagW, (FuncWith, Int32x4>), 2, 0, WithFlagW) \ + V(withX, (FuncWith, Int32x4>), 2, 0, WithX) \ + V(withY, (FuncWith, Int32x4>), 2, 0, WithY) \ + V(withZ, (FuncWith, Int32x4>), 2, 0, WithZ) \ + V(withW, (FuncWith, Int32x4>), 2, 0, WithW) \ + V(xor, (Func, Int32x4>), 2, 0, Xor) + +#define INT32X4_TERNARY_FUNCTION_LIST(V) \ + V(select, Int32x4Select, 3, 0, Select) \ + V(shuffleMix, (FuncShuffle, Int32x4>), 3, 0, ShuffleMix) + +#define INT32X4_QUARTERNARY_FUNCTION_LIST(V) \ + V(bool, Int32x4Bool, 4, 0, Bool) + +#define INT32X4_FUNCTION_LIST(V) \ + INT32X4_NULLARY_FUNCTION_LIST(V) \ + INT32X4_UNARY_FUNCTION_LIST(V) \ + INT32X4_BINARY_FUNCTION_LIST(V) \ + INT32X4_TERNARY_FUNCTION_LIST(V) \ + INT32X4_QUARTERNARY_FUNCTION_LIST(V) + namespace js { class SIMDObject : public JSObject @@ -73,6 +157,18 @@ struct Int32x4 { template JSObject *Create(JSContext *cx, typename V::Elem *data); +#define DECLARE_SIMD_FLOAT32X4_FUNCTION(Name, Func, Operands, Flags, MIRId) \ +extern bool \ +simd_float32x4_##Name(JSContext *cx, unsigned argc, Value *vp); +FLOAT32X4_FUNCTION_LIST(DECLARE_SIMD_FLOAT32X4_FUNCTION) +#undef DECLARE_SIMD_FLOAT32X4_FUNCTION + +#define DECLARE_SIMD_INT32x4_FUNCTION(Name, Func, Operands, Flags, MIRId) \ +extern bool \ +simd_int32x4_##Name(JSContext *cx, unsigned argc, Value *vp); +INT32X4_FUNCTION_LIST(DECLARE_SIMD_INT32x4_FUNCTION) +#undef DECLARE_SIMD_INT32x4_FUNCTION + } /* namespace js */ JSObject * diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index ad48f4db972..0954b76f967 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -366,9 +366,19 @@ IsAboutToBeFinalized(T **thingp) return !(*thingp)->isMarked(); } +template +T * +UpdateIfRelocated(JSRuntime *rt, T **thingp) +{ + JS_ASSERT(thingp); + if (*thingp && rt->isHeapMinorCollecting()) + IsAboutToBeFinalized(thingp); + return *thingp; +} + #define DeclMarkerImpl(base, type) \ void \ -Mark##base(JSTracer *trc, BarrieredPtr *thing, const char *name) \ +Mark##base(JSTracer *trc, BarrieredPtr *thing, const char *name) \ { \ Mark(trc, thing, name); \ } \ @@ -409,7 +419,7 @@ Is##base##Marked(type **thingp) } \ \ bool \ -Is##base##Marked(BarrieredPtr *thingp) \ +Is##base##Marked(BarrieredPtr *thingp) \ { \ return IsMarked(thingp->unsafeGet()); \ } \ @@ -421,11 +431,24 @@ Is##base##AboutToBeFinalized(type **thingp) } \ \ bool \ -Is##base##AboutToBeFinalized(BarrieredPtr *thingp) \ +Is##base##AboutToBeFinalized(BarrieredPtr *thingp) \ { \ return IsAboutToBeFinalized(thingp->unsafeGet()); \ +} \ + \ +type * \ +Update##base##IfRelocated(JSRuntime *rt, BarrieredPtr *thingp) \ +{ \ + return UpdateIfRelocated(rt, thingp->unsafeGet()); \ +} \ + \ +type * \ +Update##base##IfRelocated(JSRuntime *rt, type **thingp) \ +{ \ + return UpdateIfRelocated(rt, thingp); \ } + DeclMarkerImpl(BaseShape, BaseShape) DeclMarkerImpl(BaseShape, UnownedBaseShape) DeclMarkerImpl(JitCode, jit::JitCode) diff --git a/js/src/gc/Marking.h b/js/src/gc/Marking.h index 961e7a506ee..16404fe4abe 100644 --- a/js/src/gc/Marking.h +++ b/js/src/gc/Marking.h @@ -80,17 +80,25 @@ namespace gc { * IsObjectMarked(JSObject **thing); * This function is indended to be used in rare cases in code used to mark * GC things. It indicates whether the object is currently marked. + * + * UpdateObjectIfRelocated(JSObject **thingp); + * In some circumstances -- e.g. optional weak marking -- it is necessary + * to look at the pointer before marking it strongly or weakly. In these + * cases, the following must be called to update the pointer before use. */ + #define DeclMarker(base, type) \ -void Mark##base(JSTracer *trc, BarrieredPtr *thing, const char *name); \ +void Mark##base(JSTracer *trc, BarrieredPtr *thing, const char *name); \ void Mark##base##Root(JSTracer *trc, type **thingp, const char *name); \ void Mark##base##Unbarriered(JSTracer *trc, type **thingp, const char *name); \ void Mark##base##Range(JSTracer *trc, size_t len, HeapPtr *thing, const char *name); \ void Mark##base##RootRange(JSTracer *trc, size_t len, type **thing, const char *name); \ bool Is##base##Marked(type **thingp); \ -bool Is##base##Marked(BarrieredPtr *thingp); \ +bool Is##base##Marked(BarrieredPtr *thingp); \ bool Is##base##AboutToBeFinalized(type **thingp); \ -bool Is##base##AboutToBeFinalized(BarrieredPtr *thingp); \ +bool Is##base##AboutToBeFinalized(BarrieredPtr *thingp); \ +type *Update##base##IfRelocated(JSRuntime *rt, BarrieredPtr *thingp); \ +type *Update##base##IfRelocated(JSRuntime *rt, type **thingp); DeclMarker(BaseShape, BaseShape) DeclMarker(BaseShape, UnownedBaseShape) diff --git a/js/src/gc/Nursery.cpp b/js/src/gc/Nursery.cpp index 50693dc4160..a204ff2b035 100644 --- a/js/src/gc/Nursery.cpp +++ b/js/src/gc/Nursery.cpp @@ -722,10 +722,10 @@ js::Nursery::collect(JSRuntime *rt, JS::gcreason::Reason reason, TypeObjectList AutoStopVerifyingBarriers av(rt, false); - /* Move objects pointed to by roots from the nursery to the major heap. */ + // Move objects pointed to by roots from the nursery to the major heap. MinorCollectionTracer trc(rt, this); - /* Mark the store buffer. This must happen first. */ + // Mark the store buffer. This must happen first. StoreBuffer &sb = rt->gcStoreBuffer; TIME_START(markValues); sb.markValues(&trc); @@ -771,25 +771,31 @@ js::Nursery::collect(JSRuntime *rt, JS::gcreason::Reason reason, TypeObjectList rt->newObjectCache.clearNurseryObjects(rt); TIME_END(clearNewObjectCache); - /* - * Most of the work is done here. This loop iterates over objects that have - * been moved to the major heap. If these objects have any outgoing pointers - * to the nursery, then those nursery objects get moved as well, until no - * objects are left to move. That is, we iterate to a fixed point. - */ + // Most of the work is done here. This loop iterates over objects that have + // been moved to the major heap. If these objects have any outgoing pointers + // to the nursery, then those nursery objects get moved as well, until no + // objects are left to move. That is, we iterate to a fixed point. TIME_START(collectToFP); TenureCountCache tenureCounts; collectToFixedPoint(&trc, tenureCounts); TIME_END(collectToFP); + // Update the array buffer object's view lists. + TIME_START(sweepArrayBufferViewList); + for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) { + if (c->gcLiveArrayBuffers) + ArrayBufferObject::sweep(c); + } + TIME_END(sweepArrayBufferViewList); + + // Update any slot or element pointers whose destination has been tenured. TIME_START(updateJitActivations); #ifdef JS_ION - /* Update any slot or element pointers whose destination has been tenured. */ js::jit::UpdateJitActivationsForMinorGC(rt, &trc); #endif TIME_END(updateJitActivations); - /* Resize the nursery. */ + // Resize the nursery. TIME_START(resize); double promotionRate = trc.tenuredSize / double(allocationEnd() - start()); if (promotionRate > 0.05) @@ -798,11 +804,11 @@ js::Nursery::collect(JSRuntime *rt, JS::gcreason::Reason reason, TypeObjectList shrinkAllocableSpace(); TIME_END(resize); - TIME_START(pretenure); // If we are promoting the nursery, or exhausted the store buffer with // pointers to nursery things, which will force a collection well before // the nursery is full, look for object types that are getting promoted // excessively and try to pretenure them. + TIME_START(pretenure); if (pretenureTypes && (promotionRate > 0.8 || reason == JS::gcreason::FULL_STORE_BUFFER)) { for (size_t i = 0; i < ArrayLength(tenureCounts.entries); i++) { const TenureCount &entry = tenureCounts.entries[i]; @@ -812,7 +818,7 @@ js::Nursery::collect(JSRuntime *rt, JS::gcreason::Reason reason, TypeObjectList } TIME_END(pretenure); - /* Sweep. */ + // Sweep. TIME_START(freeHugeSlots); freeHugeSlots(rt); TIME_END(freeHugeSlots); @@ -825,11 +831,9 @@ js::Nursery::collect(JSRuntime *rt, JS::gcreason::Reason reason, TypeObjectList rt->gcStoreBuffer.clear(); TIME_END(clearStoreBuffer); - /* - * We ignore gcMaxBytes when allocating for minor collection. However, if we - * overflowed, we disable the nursery. The next time we allocate, we'll fail - * because gcBytes >= gcMaxBytes. - */ + // We ignore gcMaxBytes when allocating for minor collection. However, if we + // overflowed, we disable the nursery. The next time we allocate, we'll fail + // because gcBytes >= gcMaxBytes. if (rt->gcBytes >= rt->gcMaxBytes) disable(); @@ -842,13 +846,13 @@ js::Nursery::collect(JSRuntime *rt, JS::gcreason::Reason reason, TypeObjectList static bool printedHeader = false; if (!printedHeader) { fprintf(stderr, - "MinorGC: Reason PRate Size Time mkVals mkClls mkSlts mkWCll mkRVal mkRCll mkGnrc ckTbls mkRntm mkDbgr clrNOC collct updtIn resize pretnr frSlts clrSB sweep\n"); + "MinorGC: Reason PRate Size Time mkVals mkClls mkSlts mkWCll mkRVal mkRCll mkGnrc ckTbls mkRntm mkDbgr clrNOC collct swpABO updtIn resize pretnr frSlts clrSB sweep\n"); printedHeader = true; } #define FMT " %6" PRIu64 fprintf(stderr, - "MinorGC: %20s %5.1f%% %4d" FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT "\n", + "MinorGC: %20s %5.1f%% %4d" FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT "\n", js::gcstats::ExplainReason(reason), promotionRate * 100, numActiveChunks_, @@ -865,6 +869,7 @@ js::Nursery::collect(JSRuntime *rt, JS::gcreason::Reason reason, TypeObjectList TIME_TOTAL(markDebugger), TIME_TOTAL(clearNewObjectCache), TIME_TOTAL(collectToFP), + TIME_TOTAL(sweepArrayBufferViewList), TIME_TOTAL(updateJitActivations), TIME_TOTAL(resize), TIME_TOTAL(pretenure), diff --git a/js/src/gc/StoreBuffer.cpp b/js/src/gc/StoreBuffer.cpp index 8dcdf081b88..089e5d7a193 100644 --- a/js/src/gc/StoreBuffer.cpp +++ b/js/src/gc/StoreBuffer.cpp @@ -100,7 +100,7 @@ StoreBuffer::MonoTypeBuffer::handleOverflow(StoreBuffer *owner) * compacting unless the buffer is totally full. */ if (storage_->availableInCurrentChunk() < sizeof(T)) - compact(owner); + maybeCompact(owner); } } diff --git a/js/src/jit-test/tests/basic/bug829821.js b/js/src/jit-test/tests/basic/bug829821.js index 3dd737bea8f..9825e6e2b69 100644 --- a/js/src/jit-test/tests/basic/bug829821.js +++ b/js/src/jit-test/tests/basic/bug829821.js @@ -1,4 +1,4 @@ - +// |jit-test| error:TypeError x = []; x.unshift(Uint8ClampedArray); diff --git a/js/src/jit-test/tests/basic/typed-array-index-out-of-range.js b/js/src/jit-test/tests/basic/typed-array-index-out-of-range.js new file mode 100644 index 00000000000..681625be169 --- /dev/null +++ b/js/src/jit-test/tests/basic/typed-array-index-out-of-range.js @@ -0,0 +1,29 @@ + +// Out of bounds writes on typed arrays are uneffectful for all integers. + +var x = new Int32Array(10); + +function f() { + for (var i = -100; i < 100; i++) { + x[i] = i + 1; + if (i >= 0 && i < 10) + assertEq(x[i], i + 1); + else + assertEq(x[i], undefined); + } +} +f(); + +// Integers which don't fit in a double value's mantissa aren't really integers. + +var bigint = "" + Math.pow(2, 53); +x[bigint] = "twelve"; +assertEq(x[bigint], "twelve"); + +// Infinity and -Infinity maybe are supposed to be integers, but they aren't currently. + +x["Infinity"] = "twelve"; +assertEq(x["Infinity"], "twelve"); + +x["-Infinity"] = "twelve"; +assertEq(x["-Infinity"], "twelve"); diff --git a/js/src/jit-test/tests/basic/typed-array-sealed-frozen.js b/js/src/jit-test/tests/basic/typed-array-sealed-frozen.js index bc37144cb5a..d7be854db0d 100644 --- a/js/src/jit-test/tests/basic/typed-array-sealed-frozen.js +++ b/js/src/jit-test/tests/basic/typed-array-sealed-frozen.js @@ -1,8 +1,6 @@ // Any copyright is dedicated to the Public Domain. // http://creativecommons.org/licenses/publicdomain/ -// Typed arrays are always sealed. - load(libdir + "asserts.js") const constructors = [ @@ -20,8 +18,8 @@ const constructors = [ for (constructor of constructors) { print("testing non-empty " + constructor.name); let a = new constructor(10); - assertEq(Object.isExtensible(a), false); - assertEq(Object.isSealed(a), true); + assertEq(Object.isExtensible(a), true); + assertEq(Object.isSealed(a), false); assertEq(Object.isFrozen(a), false); // Should not throw. @@ -36,9 +34,9 @@ print(); for (constructor of constructors) { print("testing zero-length " + constructor.name); let a = new constructor(0); - assertEq(Object.isExtensible(a), false); - assertEq(Object.isSealed(a), true); - assertEq(Object.isFrozen(a), true); + assertEq(Object.isExtensible(a), true); + assertEq(Object.isSealed(a), false); + assertEq(Object.isFrozen(a), false); // Should not throw. Object.seal(a); @@ -51,3 +49,37 @@ for (constructor of constructors) { let a = new Uint8Array(1 << 24); Object.isSealed(a); Object.isFrozen(a); + +for (constructor of constructors) { + print("testing extensibility " + constructor.name); + let a = new constructor(10); + + // New named properties should show up on typed arrays. + a.foo = "twelve"; + assertEq(a.foo, "twelve"); + + // New indexed properties should not show up on typed arrays. + a[20] = "twelve"; + assertEq(a[20], undefined); + + // Watch for especially large indexed properties. + a[-10 >>> 0] = "twelve"; + assertEq(a[-10 >>> 0], undefined); + + // Watch for overly large indexed properties. + a[Math.pow(2, 53)] = "twelve"; + assertEq(a[Math.pow(2, 53)], "twelve"); + + // Don't define old properties. + Object.defineProperty(a, 5, {value: 3}); + assertEq(a[5], 0); + + // Don't define new properties. + Object.defineProperty(a, 20, {value: 3}); + assertEq(a[20], undefined); + + // Don't delete indexed properties. + a[3] = 3; + delete a[3]; + assertEq(a[3], 3); +} diff --git a/js/src/jit-test/tests/collections/Array-of-generic-3.js b/js/src/jit-test/tests/collections/Array-of-generic-3.js index 64b6ca7d90c..7288c85990d 100644 --- a/js/src/jit-test/tests/collections/Array-of-generic-3.js +++ b/js/src/jit-test/tests/collections/Array-of-generic-3.js @@ -1,3 +1,4 @@ +// |jit-test| error:TypeError // Array.of can be transplanted to builtin constructors. load(libdir + "asserts.js"); diff --git a/js/src/jit-test/tests/gc/bug-975959.js b/js/src/jit-test/tests/gc/bug-975959.js index 654eb267bcd..1487c61cc46 100644 --- a/js/src/jit-test/tests/gc/bug-975959.js +++ b/js/src/jit-test/tests/gc/bug-975959.js @@ -1,3 +1,6 @@ +if (!getBuildConfiguration().parallelJS) + quit(0); + try { y = z = []; y[1] = x diff --git a/js/src/jit-test/tests/gc/bug-978353.js b/js/src/jit-test/tests/gc/bug-978353.js new file mode 100644 index 00000000000..44635209feb --- /dev/null +++ b/js/src/jit-test/tests/gc/bug-978353.js @@ -0,0 +1,6 @@ +var arr = new Float64Array(2); +function test(m) { + arr[1] = m; +} +for(var i=0; i<20000; ++i, Array('x')) + test(0); diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp index f60b6f4ba25..06b223bd27a 100644 --- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -3304,11 +3304,6 @@ EffectlesslyLookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName n checkObj = GetDOMProxyProto(obj); if (!checkObj) return true; - } else if (obj->is() && obj->getProto()) { - // Typed array objects are non-native, but don't have any named - // properties. Just forward the lookup to the prototype, to allow - // inlining common getters like byteOffset. - checkObj = obj->getProto(); } else if (!obj->isNative()) { return true; } @@ -3328,7 +3323,7 @@ static bool IsCacheableProtoChain(JSObject *obj, JSObject *holder, bool isDOMProxy=false) { JS_ASSERT_IF(isDOMProxy, IsCacheableDOMProxy(obj)); - JS_ASSERT_IF(!isDOMProxy, obj->isNative() || obj->is()); + JS_ASSERT_IF(!isDOMProxy, obj->isNative()); // Don't handle objects which require a prototype guard. This should // be uncommon so handling it is likely not worth the complexity. @@ -3894,7 +3889,7 @@ TryAttachGetElemStub(JSContext *cx, JSScript *script, jsbytecode *pc, ICGetElem_ if (obj->isNative()) { // Check for NativeObject[int] dense accesses. - if (rhs.isInt32() && rhs.toInt32() >= 0) { + if (rhs.isInt32() && rhs.toInt32() >= 0 && !obj->is()) { IonSpew(IonSpew_BaselineIC, " Generating GetElem(Native[Int32] dense) stub"); ICGetElem_Dense::Compiler compiler(cx, stub->fallbackMonitorStub()->firstMonitorStub(), obj->lastProperty(), isCallElem); @@ -3942,10 +3937,10 @@ TryAttachGetElemStub(JSContext *cx, JSScript *script, jsbytecode *pc, ICGetElem_ return true; } - // GetElem operations on non-native objects other than typed arrays cannot - // be cached by either Baseline or Ion. Indicate this in the cache so that - // Ion does not generate a cache for this op. - if (!obj->isNative() && !obj->is()) + // GetElem operations on non-native objects cannot be cached by either + // Baseline or Ion. Indicate this in the cache so that Ion does not + // generate a cache for this op. + if (!obj->isNative()) stub->noteNonNativeAccess(); // GetElem operations which could access negative indexes generally can't @@ -4990,11 +4985,10 @@ DoSetElemFallback(JSContext *cx, BaselineFrame *frame, ICSetElem_Fallback *stub, // Try to generate new stubs. if (obj->isNative() && + !obj->is() && index.isInt32() && index.toInt32() >= 0 && !rhs.isMagic(JS_ELEMENTS_HOLE)) { - JS_ASSERT(!obj->is()); - bool addingCase; size_t protoDepth; @@ -6093,7 +6087,7 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, return false; } - if (!isDOMProxy && !obj->isNative() && !obj->is()) + if (!isDOMProxy && !obj->isNative()) return true; bool isCallProp = (JSOp(*pc) == JSOP_CALLPROP); diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index a6c62289f6f..c0898ce5227 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -964,6 +964,7 @@ CodeGenerator::visitLambda(LLambda *lir) { Register scopeChain = ToRegister(lir->scopeChain()); Register output = ToRegister(lir->output()); + Register tempReg = ToRegister(lir->temp()); const LambdaFunctionInfo &info = lir->mir()->info(); OutOfLineCode *ool = oolCallVM(LambdaInfo, lir, (ArgList(), ImmGCPtr(info.fun), scopeChain), @@ -973,8 +974,8 @@ CodeGenerator::visitLambda(LLambda *lir) JS_ASSERT(!info.singletonType); - masm.newGCThing(output, info.fun, ool->entry(), gc::DefaultHeap); - masm.initGCThing(output, info.fun); + masm.newGCThing(output, tempReg, info.fun, ool->entry(), gc::DefaultHeap); + masm.initGCThing(output, tempReg, info.fun); emitLambdaInit(output, scopeChain, info); @@ -983,7 +984,7 @@ CodeGenerator::visitLambda(LLambda *lir) } void -CodeGenerator::emitLambdaInit(const Register &output, const Register &scopeChain, +CodeGenerator::emitLambdaInit(Register output, Register scopeChain, const LambdaFunctionInfo &info) { // Initialize nargs and flags. We do this with a single uint32 to avoid @@ -3396,6 +3397,7 @@ CodeGenerator::visitNewArray(LNewArray *lir) { JS_ASSERT(gen->info().executionMode() == SequentialExecution); Register objReg = ToRegister(lir->output()); + Register tempReg = ToRegister(lir->temp()); JSObject *templateObject = lir->mir()->templateObject(); DebugOnly count = lir->mir()->count(); @@ -3408,8 +3410,8 @@ CodeGenerator::visitNewArray(LNewArray *lir) if (!addOutOfLineCode(ool)) return false; - masm.newGCThing(objReg, templateObject, ool->entry(), lir->mir()->initialHeap()); - masm.initGCThing(objReg, templateObject); + masm.newGCThing(objReg, tempReg, templateObject, ool->entry(), lir->mir()->initialHeap()); + masm.initGCThing(objReg, tempReg, templateObject); masm.bind(ool->rejoin()); return true; @@ -3485,6 +3487,7 @@ CodeGenerator::visitNewObject(LNewObject *lir) { JS_ASSERT(gen->info().executionMode() == SequentialExecution); Register objReg = ToRegister(lir->output()); + Register tempReg = ToRegister(lir->temp()); JSObject *templateObject = lir->mir()->templateObject(); if (lir->mir()->shouldUseVM()) @@ -3494,8 +3497,8 @@ CodeGenerator::visitNewObject(LNewObject *lir) if (!addOutOfLineCode(ool)) return false; - masm.newGCThing(objReg, templateObject, ool->entry(), lir->mir()->initialHeap()); - masm.initGCThing(objReg, templateObject); + masm.newGCThing(objReg, tempReg, templateObject, ool->entry(), lir->mir()->initialHeap()); + masm.initGCThing(objReg, tempReg, templateObject); masm.bind(ool->rejoin()); return true; @@ -3517,7 +3520,8 @@ static const VMFunction NewDeclEnvObjectInfo = bool CodeGenerator::visitNewDeclEnvObject(LNewDeclEnvObject *lir) { - Register obj = ToRegister(lir->output()); + Register objReg = ToRegister(lir->output()); + Register tempReg = ToRegister(lir->temp()); JSObject *templateObj = lir->mir()->templateObj(); CompileInfo &info = lir->mir()->block()->info(); @@ -3525,12 +3529,12 @@ CodeGenerator::visitNewDeclEnvObject(LNewDeclEnvObject *lir) OutOfLineCode *ool = oolCallVM(NewDeclEnvObjectInfo, lir, (ArgList(), ImmGCPtr(info.funMaybeLazy()), Imm32(gc::DefaultHeap)), - StoreRegisterTo(obj)); + StoreRegisterTo(objReg)); if (!ool) return false; - masm.newGCThing(obj, templateObj, ool->entry(), gc::DefaultHeap); - masm.initGCThing(obj, templateObj); + masm.newGCThing(objReg, tempReg, templateObj, ool->entry(), gc::DefaultHeap); + masm.initGCThing(objReg, tempReg, templateObj); masm.bind(ool->rejoin()); return true; } @@ -3543,7 +3547,8 @@ static const VMFunction NewCallObjectInfo = bool CodeGenerator::visitNewCallObject(LNewCallObject *lir) { - Register obj = ToRegister(lir->output()); + Register objReg = ToRegister(lir->output()); + Register tempReg = ToRegister(lir->temp()); JSObject *templateObj = lir->mir()->templateObject(); @@ -3555,14 +3560,14 @@ CodeGenerator::visitNewCallObject(LNewCallObject *lir) ImmGCPtr(templateObj->lastProperty()), ImmGCPtr(templateObj->hasSingletonType() ? nullptr : templateObj->type()), ToRegister(lir->slots())), - StoreRegisterTo(obj)); + StoreRegisterTo(objReg)); } else { ool = oolCallVM(NewCallObjectInfo, lir, (ArgList(), ImmGCPtr(lir->mir()->block()->info().script()), ImmGCPtr(templateObj->lastProperty()), ImmGCPtr(templateObj->hasSingletonType() ? nullptr : templateObj->type()), ImmPtr(nullptr)), - StoreRegisterTo(obj)); + StoreRegisterTo(objReg)); } if (!ool) return false; @@ -3571,11 +3576,11 @@ CodeGenerator::visitNewCallObject(LNewCallObject *lir) // Objects can only be given singleton types in VM calls. masm.jump(ool->entry()); } else { - masm.newGCThing(obj, templateObj, ool->entry(), gc::DefaultHeap); - masm.initGCThing(obj, templateObj); + masm.newGCThing(objReg, tempReg, templateObj, ool->entry(), gc::DefaultHeap); + masm.initGCThing(objReg, tempReg, templateObj); if (lir->slots()->isRegister()) - masm.storePtr(ToRegister(lir->slots()), Address(obj, JSObject::offsetOfSlots())); + masm.storePtr(ToRegister(lir->slots()), Address(objReg, JSObject::offsetOfSlots())); } masm.bind(ool->rejoin()); @@ -3661,8 +3666,8 @@ CodeGenerator::visitNewStringObject(LNewStringObject *lir) if (!ool) return false; - masm.newGCThing(output, templateObj, ool->entry(), gc::DefaultHeap); - masm.initGCThing(output, templateObj); + masm.newGCThing(output, temp, templateObj, ool->entry(), gc::DefaultHeap); + masm.initGCThing(output, temp, templateObj); masm.loadStringLength(input, temp); @@ -3704,9 +3709,8 @@ public: }; bool -CodeGenerator::emitAllocateGCThingPar(LInstruction *lir, const Register &objReg, - const Register &cxReg, const Register &tempReg1, - const Register &tempReg2, JSObject *templateObj) +CodeGenerator::emitAllocateGCThingPar(LInstruction *lir, Register objReg, Register cxReg, + Register tempReg1, Register tempReg2, JSObject *templateObj) { gc::AllocKind allocKind = templateObj->tenuredGetAllocKind(); OutOfLineNewGCThingPar *ool = new(alloc()) OutOfLineNewGCThingPar(lir, allocKind, objReg, cxReg); @@ -3715,7 +3719,7 @@ CodeGenerator::emitAllocateGCThingPar(LInstruction *lir, const Register &objReg, masm.newGCThingPar(objReg, cxReg, tempReg1, tempReg2, templateObj, ool->entry()); masm.bind(ool->rejoin()); - masm.initGCThing(objReg, templateObj); + masm.initGCThing(objReg, tempReg1, templateObj); return true; } @@ -3899,6 +3903,7 @@ CodeGenerator::visitCreateThisWithTemplate(LCreateThisWithTemplate *lir) gc::AllocKind allocKind = templateObject->tenuredGetAllocKind(); gc::InitialHeap initialHeap = lir->mir()->initialHeap(); Register objReg = ToRegister(lir->output()); + Register tempReg = ToRegister(lir->temp()); OutOfLineCode *ool = oolCallVM(NewGCObjectInfo, lir, (ArgList(), Imm32(allocKind), Imm32(initialHeap)), @@ -3907,11 +3912,11 @@ CodeGenerator::visitCreateThisWithTemplate(LCreateThisWithTemplate *lir) return false; // Allocate. If the FreeList is empty, call to VM, which may GC. - masm.newGCThing(objReg, templateObject, ool->entry(), lir->mir()->initialHeap()); + masm.newGCThing(objReg, tempReg, templateObject, ool->entry(), lir->mir()->initialHeap()); // Initialize based on the templateObject. masm.bind(ool->rejoin()); - masm.initGCThing(objReg, templateObject); + masm.initGCThing(objReg, tempReg, templateObject); return true; } @@ -4865,7 +4870,7 @@ JitCompartment::generateStringConcatStub(JSContext *cx, ExecutionMode mode) // Allocate a new rope. switch (mode) { case SequentialExecution: - masm.newGCString(output, &failure); + masm.newGCString(output, temp3, &failure); break; case ParallelExecution: masm.push(temp1); @@ -4910,7 +4915,7 @@ JitCompartment::generateStringConcatStub(JSContext *cx, ExecutionMode mode) // Allocate a JSShortString. switch (mode) { case SequentialExecution: - masm.newGCShortString(output, &failure); + masm.newGCShortString(output, temp3, &failure); break; case ParallelExecution: masm.push(temp1); @@ -5630,8 +5635,8 @@ CodeGenerator::visitArrayConcat(LArrayConcat *lir) // Try to allocate an object. JSObject *templateObj = lir->mir()->templateObj(); - masm.newGCThing(temp1, templateObj, &fail, lir->mir()->initialHeap()); - masm.initGCThing(temp1, templateObj); + masm.newGCThing(temp1, temp2, templateObj, &fail, lir->mir()->initialHeap()); + masm.initGCThing(temp1, temp2, templateObj); masm.jump(&call); { masm.bind(&fail); @@ -6002,8 +6007,8 @@ CodeGenerator::visitRest(LRest *lir) JSObject *templateObject = lir->mir()->templateObject(); Label joinAlloc, failAlloc; - masm.newGCThing(temp2, templateObject, &failAlloc, gc::DefaultHeap); - masm.initGCThing(temp2, templateObject); + masm.newGCThing(temp2, temp0, templateObject, &failAlloc, gc::DefaultHeap); + masm.initGCThing(temp2, temp0, templateObject); masm.jump(&joinAlloc); { masm.bind(&failAlloc); diff --git a/js/src/jit/CodeGenerator.h b/js/src/jit/CodeGenerator.h index bceff37aefe..007500b8479 100644 --- a/js/src/jit/CodeGenerator.h +++ b/js/src/jit/CodeGenerator.h @@ -366,13 +366,13 @@ class CodeGenerator : public CodeGeneratorSpecific bool generateBranchV(const ValueOperand &value, Label *ifTrue, Label *ifFalse, FloatRegister fr); - bool emitAllocateGCThingPar(LInstruction *lir, const Register &objReg, const Register &cxReg, - const Register &tempReg1, const Register &tempReg2, + bool emitAllocateGCThingPar(LInstruction *lir, Register objReg, Register cxReg, + Register tempReg1, Register tempReg2, JSObject *templateObj); bool emitCallToUncompiledScriptPar(LInstruction *lir, Register calleeReg); - void emitLambdaInit(const Register &resultReg, const Register &scopeChainReg, + void emitLambdaInit(Register resultReg, Register scopeChainReg, const LambdaFunctionInfo &info); bool emitFilterArgumentsOrEval(LInstruction *lir, Register string, Register temp1, diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index 2759e95f90f..73921f18557 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -5922,12 +5922,6 @@ IonBuilder::maybeInsertResume() static bool ClassHasEffectlessLookup(const Class *clasp, PropertyName *name) { - if (IsTypedArrayClass(clasp)) { - // Typed arrays have a lookupGeneric hook, but it only handles - // integers, not names. - JS_ASSERT(name); - return true; - } return clasp->isNative() && !clasp->ops.lookupGeneric; } @@ -7181,14 +7175,17 @@ IonBuilder::getTypedArrayElements(MDefinition *obj) if (obj->isConstant() && obj->toConstant()->value().isObject()) { TypedArrayObject *tarr = &obj->toConstant()->value().toObject().as(); void *data = tarr->viewData(); + // Bug 979449 - Optimistically embed the elements and use TI to + // invalidate if we move them. + if (!gc::IsInsideNursery(tarr->runtimeFromMainThread(), data)) { + // The 'data' pointer can change in rare circumstances + // (ArrayBufferObject::changeContents). + types::TypeObjectKey *tarrType = types::TypeObjectKey::get(tarr); + tarrType->watchStateChangeForTypedArrayBuffer(constraints()); - // The 'data' pointer can change in rare circumstances - // (ArrayBufferObject::changeContents). - types::TypeObjectKey *tarrType = types::TypeObjectKey::get(tarr); - tarrType->watchStateChangeForTypedArrayBuffer(constraints()); - - obj->setImplicitlyUsedUnchecked(); - return MConstantElements::New(alloc(), data); + obj->setImplicitlyUsedUnchecked(); + return MConstantElements::New(alloc(), data); + } } return MTypedArrayElements::New(alloc(), obj); } @@ -7931,7 +7928,7 @@ IonBuilder::jsop_rest() // Unroll the argument copy loop. We don't need to do any bounds or hole // checking here. - MConstant *index; + MConstant *index = nullptr; for (unsigned i = numFormals; i < numActuals; i++) { index = MConstant::New(alloc(), Int32Value(i - numFormals)); current->add(index); diff --git a/js/src/jit/IonBuilder.h b/js/src/jit/IonBuilder.h index d6643a84fe0..2e8f030c3db 100644 --- a/js/src/jit/IonBuilder.h +++ b/js/src/jit/IonBuilder.h @@ -156,7 +156,7 @@ class IonBuilder : public MIRGenerator // MIR instruction MTableSwitch *ins; - // The number of current successor that get mapped into a block. + // The number of current successor that get mapped into a block. uint32_t currentBlock; } tableswitch; @@ -649,6 +649,10 @@ class IonBuilder : public MIRGenerator InliningStatus inlineMathFRound(CallInfo &callInfo); InliningStatus inlineMathFunction(CallInfo &callInfo, MMathFunction::Function function); + // SIMD natives. + InliningStatus checkSIMDArgs(CallInfo &callInfo, const MIRType *argumentTypes); + InliningStatus inlineSIMDFunction(CallInfo &callInfo, uint32_t id, uint32_t argumentCount); + // String natives. InliningStatus inlineStringObject(CallInfo &callInfo); InliningStatus inlineStringSplit(CallInfo &callInfo); diff --git a/js/src/jit/IonFrameIterator.h b/js/src/jit/IonFrameIterator.h index 653a70c1f58..d2cd699a7b7 100644 --- a/js/src/jit/IonFrameIterator.h +++ b/js/src/jit/IonFrameIterator.h @@ -217,7 +217,7 @@ class IonFrameIterator MachineState machineState() const; template - void forEachCanonicalActualArg(Op op, ReadFrameArgsBehavior behavior) const { + void unaliasedForEachActual(Op op, ReadFrameArgsBehavior behavior) const { JS_ASSERT(isBaselineJS()); unsigned nactual = numActualArgs(); @@ -476,7 +476,7 @@ class InlineFrameIteratorMaybeGC } template - void forEachCanonicalActualArg(JSContext *cx, Op op, ReadFrameArgsBehavior behavior) const { + void unaliasedForEachActual(JSContext *cx, Op op, ReadFrameArgsBehavior behavior) const { Nop nop; readFrameArgsAndLocals(cx, op, nop, nullptr, nullptr, behavior); } diff --git a/js/src/jit/IonFrames.cpp b/js/src/jit/IonFrames.cpp index 1fce1635c04..f0d14948eb9 100644 --- a/js/src/jit/IonFrames.cpp +++ b/js/src/jit/IonFrames.cpp @@ -1829,7 +1829,7 @@ InlineFrameIteratorMaybeGC::dump() const else { if (i - 2 == callee()->nargs() && numActualArgs() > callee()->nargs()) { DumpOp d(callee()->nargs()); - forEachCanonicalActualArg(GetJSContextFromJitCode(), d, ReadFrame_Overflown); + unaliasedForEachActual(GetJSContextFromJitCode(), d, ReadFrame_Overflown); } fprintf(stderr, " slot %d: ", int(i - 2 - callee()->nargs())); diff --git a/js/src/jit/IonMacroAssembler.cpp b/js/src/jit/IonMacroAssembler.cpp index 269ec33d31b..3b3723d4abb 100644 --- a/js/src/jit/IonMacroAssembler.cpp +++ b/js/src/jit/IonMacroAssembler.cpp @@ -361,7 +361,7 @@ MacroAssembler::branchNurseryPtr(Condition cond, const Address &ptr1, const ImmM } void -MacroAssembler::moveNurseryPtr(const ImmMaybeNurseryPtr &ptr, const Register ®) +MacroAssembler::moveNurseryPtr(const ImmMaybeNurseryPtr &ptr, Register reg) { #ifdef JSGC_GENERATIONAL if (ptr.value && gc::IsInsideNursery(GetIonContext()->cx->runtime(), (void *)ptr.value)) @@ -634,7 +634,7 @@ MacroAssembler::clampDoubleToUint8(FloatRegister input, Register output) } void -MacroAssembler::newGCThing(const Register &result, gc::AllocKind allocKind, Label *fail, +MacroAssembler::newGCThing(Register result, Register temp, gc::AllocKind allocKind, Label *fail, gc::InitialHeap initialHeap /* = gc::DefaultHeap */) { // Inlined equivalent of js::gc::NewGCThing() without failure case handling. @@ -662,10 +662,9 @@ MacroAssembler::newGCThing(const Register &result, gc::AllocKind allocKind, Labe // in such cases. const Nursery &nursery = GetIonContext()->runtime->gcNursery(); loadPtr(AbsoluteAddress(nursery.addressOfPosition()), result); - addPtr(Imm32(thingSize), result); - branchPtr(Assembler::BelowOrEqual, AbsoluteAddress(nursery.addressOfCurrentEnd()), result, fail); - storePtr(result, AbsoluteAddress(nursery.addressOfPosition())); - subPtr(Imm32(thingSize), result); + computeEffectiveAddress(Address(result, thingSize), temp); + branchPtr(Assembler::BelowOrEqual, AbsoluteAddress(nursery.addressOfCurrentEnd()), temp, fail); + storePtr(temp, AbsoluteAddress(nursery.addressOfPosition())); return; } #endif // JSGC_GENERATIONAL @@ -678,37 +677,34 @@ MacroAssembler::newGCThing(const Register &result, gc::AllocKind allocKind, Labe // which the code below always re-reads. loadPtr(AbsoluteAddress(zone->addressOfFreeListFirst(allocKind)), result); branchPtr(Assembler::BelowOrEqual, AbsoluteAddress(zone->addressOfFreeListLast(allocKind)), result, fail); - - addPtr(Imm32(thingSize), result); - storePtr(result, AbsoluteAddress(zone->addressOfFreeListFirst(allocKind))); - subPtr(Imm32(thingSize), result); + computeEffectiveAddress(Address(result, thingSize), temp); + storePtr(temp, AbsoluteAddress(zone->addressOfFreeListFirst(allocKind))); } void -MacroAssembler::newGCThing(const Register &result, JSObject *templateObject, - Label *fail, gc::InitialHeap initialHeap) +MacroAssembler::newGCThing(Register result, Register temp, JSObject *templateObject, Label *fail, + gc::InitialHeap initialHeap) { gc::AllocKind allocKind = templateObject->tenuredGetAllocKind(); JS_ASSERT(allocKind >= gc::FINALIZE_OBJECT0 && allocKind <= gc::FINALIZE_OBJECT_LAST); - newGCThing(result, allocKind, fail, initialHeap); + newGCThing(result, temp, allocKind, fail, initialHeap); } void -MacroAssembler::newGCString(const Register &result, Label *fail) +MacroAssembler::newGCString(Register result, Register temp, Label *fail) { - newGCThing(result, js::gc::FINALIZE_STRING, fail); + newGCThing(result, temp, js::gc::FINALIZE_STRING, fail); } void -MacroAssembler::newGCShortString(const Register &result, Label *fail) +MacroAssembler::newGCShortString(Register result, Register temp, Label *fail) { - newGCThing(result, js::gc::FINALIZE_SHORT_STRING, fail); + newGCThing(result, temp, js::gc::FINALIZE_SHORT_STRING, fail); } void -MacroAssembler::newGCThingPar(const Register &result, const Register &cx, - const Register &tempReg1, const Register &tempReg2, +MacroAssembler::newGCThingPar(Register result, Register cx, Register tempReg1, Register tempReg2, gc::AllocKind allocKind, Label *fail) { // Similar to ::newGCThing(), except that it allocates from a custom @@ -755,8 +751,7 @@ MacroAssembler::newGCThingPar(const Register &result, const Register &cx, } void -MacroAssembler::newGCThingPar(const Register &result, const Register &cx, - const Register &tempReg1, const Register &tempReg2, +MacroAssembler::newGCThingPar(Register result, Register cx, Register tempReg1, Register tempReg2, JSObject *templateObject, Label *fail) { gc::AllocKind allocKind = templateObject->tenuredGetAllocKind(); @@ -766,69 +761,127 @@ MacroAssembler::newGCThingPar(const Register &result, const Register &cx, } void -MacroAssembler::newGCStringPar(const Register &result, const Register &cx, - const Register &tempReg1, const Register &tempReg2, +MacroAssembler::newGCStringPar(Register result, Register cx, Register tempReg1, Register tempReg2, Label *fail) { newGCThingPar(result, cx, tempReg1, tempReg2, js::gc::FINALIZE_STRING, fail); } void -MacroAssembler::newGCShortStringPar(const Register &result, const Register &cx, - const Register &tempReg1, const Register &tempReg2, - Label *fail) +MacroAssembler::newGCShortStringPar(Register result, Register cx, Register tempReg1, + Register tempReg2, Label *fail) { newGCThingPar(result, cx, tempReg1, tempReg2, js::gc::FINALIZE_SHORT_STRING, fail); } void -MacroAssembler::initGCThing(const Register &obj, JSObject *templateObject) +MacroAssembler::copySlotsFromTemplate(Register obj, Register temp, const JSObject *templateObj, + uint32_t start, uint32_t end) +{ + uint32_t nfixed = Min(templateObj->numFixedSlots(), end); + for (unsigned i = start; i < nfixed; i++) + storeValue(templateObj->getFixedSlot(i), Address(obj, JSObject::getFixedSlotOffset(i))); +} + +void +MacroAssembler::fillSlotsWithUndefined(Register obj, Register temp, const JSObject *templateObj, + uint32_t start, uint32_t end) +{ +#ifdef JS_NUNBOX32 + // We only have a single spare register, so do the initialization as two + // strided writes of the tag and body. + jsval_layout jv = JSVAL_TO_IMPL(UndefinedValue()); + uint32_t nfixed = Min(templateObj->numFixedSlots(), end); + + mov(ImmWord(jv.s.tag), temp); + for (unsigned i = start; i < nfixed; i++) + store32(temp, ToType(Address(obj, JSObject::getFixedSlotOffset(i)))); + + mov(ImmWord(jv.s.payload.i32), temp); + for (unsigned i = start; i < nfixed; i++) + store32(temp, ToPayload(Address(obj, JSObject::getFixedSlotOffset(i)))); +#else + moveValue(UndefinedValue(), temp); + uint32_t nfixed = Min(templateObj->numFixedSlots(), end); + for (unsigned i = start; i < nfixed; i++) + storePtr(temp, Address(obj, JSObject::getFixedSlotOffset(i))); +#endif +} + +static uint32_t +FindStartOfUndefinedSlots(JSObject *templateObj, uint32_t nslots) +{ + JS_ASSERT(nslots == templateObj->lastProperty()->slotSpan(templateObj->getClass())); + JS_ASSERT(nslots > 0); + for (uint32_t first = nslots; first != 0; --first) { + if (templateObj->getSlot(first - 1) != UndefinedValue()) + return first; + } + return 0; +} + +void +MacroAssembler::initGCSlots(Register obj, Register temp, JSObject *templateObj) +{ + // Slots of non-array objects are required to be initialized. + // Use the values currently in the template object. + uint32_t nslots = templateObj->lastProperty()->slotSpan(templateObj->getClass()); + if (nslots == 0) + return; + + // Attempt to group slot writes such that we minimize the amount of + // duplicated data we need to embed in code and load into registers. In + // general, most template object slots will be undefined except for any + // reserved slots. Since reserved slots come first, we split the object + // logically into independent non-UndefinedValue writes to the head and + // duplicated writes of UndefinedValue to the tail. For the majority of + // objects, the "tail" will be the entire slot range. + uint32_t startOfUndefined = FindStartOfUndefinedSlots(templateObj, nslots); + copySlotsFromTemplate(obj, temp, templateObj, 0, startOfUndefined); + fillSlotsWithUndefined(obj, temp, templateObj, startOfUndefined, nslots); +} + +void +MacroAssembler::initGCThing(Register obj, Register temp, JSObject *templateObj) { // Fast initialization of an empty object returned by NewGCThing(). - JS_ASSERT(!templateObject->hasDynamicElements()); + JS_ASSERT(!templateObj->hasDynamicElements()); - storePtr(ImmGCPtr(templateObject->lastProperty()), Address(obj, JSObject::offsetOfShape())); - storePtr(ImmGCPtr(templateObject->type()), Address(obj, JSObject::offsetOfType())); + storePtr(ImmGCPtr(templateObj->lastProperty()), Address(obj, JSObject::offsetOfShape())); + storePtr(ImmGCPtr(templateObj->type()), Address(obj, JSObject::offsetOfType())); storePtr(ImmPtr(nullptr), Address(obj, JSObject::offsetOfSlots())); - if (templateObject->is()) { - JS_ASSERT(!templateObject->getDenseInitializedLength()); + if (templateObj->is()) { + JS_ASSERT(!templateObj->getDenseInitializedLength()); int elementsOffset = JSObject::offsetOfFixedElements(); - addPtr(Imm32(elementsOffset), obj); - storePtr(obj, Address(obj, -elementsOffset + JSObject::offsetOfElements())); - addPtr(Imm32(-elementsOffset), obj); + computeEffectiveAddress(Address(obj, elementsOffset), temp); + storePtr(temp, Address(obj, JSObject::offsetOfElements())); // Fill in the elements header. - store32(Imm32(templateObject->getDenseCapacity()), + store32(Imm32(templateObj->getDenseCapacity()), Address(obj, elementsOffset + ObjectElements::offsetOfCapacity())); - store32(Imm32(templateObject->getDenseInitializedLength()), + store32(Imm32(templateObj->getDenseInitializedLength()), Address(obj, elementsOffset + ObjectElements::offsetOfInitializedLength())); - store32(Imm32(templateObject->as().length()), + store32(Imm32(templateObj->as().length()), Address(obj, elementsOffset + ObjectElements::offsetOfLength())); - store32(Imm32(templateObject->shouldConvertDoubleElements() + store32(Imm32(templateObj->shouldConvertDoubleElements() ? ObjectElements::CONVERT_DOUBLE_ELEMENTS : 0), Address(obj, elementsOffset + ObjectElements::offsetOfFlags())); + JS_ASSERT(!templateObj->hasPrivate()); } else { storePtr(ImmPtr(emptyObjectElements), Address(obj, JSObject::offsetOfElements())); - // Fixed slots of non-array objects are required to be initialized. - // Use the values currently in the template object. - size_t nslots = Min(templateObject->numFixedSlots(), - templateObject->lastProperty()->slotSpan(templateObject->getClass())); - for (unsigned i = 0; i < nslots; i++) { - storeValue(templateObject->getFixedSlot(i), - Address(obj, JSObject::getFixedSlotOffset(i))); - } - } + initGCSlots(obj, temp, templateObj); - if (templateObject->hasPrivate()) { - uint32_t nfixed = templateObject->numFixedSlots(); - storePtr(ImmPtr(templateObject->getPrivate()), - Address(obj, JSObject::getPrivateDataOffset(nfixed))); + if (templateObj->hasPrivate()) { + uint32_t nfixed = templateObj->numFixedSlots(); + storePtr(ImmPtr(templateObj->getPrivate()), + Address(obj, JSObject::getPrivateDataOffset(nfixed))); + } } } @@ -870,7 +923,7 @@ MacroAssembler::compareStrings(JSOp op, Register left, Register right, Register } void -MacroAssembler::checkInterruptFlagPar(const Register &tempReg, Label *fail) +MacroAssembler::checkInterruptFlagPar(Register tempReg, Label *fail) { #ifdef JS_THREADSAFE movePtr(ImmPtr(GetIonContext()->runtime->addressOfInterruptPar()), tempReg); @@ -1819,7 +1872,7 @@ MacroAssembler::branchIfNotInterpretedConstructor(Register fun, Register scratch } void -MacroAssembler::branchEqualTypeIfNeeded(MIRType type, MDefinition *maybeDef, const Register &tag, +MacroAssembler::branchEqualTypeIfNeeded(MIRType type, MDefinition *maybeDef, Register tag, Label *label) { if (!maybeDef || maybeDef->mightBeType(type)) { diff --git a/js/src/jit/IonMacroAssembler.h b/js/src/jit/IonMacroAssembler.h index 230428fc0d0..7e889d447db 100644 --- a/js/src/jit/IonMacroAssembler.h +++ b/js/src/jit/IonMacroAssembler.h @@ -352,13 +352,13 @@ class MacroAssembler : public MacroAssemblerSpecific } // Branches to |label| if |reg| is false. |reg| should be a C++ bool. - void branchIfFalseBool(const Register ®, Label *label) { + void branchIfFalseBool(Register reg, Label *label) { // Note that C++ bool is only 1 byte, so ignore the higher-order bits. branchTest32(Assembler::Zero, reg, Imm32(0xFF), label); } // Branches to |label| if |reg| is true. |reg| should be a C++ bool. - void branchIfTrueBool(const Register ®, Label *label) { + void branchIfTrueBool(Register reg, Label *label) { // Note that C++ bool is only 1 byte, so ignore the higher-order bits. branchTest32(Assembler::NonZero, reg, Imm32(0xFF), label); } @@ -381,10 +381,10 @@ class MacroAssembler : public MacroAssemblerSpecific loadPtr(Address(worker, ThreadPoolWorker::offsetOfSliceBounds()), dest); } - void loadJSContext(const Register &dest) { + void loadJSContext(Register dest) { loadPtr(AbsoluteAddress(GetIonContext()->runtime->addressOfJSContext()), dest); } - void loadJitActivation(const Register &dest) { + void loadJitActivation(Register dest) { loadPtr(AbsoluteAddress(GetIonContext()->runtime->addressOfActivation()), dest); } @@ -634,7 +634,7 @@ class MacroAssembler : public MacroAssemblerSpecific branch32(cond, length, Imm32(key.constant()), label); } - void branchTestNeedsBarrier(Condition cond, const Register &scratch, Label *label) { + void branchTestNeedsBarrier(Condition cond, Register scratch, Label *label) { JS_ASSERT(cond == Zero || cond == NonZero); CompileZone *zone = GetIonContext()->compartment->zone(); movePtr(ImmPtr(zone->addressOfNeedsBarrier()), scratch); @@ -690,7 +690,7 @@ class MacroAssembler : public MacroAssemblerSpecific void branchNurseryPtr(Condition cond, const Address &ptr1, const ImmMaybeNurseryPtr &ptr2, Label *label); - void moveNurseryPtr(const ImmMaybeNurseryPtr &ptr, const Register ®); + void moveNurseryPtr(const ImmMaybeNurseryPtr &ptr, Register reg); void canonicalizeDouble(FloatRegister reg) { Label notNaN; @@ -783,30 +783,31 @@ class MacroAssembler : public MacroAssemblerSpecific // Emit type case branch on tag matching if the type tag in the definition // might actually be that type. - void branchEqualTypeIfNeeded(MIRType type, MDefinition *maybeDef, const Register &tag, - Label *label); + void branchEqualTypeIfNeeded(MIRType type, MDefinition *maybeDef, Register tag, Label *label); // Inline allocation. - void newGCThing(const Register &result, gc::AllocKind allocKind, Label *fail, + void newGCThing(Register result, Register temp, gc::AllocKind allocKind, Label *fail, gc::InitialHeap initialHeap = gc::DefaultHeap); - void newGCThing(const Register &result, JSObject *templateObject, Label *fail, + void newGCThing(Register result, Register temp, JSObject *templateObject, Label *fail, gc::InitialHeap initialHeap); - void newGCString(const Register &result, Label *fail); - void newGCShortString(const Register &result, Label *fail); + void newGCString(Register result, Register temp, Label *fail); + void newGCShortString(Register result, Register temp, Label *fail); - void newGCThingPar(const Register &result, const Register &cx, - const Register &tempReg1, const Register &tempReg2, + void newGCThingPar(Register result, Register cx, Register tempReg1, Register tempReg2, gc::AllocKind allocKind, Label *fail); - void newGCThingPar(const Register &result, const Register &cx, - const Register &tempReg1, const Register &tempReg2, + void newGCThingPar(Register result, Register cx, Register tempReg1, Register tempReg2, JSObject *templateObject, Label *fail); - void newGCStringPar(const Register &result, const Register &cx, - const Register &tempReg1, const Register &tempReg2, + void newGCStringPar(Register result, Register cx, Register tempReg1, Register tempReg2, Label *fail); - void newGCShortStringPar(const Register &result, const Register &cx, - const Register &tempReg1, const Register &tempReg2, + void newGCShortStringPar(Register result, Register cx, Register tempReg1, Register tempReg2, Label *fail); - void initGCThing(const Register &obj, JSObject *templateObject); + + void copySlotsFromTemplate(Register obj, Register temp, const JSObject *templateObj, + uint32_t start, uint32_t end); + void fillSlotsWithUndefined(Register obj, Register temp, const JSObject *templateObj, + uint32_t start, uint32_t end); + void initGCSlots(Register obj, Register temp, JSObject *templateObj); + void initGCThing(Register obj, Register temp, JSObject *templateObj); // Compares two strings for equality based on the JSOP. // This checks for identical pointers, atoms and length and fails for everything else. @@ -815,7 +816,7 @@ class MacroAssembler : public MacroAssemblerSpecific // Checks the flags that signal that parallel code may need to interrupt or // abort. Branches to fail in that case. - void checkInterruptFlagPar(const Register &tempReg, Label *fail); + void checkInterruptFlagPar(Register tempReg, Label *fail); // If the JitCode that created this assembler needs to transition into the VM, // we want to store the JitCode on the stack in order to mark it during a GC. @@ -903,7 +904,7 @@ class MacroAssembler : public MacroAssemblerSpecific } // see above comment for what is returned - uint32_t callIon(const Register &callee) { + uint32_t callIon(Register callee) { leaveSPSFrame(); MacroAssemblerSpecific::callIon(callee); uint32_t ret = currentOffset(); diff --git a/js/src/jit/IonTypes.h b/js/src/jit/IonTypes.h index 0a7d9276ef7..b54450e147b 100644 --- a/js/src/jit/IonTypes.h +++ b/js/src/jit/IonTypes.h @@ -164,6 +164,9 @@ ValueTypeFromMIRType(MIRType type) return JSVAL_TYPE_STRING; case MIRType_Magic: return JSVAL_TYPE_MAGIC; + case MIRType_Float32x4: + case MIRType_Int32x4: + return JSVAL_TYPE_OBJECT; default: JS_ASSERT(type == MIRType_Object); return JSVAL_TYPE_OBJECT; @@ -194,6 +197,10 @@ StringFromMIRType(MIRType type) return "Float32"; case MIRType_String: return "String"; + case MIRType_Float32x4: + return "Float32x4"; + case MIRType_Int32x4: + return "Int32x4"; case MIRType_Object: return "Object"; case MIRType_Magic: diff --git a/js/src/jit/LIR-Common.h b/js/src/jit/LIR-Common.h index 44a1ad7ade6..1b8d8a6590f 100644 --- a/js/src/jit/LIR-Common.h +++ b/js/src/jit/LIR-Common.h @@ -328,29 +328,45 @@ class LNewSlots : public LCallInstructionHelper<1, 0, 3> } }; -class LNewArray : public LInstructionHelper<1, 0, 0> +class LNewArray : public LInstructionHelper<1, 0, 1> { public: LIR_HEADER(NewArray) + LNewArray(const LDefinition &temp) { + setTemp(0, temp); + } + const char *extraName() const { return mir()->shouldUseVM() ? "VMCall" : nullptr; } + const LDefinition *temp() { + return getTemp(0); + } + MNewArray *mir() const { return mir_->toNewArray(); } }; -class LNewObject : public LInstructionHelper<1, 0, 0> +class LNewObject : public LInstructionHelper<1, 0, 1> { public: LIR_HEADER(NewObject) + LNewObject(const LDefinition &temp) { + setTemp(0, temp); + } + const char *extraName() const { return mir()->shouldUseVM() ? "VMCall" : nullptr; } + const LDefinition *temp() { + return getTemp(0); + } + MNewObject *mir() const { return mir_->toNewObject(); } @@ -430,11 +446,19 @@ class LNewDenseArrayPar : public LCallInstructionHelper<1, 2, 3> // (1) An inline allocation of the call object is attempted. // (2) Otherwise, a callVM create a new object. // -class LNewDeclEnvObject : public LInstructionHelper<1, 0, 0> +class LNewDeclEnvObject : public LInstructionHelper<1, 0, 1> { public: LIR_HEADER(NewDeclEnvObject); + LNewDeclEnvObject(const LDefinition &temp) { + setTemp(0, temp); + } + + const LDefinition *temp() { + return getTemp(0); + } + MNewDeclEnvObject *mir() const { return mir_->toNewDeclEnvObject(); } @@ -449,13 +473,18 @@ class LNewDeclEnvObject : public LInstructionHelper<1, 0, 0> // call object. // (2) Otherwise, an inline allocation of the call object is attempted. // -class LNewCallObject : public LInstructionHelper<1, 1, 0> +class LNewCallObject : public LInstructionHelper<1, 1, 1> { public: LIR_HEADER(NewCallObject) - LNewCallObject(const LAllocation &slots) { + LNewCallObject(const LAllocation &slots, const LDefinition &temp) { setOperand(0, slots); + setTemp(0, temp); + } + + const LDefinition *temp() { + return getTemp(0); } const LAllocation *slots() { @@ -883,17 +912,22 @@ class LCreateThisWithProto : public LCallInstructionHelper<1, 2, 0> // Allocate an object for |new| on the caller-side. // Always performs object initialization with a fast path. -class LCreateThisWithTemplate : public LInstructionHelper<1, 0, 0> +class LCreateThisWithTemplate : public LInstructionHelper<1, 0, 1> { public: LIR_HEADER(CreateThisWithTemplate) - LCreateThisWithTemplate() - { } + LCreateThisWithTemplate(const LDefinition &temp) { + setTemp(0, temp); + } MCreateThisWithTemplate *mir() const { return mir_->toCreateThisWithTemplate(); } + + const LDefinition *temp() { + return getTemp(0); + } }; // Allocate a new arguments object for the frame. @@ -3396,17 +3430,21 @@ class LLambdaForSingleton : public LCallInstructionHelper<1, 1, 0> } }; -class LLambda : public LInstructionHelper<1, 1, 0> +class LLambda : public LInstructionHelper<1, 1, 1> { public: LIR_HEADER(Lambda) - LLambda(const LAllocation &scopeChain) { + LLambda(const LAllocation &scopeChain, const LDefinition &temp) { setOperand(0, scopeChain); + setTemp(0, temp); } const LAllocation *scopeChain() { return getOperand(0); } + const LDefinition *temp() { + return getTemp(0); + } const MLambda *mir() const { return mir_->toLambda(); } diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp index f6e5ba026f2..bff96c4ddec 100644 --- a/js/src/jit/Lowering.cpp +++ b/js/src/jit/Lowering.cpp @@ -174,21 +174,21 @@ LIRGenerator::visitNewSlots(MNewSlots *ins) bool LIRGenerator::visitNewArray(MNewArray *ins) { - LNewArray *lir = new(alloc()) LNewArray(); + LNewArray *lir = new(alloc()) LNewArray(temp()); return define(lir, ins) && assignSafepoint(lir, ins); } bool LIRGenerator::visitNewObject(MNewObject *ins) { - LNewObject *lir = new(alloc()) LNewObject(); + LNewObject *lir = new(alloc()) LNewObject(temp()); return define(lir, ins) && assignSafepoint(lir, ins); } bool LIRGenerator::visitNewDeclEnvObject(MNewDeclEnvObject *ins) { - LNewDeclEnvObject *lir = new(alloc()) LNewDeclEnvObject(); + LNewDeclEnvObject *lir = new(alloc()) LNewDeclEnvObject(temp()); return define(lir, ins) && assignSafepoint(lir, ins); } @@ -201,7 +201,7 @@ LIRGenerator::visitNewCallObject(MNewCallObject *ins) else slots = LConstantIndex::Bogus(); - LNewCallObject *lir = new(alloc()) LNewCallObject(slots); + LNewCallObject *lir = new(alloc()) LNewCallObject(slots, temp()); if (!define(lir, ins)) return false; @@ -311,7 +311,7 @@ LIRGenerator::visitInitPropGetterSetter(MInitPropGetterSetter *ins) bool LIRGenerator::visitCreateThisWithTemplate(MCreateThisWithTemplate *ins) { - LCreateThisWithTemplate *lir = new(alloc()) LCreateThisWithTemplate(); + LCreateThisWithTemplate *lir = new(alloc()) LCreateThisWithTemplate(temp()); return define(lir, ins) && assignSafepoint(lir, ins); } @@ -2026,7 +2026,7 @@ LIRGenerator::visitLambda(MLambda *ins) return defineReturn(lir, ins) && assignSafepoint(lir, ins); } - LLambda *lir = new(alloc()) LLambda(useRegister(ins->scopeChain())); + LLambda *lir = new(alloc()) LLambda(useRegister(ins->scopeChain()), temp()); return define(lir, ins) && assignSafepoint(lir, ins); } diff --git a/js/src/jit/MCallOptimize.cpp b/js/src/jit/MCallOptimize.cpp index f6f1c809021..1f73973bcae 100644 --- a/js/src/jit/MCallOptimize.cpp +++ b/js/src/jit/MCallOptimize.cpp @@ -6,6 +6,7 @@ #include "jsmath.h" +#include "builtin/SIMD.h" #include "builtin/TestingFunctions.h" #include "jit/BaselineInspector.h" #include "jit/IonBuilder.h" @@ -108,6 +109,57 @@ IonBuilder::inlineNativeCall(CallInfo &callInfo, JSNative native) if (native == js::math_cbrt) return inlineMathFunction(callInfo, MMathFunction::Cbrt); + // SIMD natives. +#define INLINE_FLOAT32X4_NULLARY_FUNCTION(Name, Func, Operands, Flags, MIRId) \ + if (native == js::simd_float32x4_##Name) \ + return inlineSIMDFunction(callInfo, MSIMDNullaryFunction::Float32x4##MIRId, 0); +FLOAT32X4_NULLARY_FUNCTION_LIST(INLINE_FLOAT32X4_NULLARY_FUNCTION) +#undef INLINE_FLOAT32X4_NULLARY_FUNCTION +#define INLINE_INT32X4_NULLARY_FUNCTION(Name, Func, Operands, Flags, MIRId) \ + if (native == js::simd_int32x4_##Name) \ + return inlineSIMDFunction(callInfo, MSIMDNullaryFunction::Int32x4##MIRId, 0); +INT32X4_NULLARY_FUNCTION_LIST(INLINE_INT32X4_NULLARY_FUNCTION) +#undef INLINE_INT32X4_NULLARY_FUNCTION + +#define INLINE_FLOAT32X4_UNARY_FUNCTION(Name, Func, Operands, Flags, MIRId) \ + if (native == js::simd_float32x4_##Name) \ + return inlineSIMDFunction(callInfo, MSIMDUnaryFunction::Float32x4##MIRId, 1); +FLOAT32X4_UNARY_FUNCTION_LIST(INLINE_FLOAT32X4_UNARY_FUNCTION) +#undef INLINE_FLOAT32X4_UNARY_FUNCTION +#define INLINE_INT32X4_UNARY_FUNCTION(Name, Func, Operands, Flags, MIRId) \ + if (native == js::simd_int32x4_##Name) \ + return inlineSIMDFunction(callInfo, MSIMDUnaryFunction::Int32x4##MIRId, 1); +INT32X4_UNARY_FUNCTION_LIST(INLINE_INT32X4_UNARY_FUNCTION) +#undef INLINE_INT32X4_UNARY_FUNCTION + +#define INLINE_FLOAT32X4_BINARY_FUNCTION(Name, Func, Operands, Flags, MIRId) \ + if (native == js::simd_float32x4_##Name) \ + return inlineSIMDFunction(callInfo, MSIMDBinaryFunction::Float32x4##MIRId, 2); +FLOAT32X4_BINARY_FUNCTION_LIST(INLINE_FLOAT32X4_BINARY_FUNCTION) +#undef INLINE_FLOAT32X4_BINARY_FUNCTION +#define INLINE_INT32X4_BINARY_FUNCTION(Name, Func, Operands, Flags, MIRId) \ + if (native == js::simd_int32x4_##Name) \ + return inlineSIMDFunction(callInfo, MSIMDBinaryFunction::Int32x4##MIRId, 2); +INT32X4_BINARY_FUNCTION_LIST(INLINE_INT32X4_BINARY_FUNCTION) +#undef INLINE_INT32X4_BINARY_FUNCTION + +#define INLINE_FLOAT32X4_TERNARY_FUNCTION(Name, Func, Operands, Flags, MIRId) \ + if (native == js::simd_float32x4_##Name) \ + return inlineSIMDFunction(callInfo, MSIMDTernaryFunction::Float32x4##MIRId, 3); +FLOAT32X4_TERNARY_FUNCTION_LIST(INLINE_FLOAT32X4_TERNARY_FUNCTION) +#undef INLINE_FLOAT32X4_TERNARY_FUNCTION +#define INLINE_INT32X4_TERNARY_FUNCTION(Name, Func, Operands, Flags, MIRId) \ + if (native == js::simd_int32x4_##Name) \ + return inlineSIMDFunction(callInfo, MSIMDTernaryFunction::Int32x4##MIRId, 3); +INT32X4_TERNARY_FUNCTION_LIST(INLINE_INT32X4_TERNARY_FUNCTION) +#undef INLINE_INT32X4_TERNARY_FUNCTION + +#define INLINE_INT32X4_QUARTERNARY_FUNCTION(Name, Func, Operands, Flags, MIRId) \ + if (native == js::simd_int32x4_##Name) \ + return inlineSIMDFunction(callInfo, MSIMDQuarternaryFunction::Int32x4##MIRId, 4); +INT32X4_QUARTERNARY_FUNCTION_LIST(INLINE_INT32X4_QUARTERNARY_FUNCTION) +#undef INLINE_INT32X4_QUARTERNARY_FUNCTION + // String natives. if (native == js_String) return inlineStringObject(callInfo); @@ -216,6 +268,100 @@ IonBuilder::inlineMathFunction(CallInfo &callInfo, MMathFunction::Function funct return InliningStatus_Inlined; } +IonBuilder::InliningStatus +IonBuilder::checkSIMDArgs(CallInfo &callInfo, const MIRType *argumentTypes) +{ + for (uint32_t i = 0; i < callInfo.argc(); i++) { + MDefinition *arg = callInfo.getArg(i); + MIRType type = argumentTypes[i]; + switch (type) { + case MIRType_Float32x4: + case MIRType_Int32x4: + // SIMDTypePolicy will do the type check and un-box the typed object. + break; + + case MIRType_Int32: + case MIRType_Float32: + if (!IsNumberType(arg->type())) + return InliningStatus_NotInlined; + break; + + default: + MOZ_ASSUME_UNREACHABLE("Unknown SIMD MIR Type"); + } + } + return InliningStatus_Inlined; +} + +IonBuilder::InliningStatus +IonBuilder::inlineSIMDFunction(CallInfo &callInfo, uint32_t id, uint32_t argumentCount) +{ + if (callInfo.constructing()) + return InliningStatus_NotInlined; + + if (callInfo.argc() != argumentCount) + return InliningStatus_NotInlined; + + if (getInlineReturnType() != MIRType_Object) + return InliningStatus_NotInlined; + + MIRType *argumentTypes = nullptr; + switch (argumentCount) { + case 0: + break; + case 1: + argumentTypes = &MSIMDUnaryFunction::ArgumentTypes[id]; + break; + case 2: + argumentTypes = MSIMDBinaryFunction::ArgumentTypes[id]; + break; + case 3: + argumentTypes = MSIMDTernaryFunction::ArgumentTypes[id]; + break; + case 4: + argumentTypes = MSIMDQuarternaryFunction::ArgumentTypes[id]; + break; + default: + MOZ_ASSUME_UNREACHABLE("Unknown SIMD function argument count"); + } + InliningStatus s = checkSIMDArgs(callInfo, argumentTypes); + if (s != InliningStatus_Inlined) + return s; + + callInfo.setImplicitlyUsedUnchecked(); + + MInstruction *ins = nullptr; + switch (argumentCount) { + case 0: + ins = MSIMDNullaryFunction::New(alloc(), static_cast(id)); + break; + case 1: + ins = MSIMDUnaryFunction::New(alloc(), callInfo.getArg(0), + static_cast(id)); + break; + case 2: + ins = MSIMDBinaryFunction::New(alloc(), callInfo.getArg(0), callInfo.getArg(1), + static_cast(id)); + break; + case 3: + ins = MSIMDTernaryFunction::New(alloc(), callInfo.getArg(0), + callInfo.getArg(1), callInfo.getArg(2), + static_cast(id)); + break; + case 4: + ins = MSIMDQuarternaryFunction::New(alloc(), callInfo.getArg(0), callInfo.getArg(1), + callInfo.getArg(2), callInfo.getArg(3), + static_cast(id)); + break; + default: + MOZ_ASSUME_UNREACHABLE("Unknown SIMD function argument count"); + } + + current->add(ins); + current->push(ins); + return InliningStatus_Inlined; +} + IonBuilder::InliningStatus IonBuilder::inlineArray(CallInfo &callInfo) { diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp index 0ce5be00463..83a887652b0 100644 --- a/js/src/jit/MIR.cpp +++ b/js/src/jit/MIR.cpp @@ -13,6 +13,7 @@ #include "jslibmath.h" #include "jsstr.h" +#include "builtin/SIMD.h" #include "jit/BaselineInspector.h" #include "jit/IonBuilder.h" #include "jit/IonSpewer.h" @@ -624,6 +625,116 @@ MMathFunction::printOpcode(FILE *fp) const fprintf(fp, " %s", FunctionName(function())); } +const char *MSIMDNullaryFunction::Names[] = { +#define MSIMD_NULLARY_FUNCTION_NAME_TYPE(Id, Name, ReturnType) "SIMD." Name, + MSIMD_NULLARY_FUNCTION_LIST(MSIMD_NULLARY_FUNCTION_NAME_TYPE) +#undef MSIMD_NULLARY_FUNCTION_NAME_TYPE + "" +}; + +MIRType MSIMDNullaryFunction::ReturnTypes[] = { +#define MSIMD_NULLARY_FUNCTION_RETURN_TYPE(Id, Name, ReturnType) ReturnType, + MSIMD_NULLARY_FUNCTION_LIST(MSIMD_NULLARY_FUNCTION_RETURN_TYPE) +#undef MSIMD_NULLARY_FUNCTION_RETURN_TYPE + MIRType_None +}; + +const char *MSIMDUnaryFunction::Names[] = { +#define MSIMD_UNARY_FUNCTION_NAME_TYPE(Id, Name, ReturnType, ArgumentType) \ + "SIMD." Name, + MSIMD_UNARY_FUNCTION_LIST(MSIMD_UNARY_FUNCTION_NAME_TYPE) +#undef MSIMD_UNARY_FUNCTION_NAME_TYPE + "" +}; + +MIRType MSIMDUnaryFunction::ReturnTypes[] = { +#define MSIMD_UNARY_FUNCTION_RETURN_TYPE(Id, Name, ReturnType, ArgumentType) \ + ReturnType, + MSIMD_UNARY_FUNCTION_LIST(MSIMD_UNARY_FUNCTION_RETURN_TYPE) +#undef MSIMD_UNARY_FUNCTION_RETURN_TYPE + MIRType_None +}; + +MIRType MSIMDUnaryFunction::ArgumentTypes[] = { +#define MSIMD_UNARY_FUNCTION_ARGUMENT_TYPE(Id, Name, ReturnType, ArgumentType) \ + ArgumentType, + MSIMD_UNARY_FUNCTION_LIST(MSIMD_UNARY_FUNCTION_ARGUMENT_TYPE) +#undef MSIMD_UNARY_FUNCTION_ARGUMENT_TYPE + MIRType_None +}; + +const char *MSIMDBinaryFunction::Names[] = { +#define MSIMD_BINARY_FUNCTION_NAME_TYPE(Id, Name, ReturnType, Argument1Type, Argument2Type) \ + "SIMD." Name, + MSIMD_BINARY_FUNCTION_LIST(MSIMD_BINARY_FUNCTION_NAME_TYPE) +#undef MSIMD_BINARY_FUNCTION_NAME_TYPE + "" +}; + +MIRType MSIMDBinaryFunction::ReturnTypes[] = { +#define MSIMD_BINARY_FUNCTION_RETURN_TYPE(Id, Name, ReturnType, Argument1Type, Argument2Type) \ + ReturnType, + MSIMD_BINARY_FUNCTION_LIST(MSIMD_BINARY_FUNCTION_RETURN_TYPE) +#undef MSIMD_BINARY_FUNCTION_RETURN_TYPE + MIRType_None +}; + +MIRType MSIMDBinaryFunction::ArgumentTypes[][2] = { +#define MSIMD_BINARY_FUNCTION_ARGUMENTS_TYPE(Id, Name, ReturnType, Argument1Type, Argument2Type) \ + {Argument1Type, Argument2Type}, + MSIMD_BINARY_FUNCTION_LIST(MSIMD_BINARY_FUNCTION_ARGUMENTS_TYPE) +#undef MSIMD_BINARY_FUNCTION_ARGUMENTS_TYPE + {MIRType_None, MIRType_None} +}; + +const char *MSIMDTernaryFunction::Names[] = { +#define MSIMD_TERNARY_FUNCTION_NAME_TYPE(Id, Name, ReturnType, Argument1Type, Argument2Type, Argument3Type) \ + "SIMD." Name, + MSIMD_TERNARY_FUNCTION_LIST(MSIMD_TERNARY_FUNCTION_NAME_TYPE) +#undef MSIMD_TERNARY_FUNCTION_NAME_TYPE + "" +}; + +MIRType MSIMDTernaryFunction::ReturnTypes[] = { +#define MSIMD_TERNARY_FUNCTION_RETURN_TYPE(Id, Name, ReturnType, Argument1Type, Argument2Type, Argument3Type) \ + ReturnType, + MSIMD_TERNARY_FUNCTION_LIST(MSIMD_TERNARY_FUNCTION_RETURN_TYPE) +#undef MSIMD_TERNARY_FUNCTION_RETURN_TYPE + MIRType_None +}; + +MIRType MSIMDTernaryFunction::ArgumentTypes[][3] = { +#define MSIMD_TERNARY_FUNCTION_ARGUMENTS_TYPE(Id, Name, ReturnType, Argument1Type, Argument2Type, Argument3Type) \ + {Argument1Type, Argument2Type, Argument3Type}, + MSIMD_TERNARY_FUNCTION_LIST(MSIMD_TERNARY_FUNCTION_ARGUMENTS_TYPE) +#undef MSIMD_TERNARY_FUNCTION_ARGUMENTS_TYPE + {MIRType_None, MIRType_None, MIRType_None} +}; + +const char *MSIMDQuarternaryFunction::Names[] = { +#define MSIMD_QUARTERNARY_FUNCTION_NAME_TYPE(Id, Name, ReturnType, Argument1Type, Argument2Type, Argument3Type, Argument4Type) \ + "SIMD." Name, + MSIMD_QUARTERNARY_FUNCTION_LIST(MSIMD_QUARTERNARY_FUNCTION_NAME_TYPE) +#undef MSIMD_QUARTERNARY_FUNCTION_NAME_TYPE + "" +}; + +MIRType MSIMDQuarternaryFunction::ReturnTypes[] = { +#define MSIMD_QUARTERNARY_FUNCTION_RETURN_TYPE(Id, Name, ReturnType, Argument1Type, Argument2Type, Argument3Type, Argument4Type) \ + ReturnType, + MSIMD_QUARTERNARY_FUNCTION_LIST(MSIMD_QUARTERNARY_FUNCTION_RETURN_TYPE) +#undef MSIMD_QUARTERNARY_FUNCTION_RETURN_TYPE + MIRType_None +}; + +MIRType MSIMDQuarternaryFunction::ArgumentTypes[][4] = { +#define MSIMD_QUARTERNARY_FUNCTION_ARGUMENTS_TYPE(Id, Name, ReturnType, Argument1Type, Argument2Type, Argument3Type, Argument4Type) \ + {Argument1Type, Argument2Type, Argument3Type, Argument4Type}, + MSIMD_QUARTERNARY_FUNCTION_LIST(MSIMD_QUARTERNARY_FUNCTION_ARGUMENTS_TYPE) +#undef MSIMD_QUARTERNARY_FUNCTION_ARGUMENTS_TYPE + {MIRType_None, MIRType_None, MIRType_None, MIRType_None} +}; + MParameter * MParameter::New(TempAllocator &alloc, int32_t index, types::TemporaryTypeSet *types) { @@ -896,7 +1007,7 @@ MTypeBarrier::printOpcode(FILE *fp) const fprintf(fp, " "); getOperand(0)->printName(fp); } - + void MPhi::removeOperand(size_t index) { @@ -2444,7 +2555,7 @@ MCompare::evaluateConstantOperands(bool *result) int32_t comp = 0; // Default to equal. if (left != right) comp = CompareAtoms(&lhs.toString()->asAtom(), &rhs.toString()->asAtom()); - + switch (jsop_) { case JSOP_LT: *result = (comp < 0); @@ -2933,8 +3044,9 @@ jit::ElementAccessIsDenseNative(MDefinition *obj, MDefinition *id) if (!types) return false; + // Typed arrays are native classes but do not have dense elements. const Class *clasp = types->getKnownClass(); - return clasp && clasp->isNative(); + return clasp && clasp->isNative() && !IsTypedArrayClass(clasp); } bool diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index 6695a4e0999..5b7c1c7cf94 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -3936,6 +3936,283 @@ class MMathFunction void computeRange(TempAllocator &alloc); }; +#define DECLARE_COMMON_SIMD_FUNCTION(opcode) \ + static MIRType ReturnTypes[]; \ + static const char *Names[]; \ + Id id() const { \ + return id_; \ + } \ + bool congruentTo(MDefinition *ins) const { \ + if (!ins->is##opcode()) \ + return false; \ + if (ins->to##opcode()->id() != id()) \ + return false; \ + return congruentIfOperandsEqual(ins); \ + } \ + AliasSet getAliasSet() const { \ + return AliasSet::None(); \ + } \ + bool possiblyCalls() const { \ + return true; \ + } \ + void printOpcode(FILE *fp) const { \ + MDefinition::printOpcode(fp); \ + fprintf(fp, " %s", Names[id()]); \ + } + +#define MSIMD_NULLARY_FUNCTION_LIST(V) \ + V(Float32x4Zero, "float32x4.zero", MIRType_Float32x4) \ + V(Int32x4Zero, "int32x4.zero", MIRType_Int32x4) + +class MSIMDNullaryFunction + : public MNullaryInstruction +{ + public: + enum Id { +#define MSIMD_NULLARY_FUNCTION_ID(Id, Name, Type) Id, + MSIMD_NULLARY_FUNCTION_LIST(MSIMD_NULLARY_FUNCTION_ID) + NUMBER_OF_IDS +#undef MSIMD_NULLARY_FUNCTION_ID + }; + + private: + Id id_; + + MSIMDNullaryFunction(Id id) + : MNullaryInstruction(), id_(id) + { + setMovable(); + setResultType(ReturnTypes[id]); + } + + public: + INSTRUCTION_HEADER(SIMDNullaryFunction) + DECLARE_COMMON_SIMD_FUNCTION(SIMDNullaryFunction) + static MSIMDNullaryFunction *New(TempAllocator &alloc, Id id) + { + return new(alloc) MSIMDNullaryFunction(id); + } +}; + +#define MSIMD_UNARY_FUNCTION_LIST(V) \ + V(Float32x4Abs, "float32x4.abs", MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4BitsToInt32x4, "float32x4.bitstoInt32x4", MIRType_Int32x4, MIRType_Float32x4) \ + V(Float32x4Neg, "float32x4.neg", MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4Reciprocal, "float32x4.reciprocal", MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4ReciprocalSqrt, "float32x4.reciprocalSqrt", MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4Splat, "float32x4.splat", MIRType_Float32x4, MIRType_Float32) \ + V(Float32x4Sqrt, "float32x4.sqrt", MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4ToInt32x4, "float32x4.toInt32x4", MIRType_Int32x4, MIRType_Float32x4) \ + V(Float32x4GetX, "float32x4.getX", MIRType_Float32, MIRType_Float32x4) \ + V(Float32x4GetY, "float32x4.getY", MIRType_Float32, MIRType_Float32x4) \ + V(Float32x4GetZ, "float32x4.getZ", MIRType_Float32, MIRType_Float32x4) \ + V(Float32x4GetW, "float32x4.getW", MIRType_Float32, MIRType_Float32x4) \ + V(Float32x4GetSignMask, "float32x4.getSignMask", MIRType_Int32, MIRType_Float32x4) \ + V(Int32x4BitsToFloat32x4, "int32x4.bitsToFloat32x4", MIRType_Float32x4, MIRType_Int32x4) \ + V(Int32x4Neg, "int32x4.neg", MIRType_Int32x4, MIRType_Int32x4) \ + V(Int32x4Not, "int32x4.not", MIRType_Int32x4, MIRType_Int32x4) \ + V(Int32x4Splat, "int32x4.splat", MIRType_Int32x4, MIRType_Int32) \ + V(Int32x4ToFloat32x4, "int32x4.toFloat32x4", MIRType_Float32x4, MIRType_Int32x4) \ + V(Int32x4GetX, "int32x4.getX", MIRType_Int32, MIRType_Int32x4) \ + V(Int32x4GetY, "int32x4.getY", MIRType_Int32, MIRType_Int32x4) \ + V(Int32x4GetZ, "int32x4.getZ", MIRType_Int32, MIRType_Int32x4) \ + V(Int32x4GetW, "int32x4.getW", MIRType_Int32, MIRType_Int32x4) \ + V(Int32x4GetSignMask, "int32x4.getSignMask", MIRType_Int32, MIRType_Int32x4) \ + V(Int32x4GetFlagX, "int32x4.getFlagX", MIRType_Boolean, MIRType_Int32x4) \ + V(Int32x4GetFlagY, "int32x4.getFlagY", MIRType_Boolean, MIRType_Int32x4) \ + V(Int32x4GetFlagZ, "int32x4.getFlagZ", MIRType_Boolean, MIRType_Int32x4) \ + V(Int32x4GetFlagW, "int32x4.getFlagW", MIRType_Boolean, MIRType_Int32x4) + +class MSIMDUnaryFunction + : public MUnaryInstruction +{ + public: + enum Id { +#define MSIMD_UNARY_FUNCTION_ID(Id, Name, ReturnType, ArgumentType) Id, + MSIMD_UNARY_FUNCTION_LIST(MSIMD_UNARY_FUNCTION_ID) + NUMBER_OF_IDS +#undef MSIMD_UNARY_FUNCTION_ID + }; + + static MIRType ArgumentTypes[]; + + private: + Id id_; + + MSIMDUnaryFunction(MDefinition *argument, Id id) + : MUnaryInstruction(argument), id_(id) + { + setMovable(); + setResultType(ReturnTypes[id]); + } + + public: + INSTRUCTION_HEADER(SIMDUnaryFunction) + DECLARE_COMMON_SIMD_FUNCTION(SIMDUnaryFunction) + static MSIMDUnaryFunction *New(TempAllocator &alloc, MDefinition *argument, Id id) + { + return new(alloc) MSIMDUnaryFunction(argument, id); + } + bool canProduceFloat32() const { + return type() == MIRType_Float32; + } + bool canConsumeFloat32(MUse *use) const { + return id() == Float32x4Splat; + } +#ifdef DEBUG + bool isConsistentFloat32Use(MUse *use) const { return canProduceFloat32() || canConsumeFloat32(use); } +#endif +}; + +#define MSIMD_BINARY_FUNCTION_LIST(V) \ + V(Float32x4Add, "float32x4.add", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4Div, "float32x4.div", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4Equal, "float32x4.equal", MIRType_Int32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4GreaterThan, "float32x4.greaterThan", MIRType_Int32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4GreaterThanOrEqual, "float32x4.greaterThanOrEqual", MIRType_Int32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4LessThan, "float32x4.lessThan", MIRType_Int32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4LessThanOrEqual, "float32x4.lessThanOrEqual", MIRType_Int32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4Max, "float32x4.max", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4Min, "float32x4.min", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4Mul, "float32x4.mul", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4NotEqual, "float32x4.notEqual", MIRType_Int32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4Shuffle, "float32x4.shuffle", MIRType_Float32x4, MIRType_Float32x4, MIRType_Int32) \ + V(Float32x4Scale, "float32x4.scale", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32) \ + V(Float32x4Sub, "float32x4.sub", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4WithX, "float32x4.withX", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32) \ + V(Float32x4WithY, "float32x4.withY", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32) \ + V(Float32x4WithZ, "float32x4.withZ", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32) \ + V(Float32x4WithW, "float32x4.withW", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32) \ + V(Int32x4Add, "int32x4.add", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32x4) \ + V(Int32x4And, "int32x4.and", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32x4) \ + V(Int32x4Mul, "int32x4.mul", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32x4) \ + V(Int32x4Or, "int32x4.or", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32x4) \ + V(Int32x4Sub, "int32x4.sub", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32x4) \ + V(Int32x4Shuffle, "int32x4.shuffle", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32) \ + V(Int32x4WithFlagX, "int32x4.withFlagX", MIRType_Int32x4, MIRType_Int32x4, MIRType_Boolean) \ + V(Int32x4WithFlagY, "int32x4.withFlagY", MIRType_Int32x4, MIRType_Int32x4, MIRType_Boolean) \ + V(Int32x4WithFlagZ, "int32x4.withFlagZ", MIRType_Int32x4, MIRType_Int32x4, MIRType_Boolean) \ + V(Int32x4WithFlagW, "int32x4.withFlagW", MIRType_Int32x4, MIRType_Int32x4, MIRType_Boolean) \ + V(Int32x4WithX, "int32x4.withX", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32) \ + V(Int32x4WithY, "int32x4.withY", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32) \ + V(Int32x4WithZ, "int32x4.withZ", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32) \ + V(Int32x4WithW, "int32x4.withW", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32) \ + V(Int32x4Xor, "int32x4.xor", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32x4) + +class MSIMDBinaryFunction + : public MBinaryInstruction +{ + public: + enum Id { +#define MSIMD_BINARY_FUNCTION_ID(Id, Name, Type, Argument1Type, Argument2Type) Id, + MSIMD_BINARY_FUNCTION_LIST(MSIMD_BINARY_FUNCTION_ID) + NUMBER_OF_IDS +#undef MSIMD_BINARY_FUNCTION_ID + }; + + static MIRType ArgumentTypes[][2]; + + private: + Id id_; + + MSIMDBinaryFunction(MDefinition *left, MDefinition *right, Id id) + : MBinaryInstruction(left, right), id_(id) + { + setMovable(); + setResultType(ReturnTypes[id]); + } + + public: + INSTRUCTION_HEADER(SIMDBinaryFunction) + DECLARE_COMMON_SIMD_FUNCTION(SIMDBinaryFunction) + static MSIMDBinaryFunction *New(TempAllocator &alloc, MDefinition *left, MDefinition *right, Id id) + { + return new(alloc) MSIMDBinaryFunction(left, right, id); + } + bool canConsumeFloat32(MUse *use) const { + return id() == Float32x4Scale || id() == Float32x4WithX || id() == Float32x4WithY || + id() == Float32x4WithZ || id() == Float32x4WithW; + } +#ifdef DEBUG + bool isConsistentFloat32Use(MUse *use) const { + return canConsumeFloat32(use); + } +#endif +}; + +#define MSIMD_TERNARY_FUNCTION_LIST(V) \ + V(Float32x4Clamp, "float32x4.clamp", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4ShuffleMix, "float32x4.shuffleMix", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32x4, MIRType_Int32) \ + V(Int32x4Select, "int32x4.select", MIRType_Float32x4, MIRType_Int32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Int32x4ShuffleMix, "int32x4.shuffleMix", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32) + +class MSIMDTernaryFunction + : public MTernaryInstruction +{ + public: + enum Id { +#define MSIMD_TERNARY_FUNCTION_ID(Id, Name, Type, Argument1Type, Argument2Type, Argument3Type) Id, + MSIMD_TERNARY_FUNCTION_LIST(MSIMD_TERNARY_FUNCTION_ID) + NUMBER_OF_IDS +#undef MSIMD_TERNARY_FUNCTION_ID + }; + + static MIRType ArgumentTypes[][3]; + + private: + Id id_; + + MSIMDTernaryFunction(MDefinition *first, MDefinition *second, MDefinition *third, Id id) + : MTernaryInstruction(first, second, third), id_(id) + { + setMovable(); + setResultType(ReturnTypes[id]); + } + + public: + INSTRUCTION_HEADER(SIMDTernaryFunction) + DECLARE_COMMON_SIMD_FUNCTION(SIMDTernaryFunction) + static MSIMDTernaryFunction *New(TempAllocator &alloc, MDefinition *first, MDefinition *second, MDefinition *third, Id id) + { + return new(alloc) MSIMDTernaryFunction(first, second, third, id); + } +}; + +#define MSIMD_QUARTERNARY_FUNCTION_LIST(V) \ + V(Int32x4Bool, "int32x4.bool", MIRType_Int32x4, MIRType_Boolean, MIRType_Boolean, MIRType_Boolean, MIRType_Boolean) + +class MSIMDQuarternaryFunction + : public MQuaternaryInstruction +{ + public: + enum Id { +#define MSIMD_QUARTERNARY_FUNCTION_ID(Id, Name, Type, Argument1Type, Argument2Type, Argument3Type, Argument4Type) Id, + MSIMD_QUARTERNARY_FUNCTION_LIST(MSIMD_QUARTERNARY_FUNCTION_ID) + NUMBER_OF_IDS +#undef MSIMD_QUARTERNARY_FUNCTION_ID + }; + + static MIRType ArgumentTypes[][4]; + + private: + Id id_; + + MSIMDQuarternaryFunction(MDefinition *first, MDefinition *second, MDefinition *third, MDefinition *fourth, Id id) + : MQuaternaryInstruction(first, second, third, fourth), id_(id) + { + setMovable(); + setResultType(ReturnTypes[id]); + } + + public: + INSTRUCTION_HEADER(SIMDQuarternaryFunction) + DECLARE_COMMON_SIMD_FUNCTION(SIMDQuarternaryFunction) + static MSIMDQuarternaryFunction *New(TempAllocator &alloc, MDefinition *first, MDefinition *second, MDefinition *third, MDefinition *fourth, Id id) + { + return new(alloc) MSIMDQuarternaryFunction(first, second, third, fourth, id); + } +}; + class MAdd : public MBinaryArithInstruction { // Is this instruction really an int at heart? diff --git a/js/src/jit/MOpcodes.h b/js/src/jit/MOpcodes.h index e598a711a5e..46c65100960 100644 --- a/js/src/jit/MOpcodes.h +++ b/js/src/jit/MOpcodes.h @@ -63,6 +63,11 @@ namespace jit { _(PowHalf) \ _(Random) \ _(MathFunction) \ + _(SIMDNullaryFunction) \ + _(SIMDUnaryFunction) \ + _(SIMDBinaryFunction) \ + _(SIMDTernaryFunction) \ + _(SIMDQuarternaryFunction) \ _(Add) \ _(Sub) \ _(Mul) \ diff --git a/js/src/jit/ParallelSafetyAnalysis.cpp b/js/src/jit/ParallelSafetyAnalysis.cpp index 791b38614cf..2ec4942a264 100644 --- a/js/src/jit/ParallelSafetyAnalysis.cpp +++ b/js/src/jit/ParallelSafetyAnalysis.cpp @@ -158,6 +158,11 @@ class ParallelSafetyVisitor : public MInstructionVisitor UNSAFE_OP(Atan2) UNSAFE_OP(Hypot) CUSTOM_OP(MathFunction) + SAFE_OP(SIMDNullaryFunction) + SAFE_OP(SIMDUnaryFunction) + SAFE_OP(SIMDBinaryFunction) + SAFE_OP(SIMDTernaryFunction) + SAFE_OP(SIMDQuarternaryFunction) SPECIALIZED_OP(Add, PERMIT_NUMERIC) SPECIALIZED_OP(Sub, PERMIT_NUMERIC) SPECIALIZED_OP(Mul, PERMIT_NUMERIC) diff --git a/js/src/jit/arm/MacroAssembler-arm.cpp b/js/src/jit/arm/MacroAssembler-arm.cpp index 1cff932432f..f0ed5ab4420 100644 --- a/js/src/jit/arm/MacroAssembler-arm.cpp +++ b/js/src/jit/arm/MacroAssembler-arm.cpp @@ -2531,14 +2531,6 @@ MacroAssemblerARMCompat::branchFloat(DoubleCondition cond, const FloatRegister & ma_b(label, ConditionFromDoubleCondition(cond)); } -// higher level tag testing code -Operand ToPayload(Operand base) { - return Operand(Register::FromCode(base.base()), base.disp()); -} -Operand ToType(Operand base) { - return Operand(Register::FromCode(base.base()), base.disp() + sizeof(void *)); -} - Assembler::Condition MacroAssemblerARMCompat::testInt32(Assembler::Condition cond, const ValueOperand &value) { diff --git a/js/src/jit/arm/MacroAssembler-arm.h b/js/src/jit/arm/MacroAssembler-arm.h index 5d6d18b6222..45ecc23b567 100644 --- a/js/src/jit/arm/MacroAssembler-arm.h +++ b/js/src/jit/arm/MacroAssembler-arm.h @@ -35,6 +35,20 @@ class MacroAssemblerARM : public Assembler // baseline IC stubs rely on lr holding the return address. Register secondScratchReg_; + // higher level tag testing code + Operand ToPayload(Operand base) { + return Operand(Register::FromCode(base.base()), base.disp()); + } + Address ToPayload(Address base) { + return ToPayload(Operand(base)).toAddress(); + } + Operand ToType(Operand base) { + return Operand(Register::FromCode(base.base()), base.disp() + sizeof(void *)); + } + Address ToType(Address base) { + return ToType(Operand(base)).toAddress(); + } + public: MacroAssemblerARM() : secondScratchReg_(lr) diff --git a/js/src/jit/x86/MacroAssembler-x86.h b/js/src/jit/x86/MacroAssembler-x86.h index 19a0675967f..69a1fd19e47 100644 --- a/js/src/jit/x86/MacroAssembler-x86.h +++ b/js/src/jit/x86/MacroAssembler-x86.h @@ -91,6 +91,9 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared Operand ToPayload(Operand base) { return base; } + Address ToPayload(Address base) { + return base; + } Operand ToType(Operand base) { switch (base.kind()) { case Operand::MEM_REG_DISP: @@ -104,6 +107,9 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared MOZ_ASSUME_UNREACHABLE("unexpected operand kind"); } } + Address ToType(Address base) { + return ToType(Operand(base)).toAddress(); + } void moveValue(const Value &val, Register type, Register data) { jsval_layout jv = JSVAL_TO_IMPL(val); movl(Imm32(jv.s.tag), type); diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index e5e33e954a7..8b66c1f3074 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -2715,8 +2715,8 @@ LookupResult(JSContext *cx, HandleObject obj, HandleObject obj2, HandleId id, return true; } } - } else if (IsImplicitDenseElement(shape)) { - vp.set(obj2->getDenseElement(JSID_TO_INT(id))); + } else if (IsImplicitDenseOrTypedArrayElement(shape)) { + vp.set(obj2->getDenseOrTypedArrayElement(JSID_TO_INT(id))); return true; } else { /* Peek at the native property's slot value, without doing a Get. */ @@ -2864,9 +2864,21 @@ JS_AlreadyHasOwnPropertyById(JSContext *cx, HandleObject obj, HandleId id, bool return true; } - if (JSID_IS_INT(id) && obj->containsDenseElement(JSID_TO_INT(id))) { - *foundp = true; - return true; + // Check for an existing native property on the objct. Be careful not to + // call any lookup or resolve hooks. + + if (JSID_IS_INT(id)) { + uint32_t index = JSID_TO_INT(id); + + if (obj->containsDenseElement(index)) { + *foundp = true; + return true; + } + + if (obj->is() && index < obj->as().length()) { + *foundp = true; + return true; + } } *foundp = obj->nativeContains(cx, id); @@ -3257,9 +3269,9 @@ GetPropertyDescriptorById(JSContext *cx, HandleObject obj, HandleId id, unsigned desc.object().set(obj2); if (obj2->isNative()) { - if (IsImplicitDenseElement(shape)) { + if (IsImplicitDenseOrTypedArrayElement(shape)) { desc.setEnumerable(); - desc.value().set(obj2->getDenseElement(JSID_TO_INT(id))); + desc.value().set(obj2->getDenseOrTypedArrayElement(JSID_TO_INT(id))); } else { desc.setAttributes(shape->attributes()); desc.setGetter(shape->getter()); diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 20d1abe2946..e067779129c 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -823,6 +823,8 @@ js::ObjectMayHaveExtraIndexedProperties(JSObject *obj) return true; if (obj->getDenseInitializedLength() > 0) return true; + if (obj->is()) + return true; } return false; @@ -2040,7 +2042,7 @@ js::array_push(JSContext *cx, unsigned argc, Value *vp) /* Fast path for native objects with dense elements. */ do { - if (!obj->isNative()) + if (!obj->isNative() || obj->is()) break; if (obj->is() && !obj->as().lengthIsWritable()) diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index bd3dd3f1e32..c701e8992aa 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -919,197 +919,109 @@ fun_toSource(JSContext *cx, unsigned argc, Value *vp) bool js_fun_call(JSContext *cx, unsigned argc, Value *vp) { - RootedValue fval(cx, vp[1]); + CallArgs args = CallArgsFromVp(argc, vp); + HandleValue fval = args.thisv(); if (!js_IsCallable(fval)) { - ReportIncompatibleMethod(cx, CallReceiverFromVp(vp), &JSFunction::class_); + ReportIncompatibleMethod(cx, args, &JSFunction::class_); return false; } - Value *argv = vp + 2; - RootedValue thisv(cx, UndefinedValue()); - if (argc != 0) { - thisv = argv[0]; - - argc--; - argv++; - } - - /* Allocate stack space for fval, obj, and the args. */ - InvokeArgs args(cx); - if (!args.init(argc)) + InvokeArgs args2(cx); + if (!args2.init(args.length() ? args.length() - 1 : 0)) return false; - /* Push fval, thisv, and the args. */ - args.setCallee(fval); - args.setThis(thisv); - PodCopy(args.array(), argv, argc); + args2.setCallee(fval); + args2.setThis(args.get(0)); + PodCopy(args2.array(), args.array() + 1, args2.length()); - bool ok = Invoke(cx, args); - *vp = args.rval(); - return ok; -} - -#ifdef JS_ION -static bool -PushBaselineFunApplyArguments(JSContext *cx, jit::IonFrameIterator &frame, InvokeArgs &args, - Value *vp) -{ - unsigned length = frame.numActualArgs(); - JS_ASSERT(length <= ARGS_LENGTH_MAX); - - if (!args.init(length)) + if (!Invoke(cx, args2)) return false; - /* Push fval, obj, and aobj's elements as args. */ - args.setCallee(vp[1]); - args.setThis(vp[2]); - - /* Steps 7-8. */ - frame.forEachCanonicalActualArg(CopyTo(args.array()), jit::ReadFrame_Actuals); + args.rval().set(args2.rval()); return true; } -#endif -/* ES5 15.3.4.3 */ +// ES5 15.3.4.3 bool js_fun_apply(JSContext *cx, unsigned argc, Value *vp) { - /* Step 1. */ - RootedValue fval(cx, vp[1]); + CallArgs args = CallArgsFromVp(argc, vp); + + // Step 1. + HandleValue fval = args.thisv(); if (!js_IsCallable(fval)) { - ReportIncompatibleMethod(cx, CallReceiverFromVp(vp), &JSFunction::class_); + ReportIncompatibleMethod(cx, args, &JSFunction::class_); return false; } - /* Step 2. */ - if (argc < 2 || vp[3].isNullOrUndefined()) + // Step 2. + if (args.length() < 2 || args[1].isNullOrUndefined()) return js_fun_call(cx, (argc > 0) ? 1 : 0, vp); - InvokeArgs args(cx); + InvokeArgs args2(cx); - /* - * GuardFunApplyArgumentsOptimization already called IsOptimizedArguments, - * so we don't need to here. This is not an optimization: we can't rely on - * cx->fp (since natives can be called directly from JSAPI). - */ - if (vp[3].isMagic(JS_OPTIMIZED_ARGUMENTS)) { - /* - * Pretend we have been passed the 'arguments' object for the current - * function and read actuals out of the frame. - */ - /* Steps 4-6. */ + // A JS_OPTIMIZED_ARGUMENTS magic value means that 'arguments' flows into + // this apply call from a scripted caller and, as an optimization, we've + // avoided creating it since apply can simply pull the argument values from + // the calling frame (which we must do now). + if (args[1].isMagic(JS_OPTIMIZED_ARGUMENTS)) { + // Step 3-6. + ScriptFrameIter iter(cx); + JS_ASSERT(iter.numActualArgs() <= ARGS_LENGTH_MAX); + if (!args2.init(iter.numActualArgs())) + return false; -#ifdef JS_ION - // We do not want to use ScriptFrameIter to abstract here because this - // is supposed to be a fast path as opposed to ScriptFrameIter which is - // doing complex logic to settle on the next frame twice. - if (cx->currentlyRunningInJit()) { - jit::JitActivationIterator activations(cx->runtime()); - jit::IonFrameIterator frame(activations); - if (frame.isNative()) { - // Stop on the next Ion JS Frame. - ++frame; - if (frame.isOptimizedJS()) { - jit::InlineFrameIterator iter(cx, &frame); + args2.setCallee(fval); + args2.setThis(args[0]); - unsigned length = iter.numActualArgs(); - JS_ASSERT(length <= ARGS_LENGTH_MAX); - - if (!args.init(length)) - return false; - - /* Push fval, obj, and aobj's elements as args. */ - args.setCallee(fval); - args.setThis(vp[2]); - - /* Steps 7-8. */ - iter.forEachCanonicalActualArg(cx, CopyTo(args.array()), - jit::ReadFrame_Actuals); - } else { - JS_ASSERT(frame.isBaselineStub()); - - ++frame; - JS_ASSERT(frame.isBaselineJS()); - - if (!PushBaselineFunApplyArguments(cx, frame, args, vp)) - return false; - } - } else { - JS_ASSERT(frame.type() == jit::IonFrame_Exit); - - ++frame; - JS_ASSERT(frame.isBaselineStub()); - - ++frame; - JS_ASSERT(frame.isBaselineJS()); - - if (!PushBaselineFunApplyArguments(cx, frame, args, vp)) - return false; - } - } else -#endif - { - StackFrame *fp = cx->interpreterFrame(); - unsigned length = fp->numActualArgs(); - JS_ASSERT(length <= ARGS_LENGTH_MAX); - - if (!args.init(length)) - return false; - - /* Push fval, obj, and aobj's elements as args. */ - args.setCallee(fval); - args.setThis(vp[2]); - - /* Steps 7-8. */ - fp->forEachUnaliasedActual(CopyTo(args.array())); - } + // Steps 7-8. + iter.unaliasedForEachActual(cx, CopyTo(args2.array())); } else { - /* Step 3. */ - if (!vp[3].isObject()) { + // Step 3. + if (!args[1].isObject()) { JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_APPLY_ARGS, js_apply_str); return false; } - /* - * Steps 4-5 (note erratum removing steps originally numbered 5 and 7 in - * original version of ES5). - */ - RootedObject aobj(cx, &vp[3].toObject()); + // Steps 4-5 (note erratum removing steps originally numbered 5 and 7 in + // original version of ES5). + RootedObject aobj(cx, &args[1].toObject()); uint32_t length; if (!GetLengthProperty(cx, aobj, &length)) return false; - /* Step 6. */ + // Step 6. if (length > ARGS_LENGTH_MAX) { JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TOO_MANY_FUN_APPLY_ARGS); return false; } - if (!args.init(length)) + if (!args2.init(length)) return false; - /* Push fval, obj, and aobj's elements as args. */ - args.setCallee(fval); - args.setThis(vp[2]); + // Push fval, obj, and aobj's elements as args. + args2.setCallee(fval); + args2.setThis(args[0]); // Make sure the function is delazified before querying its arguments. - if (args.callee().is()) { - JSFunction *fun = &args.callee().as(); + if (args2.callee().is()) { + JSFunction *fun = &args2.callee().as(); if (fun->isInterpreted() && !fun->getOrCreateScript(cx)) return false; } - /* Steps 7-8. */ - if (!GetElements(cx, aobj, length, args.array())) + + // Steps 7-8. + if (!GetElements(cx, aobj, length, args2.array())) return false; } - /* Step 9. */ - if (!Invoke(cx, args)) + // Step 9. + if (!Invoke(cx, args2)) return false; - *vp = args.rval(); + args.rval().set(args2.rval()); return true; } diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index 43553fd9044..3bdf893654f 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -2134,7 +2134,10 @@ static inline bool ClassCanHaveExtraProperties(const Class *clasp) { JS_ASSERT(clasp->resolve); - return clasp->resolve != JS_ResolveStub || clasp->ops.lookupGeneric || clasp->ops.getGeneric; + return clasp->resolve != JS_ResolveStub + || clasp->ops.lookupGeneric + || clasp->ops.getGeneric + || IsTypedArrayClass(clasp); } static inline bool diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index e1821a8d9c5..5ab62242b8f 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -131,13 +131,22 @@ static bool EnumerateNativeProperties(JSContext *cx, HandleObject pobj, unsigned flags, IdSet &ht, AutoIdVector *props) { - /* Collect any elements from this object. */ + /* Collect any dense elements from this object. */ size_t initlen = pobj->getDenseInitializedLength(); const Value *vp = pobj->getDenseElements(); for (size_t i = 0; i < initlen; ++i, ++vp) { if (!vp->isMagic(JS_ELEMENTS_HOLE)) { /* Dense arrays never get so large that i would not fit into an integer id. */ - if (!Enumerate(cx, pobj, INT_TO_JSID(i), true, flags, ht, props)) + if (!Enumerate(cx, pobj, INT_TO_JSID(i), /* enumerable = */ true, flags, ht, props)) + return false; + } + } + + /* Collect any typed array elements from this object. */ + if (pobj->is()) { + size_t len = pobj->as().length(); + for (size_t i = 0; i < len; i++) { + if (!Enumerate(cx, pobj, INT_TO_JSID(i), /* enumerable = */ true, flags, ht, props)) return false; } } @@ -623,6 +632,7 @@ js::GetIterator(JSContext *cx, HandleObject obj, unsigned flags, MutableHandleVa do { if (!pobj->isNative() || !pobj->hasEmptyElements() || + pobj->is() || pobj->hasUncacheableProto() || pobj->getOps()->enumerate || pobj->getClass()->enumerate != JS_EnumerateStub || @@ -1053,7 +1063,7 @@ SuppressDeletedPropertyHelper(JSContext *cx, HandleObject obj, StringPredicate p if (prop) { unsigned attrs; if (obj2->isNative()) - attrs = GetShapeAttributes(prop); + attrs = GetShapeAttributes(obj2, prop); else if (!JSObject::getGenericAttributes(cx, obj2, id, &attrs)) return false; diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 78a7daa9eaf..8cc46254579 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -236,7 +236,7 @@ js::GetOwnPropertyDescriptor(JSContext *cx, HandleObject obj, HandleId id, bool doGet = true; if (pobj->isNative()) { - desc.setAttributes(GetShapeAttributes(shape)); + desc.setAttributes(GetShapeAttributes(pobj, shape)); if (desc.hasGetterOrSetterObject()) { doGet = false; if (desc.hasGetterObject()) @@ -599,8 +599,8 @@ DefinePropertyOnObject(JSContext *cx, HandleObject obj, HandleId id, const PropD shapeHasDefaultSetter = true, shapeHasGetterValue = false, shapeHasSetterValue = false; - uint8_t shapeAttributes = JSPROP_ENUMERATE; - if (!IsImplicitDenseElement(shape)) { + uint8_t shapeAttributes = GetShapeAttributes(obj, shape); + if (!IsImplicitDenseOrTypedArrayElement(shape)) { shapeDataDescriptor = shape->isDataDescriptor(); shapeAccessorDescriptor = shape->isAccessorDescriptor(); shapeWritable = shape->writable(); @@ -641,8 +641,8 @@ DefinePropertyOnObject(JSContext *cx, HandleObject obj, HandleId id, const PropD * avoid calling a getter; we won't need the value if it's not a * data descriptor. */ - if (IsImplicitDenseElement(shape)) { - v = obj->getDenseElement(JSID_TO_INT(id)); + if (IsImplicitDenseOrTypedArrayElement(shape)) { + v = obj->getDenseOrTypedArrayElement(JSID_TO_INT(id)); } else if (shape->isDataDescriptor()) { /* * We must rule out a non-configurable js::PropertyOp-guarded @@ -783,8 +783,8 @@ DefinePropertyOnObject(JSContext *cx, HandleObject obj, HandleId id, const PropD changed |= JSPROP_ENUMERATE; attrs = (shapeAttributes & ~changed) | (desc.attributes() & changed); - getter = IsImplicitDenseElement(shape) ? JS_PropertyStub : shape->getter(); - setter = IsImplicitDenseElement(shape) ? JS_StrictPropertyStub : shape->setter(); + getter = IsImplicitDenseOrTypedArrayElement(shape) ? JS_PropertyStub : shape->getter(); + setter = IsImplicitDenseOrTypedArrayElement(shape) ? JS_StrictPropertyStub : shape->setter(); } else if (desc.isDataDescriptor()) { unsigned unchanged = 0; if (!desc.hasConfigurable()) @@ -1084,7 +1084,7 @@ JSObject::sealOrFreeze(JSContext *cx, HandleObject obj, ImmutabilityType it) /* preventExtensions must sparsify dense objects, so we can assign to holes without checks. */ JS_ASSERT_IF(obj->isNative(), obj->getDenseCapacity() == 0); - if (obj->isNative() && !obj->inDictionaryMode()) { + if (obj->isNative() && !obj->inDictionaryMode() && !obj->is()) { /* * Seal/freeze non-dictionary objects by constructing a new shape * hierarchy mirroring the original one, which can be shared if many @@ -3066,6 +3066,7 @@ bool JSObject::growElements(ThreadSafeContext *cx, uint32_t newcap) { JS_ASSERT(nonProxyIsExtensible()); + JS_ASSERT(canHaveNonEmptyElements()); /* * When an object with CAPACITY_DOUBLING_MAX or fewer elements needs to @@ -3132,6 +3133,7 @@ void JSObject::shrinkElements(ThreadSafeContext *cx, uint32_t newcap) { JS_ASSERT(cx->isThreadLocal(this)); + JS_ASSERT(canHaveNonEmptyElements()); uint32_t oldcap = getDenseCapacity(); JS_ASSERT(newcap <= oldcap); @@ -3705,7 +3707,8 @@ DefinePropertyOrElement(typename ExecutionModeTraits::ExclusiveContextType getter == JS_PropertyStub && setter == JS_StrictPropertyStub && attrs == JSPROP_ENUMERATE && - (!obj->isIndexed() || !obj->nativeContainsPure(id))) + (!obj->isIndexed() || !obj->nativeContainsPure(id)) && + !obj->is()) { uint32_t index = JSID_TO_INT(id); bool definesPast; @@ -3755,6 +3758,13 @@ DefinePropertyOrElement(typename ExecutionModeTraits::ExclusiveContextType } } + // Don't define new indexed properties on typed arrays. + if (obj->is()) { + double index; + if (IsTypedArrayIndex(id, &index)) + return true; + } + AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter); RootedShape shape(cx, JSObject::putProperty(cx, obj, id, getter, setter, @@ -3826,7 +3836,11 @@ js::DefineNativeProperty(ExclusiveContext *cx, HandleObject obj, HandleId id, Ha if (!NativeLookupOwnProperty(cx, obj, id, flags, &shape)) return false; if (shape) { - if (IsImplicitDenseElement(shape)) { + if (IsImplicitDenseOrTypedArrayElement(shape)) { + if (obj->is()) { + /* Ignore getter/setter properties added to typed arrays. */ + return true; + } if (!JSObject::sparsifyDenseElement(cx, obj, JSID_TO_INT(id))) return false; shape = obj->nativeLookup(cx, id); @@ -3953,7 +3967,7 @@ CallResolveOp(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, } if (JSID_IS_INT(id) && objp->containsDenseElement(JSID_TO_INT(id))) { - MarkDenseElementFound(propp); + MarkDenseOrTypedArrayElementFound(propp); return true; } @@ -3979,11 +3993,26 @@ LookupOwnPropertyWithFlagsInline(ExclusiveContext *cx, // Check for a native dense element. if (JSID_IS_INT(id) && obj->containsDenseElement(JSID_TO_INT(id))) { objp.set(obj); - MarkDenseElementFound(propp); + MarkDenseOrTypedArrayElementFound(propp); *donep = true; return true; } + // Check for a typed array element. Integer lookups always finish here + // so that integer properties on the prototype are ignored even for out + // of bounds accesses. + if (obj->template is()) { + double index; + if (IsTypedArrayIndex(id, &index)) { + if (index >= 0 && index < obj->template as().length()) { + objp.set(obj); + MarkDenseOrTypedArrayElementFound(propp); + } + *donep = true; + return true; + } + } + // Check for a native property. if (Shape *shape = obj->nativeLookup(cx, id)) { objp.set(obj); @@ -4523,8 +4552,8 @@ GetPropertyHelperInline(JSContext *cx, : JSObject::getGeneric(cx, obj2Handle, obj2Handle, idHandle, vpHandle); } - if (IsImplicitDenseElement(shape)) { - vp.set(obj2->getDenseElement(JSID_TO_INT(id))); + if (IsImplicitDenseOrTypedArrayElement(shape)) { + vp.set(obj2->getDenseOrTypedArrayElement(JSID_TO_INT(id))); return true; } @@ -4557,21 +4586,34 @@ LookupPropertyPureInline(JSObject *obj, jsid id, JSObject **objp, Shape **propp) JSObject *current = obj; while (true) { - /* Search for a native dense element or property. */ - { - if (JSID_IS_INT(id) && current->containsDenseElement(JSID_TO_INT(id))) { - *objp = current; - MarkDenseElementFound(propp); - return true; - } + /* Search for a native dense element, typed array element, or property. */ - if (Shape *shape = current->nativeLookupPure(id)) { - *objp = current; - *propp = shape; + if (JSID_IS_INT(id) && current->containsDenseElement(JSID_TO_INT(id))) { + *objp = current; + MarkDenseOrTypedArrayElementFound(propp); + return true; + } + + if (current->is()) { + double index; + if (IsTypedArrayIndex(id, &index)) { + if (index >= 0 && index < obj->as().length()) { + *objp = current; + MarkDenseOrTypedArrayElementFound(propp); + } else { + *objp = nullptr; + *propp = nullptr; + } return true; } } + if (Shape *shape = current->nativeLookupPure(id)) { + *objp = current; + *propp = shape; + return true; + } + /* Fail if there's a resolve hook. */ if (current->getClass()->resolve != JS_ResolveStub) return false; @@ -4632,28 +4674,6 @@ IdIsLength(ThreadSafeContext *cx, jsid id) bool js::GetPropertyPure(ThreadSafeContext *cx, JSObject *obj, jsid id, Value *vp) { - /* Typed arrays are not native, so we fast-path them here. */ - if (obj->is()) { - TypedArrayObject *tarr = &obj->as(); - - if (JSID_IS_INT(id)) { - uint32_t index = JSID_TO_INT(id); - if (index < tarr->length()) { - MutableHandleValue vpHandle = MutableHandleValue::fromMarkedLocation(vp); - tarr->copyTypedArrayElement(index, vpHandle); - return true; - } - return false; - } - - if (IdIsLength(cx, id)) { - vp->setNumber(tarr->length()); - return true; - } - - return false; - } - /* Deal with native objects. */ JSObject *obj2; Shape *shape; @@ -4673,15 +4693,22 @@ js::GetPropertyPure(ThreadSafeContext *cx, JSObject *obj, jsid id, Value *vp) return true; } - if (IsImplicitDenseElement(shape)) { - *vp = obj2->getDenseElement(JSID_TO_INT(id)); + if (IsImplicitDenseOrTypedArrayElement(shape)) { + *vp = obj2->getDenseOrTypedArrayElement(JSID_TO_INT(id)); return true; } - /* Special case 'length' on Array. */ - if (obj->is() && IdIsLength(cx, id)) { - vp->setNumber(obj->as().length()); - return true; + /* Special case 'length' on Array and TypedArray. */ + if (IdIsLength(cx, id)) { + if (obj->is()) { + vp->setNumber(obj->as().length()); + return true; + } + + if (obj->is()) { + vp->setNumber(obj->as().length()); + return true; + } } return NativeGetPureInline(obj2, shape, vp); @@ -4936,7 +4963,7 @@ baseops::SetPropertyHelper(typename ExecutionModeTraits::ContextType cxArg PropertyOp getter = clasp->getProperty; StrictPropertyOp setter = clasp->setProperty; - if (IsImplicitDenseElement(shape)) { + if (IsImplicitDenseOrTypedArrayElement(shape)) { /* ES5 8.12.4 [[Put]] step 2, for a dense data property on pobj. */ if (pobj != obj) shape = nullptr; @@ -5013,7 +5040,7 @@ baseops::SetPropertyHelper(typename ExecutionModeTraits::ContextType cxArg } } - if (IsImplicitDenseElement(shape)) { + if (IsImplicitDenseOrTypedArrayElement(shape)) { uint32_t index = JSID_TO_INT(id); bool definesPast; if (!WouldDefinePastNonwritableLength(cxArg, obj, index, strict, &definesPast)) @@ -5026,10 +5053,8 @@ baseops::SetPropertyHelper(typename ExecutionModeTraits::ContextType cxArg } if (mode == ParallelExecution) - obj->setDenseElementIfHasType(index, vp); - else - obj->setDenseElementWithType(cxArg->asJSContext(), index, vp); - return true; + return obj->setDenseOrTypedArrayElementIfHasType(cxArg, index, vp); + return obj->setDenseOrTypedArrayElementWithType(cxArg->asJSContext(), index, vp); } if (obj->is() && id == NameToId(cxArg->names().length)) { @@ -5114,7 +5139,7 @@ baseops::GetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *a if (!nobj->isNative()) return JSObject::getGenericAttributes(cx, nobj, id, attrsp); - *attrsp = GetShapeAttributes(shape); + *attrsp = GetShapeAttributes(nobj, shape); return true; } @@ -5127,7 +5152,13 @@ baseops::SetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *a return false; if (!shape) return true; - if (nobj->isNative() && IsImplicitDenseElement(shape)) { + if (nobj->isNative() && IsImplicitDenseOrTypedArrayElement(shape)) { + if (nobj->is()) { + if (*attrsp == (JSPROP_ENUMERATE | JSPROP_PERMANENT)) + return true; + JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_SET_ARRAY_ATTRS); + return false; + } if (!JSObject::sparsifyDenseElement(cx, nobj, JSID_TO_INT(id))) return false; shape = obj->nativeLookup(cx, id); @@ -5160,7 +5191,13 @@ baseops::DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, bool *succe GCPoke(cx->runtime()); - if (IsImplicitDenseElement(shape)) { + if (IsImplicitDenseOrTypedArrayElement(shape)) { + if (obj->is()) { + // Don't delete elements from typed arrays. + *succeeded = false; + return true; + } + if (!CallJSDeletePropertyOp(cx, obj->getClass()->delProperty, obj, id, succeeded)) return false; if (!succeeded) @@ -5237,7 +5274,7 @@ js::WatchGuts(JSContext *cx, JS::HandleObject origObj, JS::HandleId id, JS::Hand bool baseops::Watch(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject callable) { - if (!obj->isNative()) { + if (!obj->isNative() || obj->is()) { JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_WATCH, obj->getClass()->name); return false; diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 7e1cfde68bd..4c11985aa27 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -672,6 +672,12 @@ class JSObject : public js::ObjectImpl static inline void removeDenseElementForSparseIndex(js::ExclusiveContext *cx, js::HandleObject obj, uint32_t index); + inline js::Value getDenseOrTypedArrayElement(uint32_t idx); + inline bool setDenseOrTypedArrayElementIfHasType(js::ThreadSafeContext *cx, uint32_t index, + const js::Value &val); + inline bool setDenseOrTypedArrayElementWithType(js::ExclusiveContext *cx, uint32_t index, + const js::Value &val); + void copyDenseElements(uint32_t dstStart, const js::Value *src, uint32_t count) { JS_ASSERT(dstStart + count <= getDenseCapacity()); JSRuntime *rt = runtimeFromMainThread(); diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index 35dc5ce3c49..4a566cc9f56 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -353,6 +353,33 @@ JSObject::ensureDenseElementsPreservePackedFlag(js::ThreadSafeContext *cx, uint3 return ensureDenseElementsNoPackedCheck(cx, index, extra); } +inline js::Value +JSObject::getDenseOrTypedArrayElement(uint32_t idx) +{ + if (is()) + return as().getElement(idx); + return getDenseElement(idx); +} + +inline bool +JSObject::setDenseOrTypedArrayElementIfHasType(js::ThreadSafeContext *cx, uint32_t index, + const js::Value &val) +{ + if (is()) + return as().setElement(cx, index, val); + return setDenseElementIfHasType(index, val); +} + +inline bool +JSObject::setDenseOrTypedArrayElementWithType(js::ExclusiveContext *cx, uint32_t index, + const js::Value &val) +{ + if (is()) + return as().setElement(cx, index, val); + setDenseElementWithType(cx, index, val); + return true; +} + /* static */ inline bool JSObject::setSingletonType(js::ExclusiveContext *cx, js::HandleObject obj) { diff --git a/js/src/vm/ArgumentsObject.cpp b/js/src/vm/ArgumentsObject.cpp index 1d47c8f8d59..02191e3720f 100644 --- a/js/src/vm/ArgumentsObject.cpp +++ b/js/src/vm/ArgumentsObject.cpp @@ -134,13 +134,8 @@ struct CopyScriptFrameIterArgs { } void copyArgs(JSContext *cx, HeapValue *dstBase, unsigned totalArgs) const { - if (!iter_.isJit()) { - CopyStackFrameArguments(iter_.abstractFramePtr(), dstBase, totalArgs); - return; - } - /* Copy actual arguments. */ - iter_.ionForEachCanonicalActualArg(cx, CopyToHeap(dstBase)); + iter_.unaliasedForEachActual(cx, CopyToHeap(dstBase)); /* Define formals which are not part of the actuals. */ unsigned numActuals = iter_.numActualArgs(); diff --git a/js/src/vm/ArrayBufferObject.cpp b/js/src/vm/ArrayBufferObject.cpp index cdf74994523..5244cbb7cda 100644 --- a/js/src/vm/ArrayBufferObject.cpp +++ b/js/src/vm/ArrayBufferObject.cpp @@ -821,6 +821,9 @@ ArrayBufferObject::obj_trace(JSTracer *trc, JSObject *obj) obj->setPrivateUnbarriered(delegate); } + if (!IS_GC_MARKING_TRACER(trc) && !trc->runtime->isHeapMinorCollecting()) + return; + // ArrayBufferObjects need to maintain a list of possibly-weak pointers to // their views. The straightforward way to update the weak pointers would // be in the views' finalizers, but giving views finalizers means they @@ -834,69 +837,55 @@ ArrayBufferObject::obj_trace(JSTracer *trc, JSObject *obj) // then swept to prune out their dead views. ArrayBufferObject &buffer = AsArrayBuffer(obj); - ArrayBufferViewObject *viewsHead = GetViewList(&buffer); + ArrayBufferViewObject *viewsHead = UpdateObjectIfRelocated(trc->runtime, + &GetViewListRef(&buffer)); if (!viewsHead) return; - // During minor collections, mark weak pointers on the buffer strongly. - if (trc->runtime->isHeapMinorCollecting()) { - MarkObject(trc, &GetViewListRef(&buffer), "arraybuffer.viewlist"); - ArrayBufferViewObject *prior = GetViewList(&buffer); - for (ArrayBufferViewObject *view = prior->nextView(); - view; - prior = view, view = view->nextView()) - { - MarkObjectUnbarriered(trc, &view, "arraybuffer.views"); - prior->setNextView(view); - } - return; - } - + viewsHead = UpdateObjectIfRelocated(trc->runtime, &GetViewListRef(&buffer)); ArrayBufferViewObject *firstView = viewsHead; if (firstView->nextView() == nullptr) { // Single view: mark it, but only if we're actually doing a GC pass // right now. Otherwise, the tracing pass for barrier verification will // fail if we add another view and the pointer becomes weak. - if (IS_GC_MARKING_TRACER(trc)) - MarkObject(trc, &GetViewListRef(&buffer), "arraybuffer.singleview"); + MarkObject(trc, &GetViewListRef(&buffer), "arraybuffer.singleview"); } else { // Multiple views: do not mark, but append buffer to list. - if (IS_GC_MARKING_TRACER(trc)) { - // obj_trace may be called multiple times before sweep(), so avoid - // adding this buffer to the list multiple times. - if (firstView->bufferLink() == UNSET_BUFFER_LINK) { - JS_ASSERT(obj->compartment() == firstView->compartment()); - ArrayBufferObject **bufList = &obj->compartment()->gcLiveArrayBuffers; - firstView->setBufferLink(*bufList); - *bufList = &AsArrayBuffer(obj); - } else { + // obj_trace may be called multiple times before sweep(), so avoid + // adding this buffer to the list multiple times. + if (firstView->bufferLink() == UNSET_BUFFER_LINK) { + JS_ASSERT(obj->compartment() == firstView->compartment()); + ArrayBufferObject **bufList = &obj->compartment()->gcLiveArrayBuffers; + firstView->setBufferLink(*bufList); + *bufList = &AsArrayBuffer(obj); + } else { #ifdef DEBUG - bool found = false; - for (ArrayBufferObject *p = obj->compartment()->gcLiveArrayBuffers; - p; - p = GetViewList(p)->bufferLink()) + bool found = false; + for (ArrayBufferObject *p = obj->compartment()->gcLiveArrayBuffers; + p; + p = GetViewList(p)->bufferLink()) + { + if (p == obj) { - if (p == obj) - { - JS_ASSERT(!found); - found = true; - } + JS_ASSERT(!found); + found = true; } -#endif } +#endif } } } -void +/* static */ void ArrayBufferObject::sweep(JSCompartment *compartment) { + JSRuntime *rt = compartment->runtimeFromMainThread(); ArrayBufferObject *buffer = compartment->gcLiveArrayBuffers; JS_ASSERT(buffer != UNSET_BUFFER_LINK); compartment->gcLiveArrayBuffers = nullptr; while (buffer) { - ArrayBufferViewObject *viewsHead = GetViewList(buffer); + ArrayBufferViewObject *viewsHead = UpdateObjectIfRelocated(rt, &GetViewListRef(buffer)); JS_ASSERT(viewsHead); ArrayBufferObject *nextBuffer = viewsHead->bufferLink(); @@ -914,7 +903,7 @@ ArrayBufferObject::sweep(JSCompartment *compartment) view->setNextView(prevLiveView); prevLiveView = view; } - view = nextView; + view = UpdateObjectIfRelocated(rt, &nextView); } SetViewList(buffer, prevLiveView); diff --git a/js/src/vm/ObjectImpl.cpp b/js/src/vm/ObjectImpl.cpp index 5879c2e248e..7132303368a 100644 --- a/js/src/vm/ObjectImpl.cpp +++ b/js/src/vm/ObjectImpl.cpp @@ -153,6 +153,19 @@ static const ObjectElements emptyElementsHeader(0, 0); HeapSlot *const js::emptyObjectElements = reinterpret_cast(uintptr_t(&emptyElementsHeader) + sizeof(ObjectElements)); +#ifdef DEBUG + +bool +ObjectImpl::canHaveNonEmptyElements() +{ + JSObject *obj = static_cast(this); + if (isNative()) + return !obj->is(); + return obj->is() || obj->is(); +} + +#endif // DEBUG + /* static */ bool ObjectElements::ConvertElementsToDoubles(JSContext *cx, uintptr_t elementsPtr) { diff --git a/js/src/vm/ObjectImpl.h b/js/src/vm/ObjectImpl.h index 37964bb2f82..dad2f0ae542 100644 --- a/js/src/vm/ObjectImpl.h +++ b/js/src/vm/ObjectImpl.h @@ -684,7 +684,8 @@ ArraySetLength(typename ExecutionModeTraits::ContextType cx, unsigned attrs, HandleValue value, bool setterIsStrict); /* - * Elements header used for all native objects. The elements component of such + * Elements header used for all objects other than non-native objects (except + * for ArrayBufferObjects!!!) and typed arrays. The elements component of such * objects offers an efficient representation for all or some of the indexed * properties of the object, using a flat array of Values rather than a shape * hierarchy stored in the object's slots. This structure is immediately @@ -1457,7 +1458,14 @@ class ObjectImpl : public gc::BarrieredCell return &fixedSlots()[2]; } - void setFixedElements() { this->elements = fixedElements(); } +#ifdef DEBUG + bool canHaveNonEmptyElements(); +#endif + + void setFixedElements() { + JS_ASSERT(canHaveNonEmptyElements()); + this->elements = fixedElements(); + } inline bool hasDynamicElements() const { /* diff --git a/js/src/vm/OldDebugAPI.cpp b/js/src/vm/OldDebugAPI.cpp index bdba177c631..7b445f2bad2 100644 --- a/js/src/vm/OldDebugAPI.cpp +++ b/js/src/vm/OldDebugAPI.cpp @@ -318,7 +318,7 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj_, jsid id_, return false; } - if (!obj->isNative()) { + if (!obj->isNative() || obj->is()) { JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_WATCH, obj->getClass()->name); return false; diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp index ce91b8795e1..5da68ef948d 100644 --- a/js/src/vm/SelfHosting.cpp +++ b/js/src/vm/SelfHosting.cpp @@ -414,22 +414,21 @@ js::intrinsic_UnsafePutElements(JSContext *cx, unsigned argc, Value *vp) uint32_t elemi = base+2; JS_ASSERT(args[arri].isObject()); - JS_ASSERT(args[arri].toObject().isNative() || - args[arri].toObject().is()); + JS_ASSERT(args[arri].toObject().isNative()); JS_ASSERT(args[idxi].isInt32()); RootedObject arrobj(cx, &args[arri].toObject()); uint32_t idx = args[idxi].toInt32(); - if (arrobj->isNative()) { - JS_ASSERT(idx < arrobj->getDenseInitializedLength()); - arrobj->setDenseElementWithType(cx, idx, args[elemi]); - } else { + if (arrobj->is()) { JS_ASSERT(idx < arrobj->as().length()); RootedValue tmp(cx, args[elemi]); // XXX: Always non-strict. if (!JSObject::setElement(cx, arrobj, arrobj, idx, &tmp, false)) return false; + } else { + JS_ASSERT(idx < arrobj->getDenseInitializedLength()); + arrobj->setDenseElementWithType(cx, idx, args[elemi]); } } diff --git a/js/src/vm/Shape-inl.h b/js/src/vm/Shape-inl.h index afed46fce6d..68d6eb9e022 100644 --- a/js/src/vm/Shape-inl.h +++ b/js/src/vm/Shape-inl.h @@ -15,6 +15,7 @@ #include "vm/Interpreter.h" #include "vm/ScopeObject.h" +#include "vm/TypedArrayObject.h" #include "jsatominlines.h" #include "jscntxtinlines.h" @@ -204,6 +205,20 @@ AutoRooterGetterSetter::AutoRooterGetterSetter(ThreadSafeContext *cx, uint8_t at MOZ_GUARD_OBJECT_NOTIFIER_INIT; } +static inline uint8_t +GetShapeAttributes(JSObject *obj, Shape *shape) +{ + JS_ASSERT(obj->isNative()); + + if (IsImplicitDenseOrTypedArrayElement(shape)) { + if (obj->is()) + return JSPROP_ENUMERATE | JSPROP_PERMANENT; + return JSPROP_ENUMERATE; + } + + return shape->attributes(); +} + } /* namespace js */ #endif /* vm_Shape_inl_h */ diff --git a/js/src/vm/Shape.h b/js/src/vm/Shape.h index 061ee52ba4c..0b35862b3a5 100644 --- a/js/src/vm/Shape.h +++ b/js/src/vm/Shape.h @@ -1660,23 +1660,17 @@ MarkNonNativePropertyFound(MutableHandleShape propp) template static inline void -MarkDenseElementFound(typename MaybeRooted::MutableHandleType propp) +MarkDenseOrTypedArrayElementFound(typename MaybeRooted::MutableHandleType propp) { propp.set(reinterpret_cast(1)); } static inline bool -IsImplicitDenseElement(Shape *prop) +IsImplicitDenseOrTypedArrayElement(Shape *prop) { return prop == reinterpret_cast(1); } -static inline uint8_t -GetShapeAttributes(HandleShape shape) -{ - return IsImplicitDenseElement(shape) ? JSPROP_ENUMERATE : shape->attributes(); -} - } // namespace js #ifdef _MSC_VER diff --git a/js/src/vm/Stack-inl.h b/js/src/vm/Stack-inl.h index cac4a8362b9..ed0cf59598d 100644 --- a/js/src/vm/Stack-inl.h +++ b/js/src/vm/Stack-inl.h @@ -134,10 +134,11 @@ StackFrame::unaliasedActual(unsigned i, MaybeCheckAliasing checkAliasing) template inline void -StackFrame::forEachUnaliasedActual(Op op) +StackFrame::unaliasedForEachActual(Op op) { - JS_ASSERT(!script()->funHasAnyAliasedFormal()); - JS_ASSERT(!script()->needsArgsObj()); + // Don't assert !script()->funHasAnyAliasedFormal() since this function is + // called from ArgumentsObject::createUnexpected() which can access aliased + // slots. const Value *argsEnd = argv() + numActualArgs(); for (const Value *p = argv(); p < argsEnd; ++p) @@ -325,17 +326,28 @@ InterpreterStack::popInlineFrame(FrameRegs ®s) template inline void -ScriptFrameIter::ionForEachCanonicalActualArg(JSContext *cx, Op op) +ScriptFrameIter::unaliasedForEachActual(JSContext *cx, Op op) { - JS_ASSERT(isJit()); + switch (data_.state_) { + case DONE: + break; + case SCRIPTED: + interpFrame()->unaliasedForEachActual(op); + return; + case JIT: #ifdef JS_ION - if (data_.ionFrames_.isOptimizedJS()) { - ionInlineFrames_.forEachCanonicalActualArg(cx, op, jit::ReadFrame_Actuals); - } else { - JS_ASSERT(data_.ionFrames_.isBaselineJS()); - data_.ionFrames_.forEachCanonicalActualArg(op, jit::ReadFrame_Actuals); - } + if (data_.ionFrames_.isOptimizedJS()) { + ionInlineFrames_.unaliasedForEachActual(cx, op, jit::ReadFrame_Actuals); + } else { + JS_ASSERT(data_.ionFrames_.isBaselineJS()); + data_.ionFrames_.unaliasedForEachActual(op, jit::ReadFrame_Actuals); + } + return; +#else + break; #endif + } + MOZ_ASSUME_UNREACHABLE("Unexpected state"); } inline void * diff --git a/js/src/vm/Stack.h b/js/src/vm/Stack.h index 791c6aebb41..12d44caff92 100644 --- a/js/src/vm/Stack.h +++ b/js/src/vm/Stack.h @@ -215,6 +215,7 @@ class AbstractFramePtr inline Value &unaliasedLocal(uint32_t i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING); inline Value &unaliasedFormal(unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING); inline Value &unaliasedActual(unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING); + template inline void unaliasedForEachActual(JSContext *cx, Op op); inline bool prevUpToDate() const; inline void setPrevUpToDate() const; @@ -530,18 +531,13 @@ class StackFrame bool hasArgs() const { return isNonEvalFunctionFrame(); } inline Value &unaliasedFormal(unsigned i, MaybeCheckAliasing = CHECK_ALIASING); inline Value &unaliasedActual(unsigned i, MaybeCheckAliasing = CHECK_ALIASING); - template inline void forEachUnaliasedActual(Op op); + template inline void unaliasedForEachActual(Op op); bool copyRawFrameSlots(AutoValueVector *v); unsigned numFormalArgs() const { JS_ASSERT(hasArgs()); return fun()->nargs(); } unsigned numActualArgs() const { JS_ASSERT(hasArgs()); return u.nactual; } - inline Value &canonicalActualArg(unsigned i) const; - template - inline bool forEachCanonicalActualArg(Op op, unsigned start = 0, unsigned count = unsigned(-1)); - template inline bool forEachFormalArg(Op op); - /* * Arguments object * @@ -1566,6 +1562,7 @@ class ScriptFrameIter unsigned numActualArgs() const; unsigned numFormalArgs() const { return script()->functionNonDelazifying()->nargs(); } Value unaliasedActual(unsigned i, MaybeCheckAliasing = CHECK_ALIASING) const; + template inline void unaliasedForEachActual(JSContext *cx, Op op); JSObject *scopeChain() const; CallObject &callObj() const; @@ -1587,9 +1584,6 @@ class ScriptFrameIter // These are only valid for the top frame. size_t numFrameSlots() const; Value frameSlotValue(size_t index) const; - - template - inline void ionForEachCanonicalActualArg(JSContext *cx, Op op); }; #ifdef DEBUG diff --git a/js/src/vm/TypedArrayObject.cpp b/js/src/vm/TypedArrayObject.cpp index 07b3e5e54c9..0ab33bc67d7 100644 --- a/js/src/vm/TypedArrayObject.cpp +++ b/js/src/vm/TypedArrayObject.cpp @@ -50,7 +50,9 @@ using namespace js::gc; using namespace js::types; using mozilla::IsNaN; +using mozilla::NegativeInfinity; using mozilla::PodCopy; +using mozilla::PositiveInfinity; using JS::CanonicalizeNaN; using JS::GenericNaN; @@ -117,77 +119,6 @@ TypedArrayObject::sharedBuffer() const return &bufferValue(const_cast(this)).toObject().as(); } -bool -TypedArrayObject::obj_lookupGeneric(JSContext *cx, HandleObject tarray, HandleId id, - MutableHandleObject objp, MutableHandleShape propp) -{ - if (tarray->as().isArrayIndex(id)) { - MarkNonNativePropertyFound(propp); - objp.set(tarray); - return true; - } - - RootedObject proto(cx, tarray->getProto()); - if (!proto) { - objp.set(nullptr); - propp.set(nullptr); - return true; - } - - return JSObject::lookupGeneric(cx, proto, id, objp, propp); -} - -bool -TypedArrayObject::obj_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, - MutableHandleObject objp, MutableHandleShape propp) -{ - Rooted id(cx, NameToId(name)); - return obj_lookupGeneric(cx, obj, id, objp, propp); -} - -bool -TypedArrayObject::obj_lookupElement(JSContext *cx, HandleObject tarray, uint32_t index, - MutableHandleObject objp, MutableHandleShape propp) -{ - if (index < tarray->as().length()) { - MarkNonNativePropertyFound(propp); - objp.set(tarray); - return true; - } - - RootedObject proto(cx, tarray->getProto()); - if (proto) - return JSObject::lookupElement(cx, proto, index, objp, propp); - - objp.set(nullptr); - propp.set(nullptr); - return true; -} - -bool -TypedArrayObject::obj_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, - MutableHandleObject objp, MutableHandleShape propp) -{ - Rooted id(cx, SPECIALID_TO_JSID(sid)); - return obj_lookupGeneric(cx, obj, id, objp, propp); -} - -bool -TypedArrayObject::obj_getGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, - unsigned *attrsp) -{ - *attrsp = JSPROP_PERMANENT | JSPROP_ENUMERATE; - return true; -} - -bool -TypedArrayObject::obj_setGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, - unsigned *attrsp) -{ - JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_SET_ARRAY_ATTRS); - return false; -} - /* static */ int TypedArrayObject::lengthOffset() { @@ -235,8 +166,8 @@ js::ClampDoubleToUint8(const double x) return y; } -bool -js::ToDoubleForTypedArray(JSContext *cx, JS::HandleValue vp, double *d) +static bool +ToDoubleForTypedArray(ThreadSafeContext *cx, const Value &vp, double *d) { if (vp.isDouble()) { *d = vp.toDouble(); @@ -245,7 +176,7 @@ js::ToDoubleForTypedArray(JSContext *cx, JS::HandleValue vp, double *d) } else if (vp.isPrimitive()) { JS_ASSERT(vp.isString() || vp.isUndefined() || vp.isBoolean()); if (vp.isString()) { - if (!ToNumber(cx, vp, d)) + if (!StringToNumber(cx, vp.toString(), d)) return false; } else if (vp.isUndefined()) { *d = GenericNaN(); @@ -312,83 +243,18 @@ class TypedArrayObjectTemplate : public TypedArrayObject } static bool - obj_getProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandlePropertyName name, - MutableHandleValue vp) - { - RootedObject proto(cx, obj->getProto()); - if (!proto) { - vp.setUndefined(); - return true; - } - - return JSObject::getProperty(cx, proto, receiver, name, vp); - } - - static bool - obj_getElement(JSContext *cx, HandleObject tarray, HandleObject receiver, uint32_t index, - MutableHandleValue vp) - { - if (index < tarray->as().length()) { - copyIndexToValue(tarray, index, vp); - return true; - } - - vp.setUndefined(); - return true; - } - - static bool - obj_getSpecial(JSContext *cx, HandleObject obj, HandleObject receiver, HandleSpecialId sid, - MutableHandleValue vp) - { - RootedObject proto(cx, obj->getProto()); - if (!proto) { - vp.setUndefined(); - return true; - } - - return JSObject::getSpecial(cx, proto, receiver, sid, vp); - } - - static bool - obj_getGeneric(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id, - MutableHandleValue vp) - { - RootedValue idval(cx, IdToValue(id)); - - uint32_t index; - if (IsDefinitelyIndex(idval, &index)) - return obj_getElement(cx, obj, receiver, index, vp); - - Rooted sid(cx); - if (ValueIsSpecial(obj, &idval, &sid, cx)) - return obj_getSpecial(cx, obj, receiver, sid, vp); - - JSAtom *atom = ToAtom(cx, idval); - if (!atom) - return false; - - if (atom->isIndex(&index)) - return obj_getElement(cx, obj, receiver, index, vp); - - Rooted name(cx, atom->asPropertyName()); - return obj_getProperty(cx, obj, receiver, name, vp); - } - - static bool - setElementTail(JSContext *cx, HandleObject tarray, uint32_t index, - MutableHandleValue vp, bool strict) + setIndexValue(ThreadSafeContext *cx, JSObject *tarray, uint32_t index, const Value &value) { JS_ASSERT(tarray); JS_ASSERT(index < tarray->as().length()); - if (vp.isInt32()) { - setIndex(tarray, index, NativeType(vp.toInt32())); + if (value.isInt32()) { + setIndex(tarray, index, NativeType(value.toInt32())); return true; } double d; - if (!ToDoubleForTypedArray(cx, vp, &d)) + if (!ToDoubleForTypedArray(cx, value, &d)) return false; // If the array is an integer array, we only handle up to @@ -415,150 +281,6 @@ class TypedArrayObjectTemplate : public TypedArrayObject return true; } - static bool - obj_setGeneric(JSContext *cx, HandleObject tarray, HandleId id, - MutableHandleValue vp, bool strict) - { - uint32_t index; - // We can't just chain to js_SetPropertyHelper, because we're not a normal object. - if (!tarray->as().isArrayIndex(id, &index)) { - // Silent ignore is better than an exception here, because - // at some point we may want to support other properties on - // these objects. This is especially true when these arrays - // are used to implement HTML Canvas 2D's PixelArray objects, - // which used to be plain old arrays. - vp.setUndefined(); - return true; - } - - return setElementTail(cx, tarray, index, vp, strict); - } - - static bool - obj_setProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, - MutableHandleValue vp, bool strict) - { - Rooted id(cx, NameToId(name)); - return obj_setGeneric(cx, obj, id, vp, strict); - } - - static bool - obj_setElement(JSContext *cx, HandleObject tarray, uint32_t index, - MutableHandleValue vp, bool strict) - { - if (index >= tarray->as().length()) { - // Silent ignore is better than an exception here, because - // at some point we may want to support other properties on - // these objects. This is especially true when these arrays - // are used to implement HTML Canvas 2D's PixelArray objects, - // which used to be plain old arrays. - vp.setUndefined(); - return true; - } - - return setElementTail(cx, tarray, index, vp, strict); - } - - static bool - obj_setSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, - MutableHandleValue vp, bool strict) - { - Rooted id(cx, SPECIALID_TO_JSID(sid)); - return obj_setGeneric(cx, obj, id, vp, strict); - } - - static bool - obj_defineGeneric(JSContext *cx, HandleObject obj, HandleId id, HandleValue v, - PropertyOp getter, StrictPropertyOp setter, unsigned attrs) - { - RootedValue tmp(cx, v); - return obj_setGeneric(cx, obj, id, &tmp, false); - } - - static bool - obj_defineProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue v, - PropertyOp getter, StrictPropertyOp setter, unsigned attrs) - { - Rooted id(cx, NameToId(name)); - return obj_defineGeneric(cx, obj, id, v, getter, setter, attrs); - } - - static bool - obj_defineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue v, - PropertyOp getter, StrictPropertyOp setter, unsigned attrs) - { - RootedValue tmp(cx, v); - return obj_setElement(cx, obj, index, &tmp, false); - } - - static bool - obj_defineSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, HandleValue v, - PropertyOp getter, StrictPropertyOp setter, unsigned attrs) - { - Rooted id(cx, SPECIALID_TO_JSID(sid)); - return obj_defineGeneric(cx, obj, id, v, getter, setter, attrs); - } - - static bool - obj_deleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, bool *succeeded) - { - *succeeded = true; - return true; - } - - static bool - obj_deleteElement(JSContext *cx, HandleObject tarray, uint32_t index, bool *succeeded) - { - if (index < tarray->as().length()) { - *succeeded = false; - return true; - } - - *succeeded = true; - return true; - } - - static bool - obj_deleteSpecial(JSContext *cx, HandleObject tarray, HandleSpecialId sid, bool *succeeded) - { - *succeeded = true; - return true; - } - - static bool - obj_enumerate(JSContext *cx, HandleObject tarray, JSIterateOp enum_op, - MutableHandleValue statep, MutableHandleId idp) - { - JS_ASSERT(tarray->is()); - - uint32_t index; - switch (enum_op) { - case JSENUMERATE_INIT_ALL: - case JSENUMERATE_INIT: - statep.setInt32(0); - idp.set(::INT_TO_JSID(tarray->as().length())); - break; - - case JSENUMERATE_NEXT: { - index = static_cast(statep.toInt32()); - uint32_t length = tarray->as().length(); - if (index < length) { - idp.set(::INT_TO_JSID(index)); - statep.setInt32(index + 1); - } else { - JS_ASSERT(index == length); - statep.setNull(); - } - break; - } - case JSENUMERATE_DESTROY: - statep.setNull(); - break; - } - - return true; - } - static TypedArrayObject * makeProtoInstance(JSContext *cx, HandleObject proto) { @@ -629,16 +351,9 @@ class TypedArrayObjectTemplate : public TypedArrayObject obj->setSlot(NEXT_VIEW_SLOT, PrivateValue(nullptr)); obj->setSlot(NEXT_BUFFER_SLOT, PrivateValue(UNSET_BUFFER_LINK)); - // Mark the object as non-extensible. We cannot simply call - // obj->preventExtensions() because that has to iterate through all - // properties, and on long arrays that is much too slow. We could - // initialize the length fields to zero to avoid that, but then it - // would just boil down to a slightly slower wrapper around the - // following code anyway: js::Shape *empty = EmptyShape::getInitialShape(cx, fastClass(), obj->getProto(), obj->getParent(), obj->getMetadata(), - gc::FINALIZE_OBJECT8_BACKGROUND, - BaseShape::NOT_EXTENSIBLE); + gc::FINALIZE_OBJECT8_BACKGROUND); if (!empty) return nullptr; obj->setLastPropertyInfallible(empty); @@ -1118,7 +833,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject *(static_cast(obj->as().viewData()) + index) = val; } - static void copyIndexToValue(JSObject *tarray, uint32_t index, MutableHandleValue vp); + static Value getIndexValue(JSObject *tarray, uint32_t index); static JSObject * createSubarray(JSContext *cx, HandleObject tarrayArg, uint32_t begin, uint32_t end) @@ -1509,40 +1224,35 @@ ArrayBufferObject::createTypedArrayFromBuffer(JSContext *cx, unsigned argc, Valu // this default implementation is only valid for integer types // less than 32-bits in size. template -void -TypedArrayObjectTemplate::copyIndexToValue(JSObject *tarray, uint32_t index, - MutableHandleValue vp) +Value +TypedArrayObjectTemplate::getIndexValue(JSObject *tarray, uint32_t index) { JS_STATIC_ASSERT(sizeof(NativeType) < 4); - vp.setInt32(getIndex(tarray, index)); + return Int32Value(getIndex(tarray, index)); } namespace { // and we need to specialize for 32-bit integers and floats template<> -void -TypedArrayObjectTemplate::copyIndexToValue(JSObject *tarray, uint32_t index, - MutableHandleValue vp) +Value +TypedArrayObjectTemplate::getIndexValue(JSObject *tarray, uint32_t index) { - int32_t val = getIndex(tarray, index); - vp.setInt32(val); + return Int32Value(getIndex(tarray, index)); } template<> -void -TypedArrayObjectTemplate::copyIndexToValue(JSObject *tarray, uint32_t index, - MutableHandleValue vp) +Value +TypedArrayObjectTemplate::getIndexValue(JSObject *tarray, uint32_t index) { uint32_t val = getIndex(tarray, index); - vp.setNumber(val); + return NumberValue(val); } template<> -void -TypedArrayObjectTemplate::copyIndexToValue(JSObject *tarray, uint32_t index, - MutableHandleValue vp) +Value +TypedArrayObjectTemplate::getIndexValue(JSObject *tarray, uint32_t index) { float val = getIndex(tarray, index); double dval = val; @@ -1557,13 +1267,12 @@ TypedArrayObjectTemplate::copyIndexToValue(JSObject *tarray, uint32_t ind * This could be removed for platforms/compilers known to convert a 32-bit * non-canonical nan to a 64-bit canonical nan. */ - vp.setDouble(CanonicalizeNaN(dval)); + return DoubleValue(CanonicalizeNaN(dval)); } template<> -void -TypedArrayObjectTemplate::copyIndexToValue(JSObject *tarray, uint32_t index, - MutableHandleValue vp) +Value +TypedArrayObjectTemplate::getIndexValue(JSObject *tarray, uint32_t index) { double val = getIndex(tarray, index); @@ -1574,7 +1283,7 @@ TypedArrayObjectTemplate::copyIndexToValue(JSObject *tarray, uint32_t in * confuse the engine into interpreting a double-typed jsval as an * object-typed jsval. */ - vp.setDouble(CanonicalizeNaN(val)); + return DoubleValue(CanonicalizeNaN(val)); } } /* anonymous namespace */ @@ -2228,38 +1937,77 @@ DataViewObject::fun_setFloat64(JSContext *cx, unsigned argc, Value *vp) return CallNonGenericMethod(cx, args); } -void -TypedArrayObject::copyTypedArrayElement(uint32_t index, MutableHandleValue vp) +Value +TypedArrayObject::getElement(uint32_t index) { JS_ASSERT(index < length()); switch (type()) { case ScalarTypeDescr::TYPE_INT8: - TypedArrayObjectTemplate::copyIndexToValue(this, index, vp); + return TypedArrayObjectTemplate::getIndexValue(this, index); break; case ScalarTypeDescr::TYPE_UINT8: - TypedArrayObjectTemplate::copyIndexToValue(this, index, vp); + return TypedArrayObjectTemplate::getIndexValue(this, index); break; case ScalarTypeDescr::TYPE_UINT8_CLAMPED: - TypedArrayObjectTemplate::copyIndexToValue(this, index, vp); + return TypedArrayObjectTemplate::getIndexValue(this, index); break; case ScalarTypeDescr::TYPE_INT16: - TypedArrayObjectTemplate::copyIndexToValue(this, index, vp); + return TypedArrayObjectTemplate::getIndexValue(this, index); break; case ScalarTypeDescr::TYPE_UINT16: - TypedArrayObjectTemplate::copyIndexToValue(this, index, vp); + return TypedArrayObjectTemplate::getIndexValue(this, index); break; case ScalarTypeDescr::TYPE_INT32: - TypedArrayObjectTemplate::copyIndexToValue(this, index, vp); + return TypedArrayObjectTemplate::getIndexValue(this, index); break; case ScalarTypeDescr::TYPE_UINT32: - TypedArrayObjectTemplate::copyIndexToValue(this, index, vp); + return TypedArrayObjectTemplate::getIndexValue(this, index); break; case ScalarTypeDescr::TYPE_FLOAT32: - TypedArrayObjectTemplate::copyIndexToValue(this, index, vp); + return TypedArrayObjectTemplate::getIndexValue(this, index); break; case ScalarTypeDescr::TYPE_FLOAT64: - TypedArrayObjectTemplate::copyIndexToValue(this, index, vp); + return TypedArrayObjectTemplate::getIndexValue(this, index); + break; + default: + MOZ_ASSUME_UNREACHABLE("Unknown TypedArray type"); + break; + } +} + +bool +TypedArrayObject::setElement(ThreadSafeContext *cx, uint32_t index, const Value &value) +{ + JS_ASSERT(index < length()); + + switch (type()) { + case ScalarTypeDescr::TYPE_INT8: + return TypedArrayObjectTemplate::setIndexValue(cx, this, index, value); + break; + case ScalarTypeDescr::TYPE_UINT8: + return TypedArrayObjectTemplate::setIndexValue(cx, this, index, value); + break; + case ScalarTypeDescr::TYPE_UINT8_CLAMPED: + return TypedArrayObjectTemplate::setIndexValue(cx, this, index, value); + break; + case ScalarTypeDescr::TYPE_INT16: + return TypedArrayObjectTemplate::setIndexValue(cx, this, index, value); + break; + case ScalarTypeDescr::TYPE_UINT16: + return TypedArrayObjectTemplate::setIndexValue(cx, this, index, value); + break; + case ScalarTypeDescr::TYPE_INT32: + return TypedArrayObjectTemplate::setIndexValue(cx, this, index, value); + break; + case ScalarTypeDescr::TYPE_UINT32: + return TypedArrayObjectTemplate::setIndexValue(cx, this, index, value); + break; + case ScalarTypeDescr::TYPE_FLOAT32: + return TypedArrayObjectTemplate::setIndexValue(cx, this, index, value); + break; + case ScalarTypeDescr::TYPE_FLOAT64: + return TypedArrayObjectTemplate::setIndexValue(cx, this, index, value); break; default: MOZ_ASSUME_UNREACHABLE("Unknown TypedArray type"); @@ -2376,8 +2124,7 @@ IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Float64, double, double) #_typedArray, \ JSCLASS_HAS_RESERVED_SLOTS(TypedArrayObject::RESERVED_SLOTS) | \ JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | \ - JSCLASS_HAS_CACHED_PROTO(JSProto_##_typedArray) | \ - Class::NON_NATIVE, \ + JSCLASS_HAS_CACHED_PROTO(JSProto_##_typedArray), \ JS_PropertyStub, /* addProperty */ \ JS_DeletePropertyStub, /* delProperty */ \ JS_PropertyStub, /* getProperty */ \ @@ -2390,35 +2137,6 @@ IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Float64, double, double) nullptr, /* hasInstance */ \ nullptr, /* construct */ \ ArrayBufferViewObject::trace, /* trace */ \ - JS_NULL_CLASS_SPEC, \ - JS_NULL_CLASS_EXT, \ - { \ - _typedArray##Object::obj_lookupGeneric, \ - _typedArray##Object::obj_lookupProperty, \ - _typedArray##Object::obj_lookupElement, \ - _typedArray##Object::obj_lookupSpecial, \ - _typedArray##Object::obj_defineGeneric, \ - _typedArray##Object::obj_defineProperty, \ - _typedArray##Object::obj_defineElement, \ - _typedArray##Object::obj_defineSpecial, \ - _typedArray##Object::obj_getGeneric, \ - _typedArray##Object::obj_getProperty, \ - _typedArray##Object::obj_getElement, \ - _typedArray##Object::obj_getSpecial, \ - _typedArray##Object::obj_setGeneric, \ - _typedArray##Object::obj_setProperty, \ - _typedArray##Object::obj_setElement, \ - _typedArray##Object::obj_setSpecial, \ - _typedArray##Object::obj_getGenericAttributes, \ - _typedArray##Object::obj_setGenericAttributes, \ - _typedArray##Object::obj_deleteProperty, \ - _typedArray##Object::obj_deleteElement, \ - _typedArray##Object::obj_deleteSpecial, \ - nullptr, nullptr, /* watch/unwatch */ \ - nullptr, /* slice */ \ - _typedArray##Object::obj_enumerate, \ - nullptr, /* thisObject */ \ - } \ } template @@ -2583,7 +2301,6 @@ const Class DataViewObject::class_ = { "DataView", JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | - /* Bug 886622: Consider making this Class NON_NATIVE. */ JSCLASS_HAS_RESERVED_SLOTS(DataViewObject::RESERVED_SLOTS) | JSCLASS_HAS_CACHED_PROTO(JSProto_DataView), JS_PropertyStub, /* addProperty */ @@ -2782,6 +2499,58 @@ js::AsTypedArrayBuffer(HandleValue v) return v.toObject().as(); } +bool +js::StringIsTypedArrayIndex(JSLinearString *str, double *indexp) +{ + // Largest double (2^53 - 1) which can be exactly represented in the + // mantissa of a double. + static const double MAX_INTEGER = 9007199254740991; + + const jschar *s = str->chars(); + const jschar *end = s + str->length(); + + if (s == end) + return false; + + bool negative = false; + if (*s == '-') { + negative = true; + if (++s == end) + return false; + } + + if (!JS7_ISDEC(*s)) + return false; + + double index = 0; + uint32_t digit = JS7_UNDEC(*s++); + + /* Don't allow leading zeros. */ + if (digit == 0 && s != end) + return false; + + index = digit; + + for (; s < end; s++) { + if (!JS7_ISDEC(*s)) + return false; + + digit = JS7_UNDEC(*s); + + /* Watch for mantissa overflows. */ + if ((MAX_INTEGER - digit) / 10 < index) + return false; + + index = 10 * index + digit; + } + + if (negative) + index = -index; + + *indexp = index; + return true; +} + /* JS Friend API */ JS_FRIEND_API(bool) diff --git a/js/src/vm/TypedArrayObject.h b/js/src/vm/TypedArrayObject.h index 79daa3dd415..bb7fb999b54 100644 --- a/js/src/vm/TypedArrayObject.h +++ b/js/src/vm/TypedArrayObject.h @@ -40,20 +40,6 @@ class TypedArrayObject : public ArrayBufferViewObject static const Class classes[ScalarTypeDescr::TYPE_MAX]; static const Class protoClasses[ScalarTypeDescr::TYPE_MAX]; - static bool obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, - MutableHandleObject objp, MutableHandleShape propp); - static bool obj_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, - MutableHandleObject objp, MutableHandleShape propp); - static bool obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, - MutableHandleObject objp, MutableHandleShape propp); - static bool obj_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, - MutableHandleObject objp, MutableHandleShape propp); - - static bool obj_getGenericAttributes(JSContext *cx, HandleObject obj, - HandleId id, unsigned *attrsp); - static bool obj_setGenericAttributes(JSContext *cx, HandleObject obj, - HandleId id, unsigned *attrsp); - static Value bufferValue(TypedArrayObject *tarr) { return tarr->getFixedSlot(BUFFER_SLOT); } @@ -92,7 +78,8 @@ class TypedArrayObject : public ArrayBufferViewObject } inline bool isArrayIndex(jsid id, uint32_t *ip = nullptr); - void copyTypedArrayElement(uint32_t index, MutableHandleValue vp); + Value getElement(uint32_t index); + bool setElement(ThreadSafeContext *cx, uint32_t index, const Value &value); void neuter(JSContext *cx); @@ -153,6 +140,25 @@ IsTypedArrayBuffer(HandleValue v); ArrayBufferObject & AsTypedArrayBuffer(HandleValue v); +bool +StringIsTypedArrayIndex(JSLinearString *str, double *indexp); + +inline bool +IsTypedArrayIndex(jsid id, double *indexp) +{ + if (JSID_IS_INT(id)) { + int32_t i = JSID_TO_INT(id); + JS_ASSERT(i >= 0); + *indexp = (double)i; + return true; + } + + if (MOZ_UNLIKELY(!JSID_IS_STRING(id))) + return false; + + return StringIsTypedArrayIndex(JSID_TO_ATOM(id), indexp); +} + static inline unsigned TypedArrayShift(ArrayBufferView::ViewType viewType) { @@ -322,8 +328,6 @@ ClampIntForUint8Array(int32_t x) return x; } -bool ToDoubleForTypedArray(JSContext *cx, JS::HandleValue vp, double *d); - extern js::ArrayBufferObject * const UNSET_BUFFER_LINK; } // namespace js diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp index d4a0368860c..e595db32d69 100644 --- a/js/xpconnect/src/XPCComponents.cpp +++ b/js/xpconnect/src/XPCComponents.cpp @@ -26,6 +26,7 @@ #include "nsZipArchive.h" #include "nsIDOMFile.h" #include "nsIDOMFileList.h" +#include "nsWindowMemoryReporter.h" using namespace mozilla; using namespace JS; diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index 07bd269768a..53ae0d67b31 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -1412,8 +1412,7 @@ XPCJSRuntime::OutOfMemoryCallback(JSContext *cx) // If this fails, it fails silently. dumper->DumpMemoryInfoToTempDir(NS_LITERAL_STRING("due-to-JS-OOM"), - /* minimizeMemoryUsage = */ false, - /* dumpChildProcesses = */ false); + /* minimizeMemoryUsage = */ false); } size_t diff --git a/js/xpconnect/src/event_impl_gen.py b/js/xpconnect/src/event_impl_gen.py index 280113ae588..7be9433a19f 100644 --- a/js/xpconnect/src/event_impl_gen.py +++ b/js/xpconnect/src/event_impl_gen.py @@ -58,10 +58,7 @@ def firstCap(str): return str[0].upper() + str[1:] def getBaseName(iface): - basename = ("%s" % iface.base[6:]) - if (basename == "Event"): - basename = "nsDOMEvent" - return basename + return ("%s" % iface.base[6:]) def print_header_file(fd, conf): fd.write("#ifndef _gen_mozilla_idl_generated_events_h_\n" @@ -88,7 +85,7 @@ def print_classes_file(fd, conf): fd.write("#ifndef _gen_mozilla_idl_generated_event_declarations_h_\n") fd.write("#define _gen_mozilla_idl_generated_event_declarations_h_\n\n") - fd.write("#include \"nsDOMEvent.h\"\n"); + fd.write("#include \"mozilla/dom/Event.h\"\n"); includes = [] for s in conf.special_includes: if not s in includes: @@ -154,12 +151,10 @@ def print_class_declaration(eventname, iface, fd, conf): fd.write(" virtual ~%s();\n\n" % classname) fd.write(" NS_DECL_ISUPPORTS_INHERITED\n") fd.write(" NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(%s, %s)\n" % (classname, basename)) - fd.write(" NS_FORWARD_TO_NSDOMEVENT\n") + fd.write(" NS_FORWARD_TO_EVENT\n") for baseiface in baseinterfaces: baseimpl = ("%s" % baseiface.name[6:]) - if (baseimpl == "Event"): - baseimpl = "nsDOMEvent" fd.write(" NS_FORWARD_%s(%s::)\n" % (baseiface.name.upper(), baseimpl)) fd.write(" NS_DECL_%s\n" % iface.name.upper()) @@ -251,7 +246,7 @@ def print_cpp_file(fd, conf): fd.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n") fd.write('#include "GeneratedEventClasses.h"\n') fd.write('#include "xpcprivate.h"\n'); - fd.write('#include "nsDOMEvent.h"\n'); + fd.write('#include "mozilla/dom/Event.h"\n'); fd.write('#include "mozilla/dom/EventTarget.h"\n'); for e in conf.simple_events: diff --git a/js/xpconnect/src/nsDOMQS.h b/js/xpconnect/src/nsDOMQS.h index 98fe9a56c49..0e3827460a7 100644 --- a/js/xpconnect/src/nsDOMQS.h +++ b/js/xpconnect/src/nsDOMQS.h @@ -16,7 +16,7 @@ #include "nsHTMLDocument.h" #include "nsICSSDeclaration.h" #include "nsSVGElement.h" -#include "nsDOMEvent.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/UIEvent.h" #include "mozilla/dom/MouseEvent.h" #include "mozilla/dom/EventTargetBinding.h" @@ -57,7 +57,7 @@ NEW_BINDING(nsIDocument, Document); NEW_BINDING(nsDocument, Document); NEW_BINDING(nsHTMLDocument, HTMLDocument); NEW_BINDING(nsSVGElement, SVGElement); -NEW_BINDING(nsDOMEvent, Event); +NEW_BINDING(mozilla::dom::Event, Event); NEW_BINDING(mozilla::dom::UIEvent, UIEvent); NEW_BINDING(mozilla::dom::MouseEvent, MouseEvent); diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index e64433d4963..0c7ebd87d12 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -82,6 +82,7 @@ #include "mozilla/GuardObjects.h" #include "mozilla/Maybe.h" #include "mozilla/MemoryReporting.h" +#include "mozilla/TimeStamp.h" #include #include diff --git a/layout/base/RestyleManager.cpp b/layout/base/RestyleManager.cpp index 214257d327e..ba68a22a25a 100644 --- a/layout/base/RestyleManager.cpp +++ b/layout/base/RestyleManager.cpp @@ -34,6 +34,7 @@ #include "nsContentUtils.h" #include "nsIFrameInlines.h" #include "ActiveLayerTracker.h" +#include "nsDisplayList.h" #ifdef ACCESSIBILITY #include "nsAccessibilityService.h" @@ -41,6 +42,8 @@ namespace mozilla { +using namespace layers; + RestyleManager::RestyleManager(nsPresContext* aPresContext) : mPresContext(aPresContext) , mRebuildAllStyleData(false) @@ -237,7 +240,16 @@ DoApplyRenderingChangeToTree(nsIFrame* aFrame, // layer for this frame, and not scheduling an invalidating // paint. if (!needInvalidatingPaint) { - needInvalidatingPaint |= !aFrame->TryUpdateTransformOnly(); + Layer* layer; + needInvalidatingPaint |= !aFrame->TryUpdateTransformOnly(&layer); + + if (!needInvalidatingPaint) { + // Since we're not going to paint, we need to resend animation + // data to the layer. + MOZ_ASSERT(layer, "this can't happen if there's no layer"); + nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(layer, + nullptr, nullptr, aFrame, eCSSProperty_transform); + } } } if (aChange & nsChangeHint_ChildrenOnlyTransform) { diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 4b255283583..cb53727aa35 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -61,6 +61,12 @@ using namespace mozilla::layers; using namespace mozilla::dom; typedef FrameMetrics::ViewID ViewID; +static inline nsIFrame* +GetTransformRootFrame(nsIFrame* aFrame) +{ + return nsLayoutUtils::GetTransformRootFrame(aFrame); +} + static void AddTransformFunctions(nsCSSValueList* aList, nsStyleContext* aContext, nsPresContext* aPresContext, @@ -308,7 +314,7 @@ ToTimingFunction(css::ComputedTimingFunction& aCTF) static void AddAnimationsForProperty(nsIFrame* aFrame, nsCSSProperty aProperty, ElementAnimation* ea, Layer* aLayer, - AnimationData& aData) + AnimationData& aData, bool aPending) { NS_ASSERTION(aLayer->AsContainerLayer(), "Should only animate ContainerLayer"); nsStyleContext* styleContext = aFrame->StyleContext(); @@ -317,15 +323,16 @@ AddAnimationsForProperty(nsIFrame* aFrame, nsCSSProperty aProperty, // all data passed directly to the compositor should be in css pixels float scale = nsDeviceContext::AppUnitsPerCSSPixel(); - TimeStamp startTime = ea->mStartTime + ea->mDelay; - TimeDuration duration = ea->mIterationDuration; - float iterations = ea->mIterationCount != NS_IEEEPositiveInfinity() - ? ea->mIterationCount : -1; - int direction = ea->mDirection; + Animation* animation = aPending ? aLayer->AddAnimationForNextTransaction() + : aLayer->AddAnimation(); - Animation* animation = aLayer->AddAnimation(startTime, duration, - iterations, direction, - aProperty, aData); + animation->startTime() = ea->mStartTime + ea->mDelay; + animation->duration() = ea->mIterationDuration; + animation->numIterations() = + ea->mIterationCount != NS_IEEEPositiveInfinity() ? ea->mIterationCount : -1; + animation->direction() = ea->mDirection; + animation->property() = aProperty; + animation->data() = aData; for (uint32_t propIdx = 0; propIdx < ea->mProperties.Length(); propIdx++) { AnimationProperty* property = &ea->mProperties[propIdx]; @@ -361,15 +368,31 @@ AddAnimationsForProperty(nsIFrame* aFrame, nsCSSProperty aProperty, } } -static void -AddAnimationsAndTransitionsToLayer(Layer* aLayer, nsDisplayListBuilder* aBuilder, - nsDisplayItem* aItem, nsCSSProperty aProperty) +/* static */ void +nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(Layer* aLayer, + nsDisplayListBuilder* aBuilder, + nsDisplayItem* aItem, + nsIFrame* aFrame, + nsCSSProperty aProperty) { - aLayer->ClearAnimations(); + // This function can be called in two ways: from + // nsDisplay*::BuildLayer while constructing a layer (with all + // pointers non-null), or from RestyleManager's handling of + // UpdateOpacityLayer/UpdateTransformLayer hints. + MOZ_ASSERT(!aBuilder == !aItem, + "should only be called in two configurations, with both " + "aBuilder and aItem, or with neither"); + MOZ_ASSERT(!aItem || aFrame == aItem->Frame(), "frame mismatch"); - nsIFrame* frame = aItem->Frame(); + bool pending = !aBuilder; - nsIContent* content = frame->GetContent(); + if (pending) { + aLayer->ClearAnimationsForNextTransaction(); + } else { + aLayer->ClearAnimations(); + } + + nsIContent* content = aFrame->GetContent(); if (!content) { return; } @@ -384,43 +407,54 @@ AddAnimationsAndTransitionsToLayer(Layer* aLayer, nsDisplayListBuilder* aBuilder } // If the frame is not prerendered, bail out. - if (!aItem->CanUseAsyncAnimations(aBuilder)) { + // Do this check only during layer construction; during updating the + // caller is required to check it appropriately. + if (aItem && !aItem->CanUseAsyncAnimations(aBuilder)) { // AnimationManager or TransitionManager need to know that we refused to // run this animation asynchronously so that they will not throttle the // main thread animation. - frame->Properties().Set(nsIFrame::RefusedAsyncAnimation(), + aFrame->Properties().Set(nsIFrame::RefusedAsyncAnimation(), reinterpret_cast(intptr_t(true))); // We need to schedule another refresh driver run so that AnimationManager // or TransitionManager get a chance to unthrottle the animation. - frame->SchedulePaint(); + aFrame->SchedulePaint(); return; } mozilla::TimeStamp currentTime = - frame->PresContext()->RefreshDriver()->MostRecentRefresh(); + aFrame->PresContext()->RefreshDriver()->MostRecentRefresh(); AnimationData data; if (aProperty == eCSSProperty_transform) { - nsRect bounds = nsDisplayTransform::GetFrameBoundsForTransform(frame); + nsRect bounds = nsDisplayTransform::GetFrameBoundsForTransform(aFrame); // all data passed directly to the compositor should be in css pixels float scale = nsDeviceContext::AppUnitsPerCSSPixel(); gfxPoint3D offsetToTransformOrigin = - nsDisplayTransform::GetDeltaToTransformOrigin(frame, scale, &bounds); + nsDisplayTransform::GetDeltaToTransformOrigin(aFrame, scale, &bounds); gfxPoint3D offsetToPerspectiveOrigin = - nsDisplayTransform::GetDeltaToPerspectiveOrigin(frame, scale); + nsDisplayTransform::GetDeltaToPerspectiveOrigin(aFrame, scale); nscoord perspective = 0.0; - nsStyleContext* parentStyleContext = frame->StyleContext()->GetParent(); + nsStyleContext* parentStyleContext = aFrame->StyleContext()->GetParent(); if (parentStyleContext) { const nsStyleDisplay* disp = parentStyleContext->StyleDisplay(); if (disp && disp->mChildPerspective.GetUnit() == eStyleUnit_Coord) { perspective = disp->mChildPerspective.GetCoordValue(); } } - nsPoint origin = aItem->ToReferenceFrame(); + nsPoint origin; + if (aItem) { + origin = aItem->ToReferenceFrame(); + } else { + // transform display items used a reference frame computed from + // their GetTransformRootFrame(). + nsIFrame* referenceFrame = + nsLayoutUtils::GetReferenceFrame(GetTransformRootFrame(aFrame)); + origin = aFrame->GetOffsetToCrossDoc(referenceFrame); + } data = TransformData(origin, offsetToTransformOrigin, offsetToPerspectiveOrigin, bounds, perspective, - frame->PresContext()->AppUnitsPerDevPixel()); + aFrame->PresContext()->AppUnitsPerDevPixel()); } else if (aProperty == eCSSProperty_opacity) { data = null_t(); } @@ -452,8 +486,8 @@ AddAnimationsAndTransitionsToLayer(Layer* aLayer, nsDisplayListBuilder* aBuilder segment.mToValue = pt->mEndValue; segment.mTimingFunction = pt->mTimingFunction; - AddAnimationsForProperty(frame, aProperty, &anim, - aLayer, data); + AddAnimationsForProperty(aFrame, aProperty, &anim, + aLayer, data, pending); pt->mIsRunningOnCompositor = true; } @@ -467,8 +501,8 @@ AddAnimationsAndTransitionsToLayer(Layer* aLayer, nsDisplayListBuilder* aBuilder anim->IsRunningAt(currentTime))) { continue; } - AddAnimationsForProperty(frame, aProperty, anim, - aLayer, data); + AddAnimationsForProperty(aFrame, aProperty, anim, + aLayer, data, pending); } aLayer->SetAnimationGeneration(ea->mAnimationGeneration); } @@ -2878,15 +2912,6 @@ nsDisplayBoxShadowInner::ComputeVisibility(nsDisplayListBuilder* aBuilder, return true; } -nsIFrame *GetTransformRootFrame(nsIFrame* aFrame) -{ - nsIFrame *parent = nsLayoutUtils::GetCrossDocParentFrame(aFrame); - while (parent && parent->Preserves3DChildren()) { - parent = nsLayoutUtils::GetCrossDocParentFrame(parent); - } - return parent; -} - nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsDisplayList* aList) : nsDisplayItem(aBuilder, aFrame) { @@ -3198,8 +3223,9 @@ nsDisplayOpacity::BuildLayer(nsDisplayListBuilder* aBuilder, return nullptr; container->SetOpacity(mFrame->StyleDisplay()->mOpacity); - AddAnimationsAndTransitionsToLayer(container, aBuilder, - this, eCSSProperty_opacity); + nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(container, aBuilder, + this, mFrame, + eCSSProperty_opacity); return container.forget(); } @@ -4665,8 +4691,9 @@ already_AddRefed nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBu container->SetContentFlags(container->GetContentFlags() & ~Layer::CONTENT_PRESERVE_3D); } - AddAnimationsAndTransitionsToLayer(container, aBuilder, - this, eCSSProperty_transform); + nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(container, aBuilder, + this, mFrame, + eCSSProperty_transform); if (ShouldPrerenderTransformedContent(aBuilder, mFrame, false)) { container->SetUserData(nsIFrame::LayerIsPrerenderedDataKey(), /*the value is irrelevant*/nullptr); diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index a3687727c1d..97a51af7a4b 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -39,6 +39,7 @@ class nsDisplayLayerEventRegions; namespace mozilla { namespace layers { +class Layer; class ImageLayer; class ImageContainer; } //namepsace @@ -112,6 +113,7 @@ public: typedef mozilla::DisplayItemClip DisplayItemClip; typedef mozilla::DisplayListClipState DisplayListClipState; typedef nsIWidget::ThemeGeometry ThemeGeometry; + typedef mozilla::layers::Layer Layer; /** * @param aReferenceFrame the frame at the root of the subtree; its origin @@ -481,6 +483,18 @@ public: */ const DisplayItemClip* AllocateDisplayItemClip(const DisplayItemClip& aOriginal); + /** + * Transfer off main thread animations to the layer. May be called + * with aBuilder and aItem both null, but only if the caller has + * already checked that off main thread animations should be sent to + * the layer. When they are both null, the animations are added to + * the layer as pending animations. + */ + static void AddAnimationsAndTransitionsToLayer(Layer* aLayer, + nsDisplayListBuilder* aBuilder, + nsDisplayItem* aItem, + nsIFrame* aFrame, + nsCSSProperty aProperty); /** * A helper class to temporarily set the value of * mIsAtRootOfPseudoStackingContext, and temporarily diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 932c9479b0b..8d830ce0071 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -4787,6 +4787,32 @@ nsLayoutUtils::GetDisplayRootFrame(nsIFrame* aFrame) } } +/* static */ nsIFrame* +nsLayoutUtils::GetReferenceFrame(nsIFrame* aFrame) +{ + nsIFrame *f = aFrame; + for (;;) { + if (f->IsTransformed() || IsPopup(f)) { + return f; + } + nsIFrame* parent = GetCrossDocParentFrame(f); + if (!parent) { + return f; + } + f = parent; + } +} + +/* static */ nsIFrame* +nsLayoutUtils::GetTransformRootFrame(nsIFrame* aFrame) +{ + nsIFrame *parent = nsLayoutUtils::GetCrossDocParentFrame(aFrame); + while (parent && parent->Preserves3DChildren()) { + parent = nsLayoutUtils::GetCrossDocParentFrame(parent); + } + return parent; +} + /* static */ uint32_t nsLayoutUtils::GetTextRunFlagsForStyle(nsStyleContext* aStyleContext, const nsStyleFont* aStyleFont, diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 636afc2d546..a195d72c9b4 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -1516,6 +1516,31 @@ public: */ static nsIFrame* GetDisplayRootFrame(nsIFrame* aFrame); + /** + * Get the reference frame that would be used when constructing a + * display item for this frame. (Note, however, that + * nsDisplayTransform use the reference frame appropriate for their + * GetTransformRootFrame(), rather than using their own frame as a + * reference frame.) + * + * This duplicates some of the logic of GetDisplayRootFrame above and + * of nsDisplayListBuilder::FindReferenceFrameFor. + * + * If you have an nsDisplayListBuilder, you should get the reference + * frame from it instead of calling this. + */ + static nsIFrame* GetReferenceFrame(nsIFrame* aFrame); + + /** + * Get the parent of this frame, except if that parent is part of a + * preserve-3d hierarchy, get the parent of the root of the + * preserve-3d hierarchy. + * + * (This is used as the starting point for reference frame computation + * for nsDisplayTransform display items.) + */ + static nsIFrame* GetTransformRootFrame(nsIFrame* aFrame); + /** * Get textrun construction flags determined by a given style; in particular * some combination of: diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 4bb7e10cbe5..0ea8ca05dfd 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -40,6 +40,7 @@ #include "nsPresContext.h" #include "nsIContent.h" #include "mozilla/dom/Element.h" +#include "mozilla/dom/Event.h" // for Event::GetEventPopupControlState() #include "mozilla/dom/ShadowRoot.h" #include "nsIDocument.h" #include "nsCSSStyleSheet.h" @@ -55,7 +56,6 @@ #include "nsTArray.h" #include "nsCOMArray.h" #include "nsContainerFrame.h" -#include "nsDOMEvent.h" #include "nsISelection.h" #include "mozilla/Selection.h" #include "nsGkAtoms.h" @@ -113,6 +113,7 @@ #include "SVGContentUtils.h" #include "nsSVGEffects.h" #include "SVGFragmentIdentifier.h" +#include "nsArenaMemoryStats.h" #include "nsPerformance.h" #include "nsRefreshDriver.h" @@ -738,7 +739,7 @@ PresShell::PresShell() addedSynthMouseMove = true; } static bool addedPointerEventEnabled = false; - if (addedPointerEventEnabled) { + if (!addedPointerEventEnabled) { Preferences::AddBoolVarCache(&sPointerEventEnabled, "dom.w3c_pointer_events.enabled", true); addedPointerEventEnabled = true; @@ -7212,7 +7213,8 @@ PresShell::HandleEventInternal(WidgetEvent* aEvent, nsEventStatus* aStatus) nsEventStateManager::GetActiveEventStateManager() == manager); } - nsAutoPopupStatePusher popupStatePusher(nsDOMEvent::GetEventPopupControlState(aEvent)); + nsAutoPopupStatePusher popupStatePusher( + Event::GetEventPopupControlState(aEvent)); // FIXME. If the event was reused, we need to clear the old target, // bug 329430 diff --git a/layout/generic/crashtests/973701-1.xhtml b/layout/generic/crashtests/973701-1.xhtml new file mode 100644 index 00000000000..e12a7a8bdd2 --- /dev/null +++ b/layout/generic/crashtests/973701-1.xhtml @@ -0,0 +1,5 @@ + + + + + diff --git a/layout/generic/crashtests/973701-2.xhtml b/layout/generic/crashtests/973701-2.xhtml new file mode 100644 index 00000000000..9fcddd11ddb --- /dev/null +++ b/layout/generic/crashtests/973701-2.xhtml @@ -0,0 +1,6 @@ + + + + + + diff --git a/layout/generic/crashtests/crashtests.list b/layout/generic/crashtests/crashtests.list index fb913e751f7..7c6d76b207a 100644 --- a/layout/generic/crashtests/crashtests.list +++ b/layout/generic/crashtests/crashtests.list @@ -525,4 +525,6 @@ test-pref(layout.css.sticky.enabled,true) load 915475.xhtml load 943509-1.html asserts(4-8) load 944909-1.html test-pref(layout.css.sticky.enabled,true) load 949932.html +load 973701-1.xhtml +load 973701-2.xhtml load outline-on-frameset.xhtml diff --git a/layout/generic/nsFlexContainerFrame.cpp b/layout/generic/nsFlexContainerFrame.cpp index 65ba261742e..9e0cf653f39 100644 --- a/layout/generic/nsFlexContainerFrame.cpp +++ b/layout/generic/nsFlexContainerFrame.cpp @@ -1053,8 +1053,10 @@ FlexItem::FlexItem(nsIFrame* aChildFrame, mAlignSelf(aChildFrame->StylePosition()->mAlignSelf) { MOZ_ASSERT(mFrame, "expecting a non-null child frame"); - MOZ_ASSERT(!mFrame->IsAbsolutelyPositioned(), - "abspos child frames should not be treated as flex items"); + MOZ_ASSERT(mFrame->GetType() != nsGkAtoms::placeholderFrame, + "placeholder frames should not be treated as flex items"); + MOZ_ASSERT(!(mFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW), + "out-of-flow frames should not be treated as flex items"); SetFlexBaseSizeAndMainSize(aFlexBaseSize); @@ -1126,8 +1128,10 @@ FlexItem::FlexItem(nsIFrame* aChildFrame, nscoord aCrossSize) MOZ_ASSERT(NS_STYLE_VISIBILITY_COLLAPSE == mFrame->StyleVisibility()->mVisible, "Should only make struts for children with 'visibility:collapse'"); - MOZ_ASSERT(!mFrame->IsAbsolutelyPositioned(), - "abspos child frames should not be treated as flex items"); + MOZ_ASSERT(mFrame->GetType() != nsGkAtoms::placeholderFrame, + "placeholder frames should not be treated as flex items"); + MOZ_ASSERT(!(mFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW), + "out-of-flow frames should not be treated as flex items"); } nscoord diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index e21ce0177d3..11f21b1e52a 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -4846,7 +4846,7 @@ nsIFrame::InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey) /*static*/ uint8_t nsIFrame::sLayerIsPrerenderedDataKey; bool -nsIFrame::TryUpdateTransformOnly() +nsIFrame::TryUpdateTransformOnly(Layer** aLayerResult) { Layer* layer = FrameLayerBuilder::GetDedicatedLayer( this, nsDisplayItem::TYPE_TRANSFORM); @@ -4885,6 +4885,7 @@ nsIFrame::TryUpdateTransformOnly() gfx::Matrix4x4 matrix; gfx::ToMatrix4x4(transform3d, matrix); layer->SetBaseTransformForNextTransaction(matrix); + *aLayerResult = layer; return true; } diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index d6adba47e8f..8aa5415fb37 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -687,13 +687,50 @@ public: return nsRect(nsPoint(0, 0), mRect.Size()); } /** - * Rect and position in logical coordinates in the frame's writing mode + * Dimensions and position in logical coordinates in the frame's writing mode + * or another writing mode */ mozilla::LogicalRect GetLogicalRect(nscoord aContainerWidth) const { - return mozilla::LogicalRect(GetWritingMode(), GetRect(), aContainerWidth); + return GetLogicalRect(GetWritingMode(), aContainerWidth); } mozilla::LogicalPoint GetLogicalPosition(nscoord aContainerWidth) const { - return GetLogicalRect(aContainerWidth).Origin(GetWritingMode()); + return GetLogicalPosition(GetWritingMode(), aContainerWidth); + } + mozilla::LogicalSize GetLogicalSize() const { + return GetLogicalSize(GetWritingMode()); + } + mozilla::LogicalRect GetLogicalRect(mozilla::WritingMode aWritingMode, + nscoord aContainerWidth) const { + return mozilla::LogicalRect(aWritingMode, GetRect(), aContainerWidth); + } + mozilla::LogicalPoint GetLogicalPosition(mozilla::WritingMode aWritingMode, + nscoord aContainerWidth) const { + return GetLogicalRect(aWritingMode, aContainerWidth).Origin(aWritingMode); + } + mozilla::LogicalSize GetLogicalSize(mozilla::WritingMode aWritingMode) const { + return mozilla::LogicalSize(aWritingMode, GetSize()); + } + nscoord IStart(nscoord aContainerWidth) const { + return IStart(GetWritingMode(), aContainerWidth); + } + nscoord IStart(mozilla::WritingMode aWritingMode, + nscoord aContainerWidth) const { + return GetLogicalPosition(aWritingMode, aContainerWidth).I(aWritingMode); + } + nscoord BStart(nscoord aContainerWidth) const { + return BStart(GetWritingMode(), aContainerWidth); + } + nscoord BStart(mozilla::WritingMode aWritingMode, + nscoord aContainerWidth) const { + return GetLogicalPosition(aWritingMode, aContainerWidth).B(aWritingMode); + } + nscoord ISize() const { return ISize(GetWritingMode()); } + nscoord ISize(mozilla::WritingMode aWritingMode) const { + return GetLogicalSize(aWritingMode).ISize(aWritingMode); + } + nscoord BSize() const { return BSize(GetWritingMode()); } + nscoord BSize(mozilla::WritingMode aWritingMode) const { + return GetLogicalSize(aWritingMode).BSize(aWritingMode); } /** @@ -715,17 +752,16 @@ public: /** * Set this frame's rect from a logical rect in its own writing direction */ - void SetRectFromLogicalRect(const mozilla::LogicalRect& aRect, - nscoord aContainerWidth) { - SetRectFromLogicalRect(GetWritingMode(), aRect, aContainerWidth); + void SetRect(const mozilla::LogicalRect& aRect, nscoord aContainerWidth) { + SetRect(GetWritingMode(), aRect, aContainerWidth); } /** * Set this frame's rect from a logical rect in a different writing direction * (GetPhysicalRect will assert if the writing mode doesn't match) */ - void SetRectFromLogicalRect(mozilla::WritingMode aWritingMode, - const mozilla::LogicalRect& aRect, - nscoord aContainerWidth) { + void SetRect(mozilla::WritingMode aWritingMode, + const mozilla::LogicalRect& aRect, + nscoord aContainerWidth) { SetRect(aRect.GetPhysicalRect(aWritingMode, aContainerWidth)); } void SetSize(const nsSize& aSize) { @@ -2106,8 +2142,11 @@ public: * Try to update this frame's transform without invalidating any * content. Return true iff successful. If unsuccessful, the * caller is responsible for scheduling an invalidating paint. + * + * If the result is true, aLayerResult will be filled in with the + * transform layer for the frame. */ - bool TryUpdateTransformOnly(); + bool TryUpdateTransformOnly(Layer** aLayerResult); /** * Checks if a frame has had InvalidateFrame() called on it since the diff --git a/layout/generic/nsIFrameInlines.h b/layout/generic/nsIFrameInlines.h index 9c97ffe3d39..0ac124cebfd 100644 --- a/layout/generic/nsIFrameInlines.h +++ b/layout/generic/nsIFrameInlines.h @@ -15,7 +15,7 @@ nsIFrame::IsFlexItem() const { return mParent && mParent->GetType() == nsGkAtoms::flexContainerFrame && - !IsAbsolutelyPositioned(); + !(GetStateBits() & NS_FRAME_OUT_OF_FLOW); } bool diff --git a/layout/generic/nsImageMap.cpp b/layout/generic/nsImageMap.cpp index 8d7133b281c..5fd24485d20 100644 --- a/layout/generic/nsImageMap.cpp +++ b/layout/generic/nsImageMap.cpp @@ -7,12 +7,12 @@ #include "nsImageMap.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() #include "nsString.h" -#include "nsDOMEvent.h" #include "nsReadableUtils.h" #include "nsRenderingContext.h" #include "nsPresContext.h" -#include "mozilla/dom/Element.h" #include "nsNameSpaceManager.h" #include "nsGkAtoms.h" #include "nsImageFrame.h" diff --git a/layout/printing/nsPrintPreviewListener.cpp b/layout/printing/nsPrintPreviewListener.cpp index 33cc2c317c4..14393b0d54f 100644 --- a/layout/printing/nsPrintPreviewListener.cpp +++ b/layout/printing/nsPrintPreviewListener.cpp @@ -8,7 +8,7 @@ #include "mozilla/TextEvents.h" #include "mozilla/dom/Element.h" -#include "nsDOMEvent.h" +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() #include "nsIDOMWindow.h" #include "nsPIDOMWindow.h" #include "nsIDOMElement.h" diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index d1e06eb4473..24ca7e44890 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -1650,7 +1650,7 @@ skip-if(Android||B2G) random-if(winWidget) == 632781-verybig.html 632781-ref.htm == 632781-normalsize.html 632781-ref.html == 633344-1.html 633344-1-ref.html == 634232-1.html 634232-1-ref.html -fails-if(Android) == 635302-1.html 635302-1-ref.html +fails-if(Android&&AndroidVersion<17) == 635302-1.html 635302-1-ref.html skip-if(B2G) random-if(d2d) fails-if(Android) fuzzy-if(winWidget&&!d2d,1,11) == 635373-1.html 635373-1-ref.html skip-if(B2G) random-if(d2d) fails-if(Android) fuzzy-if(winWidget&&!d2d,1,15) == 635373-2.html 635373-2-ref.html skip-if(B2G) random-if(d2d) fails-if(Android) fuzzy-if(winWidget&&!d2d,1,15) == 635373-3.html 635373-3-ref.html diff --git a/layout/reftests/margin-collapsing/block-abs-pos-1-dyn.html b/layout/reftests/margin-collapsing/block-abs-pos-1-dyn.html new file mode 100644 index 00000000000..d71584e2d86 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-abs-pos-1-dyn.html @@ -0,0 +1,39 @@ + + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-abs-pos-2-dyn.html b/layout/reftests/margin-collapsing/block-abs-pos-2-dyn.html new file mode 100644 index 00000000000..e59e53e84be --- /dev/null +++ b/layout/reftests/margin-collapsing/block-abs-pos-2-dyn.html @@ -0,0 +1,31 @@ + + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-em-length-1-dyn.html b/layout/reftests/margin-collapsing/block-em-length-1-dyn.html new file mode 100644 index 00000000000..961f28753f0 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-em-length-1-dyn.html @@ -0,0 +1,31 @@ + + + + + + + +
+
+ + diff --git a/layout/reftests/margin-collapsing/block-em-length-1-ref.html b/layout/reftests/margin-collapsing/block-em-length-1-ref.html new file mode 100644 index 00000000000..848a2382fd4 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-em-length-1-ref.html @@ -0,0 +1,27 @@ + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-em-length-1.html b/layout/reftests/margin-collapsing/block-em-length-1.html new file mode 100644 index 00000000000..bc66603140c --- /dev/null +++ b/layout/reftests/margin-collapsing/block-em-length-1.html @@ -0,0 +1,25 @@ + + + + + + +
+
+ + diff --git a/layout/reftests/margin-collapsing/block-float-1a-dyn.html b/layout/reftests/margin-collapsing/block-float-1a-dyn.html new file mode 100644 index 00000000000..072f3d372fa --- /dev/null +++ b/layout/reftests/margin-collapsing/block-float-1a-dyn.html @@ -0,0 +1,28 @@ + + + + + + + +
+
+ + diff --git a/layout/reftests/margin-collapsing/block-float-1b-dyn.html b/layout/reftests/margin-collapsing/block-float-1b-dyn.html new file mode 100644 index 00000000000..89e7bd5664d --- /dev/null +++ b/layout/reftests/margin-collapsing/block-float-1b-dyn.html @@ -0,0 +1,28 @@ + + + + + + + +
+
+ + diff --git a/layout/reftests/margin-collapsing/block-float-2a-dyn.html b/layout/reftests/margin-collapsing/block-float-2a-dyn.html new file mode 100644 index 00000000000..8d1f27fd438 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-float-2a-dyn.html @@ -0,0 +1,34 @@ + + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-float-2b-dyn.html b/layout/reftests/margin-collapsing/block-float-2b-dyn.html new file mode 100644 index 00000000000..08a0c8a433f --- /dev/null +++ b/layout/reftests/margin-collapsing/block-float-2b-dyn.html @@ -0,0 +1,34 @@ + + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-float-3a-dyn.html b/layout/reftests/margin-collapsing/block-float-3a-dyn.html new file mode 100644 index 00000000000..be25f763958 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-float-3a-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-float-3a-ref.html b/layout/reftests/margin-collapsing/block-float-3a-ref.html new file mode 100644 index 00000000000..7b776b279f2 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-float-3a-ref.html @@ -0,0 +1,23 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-float-3a.html b/layout/reftests/margin-collapsing/block-float-3a.html new file mode 100644 index 00000000000..639e72b8bb9 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-float-3a.html @@ -0,0 +1,29 @@ + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-float-3b-dyn.html b/layout/reftests/margin-collapsing/block-float-3b-dyn.html new file mode 100644 index 00000000000..1fd4431a215 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-float-3b-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-float-3b-ref.html b/layout/reftests/margin-collapsing/block-float-3b-ref.html new file mode 100644 index 00000000000..2e6734c3703 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-float-3b-ref.html @@ -0,0 +1,23 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-float-3b.html b/layout/reftests/margin-collapsing/block-float-3b.html new file mode 100644 index 00000000000..c2ecd8d2a13 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-float-3b.html @@ -0,0 +1,29 @@ + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-1a-dyn.html b/layout/reftests/margin-collapsing/block-no-content-1a-dyn.html new file mode 100644 index 00000000000..e167d73c305 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-1a-dyn.html @@ -0,0 +1,23 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-1b-dyn.html b/layout/reftests/margin-collapsing/block-no-content-1b-dyn.html new file mode 100644 index 00000000000..d82839a6e78 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-1b-dyn.html @@ -0,0 +1,23 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-1c-dyn.html b/layout/reftests/margin-collapsing/block-no-content-1c-dyn.html new file mode 100644 index 00000000000..fe87796340c --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-1c-dyn.html @@ -0,0 +1,23 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-1d-dyn.html b/layout/reftests/margin-collapsing/block-no-content-1d-dyn.html new file mode 100644 index 00000000000..2bb68ad7747 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-1d-dyn.html @@ -0,0 +1,23 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-1d.html b/layout/reftests/margin-collapsing/block-no-content-1d.html new file mode 100644 index 00000000000..63bb28eb48a --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-1d.html @@ -0,0 +1,20 @@ + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-2a-dyn.html b/layout/reftests/margin-collapsing/block-no-content-2a-dyn.html new file mode 100644 index 00000000000..c0339efc098 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-2a-dyn.html @@ -0,0 +1,32 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-2b-dyn.html b/layout/reftests/margin-collapsing/block-no-content-2b-dyn.html new file mode 100644 index 00000000000..a278a2d3173 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-2b-dyn.html @@ -0,0 +1,32 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-2c-dyn.html b/layout/reftests/margin-collapsing/block-no-content-2c-dyn.html new file mode 100644 index 00000000000..212222d297b --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-2c-dyn.html @@ -0,0 +1,32 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-2d-dyn.html b/layout/reftests/margin-collapsing/block-no-content-2d-dyn.html new file mode 100644 index 00000000000..2c546d0415f --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-2d-dyn.html @@ -0,0 +1,32 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-2e-dyn.html b/layout/reftests/margin-collapsing/block-no-content-2e-dyn.html new file mode 100644 index 00000000000..d27fc524da9 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-2e-dyn.html @@ -0,0 +1,32 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-2e.html b/layout/reftests/margin-collapsing/block-no-content-2e.html new file mode 100644 index 00000000000..bb0896d0db3 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-2e.html @@ -0,0 +1,26 @@ + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-3a-dyn.html b/layout/reftests/margin-collapsing/block-no-content-3a-dyn.html new file mode 100644 index 00000000000..a74e8e402bc --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-3a-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-3.html b/layout/reftests/margin-collapsing/block-no-content-3a.html similarity index 100% rename from layout/reftests/margin-collapsing/block-no-content-3.html rename to layout/reftests/margin-collapsing/block-no-content-3a.html diff --git a/layout/reftests/margin-collapsing/block-no-content-3b-dyn.html b/layout/reftests/margin-collapsing/block-no-content-3b-dyn.html new file mode 100644 index 00000000000..aae9c716539 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-3b-dyn.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-3b.html b/layout/reftests/margin-collapsing/block-no-content-3b.html new file mode 100644 index 00000000000..00f81516316 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-3b.html @@ -0,0 +1,29 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-3c-dyn.html b/layout/reftests/margin-collapsing/block-no-content-3c-dyn.html new file mode 100644 index 00000000000..b4942b4932f --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-3c-dyn.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-3c.html b/layout/reftests/margin-collapsing/block-no-content-3c.html new file mode 100644 index 00000000000..39ad02c6210 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-3c.html @@ -0,0 +1,29 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-4a-dyn.html b/layout/reftests/margin-collapsing/block-no-content-4a-dyn.html new file mode 100644 index 00000000000..f8fe446d59f --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-4a-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-4.html b/layout/reftests/margin-collapsing/block-no-content-4a.html similarity index 100% rename from layout/reftests/margin-collapsing/block-no-content-4.html rename to layout/reftests/margin-collapsing/block-no-content-4a.html diff --git a/layout/reftests/margin-collapsing/block-no-content-4b-dyn.html b/layout/reftests/margin-collapsing/block-no-content-4b-dyn.html new file mode 100644 index 00000000000..d4fcf2c36a5 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-4b-dyn.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-4b.html b/layout/reftests/margin-collapsing/block-no-content-4b.html new file mode 100644 index 00000000000..4faf50c21e0 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-4b.html @@ -0,0 +1,29 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-4c-dyn.html b/layout/reftests/margin-collapsing/block-no-content-4c-dyn.html new file mode 100644 index 00000000000..2f5d81750d5 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-4c-dyn.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-4c.html b/layout/reftests/margin-collapsing/block-no-content-4c.html new file mode 100644 index 00000000000..0b6daef65ef --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-4c.html @@ -0,0 +1,29 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-5-ref.html b/layout/reftests/margin-collapsing/block-no-content-5-ref.html new file mode 100644 index 00000000000..df55ad5424e --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-5-ref.html @@ -0,0 +1,21 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-5a-dyn.html b/layout/reftests/margin-collapsing/block-no-content-5a-dyn.html new file mode 100644 index 00000000000..699755aa619 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-5a-dyn.html @@ -0,0 +1,32 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-5a.html b/layout/reftests/margin-collapsing/block-no-content-5a.html new file mode 100644 index 00000000000..3926ecd2988 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-5a.html @@ -0,0 +1,26 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-5b-dyn.html b/layout/reftests/margin-collapsing/block-no-content-5b-dyn.html new file mode 100644 index 00000000000..7310942520d --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-5b-dyn.html @@ -0,0 +1,32 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-5b.html b/layout/reftests/margin-collapsing/block-no-content-5b.html new file mode 100644 index 00000000000..39814db731b --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-5b.html @@ -0,0 +1,26 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-6-dyn.html b/layout/reftests/margin-collapsing/block-no-content-6-dyn.html new file mode 100644 index 00000000000..c870817e963 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-6-dyn.html @@ -0,0 +1,34 @@ + + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-6-ref.html b/layout/reftests/margin-collapsing/block-no-content-6-ref.html new file mode 100644 index 00000000000..a982b3cbc0a --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-6-ref.html @@ -0,0 +1,24 @@ + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-6.html b/layout/reftests/margin-collapsing/block-no-content-6.html new file mode 100644 index 00000000000..3bc17bfa913 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-6.html @@ -0,0 +1,28 @@ + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-7-dyn.html b/layout/reftests/margin-collapsing/block-no-content-7-dyn.html new file mode 100644 index 00000000000..d150442695b --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-7-dyn.html @@ -0,0 +1,27 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-7-ref.html b/layout/reftests/margin-collapsing/block-no-content-7-ref.html new file mode 100644 index 00000000000..777047603b0 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-7-ref.html @@ -0,0 +1,19 @@ + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-7.html b/layout/reftests/margin-collapsing/block-no-content-7.html new file mode 100644 index 00000000000..4ededc1e29d --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-7.html @@ -0,0 +1,21 @@ + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-8-dyn.html b/layout/reftests/margin-collapsing/block-no-content-8-dyn.html new file mode 100644 index 00000000000..8eea3bb005a --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-8-dyn.html @@ -0,0 +1,34 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-8-ref.html b/layout/reftests/margin-collapsing/block-no-content-8-ref.html new file mode 100644 index 00000000000..f2f666e9bfb --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-8-ref.html @@ -0,0 +1,30 @@ + + + + + + +
+
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-8.html b/layout/reftests/margin-collapsing/block-no-content-8.html new file mode 100644 index 00000000000..23d703e9c67 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-8.html @@ -0,0 +1,28 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-overflow-1-dyn.html b/layout/reftests/margin-collapsing/block-overflow-1-dyn.html new file mode 100644 index 00000000000..5981abdbb8d --- /dev/null +++ b/layout/reftests/margin-collapsing/block-overflow-1-dyn.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-overflow-2-dyn.html b/layout/reftests/margin-collapsing/block-overflow-2-dyn.html new file mode 100644 index 00000000000..7fee2a812ee --- /dev/null +++ b/layout/reftests/margin-collapsing/block-overflow-2-dyn.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-overflow-3-dyn.html b/layout/reftests/margin-collapsing/block-overflow-3-dyn.html new file mode 100644 index 00000000000..0f2b6468716 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-overflow-3-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-overflow-4-dyn.html b/layout/reftests/margin-collapsing/block-overflow-4-dyn.html new file mode 100644 index 00000000000..e8d49258d1f --- /dev/null +++ b/layout/reftests/margin-collapsing/block-overflow-4-dyn.html @@ -0,0 +1,37 @@ + + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-overflow-5a-dyn.html b/layout/reftests/margin-collapsing/block-overflow-5a-dyn.html new file mode 100644 index 00000000000..8e0607619ea --- /dev/null +++ b/layout/reftests/margin-collapsing/block-overflow-5a-dyn.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-overflow-5b-dyn.html b/layout/reftests/margin-collapsing/block-overflow-5b-dyn.html new file mode 100644 index 00000000000..3c041d86885 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-overflow-5b-dyn.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-overflow-5c-dyn.html b/layout/reftests/margin-collapsing/block-overflow-5c-dyn.html new file mode 100644 index 00000000000..731f2fa6003 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-overflow-5c-dyn.html @@ -0,0 +1,34 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-overflow-5d-dyn.html b/layout/reftests/margin-collapsing/block-overflow-5d-dyn.html new file mode 100644 index 00000000000..cd5a969d426 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-overflow-5d-dyn.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-percent-1-dyn.html b/layout/reftests/margin-collapsing/block-percent-1-dyn.html new file mode 100644 index 00000000000..780e95a7213 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-percent-1-dyn.html @@ -0,0 +1,32 @@ + + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-percent-1.html b/layout/reftests/margin-collapsing/block-percent-1.html index 1450efa3163..3344bd0b23a 100644 --- a/layout/reftests/margin-collapsing/block-percent-1.html +++ b/layout/reftests/margin-collapsing/block-percent-1.html @@ -3,7 +3,7 @@ + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-percent-2-ref.html b/layout/reftests/margin-collapsing/block-percent-2-ref.html new file mode 100644 index 00000000000..d9efe6bfb57 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-percent-2-ref.html @@ -0,0 +1,33 @@ + + + + + + +
+
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-percent-2.html b/layout/reftests/margin-collapsing/block-percent-2.html new file mode 100644 index 00000000000..0137dc9b9f8 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-percent-2.html @@ -0,0 +1,31 @@ + + + + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/caption-child-1-dyn.html b/layout/reftests/margin-collapsing/caption-child-1-dyn.html new file mode 100644 index 00000000000..1dfe6009076 --- /dev/null +++ b/layout/reftests/margin-collapsing/caption-child-1-dyn.html @@ -0,0 +1,40 @@ + + + + + + + +
+
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/caption-child-1-ref.html b/layout/reftests/margin-collapsing/caption-child-1-ref.html new file mode 100644 index 00000000000..5ebbe846536 --- /dev/null +++ b/layout/reftests/margin-collapsing/caption-child-1-ref.html @@ -0,0 +1,27 @@ + + + + + + +
+
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/caption-child-1.html b/layout/reftests/margin-collapsing/caption-child-1.html new file mode 100644 index 00000000000..e54ad40e42d --- /dev/null +++ b/layout/reftests/margin-collapsing/caption-child-1.html @@ -0,0 +1,33 @@ + + + + + + +
+
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-child-1-dyn.html b/layout/reftests/margin-collapsing/column-child-1-dyn.html new file mode 100644 index 00000000000..58781e91512 --- /dev/null +++ b/layout/reftests/margin-collapsing/column-child-1-dyn.html @@ -0,0 +1,32 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-child-1-ref.html b/layout/reftests/margin-collapsing/column-child-1-ref.html new file mode 100644 index 00000000000..7715129b64f --- /dev/null +++ b/layout/reftests/margin-collapsing/column-child-1-ref.html @@ -0,0 +1,26 @@ + + + + + + +
+
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-child-1.html b/layout/reftests/margin-collapsing/column-child-1.html new file mode 100644 index 00000000000..bc557f8059f --- /dev/null +++ b/layout/reftests/margin-collapsing/column-child-1.html @@ -0,0 +1,26 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-1-ref.html b/layout/reftests/margin-collapsing/column-sibling-1-ref.html new file mode 100644 index 00000000000..1c7c66311f6 --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-1-ref.html @@ -0,0 +1,25 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-1a-dyn.html b/layout/reftests/margin-collapsing/column-sibling-1a-dyn.html new file mode 100644 index 00000000000..c7a05c68ff2 --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-1a-dyn.html @@ -0,0 +1,37 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-1a.html b/layout/reftests/margin-collapsing/column-sibling-1a.html new file mode 100644 index 00000000000..2f2a1e84ee3 --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-1a.html @@ -0,0 +1,29 @@ + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-1b-dyn.html b/layout/reftests/margin-collapsing/column-sibling-1b-dyn.html new file mode 100644 index 00000000000..26949a434ac --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-1b-dyn.html @@ -0,0 +1,37 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-1b.html b/layout/reftests/margin-collapsing/column-sibling-1b.html new file mode 100644 index 00000000000..1bf4dfed6a5 --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-1b.html @@ -0,0 +1,29 @@ + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-1c-dyn.html b/layout/reftests/margin-collapsing/column-sibling-1c-dyn.html new file mode 100644 index 00000000000..9a0c9dc890d --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-1c-dyn.html @@ -0,0 +1,37 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-1c.html b/layout/reftests/margin-collapsing/column-sibling-1c.html new file mode 100644 index 00000000000..90446d65cf8 --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-1c.html @@ -0,0 +1,29 @@ + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-2-ref.html b/layout/reftests/margin-collapsing/column-sibling-2-ref.html new file mode 100644 index 00000000000..3d160baaa35 --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-2-ref.html @@ -0,0 +1,21 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-2a-dyn.html b/layout/reftests/margin-collapsing/column-sibling-2a-dyn.html new file mode 100644 index 00000000000..643f7b98f8b --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-2a-dyn.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-2a.html b/layout/reftests/margin-collapsing/column-sibling-2a.html new file mode 100644 index 00000000000..e4753529030 --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-2a.html @@ -0,0 +1,27 @@ + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-2b-dyn.html b/layout/reftests/margin-collapsing/column-sibling-2b-dyn.html new file mode 100644 index 00000000000..85df871b49b --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-2b-dyn.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-2b.html b/layout/reftests/margin-collapsing/column-sibling-2b.html new file mode 100644 index 00000000000..484674559b6 --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-2b.html @@ -0,0 +1,27 @@ + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-2c-dyn.html b/layout/reftests/margin-collapsing/column-sibling-2c-dyn.html new file mode 100644 index 00000000000..d9e89ec5e53 --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-2c-dyn.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-2c.html b/layout/reftests/margin-collapsing/column-sibling-2c.html new file mode 100644 index 00000000000..9adff98160d --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-2c.html @@ -0,0 +1,27 @@ + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/fieldset-child-1-dyn.html b/layout/reftests/margin-collapsing/fieldset-child-1-dyn.html new file mode 100644 index 00000000000..295432e5c35 --- /dev/null +++ b/layout/reftests/margin-collapsing/fieldset-child-1-dyn.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/fieldset-sibling-1a-dyn.html b/layout/reftests/margin-collapsing/fieldset-sibling-1a-dyn.html new file mode 100644 index 00000000000..c99607db615 --- /dev/null +++ b/layout/reftests/margin-collapsing/fieldset-sibling-1a-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/fieldset-sibling-1b-dyn.html b/layout/reftests/margin-collapsing/fieldset-sibling-1b-dyn.html new file mode 100644 index 00000000000..a7d1e40a3c3 --- /dev/null +++ b/layout/reftests/margin-collapsing/fieldset-sibling-1b-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/fieldset-sibling-1c-dyn.html b/layout/reftests/margin-collapsing/fieldset-sibling-1c-dyn.html new file mode 100644 index 00000000000..91e97ced1f5 --- /dev/null +++ b/layout/reftests/margin-collapsing/fieldset-sibling-1c-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/fieldset-sibling-1c.html b/layout/reftests/margin-collapsing/fieldset-sibling-1c.html index 14eb77ad72d..e525761d498 100644 --- a/layout/reftests/margin-collapsing/fieldset-sibling-1c.html +++ b/layout/reftests/margin-collapsing/fieldset-sibling-1c.html @@ -4,7 +4,7 @@ + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/fieldset-sibling-2b-dyn.html b/layout/reftests/margin-collapsing/fieldset-sibling-2b-dyn.html new file mode 100644 index 00000000000..8b8a2eac343 --- /dev/null +++ b/layout/reftests/margin-collapsing/fieldset-sibling-2b-dyn.html @@ -0,0 +1,34 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/fieldset-sibling-2c-dyn.html b/layout/reftests/margin-collapsing/fieldset-sibling-2c-dyn.html new file mode 100644 index 00000000000..76f3827c4fd --- /dev/null +++ b/layout/reftests/margin-collapsing/fieldset-sibling-2c-dyn.html @@ -0,0 +1,34 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/inline-block-child-1-dyn.html b/layout/reftests/margin-collapsing/inline-block-child-1-dyn.html new file mode 100644 index 00000000000..6376b99d80d --- /dev/null +++ b/layout/reftests/margin-collapsing/inline-block-child-1-dyn.html @@ -0,0 +1,30 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/inline-block-child-2-dyn.html b/layout/reftests/margin-collapsing/inline-block-child-2-dyn.html new file mode 100644 index 00000000000..3ffee5dc0ca --- /dev/null +++ b/layout/reftests/margin-collapsing/inline-block-child-2-dyn.html @@ -0,0 +1,26 @@ + + + + + + + +
Hello Kitty
+ + diff --git a/layout/reftests/margin-collapsing/inline-block-child-3-dyn.html b/layout/reftests/margin-collapsing/inline-block-child-3-dyn.html new file mode 100644 index 00000000000..98f56d360f8 --- /dev/null +++ b/layout/reftests/margin-collapsing/inline-block-child-3-dyn.html @@ -0,0 +1,29 @@ + + + + + + + +
Hello Kitty
+ + diff --git a/layout/reftests/margin-collapsing/inline-block-child-3-ref.html b/layout/reftests/margin-collapsing/inline-block-child-3-ref.html new file mode 100644 index 00000000000..6ca83dd06eb --- /dev/null +++ b/layout/reftests/margin-collapsing/inline-block-child-3-ref.html @@ -0,0 +1,22 @@ + + + + + + +
Hello Kitty
+ + diff --git a/layout/reftests/margin-collapsing/inline-block-child-3.html b/layout/reftests/margin-collapsing/inline-block-child-3.html new file mode 100644 index 00000000000..e0bd8ae1db4 --- /dev/null +++ b/layout/reftests/margin-collapsing/inline-block-child-3.html @@ -0,0 +1,22 @@ + + + + + + +
Hello Kitty
+ + diff --git a/layout/reftests/margin-collapsing/inline-block-sibling-1a-dyn.html b/layout/reftests/margin-collapsing/inline-block-sibling-1a-dyn.html new file mode 100644 index 00000000000..a3224b8e732 --- /dev/null +++ b/layout/reftests/margin-collapsing/inline-block-sibling-1a-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/inline-block-sibling-1b-dyn.html b/layout/reftests/margin-collapsing/inline-block-sibling-1b-dyn.html new file mode 100644 index 00000000000..14d656756e8 --- /dev/null +++ b/layout/reftests/margin-collapsing/inline-block-sibling-1b-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/inline-block-sibling-1c-dyn.html b/layout/reftests/margin-collapsing/inline-block-sibling-1c-dyn.html new file mode 100644 index 00000000000..be14f2870a6 --- /dev/null +++ b/layout/reftests/margin-collapsing/inline-block-sibling-1c-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/inline-block-sibling-2-dyn.html b/layout/reftests/margin-collapsing/inline-block-sibling-2-dyn.html new file mode 100644 index 00000000000..be0847ac031 --- /dev/null +++ b/layout/reftests/margin-collapsing/inline-block-sibling-2-dyn.html @@ -0,0 +1,38 @@ + + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/reftest.list b/layout/reftests/margin-collapsing/reftest.list index 42ed7068987..6edc5dcdf32 100644 --- a/layout/reftests/margin-collapsing/reftest.list +++ b/layout/reftests/margin-collapsing/reftest.list @@ -514,12 +514,47 @@ fails == block-max-height-last-child-9a-dyn.html block-max-height-last-child-9-r == block-no-content-1a.html block-no-content-1-ref.html == block-no-content-1b.html block-no-content-1-ref.html == block-no-content-1c.html block-no-content-1-ref.html +== block-no-content-1d.html block-no-content-1-ref.html == block-no-content-2a.html block-no-content-2-ref.html == block-no-content-2b.html block-no-content-2-ref.html == block-no-content-2c.html block-no-content-2-ref.html == block-no-content-2d.html block-no-content-2-ref.html -== block-no-content-3.html block-no-content-3-ref.html -== block-no-content-4.html block-no-content-4-ref.html +== block-no-content-2e.html block-no-content-2-ref.html +== block-no-content-3a.html block-no-content-3-ref.html +== block-no-content-3b.html block-no-content-3-ref.html +== block-no-content-3c.html block-no-content-3-ref.html +== block-no-content-4a.html block-no-content-4-ref.html +== block-no-content-4b.html block-no-content-4-ref.html +== block-no-content-4c.html block-no-content-4-ref.html +== block-no-content-5a.html block-no-content-5-ref.html +== block-no-content-5b.html block-no-content-5-ref.html +== block-no-content-6.html block-no-content-6-ref.html +== block-no-content-7.html block-no-content-7-ref.html +# "If the top margin of a box with non-zero computed 'min-height' and 'auto' +# computed 'height' collapses with the bottom margin of its last in-flow +# child, then the child's bottom margin does not collapse with the parent's +# bottom margin." +== block-no-content-8.html block-no-content-8-ref.html +== block-no-content-1a-dyn.html block-no-content-1-ref.html +== block-no-content-1b-dyn.html block-no-content-1-ref.html +== block-no-content-1c-dyn.html block-no-content-1-ref.html +== block-no-content-1d-dyn.html block-no-content-1-ref.html +== block-no-content-2a-dyn.html block-no-content-2-ref.html +== block-no-content-2b-dyn.html block-no-content-2-ref.html +== block-no-content-2c-dyn.html block-no-content-2-ref.html +== block-no-content-2d-dyn.html block-no-content-2-ref.html +== block-no-content-2e-dyn.html block-no-content-2-ref.html +== block-no-content-3a-dyn.html block-no-content-3-ref.html +== block-no-content-3b-dyn.html block-no-content-3-ref.html +== block-no-content-3c-dyn.html block-no-content-3-ref.html +== block-no-content-4a-dyn.html block-no-content-4-ref.html +== block-no-content-4b-dyn.html block-no-content-4-ref.html +== block-no-content-4c-dyn.html block-no-content-4-ref.html +== block-no-content-5a-dyn.html block-no-content-5-ref.html +== block-no-content-5b-dyn.html block-no-content-5-ref.html +== block-no-content-6-dyn.html block-no-content-6-ref.html +== block-no-content-7-dyn.html block-no-content-7-ref.html +== block-no-content-8-dyn.html block-no-content-8-ref.html # These tests are similar to the no-content ones, except that some boxes # have height: 0; declared on them. == block-zero-height-1a.html block-zero-height-1a-ref.html @@ -552,6 +587,14 @@ skip-if(B2G) == block-overflow-4.html block-overflow-4-ref2.html == block-overflow-5c.html block-overflow-5c-ref2.html == block-overflow-5d.html block-overflow-5-ref.html == block-overflow-5d.html block-overflow-5-ref2.html +== block-overflow-1-dyn.html block-overflow-1-ref2.html +== block-overflow-2-dyn.html block-overflow-2-ref2.html +skip-if(B2G) == block-overflow-3-dyn.html block-overflow-3-ref2.html # bug 773482 +skip-if(B2G) == block-overflow-4-dyn.html block-overflow-4-ref2.html +== block-overflow-5a-dyn.html block-overflow-5-ref2.html +== block-overflow-5b-dyn.html block-overflow-5-ref2.html +== block-overflow-5c-dyn.html block-overflow-5c-ref2.html +== block-overflow-5d-dyn.html block-overflow-5-ref2.html # * 'fieldset' elements, per HTML5 (Candidate Recommendation 6 August 2013): # §10.3.13 (The fieldset and legend elements): "The fieldset element is # expected to establish a new block formatting context." @@ -564,7 +607,14 @@ skip-if(B2G) == block-overflow-4.html block-overflow-4-ref2.html == fieldset-sibling-2a.html fieldset-sibling-2-ref2.html == fieldset-sibling-2b.html fieldset-sibling-2-ref2.html == fieldset-sibling-2c.html fieldset-sibling-2-ref2.html +== fieldset-sibling-1a-dyn.html fieldset-sibling-1-ref.html +== fieldset-sibling-1b-dyn.html fieldset-sibling-1-ref.html +== fieldset-sibling-1c-dyn.html fieldset-sibling-1-ref.html +== fieldset-sibling-2a-dyn.html fieldset-sibling-2-ref2.html +== fieldset-sibling-2b-dyn.html fieldset-sibling-2-ref2.html +== fieldset-sibling-2c-dyn.html fieldset-sibling-2-ref2.html == fieldset-child-1.html fieldset-child-1-ref.html +== fieldset-child-1-dyn.html fieldset-child-1-ref.html # * Tables, per CSS 2.1 §17.4 (Tables in the visual formatting model): # "The table wrapper box establishes a block formatting context." # "The table wrapper box is a 'block' box if the table is block-level [...]" @@ -602,13 +652,37 @@ skip-if(B2G) == table-sibling-3-dyn.html table-sibling-3-ref.html # bug 773482 # table-captions, though, if they share the same caption-side. == table-caption-1a.html table-caption-1-ref.html == table-caption-1b.html table-caption-1-ref.html +== table-caption-1c.html table-caption-1-ref.html == table-caption-2a.html table-caption-2-ref.html == table-caption-2b.html table-caption-2-ref.html == table-caption-2c.html table-caption-2-ref.html +== table-caption-1a-dyn.html table-caption-1-ref.html +== table-caption-1b-dyn.html table-caption-1-ref.html +== table-caption-1c-dyn.html table-caption-1-ref.html +== table-caption-2a-dyn.html table-caption-2-ref.html +== table-caption-2b-dyn.html table-caption-2-ref.html +== table-caption-2c-dyn.html table-caption-2-ref.html +# Note: CSS 2.1 suggests that the 'caption-side' values 'top-outside' and +# 'bottom-outside' will be used in a future CSS Module to restore the +# CSS 2 definition of 'top' and 'bottom' (which is different from CSS 2.1's). +# Since Bug #659828 was fixed, 'top-outside' and 'bottom-outside' act as an +# alias for the CSS 2.1 values 'top' and 'bottom' respectively. == table-caption-top-1.html table-caption-top-1-ref.html == table-caption-top-2.html table-caption-top-2-ref.html +== table-caption-top-outside-1.html table-caption-top-1-ref.html +== table-caption-top-outside-2.html table-caption-top-1-ref.html == table-caption-bottom-1.html table-caption-bottom-1-ref.html == table-caption-bottom-2.html table-caption-bottom-2-ref.html +== table-caption-bottom-outside-1.html table-caption-bottom-1-ref.html +== table-caption-bottom-outside-2.html table-caption-bottom-1-ref.html +== table-caption-top-1-dyn.html table-caption-top-1-ref.html +== table-caption-top-2-dyn.html table-caption-top-1-ref.html +== table-caption-top-outside-1-dyn.html table-caption-top-1-ref.html +== table-caption-top-outside-2-dyn.html table-caption-top-2-ref.html +== table-caption-bottom-1-dyn.html table-caption-bottom-1-ref.html +== table-caption-bottom-2-dyn.html table-caption-bottom-1-ref.html +== table-caption-bottom-outside-1-dyn.html table-caption-bottom-1-ref.html +== table-caption-bottom-outside-2-dyn.html table-caption-bottom-1-ref.html fails == caption-sibling-1a.html caption-sibling-1-ref.html # Bug 144517 != caption-sibling-1a.html caption-sibling-1-noref.html fails == caption-sibling-1b.html caption-sibling-1-ref.html # Bug 144517 @@ -623,6 +697,25 @@ fails == caption-sibling-1c-dyn.html caption-sibling-1-ref.html # Bug 144517 != caption-sibling-1c-dyn.html caption-sibling-1-noref2.html fails == caption-sibling-2-dyn.html caption-sibling-2-ref.html # Bug 144517 != caption-sibling-2-dyn.html caption-sibling-2-noref.html +== caption-child-1.html caption-child-1-ref.html +== caption-child-1-dyn.html caption-child-1-ref.html +# * Multi-column elements, per CSS Multi-column Layout Module +# (Candidate Recommendation 12 April 2011): +# "A multi-column element establishes a new block formatting context [...]" +== column-sibling-1a.html column-sibling-1-ref.html +== column-sibling-1b.html column-sibling-1-ref.html +== column-sibling-1c.html column-sibling-1-ref.html +== column-sibling-1a-dyn.html column-sibling-1-ref.html +== column-sibling-1b-dyn.html column-sibling-1-ref.html +== column-sibling-1c-dyn.html column-sibling-1-ref.html +== column-sibling-2a.html column-sibling-2-ref.html +== column-sibling-2b.html column-sibling-2-ref.html +== column-sibling-2c.html column-sibling-2-ref.html +== column-sibling-2a-dyn.html column-sibling-2-ref.html +== column-sibling-2b-dyn.html column-sibling-2-ref.html +== column-sibling-2c-dyn.html column-sibling-2-ref.html +== column-child-1.html column-child-1-ref.html +== column-child-1-dyn.html column-child-1-ref.html # * inline-block boxes # "Margins of inline-block boxes do not collapse # (not even with their in-flow children)." @@ -631,15 +724,25 @@ fails == caption-sibling-2-dyn.html caption-sibling-2-ref.html # Bug 144517 == inline-block-sibling-1c.html inline-block-sibling-1-ref.html == inline-block-sibling-2.html inline-block-sibling-2-ref.html != inline-block-sibling-2.html inline-block-sibling-2-noref.html +== inline-block-sibling-1a-dyn.html inline-block-sibling-1-ref.html +== inline-block-sibling-1b-dyn.html inline-block-sibling-1-ref.html +== inline-block-sibling-1c-dyn.html inline-block-sibling-1-ref.html +== inline-block-sibling-2-dyn.html inline-block-sibling-2-ref.html == inline-block-child-1.html inline-block-child-1-ref.html == inline-block-child-2.html inline-block-child-2-ref.html != inline-block-child-2.html inline-block-child-2-noref.html +== inline-block-child-3.html inline-block-child-3-ref.html +== inline-block-child-1-dyn.html inline-block-child-1-ref.html +== inline-block-child-2-dyn.html inline-block-child-2-ref.html +== inline-block-child-3-dyn.html inline-block-child-3-ref.html # * absolutely positioned elements # "Margins of absolutely positioned boxes do not collapse # (not even with their in-flow children)." == block-abs-pos-1.html block-abs-pos-1-ref.html == block-abs-pos-2.html block-abs-pos-2-ref.html == block-abs-pos-2.html block-abs-pos-2-ref2.html +== block-abs-pos-1-dyn.html block-abs-pos-1-ref.html +== block-abs-pos-2-dyn.html block-abs-pos-2-ref2.html # * Floats # "Margins between a floated box and any other box do not collapse # (not even between a float and its in-flow children)." @@ -653,6 +756,14 @@ fails == caption-sibling-2-dyn.html caption-sibling-2-ref.html # Bug 144517 != block-float-2a.html block-float-2a-noref.html == block-float-2b.html block-float-2b-ref.html != block-float-2b.html block-float-2b-noref.html +== block-float-3a.html block-float-3a-ref.html +== block-float-3b.html block-float-3b-ref.html +== block-float-1a-dyn.html block-float-1a-ref.html +== block-float-1b-dyn.html block-float-1b-ref.html +== block-float-2a-dyn.html block-float-2a-ref.html +== block-float-2b-dyn.html block-float-2b-ref.html +== block-float-3a-dyn.html block-float-3a-ref.html +== block-float-3b-dyn.html block-float-3b-ref.html # Tests for various cases where clearance is applied and collapsing is # prevented or only allows for certain margins. fails == block-clear-1a.html block-clear-1a-ref.html # Bug 451791 @@ -740,8 +851,14 @@ fails == block-clear-7g-left.html block-clear-7efgh-left-ref2.html # Bug 493380 == block-html-body-1.html block-html-body-1-ref.html == block-html-body-1.html block-html-body-1-ref2.html != block-html-body-1.html block-html-body-1-noref.html -# Other tests. +# Some basic tests for margins given in percent and em. == block-percent-1.html block-percent-1-ref.html +== block-percent-1-dyn.html block-percent-1-ref.html +== block-percent-2.html block-percent-2-ref.html +== block-percent-2-dyn.html block-percent-2-ref.html +== block-em-length-1.html block-em-length-1-ref.html +== block-em-length-1-dyn.html block-em-length-1-ref.html +# Other tests. == dynamic-add-text-1.html dynamic-add-text-1-ref.html # Bug 467321 == scrollable-vertical-margin.html scrollable-vertical-margin-ref.html == scrollable-horizontal-margin.html scrollable-horizontal-margin-ref.html diff --git a/layout/reftests/margin-collapsing/table-caption-1a-dyn.html b/layout/reftests/margin-collapsing/table-caption-1a-dyn.html new file mode 100644 index 00000000000..d70070d14cb --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-1a-dyn.html @@ -0,0 +1,41 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-1b-dyn.html b/layout/reftests/margin-collapsing/table-caption-1b-dyn.html new file mode 100644 index 00000000000..8dc7c29211f --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-1b-dyn.html @@ -0,0 +1,41 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-1c-dyn.html b/layout/reftests/margin-collapsing/table-caption-1c-dyn.html new file mode 100644 index 00000000000..4e386b5f661 --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-1c-dyn.html @@ -0,0 +1,41 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-1c.html b/layout/reftests/margin-collapsing/table-caption-1c.html new file mode 100644 index 00000000000..b7956a130b6 --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-1c.html @@ -0,0 +1,34 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-2a-dyn.html b/layout/reftests/margin-collapsing/table-caption-2a-dyn.html new file mode 100644 index 00000000000..d9943ca7201 --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-2a-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-2b-dyn.html b/layout/reftests/margin-collapsing/table-caption-2b-dyn.html new file mode 100644 index 00000000000..90f55e03240 --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-2b-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-2c-dyn.html b/layout/reftests/margin-collapsing/table-caption-2c-dyn.html new file mode 100644 index 00000000000..6d79c3cd300 --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-2c-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-bottom-1-dyn.html b/layout/reftests/margin-collapsing/table-caption-bottom-1-dyn.html new file mode 100644 index 00000000000..dd456eb4702 --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-bottom-1-dyn.html @@ -0,0 +1,48 @@ + + + + + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-bottom-2-dyn.html b/layout/reftests/margin-collapsing/table-caption-bottom-2-dyn.html new file mode 100644 index 00000000000..7363e73cd9c --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-bottom-2-dyn.html @@ -0,0 +1,43 @@ + + + + + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-bottom-outside-1-dyn.html b/layout/reftests/margin-collapsing/table-caption-bottom-outside-1-dyn.html new file mode 100644 index 00000000000..c31a8e6ef9c --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-bottom-outside-1-dyn.html @@ -0,0 +1,48 @@ + + + + + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-bottom-outside-1.html b/layout/reftests/margin-collapsing/table-caption-bottom-outside-1.html new file mode 100644 index 00000000000..5a4c9c7c827 --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-bottom-outside-1.html @@ -0,0 +1,41 @@ + + + + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-bottom-outside-2-dyn.html b/layout/reftests/margin-collapsing/table-caption-bottom-outside-2-dyn.html new file mode 100644 index 00000000000..c1d6595afc7 --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-bottom-outside-2-dyn.html @@ -0,0 +1,43 @@ + + + + + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-bottom-outside-2.html b/layout/reftests/margin-collapsing/table-caption-bottom-outside-2.html new file mode 100644 index 00000000000..c730424e77b --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-bottom-outside-2.html @@ -0,0 +1,36 @@ + + + + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-top-1-dyn.html b/layout/reftests/margin-collapsing/table-caption-top-1-dyn.html new file mode 100644 index 00000000000..8e456adebc9 --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-top-1-dyn.html @@ -0,0 +1,48 @@ + + + + + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-top-2-dyn.html b/layout/reftests/margin-collapsing/table-caption-top-2-dyn.html new file mode 100644 index 00000000000..01dd40ad85a --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-top-2-dyn.html @@ -0,0 +1,43 @@ + + + + + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-top-outside-1-dyn.html b/layout/reftests/margin-collapsing/table-caption-top-outside-1-dyn.html new file mode 100644 index 00000000000..3767070f97c --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-top-outside-1-dyn.html @@ -0,0 +1,48 @@ + + + + + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-top-outside-1.html b/layout/reftests/margin-collapsing/table-caption-top-outside-1.html new file mode 100644 index 00000000000..f159d429724 --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-top-outside-1.html @@ -0,0 +1,41 @@ + + + + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-top-outside-2-dyn.html b/layout/reftests/margin-collapsing/table-caption-top-outside-2-dyn.html new file mode 100644 index 00000000000..f01fa94f88d --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-top-outside-2-dyn.html @@ -0,0 +1,43 @@ + + + + + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-top-outside-2.html b/layout/reftests/margin-collapsing/table-caption-top-outside-2.html new file mode 100644 index 00000000000..d5516f8c7e1 --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-top-outside-2.html @@ -0,0 +1,36 @@ + + + + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/w3c-css/submitted/variables/support/external-variable-declaration.css b/layout/reftests/w3c-css/submitted/variables/support/external-variable-declaration.css new file mode 100644 index 00000000000..ec5726b4649 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/variables/support/external-variable-declaration.css @@ -0,0 +1,5 @@ +p { + color: red; + var-a: green; + color: var(a); +} diff --git a/layout/reftests/w3c-css/submitted/variables/support/external-variable-font-face.css b/layout/reftests/w3c-css/submitted/variables/support/external-variable-font-face.css new file mode 100644 index 00000000000..9edf374afe6 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/variables/support/external-variable-font-face.css @@ -0,0 +1,15 @@ +@font-face { + var-a: MyTestFontName; + font-family: var(a); + src: url(../../../../fonts/Ahem.ttf); +} +@font-face { + font-family: MyTestFontName2; + src: url(../../../../fonts/Ahem.ttf); +} +#a { + font-family: MyTestFontName; +} +#b { + font-family: MyTestFontName2; +} diff --git a/layout/reftests/w3c-css/submitted/variables/support/external-variable-reference.css b/layout/reftests/w3c-css/submitted/variables/support/external-variable-reference.css new file mode 100644 index 00000000000..5c912acb0a6 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/variables/support/external-variable-reference.css @@ -0,0 +1,6 @@ +:root { + var-a: green; +} +p { + color: var(a); +} diff --git a/layout/reftests/w3c-css/submitted/variables/support/external-variable-supports.css b/layout/reftests/w3c-css/submitted/variables/support/external-variable-supports.css new file mode 100644 index 00000000000..e7fdd9f04a8 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/variables/support/external-variable-supports.css @@ -0,0 +1,4 @@ +body { color: red; } +@supports (color:var(a)) { + p { color: green; } +} diff --git a/layout/reftests/w3c-css/submitted/variables/variable-external-declaration-01.html b/layout/reftests/w3c-css/submitted/variables/variable-external-declaration-01.html new file mode 100644 index 00000000000..bae5abf700a --- /dev/null +++ b/layout/reftests/w3c-css/submitted/variables/variable-external-declaration-01.html @@ -0,0 +1,12 @@ + + +CSS Test: Test declaring a variable in an external CSS file. + + + + + +

This text must be green.

diff --git a/layout/reftests/w3c-css/submitted/variables/variable-external-font-face-01.html b/layout/reftests/w3c-css/submitted/variables/variable-external-font-face-01.html new file mode 100644 index 00000000000..f248418120d --- /dev/null +++ b/layout/reftests/w3c-css/submitted/variables/variable-external-font-face-01.html @@ -0,0 +1,13 @@ + + +CSS Test: Test the invalid declaration and use of a variable in an @font-face rule within an external CSS. + + + + + +

This text must not be in Ahem.

+

But this text must be in Ahem.

diff --git a/layout/reftests/w3c-css/submitted/variables/variable-external-reference-01.html b/layout/reftests/w3c-css/submitted/variables/variable-external-reference-01.html new file mode 100644 index 00000000000..ee40db762cd --- /dev/null +++ b/layout/reftests/w3c-css/submitted/variables/variable-external-reference-01.html @@ -0,0 +1,12 @@ + + +CSS Test: Test the use of a variable in a non-custom property where the variable value is inherited within an external CSS. + + + + + +

This text must be green.

diff --git a/layout/reftests/w3c-css/submitted/variables/variable-external-supports-01.html b/layout/reftests/w3c-css/submitted/variables/variable-external-supports-01.html new file mode 100644 index 00000000000..dd3ad172818 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/variables/variable-external-supports-01.html @@ -0,0 +1,12 @@ + + +CSS Test: Test a passing non-custom property declaration in an @supports rule where the property value contains a variable reference within an external stylesheet file. + + + + + +

This text must be green.

diff --git a/layout/style/AnimationCommon.cpp b/layout/style/AnimationCommon.cpp index 7a1850f979a..b3bda874625 100644 --- a/layout/style/AnimationCommon.cpp +++ b/layout/style/AnimationCommon.cpp @@ -191,28 +191,6 @@ CommonAnimationManager::ReparentBeforeAndAfter(dom::Element* aElement, } } -// Ensure that the next repaint rebuilds the layer tree for aFrame. That -// means that changes to animations on aFrame's layer are propagated to -// the compositor, which is needed for correct behaviour of new -// transitions. -static void -ForceLayerRerendering(nsIFrame* aFrame, CommonElementAnimationData* aData) -{ - if (aData->HasAnimationOfProperty(eCSSProperty_opacity)) { - if (Layer* layer = FrameLayerBuilder::GetDedicatedLayer( - aFrame, nsDisplayItem::TYPE_OPACITY)) { - layer->RemoveUserData(nsIFrame::LayerIsPrerenderedDataKey()); - } - } - - if (aData->HasAnimationOfProperty(eCSSProperty_transform)) { - if (Layer* layer = FrameLayerBuilder::GetDedicatedLayer( - aFrame, nsDisplayItem::TYPE_TRANSFORM)) { - layer->RemoveUserData(nsIFrame::LayerIsPrerenderedDataKey()); - } - } -} - nsStyleContext* CommonAnimationManager::UpdateThrottledStyle(dom::Element* aElement, nsStyleContext* aParentStyle, @@ -254,9 +232,6 @@ CommonAnimationManager::UpdateThrottledStyle(dom::Element* aElement, mPresContext->AnimationManager()->EnsureStyleRuleFor(ea); curRule.mRule = ea->mStyleRule; - - // FIXME (bug 828173): maybe not needed anymore: - ForceLayerRerendering(primaryFrame, ea); } else if (curRule.mLevel == nsStyleSet::eTransitionSheet) { ElementTransitions *et = mPresContext->TransitionManager()->GetElementTransitions( @@ -268,9 +243,6 @@ CommonAnimationManager::UpdateThrottledStyle(dom::Element* aElement, et->EnsureStyleRuleFor(mPresContext->RefreshDriver()->MostRecentRefresh()); curRule.mRule = et->mStyleRule; - - // FIXME (bug 828173): maybe not needed anymore: - ForceLayerRerendering(primaryFrame, et); } else { curRule.mRule = ruleNode->GetRule(); } @@ -394,10 +366,12 @@ CommonElementAnimationData::CanAnimatePropertyOnCompositor(const dom::Element *a CanAnimateFlags aFlags) { bool shouldLog = nsLayoutUtils::IsAnimationLoggingEnabled(); - if (shouldLog && !gfxPlatform::OffMainThreadCompositingEnabled()) { - nsCString message; - message.AppendLiteral("Performance warning: Compositor disabled"); - LogAsyncAnimationFailure(message); + if (!gfxPlatform::OffMainThreadCompositingEnabled()) { + if (shouldLog) { + nsCString message; + message.AppendLiteral("Performance warning: Compositor disabled"); + LogAsyncAnimationFailure(message); + } return false; } diff --git a/layout/style/crashtests/972199-1.html b/layout/style/crashtests/972199-1.html new file mode 100644 index 00000000000..ecd57ca2a7a --- /dev/null +++ b/layout/style/crashtests/972199-1.html @@ -0,0 +1,39 @@ + + + + + + +
+ + diff --git a/layout/style/crashtests/crashtests.list b/layout/style/crashtests/crashtests.list index b4b0b245475..ce082d5b6b9 100644 --- a/layout/style/crashtests/crashtests.list +++ b/layout/style/crashtests/crashtests.list @@ -101,4 +101,5 @@ load 927734-1.html load 930270-1.html load 930270-2.html load 945048-1.html +load 972199-1.html load large_border_image_width.html diff --git a/layout/style/nsAnimationManager.h b/layout/style/nsAnimationManager.h index 9905b752a2b..69c38aedb17 100644 --- a/layout/style/nsAnimationManager.h +++ b/layout/style/nsAnimationManager.h @@ -141,7 +141,7 @@ struct ElementAnimations MOZ_FINAL // This function returns -1 for the position if the animation should not be // run (because it is not currently active and has no fill behavior), but // only does so if aAnimation is non-null; with a null aAnimation it is an - // error to give aCurrentTime < aStartTime, and fill-forwards is assumed. + // error to give aElapsedDuration < 0, and fill-forwards is assumed. // After calling GetPositionInIteration with non-null aAnimation and aEa, be // sure to call CheckNeedsRefresh on the animation manager afterwards. static double GetPositionInIteration(TimeDuration aElapsedDuration, diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index cbc800c7afb..bfd4b3cd70b 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -2757,7 +2757,7 @@ CSSParserImpl::ParseMediaQueryExpression(nsMediaQuery* aQuery) return false; } - bool rv; + bool rv = false; switch (feature->mValueType) { case nsMediaFeature::eLength: rv = ParseNonNegativeVariant(expr->mValue, VARIANT_LENGTH, nullptr); @@ -5963,6 +5963,11 @@ CSSParserImpl::TranslateDimension(nsCSSValue& aValue, } } + if (i == ArrayLength(UnitData)) { + // Unknown unit + return false; + } + if (!mViewportUnitsEnabled && (eCSSUnit_ViewportWidth == units || eCSSUnit_ViewportHeight == units || @@ -5972,11 +5977,6 @@ CSSParserImpl::TranslateDimension(nsCSSValue& aValue, // inside an @page declaration. Fail. return false; } - - if (i == ArrayLength(UnitData)) { - // Unknown unit - return false; - } } else { // Must be a zero number... NS_ASSERTION(0 == aNumber, "numbers without units must be 0"); diff --git a/layout/style/nsCSSRules.cpp b/layout/style/nsCSSRules.cpp index 73e22d444d8..5d5d344beda 100644 --- a/layout/style/nsCSSRules.cpp +++ b/layout/style/nsCSSRules.cpp @@ -37,6 +37,7 @@ #include "StyleRule.h" #include "nsFont.h" #include "nsIURI.h" +#include "mozAutoDocUpdate.h" using namespace mozilla; @@ -2374,15 +2375,23 @@ nsCSSKeyframeRule::SetKeyText(const nsAString& aKeyText) InfallibleTArray newSelectors; // FIXME: pass filename and line number - if (parser.ParseKeyframeSelectorString(aKeyText, nullptr, 0, newSelectors)) { - newSelectors.SwapElements(mKeys); - } else { + if (!parser.ParseKeyframeSelectorString(aKeyText, nullptr, 0, newSelectors)) { // for now, we don't do anything if the parse fails + return NS_OK; } + nsIDocument* doc = GetDocument(); + MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true); + + newSelectors.SwapElements(mKeys); + nsCSSStyleSheet* sheet = GetStyleSheet(); if (sheet) { sheet->SetModifiedByChildRule(); + + if (doc) { + doc->StyleRuleChanged(sheet, this, this); + } } return NS_OK; @@ -2401,6 +2410,12 @@ nsCSSKeyframeRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle) void nsCSSKeyframeRule::ChangeDeclaration(css::Declaration* aDeclaration) { + // Our caller already did a BeginUpdate/EndUpdate, but with + // UPDATE_CONTENT, and we need UPDATE_STYLE to trigger work in + // PresShell::EndUpdate. + nsIDocument* doc = GetDocument(); + MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true); + // Be careful to not assign to an nsAutoPtr if we would be assigning // the thing it already holds. if (aDeclaration != mDeclaration) { @@ -2410,6 +2425,10 @@ nsCSSKeyframeRule::ChangeDeclaration(css::Declaration* aDeclaration) nsCSSStyleSheet* sheet = GetStyleSheet(); if (sheet) { sheet->SetModifiedByChildRule(); + + if (doc) { + doc->StyleRuleChanged(sheet, this, this); + } } } @@ -2533,11 +2552,22 @@ nsCSSKeyframesRule::GetName(nsAString& aName) NS_IMETHODIMP nsCSSKeyframesRule::SetName(const nsAString& aName) { + if (mName == aName) { + return NS_OK; + } + + nsIDocument* doc = GetDocument(); + MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true); + mName = aName; nsCSSStyleSheet* sheet = GetStyleSheet(); if (sheet) { sheet->SetModifiedByChildRule(); + + if (doc) { + doc->StyleRuleChanged(sheet, this, this); + } } return NS_OK; @@ -2561,7 +2591,19 @@ nsCSSKeyframesRule::AppendRule(const nsAString& aRule) nsRefPtr rule = parser.ParseKeyframeRule(aRule, nullptr, 0); if (rule) { + nsIDocument* doc = GetDocument(); + MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true); + AppendStyleRule(rule); + + nsCSSStyleSheet* sheet = GetStyleSheet(); + if (sheet) { + sheet->SetModifiedByChildRule(); + + if (doc) { + doc->StyleRuleChanged(sheet, this, this); + } + } } return NS_OK; @@ -2597,10 +2639,18 @@ nsCSSKeyframesRule::DeleteRule(const nsAString& aKey) { uint32_t index = FindRuleIndexForKey(aKey); if (index != RULE_NOT_FOUND) { + nsIDocument* doc = GetDocument(); + MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true); + mRules.RemoveObjectAt(index); + nsCSSStyleSheet* sheet = GetStyleSheet(); if (sheet) { sheet->SetModifiedByChildRule(); + + if (doc) { + doc->StyleRuleChanged(sheet, this, this); + } } } return NS_OK; diff --git a/layout/style/test/mochitest.ini b/layout/style/test/mochitest.ini index 350023f5ec9..1d0aba60af7 100644 --- a/layout/style/test/mochitest.ini +++ b/layout/style/test/mochitest.ini @@ -201,6 +201,7 @@ skip-if = toolkit == 'android' [test_variable_serialization_computed.html] [test_variable_serialization_specified.html] [test_variables.html] +support-files = support/external-variable-url.css [test_viewport_units.html] [test_visited_image_loading.html] skip-if = toolkit == 'android' #TIMED_OUT diff --git a/layout/style/test/support/external-variable-url.css b/layout/style/test/support/external-variable-url.css new file mode 100644 index 00000000000..3570c552213 --- /dev/null +++ b/layout/style/test/support/external-variable-url.css @@ -0,0 +1,3 @@ +div { + var-a: url('image.png'); +} diff --git a/layout/style/test/test_animations.html b/layout/style/test/test_animations.html index 0d7fb506a0e..94fe7038bfc 100644 --- a/layout/style/test/test_animations.html +++ b/layout/style/test/test_animations.html @@ -1497,6 +1497,37 @@ is(cs.marginRight, "75px", "animation-name list length is the length that matter is(cs.marginTop, "25px", "animation-name list length is the length that matters"); done_div(); +var dyn_sheet_elt = document.createElement("style"); +document.head.appendChild(dyn_sheet_elt); +var dyn_sheet = dyn_sheet_elt.sheet; +dyn_sheet.insertRule("@keyframes dyn1 { from { margin-left: 0 } 50% { margin-left: 50px } to { margin-left: 100px } }", 0); +dyn_sheet.insertRule("@keyframes dyn2 { from { margin-left: 100px } to { margin-left: 200px } }", 1); +var dyn1 = dyn_sheet.cssRules[0]; +var dyn2 = dyn_sheet.cssRules[1]; +new_div("animation: dyn1 1s linear"); +is(cs.marginLeft, "0px", "dynamic rule change test, initial state"); +advance_clock(250); +is(cs.marginLeft, "25px", "dynamic rule change test, 250ms"); +dyn2.name = "dyn1"; +is(cs.marginLeft, "125px", "dynamic rule change test, change in @keyframes name applies"); +dyn2.appendRule("50% { margin-left: 0px }"); +is(cs.marginLeft, "50px", "dynamic rule change test, @keyframes appendRule"); +var dyn2_kf1 = dyn2.cssRules[0]; // currently 0% { margin-left: 100px } +dyn2_kf1.style.marginLeft = "-100px"; +// FIXME: Bug 978833 (keyframe rules used as nsIStyleRule but doesn't follow immutability contract) +todo_is(cs.marginLeft, "-50px", "dynamic rule change test, keyframe style set"); +dyn2.name = "dyn2"; +is(cs.marginLeft, "25px", "dynamic rule change test, change in @keyframes name applies (second time)"); +var dyn1_kf2 = dyn1.cssRules[1]; // currently 50% { margin-left: 50px } +dyn1_kf2.keyText = "25%"; +is(cs.marginLeft, "50px", "dynamic rule change test, change in keyframe keyText"); +dyn1.deleteRule("25%"); +is(cs.marginLeft, "25px", "dynamic rule change test, @keyframes deleteRule"); +done_div(); +dyn_sheet_elt.parentNode.removeChild(dyn_sheet_elt); +dyn_sheet_elt = null; +dyn_sheet = null; + SpecialPowers.DOMWindowUtils.restoreNormalRefresh(); diff --git a/layout/style/test/test_variables.html b/layout/style/test/test_variables.html index c97a84d66f3..7857273d5e8 100644 --- a/layout/style/test/test_variables.html +++ b/layout/style/test/test_variables.html @@ -13,6 +13,11 @@ + + +
+ diff --git a/layout/xul/nsXULPopupManager.cpp b/layout/xul/nsXULPopupManager.cpp index c0ec0bbcfa9..8e56d26c6da 100644 --- a/layout/xul/nsXULPopupManager.cpp +++ b/layout/xul/nsXULPopupManager.cpp @@ -12,7 +12,6 @@ #include "nsMenuBarListener.h" #include "nsContentUtils.h" #include "nsIDOMDocument.h" -#include "nsDOMEvent.h" #include "nsIDOMEvent.h" #include "nsIDOMXULElement.h" #include "nsIXULDocument.h" @@ -37,6 +36,7 @@ #include "nsFrameManager.h" #include "nsIObserverService.h" #include "mozilla/dom/Element.h" +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() #include "mozilla/LookAndFeel.h" #include "mozilla/MouseEvents.h" #include "mozilla/Services.h" diff --git a/layout/xul/nsXULPopupManager.h b/layout/xul/nsXULPopupManager.h index 1273ac667dc..3a325c6a54c 100644 --- a/layout/xul/nsXULPopupManager.h +++ b/layout/xul/nsXULPopupManager.h @@ -17,6 +17,7 @@ #include "nsPoint.h" #include "nsCOMPtr.h" #include "nsTArray.h" +#include "nsIObserver.h" #include "nsITimer.h" #include "nsIReflowCallback.h" #include "nsThreadUtils.h" diff --git a/layout/xul/nsXULTooltipListener.cpp b/layout/xul/nsXULTooltipListener.cpp index 6a85bc2544b..421b87cb884 100644 --- a/layout/xul/nsXULTooltipListener.cpp +++ b/layout/xul/nsXULTooltipListener.cpp @@ -5,7 +5,6 @@ #include "nsXULTooltipListener.h" -#include "nsDOMEvent.h" #include "nsIDOMMouseEvent.h" #include "nsIDOMXULDocument.h" #include "nsIDOMXULElement.h" @@ -30,6 +29,7 @@ #include "mozilla/Preferences.h" #include "mozilla/LookAndFeel.h" #include "mozilla/dom/Element.h" +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() using namespace mozilla; using namespace mozilla::dom; diff --git a/media/omx-plugin/Makefile.in b/media/omx-plugin/Makefile.in index 812c1767b07..a8e3fd0a78f 100644 --- a/media/omx-plugin/Makefile.in +++ b/media/omx-plugin/Makefile.in @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = - include $(topsrcdir)/config/rules.mk ifeq ($(MOZ_WIDGET_TOOLKIT),gonk) diff --git a/media/omx-plugin/froyo/Makefile.in b/media/omx-plugin/froyo/Makefile.in index 567cdff2f35..3ef91b2da64 100644 --- a/media/omx-plugin/froyo/Makefile.in +++ b/media/omx-plugin/froyo/Makefile.in @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = - include $(topsrcdir)/config/rules.mk EXTRA_DSO_LDOPTS += \ diff --git a/media/omx-plugin/froyo/moz.build b/media/omx-plugin/froyo/moz.build index 4d51ea03cd9..f04155c4a03 100644 --- a/media/omx-plugin/froyo/moz.build +++ b/media/omx-plugin/froyo/moz.build @@ -18,3 +18,5 @@ LOCAL_INCLUDES += [ '../include/froyo/media/stagefright/openmax', ] +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/gb/Makefile.in b/media/omx-plugin/gb/Makefile.in index bf80ffc9b8e..6261176b211 100644 --- a/media/omx-plugin/gb/Makefile.in +++ b/media/omx-plugin/gb/Makefile.in @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = - include $(topsrcdir)/config/rules.mk EXTRA_DSO_LDOPTS += \ diff --git a/media/omx-plugin/gb/moz.build b/media/omx-plugin/gb/moz.build index ff7024bd69e..3829c3b9c05 100644 --- a/media/omx-plugin/gb/moz.build +++ b/media/omx-plugin/gb/moz.build @@ -18,3 +18,5 @@ LOCAL_INCLUDES += [ '../include/gb/media/stagefright/openmax', ] +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/gb235/Makefile.in b/media/omx-plugin/gb235/Makefile.in index 83c23623a1b..6fda5a5639f 100644 --- a/media/omx-plugin/gb235/Makefile.in +++ b/media/omx-plugin/gb235/Makefile.in @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = - include $(topsrcdir)/config/rules.mk EXTRA_DSO_LDOPTS += \ diff --git a/media/omx-plugin/gb235/moz.build b/media/omx-plugin/gb235/moz.build index 7089c67931d..fc2b8b76a46 100644 --- a/media/omx-plugin/gb235/moz.build +++ b/media/omx-plugin/gb235/moz.build @@ -18,3 +18,5 @@ LOCAL_INCLUDES += [ '../include/gb/media/stagefright/openmax', ] +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/hc/Makefile.in b/media/omx-plugin/hc/Makefile.in index 3b854cab30b..fe26b7596dc 100644 --- a/media/omx-plugin/hc/Makefile.in +++ b/media/omx-plugin/hc/Makefile.in @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = - include $(topsrcdir)/config/rules.mk EXTRA_DSO_LDOPTS += \ diff --git a/media/omx-plugin/hc/moz.build b/media/omx-plugin/hc/moz.build index 16d7b373f43..513a554bfe9 100644 --- a/media/omx-plugin/hc/moz.build +++ b/media/omx-plugin/hc/moz.build @@ -18,3 +18,5 @@ LOCAL_INCLUDES += [ '../include/gb/media/stagefright/openmax', ] +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/kk/Makefile.in b/media/omx-plugin/kk/Makefile.in index 7c2a95e8cf7..9e6be39d253 100644 --- a/media/omx-plugin/kk/Makefile.in +++ b/media/omx-plugin/kk/Makefile.in @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = - include $(topsrcdir)/config/rules.mk EXTRA_DSO_LDOPTS += \ diff --git a/media/omx-plugin/kk/moz.build b/media/omx-plugin/kk/moz.build index 88fde1abdfc..183965dd9d1 100644 --- a/media/omx-plugin/kk/moz.build +++ b/media/omx-plugin/kk/moz.build @@ -18,3 +18,5 @@ LOCAL_INCLUDES += [ '../include/ics/media/stagefright/openmax', ] +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/lib/froyo/libstagefright/Makefile.in b/media/omx-plugin/lib/froyo/libstagefright/Makefile.in index 0b840e60929..a6272b4ea70 100644 --- a/media/omx-plugin/lib/froyo/libstagefright/Makefile.in +++ b/media/omx-plugin/lib/froyo/libstagefright/Makefile.in @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = - include $(topsrcdir)/config/rules.mk EXTRA_DSO_LDOPTS += \ diff --git a/media/omx-plugin/lib/froyo/libstagefright/moz.build b/media/omx-plugin/lib/froyo/libstagefright/moz.build index 9ea4c9e1fcd..cd9c2e48483 100644 --- a/media/omx-plugin/lib/froyo/libstagefright/moz.build +++ b/media/omx-plugin/lib/froyo/libstagefright/moz.build @@ -19,3 +19,5 @@ LOCAL_INCLUDES += [ '/media/omx-plugin/include/froyo/media/stagefright/openmax', ] +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/lib/gb/libstagefright/Makefile.in b/media/omx-plugin/lib/gb/libstagefright/Makefile.in index 0b840e60929..a6272b4ea70 100644 --- a/media/omx-plugin/lib/gb/libstagefright/Makefile.in +++ b/media/omx-plugin/lib/gb/libstagefright/Makefile.in @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = - include $(topsrcdir)/config/rules.mk EXTRA_DSO_LDOPTS += \ diff --git a/media/omx-plugin/lib/gb/libstagefright/moz.build b/media/omx-plugin/lib/gb/libstagefright/moz.build index 35374f1b479..9adcb0ece2c 100644 --- a/media/omx-plugin/lib/gb/libstagefright/moz.build +++ b/media/omx-plugin/lib/gb/libstagefright/moz.build @@ -19,3 +19,5 @@ LOCAL_INCLUDES += [ '/media/omx-plugin/include/gb/media/stagefright/openmax', ] +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/lib/gb/libstagefright_color_conversion/Makefile.in b/media/omx-plugin/lib/gb/libstagefright_color_conversion/Makefile.in index 73c08c97b3c..0039e347ccd 100644 --- a/media/omx-plugin/lib/gb/libstagefright_color_conversion/Makefile.in +++ b/media/omx-plugin/lib/gb/libstagefright_color_conversion/Makefile.in @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = - include $(topsrcdir)/config/rules.mk # EXTRA_DSO_LDOPTS += \ diff --git a/media/omx-plugin/lib/gb/libstagefright_color_conversion/moz.build b/media/omx-plugin/lib/gb/libstagefright_color_conversion/moz.build index b8ff7785dbc..94dd14641dd 100644 --- a/media/omx-plugin/lib/gb/libstagefright_color_conversion/moz.build +++ b/media/omx-plugin/lib/gb/libstagefright_color_conversion/moz.build @@ -19,3 +19,5 @@ LOCAL_INCLUDES += [ '/media/omx-plugin/include/gb/media/stagefright/openmax', ] +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/lib/gb/libutils/Makefile.in b/media/omx-plugin/lib/gb/libutils/Makefile.in deleted file mode 100644 index f664dc3c4ec..00000000000 --- a/media/omx-plugin/lib/gb/libutils/Makefile.in +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright 2012 Mozilla Foundation and Mozilla contributors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = diff --git a/media/omx-plugin/lib/gb/libutils/moz.build b/media/omx-plugin/lib/gb/libutils/moz.build index 6fc8df848fa..5baea328af2 100644 --- a/media/omx-plugin/lib/gb/libutils/moz.build +++ b/media/omx-plugin/lib/gb/libutils/moz.build @@ -19,3 +19,5 @@ LOCAL_INCLUDES += [ '/media/omx-plugin/include/gb/media/stagefright/openmax', ] +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/lib/gb235/libstagefright/Makefile.in b/media/omx-plugin/lib/gb235/libstagefright/Makefile.in index 0b840e60929..a6272b4ea70 100644 --- a/media/omx-plugin/lib/gb235/libstagefright/Makefile.in +++ b/media/omx-plugin/lib/gb235/libstagefright/Makefile.in @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = - include $(topsrcdir)/config/rules.mk EXTRA_DSO_LDOPTS += \ diff --git a/media/omx-plugin/lib/gb235/libstagefright/moz.build b/media/omx-plugin/lib/gb235/libstagefright/moz.build index 35374f1b479..9adcb0ece2c 100644 --- a/media/omx-plugin/lib/gb235/libstagefright/moz.build +++ b/media/omx-plugin/lib/gb235/libstagefright/moz.build @@ -19,3 +19,5 @@ LOCAL_INCLUDES += [ '/media/omx-plugin/include/gb/media/stagefright/openmax', ] +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/lib/hc/libstagefright/Makefile.in b/media/omx-plugin/lib/hc/libstagefright/Makefile.in index 0b840e60929..a6272b4ea70 100644 --- a/media/omx-plugin/lib/hc/libstagefright/Makefile.in +++ b/media/omx-plugin/lib/hc/libstagefright/Makefile.in @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = - include $(topsrcdir)/config/rules.mk EXTRA_DSO_LDOPTS += \ diff --git a/media/omx-plugin/lib/hc/libstagefright/moz.build b/media/omx-plugin/lib/hc/libstagefright/moz.build index 35374f1b479..9adcb0ece2c 100644 --- a/media/omx-plugin/lib/hc/libstagefright/moz.build +++ b/media/omx-plugin/lib/hc/libstagefright/moz.build @@ -19,3 +19,5 @@ LOCAL_INCLUDES += [ '/media/omx-plugin/include/gb/media/stagefright/openmax', ] +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/lib/ics/libstagefright/Makefile.in b/media/omx-plugin/lib/ics/libstagefright/Makefile.in index 2cb717b1a21..bb94a747f31 100644 --- a/media/omx-plugin/lib/ics/libstagefright/Makefile.in +++ b/media/omx-plugin/lib/ics/libstagefright/Makefile.in @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = - include $(topsrcdir)/config/rules.mk EXTRA_DSO_LDOPTS += \ diff --git a/media/omx-plugin/lib/ics/libstagefright/moz.build b/media/omx-plugin/lib/ics/libstagefright/moz.build index e629f4c66cb..fed780fa9a1 100644 --- a/media/omx-plugin/lib/ics/libstagefright/moz.build +++ b/media/omx-plugin/lib/ics/libstagefright/moz.build @@ -19,3 +19,5 @@ LOCAL_INCLUDES += [ '/media/omx-plugin/include/ics/media/stagefright/openmax', ] +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/lib/ics/libutils/Makefile.in b/media/omx-plugin/lib/ics/libutils/Makefile.in deleted file mode 100644 index f664dc3c4ec..00000000000 --- a/media/omx-plugin/lib/ics/libutils/Makefile.in +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright 2012 Mozilla Foundation and Mozilla contributors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = diff --git a/media/omx-plugin/lib/ics/libutils/moz.build b/media/omx-plugin/lib/ics/libutils/moz.build index 2fa0558fced..e938d5c25c5 100644 --- a/media/omx-plugin/lib/ics/libutils/moz.build +++ b/media/omx-plugin/lib/ics/libutils/moz.build @@ -19,3 +19,5 @@ LOCAL_INCLUDES += [ '/media/omx-plugin/include/ics/media/stagefright/openmax', ] +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/lib/ics/libvideoeditorplayer/Makefile.in b/media/omx-plugin/lib/ics/libvideoeditorplayer/Makefile.in index 2f1af133e62..d5219102fe1 100644 --- a/media/omx-plugin/lib/ics/libvideoeditorplayer/Makefile.in +++ b/media/omx-plugin/lib/ics/libvideoeditorplayer/Makefile.in @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = - include $(topsrcdir)/config/rules.mk INCLUDES += \ diff --git a/media/omx-plugin/lib/ics/libvideoeditorplayer/moz.build b/media/omx-plugin/lib/ics/libvideoeditorplayer/moz.build index 40e83bca89d..af91a68498f 100644 --- a/media/omx-plugin/lib/ics/libvideoeditorplayer/moz.build +++ b/media/omx-plugin/lib/ics/libvideoeditorplayer/moz.build @@ -13,3 +13,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk': LIBRARY_NAME = 'videoeditorplayer' FORCE_SHARED_LIB = True + +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/moz.build b/media/omx-plugin/moz.build index 10c89eb5174..bb217ba7034 100644 --- a/media/omx-plugin/moz.build +++ b/media/omx-plugin/moz.build @@ -53,3 +53,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': 'hardware/libhardware/include', ] ] + +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/memory/build/replace_malloc.h b/memory/build/replace_malloc.h index 371e824ad1e..1feb4fe3267 100644 --- a/memory/build/replace_malloc.h +++ b/memory/build/replace_malloc.h @@ -54,7 +54,8 @@ * Makefile.in: * MOZ_GLUE_LDFLAGS = # Don't link against mozglue * WRAP_LDFLAGS = # Never wrap malloc function calls with -Wl,--wrap - * STL_FLAGS = # Avoid STL wrapping + * and the following to the implementation's moz.build: + * DISABLE_STL_WRAPPING = True # Avoid STL wrapping * * If your replace-malloc implementation lives under memory/replace, these * are taken care of by memory/replace/defs.mk. diff --git a/memory/mozalloc/Makefile.in b/memory/mozalloc/Makefile.in index 4aee791c7ed..bec80e2182e 100644 --- a/memory/mozalloc/Makefile.in +++ b/memory/mozalloc/Makefile.in @@ -3,11 +3,6 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -STL_FLAGS = -ifdef _MSC_VER -STL_FLAGS = -D_HAS_EXCEPTIONS=0 -endif - DIST_INSTALL = 1 ifneq (,$(filter WINNT,$(OS_ARCH))) diff --git a/memory/mozalloc/moz.build b/memory/mozalloc/moz.build index 7a4a9ae5616..15978235b7f 100644 --- a/memory/mozalloc/moz.build +++ b/memory/mozalloc/moz.build @@ -22,6 +22,7 @@ if CONFIG['WRAP_STL_INCLUDES']: if CONFIG['GNU_CXX']: EXPORTS.mozilla += ['throw_gcc.h'] elif CONFIG['_MSC_VER']: + DEFINES['_HAS_EXCEPTIONS'] = 0 if build_msvc_wrappers: EXPORTS.mozilla += [ 'msvc_raise_wrappers.h', @@ -69,3 +70,5 @@ DEFINES['_GNU_SOURCE'] = True TEST_TOOL_DIRS += ['tests'] GENERATED_INCLUDES += ['/xpcom'] + +DISABLE_STL_WRAPPING = True diff --git a/memory/replace/defs.mk b/memory/replace/defs.mk index 68d1b8c9273..6bfb5d9b04c 100644 --- a/memory/replace/defs.mk +++ b/memory/replace/defs.mk @@ -1,3 +1,2 @@ MOZ_GLUE_LDFLAGS = # Don't link against mozglue WRAP_LDFLAGS = # Never wrap malloc function calls with -Wl,--wrap -STL_FLAGS = # Avoid STL wrapping diff --git a/memory/replace/dmd/Makefile.in b/memory/replace/dmd/Makefile.in index ea585d81c80..f5006f56e8d 100644 --- a/memory/replace/dmd/Makefile.in +++ b/memory/replace/dmd/Makefile.in @@ -7,8 +7,6 @@ WRAP_LDFLAGS = MOZ_GLUE_LDFLAGS= -STL_FLAGS = - ifeq ($(OS_ARCH),WINNT) OS_LIBS += $(call EXPAND_LIBNAME,dbghelp) endif diff --git a/memory/replace/dmd/moz.build b/memory/replace/dmd/moz.build index 8c08f84d498..59bb34bb8e0 100644 --- a/memory/replace/dmd/moz.build +++ b/memory/replace/dmd/moz.build @@ -26,3 +26,5 @@ DEFINES['MOZ_NO_MOZALLOC'] = True if CONFIG['MOZ_OPTIMIZE']: DEFINES['MOZ_OPTIMIZE'] = True + +DISABLE_STL_WRAPPING = True diff --git a/memory/replace/dummy/moz.build b/memory/replace/dummy/moz.build index b9931b3baf1..7d2c185c85e 100644 --- a/memory/replace/dummy/moz.build +++ b/memory/replace/dummy/moz.build @@ -12,3 +12,5 @@ SOURCES += [ LIBRARY_NAME = 'replace_malloc' FORCE_SHARED_LIB = True + +DISABLE_STL_WRAPPING = True diff --git a/memory/replace/jemalloc/moz.build b/memory/replace/jemalloc/moz.build index 22f5a7aefa2..85197b2235b 100644 --- a/memory/replace/jemalloc/moz.build +++ b/memory/replace/jemalloc/moz.build @@ -28,3 +28,5 @@ DEFINES['MOZ_REPLACE_JEMALLOC'] = True GENERATED_INCLUDES += ['../../jemalloc/src/include'] if CONFIG['_MSC_VER']: LOCAL_INCLUDES += ['/memory/jemalloc/src/include/msvc_compat'] + +DISABLE_STL_WRAPPING = True diff --git a/memory/replace/moz.build b/memory/replace/moz.build index cb00e573fa9..abd231e8400 100644 --- a/memory/replace/moz.build +++ b/memory/replace/moz.build @@ -7,3 +7,5 @@ # Build jemalloc3 as a replace-malloc lib when building with mozjemalloc if not CONFIG['MOZ_JEMALLOC']: DIRS += ['jemalloc'] + +DISABLE_STL_WRAPPING = True diff --git a/mfbt/Makefile.in b/mfbt/Makefile.in index ded3e30ce19..6fbe8159b2d 100644 --- a/mfbt/Makefile.in +++ b/mfbt/Makefile.in @@ -1,5 +1,3 @@ # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. - -STL_FLAGS = diff --git a/mfbt/moz.build b/mfbt/moz.build index d5594ef750a..e4ec5107f46 100644 --- a/mfbt/moz.build +++ b/mfbt/moz.build @@ -89,3 +89,5 @@ SOURCES += [ 'Compression.cpp', 'decimal/Decimal.cpp', ] + +DISABLE_STL_WRAPPING = True diff --git a/mfbt/tests/Makefile.in b/mfbt/tests/Makefile.in index 77d167b19c0..c154f9aa480 100644 --- a/mfbt/tests/Makefile.in +++ b/mfbt/tests/Makefile.in @@ -2,8 +2,6 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. -STL_FLAGS = - # in order to prevent rules.mk from trying to link to libraries that are # not available to MFBT, we have to reset these MOZ_GLUE*_LDFLAGS before including it # and LIBS_ after including it. For WRAP_LDFLAGS, it shouldn't matter. diff --git a/mfbt/tests/moz.build b/mfbt/tests/moz.build index 3a701d985b7..2163a5f3279 100644 --- a/mfbt/tests/moz.build +++ b/mfbt/tests/moz.build @@ -29,3 +29,5 @@ if not CONFIG['MOZ_ASAN']: # Since we link directly with MFBT object files, define IMPL_MFBT DEFINES['IMPL_MFBT'] = True + +DISABLE_STL_WRAPPING = True diff --git a/mobile/android/app/Makefile.in b/mobile/android/app/Makefile.in index 74ed77201a7..8aaa75ad435 100644 --- a/mobile/android/app/Makefile.in +++ b/mobile/android/app/Makefile.in @@ -8,8 +8,6 @@ PREF_JS_EXPORTS = $(srcdir)/mobile.js ifndef LIBXUL_SDK ifneq (Android,$(OS_TARGET)) -STL_FLAGS= - LIBS += \ $(XPCOM_STANDALONE_GLUE_LDOPTS) \ $(NULL) diff --git a/mobile/android/app/moz.build b/mobile/android/app/moz.build index 963d4ee98dd..735ac4a3c1f 100644 --- a/mobile/android/app/moz.build +++ b/mobile/android/app/moz.build @@ -14,6 +14,7 @@ if not CONFIG['LIBXUL_SDK']: '/xpcom/base', '/xpcom/build', ] + DISABLE_STL_WRAPPING = True for var in ('APP_NAME', 'APP_VERSION'): DEFINES[var] = CONFIG['MOZ_%s' % var] diff --git a/mobile/android/base/BrowserApp.java b/mobile/android/base/BrowserApp.java index 17a1f279686..deb79dbf230 100644 --- a/mobile/android/base/BrowserApp.java +++ b/mobile/android/base/BrowserApp.java @@ -2136,6 +2136,11 @@ abstract public class BrowserApp extends GeckoApp } save.setVisible(!GeckoProfile.get(this).inGuestMode()); + if (tab.isBookmark() || tab.isReadingListItem()) { + save.setIcon(R.drawable.ic_menu_bookmark_remove); + } else { + save.setIcon(R.drawable.ic_menu_bookmark_add); + } bookmark.setEnabled(!AboutPages.isAboutReader(tab.getURL())); bookmark.setChecked(tab.isBookmark()); diff --git a/mobile/android/base/GeckoApp.java b/mobile/android/base/GeckoApp.java index 51e6d801845..341343fa1b2 100644 --- a/mobile/android/base/GeckoApp.java +++ b/mobile/android/base/GeckoApp.java @@ -1305,6 +1305,11 @@ public abstract class GeckoApp mGeckoLayout = (RelativeLayout) findViewById(R.id.gecko_layout); mMainLayout = (RelativeLayout) findViewById(R.id.main_layout); + // Removing the view clipping causes layout issues on < 3.0 (bug 978796). + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { + mMainLayout.setClipChildren(true); + } + // Determine whether we should restore tabs. mShouldRestore = getSessionRestoreState(savedInstanceState); if (mShouldRestore && savedInstanceState != null) { diff --git a/mobile/android/base/db/BrowserContract.java b/mobile/android/base/db/BrowserContract.java index c632aaea6f7..9462473bdeb 100644 --- a/mobile/android/base/db/BrowserContract.java +++ b/mobile/android/base/db/BrowserContract.java @@ -372,12 +372,12 @@ public class BrowserContract { } static final String TABLE_BOOKMARKS_JOIN_IMAGES = Bookmarks.TABLE_NAME + " LEFT OUTER JOIN " + - Obsolete.TABLE_IMAGES + " ON " + DBUtils.qualifyColumn(Bookmarks.TABLE_NAME, Bookmarks.URL) + " = " + - DBUtils.qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.URL); + Obsolete.TABLE_IMAGES + " ON " + Bookmarks.TABLE_NAME + "." + Bookmarks.URL + " = " + + Obsolete.TABLE_IMAGES + "." + Obsolete.Images.URL; static final String TABLE_HISTORY_JOIN_IMAGES = History.TABLE_NAME + " LEFT OUTER JOIN " + - Obsolete.TABLE_IMAGES + " ON " + DBUtils.qualifyColumn(Bookmarks.TABLE_NAME, History.URL) + " = " + - DBUtils.qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.URL); + Obsolete.TABLE_IMAGES + " ON " + Bookmarks.TABLE_NAME + "." + History.URL + " = " + + Obsolete.TABLE_IMAGES + "." + Obsolete.Images.URL; static final String FAVICON_DB = "favicon_urls.db"; } diff --git a/mobile/android/base/resources/drawable-hdpi/progress.9.png b/mobile/android/base/resources/drawable-hdpi/progress.9.png index f3fe0bdaf5a..ae39f6583c7 100644 Binary files a/mobile/android/base/resources/drawable-hdpi/progress.9.png and b/mobile/android/base/resources/drawable-hdpi/progress.9.png differ diff --git a/mobile/android/base/resources/drawable-mdpi/progress.9.png b/mobile/android/base/resources/drawable-mdpi/progress.9.png index 34725059357..31d7f0bd004 100644 Binary files a/mobile/android/base/resources/drawable-mdpi/progress.9.png and b/mobile/android/base/resources/drawable-mdpi/progress.9.png differ diff --git a/mobile/android/base/resources/drawable-xhdpi/progress.9.png b/mobile/android/base/resources/drawable-xhdpi/progress.9.png index a37de873f1d..f9cfb79c91e 100644 Binary files a/mobile/android/base/resources/drawable-xhdpi/progress.9.png and b/mobile/android/base/resources/drawable-xhdpi/progress.9.png differ diff --git a/mobile/android/base/resources/layout/browser_toolbar.xml b/mobile/android/base/resources/layout/browser_toolbar.xml index 7f567ff80b3..bd6f15349c0 100644 --- a/mobile/android/base/resources/layout/browser_toolbar.xml +++ b/mobile/android/base/resources/layout/browser_toolbar.xml @@ -107,7 +107,8 @@ + android:background="@android:color/transparent" + android:clipChildren="false"> window.close(), false); + } let sumoLink = Services.urlFormatter.formatURLPref("app.support.baseURL"); document.getElementById("sumo-link").href = sumoLink; diff --git a/mobile/android/chrome/content/aboutFeedback.xhtml b/mobile/android/chrome/content/aboutFeedback.xhtml index 1b77dac605c..afe5159b6ea 100644 --- a/mobile/android/chrome/content/aboutFeedback.xhtml +++ b/mobile/android/chrome/content/aboutFeedback.xhtml @@ -35,6 +35,7 @@ @@ -50,7 +51,7 @@ diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index 04260e069a4..e42b2a0873e 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -3974,6 +3974,9 @@ pref("layers.offmainthreadcomposition.force-basic", false); // Whether to animate simple opacity and transforms on the compositor pref("layers.offmainthreadcomposition.async-animations", false); +// Whether to log information about off main thread animations to stderr +pref("layers.offmainthreadcomposition.log-animations", false); + pref("layers.bufferrotation.enabled", true); pref("layers.componentalpha.enabled", true); diff --git a/mozglue/android/Makefile.in b/mozglue/android/Makefile.in index faa3246e8bc..3c8062a29a5 100644 --- a/mozglue/android/Makefile.in +++ b/mozglue/android/Makefile.in @@ -2,8 +2,6 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -STL_FLAGS= - include $(topsrcdir)/config/rules.mk prcpucfg.h: $(topsrcdir)/nsprpub/pr/include/md/_linux.cfg diff --git a/mozglue/android/moz.build b/mozglue/android/moz.build index 3d8389220a9..37baa923e4d 100644 --- a/mozglue/android/moz.build +++ b/mozglue/android/moz.build @@ -48,3 +48,5 @@ LOCAL_INCLUDES += [ '/toolkit/components/startup', '/xpcom/build', ] + +DISABLE_STL_WRAPPING = True diff --git a/mozglue/build/Makefile.in b/mozglue/build/Makefile.in index ab6d88125df..6c83b36dc43 100644 --- a/mozglue/build/Makefile.in +++ b/mozglue/build/Makefile.in @@ -50,8 +50,6 @@ EXTRA_DSO_LDOPTS += \ $(call EXPAND_LIBNAME,version) \ $(NULL) -STL_FLAGS= - endif ifeq (Darwin_1,$(OS_TARGET)_$(MOZ_REPLACE_MALLOC)) diff --git a/mozglue/build/moz.build b/mozglue/build/moz.build index 3b01cf2be56..d4130460183 100644 --- a/mozglue/build/moz.build +++ b/mozglue/build/moz.build @@ -32,6 +32,7 @@ if CONFIG['OS_TARGET'] == 'WINNT': 'WindowsDllBlocklist.cpp', ] DEFFILE = 'mozglue.def' + DISABLE_STL_WRAPPING = True if CONFIG['MOZ_NUWA_PROCESS']: EXPORTS.ipc += [ diff --git a/mozglue/linker/Makefile.in b/mozglue/linker/Makefile.in index 2e1e372d223..e4351daf85b 100644 --- a/mozglue/linker/Makefile.in +++ b/mozglue/linker/Makefile.in @@ -2,8 +2,6 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. -STL_FLAGS = - HOST_LIBS = -lz include $(topsrcdir)/config/rules.mk diff --git a/mozglue/linker/moz.build b/mozglue/linker/moz.build index d953c9b400a..36c859b420b 100644 --- a/mozglue/linker/moz.build +++ b/mozglue/linker/moz.build @@ -24,3 +24,5 @@ HOST_PROGRAM = 'szip' FINAL_LIBRARY = 'mozglue' DEFINES['IMPL_MFBT'] = True + +DISABLE_STL_WRAPPING = True diff --git a/mozglue/tests/Makefile.in b/mozglue/tests/Makefile.in index 6ec472d08e8..d93c6fdb4f7 100644 --- a/mozglue/tests/Makefile.in +++ b/mozglue/tests/Makefile.in @@ -3,8 +3,6 @@ # You can obtain one at http://mozilla.org/MPL/2.0/. ifdef MOZ_LINKER -STL_FLAGS = - # Only link against the linker, not mozglue MOZ_GLUE_PROGRAM_LDFLAGS = MOZ_GLUE_LDFLAGS = diff --git a/mozglue/tests/moz.build b/mozglue/tests/moz.build index e15e447e617..a0dbb6bc834 100644 --- a/mozglue/tests/moz.build +++ b/mozglue/tests/moz.build @@ -15,3 +15,4 @@ if CONFIG['MOZ_LINKER']: 'TestZip', ] LOCAL_INCLUDES += ['../linker'] + DISABLE_STL_WRAPPING = True diff --git a/parser/html/javasrc/TreeBuilder.java b/parser/html/javasrc/TreeBuilder.java index 4b62af7e34d..05e5a393b43 100644 --- a/parser/html/javasrc/TreeBuilder.java +++ b/parser/html/javasrc/TreeBuilder.java @@ -4638,10 +4638,22 @@ public abstract class TreeBuilder implements TokenHandler, int bookmark = formattingEltListPos; int nodePos = furthestBlockPos; StackNode lastNode = furthestBlock; // weak ref - for (int j = 0; j < 3; ++j) { + int j = 0; + for (;;) { + ++j; nodePos--; + if (nodePos == formattingEltStackPos) { + break; + } StackNode node = stack[nodePos]; // weak ref int nodeListPos = findInListOfActiveFormattingElements(node); + + if (j > 3 && nodeListPos != -1) { + removeFromListOfActiveFormattingElements(nodeListPos); + // Update position to reflect removal from list. + nodeListPos = -1; + } + if (nodeListPos == -1) { assert formattingEltStackPos < nodePos; assert bookmark < nodePos; @@ -4652,9 +4664,6 @@ public abstract class TreeBuilder implements TokenHandler, continue; } // now node is both on stack and in the list - if (nodePos == formattingEltStackPos) { - break; - } if (nodePos == furthestBlockPos) { bookmark = nodeListPos + 1; } diff --git a/parser/html/nsHtml5TreeBuilder.cpp b/parser/html/nsHtml5TreeBuilder.cpp index 88acc937afd..7d203b322e5 100644 --- a/parser/html/nsHtml5TreeBuilder.cpp +++ b/parser/html/nsHtml5TreeBuilder.cpp @@ -3557,10 +3557,19 @@ nsHtml5TreeBuilder::adoptionAgencyEndTag(nsIAtom* name) int32_t bookmark = formattingEltListPos; int32_t nodePos = furthestBlockPos; nsHtml5StackNode* lastNode = furthestBlock; - for (int32_t j = 0; j < 3; ++j) { + int32_t j = 0; + for (; ; ) { + ++j; nodePos--; + if (nodePos == formattingEltStackPos) { + break; + } nsHtml5StackNode* node = stack[nodePos]; int32_t nodeListPos = findInListOfActiveFormattingElements(node); + if (j > 3 && nodeListPos != -1) { + removeFromListOfActiveFormattingElements(nodeListPos); + nodeListPos = -1; + } if (nodeListPos == -1) { MOZ_ASSERT(formattingEltStackPos < nodePos); MOZ_ASSERT(bookmark < nodePos); @@ -3569,9 +3578,6 @@ nsHtml5TreeBuilder::adoptionAgencyEndTag(nsIAtom* name) furthestBlockPos--; continue; } - if (nodePos == formattingEltStackPos) { - break; - } if (nodePos == furthestBlockPos) { bookmark = nodeListPos + 1; } diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/adoption02.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/adoption02.dat index e54d8033bac..8d69dccce14 100644 --- a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/adoption02.dat +++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/adoption02.dat @@ -37,3 +37,27 @@ |
| | + +#data +second
first
+#errors +3: Start tag seen without seeing a doctype first. Expected "". +25: End tag "b" violates nesting rules. +34: Stray end tag "b". +63: Stray end tag "i". +#document +| +| +| +| +| +| +| +| +| +| +| +|
+| +| "first" +| "second" diff --git a/profile/dirserviceprovider/src/Makefile.in b/profile/dirserviceprovider/src/Makefile.in deleted file mode 100644 index 5032b1cf7c2..00000000000 --- a/profile/dirserviceprovider/src/Makefile.in +++ /dev/null @@ -1,7 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -include $(topsrcdir)/config/rules.mk - -STL_FLAGS = diff --git a/profile/dirserviceprovider/src/moz.build b/profile/dirserviceprovider/src/moz.build index 7c4ab1b3746..688df62d006 100644 --- a/profile/dirserviceprovider/src/moz.build +++ b/profile/dirserviceprovider/src/moz.build @@ -13,3 +13,5 @@ LIBRARY_NAME = 'profdirserviceprovidersa_s' FORCE_STATIC_LIB = True DEFINES['XPCOM_GLUE'] = 1 + +DISABLE_STL_WRAPPING = True diff --git a/python/mozbuild/mozbuild/backend/recursivemake.py b/python/mozbuild/mozbuild/backend/recursivemake.py index 5288a576dd3..8e6d1384f83 100644 --- a/python/mozbuild/mozbuild/backend/recursivemake.py +++ b/python/mozbuild/mozbuild/backend/recursivemake.py @@ -1091,7 +1091,7 @@ class RecursiveMakeBackend(CommonBackend): def _process_per_source_flag(self, per_source_flag, backend_file): for flag in per_source_flag.flags: - backend_file.write('%s_FLAGS += %s\n' % (per_source_flag.file_name, flag)) + backend_file.write('%s_FLAGS += %s\n' % (mozpath.basename(per_source_flag.file_name), flag)) def _process_java_jar_data(self, jar, backend_file): target = jar.name diff --git a/python/mozbuild/mozbuild/frontend/emitter.py b/python/mozbuild/mozbuild/frontend/emitter.py index 6795aa28411..275d81cf69a 100644 --- a/python/mozbuild/mozbuild/frontend/emitter.py +++ b/python/mozbuild/mozbuild/frontend/emitter.py @@ -217,6 +217,7 @@ class TreeMetadataEmitter(LoggingMixin): 'ANDROID_GENERATED_RESFILES', 'ANDROID_RES_DIRS', 'CPP_UNIT_TESTS', + 'DISABLE_STL_WRAPPING', 'EXPORT_LIBRARY', 'EXTRA_ASSEMBLER_FLAGS', 'EXTRA_COMPILE_FLAGS', @@ -241,6 +242,7 @@ class TreeMetadataEmitter(LoggingMixin): 'OS_LIBS', 'RCFILE', 'RESFILE', + 'RCINCLUDE', 'DEFFILE', 'SDK_LIBRARY', 'WIN32_EXE_LDFLAGS', diff --git a/python/mozbuild/mozbuild/frontend/sandbox_symbols.py b/python/mozbuild/mozbuild/frontend/sandbox_symbols.py index ac8cbbcddad..238b5771ee5 100644 --- a/python/mozbuild/mozbuild/frontend/sandbox_symbols.py +++ b/python/mozbuild/mozbuild/frontend/sandbox_symbols.py @@ -178,6 +178,11 @@ VARIABLES = { delimiters. """, None), + 'DISABLE_STL_WRAPPING': (bool, bool, + """Disable the wrappers for STL which allow it to work with C++ exceptions + disabled. + """, 'binaries'), + 'EXPORT_LIBRARY': (bool, bool, """Install the library to the static libraries folder. """, None), @@ -349,6 +354,12 @@ VARIABLES = { This variable can only be used on Windows. """, None), + 'RCINCLUDE': (unicode, unicode, + """The resource script file to be included in the default .res file. + + This variable can only be used on Windows. + """, None), + 'DEFFILE': (unicode, unicode, """The program .def (module definition) file. diff --git a/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build b/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build index 8b0b99bbc7d..aa9bcb5aa17 100644 --- a/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build +++ b/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build @@ -38,6 +38,7 @@ DELAYLOAD_DLLS = ['foo.dll', 'bar.dll'] RCFILE = 'foo.rc' RESFILE = 'bar.res' +RCINCLUDE = 'bar.rc' DEFFILE = 'baz.def' USE_STATIC_LIBS = True @@ -46,3 +47,5 @@ CFLAGS += ['-fno-exceptions', '-w'] CXXFLAGS += ['-fcxx-exceptions', '-include foo.h'] LDFLAGS += ['-framework Foo', '-x'] WIN32_EXE_LDFLAGS += ['-subsystem:console'] + +DISABLE_STL_WRAPPING = True diff --git a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py index a4823fbea38..3d7a2cc7822 100644 --- a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py +++ b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py @@ -269,6 +269,9 @@ class TestRecursiveMakeBackend(BackendTester): 'CSRCS += bar.c', 'CSRCS += foo.c', ], + 'DISABLE_STL_WRAPPING': [ + 'DISABLE_STL_WRAPPING := 1', + ], 'EXTRA_COMPONENTS': [ 'EXTRA_COMPONENTS += bar.js', 'EXTRA_COMPONENTS += foo.js', @@ -334,6 +337,9 @@ class TestRecursiveMakeBackend(BackendTester): 'RESFILE': [ 'RESFILE := bar.res', ], + 'RCINCLUDE': [ + 'RCINCLUDE := bar.rc', + ], 'DEFFILE': [ 'DEFFILE := baz.def', ], diff --git a/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build b/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build index 19df3d11418..4fbba04676d 100644 --- a/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build +++ b/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build @@ -44,6 +44,7 @@ DELAYLOAD_DLLS = ['foo.dll', 'bar.dll'] RCFILE = 'foo.rc' RESFILE = 'bar.res' +RCINCLUDE = 'bar.rc' DEFFILE = 'baz.def' USE_STATIC_LIBS = True @@ -52,3 +53,5 @@ CFLAGS += ['-fno-exceptions', '-w'] CXXFLAGS += ['-fcxx-exceptions', '-include foo.h'] LDFLAGS += ['-framework Foo', '-x'] WIN32_EXE_LDFLAGS += ['-subsystem:console'] + +DISABLE_STL_WRAPPING = True diff --git a/python/mozbuild/mozbuild/test/frontend/test_emitter.py b/python/mozbuild/mozbuild/test/frontend/test_emitter.py index d4aae3ed085..0bf986964ae 100644 --- a/python/mozbuild/mozbuild/test/frontend/test_emitter.py +++ b/python/mozbuild/mozbuild/test/frontend/test_emitter.py @@ -151,6 +151,7 @@ class TestEmitterBasic(unittest.TestCase): CMMSRCS=['fans.mm', 'tans.mm'], CSRCS=['fans.c', 'tans.c'], CPP_UNIT_TESTS=['foo.cpp'], + DISABLE_STL_WRAPPING=True, EXPORT_LIBRARY=True, EXTRA_COMPONENTS=['fans.js', 'tans.js'], EXTRA_PP_COMPONENTS=['fans.pp.js', 'tans.pp.js'], @@ -174,6 +175,7 @@ class TestEmitterBasic(unittest.TestCase): USE_DELAYIMP=True, RCFILE='foo.rc', RESFILE='bar.res', + RCINCLUDE='bar.rc', DEFFILE='baz.def', USE_STATIC_LIBS=True, MOZBUILD_CFLAGS=['-fno-exceptions', '-w'], diff --git a/security/sandbox/Makefile.in b/security/sandbox/Makefile.in index 67133c4cd6a..05cc77d5967 100644 --- a/security/sandbox/Makefile.in +++ b/security/sandbox/Makefile.in @@ -3,7 +3,6 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. ifeq ($(OS_ARCH),WINNT) -STL_FLAGS = MOZ_GLUE_LDFLAGS = endif diff --git a/security/sandbox/linux/Sandbox.cpp b/security/sandbox/linux/Sandbox.cpp index 5256b7e76ad..a0076cfcbaf 100644 --- a/security/sandbox/linux/Sandbox.cpp +++ b/security/sandbox/linux/Sandbox.cpp @@ -221,6 +221,15 @@ InstallSyscallReporter(void) static int InstallSyscallFilter(void) { +#ifdef MOZ_DMD + char* e = PR_GetEnv("DMD"); + if (e && strcmp(e, "") != 0 && strcmp(e, "0") != 0) { + LOG_ERROR("SANDBOX DISABLED FOR DMD! See bug 956961."); + // Must treat this as "failure" in order to prevent infinite loop; + // cf. the PR_GET_SECCOMP check below. + return 1; + } +#endif if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { return 1; } diff --git a/security/sandbox/moz.build b/security/sandbox/moz.build index 40c2502892f..5263fb19396 100644 --- a/security/sandbox/moz.build +++ b/security/sandbox/moz.build @@ -128,3 +128,5 @@ elif CONFIG['OS_ARCH'] == 'WINNT': LOCAL_INCLUDES += ['/security/sandbox/chromium'] LOCAL_INCLUDES += ['/security'] LOCAL_INCLUDES += ['/nsprpub'] + + DISABLE_STL_WRAPPING = True diff --git a/security/sandbox/win/src/sandboxbroker/Makefile.in b/security/sandbox/win/src/sandboxbroker/Makefile.in index c1eb29a145c..9393b2dfa2e 100644 --- a/security/sandbox/win/src/sandboxbroker/Makefile.in +++ b/security/sandbox/win/src/sandboxbroker/Makefile.in @@ -3,7 +3,6 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. # MOZ_GLUE_LDFLAGS = -STL_FLAGS = SHARED_LIBRARY_LIBS += \ ../../../$(LIB_PREFIX)sandbox_s.$(LIB_SUFFIX) \ diff --git a/security/sandbox/win/src/sandboxbroker/moz.build b/security/sandbox/win/src/sandboxbroker/moz.build index bc2972582f5..04ad0ee924e 100644 --- a/security/sandbox/win/src/sandboxbroker/moz.build +++ b/security/sandbox/win/src/sandboxbroker/moz.build @@ -27,3 +27,4 @@ LOCAL_INCLUDES += [ '/security/sandbox/chromium', ] +DISABLE_STL_WRAPPING = True diff --git a/testing/mochitest/androidx86.json b/testing/mochitest/androidx86.json index 75a82856227..a2072e2ba14 100644 --- a/testing/mochitest/androidx86.json +++ b/testing/mochitest/androidx86.json @@ -119,6 +119,7 @@ "dom/datastore/tests/test_sync.html": "x86 only bug 936226", "image/test/mochitest/test_bug490949.html": "x86 only", "image/test/mochitest/test_bug497665.html": "x86 only", + "image/test/mochitest/test_bug601470.html": "x86 only", "image/test/mochitest/test_bug671906.html": "x86 only", "image/test/mochitest/test_bug89419-1.html": "x86 only", "image/test/mochitest/test_bug89419-2.html": "x86 only", diff --git a/testing/mochitest/ssltunnel/Makefile.in b/testing/mochitest/ssltunnel/Makefile.in index 9936c4eb5ac..16214651cc2 100644 --- a/testing/mochitest/ssltunnel/Makefile.in +++ b/testing/mochitest/ssltunnel/Makefile.in @@ -3,10 +3,6 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# This isn't XPCOM code, but it wants to use STL, so disable the STL -# wrappers -STL_FLAGS = - LIBS = \ $(NSPR_LIBS) \ $(NSS_LIBS) \ diff --git a/testing/mochitest/ssltunnel/moz.build b/testing/mochitest/ssltunnel/moz.build index 862474cb660..835e3237925 100644 --- a/testing/mochitest/ssltunnel/moz.build +++ b/testing/mochitest/ssltunnel/moz.build @@ -9,3 +9,7 @@ PROGRAM = 'ssltunnel' SOURCES += [ 'ssltunnel.cpp', ] + +# This isn't XPCOM code, but it wants to use STL, so disable the STL +# wrappers +DISABLE_STL_WRAPPING = True diff --git a/toolkit/components/maintenanceservice/Makefile.in b/toolkit/components/maintenanceservice/Makefile.in index 885c4fe06c5..78374c7d763 100644 --- a/toolkit/components/maintenanceservice/Makefile.in +++ b/toolkit/components/maintenanceservice/Makefile.in @@ -8,7 +8,6 @@ DIST_PROGRAM = maintenanceservice$(BIN_SUFFIX) # bug 725876 MOZ_GLUE_LDFLAGS = MOZ_GLUE_PROGRAM_LDFLAGS = -STL_FLAGS= ifeq ($(OS_ARCH),WINNT) LIBS += $(call EXPAND_LIBNAME_PATH,updatecommon-standalone,../../mozapps/update/common-standalone) @@ -16,8 +15,6 @@ else LIBS += $(call EXPAND_LIBNAME_PATH,updatecommon,../../mozapps/update/common) endif -RCINCLUDE = maintenanceservice.rc - OS_LIBS += $(call EXPAND_LIBNAME,comctl32 ws2_32 shell32) ifndef MOZ_WINCONSOLE diff --git a/toolkit/components/maintenanceservice/moz.build b/toolkit/components/maintenanceservice/moz.build index fa62779a7b9..06532c3ba06 100644 --- a/toolkit/components/maintenanceservice/moz.build +++ b/toolkit/components/maintenanceservice/moz.build @@ -32,3 +32,7 @@ USE_STATIC_LIBS = True if CONFIG['_MSC_VER']: WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup'] + +RCINCLUDE = 'maintenanceservice.rc' + +DISABLE_STL_WRAPPING = True diff --git a/toolkit/components/places/BookmarkJSONUtils.jsm b/toolkit/components/places/BookmarkJSONUtils.jsm index a76be582072..a52d7f1af6b 100644 --- a/toolkit/components/places/BookmarkJSONUtils.jsm +++ b/toolkit/components/places/BookmarkJSONUtils.jsm @@ -108,29 +108,6 @@ this.BookmarkJSONUtils = Object.freeze({ }); }, - /** - * Takes a JSON-serialized node and inserts it into the db. - * - * @param aData - * The unwrapped data blob of dropped or pasted data. - * @param aContainer - * The container the data was dropped or pasted into - * @param aIndex - * The index within the container the item was dropped or pasted at - * @return {Promise} - * @resolves an array containing of maps of old folder ids to new folder ids, - * and an array of saved search ids that need to be fixed up. - * eg: [[[oldFolder1, newFolder1]], [search1]] - * @rejects JavaScript exception. - */ - importJSONNode: function BJU_importJSONNode(aData, aContainer, aIndex, - aGrandParentId) { - let importer = new BookmarkImporter(); - // Can't make importJSONNode a task until we have made the - // runInBatchMode in BI_importFromJSON to run asynchronously. Bug 890203 - return Promise.resolve(importer.importJSONNode(aData, aContainer, aIndex, aGrandParentId)); - }, - /** * Serializes the given node (and all its descendents) as JSON * and writes the serialization to the given output stream. @@ -141,24 +118,19 @@ this.BookmarkJSONUtils = Object.freeze({ * An nsIOutputStream. NOTE: it only uses the write(str, len) * method of nsIOutputStream. The caller is responsible for * closing the stream. - * @param aIsUICommand - * Boolean - If true, modifies serialization so that each node self-contained. - * For Example, tags are serialized inline with each bookmark. - * @param aResolveShortcuts - * Converts folder shortcuts into actual folders. - * @param aExcludeItems - * An array of item ids that should not be written to the backup. * @return {Promise} * @resolves When node have been serialized and wrote to output stream. * @rejects JavaScript exception. + * + * @note This is likely to go away (bug 970291), so it's suggested to not + * add more uses of it. This is not yet firing a deprecation warning + * cause it still has some internal usage. */ - serializeNodeAsJSONToOutputStream: function BJU_serializeNodeAsJSONToOutputStream( - aNode, aStream, aIsUICommand, aResolveShortcuts, aExcludeItems) { + serializeNodeAsJSONToOutputStream: function (aNode, aStream) { let deferred = Promise.defer(); Services.tm.mainThread.dispatch(function() { try { - BookmarkNode.serializeAsJSONToOutputStream( - aNode, aStream, aIsUICommand, aResolveShortcuts, aExcludeItems); + BookmarkNode.serializeAsJSONToOutputStream(aNode, aStream); deferred.resolve(); } catch (ex) { deferred.reject(ex); @@ -553,26 +525,15 @@ let BookmarkNode = { * An nsIOutputStream. NOTE: it only uses the write(str, len) * method of nsIOutputStream. The caller is responsible for * closing the stream. - * @param aIsUICommand - * Boolean - If true, modifies serialization so that each node self-contained. - * For Example, tags are serialized inline with each bookmark. - * @param aResolveShortcuts - * Converts folder shortcuts into actual folders. - * @param aExcludeItems - * An array of item ids that should not be written to the backup. * @returns Task promise * @resolves the number of serialized uri nodes. */ - serializeAsJSONToOutputStream: function BN_serializeAsJSONToOutputStream( - aNode, aStream, aIsUICommand, aResolveShortcuts, aExcludeItems) { + serializeAsJSONToOutputStream: function (aNode, aStream) { return Task.spawn(function* () { // Serialize to stream let array = []; - let result = yield this._appendConvertedNode(aNode, null, array, - aIsUICommand, - aResolveShortcuts, - aExcludeItems); + let result = yield this._appendConvertedNode(aNode, null, array); if (result.appendedNode) { let jsonString = JSON.stringify(array[0]); aStream.write(jsonString, jsonString.length); @@ -583,8 +544,7 @@ let BookmarkNode = { }.bind(this)); }, - _appendConvertedNode: function BN__appendConvertedNode( - bNode, aIndex, aArray, aIsUICommand, aResolveShortcuts, aExcludeItems) { + _appendConvertedNode: function (bNode, aIndex, aArray) { return Task.spawn(function* () { let node = {}; let nodeCount = 0; @@ -595,7 +555,7 @@ let BookmarkNode = { if (aIndex) node.index = aIndex; - this._addGenericProperties(bNode, node, aResolveShortcuts); + this._addGenericProperties(bNode, node); let parent = bNode.parent; let grandParent = parent ? parent.parent : null; @@ -614,15 +574,14 @@ let BookmarkNode = { return { appendedNode: false, nodeCount: nodeCount }; } - yield this._addURIProperties(bNode, node, aIsUICommand); + yield this._addURIProperties(bNode, node); nodeCount++; } else if (PlacesUtils.nodeIsContainer(bNode)) { // Tag containers accept only uri nodes if (grandParent && grandParent.itemId == PlacesUtils.tagsFolderId) return { appendedNode: false, nodeCount: nodeCount }; - this._addContainerProperties(bNode, node, aIsUICommand, - aResolveShortcuts); + this._addContainerProperties(bNode, node); } else if (PlacesUtils.nodeIsSeparator(bNode)) { // Tag root accept only folder nodes // Tag containers accept only uri nodes @@ -636,10 +595,7 @@ let BookmarkNode = { if (!node.feedURI && node.type == PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER) { nodeCount += yield this._appendConvertedComplexNode(node, bNode, - aArray, - aIsUICommand, - aResolveShortcuts, - aExcludeItems) + aArray) return { appendedNode: true, nodeCount: nodeCount }; } @@ -648,8 +604,7 @@ let BookmarkNode = { }.bind(this)); }, - _addGenericProperties: function BN__addGenericProperties( - aPlacesNode, aJSNode, aResolveShortcuts) { + _addGenericProperties: function (aPlacesNode, aJSNode) { aJSNode.title = aPlacesNode.title; aJSNode.id = aPlacesNode.itemId; if (aJSNode.id != -1) { @@ -667,17 +622,7 @@ let BookmarkNode = { let annos = []; try { annos = - PlacesUtils.getAnnotationsForItem(aJSNode.id).filter(function(anno) { - // XXX should whitelist this instead, w/ a pref for - // backup/restore of non-whitelisted annos - // XXX causes JSON encoding errors, so utf-8 encode - // anno.value = unescape(encodeURIComponent(anno.value)); - if (anno.name == PlacesUtils.READ_ONLY_ANNO && aResolveShortcuts) { - // When copying a read-only node, remove the read-only annotation. - return false; - } - return true; - }); + PlacesUtils.getAnnotationsForItem(aJSNode.id); } catch(ex) {} if (annos.length != 0) aJSNode.annos = annos; @@ -686,7 +631,7 @@ let BookmarkNode = { }, _addURIProperties: function BN__addURIProperties( - aPlacesNode, aJSNode, aIsUICommand) { + aPlacesNode, aJSNode) { return Task.spawn(function() { aJSNode.type = PlacesUtils.TYPE_X_MOZ_PLACE; aJSNode.uri = aPlacesNode.uri; @@ -697,9 +642,8 @@ let BookmarkNode = { aJSNode.keyword = keyword; } - let tags = aIsUICommand ? aPlacesNode.tags : null; - if (tags) - aJSNode.tags = tags; + if (aPlacesNode.tags) + aJSNode.tags = aPlacesNode.tags; // Last character-set let uri = NetUtil.newURI(aPlacesNode.uri); @@ -715,17 +659,15 @@ let BookmarkNode = { }, _addContainerProperties: function BN__addContainerProperties( - aPlacesNode, aJSNode, aIsUICommand, aResolveShortcuts) { + aPlacesNode, aJSNode) { let concreteId = PlacesUtils.getConcreteItemId(aPlacesNode); if (concreteId != -1) { // This is a bookmark or a tag container. if (PlacesUtils.nodeIsQuery(aPlacesNode) || - (concreteId != aPlacesNode.itemId && !aResolveShortcuts)) { + concreteId != aPlacesNode.itemId) { aJSNode.type = PlacesUtils.TYPE_X_MOZ_PLACE; aJSNode.uri = aPlacesNode.uri; - // Folder shortcut - if (aIsUICommand) - aJSNode.concreteId = concreteId; + aJSNode.concreteId = concreteId; } else { // Bookmark folder or a shortcut we should convert to folder. aJSNode.type = PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER; @@ -749,9 +691,7 @@ let BookmarkNode = { } }, - _appendConvertedComplexNode: function BN__appendConvertedComplexNode( - aNode, aSourceNode, aArray, aIsUICommand, aResolveShortcuts, - aExcludeItems) { + _appendConvertedComplexNode: function (aNode, aSourceNode, aArray) { return Task.spawn(function* () { let repr = {}; let nodeCount = 0; @@ -770,11 +710,7 @@ let BookmarkNode = { let cc = aSourceNode.childCount; for (let i = 0; i < cc; ++i) { let childNode = aSourceNode.getChild(i); - if (aExcludeItems && aExcludeItems.indexOf(childNode.itemId) != -1) - continue; - let result = yield this._appendConvertedNode(aSourceNode.getChild(i), i, children, - aIsUICommand, aResolveShortcuts, - aExcludeItems); + let result = yield this._appendConvertedNode(aSourceNode.getChild(i), i, children); nodeCount += result.nodeCount; } if (!wasOpen) diff --git a/toolkit/components/places/PlacesUtils.jsm b/toolkit/components/places/PlacesUtils.jsm index dde9b524d5a..b8055135b67 100644 --- a/toolkit/components/places/PlacesUtils.jsm +++ b/toolkit/components/places/PlacesUtils.jsm @@ -478,11 +478,9 @@ this.PlacesUtils = { * Used instead of the node's URI if provided. * This is useful for wrapping a container as TYPE_X_MOZ_URL, * TYPE_HTML or TYPE_UNICODE. - * @param aForceCopy - * Does a full copy, resolving folder shortcuts. - * @returns A string serialization of the node + * @return A string serialization of the node */ - wrapNode: function PU_wrapNode(aNode, aType, aOverrideURI, aForceCopy) { + wrapNode: function PU_wrapNode(aNode, aType, aOverrideURI) { // when wrapping a node, we want all the items, even if the original // query options are excluding them. // this can happen when copying from the left hand pane of the bookmarks @@ -490,9 +488,9 @@ this.PlacesUtils = { // @return [node, shouldClose] function convertNode(cNode) { if (PlacesUtils.nodeIsFolder(cNode) && + cNode.type != Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT && asQuery(cNode).queryOptions.excludeItems) { - let concreteId = PlacesUtils.getConcreteItemId(cNode); - return [PlacesUtils.getFolderContents(concreteId, false, true).root, true]; + return [PlacesUtils.getFolderContents(cNode.itemId, false, true).root, true]; } // If we didn't create our own query, do not alter the node's open state. @@ -530,7 +528,7 @@ this.PlacesUtils = { }; let [node, shouldClose] = convertNode(aNode); - this._serializeNodeAsJSONToOutputStream(node, writer, true, aForceCopy); + this._serializeNodeAsJSONToOutputStream(node, writer); if (shouldClose) node.containerOpen = false; @@ -1109,25 +1107,17 @@ this.PlacesUtils = { * An nsIOutputStream. NOTE: it only uses the write(str, len) * method of nsIOutputStream. The caller is responsible for * closing the stream. - * @param aIsUICommand - * Boolean - If true, modifies serialization so that each node self-contained. - * For Example, tags are serialized inline with each bookmark. - * @param aResolveShortcuts - * Converts folder shortcuts into actual folders. - * @param aExcludeItems - * An array of item ids that should not be written to the backup. */ - _serializeNodeAsJSONToOutputStream: - function PU__serializeNodeAsJSONToOutputStream(aNode, aStream, aIsUICommand, - aResolveShortcuts, - aExcludeItems) { + _serializeNodeAsJSONToOutputStream: function (aNode, aStream) { function addGenericProperties(aPlacesNode, aJSNode) { aJSNode.title = aPlacesNode.title; aJSNode.id = aPlacesNode.itemId; if (aJSNode.id != -1) { var parent = aPlacesNode.parent; - if (parent) + if (parent) { aJSNode.parent = parent.itemId; + aJSNode.parentReadOnly = PlacesUtils.nodeIsReadOnly(parent); + } var dateAdded = aPlacesNode.dateAdded; if (dateAdded) aJSNode.dateAdded = dateAdded; @@ -1145,10 +1135,6 @@ this.PlacesUtils = { //anno.value = unescape(encodeURIComponent(anno.value)); if (anno.name == PlacesUtils.LMANNO_FEEDURI) aJSNode.livemark = 1; - if (anno.name == PlacesUtils.READ_ONLY_ANNO && aResolveShortcuts) { - // When copying a read-only node, remove the read-only annotation. - return false; - } return true; }); } catch(ex) {} @@ -1168,9 +1154,8 @@ this.PlacesUtils = { aJSNode.keyword = keyword; } - var tags = aIsUICommand ? aPlacesNode.tags : null; - if (tags) - aJSNode.tags = tags; + if (aPlacesNode.tags) + aJSNode.tags = aPlacesNode.tags; // last character-set var uri = PlacesUtils._uri(aPlacesNode.uri); @@ -1190,12 +1175,11 @@ this.PlacesUtils = { if (concreteId != -1) { // This is a bookmark or a tag container. if (PlacesUtils.nodeIsQuery(aPlacesNode) || - (concreteId != aPlacesNode.itemId && !aResolveShortcuts)) { + concreteId != aPlacesNode.itemId) { aJSNode.type = PlacesUtils.TYPE_X_MOZ_PLACE; aJSNode.uri = aPlacesNode.uri; // folder shortcut - if (aIsUICommand) - aJSNode.concreteId = concreteId; + aJSNode.concreteId = concreteId; } else { // Bookmark folder or a shortcut we should convert to folder. aJSNode.type = PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER; @@ -1236,8 +1220,6 @@ this.PlacesUtils = { var cc = aSourceNode.childCount; for (var i = 0; i < cc; ++i) { var childNode = aSourceNode.getChild(i); - if (aExcludeItems && aExcludeItems.indexOf(childNode.itemId) != -1) - continue; appendConvertedNode(aSourceNode.getChild(i), i, children); } if (!wasOpen) @@ -1261,6 +1243,8 @@ this.PlacesUtils = { var parent = bNode.parent; var grandParent = parent ? parent.parent : null; + if (grandParent) + node.grandParentId = grandParent.itemId; if (PlacesUtils.nodeIsURI(bNode)) { // Tag root accept only folder nodes diff --git a/toolkit/components/places/tests/bookmarks/test_423515_forceCopyShortcuts.js b/toolkit/components/places/tests/bookmarks/test_423515_forceCopyShortcuts.js deleted file mode 100644 index 58c8a535e2b..00000000000 --- a/toolkit/components/places/tests/bookmarks/test_423515_forceCopyShortcuts.js +++ /dev/null @@ -1,122 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -const DEFAULT_INDEX = PlacesUtils.bookmarks.DEFAULT_INDEX; - -function run_test() { - run_next_test(); -} - -add_task(function test_force_copy() { - /* - - create folder A - - add a bookmark to it - - create a bookmark that's a place: folder shortcut to the new folder - - serialize it to JSON, forcing copy - - import JSON - - confirm that the newly imported folder is a full copy and not a shortcut - */ - - var folderA = - PlacesUtils.bookmarks.createFolder(PlacesUtils.toolbarFolderId, - "test folder", DEFAULT_INDEX); - var bookmarkURI = uri("http://test"); - PlacesUtils.bookmarks.insertBookmark(folderA, bookmarkURI, - DEFAULT_INDEX, ""); - - // create the query - var queryURI = uri("place:folder=" + folderA); - var queryTitle = "test query"; - var queryId = - PlacesUtils.bookmarks.insertBookmark(PlacesUtils.toolbarFolderId, - queryURI, DEFAULT_INDEX, queryTitle); - LOG("queryId: " + queryId); - - // create a query that's *not* a folder shortcut - var queryURI2 = uri("place:"); - var queryTitle2 = "non-folder test query"; - var queryId2 = - PlacesUtils.bookmarks.insertBookmark(PlacesUtils.toolbarFolderId, - queryURI2, DEFAULT_INDEX, queryTitle2); - - // check default state - var query = PlacesUtils.history.getNewQuery(); - query.setFolders([PlacesUtils.toolbarFolderId], 1); - var options = PlacesUtils.history.getNewQueryOptions(); - options.expandQueries = true; - var result = PlacesUtils.history.executeQuery(query, options); - var root = result.root; - root.containerOpen = true; - - // check folder query node - var queryNode = root.getChild(root.childCount-2); - do_check_eq(queryNode.type, queryNode.RESULT_TYPE_FOLDER_SHORTCUT); - do_check_eq(queryNode.title, queryTitle); - do_check_true(queryURI.equals(uri(queryNode.uri))); - queryNode.QueryInterface(Ci.nsINavHistoryContainerResultNode); - queryNode.containerOpen = true; - do_check_eq(queryNode.childCount, 1); - var bookmark = queryNode.getChild(0); - do_check_true(bookmarkURI.equals(uri(bookmark.uri))); - queryNode.containerOpen = false; - - // check non-folder query node - var queryNode2 = root.getChild(root.childCount-1); - do_check_eq(queryNode2.type, queryNode2.RESULT_TYPE_QUERY); - do_check_eq(queryNode2.title, queryTitle2); - do_check_true(queryURI2.equals(uri(queryNode2.uri))); - queryNode2.QueryInterface(Ci.nsINavHistoryContainerResultNode); - queryNode2.containerOpen = true; - do_check_eq(queryNode2.childCount, 0); - queryNode2.containerOpen = false; - - // clean up - root.containerOpen = false; - - // serialize - var stream = { - _str: "", - write: function(aData, aLen) { - this._str += aData; - } - }; - Cu.import("resource://gre/modules/BookmarkJSONUtils.jsm"); - yield BookmarkJSONUtils.serializeNodeAsJSONToOutputStream(queryNode, stream, false, true); - - LOG("SERIALIZED: " + stream._str); - - PlacesUtils.bookmarks.removeItem(queryId); - - // import - yield BookmarkJSONUtils.importJSONNode(stream._str, PlacesUtils.toolbarFolderId, -1); - - // query for node - var query = PlacesUtils.history.getNewQuery(); - query.setFolders([PlacesUtils.toolbarFolderId], 1); - var options = PlacesUtils.history.getNewQueryOptions(); - var result = PlacesUtils.history.executeQuery(query, options); - var root = result.root; - root.containerOpen = true; - - // check folder node (no longer shortcut) - var queryNode = root.getChild(root.childCount-2); - do_check_eq(queryNode.type, queryNode.RESULT_TYPE_FOLDER); - queryNode.QueryInterface(Ci.nsINavHistoryContainerResultNode); - queryNode.containerOpen = true; - do_check_eq(queryNode.childCount, 1); - var child = queryNode.getChild(0); - do_check_true(bookmarkURI.equals(uri(child.uri))); - queryNode.containerOpen = false; - - var queryNode2 = root.getChild(root.childCount-1); - do_check_eq(queryNode2.type, queryNode2.RESULT_TYPE_QUERY); - queryNode2.QueryInterface(Ci.nsINavHistoryContainerResultNode); - queryNode2.containerOpen = true; - do_check_eq(queryNode2.childCount, 0); - queryNode.containerOpen = false; - - root.containerOpen = false; -}); diff --git a/toolkit/components/places/tests/bookmarks/xpcshell.ini b/toolkit/components/places/tests/bookmarks/xpcshell.ini index 0eb1386d6c2..55563d8142a 100644 --- a/toolkit/components/places/tests/bookmarks/xpcshell.ini +++ b/toolkit/components/places/tests/bookmarks/xpcshell.ini @@ -11,7 +11,6 @@ tail = [test_405938_restore_queries.js] [test_417228-exclude-from-backup.js] [test_417228-other-roots.js] -[test_423515_forceCopyShortcuts.js] [test_424958-json-quoted-folders.js] [test_448584.js] [test_458683.js] diff --git a/toolkit/components/satchel/nsFormFillController.cpp b/toolkit/components/satchel/nsFormFillController.cpp index 54a3a871296..4c6ac393a19 100644 --- a/toolkit/components/satchel/nsFormFillController.cpp +++ b/toolkit/components/satchel/nsFormFillController.cpp @@ -5,6 +5,8 @@ #include "nsFormFillController.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() #include "nsIFormAutoComplete.h" #include "nsIInputListAutoComplete.h" #include "nsIAutoCompleteSimpleResult.h" @@ -32,9 +34,7 @@ #include "nsToolkitCompsCID.h" #include "nsEmbedCID.h" #include "nsIDOMNSEditableElement.h" -#include "mozilla/dom/Element.h" #include "nsContentUtils.h" -#include "nsDOMEvent.h" #include "nsILoadContext.h" using namespace mozilla::dom; diff --git a/toolkit/crashreporter/breakpad-windows-libxul/Makefile.in b/toolkit/crashreporter/breakpad-windows-libxul/Makefile.in deleted file mode 100644 index ded3e30ce19..00000000000 --- a/toolkit/crashreporter/breakpad-windows-libxul/Makefile.in +++ /dev/null @@ -1,5 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -STL_FLAGS = diff --git a/toolkit/crashreporter/breakpad-windows-libxul/moz.build b/toolkit/crashreporter/breakpad-windows-libxul/moz.build index 3edea575e54..1e44df18ef4 100644 --- a/toolkit/crashreporter/breakpad-windows-libxul/moz.build +++ b/toolkit/crashreporter/breakpad-windows-libxul/moz.build @@ -28,3 +28,5 @@ SOURCES += objs_common SOURCES += objs_crash_generation SOURCES += objs_handler SOURCES += objs_sender + +DISABLE_STL_WRAPPING = True diff --git a/toolkit/crashreporter/breakpad-windows-standalone/Makefile.in b/toolkit/crashreporter/breakpad-windows-standalone/Makefile.in index 134d32419bb..9a0b3a6d1a1 100644 --- a/toolkit/crashreporter/breakpad-windows-standalone/Makefile.in +++ b/toolkit/crashreporter/breakpad-windows-standalone/Makefile.in @@ -3,5 +3,3 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. MOZ_GLUE_LDFLAGS = - -STL_FLAGS = diff --git a/toolkit/crashreporter/breakpad-windows-standalone/moz.build b/toolkit/crashreporter/breakpad-windows-standalone/moz.build index cdde55ddddb..3e2917657c9 100644 --- a/toolkit/crashreporter/breakpad-windows-standalone/moz.build +++ b/toolkit/crashreporter/breakpad-windows-standalone/moz.build @@ -22,3 +22,5 @@ SOURCES += objs_crash_generation SOURCES += objs_handler USE_STATIC_LIBS = True + +DISABLE_STL_WRAPPING = True diff --git a/toolkit/crashreporter/client/Makefile.in b/toolkit/crashreporter/client/Makefile.in index 7e137d4a86c..c36b44e825c 100644 --- a/toolkit/crashreporter/client/Makefile.in +++ b/toolkit/crashreporter/client/Makefile.in @@ -3,10 +3,6 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# Don't use the STL wrappers in the crashreporter clients; they don't -# link with -lmozalloc, and it really doesn't matter here anyway. -STL_FLAGS = - ifneq ($(OS_TARGET),Android) DIST_PROGRAM = crashreporter$(BIN_SUFFIX) @@ -19,7 +15,6 @@ ifeq ($(OS_ARCH),WINNT) LIBS += \ $(DEPTH)/toolkit/crashreporter/breakpad-windows-libxul/$(LIB_PREFIX)google_breakpad_libxul_s.$(LIB_SUFFIX) $(NULL) -RCINCLUDE = crashreporter.rc OS_LIBS += $(call EXPAND_LIBNAME,comctl32 shell32 wininet shlwapi) MOZ_WINCONSOLE = 0 endif diff --git a/toolkit/crashreporter/client/moz.build b/toolkit/crashreporter/client/moz.build index 4978ba693e0..b7ce83256f0 100644 --- a/toolkit/crashreporter/client/moz.build +++ b/toolkit/crashreporter/client/moz.build @@ -43,3 +43,8 @@ if CONFIG['MOZ_ENABLE_GTK']: 'crashreporter_unix_common.cpp' ] +RCINCLUDE = 'crashreporter.rc' + +# Don't use the STL wrappers in the crashreporter clients; they don't +# link with -lmozalloc, and it really doesn't matter here anyway. +DISABLE_STL_WRAPPING = True diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/Makefile.in b/toolkit/crashreporter/google-breakpad/src/common/linux/Makefile.in index 3c153aa26bf..a35acea48e6 100644 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/Makefile.in +++ b/toolkit/crashreporter/google-breakpad/src/common/linux/Makefile.in @@ -10,4 +10,4 @@ endif include $(topsrcdir)/config/rules.mk # See https://bugzilla.mozilla.org/show_bug.cgi?id=741348#c11 -file_id.$(OBJ_SUFFIX): STL_FLAGS= +file_id.$(OBJ_SUFFIX): DISABLE_STL_WRAPPING := 1 diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/moz.build b/toolkit/crashreporter/google-breakpad/src/common/linux/moz.build index 701324f0094..7fa7da5049d 100644 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/moz.build +++ b/toolkit/crashreporter/google-breakpad/src/common/linux/moz.build @@ -12,7 +12,7 @@ UNIFIED_SOURCES += [ 'safe_readlink.cc', ] -# file_id.cc cannot be built in unified mode because it uses a custom STL_FLAGS +# file_id.cc cannot be built in unified mode because it uses a custom DISABLE_STL_WRAPPING SOURCES += [ 'file_id.cc', ] diff --git a/toolkit/crashreporter/injector/Makefile.in b/toolkit/crashreporter/injector/Makefile.in index 7e58cfdf01b..2dc367f8645 100644 --- a/toolkit/crashreporter/injector/Makefile.in +++ b/toolkit/crashreporter/injector/Makefile.in @@ -2,7 +2,6 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -STL_FLAGS = MOZ_GLUE_LDFLAGS = include $(topsrcdir)/config/rules.mk diff --git a/toolkit/crashreporter/injector/moz.build b/toolkit/crashreporter/injector/moz.build index 697b6fe8f42..1f706d20ec1 100644 --- a/toolkit/crashreporter/injector/moz.build +++ b/toolkit/crashreporter/injector/moz.build @@ -24,3 +24,5 @@ if CONFIG['GNU_CC']: LDFLAGS += ['-Wl,-e,_DummyEntryPoint@12'] else: LDFLAGS += ['-ENTRY:DummyEntryPoint'] + +DISABLE_STL_WRAPPING = True diff --git a/toolkit/library/Makefile.in b/toolkit/library/Makefile.in index 5a313f071e3..9d7aab8709c 100644 --- a/toolkit/library/Makefile.in +++ b/toolkit/library/Makefile.in @@ -24,10 +24,6 @@ SHARED_LIBRARY_LIBS += \ $(foreach component,$(COMPONENT_LIBS),$(DEPTH)/staticlib/$(LIB_PREFIX)$(component).$(LIB_SUFFIX)) \ $(NULL) -ifeq ($(OS_ARCH)_$(GNU_CC),WINNT_) -RCINCLUDE = xulrunner.rc -endif - # dependent libraries ifdef MOZ_B2G_BT_BLUEZ #{ ifeq (gonk,$(MOZ_WIDGET_TOOLKIT)) diff --git a/toolkit/library/moz.build b/toolkit/library/moz.build index e521453e986..e49cbdcdd86 100644 --- a/toolkit/library/moz.build +++ b/toolkit/library/moz.build @@ -16,9 +16,10 @@ if CONFIG['OS_ARCH'] == 'WINNT': ] if not CONFIG['GNU_CC']: LOCAL_INCLUDES += [ - '/widget/windows', - '/xpcom/base', - ] + '/widget/windows', + '/xpcom/base', + ] + RCINCLUDE = 'xulrunner.rc' # component libraries additional_defines = ( diff --git a/toolkit/mozapps/update/updater/Makefile.in b/toolkit/mozapps/update/updater/Makefile.in index 1eff712d4d3..a457bfda1c3 100644 --- a/toolkit/mozapps/update/updater/Makefile.in +++ b/toolkit/mozapps/update/updater/Makefile.in @@ -20,7 +20,6 @@ LIBS += \ ifeq ($(OS_ARCH),WINNT) LIBS += $(call EXPAND_LIBNAME_PATH,verifymar,$(DEPTH)/modules/libmar/verify) -RCINCLUDE = updater.rc OS_LIBS += $(call EXPAND_LIBNAME,comctl32 ws2_32 shell32 shlwapi) endif @@ -34,7 +33,6 @@ OS_LIBS += -framework Cocoa endif ifeq (gonk,$(MOZ_WIDGET_TOOLKIT)) #{ -STL_FLAGS = OS_LIBS += -lcutils -lsysutils # clear out all the --wrap flags and remove dependency on mozglue for Gonk WRAP_LDFLAGS := diff --git a/toolkit/mozapps/update/updater/moz.build b/toolkit/mozapps/update/updater/moz.build index 2a803ea6343..5777b3cfbbc 100644 --- a/toolkit/mozapps/update/updater/moz.build +++ b/toolkit/mozapps/update/updater/moz.build @@ -20,6 +20,7 @@ if CONFIG['OS_ARCH'] == 'WINNT': 'progressui_win.cpp', 'win_dirent.cpp', ] + RCINCLUDE = 'updater.rc' DEFINES['UNICODE'] = True DEFINES['_UNICODE'] = True USE_STATIC_LIBS = True @@ -43,6 +44,7 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': 'automounter_gonk.cpp', 'progressui_gonk.cpp', ] + DISABLE_STL_WRAPPING = True if have_progressui == 0: SOURCES += [ diff --git a/tools/trace-malloc/lib/Makefile.in b/tools/trace-malloc/lib/Makefile.in deleted file mode 100644 index c9a4972166d..00000000000 --- a/tools/trace-malloc/lib/Makefile.in +++ /dev/null @@ -1,6 +0,0 @@ -# -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -STL_FLAGS = diff --git a/tools/trace-malloc/lib/moz.build b/tools/trace-malloc/lib/moz.build index 2f734db0cdc..4ebdadc2499 100644 --- a/tools/trace-malloc/lib/moz.build +++ b/tools/trace-malloc/lib/moz.build @@ -30,3 +30,5 @@ if CONFIG['WRAP_SYSTEM_INCLUDES']: DEFINES['MOZ_NO_MOZALLOC'] = True DEFFILE = SRCDIR + '/tm.def' + +DISABLE_STL_WRAPPING = True diff --git a/webapprt/gtk2/Makefile.in b/webapprt/gtk2/Makefile.in index 4b0f9e035af..38d8057c4a7 100644 --- a/webapprt/gtk2/Makefile.in +++ b/webapprt/gtk2/Makefile.in @@ -2,8 +2,6 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. -STL_FLAGS= - LIBS = \ $(XPCOM_STANDALONE_GLUE_LDOPTS) \ $(MOZ_GTK2_LIBS) \ diff --git a/webapprt/gtk2/moz.build b/webapprt/gtk2/moz.build index 56a033386b0..18fb764754e 100644 --- a/webapprt/gtk2/moz.build +++ b/webapprt/gtk2/moz.build @@ -20,3 +20,5 @@ LOCAL_INCLUDES += [ '/xpcom/base', '/xpcom/build', ] + +DISABLE_STL_WRAPPING = True diff --git a/webapprt/mac/Makefile.in b/webapprt/mac/Makefile.in index dfcf4bebd95..18b6f8d9fc4 100644 --- a/webapprt/mac/Makefile.in +++ b/webapprt/mac/Makefile.in @@ -11,8 +11,6 @@ NSDISTMODE = copy MOZ_GLUE_LDFLAGS = MOZ_GLUE_PROGRAM_LDFLAGS = -STL_FLAGS= - LIBS = \ $(XPCOM_STANDALONE_GLUE_LDOPTS) \ $(NULL) diff --git a/webapprt/mac/moz.build b/webapprt/mac/moz.build index 6e3e0d70588..4327892c833 100644 --- a/webapprt/mac/moz.build +++ b/webapprt/mac/moz.build @@ -18,3 +18,5 @@ LOCAL_INCLUDES += [ '/xpcom/base', '/xpcom/build', ] + +DISABLE_STL_WRAPPING = True diff --git a/webapprt/win/Makefile.in b/webapprt/win/Makefile.in index 82c3a80cff5..5b246197c96 100644 --- a/webapprt/win/Makefile.in +++ b/webapprt/win/Makefile.in @@ -6,8 +6,6 @@ # to dynamically link into our executable, as we copy it to arbitrary locations. MOZ_GLUE_LDFLAGS = -STL_FLAGS= - LIBS = \ $(XPCOM_STANDALONE_STATICRUNTIME_GLUE_LDOPTS) \ $(NULL) @@ -30,8 +28,6 @@ DEFINES += -DAPP_VERSION=$(APP_VERSION) OS_LIBS += $(call EXPAND_LIBNAME,shell32) -RCINCLUDE = webapprt.rc - # Uninstaller ifdef LOCALE_MERGEDIR PPL_LOCALE_ARGS = \ diff --git a/webapprt/win/moz.build b/webapprt/win/moz.build index ae455f471e3..fdbc1fb70ae 100644 --- a/webapprt/win/moz.build +++ b/webapprt/win/moz.build @@ -39,3 +39,7 @@ if CONFIG['_MSC_VER']: # Set it to 256k. See bug 127069. if not CONFIG['GNU_CC']: LDFLAGS += ['/HEAP:0x40000'] + +RCINCLUDE = 'webapprt.rc' + +DISABLE_STL_WRAPPING = True diff --git a/widget/BasicEvents.h b/widget/BasicEvents.h index ade6f311a0a..fd2f7e61996 100644 --- a/widget/BasicEvents.h +++ b/widget/BasicEvents.h @@ -499,20 +499,20 @@ public: // If mInSystemGroup is true, the event is being dispatched in system group. bool mInSystemGroup: 1; // If mCancelable is true, the event can be consumed. I.e., calling - // nsDOMEvent::PreventDefault() can prevent the default action. + // dom::Event::PreventDefault() can prevent the default action. bool mCancelable : 1; // If mBubbles is true, the event can bubble. Otherwise, cannot be handled // in bubbling phase. bool mBubbles : 1; - // If mPropagationStopped is true, nsDOMEvent::StopPropagation() or - // nsDOMEvent::StopImmediatePropagation() has been called. + // If mPropagationStopped is true, dom::Event::StopPropagation() or + // dom::Event::StopImmediatePropagation() has been called. bool mPropagationStopped : 1; // If mImmediatePropagationStopped is true, - // nsDOMEvent::StopImmediatePropagation() has been called. + // dom::Event::StopImmediatePropagation() has been called. // Note that mPropagationStopped must be true when this is true. bool mImmediatePropagationStopped : 1; // If mDefaultPrevented is true, the event has been consumed. - // E.g., nsDOMEvent::PreventDefault() has been called or + // E.g., dom::Event::PreventDefault() has been called or // the default action has been performed. bool mDefaultPrevented : 1; // If mDefaultPreventedByContent is true, the event has been diff --git a/widget/cocoa/nsMenuUtilsX.mm b/widget/cocoa/nsMenuUtilsX.mm index dcccc53b609..e55a50756cd 100644 --- a/widget/cocoa/nsMenuUtilsX.mm +++ b/widget/cocoa/nsMenuUtilsX.mm @@ -3,6 +3,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "mozilla/dom/Event.h" #include "nsMenuUtilsX.h" #include "nsMenuBarX.h" #include "nsMenuX.h" @@ -11,7 +12,6 @@ #include "nsObjCExceptions.h" #include "nsCocoaUtils.h" #include "nsCocoaWindow.h" -#include "nsDOMEvent.h" #include "nsGkAtoms.h" #include "nsIDocument.h" #include "nsIDOMDocument.h" @@ -27,7 +27,7 @@ void nsMenuUtilsX::DispatchCommandTo(nsIContent* aTargetContent) nsIDocument* doc = aTargetContent->OwnerDoc(); if (doc) { ErrorResult rv; - nsRefPtr event = + nsRefPtr event = doc->CreateEvent(NS_LITERAL_STRING("xulcommandevent"), rv); nsCOMPtr command = do_QueryObject(event); diff --git a/widget/gonk/libdisplay/Makefile.in b/widget/gonk/libdisplay/Makefile.in index 9c82cdf28a0..af214b59779 100644 --- a/widget/gonk/libdisplay/Makefile.in +++ b/widget/gonk/libdisplay/Makefile.in @@ -12,8 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -STL_FLAGS= - include $(topsrcdir)/config/rules.mk CXXFLAGS += \ diff --git a/widget/gonk/libdisplay/moz.build b/widget/gonk/libdisplay/moz.build index 66902278358..f5fdd598051 100644 --- a/widget/gonk/libdisplay/moz.build +++ b/widget/gonk/libdisplay/moz.build @@ -43,3 +43,5 @@ include('/ipc/chromium/chromium-config.mozbuild') FORCE_STATIC_LIB = True DEFINES['XPCOM_GLUE'] = True + +DISABLE_STL_WRAPPING = True diff --git a/widget/gonk/nativewindow/Makefile.in b/widget/gonk/nativewindow/Makefile.in deleted file mode 100644 index 101958c89aa..00000000000 --- a/widget/gonk/nativewindow/Makefile.in +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright 2013 Mozilla Foundation and Mozilla contributors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -STL_FLAGS= - -include $(topsrcdir)/config/rules.mk diff --git a/widget/gonk/nativewindow/moz.build b/widget/gonk/nativewindow/moz.build index 33ee66d6f89..331bd9a9066 100644 --- a/widget/gonk/nativewindow/moz.build +++ b/widget/gonk/nativewindow/moz.build @@ -74,3 +74,5 @@ FAIL_ON_WARNINGS = True include('/ipc/chromium/chromium-config.mozbuild') FINAL_LIBRARY = 'xul' + +DISABLE_STL_WRAPPING = True diff --git a/xpcom/base/nsIMemoryInfoDumper.idl b/xpcom/base/nsIMemoryInfoDumper.idl index 0ea39fd224c..b310aacfe17 100644 --- a/xpcom/base/nsIMemoryInfoDumper.idl +++ b/xpcom/base/nsIMemoryInfoDumper.idl @@ -11,7 +11,7 @@ interface nsIFinishDumpingCallback : nsISupports void callback(in nsISupports data); }; -[scriptable, builtinclass, uuid(294df03b-e2ae-4fdd-b4fc-4c66a501e0ef)] +[scriptable, builtinclass, uuid(815bf31b-f5bd-425d-85c3-4657a7a91dad)] interface nsIMemoryInfoDumper : nsISupports { /** @@ -94,19 +94,17 @@ interface nsIMemoryInfoDumper : nsISupports /** * Similar to dumpMemoryReportsToNamedFile, this method dumps gzipped memory - * reports for this process and possibly its child processes (and their - * children, recursively) to a file in the tmp directory called - * memory-reports--.json.gz (or something similar, such as - * memory-reports---1.json.gz; no existing file will be - * overwritten). + * reports for this process and its child processes to files in the tmp + * directory called memory-reports--.json.gz (or something + * similar, such as memory-reports---1.json.gz; no existing + * file will be overwritten). * * If DMD is enabled, this method also dumps gzipped DMD output to a file in * the tmp directory called dmd--.txt.gz (or something * similar; again, no existing file will be overwritten). * * @param aIdentifier this identifier will appear in the filename of our - * about:memory dump and those of our children (if aDumpChildProcesses is - * true). + * about:memory dump and those of our children. * * If the identifier is empty, the implementation may set it arbitrarily * and use that new value for its own dump and the dumps of its child @@ -116,15 +114,10 @@ interface nsIMemoryInfoDumper : nsISupports * @param aMinimizeMemoryUsage indicates whether we should run a series of * gc/cc's in an attempt to reduce our memory usage before collecting our * memory report. - * - * @param aDumpChildProcesses indicates whether we should call - * dumpMemoryInfoToTempDir in our child processes. If - * so, the child processes will also dump their children, and so on. */ void dumpMemoryInfoToTempDir( in AString aIdentifier, - in bool aMinimizeMemoryUsage, - in bool aDumpChildProcesses); + in bool aMinimizeMemoryUsage); /** * Dump GC and CC logs to files in the OS's temp directory (or in diff --git a/xpcom/base/nsIMemoryReporter.idl b/xpcom/base/nsIMemoryReporter.idl index 52f82a37766..0b61aadd35c 100644 --- a/xpcom/base/nsIMemoryReporter.idl +++ b/xpcom/base/nsIMemoryReporter.idl @@ -178,7 +178,7 @@ interface nsIFinishReportingCallback : nsISupports void callback(in nsISupports data); }; -[scriptable, builtinclass, uuid(12e08b1b-6590-4f78-996b-d9062c17e856)] +[scriptable, builtinclass, uuid(b6e5ec8a-71d9-48db-8ae9-68b4c5bbf2c3)] interface nsIMemoryReporterManager : nsISupports { /* @@ -242,6 +242,21 @@ interface nsIMemoryReporterManager : nsISupports in nsIFinishReportingCallback finishReporting, in nsISupports finishReportingData); + /* + * As above, but: If |minimizeMemoryUsage| is true, then each process will + * minimize its memory usage (see the |minimizeMemoryUsage| method) before + * gathering its report. If DMD is enabled and |DMDDumpIdent| is non-empty + * then write a DMD report to a file in the usual temporary directory (see + * |dumpMemoryInfoToTempDir| in |nsIMemoryInfoDumper|.) + */ + [noscript] void + getReportsExtended(in nsIMemoryReporterCallback handleReport, + in nsISupports handleReportData, + in nsIFinishReportingCallback finishReporting, + in nsISupports finishReportingData, + in boolean minimizeMemoryUsage, + in AString DMDDumpIdent); + /* * Get memory reports in the current process only. |handleReport| is called * for each report. @@ -249,6 +264,16 @@ interface nsIMemoryReporterManager : nsISupports void getReportsForThisProcess(in nsIMemoryReporterCallback handleReport, in nsISupports handleReportData); + /* + * As above, but if DMD is enabled and |DMDDumpIdent| is non-empty + * then write a DMD report to a file in the usual temporary directory (see + * |dumpMemoryInfoToTempDir| in |nsIMemoryInfoDumper|.) + */ + [noscript] void + getReportsForThisProcessExtended(in nsIMemoryReporterCallback handleReport, + in nsISupports handleReportData, + in AString DMDDumpIdent); + /* * The memory reporter manager, for the most part, treats reporters * registered with it as a black box. However, there are some diff --git a/xpcom/base/nsMemoryInfoDumper.cpp b/xpcom/base/nsMemoryInfoDumper.cpp index 2e21ed9d354..f2faefa34a6 100644 --- a/xpcom/base/nsMemoryInfoDumper.cpp +++ b/xpcom/base/nsMemoryInfoDumper.cpp @@ -60,25 +60,21 @@ class DumpMemoryInfoToTempDirRunnable : public nsRunnable { public: DumpMemoryInfoToTempDirRunnable(const nsAString& aIdentifier, - bool aMinimizeMemoryUsage, - bool aDumpChildProcesses) + bool aMinimizeMemoryUsage) : mIdentifier(aIdentifier) , mMinimizeMemoryUsage(aMinimizeMemoryUsage) - , mDumpChildProcesses(aDumpChildProcesses) {} NS_IMETHOD Run() { nsCOMPtr dumper = do_GetService("@mozilla.org/memory-info-dumper;1"); - dumper->DumpMemoryInfoToTempDir(mIdentifier, mMinimizeMemoryUsage, - mDumpChildProcesses); + dumper->DumpMemoryInfoToTempDir(mIdentifier, mMinimizeMemoryUsage); return NS_OK; } private: const nsString mIdentifier; const bool mMinimizeMemoryUsage; - const bool mDumpChildProcesses; }; class GCAndCCLogDumpRunnable : public nsRunnable @@ -357,8 +353,7 @@ public: bool doMMUFirst = signum == sDumpAboutMemoryAfterMMUSignum; nsRefPtr runnable = new DumpMemoryInfoToTempDirRunnable(/* identifier = */ EmptyString(), - doMMUFirst, - /* dumpChildProcesses = */ true); + doMMUFirst); NS_DispatchToMainThread(runnable); } else if (signum == sGCAndCCDumpSignum) { @@ -520,8 +515,7 @@ public: LOG("FifoWatcher dispatching memory report runnable."); nsRefPtr runnable = new DumpMemoryInfoToTempDirRunnable(/* identifier = */ EmptyString(), - doMMUMemoryReport, - /* dumpChildProcesses = */ true); + doMMUMemoryReport); NS_DispatchToMainThread(runnable); } else if (doAllTracesGCCCDump || doSmallGCCCDump) { LOG("FifoWatcher dispatching GC/CC log runnable."); @@ -830,25 +824,38 @@ DumpFooter(nsIGZFileWriter* aWriter) return NS_OK; } -static nsresult -DumpProcessMemoryReportsToGZFileWriter(nsGZFileWriter* aWriter) +class TempDirMemoryFinishCallback MOZ_FINAL : public nsIFinishReportingCallback { - nsresult rv = DumpHeader(aWriter); - NS_ENSURE_SUCCESS(rv, rv); +public: + NS_DECL_ISUPPORTS - // Process reporters. - nsCOMPtr mgr = - do_GetService("@mozilla.org/memory-reporter-manager;1"); - nsRefPtr dumpReport = new DumpReportCallback(aWriter); - mgr->GetReportsForThisProcess(dumpReport, nullptr); + TempDirMemoryFinishCallback(nsGZFileWriter *aWriter, + nsIFile *aTmpFile, + const nsCString &aFilename, + const nsString &aIdentifier) + : mrWriter(aWriter) + , mrTmpFile(aTmpFile) + , mrFilename(aFilename) + , mIdentifier(aIdentifier) + {} - return DumpFooter(aWriter); -} + NS_IMETHOD Callback(nsISupports *aData); -nsresult -DumpProcessMemoryInfoToTempDir(const nsAString& aIdentifier) +private: + nsRefPtr mrWriter; + nsCOMPtr mrTmpFile; + nsCString mrFilename; + nsString mIdentifier; +}; + +NS_IMPL_ISUPPORTS1(TempDirMemoryFinishCallback, nsIFinishReportingCallback) + +NS_IMETHODIMP +nsMemoryInfoDumper::DumpMemoryInfoToTempDir(const nsAString& aIdentifier, + bool aMinimizeMemoryUsage) { - MOZ_ASSERT(!aIdentifier.IsEmpty()); + nsString identifier(aIdentifier); + EnsureNonEmptyIdentifier(identifier); #ifdef MOZ_DMD // Clear DMD's reportedness state before running the memory reporters, to @@ -870,7 +877,12 @@ DumpProcessMemoryInfoToTempDir(const nsAString& aIdentifier) // Note that |mrFilename| is missing the "incomplete-" prefix; we'll tack // that on in a moment. nsCString mrFilename; - MakeFilename("memory-report", aIdentifier, "json.gz", mrFilename); + // The "unified" indicates that we merge the memory reports from all + // processes and write out one file, rather than a separate file for + // each process as was the case before bug 946407. This is so that + // the get_about_memory.py script in the B2G repository can + // determine when it's done waiting for files to appear. + MakeFilename("unified-memory-report", identifier, "json.gz", mrFilename); nsCOMPtr mrTmpFile; nsresult rv; @@ -886,9 +898,29 @@ DumpProcessMemoryInfoToTempDir(const nsAString& aIdentifier) return rv; // Dump the memory reports to the file. - DumpProcessMemoryReportsToGZFileWriter(mrWriter); + rv = DumpHeader(mrWriter); + if (NS_WARN_IF(NS_FAILED(rv))) + return rv; + + // Process reporters. + nsCOMPtr mgr = + do_GetService("@mozilla.org/memory-reporter-manager;1"); + nsRefPtr dumpReport = new DumpReportCallback(mrWriter); + nsRefPtr finishReport = + new TempDirMemoryFinishCallback(mrWriter, mrTmpFile, mrFilename, identifier); + rv = mgr->GetReportsExtended(dumpReport, nullptr, + finishReport, nullptr, + aMinimizeMemoryUsage, + identifier); + return rv; +} #ifdef MOZ_DMD +nsresult +nsMemoryInfoDumper::DumpDMD(const nsAString &aIdentifier) +{ + nsresult rv; + // Create a filename like dmd--.txt.gz, which will be used // if DMD is enabled. nsCString dmdFilename; @@ -916,9 +948,19 @@ DumpProcessMemoryInfoToTempDir(const nsAString& aIdentifier) dmd::Dump(w); rv = dmdWriter->Finish(); + NS_WARN_IF(NS_FAILED(rv)); + return rv; +} +#endif // MOZ_DMD + +NS_IMETHODIMP +TempDirMemoryFinishCallback::Callback(nsISupports *aData) +{ + nsresult rv; + + rv = DumpFooter(mrWriter); if (NS_WARN_IF(NS_FAILED(rv))) return rv; -#endif // MOZ_DMD // The call to Finish() deallocates the memory allocated by mrWriter's first // DUMP() call (within DumpProcessMemoryReportsToGZFileWriter()). Because @@ -978,44 +1020,6 @@ DumpProcessMemoryInfoToTempDir(const nsAString& aIdentifier) return cs->LogStringMessage(msg.get()); } -NS_IMETHODIMP -nsMemoryInfoDumper::DumpMemoryInfoToTempDir(const nsAString& aIdentifier, - bool aMinimizeMemoryUsage, - bool aDumpChildProcesses) -{ - nsString identifier(aIdentifier); - EnsureNonEmptyIdentifier(identifier); - - // Kick off memory report dumps in our child processes, if applicable. We - // do this before doing our own report because writing a report may be I/O - // bound, in which case we want to busy the CPU with other reports while we - // work on our own. - if (aDumpChildProcesses) { - nsTArray children; - ContentParent::GetAll(children); - for (uint32_t i = 0; i < children.Length(); i++) { - unused << children[i]->SendDumpMemoryInfoToTempDir( - identifier, aMinimizeMemoryUsage, aDumpChildProcesses); - } - } - - if (aMinimizeMemoryUsage) { - // Minimize memory usage, then run DumpMemoryInfoToTempDir again. - nsRefPtr callback = - new DumpMemoryInfoToTempDirRunnable(identifier, - /* minimizeMemoryUsage = */ false, - /* dumpChildProcesses = */ false); - nsCOMPtr mgr = - do_GetService("@mozilla.org/memory-reporter-manager;1"); - if (NS_WARN_IF(!mgr)) - return NS_ERROR_FAILURE; - mgr->MinimizeMemoryUsage(callback); - return NS_OK; - } - - return DumpProcessMemoryInfoToTempDir(identifier); -} - // This dumps the JSON footer and closes the file, and then calls the given // nsIFinishDumpingCallback. class FinishReportingCallback MOZ_FINAL : public nsIFinishReportingCallback diff --git a/xpcom/base/nsMemoryInfoDumper.h b/xpcom/base/nsMemoryInfoDumper.h index 166c7f9f024..d4910be4d2e 100644 --- a/xpcom/base/nsMemoryInfoDumper.h +++ b/xpcom/base/nsMemoryInfoDumper.h @@ -38,6 +38,9 @@ public: * instead. */ static nsresult OpenTempFile(const nsACString &aFilename, nsIFile* *aFile); +#ifdef MOZ_DMD + static nsresult DumpDMD(const nsAString &aIdentifier); +#endif }; #define NS_MEMORY_INFO_DUMPER_CID \ diff --git a/xpcom/base/nsMemoryReporterManager.cpp b/xpcom/base/nsMemoryReporterManager.cpp index c1399b40046..0ce5a4c3cba 100644 --- a/xpcom/base/nsMemoryReporterManager.cpp +++ b/xpcom/base/nsMemoryReporterManager.cpp @@ -8,6 +8,7 @@ #include "nsAutoPtr.h" #include "nsCOMPtr.h" #include "nsCOMArray.h" +#include "nsPrintfCString.h" #include "nsServiceManagerUtils.h" #include "nsMemoryReporterManager.h" #include "nsITimer.h" @@ -952,6 +953,23 @@ nsMemoryReporterManager::GetReports( nsIFinishReportingCallback* aFinishReporting, nsISupports* aFinishReportingData) { + return GetReportsExtended(aHandleReport, aHandleReportData, + aFinishReporting, aFinishReportingData, + /* minimize = */ false, + /* DMDident = */ nsString()); +} + +NS_IMETHODIMP +nsMemoryReporterManager::GetReportsExtended( + nsIHandleReportCallback* aHandleReport, + nsISupports* aHandleReportData, + nsIFinishReportingCallback* aFinishReporting, + nsISupports* aFinishReportingData, + bool aMinimize, + const nsAString& aDMDDumpIdent) +{ + nsresult rv; + // Memory reporters are not necessarily threadsafe, so this function must // be called from the main thread. if (!NS_IsMainThread()) { @@ -979,16 +997,19 @@ nsMemoryReporterManager::GetReports( do_GetService("@mozilla.org/observer-service;1"); NS_ENSURE_STATE(obs); - // Casting the uint32_t generation to |const char16_t*| is a hack, but - // simpler than converting the number to an actual string. + nsPrintfCString genStr("generation=%x minimize=%d DMDident=", + generation, aMinimize ? 1 : 0); + nsAutoString msg = NS_ConvertUTF8toUTF16(genStr); + msg += aDMDDumpIdent; + obs->NotifyObservers(nullptr, "child-memory-reporter-request", - (const char16_t*)(uintptr_t)generation); + msg.get()); nsCOMPtr timer = do_CreateInstance(NS_TIMER_CONTRACTID); NS_ENSURE_TRUE(timer, NS_ERROR_FAILURE); - nsresult rv = timer->InitWithFuncCallback(TimeoutCallback, - this, kTimeoutLengthMS, - nsITimer::TYPE_ONE_SHOT); + rv = timer->InitWithFuncCallback(TimeoutCallback, + this, kTimeoutLengthMS, + nsITimer::TYPE_ONE_SHOT); NS_ENSURE_SUCCESS(rv, rv); mGetReportsState = new GetReportsState(generation, @@ -997,16 +1018,40 @@ nsMemoryReporterManager::GetReports( aHandleReport, aHandleReportData, aFinishReporting, - aFinishReportingData); + aFinishReportingData, + aDMDDumpIdent); + } else { + mGetReportsState = new GetReportsState(generation, + nullptr, + /* mNumChildProcesses = */ 0, + aHandleReport, + aHandleReportData, + aFinishReporting, + aFinishReportingData, + aDMDDumpIdent); } + if (aMinimize) { + rv = MinimizeMemoryUsage(NS_NewRunnableMethod(this, &nsMemoryReporterManager::StartGettingReports)); + } else { + rv = StartGettingReports(); + } + return rv; +} + +nsresult +nsMemoryReporterManager::StartGettingReports() +{ + GetReportsState *s = mGetReportsState; + // Get reports for this process. - GetReportsForThisProcess(aHandleReport, aHandleReportData); + GetReportsForThisProcessExtended(s->mHandleReport, s->mHandleReportData, + s->mDMDDumpIdent); // If there are no child processes, we can finish up immediately. - return (mNumChildProcesses == 0) - ? aFinishReporting->Callback(aFinishReportingData) - : NS_OK; + return (s->mNumChildProcesses == 0) + ? FinishReporting() + : NS_OK; } typedef nsCOMArray MemoryReporterArray; @@ -1031,6 +1076,17 @@ NS_IMETHODIMP nsMemoryReporterManager::GetReportsForThisProcess( nsIHandleReportCallback* aHandleReport, nsISupports* aHandleReportData) +{ + return GetReportsForThisProcessExtended(aHandleReport, + aHandleReportData, + nsString()); +} + +NS_IMETHODIMP +nsMemoryReporterManager::GetReportsForThisProcessExtended( + nsIHandleReportCallback* aHandleReport, + nsISupports* aHandleReportData, + const nsAString& aDMDDumpIdent) { // Memory reporters are not necessarily threadsafe, so this function must // be called from the main thread. @@ -1038,6 +1094,14 @@ nsMemoryReporterManager::GetReportsForThisProcess( MOZ_CRASH(); } +#ifdef MOZ_DMD + if (!aDMDDumpIdent.IsEmpty()) { + // Clear DMD's reportedness state before running the memory + // reporters, to avoid spurious twice-reported warnings. + dmd::ClearReports(); + } +#endif + MemoryReporterArray allReporters; { mozilla::MutexAutoLock autoLock(mMutex); @@ -1048,6 +1112,12 @@ nsMemoryReporterManager::GetReportsForThisProcess( allReporters[i]->CollectReports(aHandleReport, aHandleReportData); } +#ifdef MOZ_DMD + if (!aDMDDumpIdent.IsEmpty()) { + return nsMemoryInfoDumper::DumpDMD(aDMDDumpIdent); + } +#endif + return NS_OK; } @@ -1136,7 +1206,7 @@ nsMemoryReporterManager::TimeoutCallback(nsITimer* aTimer, void* aData) mgr->FinishReporting(); } -void +nsresult nsMemoryReporterManager::FinishReporting() { // Memory reporting only happens on the main thread. @@ -1151,11 +1221,12 @@ nsMemoryReporterManager::FinishReporting() // Call this before deleting |mGetReportsState|. That way, if // |mFinishReportData| calls GetReports(), it will silently abort, as // required. - (void)mGetReportsState->mFinishReporting->Callback( + nsresult rv = mGetReportsState->mFinishReporting->Callback( mGetReportsState->mFinishReportingData); delete mGetReportsState; mGetReportsState = nullptr; + return rv; } static void diff --git a/xpcom/base/nsMemoryReporterManager.h b/xpcom/base/nsMemoryReporterManager.h index c23d6c894ac..2c53db2729f 100644 --- a/xpcom/base/nsMemoryReporterManager.h +++ b/xpcom/base/nsMemoryReporterManager.h @@ -117,7 +117,7 @@ public: void HandleChildReports( const uint32_t& generation, const InfallibleTArray& aChildReports); - void FinishReporting(); + nsresult FinishReporting(); // Functions that (a) implement distinguished amounts, and (b) are outside of // this module. @@ -157,9 +157,12 @@ public: private: nsresult RegisterReporterHelper(nsIMemoryReporter* aReporter, bool aForce, bool aStrongRef); + nsresult StartGettingReports(); static void TimeoutCallback(nsITimer* aTimer, void* aData); - static const uint32_t kTimeoutLengthMS = 5000; + // Note: this timeout needs to be long enough to allow for the + // possibility of DMD reports and/or running on a low-end phone. + static const uint32_t kTimeoutLengthMS = 50000; mozilla::Mutex mMutex; bool mIsRegistrationBlocked; @@ -184,13 +187,15 @@ private: nsCOMPtr mHandleReportData; nsCOMPtr mFinishReporting; nsCOMPtr mFinishReportingData; + nsString mDMDDumpIdent; GetReportsState(uint32_t aGeneration, nsITimer* aTimer, uint32_t aNumChildProcesses, nsIHandleReportCallback* aHandleReport, nsISupports* aHandleReportData, nsIFinishReportingCallback* aFinishReporting, - nsISupports* aFinishReportingData) + nsISupports* aFinishReportingData, + const nsAString &aDMDDumpIdent) : mGeneration(aGeneration) , mTimer(aTimer) , mNumChildProcesses(aNumChildProcesses) @@ -199,6 +204,7 @@ private: , mHandleReportData(aHandleReportData) , mFinishReporting(aFinishReporting) , mFinishReportingData(aFinishReportingData) + , mDMDDumpIdent(aDMDDumpIdent) { } }; diff --git a/xpcom/glue/nomozalloc/Makefile.in b/xpcom/glue/nomozalloc/Makefile.in index 0501b940c96..3bec2c73e95 100644 --- a/xpcom/glue/nomozalloc/Makefile.in +++ b/xpcom/glue/nomozalloc/Makefile.in @@ -6,9 +6,6 @@ DIST_INSTALL = 1 -# Don't use STL wrappers here (i.e. wrapped ); they require mozalloc -STL_FLAGS = - include $(topsrcdir)/config/rules.mk ifdef _MSC_VER diff --git a/xpcom/glue/nomozalloc/moz.build b/xpcom/glue/nomozalloc/moz.build index 22cbf41c682..2ca8cda2c71 100644 --- a/xpcom/glue/nomozalloc/moz.build +++ b/xpcom/glue/nomozalloc/moz.build @@ -39,3 +39,6 @@ LOCAL_INCLUDES += [ # avoids "msvcrp" and assembly dependencies from creeping into the directives # for this library on Windows. USE_STATIC_LIBS = True + +# Don't use STL wrappers here (i.e. wrapped ); they require mozalloc +DISABLE_STL_WRAPPING = True diff --git a/xpcom/glue/standalone/Makefile.in b/xpcom/glue/standalone/Makefile.in index 08dfaf04ad5..f21c25153ca 100644 --- a/xpcom/glue/standalone/Makefile.in +++ b/xpcom/glue/standalone/Makefile.in @@ -6,9 +6,6 @@ DIST_INSTALL = 1 -# Don't use STL wrappers here (i.e. wrapped ); they require mozalloc -STL_FLAGS = - include $(topsrcdir)/config/rules.mk ifdef _MSC_VER diff --git a/xpcom/glue/standalone/moz.build b/xpcom/glue/standalone/moz.build index b50e16bb828..7259b019720 100644 --- a/xpcom/glue/standalone/moz.build +++ b/xpcom/glue/standalone/moz.build @@ -42,3 +42,5 @@ LOCAL_INCLUDES += [ '../../build', ] +# Don't use STL wrappers here (i.e. wrapped ); they require mozalloc +DISABLE_STL_WRAPPING = True diff --git a/xpcom/glue/standalone/staticruntime/Makefile.in b/xpcom/glue/standalone/staticruntime/Makefile.in index 161e578b6d5..734fcaadbcf 100644 --- a/xpcom/glue/standalone/staticruntime/Makefile.in +++ b/xpcom/glue/standalone/staticruntime/Makefile.in @@ -5,9 +5,6 @@ DIST_INSTALL = 1 -# Don't use STL wrappers here (i.e. wrapped ); they require mozalloc -STL_FLAGS = - include $(topsrcdir)/config/rules.mk ifdef _MSC_VER diff --git a/xpcom/glue/standalone/staticruntime/moz.build b/xpcom/glue/standalone/staticruntime/moz.build index d10cb36beed..2a94f323b50 100644 --- a/xpcom/glue/standalone/staticruntime/moz.build +++ b/xpcom/glue/standalone/staticruntime/moz.build @@ -36,3 +36,6 @@ LOCAL_INCLUDES += [ # Statically link to the CRT on Windows USE_STATIC_LIBS = True + +# Don't use STL wrappers here (i.e. wrapped ); they require mozalloc +DISABLE_STL_WRAPPING = True diff --git a/xpcom/glue/staticruntime/Makefile.in b/xpcom/glue/staticruntime/Makefile.in index a5daa703726..3bec2c73e95 100644 --- a/xpcom/glue/staticruntime/Makefile.in +++ b/xpcom/glue/staticruntime/Makefile.in @@ -6,9 +6,6 @@ DIST_INSTALL = 1 -# Don't use STL wrappers here (i.e. wrapped ); they require mozalloc -STL_FLAGS = - include $(topsrcdir)/config/rules.mk ifdef _MSC_VER diff --git a/xpcom/glue/staticruntime/moz.build b/xpcom/glue/staticruntime/moz.build index 22cd15f0182..e0f46473327 100644 --- a/xpcom/glue/staticruntime/moz.build +++ b/xpcom/glue/staticruntime/moz.build @@ -34,3 +34,6 @@ LOCAL_INCLUDES += [ # Statically link to the CRT on Windows USE_STATIC_LIBS = True + +# Don't use STL wrappers here (i.e. wrapped ); they require mozalloc +DISABLE_STL_WRAPPING = True diff --git a/xpfe/appshell/src/nsXULWindow.cpp b/xpfe/appshell/src/nsXULWindow.cpp index 9f6f1d4358c..7153ebe6073 100644 --- a/xpfe/appshell/src/nsXULWindow.cpp +++ b/xpfe/appshell/src/nsXULWindow.cpp @@ -51,7 +51,6 @@ #include "nsPresContext.h" #include "nsContentUtils.h" #include "nsWebShellWindow.h" // get rid of this one, too... -#include "nsDOMEvent.h" #include "nsGlobalWindow.h" #include "prenv.h" @@ -59,6 +58,7 @@ #include "mozilla/Preferences.h" #include "mozilla/dom/BarProps.h" #include "mozilla/dom/Element.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/ScriptSettings.h" using namespace mozilla; @@ -230,7 +230,8 @@ NS_IMETHODIMP nsXULWindow::SetZLevel(uint32_t aLevel) nsCOMPtr doc = cv->GetDocument(); if (doc) { ErrorResult rv; - nsRefPtr event = doc->CreateEvent(NS_LITERAL_STRING("Events"),rv); + nsRefPtr event = + doc->CreateEvent(NS_LITERAL_STRING("Events"),rv); if (event) { event->InitEvent(NS_LITERAL_STRING("windowZLevel"), true, false); diff --git a/xulrunner/app/Makefile.in b/xulrunner/app/Makefile.in index 792f4a93a70..5a3ffae5ac1 100644 --- a/xulrunner/app/Makefile.in +++ b/xulrunner/app/Makefile.in @@ -8,8 +8,6 @@ GARBAGE += $(addprefix $(DIST)/bin/defaults/pref/,xulrunner.js) DEFINES += -DAB_CD=$(AB_CD) -STL_FLAGS= - ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) TK_LIBS := -framework Cocoa $(TK_LIBS) endif @@ -34,7 +32,6 @@ include $(topsrcdir)/config/config.mk ifeq ($(OS_ARCH),WINNT) OS_LIBS += $(call EXPAND_LIBNAME,comctl32 comdlg32 uuid shell32 ole32 oleaut32 version winspool) -RCINCLUDE = splash.rc endif include $(topsrcdir)/config/rules.mk diff --git a/xulrunner/app/moz.build b/xulrunner/app/moz.build index 0812544c07c..23c5ae23670 100644 --- a/xulrunner/app/moz.build +++ b/xulrunner/app/moz.build @@ -42,3 +42,8 @@ if CONFIG['_MSC_VER']: # Set it to 256k. See bug 127069. if CONFIG['OS_ARCH'] == 'WINNT' and not CONFIG['GNU_CC']: LDFLAGS += ['/HEAP:0x40000'] + +if CONFIG['OS_ARCH'] == 'WINNT': + RCINCLUDE = 'splash.rc' + +DISABLE_STL_WRAPPING = True diff --git a/xulrunner/stub/Makefile.in b/xulrunner/stub/Makefile.in index 81978dc7f61..89437002df5 100644 --- a/xulrunner/stub/Makefile.in +++ b/xulrunner/stub/Makefile.in @@ -5,8 +5,6 @@ # Don't create a dependency on mozglue MOZ_GLUE_LDFLAGS = -STL_FLAGS= - LIBS = \ $(XPCOM_STANDALONE_STATICRUNTIME_GLUE_LDOPTS) \ $(NULL) @@ -18,10 +16,6 @@ LIBS += \ $(NULL) endif -ifeq ($(OS_ARCH),WINNT) -RCINCLUDE = xulrunner-stub.rc -endif - ifndef MOZ_WINCONSOLE ifdef MOZ_DEBUG MOZ_WINCONSOLE = 1 diff --git a/xulrunner/stub/moz.build b/xulrunner/stub/moz.build index ae8d82d5eae..52334d3ca69 100644 --- a/xulrunner/stub/moz.build +++ b/xulrunner/stub/moz.build @@ -36,3 +36,6 @@ if CONFIG['_MSC_VER']: if CONFIG['OS_ARCH'] == 'WINNT': DEFINES['MOZ_XULRUNNER'] = True + RCINCLUDE = 'xulrunner-stub.rc' + +DISABLE_STL_WRAPPING = True