mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge inbound to m-c. a=merge
This commit is contained in:
commit
62f7c5af6c
@ -251,6 +251,14 @@ a11y::MakeXPCEvent(AccEvent* aEvent)
|
||||
return xpEvent.forget();
|
||||
}
|
||||
|
||||
if (eventGroup & (1 << AccEvent::eObjectAttrChangedEvent)) {
|
||||
AccObjectAttrChangedEvent* oac = downcast_accEvent(aEvent);
|
||||
xpEvent = new xpcAccObjectAttributeChangedEvent(type, acc, doc, domNode,
|
||||
fromUser,
|
||||
oac->GetAttribute());
|
||||
return xpEvent.forget();
|
||||
}
|
||||
|
||||
xpEvent = new xpcAccEvent(type, acc, doc, domNode, fromUser);
|
||||
return xpEvent.forget();
|
||||
}
|
||||
|
@ -105,7 +105,8 @@ public:
|
||||
eTextSelChangeEvent,
|
||||
eSelectionChangeEvent,
|
||||
eTableChangeEvent,
|
||||
eVirtualCursorChangeEvent
|
||||
eVirtualCursorChangeEvent,
|
||||
eObjectAttrChangedEvent
|
||||
};
|
||||
|
||||
static const EventGroup kEventGroup = eGenericEvent;
|
||||
@ -494,6 +495,32 @@ private:
|
||||
int16_t mReason;
|
||||
};
|
||||
|
||||
/**
|
||||
* Accessible object attribute changed event.
|
||||
*/
|
||||
class AccObjectAttrChangedEvent: public AccEvent
|
||||
{
|
||||
public:
|
||||
AccObjectAttrChangedEvent(Accessible* aAccessible, nsIAtom* aAttribute) :
|
||||
AccEvent(::nsIAccessibleEvent::EVENT_OBJECT_ATTRIBUTE_CHANGED, aAccessible),
|
||||
mAttribute(aAttribute) { }
|
||||
|
||||
// AccEvent
|
||||
static const EventGroup kEventGroup = eObjectAttrChangedEvent;
|
||||
virtual unsigned int GetEventGroups() const
|
||||
{
|
||||
return AccEvent::GetEventGroups() | (1U << eObjectAttrChangedEvent);
|
||||
}
|
||||
|
||||
// AccObjectAttrChangedEvent
|
||||
nsIAtom* GetAttribute() const { return mAttribute; }
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIAtom> mAttribute;
|
||||
|
||||
virtual ~AccObjectAttrChangedEvent() { }
|
||||
};
|
||||
|
||||
/**
|
||||
* Downcast the generic accessible event object to derived type.
|
||||
*/
|
||||
|
@ -1094,9 +1094,11 @@ DocAccessible::ARIAAttributeChanged(Accessible* aAccessible, nsIAtom* aAttribute
|
||||
// For aria attributes like drag and drop changes we fire a generic attribute
|
||||
// change event; at least until native API comes up with a more meaningful event.
|
||||
uint8_t attrFlags = aria::AttrCharacteristicsFor(aAttribute);
|
||||
if (!(attrFlags & ATTR_BYPASSOBJ))
|
||||
FireDelayedEvent(nsIAccessibleEvent::EVENT_OBJECT_ATTRIBUTE_CHANGED,
|
||||
aAccessible);
|
||||
if (!(attrFlags & ATTR_BYPASSOBJ)) {
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccObjectAttrChangedEvent(aAccessible, aAttribute);
|
||||
FireDelayedEvent(event);
|
||||
}
|
||||
|
||||
nsIContent* elm = aAccessible->GetContent();
|
||||
|
||||
|
@ -18,6 +18,7 @@ XPIDL_SOURCES += [
|
||||
'nsIAccessibleHyperLink.idl',
|
||||
'nsIAccessibleHyperText.idl',
|
||||
'nsIAccessibleImage.idl',
|
||||
'nsIAccessibleObjectAttributeChangedEvent.idl',
|
||||
'nsIAccessiblePivot.idl',
|
||||
'nsIAccessibleRelation.idl',
|
||||
'nsIAccessibleRetrieval.idl',
|
||||
|
@ -0,0 +1,21 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* 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 "nsIAccessibleEvent.idl"
|
||||
|
||||
interface nsIAtom;
|
||||
|
||||
/**
|
||||
* Fired when an attribute of an accessible changes.
|
||||
*/
|
||||
[scriptable, builtinclass, uuid(4CA96609-23C8-4771-86E7-77C8B651CA24)]
|
||||
interface nsIAccessibleObjectAttributeChangedEvent : nsIAccessibleEvent
|
||||
{
|
||||
/**
|
||||
* Return the accessible attribute that changed.
|
||||
*/
|
||||
readonly attribute nsIAtom changedAttribute;
|
||||
};
|
@ -235,6 +235,10 @@ this.AccessFu = { // jshint ignore:line
|
||||
},
|
||||
|
||||
_output: function _output(aPresentationData, aBrowser) {
|
||||
if (!Utils.isAliveAndVisible(
|
||||
Utils.AccRetrieval.getAccessibleFor(aBrowser))) {
|
||||
return;
|
||||
}
|
||||
for (let presenter of aPresentationData) {
|
||||
if (!presenter) {
|
||||
continue;
|
||||
|
@ -225,43 +225,30 @@ this.EventManager.prototype = {
|
||||
this.editState = editState;
|
||||
break;
|
||||
}
|
||||
case Events.OBJECT_ATTRIBUTE_CHANGED:
|
||||
{
|
||||
let evt = aEvent.QueryInterface(
|
||||
Ci.nsIAccessibleObjectAttributeChangedEvent);
|
||||
if (evt.changedAttribute.toString() !== 'aria-hidden') {
|
||||
// Only handle aria-hidden attribute change.
|
||||
break;
|
||||
}
|
||||
if (Utils.isHidden(aEvent.accessible)) {
|
||||
this._handleHide(evt);
|
||||
} else {
|
||||
this._handleShow(aEvent);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Events.SHOW:
|
||||
{
|
||||
let {liveRegion, isPolite} = this._handleLiveRegion(aEvent,
|
||||
['additions', 'all']);
|
||||
// Only handle show if it is a relevant live region.
|
||||
if (!liveRegion) {
|
||||
break;
|
||||
}
|
||||
// Show for text is handled by the EVENT_TEXT_INSERTED handler.
|
||||
if (aEvent.accessible.role === Roles.TEXT_LEAF) {
|
||||
break;
|
||||
}
|
||||
this._dequeueLiveEvent(Events.HIDE, liveRegion);
|
||||
this.present(Presentation.liveRegion(liveRegion, isPolite, false));
|
||||
this._handleShow(aEvent);
|
||||
break;
|
||||
}
|
||||
case Events.HIDE:
|
||||
{
|
||||
let evt = aEvent.QueryInterface(Ci.nsIAccessibleHideEvent);
|
||||
let {liveRegion, isPolite} = this._handleLiveRegion(
|
||||
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.contentControl.autoMove(
|
||||
evt.targetPrevSibling || evt.targetParent,
|
||||
{ moveToFocused: true, delay: 500 });
|
||||
}
|
||||
}
|
||||
this._handleHide(evt);
|
||||
break;
|
||||
}
|
||||
case Events.TEXT_INSERTED:
|
||||
@ -306,6 +293,51 @@ this.EventManager.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
_handleShow: function _handleShow(aEvent) {
|
||||
let {liveRegion, isPolite} = this._handleLiveRegion(aEvent,
|
||||
['additions', 'all']);
|
||||
// Only handle show if it is a relevant live region.
|
||||
if (!liveRegion) {
|
||||
return;
|
||||
}
|
||||
// Show for text is handled by the EVENT_TEXT_INSERTED handler.
|
||||
if (aEvent.accessible.role === Roles.TEXT_LEAF) {
|
||||
return;
|
||||
}
|
||||
this._dequeueLiveEvent(Events.HIDE, liveRegion);
|
||||
this.present(Presentation.liveRegion(liveRegion, isPolite, false));
|
||||
},
|
||||
|
||||
_handleHide: function _handleHide(aEvent) {
|
||||
let {liveRegion, isPolite} = this._handleLiveRegion(
|
||||
aEvent, ['removals', 'all']);
|
||||
let acc = aEvent.accessible;
|
||||
if (liveRegion) {
|
||||
// Hide for text is handled by the EVENT_TEXT_REMOVED handler.
|
||||
if (acc.role === Roles.TEXT_LEAF) {
|
||||
return;
|
||||
}
|
||||
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, acc))) {
|
||||
let position = aEvent.targetPrevSibling || aEvent.targetParent;
|
||||
if (!position) {
|
||||
try {
|
||||
position = acc.previousSibling;
|
||||
} catch (x) {
|
||||
// Accessible is unattached from the accessible tree.
|
||||
position = acc.parent;
|
||||
}
|
||||
}
|
||||
this.contentControl.autoMove(position,
|
||||
{ moveToFocused: true, delay: 500 });
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_handleText: function _handleText(aEvent, aLiveRegion, aIsPolite) {
|
||||
let event = aEvent.QueryInterface(Ci.nsIAccessibleTextChangeEvent);
|
||||
let isInserted = event.isInserted;
|
||||
|
@ -353,10 +353,16 @@ this.Utils = { // jshint ignore:line
|
||||
return false;
|
||||
},
|
||||
|
||||
isHidden: function isHidden(aAccessible) {
|
||||
// Need to account for aria-hidden, so can't just check for INVISIBLE
|
||||
// state.
|
||||
let hidden = Utils.getAttributes(aAccessible).hidden;
|
||||
return hidden && hidden === 'true';
|
||||
},
|
||||
|
||||
inHiddenSubtree: function inHiddenSubtree(aAccessible) {
|
||||
for (let acc=aAccessible; acc; acc=acc.parent) {
|
||||
let hidden = Utils.getAttributes(acc).hidden;
|
||||
if (hidden && JSON.parse(hidden)) {
|
||||
if (this.isHidden(acc)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -789,9 +795,7 @@ PivotContext.prototype = {
|
||||
if (this._includeInvisible) {
|
||||
include = true;
|
||||
} else {
|
||||
// Need to account for aria-hidden, so can't just check for INVISIBLE
|
||||
// state.
|
||||
include = Utils.getAttributes(child).hidden !== 'true';
|
||||
include = !Utils.isHidden(child);
|
||||
}
|
||||
if (include) {
|
||||
if (aPreorder) {
|
||||
|
@ -12,6 +12,8 @@ const nsIAccessibleTextChangeEvent =
|
||||
Components.interfaces.nsIAccessibleTextChangeEvent;
|
||||
const nsIAccessibleVirtualCursorChangeEvent =
|
||||
Components.interfaces.nsIAccessibleVirtualCursorChangeEvent;
|
||||
const nsIAccessibleObjectAttributeChangedEvent =
|
||||
Components.interfaces.nsIAccessibleObjectAttributeChangedEvent;
|
||||
|
||||
const nsIAccessibleStates = Components.interfaces.nsIAccessibleStates;
|
||||
const nsIAccessibleRole = Components.interfaces.nsIAccessibleRole;
|
||||
|
@ -1773,6 +1773,43 @@ function textSelectionChecker(aID, aStartOffset, aEndOffset)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Object attribute changed checker
|
||||
*/
|
||||
function objAttrChangedChecker(aID, aAttr)
|
||||
{
|
||||
this.__proto__ = new invokerChecker(EVENT_OBJECT_ATTRIBUTE_CHANGED, aID);
|
||||
|
||||
this.check = function objAttrChangedChecker_check(aEvent)
|
||||
{
|
||||
var event = null;
|
||||
try {
|
||||
var event = aEvent.QueryInterface(
|
||||
nsIAccessibleObjectAttributeChangedEvent);
|
||||
} catch (e) {
|
||||
ok(false, "Object attribute changed event was expected");
|
||||
}
|
||||
|
||||
if (!event) {
|
||||
return;
|
||||
}
|
||||
|
||||
is(event.changedAttribute.toString(), aAttr,
|
||||
"Wrong attribute name of the object attribute changed event.");
|
||||
};
|
||||
|
||||
this.match = function objAttrChangedChecker_match(aEvent)
|
||||
{
|
||||
if (aEvent instanceof nsIAccessibleObjectAttributeChangedEvent) {
|
||||
var scEvent = aEvent.QueryInterface(
|
||||
nsIAccessibleObjectAttributeChangedEvent);
|
||||
return (aEvent.accessible == getAccessible(this.target)) &&
|
||||
(scEvent.changedAttribute.toString() == aAttr);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* State change checker.
|
||||
*/
|
||||
|
@ -20,25 +20,24 @@
|
||||
* Do tests.
|
||||
*/
|
||||
var gQueue = null;
|
||||
|
||||
function updateAttribute(aID, aAttr, aValue)
|
||||
{
|
||||
this.node = getNode(aID);
|
||||
this.accessible = getAccessible(this.node);
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_OBJECT_ATTRIBUTE_CHANGED, this.accessible),
|
||||
new objAttrChangedChecker(aID, aAttr),
|
||||
];
|
||||
|
||||
this.invoke = function updateAttribute_invoke()
|
||||
{
|
||||
this.node.setAttribute(aAttr, aValue);
|
||||
}
|
||||
};
|
||||
|
||||
this.getID = function updateAttribute_getID()
|
||||
{
|
||||
return aAttr + " for " + aID + " " + aValue;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Debug stuff.
|
||||
|
@ -24,6 +24,22 @@
|
||||
document.getElementById('alert').hidden = true;
|
||||
}
|
||||
|
||||
function ariaShowBack() {
|
||||
document.getElementById('back').setAttribute('aria-hidden', false);
|
||||
}
|
||||
|
||||
function ariaHideBack() {
|
||||
document.getElementById('back').setAttribute('aria-hidden', true);
|
||||
}
|
||||
|
||||
function ariaShowIframe() {
|
||||
document.getElementById('iframe').setAttribute('aria-hidden', false);
|
||||
}
|
||||
|
||||
function ariaHideIframe() {
|
||||
document.getElementById('iframe').setAttribute('aria-hidden', true);
|
||||
}
|
||||
|
||||
</script>
|
||||
<style>
|
||||
#windows {
|
||||
@ -58,6 +74,7 @@
|
||||
<body>
|
||||
<div>Phone status bar</div>
|
||||
<div id="windows">
|
||||
<button id="back">Back</button>
|
||||
<div id="appframe"></div>
|
||||
<div role="dialog" id="alert" hidden>
|
||||
<h1>This is an alert!</h1>
|
||||
|
@ -24,6 +24,7 @@
|
||||
function doTest() {
|
||||
var doc = currentTabDocument();
|
||||
var iframe = doc.createElement('iframe');
|
||||
iframe.id = 'iframe';
|
||||
iframe.mozbrowser = true;
|
||||
iframe.addEventListener('mozbrowserloadend', function () {
|
||||
var contentTest = new AccessFuContentTest(
|
||||
@ -33,6 +34,9 @@
|
||||
speak: ['Phone status bar', 'Traversal Rule test document'],
|
||||
focused: 'body'
|
||||
}],
|
||||
[ContentMessages.simpleMoveNext, {
|
||||
speak: ["Back", {"string": "pushbutton"}]
|
||||
}],
|
||||
[ContentMessages.simpleMoveNext, {
|
||||
speak: ['wow', {'string': 'headingLevel', 'args': [1]} ,'such app'],
|
||||
focused: 'iframe'
|
||||
@ -79,10 +83,16 @@
|
||||
[ContentMessages.simpleMovePrevious, {
|
||||
speak: ['wow', {'string': 'headingLevel', 'args': [1]}]
|
||||
}],
|
||||
[ContentMessages.simpleMovePrevious, {
|
||||
speak: ["Back", {"string": "pushbutton"}]
|
||||
}],
|
||||
[ContentMessages.simpleMovePrevious, {
|
||||
speak: ['Phone status bar']
|
||||
}],
|
||||
|
||||
[ContentMessages.simpleMoveNext, {
|
||||
speak: ["Back", {"string": "pushbutton"}]
|
||||
}],
|
||||
// Moving to the absolute last item from an embedded document
|
||||
// fails. Bug 972035.
|
||||
[ContentMessages.simpleMoveNext, {
|
||||
@ -101,6 +111,9 @@
|
||||
[ContentMessages.simpleMoveNext, {
|
||||
speak: ['Phone status bar', 'Traversal Rule test document']
|
||||
}],
|
||||
[ContentMessages.simpleMoveNext, {
|
||||
speak: ["Back", {"string": "pushbutton"}]
|
||||
}],
|
||||
[ContentMessages.simpleMoveNext, {
|
||||
speak: ['wow', {'string': 'headingLevel', 'args': [1]}, 'such app']
|
||||
}],
|
||||
@ -134,6 +147,9 @@
|
||||
[ContentMessages.simpleMoveNext, {
|
||||
speak: ['Phone status bar', 'Traversal Rule test document']
|
||||
}],
|
||||
[ContentMessages.simpleMoveNext, {
|
||||
speak: ["Back", {"string": "pushbutton"}]
|
||||
}],
|
||||
[ContentMessages.simpleMoveNext, {
|
||||
speak: ['wow', {'string': 'headingLevel', 'args': [1]}, 'such app']
|
||||
}],
|
||||
@ -149,6 +165,54 @@
|
||||
// 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.
|
||||
|
||||
// aria-hidden element that the virtual cursor is positioned on
|
||||
[ContentMessages.simpleMoveNext, {
|
||||
speak: ['Phone status bar', 'Traversal Rule test document']
|
||||
}],
|
||||
[ContentMessages.simpleMoveNext, {
|
||||
speak: ["Back", {"string": "pushbutton"}]
|
||||
}],
|
||||
[doc.defaultView.ariaHideBack, {
|
||||
speak: ["wow", {"string": "headingLevel","args": [1]}, "such app"],
|
||||
}],
|
||||
// Changing aria-hidden attribute twice and making sure that the event
|
||||
// is fired only once when the actual change happens.
|
||||
[doc.defaultView.ariaHideBack],
|
||||
[doc.defaultView.ariaShowBack],
|
||||
[ContentMessages.simpleMovePrevious, {
|
||||
speak: ["Back", {"string": "pushbutton"}]
|
||||
}],
|
||||
[ContentMessages.clearCursor, 'AccessFu:CursorCleared'],
|
||||
|
||||
// aria-hidden on the iframe that has the vc.
|
||||
[ContentMessages.simpleMoveNext, {
|
||||
speak: ['Phone status bar', 'Traversal Rule test document']
|
||||
}],
|
||||
[ContentMessages.simpleMoveNext, {
|
||||
speak: ["Back", {"string": "pushbutton"}]
|
||||
}],
|
||||
[ContentMessages.simpleMoveNext, {
|
||||
speak: ['wow', {'string': 'headingLevel', 'args': [1]}, 'such app']
|
||||
}],
|
||||
[doc.defaultView.ariaHideIframe, {
|
||||
speak: ['Home', {'string': 'pushbutton'}]
|
||||
}],
|
||||
[doc.defaultView.ariaShowIframe],
|
||||
[ContentMessages.clearCursor, 'AccessFu:CursorCleared'],
|
||||
|
||||
// aria-hidden element and auto Move
|
||||
[ContentMessages.simpleMoveNext, {
|
||||
speak: ['Phone status bar', 'Traversal Rule test document']
|
||||
}],
|
||||
[doc.defaultView.ariaHideBack],
|
||||
[ContentMessages.focusSelector('button#back', false), {
|
||||
// Must not speak Back button as it is aria-hidden
|
||||
speak: ["wow", {"string": "headingLevel","args": [1]}, "such app"],
|
||||
}],
|
||||
[doc.defaultView.ariaShowBack],
|
||||
[ContentMessages.focusSelector('button#back', true), null],
|
||||
[ContentMessages.clearCursor, 'AccessFu:CursorCleared'],
|
||||
|
||||
// Open dialog in outer doc, while cursor is also in outer doc
|
||||
[ContentMessages.simpleMoveNext, {
|
||||
speak: ['Phone status bar', 'Traversal Rule test document']
|
||||
@ -169,6 +233,9 @@
|
||||
[ContentMessages.simpleMoveNext, {
|
||||
speak: ['Phone status bar', 'Traversal Rule test document']
|
||||
}],
|
||||
[ContentMessages.simpleMoveNext, {
|
||||
speak: ["Back", {"string": "pushbutton"}]
|
||||
}],
|
||||
[ContentMessages.simpleMoveNext, {
|
||||
speak: ['wow', {'string': 'headingLevel', 'args': [1]}, 'such app']
|
||||
}],
|
||||
|
@ -33,6 +33,16 @@
|
||||
element.style.display = "block";
|
||||
}
|
||||
|
||||
function ariaHide(id) {
|
||||
var element = document.getElementById(id);
|
||||
element.setAttribute('aria-hidden', true);
|
||||
}
|
||||
|
||||
function ariaShow(id) {
|
||||
var element = document.getElementById(id);
|
||||
element.setAttribute('aria-hidden', false);
|
||||
}
|
||||
|
||||
function udpate(id, text, property) {
|
||||
var element = document.getElementById(id);
|
||||
element[property] = text;
|
||||
@ -60,7 +70,7 @@
|
||||
}, {
|
||||
expected: {
|
||||
"eventType": "liveregion-change",
|
||||
"data": [{"string": "hidden"},"I will be hidden"],
|
||||
"data": [{"string": "hidden"}, "I will be hidden"],
|
||||
"options": {
|
||||
"enqueue": true
|
||||
}
|
||||
@ -92,6 +102,54 @@
|
||||
[show(id) for (id of ["to_show_descendant1", "to_show_descendant2",
|
||||
"to_show_descendant3", "to_show_descendant4"])];
|
||||
}
|
||||
}, {
|
||||
expected: {
|
||||
"eventType": "liveregion-change",
|
||||
"data": [{"string": "hidden"}, "I will be hidden"],
|
||||
"options": {
|
||||
"enqueue": true
|
||||
}
|
||||
},
|
||||
action: function action() {
|
||||
[ariaHide(id) for (id of ["to_hide5", "to_hide6", "to_hide7",
|
||||
"to_hide8", "to_hide9"])];
|
||||
}
|
||||
}, {
|
||||
expected: {
|
||||
"eventType": "liveregion-change",
|
||||
"data": [{"string": "hidden"}, "I will be hidden"],
|
||||
"options": {
|
||||
"enqueue": true
|
||||
}
|
||||
},
|
||||
action: function action() {
|
||||
[ariaHide(id) for (id of ["to_hide_descendant5", "to_hide_descendant6",
|
||||
"to_hide_descendant7", "to_hide_descendant8"])];
|
||||
}
|
||||
}, {
|
||||
expected: {
|
||||
"eventType": "liveregion-change",
|
||||
"data": ["I will be shown"],
|
||||
"options": {
|
||||
"enqueue": true
|
||||
}
|
||||
},
|
||||
action: function action() {
|
||||
[ariaShow(id) for (id of ["to_show5", "to_show6", "to_show7",
|
||||
"to_show8", "to_show9"])];
|
||||
}
|
||||
}, {
|
||||
expected: {
|
||||
"eventType": "liveregion-change",
|
||||
"data": ["I will be shown"],
|
||||
"options": {
|
||||
"enqueue": true
|
||||
}
|
||||
},
|
||||
action: function action() {
|
||||
[ariaShow(id) for (id of ["to_show_descendant5", "to_show_descendant6",
|
||||
"to_show_descendant7", "to_show_descendant8"])];
|
||||
}
|
||||
}, {
|
||||
expected: {
|
||||
"eventType": "liveregion-change",
|
||||
@ -103,6 +161,17 @@
|
||||
action: function action() {
|
||||
hide("to_hide_live_assertive");
|
||||
}
|
||||
}, {
|
||||
expected: {
|
||||
"eventType": "liveregion-change",
|
||||
"data": [{"string": "hidden"}, "I will be hidden"],
|
||||
"options": {
|
||||
"enqueue": false
|
||||
}
|
||||
},
|
||||
action: function action() {
|
||||
ariaHide("to_hide_live_assertive2");
|
||||
}
|
||||
}, {
|
||||
expected: {
|
||||
"eventType": "liveregion-change",
|
||||
@ -114,6 +183,18 @@
|
||||
action: function action() {
|
||||
[show(id) for (id of ["to_show_live_off", "to_show_live_assertive"])];
|
||||
}
|
||||
}, {
|
||||
expected: {
|
||||
"eventType": "liveregion-change",
|
||||
"data": ["I will be shown"],
|
||||
"options": {
|
||||
"enqueue": false
|
||||
}
|
||||
},
|
||||
action: function action() {
|
||||
[ariaShow(id) for (id of ["to_show_live_off2",
|
||||
"to_show_live_assertive2"])];
|
||||
}
|
||||
}, {
|
||||
expected: {
|
||||
"eventType": "liveregion-change",
|
||||
@ -284,6 +365,12 @@
|
||||
<p id="to_hide3" aria-live="assertive" aria-relevant="text">I should not be announced 3</p>
|
||||
<p id="to_hide4" aria-live="polite" aria-relevant="all">I will be hidden</p>
|
||||
|
||||
<p id="to_hide5" aria-hidden="true">I should not be announced 5</p>
|
||||
<p id="to_hide6">I should not be announced 6</p>
|
||||
<p id="to_hide7" aria-live="polite">I should not be announced 7</p>
|
||||
<p id="to_hide8" aria-live="assertive" aria-relevant="text">I should not be announced 8</p>
|
||||
<p id="to_hide9" aria-live="polite" aria-relevant="all">I will be hidden</p>
|
||||
|
||||
<div>
|
||||
<p id="to_hide_descendant1">I should not be announced 1</p>
|
||||
</div>
|
||||
@ -297,11 +384,30 @@
|
||||
<p id="to_hide_descendant4">I will be hidden</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p id="to_hide_descendant5">I should not be announced 4</p>
|
||||
</div>
|
||||
<div aria-live="polite">
|
||||
<p id="to_hide_descendant6">I should not be announced 5</p>
|
||||
</div>
|
||||
<div aria-live="assertive" aria-relevant="text">
|
||||
<p id="to_hide_descendant7">I should not be announced 6</p>
|
||||
</div>
|
||||
<div aria-live="polite" aria-relevant="all">
|
||||
<p id="to_hide_descendant8">I will be hidden</p>
|
||||
</div>
|
||||
|
||||
<p id="to_show1" style="display: none">I should not be announced 1</p>
|
||||
<p id="to_show2" aria-live="assertive" aria-relevant="text" style="display: none">I should not be announced 2</p>
|
||||
<p id="to_show3" aria-live="polite" aria-relevant="removals" style="display: none">I should not be announced 3</p>
|
||||
<p id="to_show4" aria-live="polite" aria-relevant="all" style="display: none">I will be shown</p>
|
||||
|
||||
<p id="to_show5" aria-hidden="false">I should not be announced 5</p>
|
||||
<p id="to_show6" aria-hidden="true">I should not be announced 6</p>
|
||||
<p id="to_show7" aria-hidden="true" aria-live="assertive" aria-relevant="text">I should not be announced 7</p>
|
||||
<p id="to_show8" aria-hidden="true" aria-live="polite" aria-relevant="removals">I should not be announced 8</p>
|
||||
<p id="to_show9" aria-hidden="true" aria-live="polite" aria-relevant="all">I will be shown</p>
|
||||
|
||||
<div>
|
||||
<p id="to_show_descendant1" style="display: none">I should not be announced 1</p>
|
||||
</div>
|
||||
@ -315,13 +421,34 @@
|
||||
<p id="to_show_descendant4" style="display: none">I will be shown</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p id="to_show_descendant5" aria-hidden="true">I should not be announced 5</p>
|
||||
</div>
|
||||
<div aria-live="polite" aria-relevant="removals">
|
||||
<p id="to_show_descendant6" aria-hidden="true">I should not be announced 6</p>
|
||||
</div>
|
||||
<div aria-live="assertive" aria-relevant="text">
|
||||
<p id="to_show_descendant7" aria-hidden="true">I should not be announced 7</p>
|
||||
</div>
|
||||
<div aria-live="polite" aria-relevant="all">
|
||||
<p id="to_show_descendant8" aria-hidden="true">I will be shown</p>
|
||||
</div>
|
||||
|
||||
<div aria-live="assertive" aria-relevant="all">
|
||||
<p id="to_hide_live_assertive">I will be hidden</p>
|
||||
</div>
|
||||
|
||||
<div aria-live="assertive" aria-relevant="all">
|
||||
<p id="to_hide_live_assertive2">I will be hidden</p>
|
||||
</div>
|
||||
<p id="to_show_live_assertive" aria-live="assertive" style="display: none">I will be shown</p>
|
||||
|
||||
<p id="to_show_live_off" aria-live="off" style="display: none">I will not be shown</p>
|
||||
|
||||
<p id="to_show_live_assertive2" aria-live="assertive" aria-hidden="true">I will be shown</p>
|
||||
|
||||
<p id="to_show_live_off2" aria-live="off" aria-hidden="true">I will not be shown</p>
|
||||
|
||||
<div id="to_replace_region" aria-live="polite" aria-relevant="all">
|
||||
<p id="to_replace">I am replaced</p>
|
||||
</div>
|
||||
|
@ -12,6 +12,7 @@ simple_events = [
|
||||
'TextChangeEvent',
|
||||
'HideEvent',
|
||||
'CaretMoveEvent',
|
||||
'ObjectAttributeChangedEvent',
|
||||
'TableChangeEvent',
|
||||
'VirtualCursorChangeEvent'
|
||||
]
|
||||
|
@ -103,8 +103,21 @@ function onSubmitStatus(subj, topic, data) {
|
||||
if (data != "success" && data != "failed")
|
||||
return;
|
||||
|
||||
let extra = getPropertyBagValue(subj.QueryInterface(Ci.nsIPropertyBag),
|
||||
"extra");
|
||||
let propBag = subj.QueryInterface(Ci.nsIPropertyBag);
|
||||
if (data == "success") {
|
||||
let remoteID = getPropertyBagValue(propBag, "serverCrashID");
|
||||
ok(!!remoteID, "serverCrashID should be set");
|
||||
|
||||
// Remove the submitted report file.
|
||||
let file = Services.dirsvc.get("UAppData", Ci.nsILocalFile);
|
||||
file.append("Crash Reports");
|
||||
file.append("submitted");
|
||||
file.append(remoteID + ".txt");
|
||||
ok(file.exists(), "Submitted report file should exist");
|
||||
file.remove(false);
|
||||
}
|
||||
|
||||
let extra = getPropertyBagValue(propBag, "extra");
|
||||
ok(extra instanceof Ci.nsIPropertyBag, "Extra data should be property bag");
|
||||
|
||||
let val = getPropertyBagValue(extra, "PluginUserComment");
|
||||
|
@ -8756,6 +8756,7 @@ AC_SUBST(VPX_X86_ASM)
|
||||
AC_SUBST(VPX_ARM_ASM)
|
||||
AC_SUBST(VPX_NEED_OBJ_INT_EXTRACT)
|
||||
AC_SUBST(MOZ_INSTRUMENT_EVENT_LOOP)
|
||||
AC_SUBST(MOZ_CODE_COVERAGE)
|
||||
AC_SUBST(LIBJPEG_TURBO_AS)
|
||||
AC_SUBST(LIBJPEG_TURBO_ASFLAGS)
|
||||
AC_SUBST(LIBJPEG_TURBO_X86_ASM)
|
||||
|
@ -1500,20 +1500,22 @@ Element::UnbindFromTree(bool aDeep, bool aNullParent)
|
||||
|
||||
// Unset this since that's what the old code effectively did.
|
||||
UnsetFlags(NODE_FORCE_XBL_BINDINGS);
|
||||
bool clearBindingParent = true;
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
nsXULElement* xulElem = nsXULElement::FromContent(this);
|
||||
if (xulElem) {
|
||||
xulElem->SetXULBindingParent(nullptr);
|
||||
clearBindingParent = false;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
nsDOMSlots *slots = GetExistingDOMSlots();
|
||||
|
||||
nsDOMSlots* slots = GetExistingDOMSlots();
|
||||
if (slots) {
|
||||
if (clearBindingParent) {
|
||||
slots->mBindingParent = nullptr;
|
||||
slots->mContainingShadow = nullptr;
|
||||
}
|
||||
slots->mContainingShadow = nullptr;
|
||||
}
|
||||
|
||||
// This has to be here, rather than in nsGenericHTMLElement::UnbindFromTree,
|
||||
|
@ -34,6 +34,9 @@ function checkAllowed () {
|
||||
ok(color === green, "Eval should be allowed");
|
||||
color = window.getComputedStyle(cspframe.contentDocument.getElementById('unsafe-inline-style-allowed')).color;
|
||||
ok(color === green, "Inline style should be allowed");
|
||||
|
||||
document.getElementById('cspframe2').src = 'file_CSP_bug885433_blocks.html';
|
||||
document.getElementById('cspframe2').addEventListener('load', checkBlocked, false);
|
||||
}
|
||||
|
||||
function checkBlocked () {
|
||||
@ -52,8 +55,6 @@ function checkBlocked () {
|
||||
|
||||
document.getElementById('cspframe').src = 'file_CSP_bug885433_allows.html';
|
||||
document.getElementById('cspframe').addEventListener('load', checkAllowed, false);
|
||||
document.getElementById('cspframe2').src = 'file_CSP_bug885433_blocks.html';
|
||||
document.getElementById('cspframe2').addEventListener('load', checkBlocked, false);
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
4
content/html/content/public/HTMLMediaElement.h
Normal file → Executable file
4
content/html/content/public/HTMLMediaElement.h
Normal file → Executable file
@ -1151,6 +1151,10 @@ protected:
|
||||
// to raise the 'waiting' event as per 4.7.1.8 in HTML 5 specification.
|
||||
bool mPlayingBeforeSeek;
|
||||
|
||||
// if TRUE then the seek started while content was in active playing state
|
||||
// if FALSE then the seek started while the content was not playing.
|
||||
bool mPlayingThroughTheAudioChannelBeforeSeek;
|
||||
|
||||
// True iff this element is paused because the document is inactive or has
|
||||
// been suspended by the audio channel service.
|
||||
bool mPausedForInactiveDocumentOrChannel;
|
||||
|
9
content/html/content/src/HTMLMediaElement.cpp
Normal file → Executable file
9
content/html/content/src/HTMLMediaElement.cpp
Normal file → Executable file
@ -2034,6 +2034,7 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
|
||||
mIsCasting(false),
|
||||
mAudioCaptured(false),
|
||||
mPlayingBeforeSeek(false),
|
||||
mPlayingThroughTheAudioChannelBeforeSeek(false),
|
||||
mPausedForInactiveDocumentOrChannel(false),
|
||||
mEventDeliveryPaused(false),
|
||||
mWaitingFired(false),
|
||||
@ -3056,6 +3057,10 @@ void HTMLMediaElement::PlaybackEnded()
|
||||
void HTMLMediaElement::SeekStarted()
|
||||
{
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("seeking"));
|
||||
// Set the Variable if the Seekstarted while active playing
|
||||
if(mPlayingThroughTheAudioChannel) {
|
||||
mPlayingThroughTheAudioChannelBeforeSeek = true;
|
||||
}
|
||||
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
|
||||
FireTimeUpdate(false);
|
||||
}
|
||||
@ -3073,6 +3078,8 @@ void HTMLMediaElement::SeekCompleted()
|
||||
if (mCurrentPlayRangeStart == -1.0) {
|
||||
mCurrentPlayRangeStart = CurrentTime();
|
||||
}
|
||||
// Unset the variable on seekend
|
||||
mPlayingThroughTheAudioChannelBeforeSeek = false;
|
||||
}
|
||||
|
||||
void HTMLMediaElement::NotifySuspendedByCache(bool aIsSuspended)
|
||||
@ -3913,7 +3920,7 @@ void HTMLMediaElement::UpdateAudioChannelPlayingState()
|
||||
(HasAttr(kNameSpaceID_None, nsGkAtoms::loop) ||
|
||||
(mReadyState >= nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA &&
|
||||
!IsPlaybackEnded()) ||
|
||||
mPlayingBeforeSeek));
|
||||
mPlayingThroughTheAudioChannelBeforeSeek));
|
||||
if (playingThroughTheAudioChannel != mPlayingThroughTheAudioChannel) {
|
||||
mPlayingThroughTheAudioChannel = playingThroughTheAudioChannel;
|
||||
|
||||
|
@ -1521,8 +1521,10 @@ nsTextEditorState::UnbindFromFrame(nsTextControlFrame* aFrame)
|
||||
// If the editor is modified but nsIEditorObserver::EditAction() hasn't been
|
||||
// called yet, we need to notify it here because editor may be destroyed
|
||||
// before EditAction() is called if selection listener causes flushing layout.
|
||||
bool isInEditAction = false;
|
||||
if (mTextListener && mEditor && mEditorInitialized &&
|
||||
mEditor->GetIsInEditAction()) {
|
||||
NS_SUCCEEDED(mEditor->GetIsInEditAction(&isInEditAction)) &&
|
||||
isInEditAction) {
|
||||
mTextListener->EditAction();
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,9 @@ void GraphDriver::UpdateStateComputedTime(GraphTime aStateComputedTime)
|
||||
// The next state computed time can be the same as the previous, here: it
|
||||
// means the driver would be have been blocking indefinitly, but the graph has
|
||||
// been woken up right after having been to sleep.
|
||||
MOZ_ASSERT(aStateComputedTime >= mStateComputedTime, "State time can't go backward.");
|
||||
if (aStateComputedTime < mStateComputedTime) {
|
||||
printf("State time can't go backward %ld < %ld.\n", static_cast<long>(aStateComputedTime), static_cast<long>(mStateComputedTime));
|
||||
}
|
||||
|
||||
mStateComputedTime = aStateComputedTime;
|
||||
}
|
||||
|
@ -1310,6 +1310,7 @@ MediaStreamGraphImpl::Process(GraphTime aFrom, GraphTime aTo)
|
||||
// Only playback audio and video in real-time mode
|
||||
if (mRealtime) {
|
||||
CreateOrDestroyAudioStreams(aFrom, stream);
|
||||
if (CurrentDriver()->AsAudioCallbackDriver()) {
|
||||
TrackTicks ticksPlayedForThisStream = PlayAudio(stream, aFrom, aTo);
|
||||
if (!ticksPlayed) {
|
||||
ticksPlayed = ticksPlayedForThisStream;
|
||||
@ -1317,6 +1318,7 @@ MediaStreamGraphImpl::Process(GraphTime aFrom, GraphTime aTo)
|
||||
MOZ_ASSERT(!ticksPlayedForThisStream || ticksPlayedForThisStream == ticksPlayed,
|
||||
"Each stream should have the same number of frame.");
|
||||
}
|
||||
}
|
||||
PlayVideo(stream);
|
||||
}
|
||||
SourceMediaStream* is = stream->AsSourceStream();
|
||||
|
@ -77,4 +77,4 @@ load oscillator-ended-2.html
|
||||
include ../../mediasource/test/crashtests/crashtests.list
|
||||
|
||||
# This needs to run at the end to avoid leaking busted state into other tests.
|
||||
load 691096-1.html
|
||||
skip-if(winWidget) load 691096-1.html
|
||||
|
@ -240,6 +240,7 @@ AutoJSAPI::AutoJSAPI()
|
||||
void
|
||||
AutoJSAPI::InitInternal(JSObject* aGlobal, JSContext* aCx, bool aIsMainThread)
|
||||
{
|
||||
MOZ_ASSERT(aCx);
|
||||
mCx = aCx;
|
||||
if (aIsMainThread) {
|
||||
// This Rooted<> is necessary only as long as AutoCxPusher::AutoCxPusher
|
||||
|
@ -991,7 +991,9 @@ IMEContentObserver::FlushMergeableNotifications()
|
||||
}
|
||||
|
||||
// If we're in handling an edit action, this method will be called later.
|
||||
if (mEditor && mEditor->GetIsInEditAction()) {
|
||||
bool isInEditAction = false;
|
||||
if (mEditor && NS_SUCCEEDED(mEditor->GetIsInEditAction(&isInEditAction)) &&
|
||||
isInEditAction) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1539,6 +1539,10 @@ PeerConnectionWrapper.prototype = {
|
||||
* The location the stream is coming from ('local' or 'remote')
|
||||
*/
|
||||
attachMedia : function PCW_attachMedia(stream, type, side) {
|
||||
function isSenderOfTrack(sender) {
|
||||
return sender.track == this;
|
||||
}
|
||||
|
||||
info("Got media stream: " + type + " (" + side + ")");
|
||||
this.streams.push(stream);
|
||||
|
||||
@ -1547,9 +1551,13 @@ PeerConnectionWrapper.prototype = {
|
||||
// way and audio + audiovideo the other.
|
||||
if (type == "video") {
|
||||
this._pc.addStream(stream);
|
||||
ok(this._pc.getSenders().find(isSenderOfTrack,
|
||||
stream.getVideoTracks()[0]),
|
||||
"addStream adds sender");
|
||||
} else {
|
||||
stream.getTracks().forEach(function(track) {
|
||||
this._pc.addTrack(track, stream);
|
||||
var sender = this._pc.addTrack(track, stream);
|
||||
is(sender.track, track, "addTrack returns sender");
|
||||
}.bind(this));
|
||||
}
|
||||
}
|
||||
|
@ -39,17 +39,27 @@ ServiceWorkerContainer::ServiceWorkerContainer(nsPIDOMWindow* aWindow)
|
||||
|
||||
ServiceWorkerContainer::~ServiceWorkerContainer()
|
||||
{
|
||||
RemoveReadyPromise();
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerContainer::DisconnectFromOwner()
|
||||
{
|
||||
nsCOMPtr<nsIServiceWorkerManager> swm = mozilla::services::GetServiceWorkerManager();
|
||||
RemoveReadyPromise();
|
||||
DOMEventTargetHelper::DisconnectFromOwner();
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerContainer::RemoveReadyPromise()
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> window = GetOwner();
|
||||
if (window) {
|
||||
nsCOMPtr<nsIServiceWorkerManager> swm =
|
||||
mozilla::services::GetServiceWorkerManager();
|
||||
MOZ_ASSERT(swm);
|
||||
|
||||
swm->RemoveReadyPromise(GetOwner());
|
||||
|
||||
DOMEventTargetHelper::DisconnectFromOwner();
|
||||
swm->RemoveReadyPromise(window);
|
||||
}
|
||||
}
|
||||
|
||||
JSObject*
|
||||
|
@ -75,6 +75,8 @@ public:
|
||||
private:
|
||||
~ServiceWorkerContainer();
|
||||
|
||||
void RemoveReadyPromise();
|
||||
|
||||
// This only changes when a worker hijacks everything in its scope by calling
|
||||
// replace().
|
||||
// FIXME(nsm): Bug 982711. Provide API to let SWM invalidate this.
|
||||
|
@ -1851,6 +1851,7 @@ NS_IMETHODIMP
|
||||
ServiceWorkerManager::AddRegistrationEventListener(nsIURI* aDocumentURI, nsIDOMEventTarget* aListener)
|
||||
{
|
||||
MOZ_ASSERT(aDocumentURI);
|
||||
AssertIsOnMainThread();
|
||||
nsRefPtr<ServiceWorkerDomainInfo> domainInfo = GetDomainInfo(aDocumentURI);
|
||||
if (!domainInfo) {
|
||||
nsCString domain;
|
||||
@ -1875,6 +1876,7 @@ ServiceWorkerManager::AddRegistrationEventListener(nsIURI* aDocumentURI, nsIDOME
|
||||
NS_IMETHODIMP
|
||||
ServiceWorkerManager::RemoveRegistrationEventListener(nsIURI* aDocumentURI, nsIDOMEventTarget* aListener)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aDocumentURI);
|
||||
nsRefPtr<ServiceWorkerDomainInfo> domainInfo = GetDomainInfo(aDocumentURI);
|
||||
if (!domainInfo) {
|
||||
|
@ -38,6 +38,7 @@ ServiceWorkerRegistration::ServiceWorkerRegistration(nsPIDOMWindow* aWindow,
|
||||
const nsAString& aScope)
|
||||
: DOMEventTargetHelper(aWindow)
|
||||
, mScope(aScope)
|
||||
, mListeningForEvents(false)
|
||||
{
|
||||
MOZ_ASSERT(aWindow);
|
||||
MOZ_ASSERT(aWindow->IsInnerWindow());
|
||||
@ -47,6 +48,7 @@ ServiceWorkerRegistration::ServiceWorkerRegistration(nsPIDOMWindow* aWindow,
|
||||
|
||||
ServiceWorkerRegistration::~ServiceWorkerRegistration()
|
||||
{
|
||||
StopListeningForEvents();
|
||||
}
|
||||
|
||||
void
|
||||
@ -176,15 +178,21 @@ ServiceWorkerRegistration::StartListeningForEvents()
|
||||
nsCOMPtr<nsIServiceWorkerManager> swm = do_GetService(SERVICEWORKERMANAGER_CONTRACTID);
|
||||
if (swm) {
|
||||
swm->AddRegistrationEventListener(GetDocumentURI(), this);
|
||||
mListeningForEvents = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerRegistration::StopListeningForEvents()
|
||||
{
|
||||
if (!mListeningForEvents) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIServiceWorkerManager> swm = do_GetService(SERVICEWORKERMANAGER_CONTRACTID);
|
||||
if (swm) {
|
||||
swm->RemoveRegistrationEventListener(GetDocumentURI(), this);
|
||||
mListeningForEvents = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,6 +86,7 @@ private:
|
||||
nsRefPtr<workers::ServiceWorker> mActiveWorker;
|
||||
|
||||
const nsString mScope;
|
||||
bool mListeningForEvents;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -21,7 +21,7 @@ interface nsIEditActionListener;
|
||||
interface nsIInlineSpellChecker;
|
||||
interface nsITransferable;
|
||||
|
||||
[builtinclass, scriptable, uuid(c3b61bc9-ccdd-4bcd-acd8-1b8dcbe6a247)]
|
||||
[scriptable, uuid(04714a01-e02f-4ef5-a388-612451d0db16)]
|
||||
|
||||
interface nsIEditor : nsISupports
|
||||
{
|
||||
@ -555,5 +555,5 @@ interface nsIEditor : nsISupports
|
||||
* nsIEditorObserver::BeforeEditAction() and nsIEditorObserver::EditAction()
|
||||
* or nsIEditorObserver::CancelEditAction(). Otherwise, false.
|
||||
*/
|
||||
[infallible, noscript] readonly attribute boolean isInEditAction;
|
||||
[noscript] readonly attribute boolean isInEditAction;
|
||||
};
|
||||
|
@ -22,7 +22,7 @@ class Element;
|
||||
|
||||
[ptr] native Element (mozilla::dom::Element);
|
||||
|
||||
[builtinclass, scriptable, uuid(9470bee7-cad3-4382-8fb4-6bdda9f0273a)]
|
||||
[scriptable, uuid(393a364f-e8e2-48a1-a271-a0067b6bac9b)]
|
||||
|
||||
interface nsIHTMLEditor : nsISupports
|
||||
{
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[builtinclass, scriptable, uuid(da8f244b-6ffc-4be1-8b1a-667abfe1d304)]
|
||||
[scriptable, uuid(b74fb158-1265-4102-91eb-edd0136b49f8)]
|
||||
interface nsIPlaintextEditor : nsISupports
|
||||
{
|
||||
|
||||
|
@ -103,7 +103,7 @@ FPSCounter::IteratedFullInterval(TimeStamp aTimestamp, double aDuration) {
|
||||
|
||||
TimeStamp currentStamp = mFrameTimestamps[mIteratorIndex];
|
||||
TimeDuration duration = aTimestamp - currentStamp;
|
||||
return duration.ToSecondsSigDigits() >= aDuration;
|
||||
return duration.ToSeconds() >= aDuration;
|
||||
}
|
||||
|
||||
void
|
||||
@ -187,7 +187,7 @@ FPSCounter::BuildHistogram(std::map<int, int>& aFpsData)
|
||||
currentTimeStamp = GetNextTimeStamp();
|
||||
TimeDuration interval = currentIntervalStart - currentTimeStamp;
|
||||
|
||||
if (interval.ToSecondsSigDigits() >= 1.0 ) {
|
||||
if (interval.ToSeconds() >= 1.0 ) {
|
||||
currentIntervalStart = currentTimeStamp;
|
||||
aFpsData[frameCount]++;
|
||||
frameCount = 0;
|
||||
|
@ -132,7 +132,6 @@ EXIFParser::ParseIFD0(Orientation& aOrientationOut)
|
||||
return false;
|
||||
|
||||
// We should have an orientation value here; go ahead and parse it.
|
||||
Orientation orientation;
|
||||
if (!ParseOrientation(type, count, aOrientationOut))
|
||||
return false;
|
||||
|
||||
|
@ -26,11 +26,18 @@
|
||||
# though this may change if we find a need for additional properties.
|
||||
#
|
||||
# The Unicode data files listed above should be together in one directory.
|
||||
#
|
||||
# We also require the file
|
||||
# http://www.unicode.org/Public/security/latest/xidmodifications.txt
|
||||
# This file should be in a sub-directory "security" immediately below the
|
||||
# directory containing the other Unicode data files.
|
||||
#
|
||||
# We also require the latest data file for UTR50, currently revision-12:
|
||||
# http://www.unicode.org/Public/vertical/revision-12/VerticalOrientation-12.txt
|
||||
# This file should be in a sub-directory "vertical" immediately below the
|
||||
# directory containing the other Unicode data files.
|
||||
#
|
||||
#
|
||||
# (2) Run this tool using a command line of the form
|
||||
#
|
||||
# perl genUnicodePropertyData.pl \
|
||||
@ -301,6 +308,13 @@ my %bidicategoryCode = (
|
||||
"BN" => "18" # Boundary Neutral
|
||||
);
|
||||
|
||||
my %verticalOrientationCode = (
|
||||
'U' => 0, # U - Upright, the same orientation as in the code charts
|
||||
'R' => 1, # R - Rotated 90 degrees clockwise compared to the code charts
|
||||
'Tu' => 2, # Tu - Transformed typographically, with fallback to Upright
|
||||
'Tr' => 3 # Tr - Transformed typographically, with fallback to Rotated
|
||||
);
|
||||
|
||||
# initialize default properties
|
||||
my @script;
|
||||
my @category;
|
||||
@ -314,6 +328,7 @@ my @numericvalue;
|
||||
my @hanVariant;
|
||||
my @bidicategory;
|
||||
my @fullWidth;
|
||||
my @verticalOrientation;
|
||||
for (my $i = 0; $i < 0x110000; ++$i) {
|
||||
$script[$i] = $scriptCode{"UNKNOWN"};
|
||||
$category[$i] = $catCode{"UNASSIGNED"};
|
||||
@ -324,6 +339,7 @@ for (my $i = 0; $i < 0x110000; ++$i) {
|
||||
$hanVariant[$i] = 0;
|
||||
$bidicategory[$i] = $bidicategoryCode{"L"};
|
||||
$fullWidth[$i] = 0;
|
||||
$verticalOrientation[$i] = 1; # default for unlisted codepoints is 'R'
|
||||
}
|
||||
|
||||
# blocks where the default for bidi category is not L
|
||||
@ -628,6 +644,31 @@ while (<FH>) {
|
||||
}
|
||||
close FH;
|
||||
|
||||
# read VerticalOrientation-12.txt
|
||||
open FH, "< $ARGV[1]/vertical/VerticalOrientation-12.txt" or die "can't open UTR50 data file VerticalOrientation-12.txt\n";
|
||||
push @versionInfo, "";
|
||||
while (<FH>) {
|
||||
chomp;
|
||||
push @versionInfo, $_;
|
||||
last if /Date:/;
|
||||
}
|
||||
while (<FH>) {
|
||||
chomp;
|
||||
s/#.*//;
|
||||
if (m/([0-9A-F]{4,6})(?:\.\.([0-9A-F]{4,6}))*\s*;\s*([^ ]+)/) {
|
||||
my $vo = $3;
|
||||
warn "unknown Vertical_Orientation code $vo"
|
||||
unless exists $verticalOrientationCode{$vo};
|
||||
$vo = $verticalOrientationCode{$vo};
|
||||
my $start = hex "0x$1";
|
||||
my $end = (defined $2) ? hex "0x$2" : $start;
|
||||
for (my $i = $start; $i <= $end; ++$i) {
|
||||
$verticalOrientation[$i] = $vo;
|
||||
}
|
||||
}
|
||||
}
|
||||
close FH;
|
||||
|
||||
my $timestamp = gmtime();
|
||||
|
||||
open DATA_TABLES, "> nsUnicodePropertyData.cpp" or die "unable to open nsUnicodePropertyData.cpp for output";
|
||||
@ -706,18 +747,35 @@ sub sprintCharProps1
|
||||
my $usv = shift;
|
||||
return sprintf("{%d,%d,%d}, ", $mirror[$usv], $hangul[$usv], $combining[$usv]);
|
||||
}
|
||||
&genTables("CharProp1", "struct nsCharProps1 {\n unsigned char mMirrorOffsetIndex:5;\n unsigned char mHangulType:3;\n unsigned char mCombiningClass:8;\n};",
|
||||
"nsCharProps1", 11, 5, \&sprintCharProps1, 1, 2, 1);
|
||||
my $type = q/
|
||||
struct nsCharProps1 {
|
||||
unsigned char mMirrorOffsetIndex:5;
|
||||
unsigned char mHangulType:3;
|
||||
unsigned char mCombiningClass:8;
|
||||
};
|
||||
/;
|
||||
&genTables("CharProp1", $type, "nsCharProps1", 11, 5, \&sprintCharProps1, 1, 2, 1);
|
||||
|
||||
sub sprintCharProps2
|
||||
{
|
||||
my $usv = shift;
|
||||
return sprintf("{%d,%d,%d,%d,%d,%d},",
|
||||
return sprintf("{%d,%d,%d,%d,%d,%d,%d},",
|
||||
$script[$usv], $eaw[$usv], $category[$usv],
|
||||
$bidicategory[$usv], $xidmod[$usv], $numericvalue[$usv]);
|
||||
$bidicategory[$usv], $xidmod[$usv], $numericvalue[$usv],
|
||||
$verticalOrientation[$usv]);
|
||||
}
|
||||
&genTables("CharProp2", "struct nsCharProps2 {\n unsigned char mScriptCode:8;\n unsigned char mEAW:3;\n unsigned char mCategory:5;\n unsigned char mBidiCategory:5;\n unsigned char mXidmod:4;\n signed char mNumericValue:5;\n unsigned char mHanVariant:2;\n};",
|
||||
"nsCharProps2", 11, 5, \&sprintCharProps2, 16, 4, 1);
|
||||
$type = q/
|
||||
struct nsCharProps2 {
|
||||
unsigned char mScriptCode:8;
|
||||
unsigned char mEAW:3;
|
||||
unsigned char mCategory:5;
|
||||
unsigned char mBidiCategory:5;
|
||||
unsigned char mXidmod:4;
|
||||
signed char mNumericValue:5;
|
||||
unsigned char mVertOrient:2;
|
||||
};
|
||||
/;
|
||||
&genTables("CharProp2", $type, "nsCharProps2", 11, 5, \&sprintCharProps2, 16, 4, 1);
|
||||
|
||||
print HEADER "#pragma pack()\n\n";
|
||||
|
||||
|
@ -49,6 +49,18 @@ inline nsCharType GetBidiCat(uint32_t aCh) {
|
||||
return nsCharType(GetCharProps2(aCh).mBidiCategory);
|
||||
}
|
||||
|
||||
/* This MUST match the values assigned by genUnicodePropertyData.pl! */
|
||||
enum VerticalOrientation {
|
||||
VERTICAL_ORIENTATION_U = 0,
|
||||
VERTICAL_ORIENTATION_R = 1,
|
||||
VERTICAL_ORIENTATION_Tu = 2,
|
||||
VERTICAL_ORIENTATION_Tr = 3
|
||||
};
|
||||
|
||||
inline VerticalOrientation GetVerticalOrientation(uint32_t aCh) {
|
||||
return VerticalOrientation(GetCharProps2(aCh).mVertOrient);
|
||||
}
|
||||
|
||||
enum XidmodType {
|
||||
XIDMOD_INCLUSION,
|
||||
XIDMOD_RECOMMENDED,
|
||||
|
File diff suppressed because one or more lines are too long
@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Created on Fri Aug 22 16:49:19 2014 from UCD data files with version info:
|
||||
* Created on Tue Aug 26 10:16:12 2014 from UCD data files with version info:
|
||||
*
|
||||
|
||||
# Date: 2014-06-12, 20:18:00 GMT [KW]
|
||||
@ -52,6 +52,9 @@ Standard.
|
||||
# Unihan_Variants.txt
|
||||
# Date: 2014-05-09 18:17:02 GMT [JHJ]
|
||||
|
||||
# VerticalOrientation-12.txt
|
||||
# Date: 2014-07-07, 21:00:00 GMT [EM, KI, LI]
|
||||
|
||||
*
|
||||
* * * * * This file contains MACHINE-GENERATED DATA, do not edit! * * * * *
|
||||
*/
|
||||
@ -61,12 +64,15 @@ Standard.
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
|
||||
struct nsCharProps1 {
|
||||
unsigned char mMirrorOffsetIndex:5;
|
||||
unsigned char mHangulType:3;
|
||||
unsigned char mCombiningClass:8;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct nsCharProps2 {
|
||||
unsigned char mScriptCode:8;
|
||||
unsigned char mEAW:3;
|
||||
@ -74,9 +80,10 @@ struct nsCharProps2 {
|
||||
unsigned char mBidiCategory:5;
|
||||
unsigned char mXidmod:4;
|
||||
signed char mNumericValue:5;
|
||||
unsigned char mHanVariant:2;
|
||||
unsigned char mVertOrient:2;
|
||||
};
|
||||
|
||||
|
||||
#pragma pack()
|
||||
|
||||
enum {
|
||||
|
@ -138,7 +138,7 @@ class SplayTree
|
||||
template <class Op>
|
||||
void forEach(Op op)
|
||||
{
|
||||
forEachInner(op, root);
|
||||
forEachInner<Op>(op, root);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -245,9 +245,9 @@ class SplayTree
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
forEachInner(op, node->left);
|
||||
forEachInner<Op>(op, node->left);
|
||||
op(node->item);
|
||||
forEachInner(op, node->right);
|
||||
forEachInner<Op>(op, node->right);
|
||||
}
|
||||
|
||||
Node *checkCoherency(Node *node, Node *minimum)
|
||||
|
@ -1,3 +1,6 @@
|
||||
if (!this.SharedArrayBuffer || !isAsmJSCompilationAvailable())
|
||||
quit();
|
||||
|
||||
Random = {
|
||||
weighted: function(wa) {
|
||||
var a = [];
|
||||
|
@ -18,6 +18,13 @@ assertEq(fScripts.indexOf(fw.script) != -1, true);
|
||||
assertEq(fScripts.indexOf(ggw.script), -1);
|
||||
assertEq(fScripts.indexOf(hw.script), -1);
|
||||
|
||||
|
||||
fScripts = dbg.findScripts({ displayURL: "f.js",
|
||||
line: 1 });
|
||||
assertEq(fScripts.indexOf(fw.script) != -1, true);
|
||||
assertEq(fScripts.indexOf(ggw.script), -1);
|
||||
assertEq(fScripts.indexOf(hw.script), -1);
|
||||
|
||||
var gScripts = dbg.findScripts({ displayURL: "g.js" });
|
||||
assertEq(gScripts.indexOf(ggw.script) != -1, true);
|
||||
assertEq(gScripts.indexOf(fw.script), -1);
|
||||
|
20
js/src/jit-test/tests/debug/Debugger-findScripts-20.js
Normal file
20
js/src/jit-test/tests/debug/Debugger-findScripts-20.js
Normal file
@ -0,0 +1,20 @@
|
||||
var g = newGlobal();
|
||||
var dbg = new Debugger();
|
||||
var gw = dbg.addDebuggee(g);
|
||||
|
||||
g.eval('function f(){}');
|
||||
|
||||
var o = gw.makeDebuggeeValue(g.f);
|
||||
|
||||
var allScripts = dbg.findScripts();
|
||||
var scripts = dbg.findScripts({
|
||||
source: o.script.source
|
||||
});
|
||||
assertEq(scripts.length < allScripts.length, true);
|
||||
assertEq(scripts.indexOf(o.script) !== -1, true);
|
||||
|
||||
scripts = dbg.findScripts({
|
||||
source: o.script.source,
|
||||
line: 1
|
||||
});
|
||||
assertEq(scripts.indexOf(o.script) !== -1, true);
|
@ -371,8 +371,8 @@ MSG_DEF(JSMSG_DEBUG_WRAPPER_IN_WAY, 3, JSEXN_TYPEERR, "{0} is {1}{2}a global
|
||||
MSG_DEF(JSMSG_NOT_CALLABLE_OR_UNDEFINED, 0, JSEXN_TYPEERR, "value is not a function or undefined")
|
||||
MSG_DEF(JSMSG_NOT_TRACKING_ALLOCATIONS, 1, JSEXN_ERR, "Cannot call {0} without setting trackingAllocationSites to true")
|
||||
MSG_DEF(JSMSG_OBJECT_METADATA_CALLBACK_ALREADY_SET, 0, JSEXN_ERR, "Cannot track object allocation, because other tools are already doing so")
|
||||
MSG_DEF(JSMSG_QUERY_INNERMOST_WITHOUT_LINE_URL, 0, JSEXN_TYPEERR, "findScripts query object has 'innermost' property without both 'url' and 'line' properties")
|
||||
MSG_DEF(JSMSG_QUERY_LINE_WITHOUT_URL, 0, JSEXN_TYPEERR, "findScripts query object has 'line' property, but no 'url' property")
|
||||
MSG_DEF(JSMSG_QUERY_INNERMOST_WITHOUT_LINE_URL, 0, JSEXN_TYPEERR, "findScripts query object with 'innermost' property must have 'line' and either 'displayURL', 'url', or 'source'")
|
||||
MSG_DEF(JSMSG_QUERY_LINE_WITHOUT_URL, 0, JSEXN_TYPEERR, "findScripts query object has 'line' property, but no 'displayURL', 'url', or 'source' property")
|
||||
|
||||
// Intl
|
||||
MSG_DEF(JSMSG_DATE_NOT_FINITE, 0, JSEXN_RANGEERR, "date value is not finite in DateTimeFormat.format()")
|
||||
|
@ -2514,16 +2514,19 @@ Debugger::removeDebuggeeGlobalUnderGC(FreeOp *fop, GlobalObject *global,
|
||||
global->compartment()->removeDebuggeeUnderGC(fop, global, invalidate, compartmentEnum);
|
||||
}
|
||||
|
||||
static inline ScriptSourceObject *GetSourceReferent(JSObject *obj);
|
||||
|
||||
/*
|
||||
* A class for parsing 'findScripts' query arguments and searching for
|
||||
* scripts that match the criteria they represent.
|
||||
*/
|
||||
class Debugger::ScriptQuery {
|
||||
class MOZ_STACK_CLASS Debugger::ScriptQuery
|
||||
{
|
||||
public:
|
||||
/* Construct a ScriptQuery to use matching scripts for |dbg|. */
|
||||
ScriptQuery(JSContext *cx, Debugger *dbg):
|
||||
cx(cx), debugger(dbg), compartments(cx->runtime()), url(cx), displayURLString(cx),
|
||||
innermostForCompartment(cx->runtime())
|
||||
source(cx), innermostForCompartment(cx->runtime())
|
||||
{}
|
||||
|
||||
/*
|
||||
@ -2579,6 +2582,39 @@ class Debugger::ScriptQuery {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check for a 'source' property */
|
||||
RootedValue debuggerSource(cx);
|
||||
if (!JSObject::getProperty(cx, query, query, cx->names().source, &debuggerSource))
|
||||
return false;
|
||||
if (!debuggerSource.isUndefined()) {
|
||||
if (!debuggerSource.isObject() ||
|
||||
debuggerSource.toObject().getClass() != &DebuggerSource_class) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_UNEXPECTED_TYPE,
|
||||
"query object's 'source' property",
|
||||
"not undefined nor a Debugger.Source object");
|
||||
return false;
|
||||
}
|
||||
|
||||
source = GetSourceReferent(&debuggerSource.toObject());
|
||||
}
|
||||
|
||||
/* Check for a 'displayURL' property. */
|
||||
RootedValue displayURL(cx);
|
||||
if (!JSObject::getProperty(cx, query, query, cx->names().displayURL, &displayURL))
|
||||
return false;
|
||||
if (!displayURL.isUndefined() && !displayURL.isString()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_UNEXPECTED_TYPE,
|
||||
"query object's 'displayURL' property",
|
||||
"neither undefined nor a string");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (displayURL.isString()) {
|
||||
displayURLString = displayURL.toString()->ensureLinear(cx);
|
||||
if (!displayURLString)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check for a 'line' property. */
|
||||
RootedValue lineProperty(cx);
|
||||
if (!JSObject::getProperty(cx, query, query, cx->names().line, &lineProperty))
|
||||
@ -2586,7 +2622,7 @@ class Debugger::ScriptQuery {
|
||||
if (lineProperty.isUndefined()) {
|
||||
hasLine = false;
|
||||
} else if (lineProperty.isNumber()) {
|
||||
if (url.isUndefined()) {
|
||||
if (displayURL.isUndefined() && url.isUndefined() && !source) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
|
||||
JSMSG_QUERY_LINE_WITHOUT_URL);
|
||||
return false;
|
||||
@ -2613,30 +2649,13 @@ class Debugger::ScriptQuery {
|
||||
innermost = ToBoolean(innermostProperty);
|
||||
if (innermost) {
|
||||
/* Technically, we need only check hasLine, but this is clearer. */
|
||||
if (url.isUndefined() || !hasLine) {
|
||||
if ((displayURL.isUndefined() && url.isUndefined() && !source) || !hasLine) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
|
||||
JSMSG_QUERY_INNERMOST_WITHOUT_LINE_URL);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for a 'displayURL' property. */
|
||||
RootedValue displayURL(cx);
|
||||
if (!JSObject::getProperty(cx, query, query, cx->names().displayURL, &displayURL))
|
||||
return false;
|
||||
if (!displayURL.isUndefined() && !displayURL.isString()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_UNEXPECTED_TYPE,
|
||||
"query object's 'displayURL' property",
|
||||
"neither undefined nor a string");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (displayURL.isString()) {
|
||||
displayURLString = displayURL.toString()->ensureLinear(cx);
|
||||
if (!displayURLString)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2719,6 +2738,12 @@ class Debugger::ScriptQuery {
|
||||
* it. */
|
||||
RootedLinearString displayURLString;
|
||||
|
||||
/*
|
||||
* If this is a source object, matching scripts will have sources
|
||||
* equal to this instance.
|
||||
*/
|
||||
RootedScriptSource source;
|
||||
|
||||
/* True if the query contained a 'line' property. */
|
||||
bool hasLine;
|
||||
|
||||
@ -2841,6 +2866,8 @@ class Debugger::ScriptQuery {
|
||||
if (CompareChars(s, js_strlen(s), displayURLString) != 0)
|
||||
return;
|
||||
}
|
||||
if (source && source != script->sourceObject())
|
||||
return;
|
||||
|
||||
if (innermost) {
|
||||
/*
|
||||
|
13
layout/generic/crashtests/1058954-1.html
Normal file
13
layout/generic/crashtests/1058954-1.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
|
||||
<div style="display: -moz-grid-line;">
|
||||
<div style="position: relative; direction: rtl;">
|
||||
<div style="position: absolute;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -546,4 +546,5 @@ load outline-on-frameset.xhtml
|
||||
pref(font.size.inflation.minTwips,200) load 1032450.html
|
||||
load 1037903.html
|
||||
load 1039454-1.html
|
||||
load 1058954-1.html
|
||||
load 1042489.html
|
||||
|
@ -608,7 +608,8 @@ FloatMarginWidth(const nsHTMLReflowState& aCBReflowState,
|
||||
aCBReflowState.ComputedSize(fosWM),
|
||||
aFloatAvailableWidth,
|
||||
aFloatOffsetState.ComputedLogicalMargin().Size(fosWM),
|
||||
aFloatOffsetState.ComputedLogicalBorderPadding().Size(fosWM),
|
||||
aFloatOffsetState.ComputedLogicalBorderPadding().Size(fosWM) -
|
||||
aFloatOffsetState.ComputedLogicalPadding().Size(fosWM),
|
||||
aFloatOffsetState.ComputedLogicalPadding().Size(fosWM),
|
||||
true).Width(fosWM) +
|
||||
aFloatOffsetState.ComputedPhysicalMargin().LeftRight() +
|
||||
|
@ -8146,7 +8146,7 @@ nsFrame::DoLayout(nsBoxLayoutState& aState)
|
||||
const WritingMode outerWM = aState.OuterReflowState() ?
|
||||
aState.OuterReflowState()->GetWritingMode() : ourWM;
|
||||
nsHTMLReflowMetrics desiredSize(outerWM);
|
||||
LogicalSize ourSize = GetLogicalSize().ConvertTo(outerWM, ourWM);
|
||||
LogicalSize ourSize = GetLogicalSize(outerWM);
|
||||
|
||||
if (rendContext) {
|
||||
|
||||
@ -8186,7 +8186,7 @@ nsFrame::DoLayout(nsBoxLayoutState& aState)
|
||||
}
|
||||
|
||||
// Should we do this if IsCollapsed() is true?
|
||||
LogicalSize size(GetLogicalSize().ConvertTo(outerWM, ourWM));
|
||||
LogicalSize size(GetLogicalSize(outerWM));
|
||||
desiredSize.ISize(outerWM) = size.ISize(outerWM);
|
||||
desiredSize.BSize(outerWM) = size.BSize(outerWM);
|
||||
desiredSize.UnionOverflowAreasWithDesiredBounds();
|
||||
@ -8195,7 +8195,7 @@ nsFrame::DoLayout(nsBoxLayoutState& aState)
|
||||
// Set up a |reflowState| to pass into ReflowAbsoluteFrames
|
||||
nsHTMLReflowState reflowState(aState.PresContext(), this,
|
||||
aState.GetRenderingContext(),
|
||||
LogicalSize(ourWM, size.ISize(ourWM),
|
||||
LogicalSize(ourWM, ISize(),
|
||||
NS_UNCONSTRAINEDSIZE),
|
||||
nsHTMLReflowState::DUMMY_PARENT_REFLOW_STATE);
|
||||
|
||||
|
29
layout/reftests/bugs/1059167-1-ref.html
Normal file
29
layout/reftests/bugs/1059167-1-ref.html
Normal file
@ -0,0 +1,29 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<title>bug 1059167</title>
|
||||
<style type="text/css">
|
||||
body {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.item {
|
||||
width: 100px;
|
||||
margin-left: 80px;
|
||||
padding: 1rem;
|
||||
background: red;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
p {
|
||||
background: blue;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="item"><p>Content</p></div>
|
||||
</body>
|
||||
</html>
|
30
layout/reftests/bugs/1059167-1.html
Normal file
30
layout/reftests/bugs/1059167-1.html
Normal file
@ -0,0 +1,30 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<title>bug 1059167</title>
|
||||
<style type="text/css">
|
||||
body {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.item {
|
||||
width: 100px;
|
||||
margin-right: 20px;
|
||||
padding: 1rem;
|
||||
background: red;
|
||||
box-sizing: border-box;
|
||||
float:right;
|
||||
}
|
||||
|
||||
p {
|
||||
background: blue;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="item"><p>Content</p></div>
|
||||
</body>
|
||||
</html>
|
@ -1824,3 +1824,4 @@ pref(browser.display.use_document_fonts,0) == 1022481-1.html 1022481-1-ref.html
|
||||
== 1050788-1.html about:blank
|
||||
== 1053035-1-flex.html 1053035-1-ref.html
|
||||
test-pref(layout.css.grid.enabled,true) == 1053035-1-grid.html 1053035-1-ref.html
|
||||
== 1059167-1.html 1059167-1-ref.html
|
||||
|
@ -706,18 +706,17 @@ opensl_stream_get_position(cubeb_stream * stm, uint64_t * position)
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
int64_t compensated_position = samplerate * (msec - mixer_latency) / 1000;
|
||||
pthread_mutex_lock(&stm->mutex);
|
||||
int64_t maximum_position = stm->written * (int64_t)stm->inputrate / stm->outputrate;
|
||||
pthread_mutex_unlock(&stm->mutex);
|
||||
assert(maximum_position >= 0);
|
||||
|
||||
if (compensated_position < 0) {
|
||||
*position = 0;
|
||||
} else if(compensated_position > maximum_position) {
|
||||
*position = maximum_position;
|
||||
if (msec > mixer_latency) {
|
||||
int64_t unadjusted_position = samplerate * (msec - mixer_latency) / 1000;
|
||||
*position = unadjusted_position < maximum_position ?
|
||||
unadjusted_position : maximum_position;
|
||||
} else {
|
||||
*position = compensated_position;
|
||||
*position = 0;
|
||||
}
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
0
python/mozbuild/mozbuild/codecoverage/__init__.py
Normal file
0
python/mozbuild/mozbuild/codecoverage/__init__.py
Normal file
43
python/mozbuild/mozbuild/codecoverage/packager.py
Normal file
43
python/mozbuild/mozbuild/codecoverage/packager.py
Normal file
@ -0,0 +1,43 @@
|
||||
# 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/.
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
from mozpack.files import FileFinder
|
||||
from mozpack.copier import Jarrer
|
||||
|
||||
def package_gcno_tree(root, output_file):
|
||||
# XXX JarWriter doesn't support unicode strings, see bug 1056859
|
||||
if isinstance(root, unicode):
|
||||
root = root.encode('utf-8')
|
||||
|
||||
finder = FileFinder(root)
|
||||
jarrer = Jarrer(optimize=False)
|
||||
for p, f in finder.find("**/*.gcno"):
|
||||
jarrer.add(p, f)
|
||||
jarrer.copy(output_file)
|
||||
|
||||
|
||||
def cli(args=sys.argv[1:]):
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-o', '--output-file',
|
||||
dest='output_file',
|
||||
help='Path to save packaged data to.')
|
||||
parser.add_argument('--root',
|
||||
dest='root',
|
||||
default=None,
|
||||
help='Root directory to search from.')
|
||||
args = parser.parse_args(args)
|
||||
|
||||
if not args.root:
|
||||
from buildconfig import topobjdir
|
||||
args.root = topobjdir
|
||||
|
||||
return package_gcno_tree(args.root, args.output_file)
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(cli())
|
@ -300,12 +300,7 @@ let TPS = {
|
||||
Logger.logInfo("tab for " + taburi + " finished loading");
|
||||
if (that._tabsFinished == that._tabsAdded) {
|
||||
Logger.logInfo("all tabs loaded, continuing...");
|
||||
|
||||
// Wait a second before continuing to be sure tabs can be synced,
|
||||
// otherwise we can get 'error locating tab'
|
||||
Utils.namedTimer(function () {
|
||||
that.FinishAsyncOperation();
|
||||
}, 1000, this, "postTabsOpening");
|
||||
}
|
||||
});
|
||||
break;
|
||||
@ -895,7 +890,13 @@ let TPS = {
|
||||
|
||||
this._triggeredSync = true;
|
||||
this.StartAsyncOperation();
|
||||
|
||||
// Bug 682446
|
||||
// We wait a little before we trigger the Sync call to be sure elements are
|
||||
// ready to be synced
|
||||
Utils.namedTimer(function () {
|
||||
Weave.Service.sync();
|
||||
}, 2500, this, "beforeSyncDelay");
|
||||
},
|
||||
|
||||
WipeServer: function TPS__WipeServer() {
|
||||
|
@ -93,9 +93,6 @@ class GeckoInstance(object):
|
||||
'logfile': self.gecko_log})
|
||||
self.runner.start()
|
||||
|
||||
def check_for_crashes(self):
|
||||
return self.runner.check_for_crashes()
|
||||
|
||||
def close(self):
|
||||
if self.runner:
|
||||
self.runner.stop()
|
||||
|
@ -725,12 +725,13 @@ class Marionette(object):
|
||||
name = None
|
||||
crashed = False
|
||||
if self.runner:
|
||||
if self.runner.check_for_crashes():
|
||||
if self.runner.check_for_crashes(test_name=self.test_name):
|
||||
returncode = self.emulator.proc.returncode
|
||||
name = 'emulator'
|
||||
crashed = True
|
||||
elif self.instance:
|
||||
if self.instance.check_for_crashes():
|
||||
if self.instance.runner.check_for_crashes(
|
||||
test_name=self.test_name):
|
||||
crashed = True
|
||||
if returncode is not None:
|
||||
print ('PROCESS-CRASH | %s | abnormal termination with exit code %d' %
|
||||
|
@ -282,7 +282,6 @@ class BaseMarionetteOptions(OptionParser):
|
||||
self.add_option('--type',
|
||||
dest='type',
|
||||
action='store',
|
||||
default='browser+b2g',
|
||||
help="the type of test to run, can be a combination of values defined in the manifest file; "
|
||||
"individual values are combined with '+' or '-' characters. for example: 'browser+b2g' "
|
||||
"means the set of tests which are compatible with both browser and b2g; 'b2g-qemu' means "
|
||||
@ -957,4 +956,9 @@ class BaseMarionetteTestRunner(object):
|
||||
_extract_xml_from_skipped_manifest_test(test)
|
||||
|
||||
doc.appendChild(testsuite)
|
||||
|
||||
# change default encoding to avoid encoding problem for page source
|
||||
reload(sys)
|
||||
sys.setdefaultencoding('utf-8')
|
||||
|
||||
return doc.toprettyxml(encoding='utf-8')
|
||||
|
@ -158,7 +158,7 @@ def setup_logging(suite, args, defaults=None):
|
||||
formatters[formatter] = []
|
||||
for value in values:
|
||||
found = True
|
||||
if isinstance(value, str):
|
||||
if isinstance(value, basestring):
|
||||
value = log_file(value)
|
||||
if value == sys.stdout:
|
||||
found_stdout_logger = True
|
||||
|
@ -1,10 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import argparse
|
||||
import json
|
||||
import optparse
|
||||
import os
|
||||
import unittest
|
||||
import StringIO
|
||||
import json
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import mozfile
|
||||
|
||||
from mozlog.structured import (
|
||||
@ -501,6 +503,15 @@ class TestCommandline(unittest.TestCase):
|
||||
self.assertEqual(len(logger.handlers), 1)
|
||||
self.assertIsInstance(logger.handlers[0], handlers.StreamHandler)
|
||||
|
||||
def test_setup_logging_optparse_unicode(self):
|
||||
parser = optparse.OptionParser()
|
||||
commandline.add_logging_group(parser)
|
||||
args, _ = parser.parse_args([u"--log-raw=-"])
|
||||
logger = commandline.setup_logging("test_optparse_unicode", args, {})
|
||||
self.assertEqual(len(logger.handlers), 1)
|
||||
self.assertEqual(logger.handlers[0].stream, sys.stdout)
|
||||
self.assertIsInstance(logger.handlers[0], handlers.StreamHandler)
|
||||
|
||||
def test_logging_defaultlevel(self):
|
||||
parser = argparse.ArgumentParser()
|
||||
commandline.add_logging_group(parser)
|
||||
|
@ -125,10 +125,11 @@ class DeviceRunner(BaseRunner):
|
||||
def on_finish(self):
|
||||
self.check_for_crashes()
|
||||
|
||||
def check_for_crashes(self):
|
||||
def check_for_crashes(self, test_name=None):
|
||||
test_name = test_name or self.last_test
|
||||
dump_dir = self.device.pull_minidumps()
|
||||
crashed = BaseRunner.check_for_crashes(self, dump_directory=dump_dir,
|
||||
test_name=self.last_test)
|
||||
crashed = BaseRunner.check_for_crashes(
|
||||
self, dump_directory=dump_dir, test_name=test_name)
|
||||
mozfile.remove(dump_dir)
|
||||
return crashed
|
||||
|
||||
|
@ -1073,7 +1073,7 @@ function do_get_profile() {
|
||||
prop == "ProfLDS" || prop == "TmpD") {
|
||||
return file.clone();
|
||||
}
|
||||
throw Components.results.NS_ERROR_FAILURE;
|
||||
return null;
|
||||
},
|
||||
QueryInterface: function(iid) {
|
||||
if (iid.equals(Components.interfaces.nsIDirectoryServiceProvider) ||
|
||||
|
@ -367,6 +367,21 @@ this.CrashManager.prototype = Object.freeze({
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Record the remote ID for a crash.
|
||||
*
|
||||
* @param crashID (string) Crash ID. Likely a UUID.
|
||||
* @param remoteID (Date) Server/Breakpad ID.
|
||||
*
|
||||
* @return boolean True if the remote ID was recorded.
|
||||
*/
|
||||
setRemoteCrashID: Task.async(function* (crashID, remoteID) {
|
||||
let store = yield this._getStore();
|
||||
if (store.setRemoteCrashID(crashID, remoteID)) {
|
||||
yield store.save();
|
||||
}
|
||||
}),
|
||||
|
||||
/**
|
||||
* Record the occurrence of a submission attempt for a crash.
|
||||
*
|
||||
@ -1005,6 +1020,7 @@ CrashStore.prototype = Object.freeze({
|
||||
if (!this._data.crashes.has(id)) {
|
||||
this._data.crashes.set(id, {
|
||||
id: id,
|
||||
remoteID: null,
|
||||
type: type,
|
||||
crashDate: date,
|
||||
submissions: new Map(),
|
||||
@ -1032,6 +1048,19 @@ CrashStore.prototype = Object.freeze({
|
||||
return !!this._ensureCrashRecord(processType, crashType, id, date);
|
||||
},
|
||||
|
||||
/**
|
||||
* @return boolean True if the remote ID was recorded and false if not.
|
||||
*/
|
||||
setRemoteCrashID: function (crashID, remoteID) {
|
||||
let crash = this._data.crashes.get(crashID);
|
||||
if (!crash || !remoteID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
crash.remoteID = remoteID;
|
||||
return true;
|
||||
},
|
||||
|
||||
getCrashesOfType: function (processType, crashType) {
|
||||
let crashes = [];
|
||||
for (let crash of this.crashes) {
|
||||
@ -1126,6 +1155,10 @@ CrashRecord.prototype = Object.freeze({
|
||||
return this._o.id;
|
||||
},
|
||||
|
||||
get remoteID() {
|
||||
return this._o.remoteID;
|
||||
},
|
||||
|
||||
get crashDate() {
|
||||
return this._o.crashDate;
|
||||
},
|
||||
|
@ -353,3 +353,12 @@ add_task(function* test_addSubmissionAttemptAndResult() {
|
||||
Assert.equal(submission.responseDate.getTime(), DUMMY_DATE_2.getTime());
|
||||
Assert.equal(submission.result, m.SUBMISSION_RESULT_OK);
|
||||
});
|
||||
|
||||
add_task(function* test_setRemoteCrashID() {
|
||||
let m = yield getManager();
|
||||
|
||||
yield m.addCrash(m.PROCESS_TYPE_MAIN, m.CRASH_TYPE_CRASH,
|
||||
"main-crash", DUMMY_DATE);
|
||||
yield m.setRemoteCrashID("main-crash", "bp-1");
|
||||
Assert.equal((yield m.getCrashes())[0].remoteID, "bp-1");
|
||||
});
|
||||
|
@ -90,6 +90,7 @@ add_task(function test_save_load() {
|
||||
Assert.ok(s.addCrash(PROCESS_TYPE_MAIN, CRASH_TYPE_CRASH, "id2", d2));
|
||||
Assert.ok(s.addSubmissionAttempt("id1", "sub1", d1));
|
||||
Assert.ok(s.addSubmissionResult("id1", "sub1", d2, SUBMISSION_RESULT_OK));
|
||||
Assert.ok(s.setRemoteCrashID("id1", "bp-1"));
|
||||
|
||||
yield s.save();
|
||||
|
||||
@ -100,6 +101,7 @@ add_task(function test_save_load() {
|
||||
Assert.equal(crashes.length, 2);
|
||||
let c = s.getCrash("id1");
|
||||
Assert.equal(c.crashDate.getTime(), d1.getTime());
|
||||
Assert.equal(c.remoteID, "bp-1");
|
||||
|
||||
Assert.ok(!!c.submissions);
|
||||
let submission = c.submissions.get("sub1");
|
||||
@ -554,3 +556,14 @@ add_task(function* test_convertSubmissionsStoredAsCrashes() {
|
||||
Assert.equal(submission.requestDate.getTime(), DUMMY_DATE_2.getTime());
|
||||
Assert.equal(submission.responseDate.getTime(), DUMMY_DATE_2.getTime());
|
||||
});
|
||||
|
||||
add_task(function* test_setRemoteCrashID() {
|
||||
let s = yield getStore();
|
||||
|
||||
Assert.ok(s.addCrash(PROCESS_TYPE_MAIN, CRASH_TYPE_CRASH, "crash1",
|
||||
new Date()));
|
||||
Assert.equal(s.crashes[0].remoteID, null);
|
||||
Assert.ok(s.setRemoteCrashID("crash1", "bp-1"));
|
||||
Assert.equal(s.crashes[0].remoteID, "bp-1");
|
||||
});
|
||||
|
||||
|
@ -15,6 +15,8 @@ let httpServer = new HttpServer();
|
||||
let getEngine, postEngine, unresolvableEngine;
|
||||
|
||||
function run_test() {
|
||||
Services.prefs.setBoolPref("browser.search.suggest.enabled", true);
|
||||
|
||||
removeMetadata();
|
||||
updateAppInfo();
|
||||
|
||||
@ -25,6 +27,7 @@ function run_test() {
|
||||
// Remove added form history entries
|
||||
yield updateSearchHistory("remove", null);
|
||||
FormHistory.shutdown();
|
||||
Services.prefs.clearUserPref("browser.search.suggest.enabled");
|
||||
}));
|
||||
|
||||
run_next_test();
|
||||
@ -288,7 +291,7 @@ add_task(function* local_result_returned_remote_result_disabled() {
|
||||
do_check_eq(result.local.length, 1);
|
||||
do_check_eq(result.local[0], "letter A");
|
||||
do_check_eq(result.remote.length, 0);
|
||||
Services.prefs.clearUserPref("browser.search.suggest.enabled");
|
||||
Services.prefs.setBoolPref("browser.search.suggest.enabled", true);
|
||||
});
|
||||
|
||||
add_task(function* local_result_returned_remote_result_disabled_after_creation_of_controller() {
|
||||
@ -301,6 +304,7 @@ add_task(function* local_result_returned_remote_result_disabled_after_creation_o
|
||||
do_check_eq(result.local.length, 1);
|
||||
do_check_eq(result.local[0], "letter A");
|
||||
do_check_eq(result.remote.length, 0);
|
||||
Services.prefs.setBoolPref("browser.search.suggest.enabled", true);
|
||||
});
|
||||
|
||||
add_task(function* one_of_each_disabled_before_creation_enabled_after_creation_of_controller() {
|
||||
@ -317,8 +321,8 @@ add_task(function* one_of_each_disabled_before_creation_enabled_after_creation_o
|
||||
do_check_eq(result.remote[0], "letter B");
|
||||
});
|
||||
|
||||
add_task(function* clear_suggestions_pref() {
|
||||
Services.prefs.clearUserPref("browser.search.suggest.enabled");
|
||||
add_task(function* reset_suggestions_pref() {
|
||||
Services.prefs.setBoolPref("browser.search.suggest.enabled", true);
|
||||
});
|
||||
|
||||
add_task(function* one_local_zero_remote() {
|
||||
|
@ -18,12 +18,12 @@ const gViewSourceCSS = 'resource://gre-resources/viewsource.css';
|
||||
const NS_XHTML = 'http://www.w3.org/1999/xhtml';
|
||||
|
||||
// These are markers used to delimit the selection during processing. They
|
||||
// are removed from the final rendering, but we pick space-like characters for
|
||||
// safety (and futhermore, these are known to be mapped to a 0-length string
|
||||
// in transliterate.properties). It is okay to set start=end, we use findNext()
|
||||
// U+200B ZERO WIDTH SPACE
|
||||
const MARK_SELECTION_START = '\u200B\u200B\u200B\u200B\u200B';
|
||||
const MARK_SELECTION_END = '\u200B\u200B\u200B\u200B\u200B';
|
||||
// are removed from the final rendering.
|
||||
// We use noncharacter Unicode codepoints to minimize the risk of clashing
|
||||
// with anything that might legitimately be present in the document.
|
||||
// U+FDD0..FDEF <noncharacters>
|
||||
const MARK_SELECTION_START = '\uFDD0';
|
||||
const MARK_SELECTION_END = '\uFDEF';
|
||||
|
||||
function onLoadViewPartialSource()
|
||||
{
|
||||
|
@ -282,7 +282,7 @@ Submitter.prototype = {
|
||||
|
||||
let submissionID = Cc["@mozilla.org/uuid-generator;1"]
|
||||
.getService(Ci.nsIUUIDGenerator)
|
||||
.generateUUID().toString();
|
||||
.generateUUID().toString().slice(1, -1);
|
||||
let manager = Services.crashmanager;
|
||||
|
||||
let self = this;
|
||||
@ -297,6 +297,9 @@ Submitter.prototype = {
|
||||
manager.SUBMISSION_RESULT_FAILED;
|
||||
manager.addSubmissionResult(self.id, submissionID, new Date(),
|
||||
result);
|
||||
if (submitted) {
|
||||
manager.setRemoteCrashID(self.id, ret.CrashID);
|
||||
}
|
||||
}
|
||||
|
||||
if (submitted) {
|
||||
|
@ -15,12 +15,14 @@ XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["LayoutHelpers"];
|
||||
|
||||
this.LayoutHelpers = LayoutHelpers = function(aTopLevelWindow) {
|
||||
let LayoutHelpers = function(aTopLevelWindow) {
|
||||
this._topDocShell = aTopLevelWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell);
|
||||
};
|
||||
|
||||
this.LayoutHelpers = LayoutHelpers;
|
||||
|
||||
LayoutHelpers.prototype = {
|
||||
|
||||
/**
|
||||
|
@ -139,14 +139,14 @@ XPCOMUtils.defineLazyGetter(this, "Barriers", () => {
|
||||
// We are waiting for the connections to close. The interesting
|
||||
// status is therefore the list of connections still pending.
|
||||
return { description: "Waiting for connections to close",
|
||||
status: Barriers.connections.status };
|
||||
state: Barriers.connections.state };
|
||||
}
|
||||
|
||||
// We are still in the first stage: waiting for the barrier
|
||||
// to be lifted. The interesting status is therefore that of
|
||||
// the barrier.
|
||||
return { description: "Waiting for the barrier to be lifted",
|
||||
status: Barriers.shutdown.status };
|
||||
state: Barriers.shutdown.state };
|
||||
});
|
||||
|
||||
return Barriers;
|
||||
|
@ -125,6 +125,9 @@ endif # MOZ_PKG_PRETTYNAMES
|
||||
SYMBOL_FULL_ARCHIVE_BASENAME = $(PKG_BASENAME).crashreporter-symbols-full
|
||||
SYMBOL_ARCHIVE_BASENAME = $(PKG_BASENAME).crashreporter-symbols
|
||||
|
||||
# Code coverage package naming
|
||||
CODE_COVERAGE_ARCHIVE_BASENAME = $(PKG_BASENAME).code-coverage-gcno
|
||||
|
||||
# Test package naming
|
||||
TEST_PACKAGE = $(PKG_BASENAME).tests.zip
|
||||
|
||||
|
@ -742,6 +742,13 @@ ifdef MOZ_PACKAGE_JSSHELL
|
||||
$(MAKE_JSSHELL)
|
||||
endif # MOZ_PACKAGE_JSSHELL
|
||||
endif # LIBXUL_SDK
|
||||
ifdef MOZ_CODE_COVERAGE
|
||||
# Package code coverage gcno tree
|
||||
@echo 'Packaging code coverage data...'
|
||||
$(RM) $(CODE_COVERAGE_ARCHIVE_BASENAME).zip
|
||||
$(PYTHON) -mmozbuild.codecoverage.packager \
|
||||
--output-file='$(DIST)/$(PKG_PATH)$(CODE_COVERAGE_ARCHIVE_BASENAME).zip'
|
||||
endif
|
||||
|
||||
prepare-package: stage-package
|
||||
|
||||
@ -892,6 +899,11 @@ UPLOAD_FILES += \
|
||||
$(call QUOTED_WILDCARD,$(DIST)/$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip)
|
||||
endif
|
||||
|
||||
ifdef MOZ_CODE_COVERAGE
|
||||
UPLOAD_FILES += \
|
||||
$(call QUOTED_WILDCARD,$(DIST)/$(PKG_PATH)$(CODE_COVERAGE_ARCHIVE_BASENAME).zip)
|
||||
endif
|
||||
|
||||
SIGN_CHECKSUM_CMD=
|
||||
ifdef MOZ_SIGN_CMD
|
||||
# If we're signing with gpg, we'll have a bunch of extra detached signatures to
|
||||
|
@ -697,6 +697,8 @@ PLDHashTable::Enumerate(PLDHashEnumerator aEtor, void* aArg)
|
||||
{
|
||||
INCREMENT_RECURSION_LEVEL(this);
|
||||
|
||||
// Please keep this method in sync with the PLDHashTable::Iterator constructor
|
||||
// and ::NextEntry methods below in this file.
|
||||
char* entryAddr = mEntryStore;
|
||||
uint32_t capacity = Capacity();
|
||||
uint32_t tableSize = capacity * mEntrySize;
|
||||
@ -835,6 +837,97 @@ PL_DHashTableSizeOfIncludingThis(
|
||||
aMallocSizeOf, aArg);
|
||||
}
|
||||
|
||||
PLDHashTable::Iterator::Iterator(const PLDHashTable* aTable)
|
||||
: mTable(aTable),
|
||||
mEntryAddr(mTable->mEntryStore),
|
||||
mEntryOffset(0)
|
||||
{
|
||||
// Make sure that modifications can't simultaneously happen while the iterator
|
||||
// is active.
|
||||
INCREMENT_RECURSION_LEVEL(mTable);
|
||||
|
||||
// The following code is taken from, and should be kept in sync with, the
|
||||
// PLDHashTable::Enumerate method above. The variables i and entryAddr (which
|
||||
// vary over the course of the for loop) are converted into mEntryOffset and
|
||||
// mEntryAddr, respectively.
|
||||
uint32_t capacity = mTable->Capacity();
|
||||
uint32_t tableSize = capacity * mTable->EntrySize();
|
||||
char* entryLimit = mEntryAddr + tableSize;
|
||||
|
||||
if (ChaosMode::isActive()) {
|
||||
// Start iterating at a random point in the hashtable. It would be
|
||||
// even more chaotic to iterate in fully random order, but that's a lot
|
||||
// more work.
|
||||
mEntryAddr += ChaosMode::randomUint32LessThan(capacity) * mTable->mEntrySize;
|
||||
if (mEntryAddr >= entryLimit) {
|
||||
mEntryAddr -= tableSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PLDHashTable::Iterator::Iterator(const Iterator& aIterator)
|
||||
: mTable(aIterator.mTable),
|
||||
mEntryAddr(aIterator.mEntryAddr),
|
||||
mEntryOffset(aIterator.mEntryOffset)
|
||||
{
|
||||
// We need the copy constructor only so that we can keep the recursion level
|
||||
// consistent.
|
||||
INCREMENT_RECURSION_LEVEL(mTable);
|
||||
}
|
||||
|
||||
PLDHashTable::Iterator::~Iterator()
|
||||
{
|
||||
DECREMENT_RECURSION_LEVEL(mTable);
|
||||
}
|
||||
|
||||
bool PLDHashTable::Iterator::HasMoreEntries() const
|
||||
{
|
||||
// Check the number of live entries seen, not the total number of entries
|
||||
// seen. To see why, consider what happens if the last entry is not live: we
|
||||
// would have to iterate after returning an entry to see if more live entries
|
||||
// exist.
|
||||
return mEntryOffset < mTable->EntryCount();
|
||||
}
|
||||
|
||||
PLDHashEntryHdr* PLDHashTable::Iterator::NextEntry()
|
||||
{
|
||||
MOZ_ASSERT(HasMoreEntries());
|
||||
|
||||
// The following code is taken from, and should be kept in sync with, the
|
||||
// PLDHashTable::Enumerate method above. The variables i and entryAddr (which
|
||||
// vary over the course of the for loop) are converted into mEntryOffset and
|
||||
// mEntryAddr, respectively.
|
||||
uint32_t capacity = mTable->Capacity();
|
||||
uint32_t tableSize = capacity * mTable->mEntrySize;
|
||||
char* entryLimit = mEntryAddr + tableSize;
|
||||
|
||||
// Strictly speaking, we don't need to iterate over the full capacity each
|
||||
// time. However, it is simpler to do so rather than unnecessarily track the
|
||||
// current number of entries checked as opposed to only live entries. If debug
|
||||
// checks pass, then this method will only iterate through the full capacity
|
||||
// once. If they fail, then this loop may end up returning the early entries
|
||||
// more than once.
|
||||
for (uint32_t e = 0; e < capacity; ++e) {
|
||||
PLDHashEntryHdr* entry = (PLDHashEntryHdr*)mEntryAddr;
|
||||
|
||||
// Increment the count before returning so we don't keep returning the same
|
||||
// address. This may wrap around if ChaosMode is enabled.
|
||||
mEntryAddr += mTable->mEntrySize;
|
||||
if (mEntryAddr >= entryLimit) {
|
||||
mEntryAddr -= tableSize;
|
||||
}
|
||||
if (ENTRY_IS_LIVE(entry)) {
|
||||
++mEntryOffset;
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
// If the debug checks pass, then the above loop should always find a live
|
||||
// entry. If those checks are disabled, then it may be possible to reach this
|
||||
// if the table is empty and this method is called.
|
||||
MOZ_CRASH("Flagrant misuse of hashtable iterators not caught by checks.");
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
MOZ_ALWAYS_INLINE void
|
||||
PLDHashTable::MarkImmutable()
|
||||
|
@ -194,7 +194,7 @@ private:
|
||||
* non-DEBUG components. (Actually, even if it were removed,
|
||||
* sizeof(PLDHashTable) wouldn't change, due to struct padding.)
|
||||
*/
|
||||
uint16_t mRecursionLevel;/* used to detect unsafe re-entry */
|
||||
mutable uint16_t mRecursionLevel;/* used to detect unsafe re-entry */
|
||||
uint32_t mEntrySize; /* number of bytes in an entry */
|
||||
uint32_t mEntryCount; /* number of entries in table */
|
||||
uint32_t mRemovedCount; /* removed entry sentinels in table */
|
||||
@ -272,6 +272,27 @@ public:
|
||||
void DumpMeter(PLDHashEnumerator aDump, FILE* aFp);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This is an iterator that works over the elements of PLDHashtable. It is not
|
||||
* safe to modify the hashtable while it is being iterated over; on debug
|
||||
* builds, attempting to do so will result in an assertion failure.
|
||||
*/
|
||||
class Iterator {
|
||||
public:
|
||||
Iterator(const PLDHashTable* aTable);
|
||||
Iterator(const Iterator& aIterator);
|
||||
~Iterator();
|
||||
bool HasMoreEntries() const;
|
||||
PLDHashEntryHdr* NextEntry();
|
||||
|
||||
private:
|
||||
const PLDHashTable* mTable; /* Main table pointer */
|
||||
char* mEntryAddr; /* Pointer to the next entry to check */
|
||||
uint32_t mEntryOffset; /* The number of the elements returned */
|
||||
};
|
||||
|
||||
Iterator Iterate() const { return Iterator(this); }
|
||||
|
||||
private:
|
||||
PLDHashEntryHdr* PL_DHASH_FASTCALL
|
||||
SearchTable(const void* aKey, PLDHashNumber aKeyHash, PLDHashOperator aOp);
|
||||
|
Loading…
Reference in New Issue
Block a user