Merge last PGO green inbound changeset to m-c

This commit is contained in:
Ryan VanderMeulen 2012-05-07 20:45:43 -04:00
commit 11389729fe
74 changed files with 1385 additions and 43901 deletions

View File

@ -551,8 +551,6 @@ nsHTMLComboboxAccessible::Shutdown()
}
}
/**
*/
PRUint64
nsHTMLComboboxAccessible::NativeState()
{
@ -561,8 +559,7 @@ nsHTMLComboboxAccessible::NativeState()
// Get focus status from base class
PRUint64 state = nsAccessible::NativeState();
nsIFrame *frame = GetBoundsFrame();
nsIComboboxControlFrame *comboFrame = do_QueryFrame(frame);
nsIComboboxControlFrame* comboFrame = do_QueryFrame(GetFrame());
if (comboFrame && comboFrame->IsDroppedDown())
state |= states::EXPANDED;
else
@ -750,8 +747,7 @@ nsHTMLComboboxListAccessible::NativeState()
// Get focus status from base class
PRUint64 state = nsAccessible::NativeState();
nsIFrame *boundsFrame = GetBoundsFrame();
nsIComboboxControlFrame* comboFrame = do_QueryFrame(boundsFrame);
nsIComboboxControlFrame* comboFrame = do_QueryFrame(mParent->GetFrame());
if (comboFrame && comboFrame->IsDroppedDown())
state |= states::FLOATING;
else

View File

@ -53,9 +53,8 @@ var AccessFu = {
},
/**
* Start the special AccessFu mode, this primarily means controlling the virtual
* cursor with arrow keys. Currently, on platforms other than Android this needs
* to be called explicitly.
* Start AccessFu mode, this primarily means controlling the virtual cursor
* with arrow keys.
*/
enable: function enable() {
dump('AccessFu enable');
@ -72,8 +71,6 @@ var AccessFu = {
this.chromeWin.addEventListener('resize', this, true);
this.chromeWin.addEventListener('scroll', this, true);
this.chromeWin.addEventListener('TabOpen', this, true);
this.chromeWin.addEventListener('TabSelect', this, true);
this.chromeWin.addEventListener('TabClosed', this, true);
},
/**
@ -82,18 +79,16 @@ var AccessFu = {
disable: function disable() {
dump('AccessFu disable');
this.presenters.forEach(function(p) {p.detach();});
this.presenters.forEach(function(p) { p.detach(); });
this.presenters = [];
VirtualCursorController.detach();
Services.obs.addObserver(this, 'accessible-event', false);
this.chromeWin.removeEventListener('DOMActivate', this);
this.chromeWin.removeEventListener('resize', this);
this.chromeWin.removeEventListener('scroll', this);
this.chromeWin.removeEventListener('TabOpen', this);
this.chromeWin.removeEventListener('TabSelect', this);
this.chromeWin.removeEventListener('TabClose', this);
Services.obs.removeObserver(this, 'accessible-event');
this.chromeWin.removeEventListener('DOMActivate', this, true);
this.chromeWin.removeEventListener('resize', this, true);
this.chromeWin.removeEventListener('scroll', this, true);
this.chromeWin.removeEventListener('TabOpen', this, true);
},
amINeeded: function(aPref) {
@ -125,14 +120,17 @@ var AccessFu = {
handleEvent: function handleEvent(aEvent) {
switch (aEvent.type) {
case 'TabSelect':
{
this.getDocAccessible(
function(docAcc) {
this.presenters.forEach(function(p) {p.tabSelected(docAcc);});
});
break;
}
case 'TabOpen':
{
let browser = aEvent.target.linkedBrowser || aEvent.target;
// Store the new browser node. We will need to check later when a new
// content document is attached if it has been attached to this new tab.
// If it has, than we will need to send a 'loading' message along with
// the usual 'newdoc' to presenters.
this._pendingDocuments[browser] = true;
this.presenters.forEach(function(p) { p.tabStateChanged(null, 'newtab'); });
break;
}
case 'DOMActivate':
{
let activatedAcc = getAccessible(aEvent.originalTarget);
@ -153,25 +151,12 @@ var AccessFu = {
case 'scroll':
case 'resize':
{
this.presenters.forEach(function(p) {p.viewportChanged();});
this.presenters.forEach(function(p) { p.viewportChanged(); });
break;
}
}
},
getDocAccessible: function getDocAccessible(aCallback) {
let browserApp = (Services.appinfo.OS == 'Android') ?
this.chromeWin.BrowserApp : this.chromeWin.gBrowser;
let docAcc = getAccessible(browserApp.selectedBrowser.contentDocument);
if (!docAcc) {
// Wait for a reorder event fired by the parent of the new doc.
this._pendingDocuments[browserApp.selectedBrowser] = aCallback;
} else {
aCallback.apply(this, [docAcc]);
}
},
observe: function observe(aSubject, aTopic, aData) {
switch (aTopic) {
case 'nsPref:changed':
@ -223,16 +208,86 @@ var AccessFu = {
}
);
}
else if (event.state == Ci.nsIAccessibleStates.STATE_BUSY &&
!(event.isExtraState()) && event.isEnabled()) {
let role = event.accessible.role;
if ((role == Ci.nsIAccessibleRole.ROLE_DOCUMENT ||
role == Ci.nsIAccessibleRole.ROLE_APPLICATION)) {
// An existing document has changed to state "busy", this means
// something is loading. Send a 'loading' message to presenters.
this.presenters.forEach(
function(p) {
p.tabStateChanged(event.accessible, 'loading');
}
);
}
}
break;
}
case Ci.nsIAccessibleEvent.EVENT_REORDER:
{
let node = aEvent.accessible.DOMNode;
let callback = this._pendingDocuments[node];
if (callback && aEvent.accessible.childCount) {
// We have a callback associated with a document.
callback.apply(this, [aEvent.accessible.getChildAt(0)]);
delete this._pendingDocuments[node];
let acc = aEvent.accessible;
if (acc.childCount) {
let docAcc = acc.getChildAt(0);
if (this._pendingDocuments[aEvent.DOMNode]) {
// This is a document in a new tab. Check if it is
// in a BUSY state (i.e. loading), and inform presenters.
// We need to do this because a state change event will not be
// fired when an object is created with the BUSY state.
// If this is not a new tab, don't bother because we sent 'loading'
// when the previous doc changed its state to BUSY.
let state = {};
docAcc.getState(state, {});
if (state.value & Ci.nsIAccessibleStates.STATE_BUSY &&
this.isNotChromeDoc(docAcc))
this.presenters.forEach(
function(p) { p.tabStateChanged(docAcc, 'loading'); }
);
delete this._pendingDocuments[aEvent.DOMNode];
}
if (this.isBrowserDoc(docAcc))
// A new top-level content document has been attached
this.presenters.forEach(
function(p) { p.tabStateChanged(docAcc, 'newdoc'); }
);
}
break;
}
case Ci.nsIAccessibleEvent.EVENT_DOCUMENT_LOAD_COMPLETE:
{
if (this.isNotChromeDoc(aEvent.accessible)) {
this.presenters.forEach(
function(p) {
p.tabStateChanged(aEvent.accessible, 'loaded');
}
);
}
break;
}
case Ci.nsIAccessibleEvent.EVENT_DOCUMENT_LOAD_STOPPED:
{
this.presenters.forEach(
function(p) {
p.tabStateChanged(aEvent.accessible, 'loadstopped');
}
);
break;
}
case Ci.nsIAccessibleEvent.EVENT_DOCUMENT_RELOAD:
{
this.presenters.forEach(
function(p) {
p.tabStateChanged(aEvent.accessible, 'reload');
}
);
break;
}
case Ci.nsIAccessibleEvent.EVENT_FOCUS:
{
if (this.isBrowserDoc(aEvent.accessible)) {
// The document recieved focus, call tabSelected to present current tab.
this.presenters.forEach(
function(p) { p.tabSelected(aEvent.accessible); });
}
break;
}
@ -269,6 +324,38 @@ var AccessFu = {
}
},
/**
* Check if accessible is a top-level content document (i.e. a child of a XUL
* browser node).
* @param {nsIAccessible} aDocAcc the accessible to check.
* @return {boolean} true if this is a top-level content document.
*/
isBrowserDoc: function isBrowserDoc(aDocAcc) {
let parent = aDocAcc.parent;
if (!parent)
return false;
let domNode = parent.DOMNode;
if (!domNode)
return false;
const ns = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
return (domNode.localName == 'browser' && domNode.namespaceURI == ns);
},
/**
* Check if document is not a local "chrome" document, like about:home.
* @param {nsIDOMDocument} aDocument the document to check.
* @return {boolean} true if this is not a chrome document.
*/
isNotChromeDoc: function isNotChromeDoc(aDocument) {
let location = aDocument.DOMNode.location;
if (!location)
return false;
return location.protocol != "about:";
},
getNewContext: function getNewContext(aOldObject, aNewObject) {
let newLineage = [];
let oldLineage = [];

View File

@ -66,15 +66,21 @@ Presenter.prototype = {
selectionChanged: function selectionChanged(aObject) {},
/**
* The page state has changed, loading, stopped loading, etc. TODO.
* The tab, or the tab's document state has changed.
* @param {nsIAccessible} aDocObj the tab document accessible that has had its
* state changed, or null if the tab has no associated document yet.
* @param {string} aPageState the state name for the tab, valid states are:
* 'newtab', 'loading', 'newdoc', 'loaded', 'stopped', and 'reload'.
*/
pageStateChanged: function pageStateChanged() {},
tabStateChanged: function tabStateChanged(aDocObj, aPageState) {},
/**
* The tab has changed.
* @param {nsIAccessible} aObject the document contained in the tab.
* The current tab has changed.
* @param {nsIAccessible} aObject the document contained by the tab
* accessible, or null if it is a new tab with no attached
* document yet.
*/
tabSelected: function tabSelected(aObject) {},
tabSelected: function tabSelected(aDocObj) {},
/**
* The viewport has changed, either a scroll, pan, zoom, or
@ -147,9 +153,17 @@ VisualPresenter.prototype.pivotChanged = function(aObject, aNewContext) {
}
};
VisualPresenter.prototype.tabSelected = function(aObject) {
let vcDoc = aObject.QueryInterface(Ci.nsIAccessibleCursorable);
this.pivotChanged(vcDoc.virtualCursor.position);
VisualPresenter.prototype.tabSelected = function(aDocObj) {
let vcPos = aDocObj ?
aDocObj.QueryInterface(Ci.nsIAccessibleCursorable).virtualCursor.position :
null;
this.pivotChanged(vcPos);
};
VisualPresenter.prototype.tabStateChanged = function(aDocObj, aPageState) {
if (aPageState == "newdoc")
this.pivotChanged(null);
};
// Internals
@ -242,16 +256,40 @@ AndroidPresenter.prototype.actionInvoked = function(aObject, aActionName) {
});
};
AndroidPresenter.prototype.tabSelected = function(aObject) {
let vcDoc = aObject.QueryInterface(Ci.nsIAccessibleCursorable);
AndroidPresenter.prototype.tabSelected = function(aDocObj) {
// Send a pivot change message with the full context utterance for this doc.
let vcDoc = aDocObj.QueryInterface(Ci.nsIAccessibleCursorable);
let context = [];
let parent = vcDoc.virtualCursor.position || aObject;
while ((parent = parent.parent))
let parent = vcDoc.virtualCursor.position || aDocObj;
while ((parent = parent.parent)) {
context.push(parent);
if (parent == aDocObj)
break;
}
context.reverse();
this.pivotChanged(vcDoc.virtualCursor.position || aObject, context);
this.pivotChanged(vcDoc.virtualCursor.position || aDocObj, context);
};
AndroidPresenter.prototype.tabStateChanged = function(aDocObj, aPageState) {
let stateUtterance = UtteranceGenerator.
genForTabStateChange(aDocObj, aPageState);
if (!stateUtterance.length)
return;
this.sendMessageToJava({
gecko: {
type: 'Accessibility:Event',
eventType: ANDROID_TYPE_VIEW_TEXT_CHANGED,
text: stateUtterance,
addedCount: stateUtterance.join(' ').length,
removedCount: 0,
fromIndex: 0
}
});
};
AndroidPresenter.prototype.textChanged = function(aIsInserted, aStart, aLength, aText, aModifiedText) {

View File

@ -22,6 +22,22 @@ var gAccRetrieval = Cc['@mozilla.org/accessibleRetrieval;1'].
var EXPORTED_SYMBOLS = ['UtteranceGenerator'];
/**
* Generates speech utterances from objects, actions and state changes.
* An utterance is an array of strings.
*
* It should not be assumed that flattening an utterance array would create a
* gramatically correct sentence. For example, {@link genForObject} might
* return: ['graphic', 'Welcome to my home page'].
* Each string element in an utterance should be gramatically correct in itself.
* Another example from {@link genForObject}: ['list item 2 of 5', 'Alabama'].
*
* An utterance is ordered from the least to the most important. Speaking the
* last string usually makes sense, but speaking the first often won't.
* For example {@link genForAction} might return ['button', 'clicked'] for a
* clicked event. Speaking only 'clicked' makes sense. Speaking 'button' does
* not.
*/
var UtteranceGenerator = {
gActionMap: {
jump: 'jumpAction',
@ -39,6 +55,19 @@ var UtteranceGenerator = {
cycle: 'cycleAction'
},
/**
* Generates an utterance for an object.
* @param {nsIAccessible} aAccessible accessible object to generate utterance
* for.
* @param {boolean} aForceName include the object's name in the utterance
* even if this object type does not usually have it's name uttered.
* @return {Array} Two string array. The first string describes the object
* and its states. The second string is the object's name. Some object
* types may have the description or name omitted, instead an empty string
* is returned as a placeholder. Whether the object's description or it's role
* is included is determined by {@link verbosityRoleMap}.
*/
genForObject: function(aAccessible, aForceName) {
let roleString = gAccRetrieval.getStringRole(aAccessible.role);
@ -53,10 +82,45 @@ var UtteranceGenerator = {
return func.apply(this, [aAccessible, roleString, flags]);
},
/**
* Generates an utterance for an action performed.
* TODO: May become more verbose in the future.
* @param {nsIAccessible} aAccessible accessible object that the action was
* invoked in.
* @param {string} aActionName the name of the action, one of the keys in
* {@link gActionMap}.
* @return {Array} A one string array with the action.
*/
genForAction: function(aObject, aActionName) {
return [gStringBundle.GetStringFromName(this.gActionMap[aActionName])];
},
/**
* Generates an utterance for a tab state change.
* @param {nsIAccessible} aAccessible accessible object of the tab's attached
* document.
* @param {string} aTabState the tab state name, see
* {@link Presenter.tabStateChanged}.
* @return {Array} The tab state utterace.
*/
genForTabStateChange: function (aObject, aTabState) {
switch (aTabState) {
case 'newtab':
return [gStringBundle.GetStringFromName('tabNew')];
case 'loading':
return [gStringBundle.GetStringFromName('tabLoading')];
case 'loaded':
return [aObject.name || '',
gStringBundle.GetStringFromName('tabLoaded')];
case 'loadstopped':
return [gStringBundle.GetStringFromName('tabLoadStopped')];
case 'reload':
return [gStringBundle.GetStringFromName('tabReload')];
default:
return [];
}
},
verbosityRoleMap: {
'menubar': INCLUDE_ROLE,
'scrollbar': INCLUDE_ROLE,
@ -115,35 +179,45 @@ var UtteranceGenerator = {
let name = (aFlags & INCLUDE_NAME) ? (aAccessible.name || '') : '';
let desc = (aFlags & INCLUDE_ROLE) ? this._getLocalizedRole(aRoleStr) : '';
if (!name && !desc)
return [];
let utterance = [];
let state = {};
let extState = {};
aAccessible.getState(state, extState);
if (desc) {
let state = {};
let extState = {};
aAccessible.getState(state, extState);
if (state.value & Ci.nsIAccessibleStates.STATE_CHECKABLE) {
let stateStr = (state.value & Ci.nsIAccessibleStates.STATE_CHECKED) ?
'objChecked' : 'objNotChecked';
desc = gStringBundle.formatStringFromName(stateStr, [desc], 1);
if (state.value & Ci.nsIAccessibleStates.STATE_CHECKABLE) {
let stateStr = (state.value & Ci.nsIAccessibleStates.STATE_CHECKED) ?
'objChecked' : 'objNotChecked';
desc = gStringBundle.formatStringFromName(stateStr, [desc], 1);
}
if (extState.value & Ci.nsIAccessibleStates.EXT_STATE_EXPANDABLE) {
let stateStr = (state.value & Ci.nsIAccessibleStates.STATE_EXPANDED) ?
'objExpanded' : 'objCollapsed';
desc = gStringBundle.formatStringFromName(stateStr, [desc], 1);
}
utterance.push(desc);
}
if (extState.value & Ci.nsIAccessibleStates.EXT_STATE_EXPANDABLE) {
let stateStr = (state.value & Ci.nsIAccessibleStates.STATE_EXPANDED) ?
'objExpanded' : 'objCollapsed';
desc = gStringBundle.formatStringFromName(stateStr, [desc], 1);
}
if (name)
utterance.push(name);
return [desc, name];
return utterance;
},
heading: function(aAccessible, aRoleStr, aFlags) {
let name = (aFlags & INCLUDE_NAME) ? (aAccessible.name || '') : '';
let level = {};
aAccessible.groupPosition(level, {}, {});
let desc = gStringBundle.formatStringFromName('headingLevel',
[level.value], 1);
return [desc, name];
let utterance =
[gStringBundle.formatStringFromName('headingLevel', [level.value], 1)];
if (name)
utterance.push(name);
return utterance;
},
listitem: function(aAccessible, aRoleStr, aFlags) {
@ -152,10 +226,14 @@ var UtteranceGenerator = {
let itemno = {};
let itemof = {};
aAccessible.groupPosition({}, itemof, itemno);
let desc = gStringBundle.formatStringFromName(
'objItemOf', [localizedRole, itemno.value, itemof.value], 3);
let utterance =
[gStringBundle.formatStringFromName(
'objItemOf', [localizedRole, itemno.value, itemof.value], 3)];
return [desc, name];
if (name)
utterance.push(name);
return utterance;
}
},

View File

@ -24,7 +24,7 @@ var VirtualCursorController = {
},
detach: function detach() {
this.chromeWin.document.removeEventListener('keypress', this.onkeypress);
this.chromeWin.document.removeEventListener('keypress', this.onkeypress, true);
},
getBrowserApp: function getBrowserApp() {
@ -114,38 +114,67 @@ var VirtualCursorController = {
SimpleTraversalRule: {
getMatchRoles: function(aRules) {
aRules.value = [];
return 0;
aRules.value = this._matchRoles;
return this._matchRoles.length;
},
preFilter: Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE,
match: function(aAccessible) {
if (aAccessible.childCount)
// Non-leafs do not interest us.
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
// XXX: Find a better solution for ROLE_STATICTEXT.
// It allows to filter list bullets but the same time it
// filters CSS generated content too as unwanted side effect.
let ignoreRoles = [Ci.nsIAccessibleRole.ROLE_WHITESPACE,
Ci.nsIAccessibleRole.ROLE_STATICTEXT];
if (ignoreRoles.indexOf(aAccessible.role) < 0) {
let name = aAccessible.name;
if (name && name.trim())
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
}
let state = {};
aAccessible.getState(state, {});
if (state.value & Ci.nsIAccessibleStates.STATE_FOCUSABLE)
switch (aAccessible.role) {
case Ci.nsIAccessibleRole.ROLE_COMBOBOX:
// We don't want to ignore the subtree because this is often
// where the list box hangs out.
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
case Ci.nsIAccessibleRole.ROLE_TEXT_LEAF:
{
// Nameless text leaves are boring, skip them.
let name = aAccessible.name;
if (name && name.trim())
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
else
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
}
case Ci.nsIAccessibleRole.ROLE_LINK:
// If the link has children we should land on them instead.
// Image map links don't have children so we need to match those.
if (aAccessible.childCount == 0)
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
else
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
default:
// Ignore the subtree, if there is one. So that we don't land on
// the same content that was already presented by its parent.
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH |
Ci.nsIAccessibleTraversalRule.FILTER_IGNORE_SUBTREE;
}
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule])
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule]),
_matchRoles: [
Ci.nsIAccessibleRole.ROLE_MENUITEM,
Ci.nsIAccessibleRole.ROLE_LINK,
Ci.nsIAccessibleRole.ROLE_PAGETAB,
Ci.nsIAccessibleRole.ROLE_GRAPHIC,
// XXX: Find a better solution for ROLE_STATICTEXT.
// It allows to filter list bullets but at the same time it
// filters CSS generated content too as an unwanted side effect.
// Ci.nsIAccessibleRole.ROLE_STATICTEXT,
Ci.nsIAccessibleRole.ROLE_TEXT_LEAF,
Ci.nsIAccessibleRole.ROLE_PUSHBUTTON,
Ci.nsIAccessibleRole.ROLE_CHECKBUTTON,
Ci.nsIAccessibleRole.ROLE_RADIOBUTTON,
Ci.nsIAccessibleRole.ROLE_COMBOBOX,
Ci.nsIAccessibleRole.ROLE_PROGRESSBAR,
Ci.nsIAccessibleRole.ROLE_BUTTONDROPDOWN,
Ci.nsIAccessibleRole.ROLE_BUTTONMENU,
Ci.nsIAccessibleRole.ROLE_CHECK_MENU_ITEM,
Ci.nsIAccessibleRole.ROLE_PASSWORD_TEXT,
Ci.nsIAccessibleRole.ROLE_RADIO_MENU_ITEM,
Ci.nsIAccessibleRole.ROLE_TOGGLE_BUTTON,
Ci.nsIAccessibleRole.ROLE_ENTRY
]
}
};

View File

@ -17,6 +17,7 @@ const STATE_COLLAPSED = nsIAccessibleStates.STATE_COLLAPSED;
const STATE_DEFAULT = nsIAccessibleStates.STATE_DEFAULT;
const STATE_EXPANDED = nsIAccessibleStates.STATE_EXPANDED;
const STATE_EXTSELECTABLE = nsIAccessibleStates.STATE_EXTSELECTABLE;
const STATE_FLOATING = nsIAccessibleStates.STATE_FLOATING;
const STATE_FOCUSABLE = nsIAccessibleStates.STATE_FOCUSABLE;
const STATE_FOCUSED = nsIAccessibleStates.STATE_FOCUSED;
const STATE_HASPOPUP = nsIAccessibleStates.STATE_HASPOPUP;

View File

@ -7,14 +7,53 @@
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../states.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript">
function openComboboxNCheckStates(aID)
{
this.combobox = getAccessible(aID);
this.comboboxList = this.combobox.firstChild;
this.comboboxOption = this.comboboxList.firstChild;
this.eventSeq = [
new invokerChecker(EVENT_FOCUS, this.comboboxOption)
];
this.invoke = function openComboboxNCheckStates_invoke()
{
getNode(aID).focus();
synthesizeKey("VK_DOWN", { altKey: true });
}
this.finalCheck = function openComboboxNCheckStates_invoke()
{
// Expanded state on combobox.
testStates(this.combobox, STATE_EXPANDED);
// Floating state on combobox list.
testStates(this.comboboxList, STATE_FLOATING);
}
this.getID = function openComboboxNCheckStates_getID()
{
return "open combobox and test states";
}
}
//gA11yEventDumpToConsole = true;
var gQueue = null;
function doTest()
{
// combobox
@ -24,7 +63,7 @@
STATE_FOCUSED, 0);
var comboboxList = combobox.firstChild;
testStates(comboboxList, 0, 0, STATE_FOCUSABLE, 0);
testStates(comboboxList, STATE_INVISIBLE, 0, STATE_FOCUSABLE, 0);
var opt1 = comboboxList.firstChild;
testStates(opt1, STATE_SELECTABLE | STATE_SELECTED | STATE_FOCUSABLE,
@ -46,7 +85,10 @@
STATE_SELECTED | STATE_FOCUSED | STATE_FOCUSED,
0, 0, EXT_STATE_ACTIVE);
SimpleTest.finish();
// open combobox
gQueue = new eventQueue();
gQueue.push(new openComboboxNCheckStates("combobox"));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();

View File

@ -1069,6 +1069,7 @@ toolbar[iconsize="small"] #feed-button {
padding: 1px;
margin: -1px;
-moz-margin-end: 0;
font-size: .9em;
}
#identity-box:-moz-locale-dir(ltr) {
@ -1093,9 +1094,19 @@ toolbar[iconsize="small"] #feed-button {
#identity-box.verifiedIdentity {
background-color: #fff;
color: hsl(92,81%,16%);
-moz-border-end: 1px solid hsla(92,81%,16%,.2);
color: hsl(92,100%,30%);
-moz-margin-end: 4px;
background-image: -moz-linear-gradient(hsla(92,81%,16%,0),
hsla(92,81%,16%,.2) 25%,
hsla(92,81%,16%,.2) 75%,
hsla(92,81%,16%,0));
background-position: right;
background-size: 1px;
background-repeat: no-repeat;
}
#identity-box.verifiedIdentity:-moz-locale-dir(rtl) {
background-position: left;
}
/* Identity popup icons */

View File

@ -980,6 +980,7 @@ toolbar[mode="icons"] #zoom-in-button {
padding-bottom: 1px;
-moz-padding-start: 4px;
-moz-padding-end: 0;
font-size: .9em;
}
#identity-box:-moz-locale-dir(ltr) {
@ -1025,9 +1026,19 @@ toolbar[mode="icons"] #zoom-in-button {
}
#identity-box.verifiedIdentity {
color: hsl(92,100%,20%);
-moz-border-end: 1px solid hsla(92,81%,16%,.2);
color: hsl(92,100%,30%);
-moz-padding-end: 4px;
background-image: -moz-linear-gradient(hsla(92,81%,16%,0),
hsla(92,81%,16%,.2) 25%,
hsla(92,81%,16%,.2) 75%,
hsla(92,81%,16%,0));
background-position: right;
background-size: 1px;
background-repeat: no-repeat;
}
#identity-box.verifiedIdentity:-moz-locale-dir(rtl) {
background-position: left;
}
#identity-box:-moz-focusring {

View File

@ -1359,6 +1359,7 @@ html|*.urlbar-input:-moz-lwtheme:-moz-placeholder,
#identity-box {
padding: 2px;
font-size: .9em;
}
#identity-box:-moz-locale-dir(ltr) {
@ -1406,9 +1407,19 @@ html|*.urlbar-input:-moz-lwtheme:-moz-placeholder,
}
#identity-box.verifiedIdentity {
color: hsl(92,100%,20%);
-moz-border-end: 1px solid hsla(92,81%,16%,.2);
color: hsl(92,100%,30%);
-moz-margin-end: 4px;
background-image: -moz-linear-gradient(hsla(92,81%,16%,0),
hsla(92,81%,16%,.2) 25%,
hsla(92,81%,16%,.2) 75%,
hsla(92,81%,16%,0));
background-position: right;
background-size: 1px;
background-repeat: no-repeat;
}
#identity-box.verifiedIdentity:-moz-locale-dir(rtl) {
background-position: left;
}
#identity-box.verifiedIdentity:not(:-moz-lwtheme) {

View File

@ -169,7 +169,7 @@ class Preprocessor:
args = [sys.stdin]
includes.extend(args)
for f in includes:
self.do_include(f)
self.do_include(f, False)
pass
def getCommandLineParser(self, unescapeDefines = False):
@ -414,7 +414,7 @@ class Preprocessor:
def filter_attemptSubstitution(self, aLine):
return self.filter_substitution(aLine, fatal=False)
# File ops
def do_include(self, args):
def do_include(self, args, filters=True):
"""
Preprocess a given file.
args can either be a file name, or a file-like object.
@ -427,10 +427,13 @@ class Preprocessor:
if isName:
try:
args = str(args)
args = self.applyFilters(args)
if filters:
args = self.applyFilters(args)
if not os.path.isabs(args):
args = os.path.join(self.context['DIRECTORY'], args)
args = open(args, 'rU')
except Preprocessor.Error:
raise
except:
raise Preprocessor.Error(self, 'FILE_NOT_FOUND', str(args))
self.checkLineNumbers = bool(re.search('\.(js|java)(?:\.in)?$', args.name))
@ -476,7 +479,7 @@ def preprocess(includes=[sys.stdin], defines={},
pp.setMarker(marker)
pp.out = output
for f in includes:
pp.do_include(f)
pp.do_include(f, False)
if __name__ == "__main__":
main()

View File

@ -1,3 +1,4 @@
from __future__ import with_statement
import unittest
from StringIO import StringIO
@ -13,6 +14,33 @@ class NamedIO(StringIO):
self.name = name
StringIO.__init__(self, content)
class MockedOpen(object):
"""
Context manager diverting the open builtin such that opening files
can open NamedIO instances given when creating a MockedOpen.
with MockedOpen(NamedIO('foo', 'foo'), NamedIO('bar', 'bar')):
f = open('foo', 'r')
will thus assign the NamedIO instance for the file 'foo' to f.
"""
def __init__(self, *files):
self.files = {}
for f in files:
self.files[os.path.abspath(f.name)] = f
def __call__(self, name, args):
absname = os.path.abspath(name)
if absname in self.files:
return self.files[absname]
return self.open(name, args)
def __enter__(self):
import __builtin__
self.open = __builtin__.open
__builtin__.open = self
def __exit__(self, type, value, traceback):
import __builtin__
__builtin__.open = self.open
class TestPreprocessor(unittest.TestCase):
"""
Unit tests for the Context class
@ -499,5 +527,69 @@ octal value is not equal
self.pp.do_include(f)
self.assertEqual(self.pp.out.getvalue(), "octal value is not equal\n")
def test_undefined_variable(self):
f = NamedIO("undefined_variable.in", """#filter substitution
@foo@
""")
try:
self.pp.do_include(f)
except Preprocessor.Error, exception:
self.assertEqual(exception.key, 'UNDEFINED_VAR')
else:
self.fail("Expected a Preprocessor.Error")
def test_include(self):
with MockedOpen(NamedIO("foo/test", """#define foo foobarbaz
#include @inc@
@bar@
"""),
NamedIO("bar", """#define bar barfoobaz
@foo@
""")):
f = NamedIO("include.in", """#filter substitution
#define inc ../bar
#include foo/test""")
self.pp.do_include(f)
self.assertEqual(self.pp.out.getvalue(), """foobarbaz
barfoobaz
""")
def test_include_missing_file(self):
f = NamedIO("include_missing_file.in", "#include foo")
try:
self.pp.do_include(f)
except Preprocessor.Error, exception:
self.assertEqual(exception.key, 'FILE_NOT_FOUND')
else:
self.fail("Expected a Preprocessor.Error")
def test_include_undefined_variable(self):
f = NamedIO("include_undefined_variable.in", """#filter substitution
#include @foo@
""")
try:
self.pp.do_include(f)
except Preprocessor.Error, exception:
self.assertEqual(exception.key, 'UNDEFINED_VAR')
else:
self.fail("Expected a Preprocessor.Error")
def test_include_literal_at(self):
with MockedOpen(NamedIO("@foo@", "#define foo foobarbaz")):
f = NamedIO("include_literal_at.in", """#include @foo@
#filter substitution
@foo@
""")
self.pp.do_include(f)
self.assertEqual(self.pp.out.getvalue(), """foobarbaz
""")
def test_command_line_literal_at(self):
with MockedOpen(NamedIO("@foo@.in", """@foo@
""")):
self.pp.handleCommandLine(['-Fsubstitution', '-Dfoo=foobarbaz', '@foo@.in'])
self.assertEqual(self.pp.out.getvalue(), """foobarbaz
""")
if __name__ == '__main__':
unittest.main()

View File

@ -1724,6 +1724,19 @@ if test "$GNU_CC"; then
DSO_CFLAGS=''
DSO_PIC_CFLAGS='-fPIC'
ASFLAGS="$ASFLAGS -fPIC"
AC_MSG_CHECKING([for --noexecstack option to as])
_SAVE_CFLAGS=$CFLAGS
CFLAGS="$CFLAGS -Wa,--noexecstack"
AC_TRY_COMPILE(,,AC_MSG_RESULT([yes])
[ASFLAGS="$ASFLAGS -Wa,--noexecstack"],
AC_MSG_RESULT([no]))
CFLAGS=$_SAVE_CFLAGS
AC_MSG_CHECKING([for -z noexecstack option to ld])
_SAVE_LDFLAGS=$LDFLAGS
LDFLAGS="$LDFLAGS -Wl,-z,noexecstack"
AC_TRY_LINK(,,AC_MSG_RESULT([yes]),
AC_MSG_RESULT([no])
LDFLAGS=$_SAVE_LDFLAGS)
_MOZ_RTTI_FLAGS_ON=-frtti
_MOZ_RTTI_FLAGS_OFF=-fno-rtti
@ -3586,15 +3599,15 @@ dnl check for clock_gettime(), the CLOCK_MONOTONIC clock
AC_CACHE_CHECK(for clock_gettime(CLOCK_MONOTONIC),
ac_cv_clock_monotonic,
[for libs in "" -lrt; do
_SAVE_LDFLAGS="$LDFLAGS"
LDFLAGS="$LDFLAGS $libs"
_SAVE_LIBS="$LIBS"
LIBS="$LIBS $libs"
AC_TRY_LINK([#include <time.h>],
[ struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts); ],
ac_cv_clock_monotonic=$libs
break,
ac_cv_clock_monotonic=no)
LDFLAGS="$_SAVE_LDFLAGS"
LIBS="$_SAVE_LIBS"
done])
if test "$ac_cv_clock_monotonic" != "no"; then
HAVE_CLOCK_MONOTONIC=1

View File

@ -1021,6 +1021,9 @@ nsHTMLInputElement::SetValue(const nsAString& aValue)
}
else {
SetValueInternal(aValue, false, true);
if (IsSingleLineTextControl(false)) {
GetValueInternal(mFocusedValue);
}
}
return NS_OK;
@ -1330,6 +1333,24 @@ nsHTMLInputElement::AfterSetFiles(bool aSetValueChanged)
UpdateAllValidityStates(true);
}
void
nsHTMLInputElement::FireChangeEventIfNeeded()
{
nsString value;
GetValueInternal(value);
if (!IsSingleLineTextControl(false) || mFocusedValue.Equals(value)) {
return;
}
// Dispatch the change event.
mFocusedValue = value;
nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
static_cast<nsIContent*>(this),
NS_LITERAL_STRING("change"), true,
false);
}
const nsCOMArray<nsIDOMFile>&
nsHTMLInputElement::GetFiles() const
{
@ -1908,13 +1929,7 @@ nsHTMLInputElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
// Fire onchange (if necessary), before we do the blur, bug 357684.
if (aVisitor.mEvent->message == NS_BLUR_CONTENT) {
nsIFrame* primaryFrame = GetPrimaryFrame();
if (primaryFrame) {
nsITextControlFrame* textFrame = do_QueryFrame(primaryFrame);
if (textFrame) {
textFrame->CheckFireOnChange();
}
}
FireChangeEventIfNeeded();
}
return nsGenericHTMLFormElement::PreHandleEvent(aVisitor);
@ -1947,6 +1962,10 @@ nsHTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
if (aVisitor.mEvent->message == NS_FOCUS_CONTENT ||
aVisitor.mEvent->message == NS_BLUR_CONTENT) {
if (aVisitor.mEvent->message == NS_FOCUS_CONTENT &&
IsSingleLineTextControl(false)) {
GetValueInternal(mFocusedValue);
}
UpdateValidityUIBits(aVisitor.mEvent->message == NS_FOCUS_CONTENT);
@ -2195,16 +2214,7 @@ nsHTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
(keyEvent->keyCode == NS_VK_RETURN ||
keyEvent->keyCode == NS_VK_ENTER) &&
IsSingleLineTextControl(false, mType)) {
nsIFrame* primaryFrame = GetPrimaryFrame();
if (primaryFrame) {
nsITextControlFrame* textFrame = do_QueryFrame(primaryFrame);
// Fire onChange (if necessary)
if (textFrame) {
textFrame->CheckFireOnChange();
}
}
FireChangeEventIfNeeded();
rv = MaybeSubmitForm(aVisitor.mPresContext);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -2441,6 +2451,14 @@ nsHTMLInputElement::HandleTypeChange(PRUint8 aNewType)
// There is no value sanitizing algorithm for elements in this mode.
break;
}
//Updating mFocusedValue in consequence.
if (isNewTypeSingleLine && !isCurrentTypeSingleLine) {
GetValueInternal(mFocusedValue);
}
else if (!isNewTypeSingleLine && isCurrentTypeSingleLine) {
mFocusedValue.Truncate();
}
}
// Do not notify, it will be done after if needed.

View File

@ -303,6 +303,11 @@ public:
return HasAttr(kNameSpaceID_None, nsGkAtoms::checked);
}
/**
* Fires change event if mFocusedValue and current value held are unequal.
*/
void FireChangeEventIfNeeded();
protected:
// Pull IsSingleLineTextControl into our scope, otherwise it'd be hidden
// by the nsITextControlElement version.
@ -586,6 +591,15 @@ protected:
nsString mStaticDocFileList;
/**
* The value of the input element when first initialized and it is updated
* when the element is either changed through a script, focused or dispatches
* a change event. This is to ensure correct future change event firing.
* NB: This is ONLY applicable where the element is a text control. ie,
* where type= "text", "email", "search", "tel", "url" or "password".
*/
nsString mFocusedValue;
/**
* The type of this input (<input type=...>) as an integer.
* @see nsIFormControl.h (specifically NS_FORM_INPUT_*)

View File

@ -260,6 +260,10 @@ protected:
/** Whether we should make :-moz-ui-valid apply on the element. **/
bool mCanShowValidUI;
void FireChangeEventIfNeeded();
nsString mFocusedValue;
/** The state of the text editor (selection controller and the editor) **/
nsTextEditorState mState;
@ -589,7 +593,9 @@ nsHTMLTextAreaElement::SetValueInternal(const nsAString& aValue,
NS_IMETHODIMP
nsHTMLTextAreaElement::SetValue(const nsAString& aValue)
{
return SetValueInternal(aValue, false);
SetValueInternal(aValue, false);
GetValueInternal(mFocusedValue, true);
return NS_OK;
}
NS_IMETHODIMP
@ -733,18 +739,30 @@ nsHTMLTextAreaElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
// Fire onchange (if necessary), before we do the blur, bug 370521.
if (aVisitor.mEvent->message == NS_BLUR_CONTENT) {
nsIFrame* primaryFrame = GetPrimaryFrame();
if (primaryFrame) {
nsITextControlFrame* textFrame = do_QueryFrame(primaryFrame);
if (textFrame) {
textFrame->CheckFireOnChange();
}
}
FireChangeEventIfNeeded();
}
return nsGenericHTMLFormElement::PreHandleEvent(aVisitor);
}
void
nsHTMLTextAreaElement::FireChangeEventIfNeeded()
{
nsString value;
GetValueInternal(value, true);
if (mFocusedValue.Equals(value)) {
return;
}
// Dispatch the change event.
mFocusedValue = value;
nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
static_cast<nsIContent*>(this),
NS_LITERAL_STRING("change"), true,
false);
}
nsresult
nsHTMLTextAreaElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
{
@ -757,6 +775,7 @@ nsHTMLTextAreaElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
if (aVisitor.mEvent->message == NS_FOCUS_CONTENT) {
// If the invalid UI is shown, we should show it while focusing (and
// update). Otherwise, we should not.
GetValueInternal(mFocusedValue, true);
mCanShowInvalidUI = !IsValid() && ShouldShowValidityUI();
// If neither invalid UI nor valid UI is shown, we shouldn't show the valid

View File

@ -1743,11 +1743,6 @@ nsTextEditorState::SetValue(const nsAString& aValue, bool aUserInput)
// PrepareEditor cannot be called prematurely.
nsAutoScriptBlocker scriptBlocker;
bool fireChangeEvent = mBoundFrame->GetFireChangeEventState();
if (aUserInput) {
mBoundFrame->SetFireChangeEventState(true);
}
#ifdef DEBUG
if (IsSingleLineTextControl()) {
NS_ASSERTION(mEditorInitialized || mInitializing,
@ -1774,8 +1769,7 @@ nsTextEditorState::SetValue(const nsAString& aValue, bool aUserInput)
// this is necessary to avoid infinite recursion
if (!currentValue.Equals(aValue))
{
nsTextControlFrame::ValueSetter valueSetter(mBoundFrame, mEditor,
mBoundFrame->mFocusedValue.Equals(currentValue));
nsTextControlFrame::ValueSetter valueSetter(mBoundFrame, mEditor);
// \r is an illegal character in the dom, but people use them,
// so convert windows and mac platform linebreaks to \n:
@ -1894,9 +1888,6 @@ nsTextEditorState::SetValue(const nsAString& aValue, bool aUserInput)
scrollableFrame->ScrollTo(nsPoint(0, 0), nsIScrollableFrame::INSTANT);
}
if (aUserInput) {
mBoundFrame->SetFireChangeEventState(fireChangeEvent);
}
} else {
if (!mValue) {
mValue = new nsCString;

View File

@ -46,6 +46,7 @@ include $(topsrcdir)/config/rules.mk
_TEST_FILES = \
save_restore_radio_groups.sjs \
test_save_restore_radio_groups.html \
test_change_event.html \
test_mozistextfield.html \
test_input_attributes_reflection.html \
test_input_list_attribute.html \

View File

@ -0,0 +1,148 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=722599
-->
<head>
<title>Test for Bug 722599</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=722599">Mozilla Bug 722599</a>
<p id="display"></p>
<div id="content">
<input type="file" id="fileInput"></input>
<textarea id="textarea" onchange="++textareaChange;"></textarea>
<input type="text" id="input_text" onchange="++textInputChange[0];"></input>
<input type="email" id="input_email" onchange="++textInputChange[1];"></input>
<input type="search" id="input_search" onchange="++textInputChange[2];"></input>
<input type="tel" id="input_telephone" onchange="++textInputChange[3];"></input>
<input type="url" id="input_url" onchange="++textInputChange[4];"></input>
<input type="password" id="input_password" onchange="++textInputChange[5];"></input>
<!-- "Non-text" inputs-->
<input type="button" id="input_button" onchange="++NonTextInputChange[0];"></input>
<input type="submit" id="input_submit" onchange="++NonTextInputChange[1];"></input>
<input type="image" id="input_image" onchange="++NonTextInputChange[2];"></input>
<input type="reset" id="input_reset" onchange="++NonTextInputChange[3];"></input>
<input type="radio" id="input_radio" onchange="++NonTextInputChange[4];"></input>
<input type="checkbox" id="input_checkbox" onchange="++NonTextInputChange[5];"></input>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 722599 **/
var textareaChange = 0;
var fileInputChange = 0;
var textInputTypes = ["text", "email", "search", "telephone", "url", "password"];
var textInputChange = [0, 0, 0, 0, 0, 0];
var NonTextInputTypes = ["button", "submit", "image", "reset", "radio", "checkbox"];
var NonTextInputChange = [0, 0, 0, 0, 0, 0];
var blurTestCalled = false; //Sentinel to prevent infinite loop.
SimpleTest.waitForExplicitFinish();
var MockFilePicker = SpecialPowers.MockFilePicker;
MockFilePicker.init();
function fileInputBlurTest() {
var btn = document.getElementById('fileInput');
btn.focus()
btn.blur();
is(fileInputChange, 1, "change event shouldn't be dispatched on blur for file input element(1)");
}
function testUserInput() {
//Simulating an OK click and with a file name return.
MockFilePicker.useAnyFile();
MockFilePicker.returnValue = MockFilePicker.returnOK;
var input = document.getElementById('fileInput');
input.focus();
input.addEventListener("change", function (aEvent) {
++fileInputChange;
if (!blurTestCalled) {
is(fileInputChange, 1, "change event should have been dispatched on file input.");
blurTestCalled = true;
fileInputBlurTest();
}
else {
is(fileInputChange, 1, "change event shouldn't be dispatched on blur for file input element (2)");
}
}, false);
input.click();
//text, email, search, telephone, url & password input tests
for (var i = 0; i < textInputTypes.length; ++i) {
input = document.getElementById("input_" + textInputTypes[i]);
input.focus();
synthesizeKey("VK_ENTER", {});
is(textInputChange[i], 0, "Change event shouldn't be dispatched on " + textInputTypes[i] + " input element");
synthesizeKey("m", {});
synthesizeKey("VK_RETURN", {});
is(textInputChange[i], 1, textInputTypes[i] + " input element should have dispatched change event.");
}
//focus and blur text input
input = document.getElementById("input_text");
input.focus();
synthesizeKey("f", {});
input.blur();
is(textInputChange[0], 2, "text input element should have dispatched change event (2).");
//focus and blur textarea
var textarea = document.getElementById("textarea");
textarea.focus();
synthesizeKey("f", {});
textarea.blur();
is(textareaChange, 1, "Textarea element should have dispatched change event.");
//Non-text input tests:
for (var i = 0; i < NonTextInputTypes.length; ++i) {
//button, submit, image and reset input type tests.
if (i < 4) {
input = document.getElementById("input_" + NonTextInputTypes[i]);
input.focus();
input.click();
is(NonTextInputChange[i], 0, "Change event shouldn't be dispatched on " + NonTextInputTypes[i] + " input element");
input.blur();
is(NonTextInputChange[i], 0, "Change event shouldn't be dispatched on " + NonTextInputTypes[i] + " input element(2)");
}
//for radio and and checkboxes, we require that change event should ONLY be dispatched on setting the value.
else {
input = document.getElementById("input_" + NonTextInputTypes[i]);
input.focus();
input.click();
is(NonTextInputChange[i], 1, NonTextInputTypes[i] + " input element should have dispatched change event.");
input.blur();
is(NonTextInputChange[i], 1, "Change event shouldn't be dispatched on " + NonTextInputTypes[i] + " input element");
}
}
//Input type change test.
input = document.getElementById("input_checkbox");
input.type = "text";
input.focus();
input.click();
input.blur();
is(NonTextInputChange[5], 1, "Change event shouldn't be dispatched for checkbox ---> text input type change");
MockFilePicker.cleanup;
SimpleTest.finish();
}
addLoadEvent(testUserInput);
</script>
</pre>
</body>
</html>

View File

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */

View File

@ -92,3 +92,10 @@ collapseAction = collapsed
expandAction = expanded
activateAction = activated
cycleAction = cycled
# Tab states
tabLoading = loading
tabLoaded = loaded
tabNew = new tab
tabLoadStopped = loading stopped
tabReload = reloading

View File

@ -8,16 +8,29 @@
</head>
<body>
<script>
ok(window.performance);
ok(typeof window.performance.now == 'function');
var n = window.performance.now();
ok(n >= 0);
ok(window.performance.now() >= n);
ok(window.performance, "Performance object should exist.");
ok(typeof window.performance.now == 'function', "Performance object should have a 'now' method.");
var n = window.performance.now(), d = Date.now();
ok(n >= 0, "The value of now() should be equal to or greater than 0.");
ok(window.performance.now() >= n, "The value of now() should monotonically increase.");
SimpleTest.waitForExplicitFinish();
setTimeout(function() {
ok(window.performance.now() > n);
var checks = 0;
function checkAfterTimeout() {
checks++;
var d2 = Date.now();
// Timeouts aren't extremely reliable and especially on Windows we are prone to fallback to
// millisecond timers, in which case this test might occasionally fail. This is a workaround:
if (navigator.platform.indexOf("Win") == 0 &&
window.performance.now() == n && d == d2 &&
checks < 5) {
setTimeout(checkAfterTimeout, 20);
return;
}
ok(window.performance.now() > n, "After a timeout, the value of now() should be strictly greater than before.");
SimpleTest.finish();
}, 20);
};
setTimeout(checkAfterTimeout, 20);
</script>
</body>
</html>

View File

@ -236,7 +236,13 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
->Paint(aContext, nsnull);
}
BasicManager()->PaintedTiledLayerBuffer(BasicManager()->Hold(this), &mTiledBuffer);
// Create a heap copy owned and released by the compositor. This is needed
// since we're sending this over an async message and content needs to be
// be able to modify the tiled buffer in the next transaction.
// TODO: Remove me once Bug 747811 lands.
BasicTiledLayerBuffer *heapCopy = new BasicTiledLayerBuffer(mTiledBuffer);
BasicManager()->PaintedTiledLayerBuffer(BasicManager()->Hold(this), heapCopy);
}
} // mozilla

View File

@ -244,6 +244,10 @@ parent:
sync Update(Edit[] cset, bool isFirstPaint)
returns (EditReply[] reply);
// We don't need to send a sync transaction if
// no transaction operate require a swap.
async UpdateNoSwap(Edit[] cset, bool isFirstPaint);
async __delete__();
};

View File

@ -66,7 +66,10 @@ typedef std::set<ShadowableLayer*> ShadowableLayerSet;
class Transaction
{
public:
Transaction() : mOpen(false) {}
Transaction()
: mOpen(false)
, mSwapRequired(false)
{}
void Begin() { mOpen = true; }
@ -76,6 +79,11 @@ public:
mCset.push_back(aEdit);
}
void AddPaint(const Edit& aPaint)
{
AddNoSwapPaint(aPaint);
mSwapRequired = true;
}
void AddNoSwapPaint(const Edit& aPaint)
{
NS_ABORT_IF_FALSE(!Finished(), "forgot BeginTransaction?");
mPaints.push_back(aPaint);
@ -102,6 +110,7 @@ public:
mDyingBuffers.Clear();
mMutants.clear();
mOpen = false;
mSwapRequired = false;
}
bool Empty() const {
@ -113,6 +122,7 @@ public:
EditVector mPaints;
BufferArray mDyingBuffers;
ShadowableLayerSet mMutants;
bool mSwapRequired;
private:
bool mOpen;
@ -247,7 +257,7 @@ ShadowLayerForwarder::PaintedTiledLayerBuffer(ShadowableLayer* aLayer,
{
if (XRE_GetProcessType() != GeckoProcessType_Default)
NS_RUNTIMEABORT("PaintedTiledLayerBuffer must be made IPC safe (not share pointers)");
mTxn->AddPaint(OpPaintTiledLayerBuffer(NULL, Shadow(aLayer),
mTxn->AddNoSwapPaint(OpPaintTiledLayerBuffer(NULL, Shadow(aLayer),
uintptr_t(aTiledLayerBuffer)));
}
@ -341,11 +351,22 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies)
MOZ_LAYERS_LOG(("[LayersForwarder] syncing before send..."));
PlatformSyncBeforeUpdate();
MOZ_LAYERS_LOG(("[LayersForwarder] sending transaction..."));
RenderTraceScope rendertrace3("Foward Transaction", "000093");
if (!mShadowManager->SendUpdate(cset, mIsFirstPaint, aReplies)) {
MOZ_LAYERS_LOG(("[LayersForwarder] WARNING: sending transaction failed!"));
return false;
if (mTxn->mSwapRequired) {
MOZ_LAYERS_LOG(("[LayersForwarder] sending transaction..."));
RenderTraceScope rendertrace3("Forward Transaction", "000093");
if (!mShadowManager->SendUpdate(cset, mIsFirstPaint, aReplies)) {
MOZ_LAYERS_LOG(("[LayersForwarder] WARNING: sending transaction failed!"));
return false;
}
} else {
// If we don't require a swap we can call SendUpdateNoSwap which
// assumes that aReplies is empty (DEBUG assertion)
MOZ_LAYERS_LOG(("[LayersForwarder] sending no swap transaction..."));
RenderTraceScope rendertrace3("Forward NoSwap Transaction", "000093");
if (!mShadowManager->SendUpdateNoSwap(cset, mIsFirstPaint)) {
MOZ_LAYERS_LOG(("[LayersForwarder] WARNING: sending transaction failed!"));
return false;
}
}
mIsFirstPaint = false;

View File

@ -147,6 +147,17 @@ ShadowLayersParent::Destroy()
}
}
/* virtual */
bool
ShadowLayersParent::RecvUpdateNoSwap(const InfallibleTArray<Edit>& cset,
const bool& isFirstPaint)
{
InfallibleTArray<EditReply> noReplies;
bool success = RecvUpdate(cset, isFirstPaint, &noReplies);
NS_ABORT_IF_FALSE(noReplies.Length() == 0, "RecvUpdateNoSwap requires a sync Update to carry Edits");
return success;
}
bool
ShadowLayersParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
const bool& isFirstPaint,

View File

@ -81,6 +81,9 @@ protected:
const bool& isFirstPaint,
EditReplyArray* reply);
NS_OVERRIDE virtual bool RecvUpdateNoSwap(const EditArray& cset,
const bool& isFirstPaint);
NS_OVERRIDE virtual PLayerParent* AllocPLayer();
NS_OVERRIDE virtual bool DeallocPLayer(PLayerParent* actor);

View File

@ -132,6 +132,8 @@ void
TiledThebesLayerOGL::PaintedTiledLayerBuffer(const BasicTiledLayerBuffer* mTiledBuffer)
{
mMainMemoryTiledBuffer = *mTiledBuffer;
// TODO: Remove me once Bug 747811 lands.
delete mTiledBuffer;
mRegionToUpload.Or(mRegionToUpload, mMainMemoryTiledBuffer.GetLastPaintRegion());
}

View File

@ -169,7 +169,7 @@ class Preprocessor:
args = [sys.stdin]
includes.extend(args)
for f in includes:
self.do_include(f)
self.do_include(f, False)
pass
def getCommandLineParser(self, unescapeDefines = False):
@ -414,7 +414,7 @@ class Preprocessor:
def filter_attemptSubstitution(self, aLine):
return self.filter_substitution(aLine, fatal=False)
# File ops
def do_include(self, args):
def do_include(self, args, filters=True):
"""
Preprocess a given file.
args can either be a file name, or a file-like object.
@ -427,10 +427,13 @@ class Preprocessor:
if isName:
try:
args = str(args)
args = self.applyFilters(args)
if filters:
args = self.applyFilters(args)
if not os.path.isabs(args):
args = os.path.join(self.context['DIRECTORY'], args)
args = open(args, 'rU')
except Preprocessor.Error:
raise
except:
raise Preprocessor.Error(self, 'FILE_NOT_FOUND', str(args))
self.checkLineNumbers = bool(re.search('\.(js|java)(?:\.in)?$', args.name))
@ -476,7 +479,7 @@ def preprocess(includes=[sys.stdin], defines={},
pp.setMarker(marker)
pp.out = output
for f in includes:
pp.do_include(f)
pp.do_include(f, False)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,12 @@
a = 'a';
b = [,];
exhaustiveSliceTest("exhaustive slice test 1", a);
print('---');
exhaustiveSliceTest("exhaustive slice test 2", b);
function exhaustiveSliceTest(testname, a){
x = 0
var y = 0;
countHeap();
for (y=a.length; y + a.length; y--) { print(y);
var b = a.slice(x,y); }
}

View File

@ -0,0 +1,11 @@
// |jit-test| error: ReferenceError;
gczeal(4);
try { jsTestDriverEnd(); } catch(exc1) {}
evaluate("\
schedulegc(10);\
for(var i=0; i<3; i++) {\
var obj = { first: 'first', second: 'second' };\
for (var elem in obj) {}\
x.push(count);\
}\
");

View File

@ -1742,35 +1742,20 @@ JS_InitStandardClasses(JSContext *cx, JSObject *obj)
#define CLASP(name) (&name##Class)
#define TYPED_ARRAY_CLASP(type) (&TypedArray::classes[TypedArray::type])
#define EAGER_ATOM(name) NAME_OFFSET(name), NULL
#define EAGER_CLASS_ATOM(name) CLASS_NAME_OFFSET(name), NULL
#define EAGER_ATOM(name) NAME_OFFSET(name)
#define EAGER_CLASS_ATOM(name) CLASS_NAME_OFFSET(name)
#define EAGER_ATOM_AND_CLASP(name) EAGER_CLASS_ATOM(name), CLASP(name)
#define LAZY_ATOM(name) NAME_OFFSET(lazy.name), js_##name##_str
typedef struct JSStdName {
JSObjectOp init;
size_t atomOffset; /* offset of atom pointer in JSAtomState */
const char *name; /* null if atom is pre-pinned, else name */
Class *clasp;
} JSStdName;
static PropertyName *
StdNameToPropertyName(JSContext *cx, JSStdName *stdn)
{
size_t offset;
PropertyName *atom;
const char *name;
offset = stdn->atomOffset;
atom = OFFSET_TO_NAME(cx->runtime, offset);
if (!atom) {
name = stdn->name;
if (name) {
atom = js_Atomize(cx, name, strlen(name), InternAtom)->asPropertyName();
OFFSET_TO_NAME(cx->runtime, offset) = atom;
}
}
return atom;
return OFFSET_TO_NAME(cx->runtime, stdn->atomOffset);
}
/*
@ -1801,7 +1786,7 @@ static JSStdName standard_class_atoms[] = {
{js_InitWeakMapClass, EAGER_CLASS_ATOM(WeakMap), &js::WeakMapClass},
{js_InitMapClass, EAGER_CLASS_ATOM(Map), &js::MapObject::class_},
{js_InitSetClass, EAGER_CLASS_ATOM(Set), &js::SetObject::class_},
{NULL, 0, NULL, NULL}
{NULL, 0, NULL}
};
/*
@ -1815,20 +1800,20 @@ static JSStdName standard_class_names[] = {
/* Global properties and functions defined by the Number class. */
{js_InitNumberClass, EAGER_ATOM(NaN), CLASP(Number)},
{js_InitNumberClass, EAGER_ATOM(Infinity), CLASP(Number)},
{js_InitNumberClass, LAZY_ATOM(isNaN), CLASP(Number)},
{js_InitNumberClass, LAZY_ATOM(isFinite), CLASP(Number)},
{js_InitNumberClass, LAZY_ATOM(parseFloat), CLASP(Number)},
{js_InitNumberClass, LAZY_ATOM(parseInt), CLASP(Number)},
{js_InitNumberClass, EAGER_ATOM(isNaN), CLASP(Number)},
{js_InitNumberClass, EAGER_ATOM(isFinite), CLASP(Number)},
{js_InitNumberClass, EAGER_ATOM(parseFloat), CLASP(Number)},
{js_InitNumberClass, EAGER_ATOM(parseInt), CLASP(Number)},
/* String global functions. */
{js_InitStringClass, LAZY_ATOM(escape), CLASP(String)},
{js_InitStringClass, LAZY_ATOM(unescape), CLASP(String)},
{js_InitStringClass, LAZY_ATOM(decodeURI), CLASP(String)},
{js_InitStringClass, LAZY_ATOM(encodeURI), CLASP(String)},
{js_InitStringClass, LAZY_ATOM(decodeURIComponent), CLASP(String)},
{js_InitStringClass, LAZY_ATOM(encodeURIComponent), CLASP(String)},
{js_InitStringClass, EAGER_ATOM(escape), CLASP(String)},
{js_InitStringClass, EAGER_ATOM(unescape), CLASP(String)},
{js_InitStringClass, EAGER_ATOM(decodeURI), CLASP(String)},
{js_InitStringClass, EAGER_ATOM(encodeURI), CLASP(String)},
{js_InitStringClass, EAGER_ATOM(decodeURIComponent), CLASP(String)},
{js_InitStringClass, EAGER_ATOM(encodeURIComponent), CLASP(String)},
#if JS_HAS_UNEVAL
{js_InitStringClass, LAZY_ATOM(uneval), CLASP(String)},
{js_InitStringClass, EAGER_ATOM(uneval), CLASP(String)},
#endif
/* Exception constructors. */
@ -1842,8 +1827,8 @@ static JSStdName standard_class_names[] = {
{js_InitExceptionClasses, EAGER_CLASS_ATOM(URIError), CLASP(Error)},
#if JS_HAS_XML_SUPPORT
{js_InitXMLClass, LAZY_ATOM(XMLList), CLASP(XML)},
{js_InitXMLClass, LAZY_ATOM(isXMLName), CLASP(XML)},
{js_InitXMLClass, EAGER_ATOM(XMLList), CLASP(XML)},
{js_InitXMLClass, EAGER_ATOM(isXMLName), CLASP(XML)},
#endif
#if JS_HAS_GENERATORS
@ -1867,7 +1852,7 @@ static JSStdName standard_class_names[] = {
{js_InitWeakMapClass, EAGER_ATOM_AND_CLASP(WeakMap)},
{js_InitProxyClass, EAGER_ATOM_AND_CLASP(Proxy)},
{NULL, 0, NULL, NULL}
{NULL, 0, NULL}
};
static JSStdName object_prototype_names[] = {
@ -1880,20 +1865,20 @@ static JSStdName object_prototype_names[] = {
{js_InitObjectClass, EAGER_ATOM(toLocaleString), CLASP(Object)},
{js_InitObjectClass, EAGER_ATOM(valueOf), CLASP(Object)},
#if JS_HAS_OBJ_WATCHPOINT
{js_InitObjectClass, LAZY_ATOM(watch), CLASP(Object)},
{js_InitObjectClass, LAZY_ATOM(unwatch), CLASP(Object)},
{js_InitObjectClass, EAGER_ATOM(watch), CLASP(Object)},
{js_InitObjectClass, EAGER_ATOM(unwatch), CLASP(Object)},
#endif
{js_InitObjectClass, LAZY_ATOM(hasOwnProperty), CLASP(Object)},
{js_InitObjectClass, LAZY_ATOM(isPrototypeOf), CLASP(Object)},
{js_InitObjectClass, LAZY_ATOM(propertyIsEnumerable), CLASP(Object)},
{js_InitObjectClass, EAGER_ATOM(hasOwnProperty), CLASP(Object)},
{js_InitObjectClass, EAGER_ATOM(isPrototypeOf), CLASP(Object)},
{js_InitObjectClass, EAGER_ATOM(propertyIsEnumerable), CLASP(Object)},
#if OLD_GETTER_SETTER_METHODS
{js_InitObjectClass, LAZY_ATOM(defineGetter), CLASP(Object)},
{js_InitObjectClass, LAZY_ATOM(defineSetter), CLASP(Object)},
{js_InitObjectClass, LAZY_ATOM(lookupGetter), CLASP(Object)},
{js_InitObjectClass, LAZY_ATOM(lookupSetter), CLASP(Object)},
{js_InitObjectClass, EAGER_ATOM(defineGetter), CLASP(Object)},
{js_InitObjectClass, EAGER_ATOM(defineSetter), CLASP(Object)},
{js_InitObjectClass, EAGER_ATOM(lookupGetter), CLASP(Object)},
{js_InitObjectClass, EAGER_ATOM(lookupSetter), CLASP(Object)},
#endif
{NULL, 0, NULL, NULL}
{NULL, 0, NULL}
};
JS_PUBLIC_API(JSBool)
@ -2149,7 +2134,6 @@ JS_EnumerateResolvedStandardClasses(JSContext *cx, JSObject *obj, JSIdArray *ida
#undef EAGER_ATOM
#undef EAGER_CLASS_ATOM
#undef EAGER_ATOM_CLASP
#undef LAZY_ATOM
JS_PUBLIC_API(JSBool)
JS_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key, JSObject **objp)

View File

@ -75,7 +75,6 @@ using namespace js;
using namespace js::gc;
const size_t JSAtomState::commonAtomsOffset = offsetof(JSAtomState, emptyAtom);
const size_t JSAtomState::lazyAtomsOffset = offsetof(JSAtomState, lazy);
/*
* ATOM_HASH assumes that JSHashNumber is 32-bit even on 64-bit systems.
@ -151,9 +150,6 @@ JSAtomState::checkStaticInvariants()
offsetof(JSAtomState, booleanAtoms) - commonAtomsOffset);
JS_STATIC_ASSERT((1 + 2) * sizeof(JSAtom *) ==
offsetof(JSAtomState, typeAtoms) - commonAtomsOffset);
JS_STATIC_ASSERT(JS_ARRAY_LENGTH(js_common_atom_names) * sizeof(JSAtom *) ==
lazyAtomsOffset - commonAtomsOffset);
}
/*
@ -236,7 +232,6 @@ js::InitCommonAtoms(JSContext *cx)
*atoms = atom->asPropertyName();
}
state->clearLazyAtoms();
cx->runtime->emptyString = state->emptyAtom;
return true;
}

View File

@ -308,38 +308,7 @@ struct JSAtomState
#undef DEFINE_PROTOTYPE_ATOM
#undef DEFINE_KEYWORD_ATOM
/* Less frequently used atoms, pinned lazily by JS_ResolveStandardClass. */
struct {
js::PropertyName *XMLListAtom;
js::PropertyName *decodeURIAtom;
js::PropertyName *decodeURIComponentAtom;
js::PropertyName *defineGetterAtom;
js::PropertyName *defineSetterAtom;
js::PropertyName *encodeURIAtom;
js::PropertyName *encodeURIComponentAtom;
js::PropertyName *escapeAtom;
js::PropertyName *hasOwnPropertyAtom;
js::PropertyName *isFiniteAtom;
js::PropertyName *isNaNAtom;
js::PropertyName *isPrototypeOfAtom;
js::PropertyName *isXMLNameAtom;
js::PropertyName *lookupGetterAtom;
js::PropertyName *lookupSetterAtom;
js::PropertyName *parseFloatAtom;
js::PropertyName *parseIntAtom;
js::PropertyName *propertyIsEnumerableAtom;
js::PropertyName *unescapeAtom;
js::PropertyName *unevalAtom;
js::PropertyName *unwatchAtom;
js::PropertyName *watchAtom;
} lazy;
static const size_t commonAtomsOffset;
static const size_t lazyAtomsOffset;
void clearLazyAtoms() {
memset(&lazy, 0, sizeof(lazy));
}
void junkAtoms() {
#ifdef DEBUG

View File

@ -123,3 +123,26 @@ DEFINE_KEYWORD_ATOM(return)
DEFINE_KEYWORD_ATOM(throw)
DEFINE_ATOM(url, "url")
DEFINE_ATOM(innermost, "innermost")
DEFINE_ATOM(XMLList, "XMLList")
DEFINE_ATOM(decodeURI, "decodeURI")
DEFINE_ATOM(decodeURIComponent, "decodeURIComponent")
DEFINE_ATOM(defineGetter, "__defineGetter__")
DEFINE_ATOM(defineSetter, "__defineSetter__")
DEFINE_ATOM(encodeURI, "encodeURI")
DEFINE_ATOM(encodeURIComponent, "encodeURIComponent")
DEFINE_ATOM(escape, "escape")
DEFINE_ATOM(hasOwnProperty, "hasOwnProperty")
DEFINE_ATOM(isFinite, "isFinite")
DEFINE_ATOM(isNaN, "isNaN")
DEFINE_ATOM(isPrototypeOf, "isPrototypeOf")
DEFINE_ATOM(isXMLName, "isXMLName")
DEFINE_ATOM(lookupGetter, "__lookupGetter__")
DEFINE_ATOM(lookupSetter, "__lookupSetter__")
DEFINE_ATOM(parseFloat, "parseFloat")
DEFINE_ATOM(parseInt, "parseInt")
DEFINE_ATOM(propertyIsEnumerable, "propertyIsEnumerable")
DEFINE_ATOM(unescape, "unescape")
DEFINE_ATOM(uneval, "uneval")
DEFINE_ATOM(unwatch, "unwatch")
DEFINE_ATOM(watch, "watch")

View File

@ -4289,12 +4289,6 @@ oom:
js_free(trc);
}
static void
MarkFromAutorooter(JSTracer *jstrc, void **thingp, JSGCTraceKind kind)
{
static_cast<Cell *>(*thingp)->markIfUnmarked();
}
static bool
IsMarkedOrAllocated(Cell *cell)
{
@ -4327,21 +4321,6 @@ CheckEdge(JSTracer *jstrc, void **thingp, JSGCTraceKind kind)
return;
}
}
/*
* Anything that is reachable now should have been reachable before, or else
* it should be marked.
*/
NodeMap::Ptr p = trc->nodemap.lookup(*thingp);
JS_ASSERT_IF(!p, IsMarkedOrAllocated(static_cast<Cell *>(*thingp)));
}
static void
CheckReachable(JSTracer *jstrc, void **thingp, JSGCTraceKind kind)
{
VerifyTracer *trc = (VerifyTracer *)jstrc;
NodeMap::Ptr p = trc->nodemap.lookup(*thingp);
JS_ASSERT_IF(!p, IsMarkedOrAllocated(static_cast<Cell *>(*thingp)));
}
static void
@ -4387,18 +4366,7 @@ EndVerifyBarriers(JSRuntime *rt)
rt->gcVerifyData = NULL;
rt->gcIncrementalState = NO_INCREMENTAL;
JS_TracerInit(trc, rt, MarkFromAutorooter);
AutoGCRooter::traceAll(trc);
if (!compartmentCreated && IsIncrementalGCSafe(rt)) {
/*
* Verify that all the current roots were reachable previously, or else
* are marked.
*/
JS_TracerInit(trc, rt, CheckReachable);
MarkRuntime(trc, true);
JS_TracerInit(trc, rt, CheckEdge);
/* Start after the roots. */

View File

@ -107,10 +107,7 @@ class Type
return data > JSVAL_TYPE_UNKNOWN;
}
TypeObjectKey *objectKey() const {
JS_ASSERT(isObject());
return (TypeObjectKey *) data;
}
inline TypeObjectKey *objectKey() const;
/* Accessors for JSObject types */
@ -118,10 +115,7 @@ class Type
return isObject() && !!(data & 1);
}
JSObject *singleObject() const {
JS_ASSERT(isSingleObject());
return (JSObject *) (data ^ 1);
}
inline JSObject *singleObject() const;
/* Accessors for TypeObject types */
@ -129,10 +123,7 @@ class Type
return isObject() && !(data & 1);
}
TypeObject *typeObject() const {
JS_ASSERT(isTypeObject());
return (TypeObject *) data;
}
inline TypeObject *typeObject() const;
bool operator == (Type o) const { return data == o.data; }
bool operator != (Type o) const { return data != o.data; }

View File

@ -1014,6 +1014,33 @@ HashSetLookup(U **values, unsigned count, T key)
return NULL;
}
inline TypeObjectKey *
Type::objectKey() const
{
JS_ASSERT(isObject());
if (isTypeObject())
TypeObject::readBarrier((TypeObject *) data);
else
JSObject::readBarrier((JSObject *) (data ^ 1));
return (TypeObjectKey *) data;
}
inline JSObject *
Type::singleObject() const
{
JS_ASSERT(isSingleObject());
JSObject::readBarrier((JSObject *) (data ^ 1));
return (JSObject *) (data ^ 1);
}
inline TypeObject *
Type::typeObject() const
{
JS_ASSERT(isTypeObject());
TypeObject::readBarrier((TypeObject *) data);
return (TypeObject *) data;
}
inline bool
TypeSet::hasType(Type type)
{

View File

@ -4249,9 +4249,7 @@ END_CASE(JSOP_ARRAYPUSH)
forced_return:
UnwindScope(cx, 0);
regs.sp = regs.fp()->base();
regs.pc = script->code + script->length - JSOP_STOP_LENGTH;
JS_ASSERT(*regs.pc == JSOP_STOP);
regs.setToEndOfScript();
if (entryFrame != regs.fp())
goto inline_return;

View File

@ -455,11 +455,6 @@ js::num_parseInt(JSContext *cx, unsigned argc, Value *vp)
return true;
}
const char js_isNaN_str[] = "isNaN";
const char js_isFinite_str[] = "isFinite";
const char js_parseFloat_str[] = "parseFloat";
const char js_parseInt_str[] = "parseInt";
static JSFunctionSpec number_functions[] = {
JS_FN(js_isNaN_str, num_isNaN, 1,0),
JS_FN(js_isFinite_str, num_isFinite, 1,0),

View File

@ -1392,11 +1392,6 @@ js_PropertyIsEnumerable(JSContext *cx, JSObject *obj, jsid id, Value *vp)
#if OLD_GETTER_SETTER_METHODS
const char js_defineGetter_str[] = "__defineGetter__";
const char js_defineSetter_str[] = "__defineSetter__";
const char js_lookupGetter_str[] = "__lookupGetter__";
const char js_lookupSetter_str[] = "__lookupSetter__";
enum DefineType { Getter, Setter };
template<DefineType Type>
@ -2674,14 +2669,6 @@ obj_isSealed(JSContext *cx, unsigned argc, Value *vp)
return true;
}
#if JS_HAS_OBJ_WATCHPOINT
const char js_watch_str[] = "watch";
const char js_unwatch_str[] = "unwatch";
#endif
const char js_hasOwnProperty_str[] = "hasOwnProperty";
const char js_isPrototypeOf_str[] = "isPrototypeOf";
const char js_propertyIsEnumerable_str[] = "propertyIsEnumerable";
JSFunctionSpec object_methods[] = {
#if JS_HAS_TOSOURCE
JS_FN(js_toSource_str, obj_toSource, 0,0),

View File

@ -372,16 +372,6 @@ str_uneval(JSContext *cx, unsigned argc, Value *vp)
}
#endif
const char js_escape_str[] = "escape";
const char js_unescape_str[] = "unescape";
#if JS_HAS_UNEVAL
const char js_uneval_str[] = "uneval";
#endif
const char js_decodeURI_str[] = "decodeURI";
const char js_encodeURI_str[] = "encodeURI";
const char js_decodeURIComponent_str[] = "decodeURIComponent";
const char js_encodeURIComponent_str[] = "encodeURIComponent";
static JSFunctionSpec string_functions[] = {
JS_FN(js_escape_str, str_escape, 1,0),
JS_FN(js_unescape_str, str_unescape, 1,0),

View File

@ -139,8 +139,6 @@ js_LeaveLocalRootScopeWithResult(JSContext *cx, void *rval)
* Random utilities and global functions.
*/
const char js_AttributeName_str[] = "AttributeName";
const char js_isXMLName_str[] = "isXMLName";
const char js_XMLList_str[] = "XMLList";
const char js_localName_str[] = "localName";
const char js_xml_parent_str[] = "parent";
const char js_prefix_str[] = "prefix";

View File

@ -565,7 +565,7 @@ js_InternalThrow(VMFrame &f)
// property.
JS_ASSERT(!f.fp()->finishedInInterpreter());
UnwindScope(cx, 0);
f.regs.sp = f.fp()->base();
f.regs.setToEndOfScript();
if (cx->compartment->debugMode()) {
// This can turn a throw or error into a healthy return. Note that

View File

@ -1076,6 +1076,9 @@ mjit::EnterMethodJIT(JSContext *cx, StackFrame *fp, void *code, Value *stackLimi
return ok ? Jaeger_Returned : Jaeger_Throwing;
}
cx->regs().refreshFramePointer(fp);
cx->regs().setToEndOfScript();
/* The entry frame should have finished. */
JS_ASSERT(fp == cx->fp());

View File

@ -484,11 +484,16 @@ StackSpace::markFrameSlots(JSTracer *trc, StackFrame *fp, Value *slotsEnd, jsbyt
for (Value *vp = slotsBegin; vp < fixedEnd; vp++) {
uint32_t slot = analyze::LocalSlot(script, vp - slotsBegin);
/* Will this slot be synced by the JIT? */
/*
* Will this slot be synced by the JIT? If not, replace with a dummy
* value with the same type tag.
*/
if (!analysis->trackSlot(slot) || analysis->liveness(slot).live(offset))
gc::MarkValueRoot(trc, vp, "vm_stack");
else
*vp = UndefinedValue();
else if (vp->isObject())
*vp = ObjectValue(fp->scopeChain()->global());
else if (vp->isString())
*vp = StringValue(trc->runtime->atomState.nullAtom);
}
gc::MarkValueRootRange(trc, fixedEnd, slotsEnd, "vm_stack");

View File

@ -42,6 +42,7 @@
#define Stack_h__
#include "jsfun.h"
#include "jsautooplen.h"
struct JSContext;
struct JSCompartment;
@ -1288,6 +1289,11 @@ class FrameRegs
fp_ = (StackFrame *) newfp;
}
/* For EnterMethodJIT: */
void refreshFramePointer(StackFrame *fp) {
fp_ = fp;
}
/* For stubs::CompileFunction, ContextStack: */
void prepareToRun(StackFrame &fp, JSScript *script) {
pc = script->code;
@ -1296,6 +1302,13 @@ class FrameRegs
inlined_ = NULL;
}
void setToEndOfScript() {
JSScript *script = fp()->script();
sp = fp()->base();
pc = script->code + script->length - JSOP_STOP_LENGTH;
JS_ASSERT(*pc == JSOP_STOP);
}
/* For pushDummyFrame: */
void initDummyFrame(StackFrame &fp) {
pc = NULL;

View File

@ -3097,6 +3097,11 @@ bool BindPropertyOp(JSContext *cx, JSObject *targetObj, Op& op,
return true;
}
extern JSBool
XPC_WN_Helper_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
extern JSBool
XPC_WN_Helper_SetProperty(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp);
bool
xpc::SandboxProxyHandler::getPropertyDescriptor(JSContext *cx, JSObject *proxy,
jsid id, bool set,
@ -3120,10 +3125,16 @@ xpc::SandboxProxyHandler::getPropertyDescriptor(JSContext *cx, JSObject *proxy,
// ops can in theory rely on, but our property op forwarder doesn't know how
// to make that happen. Since we really only need to rebind the DOM methods
// here, not rebindings holder_get and holder_set is OK.
//
// Similarly, don't mess with XPC_WN_Helper_GetProperty and
// XPC_WN_Helper_SetProperty, for the same reasons: that could confuse our
// access to expandos when we're not doing Xrays.
if (desc->getter != xpc::holder_get &&
desc->getter != XPC_WN_Helper_GetProperty &&
!BindPropertyOp(cx, obj, desc->getter, desc, id, JSPROP_GETTER))
return false;
if (desc->setter != xpc::holder_set &&
desc->setter != XPC_WN_Helper_SetProperty &&
!BindPropertyOp(cx, obj, desc->setter, desc, id, JSPROP_SETTER))
return false;
if (desc->value.isObject()) {

View File

@ -977,19 +977,17 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
flat = cache->GetWrapper();
}
XPCCallContext &ccx = lccx.GetXPCCallContext();
if (!ccx.IsValid())
return false;
// We can't simply construct a slim wrapper. Go ahead and create an
// XPCWrappedNative for this object. At this point, |flat| could be
// non-null, meaning that either we already have a wrapped native from
// the cache (which might need to be QI'd to the new interface) or that
// we found a slim wrapper that we'll have to morph.
AutoMarkingNativeInterfacePtr iface;
AutoMarkingNativeInterfacePtr iface(ccx);
if (iid) {
XPCCallContext &ccx = lccx.GetXPCCallContext();
if (!ccx.IsValid())
return false;
iface.Init(ccx);
if (Interface)
iface = *Interface;
@ -1010,10 +1008,6 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
XPCWrappedNative* wrapper;
nsRefPtr<XPCWrappedNative> strongWrapper;
if (!flat) {
XPCCallContext &ccx = lccx.GetXPCCallContext();
if (!ccx.IsValid())
return false;
rv = XPCWrappedNative::GetNewOrUsed(ccx, aHelper, xpcscope, iface,
getter_AddRefs(strongWrapper));
@ -1030,18 +1024,13 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
// a valid XPCCallContext because we checked when calling Init on
// iface.
if (iface)
wrapper->FindTearOff(lccx.GetXPCCallContext(), iface, false,
&rv);
wrapper->FindTearOff(ccx, iface, false, &rv);
else
rv = NS_OK;
} else {
NS_ASSERTION(IS_SLIM_WRAPPER(flat),
"What kind of wrapper is this?");
XPCCallContext &ccx = lccx.GetXPCCallContext();
if (!ccx.IsValid())
return false;
SLIM_LOG(("***** morphing from XPCConvert::NativeInterface2JSObject"
"(%p)\n",
static_cast<nsISupports*>(xpc_GetJSPrivate(flat))));
@ -1072,10 +1061,6 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
return true;
}
XPCCallContext &ccx = lccx.GetXPCCallContext();
if (!ccx.IsValid())
return false;
JSObject *original = flat;
if (!JS_WrapObject(ccx, &flat))
return false;

View File

@ -568,7 +568,7 @@ inline void XPCNativeSet::ASSERT_NotMarked()
inline
JSObject* XPCWrappedNativeTearOff::GetJSObjectPreserveColor() const
{
return mJSObject;
return reinterpret_cast<JSObject *>(reinterpret_cast<uintptr_t>(mJSObject) & ~1);
}
inline
@ -582,7 +582,8 @@ JSObject* XPCWrappedNativeTearOff::GetJSObject()
inline
void XPCWrappedNativeTearOff::SetJSObject(JSObject* JSObj)
{
mJSObject = JSObj;
MOZ_ASSERT(!IsMarked());
mJSObject = JSObj;
}
inline

View File

@ -299,8 +299,7 @@ XPCPerThreadData::XPCPerThreadData()
void
XPCPerThreadData::Cleanup()
{
while (mAutoRoots)
mAutoRoots->Unlink();
MOZ_ASSERT(!mAutoRoots);
NS_IF_RELEASE(mExceptionManager);
NS_IF_RELEASE(mException);
delete mJSContextStack;
@ -369,13 +368,13 @@ void XPCPerThreadData::TraceJS(JSTracer *trc)
#endif
if (mAutoRoots)
mAutoRoots->TraceJS(trc);
mAutoRoots->TraceJSAll(trc);
}
void XPCPerThreadData::MarkAutoRootsAfterJSFinalize()
{
if (mAutoRoots)
mAutoRoots->MarkAfterJSFinalize();
mAutoRoots->MarkAfterJSFinalizeAll();
}
// static

View File

@ -648,19 +648,7 @@ XPC_WN_NoHelper_Finalize(js::FreeOp *fop, JSObject *obj)
static void
TraceScopeJSObjects(JSTracer *trc, XPCWrappedNativeScope* scope)
{
NS_ASSERTION(scope, "bad scope");
JSObject* obj;
obj = scope->GetGlobalJSObjectPreserveColor();
NS_ASSERTION(obj, "bad scope JSObject");
JS_CALL_OBJECT_TRACER(trc, obj, "XPCWrappedNativeScope::mGlobalJSObject");
obj = scope->GetPrototypeJSObjectPreserveColor();
if (obj) {
JS_CALL_OBJECT_TRACER(trc, obj,
"XPCWrappedNativeScope::mPrototypeJSObject");
}
scope->TraceSelf(trc);
}
static void
@ -965,7 +953,7 @@ XPC_WN_Helper_DelProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
POST_HELPER_STUB
}
static JSBool
JSBool
XPC_WN_Helper_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
PRE_HELPER_STUB
@ -973,7 +961,7 @@ XPC_WN_Helper_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
POST_HELPER_STUB
}
static JSBool
JSBool
XPC_WN_Helper_SetProperty(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
{
PRE_HELPER_STUB

View File

@ -41,6 +41,82 @@
*
* ***** END LICENSE BLOCK ***** */
/*
* XPConnect allows JS code to manipulate C++ object and C++ code to manipulate
* JS objects. JS manipulation of C++ objects tends to be significantly more
* complex. This comment explains how it is orchestrated by XPConnect.
*
* For each C++ object to be manipulated in JS, there is a corresponding JS
* object. This is called the "flattened JS object". By default, there is an
* additional C++ object involved of type XPCWrappedNative. The XPCWrappedNative
* holds pointers to the C++ object and the flat JS object.
*
* As an optimization, some C++ objects don't have XPCWrappedNatives, although
* they still have a corresponding flattened JS object. These are called "slim
* wrappers": all the wrapping information is stored in extra fields of the C++
* object and the JS object. Slim wrappers are only used for DOM objects. As a
* deoptimization, slim wrappers can be "morphed" into XPCWrappedNatives if the
* extra fields of the XPCWrappedNative become necessary.
*
* All XPCWrappedNative objects belong to an XPCWrappedNativeScope. These scopes
* are essentially in 1:1 correspondence with JS global objects. The
* XPCWrappedNativeScope has a pointer to the JS global object. The parent of a
* flattened JS object is, by default, the global JS object corresponding to the
* wrapper's XPCWrappedNativeScope (the exception to this rule is when a
* PreCreate hook asks for a different parent; see nsIXPCScriptable below).
*
* Some C++ objects (notably DOM objects) have information associated with them
* that lists the interfaces implemented by these objects. A C++ object exposes
* this information by implementing nsIClassInfo. If a C++ object implements
* nsIClassInfo, then JS code can call its methods without needing to use
* QueryInterface first. Typically, all instances of a C++ class share the same
* nsIClassInfo instance. (That is, obj->QueryInterface(nsIClassInfo) returns
* the same result for every obj of a given class.)
*
* XPConnect tracks nsIClassInfo information in an XPCWrappedNativeProto object.
* A given XPCWrappedNativeScope will have one XPCWrappedNativeProto for each
* nsIClassInfo instance being used. The XPCWrappedNativeProto has an associated
* JS object, which is used as the prototype of all flattened JS objects created
* for C++ objects with the given nsIClassInfo.
*
* Each XPCWrappedNativeProto has a pointer to its XPCWrappedNativeScope. If an
* XPCWrappedNative wraps a C++ object with class info, then it points to its
* XPCWrappedNativeProto. Otherwise it points to its XPCWrappedNativeScope. (The
* pointers are smooshed together in a tagged union.) Either way it can reach
* its scope.
*
* In the case of slim wrappers (where there is no XPCWrappedNative), the
* flattened JS object has a pointer to the XPCWrappedNativeProto stored in a
* reserved slot.
*
* An XPCWrappedNativeProto keeps track of the set of interfaces implemented by
* the C++ object in an XPCNativeSet. (The list of interfaces is obtained by
* calling a method on the nsIClassInfo.) An XPCNativeSet is a collection of
* XPCNativeInterfaces. Each interface stores the list of members, which can be
* methods, constants, getters, or setters.
*
* An XPCWrappedNative also points to an XPCNativeSet. Initially this starts out
* the same as the XPCWrappedNativeProto's set. If there is no proto, it starts
* out as a singleton set containing nsISupports. If JS code QI's new interfaces
* outside of the existing set, the set will grow. All QueryInterface results
* are cached in XPCWrappedNativeTearOff objects, which are linked off of the
* XPCWrappedNative.
*
* Besides having class info, a C++ object may be "scriptable" (i.e., implement
* nsIXPCScriptable). This allows it to implement a more DOM-like interface,
* besides just exposing XPCOM methods and constants. An nsIXPCScriptable
* instance has hooks that correspond to all the normal JSClass hooks. Each
* nsIXPCScriptable instance is mirrored by an XPCNativeScriptableInfo in
* XPConnect. These can have pointers from XPCWrappedNativeProto and
* XPCWrappedNative (since C++ objects can have scriptable info without having
* class info).
*
* Most data in an XPCNativeScriptableInfo is shared between instances. The
* shared data is stored in an XPCNativeScriptableShared object. This type is
* important because it holds the JSClass of the flattened JS objects with the
* given scriptable info.
*/
/* All the XPConnect private declarations - only include locally. */
#ifndef xpcprivate_h___
@ -1497,6 +1573,16 @@ public:
static void
TraceJS(JSTracer* trc, XPCJSRuntime* rt);
void TraceSelf(JSTracer *trc) {
JSObject *obj = GetGlobalJSObjectPreserveColor();
MOZ_ASSERT(obj);
JS_CALL_OBJECT_TRACER(trc, obj, "XPCWrappedNativeScope::mGlobalJSObject");
JSObject *proto = GetPrototypeJSObjectPreserveColor();
if (proto)
JS_CALL_OBJECT_TRACER(trc, proto, "XPCWrappedNativeScope::mPrototypeJSObject");
}
static void
SuspectAllWrappers(XPCJSRuntime* rt, nsCycleCollectionTraversalCallback &cb);
@ -1704,7 +1790,7 @@ private:
class XPCNativeInterface
{
public:
public:
static XPCNativeInterface* GetNewOrUsed(XPCCallContext& ccx,
const nsIID* iid);
static XPCNativeInterface* GetNewOrUsed(XPCCallContext& ccx,
@ -1722,19 +1808,29 @@ public:
inline JSBool HasAncestor(const nsIID* iid) const;
PRUint16 GetMemberCount() const
{NS_ASSERTION(!IsMarked(), "bad"); return mMemberCount;}
XPCNativeMember* GetMemberAt(PRUint16 i)
{NS_ASSERTION(i < mMemberCount, "bad index"); return &mMembers[i];}
PRUint16 GetMemberCount() const {
return mMemberCount;
}
XPCNativeMember* GetMemberAt(PRUint16 i) {
NS_ASSERTION(i < mMemberCount, "bad index");
return &mMembers[i];
}
void DebugDump(PRInt16 depth);
#define XPC_NATIVE_IFACE_MARK_FLAG ((PRUint16)JS_BIT(15)) // only high bit of 16 is set
void Mark() {mMemberCount |= XPC_NATIVE_IFACE_MARK_FLAG;}
void Unmark() {mMemberCount &= ~XPC_NATIVE_IFACE_MARK_FLAG;}
JSBool IsMarked() const
{return 0 != (mMemberCount & XPC_NATIVE_IFACE_MARK_FLAG);}
void Mark() {
mMarked = 1;
}
void Unmark() {
mMarked = 0;
}
bool IsMarked() const {
return mMarked != 0;
}
// NOP. This is just here to make the AutoMarkingPtr code compile.
inline void TraceJS(JSTracer* trc) {}
@ -1744,15 +1840,19 @@ public:
size_t SizeOfIncludingThis(nsMallocSizeOfFun mallocSizeOf);
protected:
protected:
static XPCNativeInterface* NewInstance(XPCCallContext& ccx,
nsIInterfaceInfo* aInfo);
XPCNativeInterface(); // not implemented
XPCNativeInterface(nsIInterfaceInfo* aInfo, jsid aName)
: mInfo(aInfo), mName(aName), mMemberCount(0)
{MOZ_COUNT_CTOR(XPCNativeInterface);}
~XPCNativeInterface() {MOZ_COUNT_DTOR(XPCNativeInterface);}
: mInfo(aInfo), mName(aName), mMemberCount(0), mMarked(0)
{
MOZ_COUNT_CTOR(XPCNativeInterface);
}
~XPCNativeInterface() {
MOZ_COUNT_DTOR(XPCNativeInterface);
}
void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
@ -1762,8 +1862,9 @@ protected:
private:
nsCOMPtr<nsIInterfaceInfo> mInfo;
jsid mName;
PRUint16 mMemberCount;
XPCNativeMember mMembers[1]; // always last - object sized for array
PRUint16 mMemberCount : 15;
PRUint16 mMarked : 1;
XPCNativeMember mMembers[1]; // always last - object sized for array
};
/***************************************************************************/
@ -1821,7 +1922,7 @@ private:
class XPCNativeSet
{
public:
public:
static XPCNativeSet* GetNewOrUsed(XPCCallContext& ccx, const nsIID* iid);
static XPCNativeSet* GetNewOrUsed(XPCCallContext& ccx,
nsIClassInfo* classInfo);
@ -1864,10 +1965,15 @@ public:
inline XPCNativeInterface* FindNamedInterface(jsid name) const;
PRUint16 GetMemberCount() const {return mMemberCount;}
PRUint16 GetInterfaceCount() const
{NS_ASSERTION(!IsMarked(), "bad"); return mInterfaceCount;}
XPCNativeInterface** GetInterfaceArray() {return mInterfaces;}
PRUint16 GetMemberCount() const {
return mMemberCount;
}
PRUint16 GetInterfaceCount() const {
return mInterfaceCount;
}
XPCNativeInterface **GetInterfaceArray() {
return mInterfaces;
}
XPCNativeInterface* GetInterfaceAt(PRUint16 i)
{NS_ASSERTION(i < mInterfaceCount, "bad index"); return mInterfaces[i];}
@ -1883,12 +1989,18 @@ public:
inline void TraceJS(JSTracer* trc) {}
inline void AutoTrace(JSTracer* trc) {}
private:
void MarkSelfOnly() {mInterfaceCount |= XPC_NATIVE_SET_MARK_FLAG;}
public:
void Unmark() {mInterfaceCount &= ~XPC_NATIVE_SET_MARK_FLAG;}
JSBool IsMarked() const
{return 0 != (mInterfaceCount & XPC_NATIVE_SET_MARK_FLAG);}
private:
void MarkSelfOnly() {
mMarked = 1;
}
public:
void Unmark() {
mMarked = 0;
}
bool IsMarked() const {
return !!mMarked;
}
#ifdef DEBUG
inline void ASSERT_NotMarked();
@ -1900,20 +2012,27 @@ public:
size_t SizeOfIncludingThis(nsMallocSizeOfFun mallocSizeOf);
protected:
protected:
static XPCNativeSet* NewInstance(XPCCallContext& ccx,
XPCNativeInterface** array,
PRUint16 count);
static XPCNativeSet* NewInstanceMutate(XPCNativeSet* otherSet,
XPCNativeInterface* newInterface,
PRUint16 position);
XPCNativeSet() {MOZ_COUNT_CTOR(XPCNativeSet);}
~XPCNativeSet() {MOZ_COUNT_DTOR(XPCNativeSet);}
XPCNativeSet()
: mMemberCount(0), mInterfaceCount(0), mMarked(0)
{
MOZ_COUNT_CTOR(XPCNativeSet);
}
~XPCNativeSet() {
MOZ_COUNT_DTOR(XPCNativeSet);
}
void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
private:
private:
PRUint16 mMemberCount;
PRUint16 mInterfaceCount;
PRUint16 mInterfaceCount : 15;
PRUint16 mMarked : 1;
XPCNativeInterface* mInterfaces[1]; // always last - object sized for array
};
@ -2254,14 +2373,22 @@ public:
void DebugDump(PRInt16 depth);
void TraceJS(JSTracer* trc)
{
if (mJSProtoObject) {
JS_CALL_OBJECT_TRACER(trc, mJSProtoObject,
"XPCWrappedNativeProto::mJSProtoObject");
void TraceSelf(JSTracer *trc) {
if (mJSProtoObject)
JS_CALL_OBJECT_TRACER(trc, mJSProtoObject, "XPCWrappedNativeProto::mJSProtoObject");
}
void TraceInside(JSTracer *trc) {
if (JS_IsGCMarkingTracer(trc)) {
mSet->Mark();
if (mScriptableInfo)
mScriptableInfo->Mark();
}
if (mScriptableInfo && JS_IsGCMarkingTracer(trc))
mScriptableInfo->Mark();
}
void TraceJS(JSTracer *trc) {
TraceSelf(trc);
TraceInside(trc);
}
void WriteBarrierPre(JSRuntime* rt)
@ -2638,22 +2765,29 @@ public:
}
// Yes, we *do* need to mark the mScriptableInfo in both cases.
inline void TraceJS(JSTracer* trc)
{
if (mScriptableInfo && JS_IsGCMarkingTracer(trc))
mScriptableInfo->Mark();
if (HasProto()) GetProto()->TraceJS(trc);
inline void TraceInside(JSTracer *trc) {
if (JS_IsGCMarkingTracer(trc)) {
mSet->Mark();
if (mScriptableInfo)
mScriptableInfo->Mark();
}
if (HasProto())
GetProto()->TraceJS(trc);
JSObject* wrapper = GetWrapperPreserveColor();
if (wrapper)
JS_CALL_OBJECT_TRACER(trc, wrapper, "XPCWrappedNative::mWrapper");
if (mScriptableInfo &&
(mScriptableInfo->GetJSClass()->flags & JSCLASS_XPCONNECT_GLOBAL))
{
TraceXPCGlobal(trc, mFlatJSObject);
}
}
inline void AutoTrace(JSTracer* trc)
{
void TraceJS(JSTracer *trc) {
TraceInside(trc);
}
void TraceSelf(JSTracer *trc) {
// If this got called, we're being kept alive by someone who really
// needs us alive and whole. Do not let our mFlatJSObject go away.
// This is the only time we should be tracing our mFlatJSObject,
@ -2665,6 +2799,10 @@ public:
}
}
void AutoTrace(JSTracer *trc) {
TraceSelf(trc);
}
#ifdef DEBUG
void ASSERT_SetsNotMarked() const
{mSet->ASSERT_NotMarked();
@ -4020,140 +4158,127 @@ private:
class AutoMarkingPtr
{
public:
AutoMarkingPtr(XPCCallContext& ccx)
: mNext(nsnull), mTLS(ccx.GetThreadData()) {Link();}
AutoMarkingPtr()
: mNext(nsnull), mTLS(nsnull) {}
public:
AutoMarkingPtr(XPCCallContext& ccx) {
mRoot = ccx.GetThreadData()->GetAutoRootsAdr();
mNext = *mRoot;
*mRoot = this;
}
virtual ~AutoMarkingPtr() {Unlink();}
void Init(XPCCallContext& ccx)
{NS_ASSERTION(!mTLS, "Already init'ed!");
mTLS = ccx.GetThreadData();
Link();}
void Link()
{if (!mTLS) return;
AutoMarkingPtr** list = mTLS->GetAutoRootsAdr();
mNext = *list; *list = this;}
void Unlink()
{if (!mTLS) return;
AutoMarkingPtr** cur = mTLS->GetAutoRootsAdr();
while (*cur != this) {
NS_ASSERTION(*cur, "This object not in list!");
cur = &(*cur)->mNext;
}
*cur = mNext;
mTLS = nsnull;
virtual ~AutoMarkingPtr() {
if (mRoot) {
MOZ_ASSERT(*mRoot == this);
*mRoot = mNext;
}
}
AutoMarkingPtr* GetNext() {return mNext;}
void TraceJSAll(JSTracer* trc) {
for (AutoMarkingPtr *cur = this; cur; cur = cur->mNext)
cur->TraceJS(trc);
}
void MarkAfterJSFinalizeAll() {
for (AutoMarkingPtr *cur = this; cur; cur = cur->mNext)
cur->MarkAfterJSFinalize();
}
protected:
virtual void TraceJS(JSTracer* trc) = 0;
virtual void MarkAfterJSFinalize() = 0;
protected:
private:
AutoMarkingPtr** mRoot;
AutoMarkingPtr* mNext;
XPCPerThreadData* mTLS;
};
// More joy of macros...
template<class T>
class TypedAutoMarkingPtr : public AutoMarkingPtr
{
public:
TypedAutoMarkingPtr(XPCCallContext& ccx) : AutoMarkingPtr(ccx), mPtr(nsnull) {}
TypedAutoMarkingPtr(XPCCallContext& ccx, T* ptr) : AutoMarkingPtr(ccx), mPtr(ptr) {}
#define DEFINE_AUTO_MARKING_PTR_TYPE(class_, type_) \
class class_ : public AutoMarkingPtr \
{ \
public: \
class_ () \
: AutoMarkingPtr(), mPtr(nsnull) {} \
class_ (XPCCallContext& ccx, type_ * ptr = nsnull) \
: AutoMarkingPtr(ccx), mPtr(ptr) {} \
virtual ~ class_ () {} \
\
virtual void TraceJS(JSTracer* trc) \
{if (mPtr) { \
mPtr->TraceJS(trc); \
mPtr->AutoTrace(trc); \
} \
if (mNext) mNext->TraceJS(trc);} \
\
virtual void MarkAfterJSFinalize() \
{if (mPtr) mPtr->Mark(); \
if (mNext) mNext->MarkAfterJSFinalize();} \
\
type_ * get() const {return mPtr;} \
operator type_ *() const {return mPtr;} \
type_ * operator->() const {return mPtr;} \
\
class_ & operator =(type_ * p) \
{NS_ASSERTION(mTLS, "Hasn't been init'ed!"); \
mPtr = p; return *this;} \
\
protected: \
type_ * mPtr; \
T* get() const { return mPtr; }
operator T *() const { return mPtr; }
T* operator->() const { return mPtr; }
TypedAutoMarkingPtr<T>& operator =(T* ptr) { mPtr = ptr; return *this; }
protected:
virtual void TraceJS(JSTracer* trc)
{
if (mPtr) {
mPtr->TraceJS(trc);
mPtr->AutoTrace(trc);
}
}
virtual void MarkAfterJSFinalize()
{
if (mPtr)
mPtr->Mark();
}
private:
T* mPtr;
};
// Use the macro above to define our AutoMarking types...
typedef TypedAutoMarkingPtr<XPCNativeInterface> AutoMarkingNativeInterfacePtr;
typedef TypedAutoMarkingPtr<XPCNativeSet> AutoMarkingNativeSetPtr;
typedef TypedAutoMarkingPtr<XPCWrappedNative> AutoMarkingWrappedNativePtr;
typedef TypedAutoMarkingPtr<XPCWrappedNativeTearOff> AutoMarkingWrappedNativeTearOffPtr;
typedef TypedAutoMarkingPtr<XPCWrappedNativeProto> AutoMarkingWrappedNativeProtoPtr;
typedef TypedAutoMarkingPtr<XPCMarkableJSVal> AutoMarkingJSVal;
DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingNativeInterfacePtr, XPCNativeInterface)
DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingNativeSetPtr, XPCNativeSet)
DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingWrappedNativePtr, XPCWrappedNative)
DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingWrappedNativeTearOffPtr, XPCWrappedNativeTearOff)
DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingWrappedNativeProtoPtr, XPCWrappedNativeProto)
DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingJSVal, XPCMarkableJSVal)
template<class T>
class ArrayAutoMarkingPtr : public AutoMarkingPtr
{
public:
ArrayAutoMarkingPtr(XPCCallContext& ccx)
: AutoMarkingPtr(ccx), mPtr(nsnull), mCount(0) {}
ArrayAutoMarkingPtr(XPCCallContext& ccx, T** ptr, PRUint32 count, bool clear)
: AutoMarkingPtr(ccx), mPtr(ptr), mCount(count)
{
if (!mPtr) mCount = 0;
else if (clear) memset(mPtr, 0, mCount*sizeof(T*));
}
#define DEFINE_AUTO_MARKING_ARRAY_PTR_TYPE(class_, type_) \
class class_ : public AutoMarkingPtr \
{ \
public: \
class_ (XPCCallContext& ccx) \
: AutoMarkingPtr(ccx), mPtr(nsnull), mCount(0) {} \
class_ (XPCCallContext& ccx, type_** aPtr, PRUint32 aCount, \
bool aClear = false) \
: AutoMarkingPtr(ccx), mPtr(aPtr), mCount(aCount) \
{ \
if (!mPtr) mCount = 0; \
else if (aClear) memset(mPtr, 0, mCount*sizeof(type_*)); \
} \
virtual ~ class_ () {} \
\
virtual void TraceJS(JSTracer* trc) \
{ \
for (PRUint32 i = 0; i < mCount; ++i) { \
type_* cur = mPtr[i]; \
if (cur) { \
cur->TraceJS(trc); \
cur->AutoTrace(trc); \
} \
} \
if (mNext) mNext->TraceJS(trc); \
} \
\
virtual void MarkAfterJSFinalize() \
{ \
for (PRUint32 i = 0; i < mCount; ++i) { \
type_* cur = mPtr[i]; \
if (cur) \
cur->Mark(); \
} \
if (mNext) mNext->MarkAfterJSFinalize(); \
} \
\
type_ ** get() const {return mPtr;} \
operator type_ **() const {return mPtr;} \
type_ ** operator->() const {return mPtr;} \
\
class_ & operator =(const class_ & inst) \
{mPtr = inst.mPtr; mCount = inst.mCount; return *this;} \
\
protected: \
type_ ** mPtr; \
PRUint32 mCount; \
T** get() const { return mPtr; }
operator T **() const { return mPtr; }
T** operator->() const { return mPtr; }
ArrayAutoMarkingPtr<T>& operator =(const ArrayAutoMarkingPtr<T> &other)
{
mPtr = other.mPtr;
mCount = other.mCount;
return *this;
}
protected:
virtual void TraceJS(JSTracer* trc)
{
for (PRUint32 i = 0; i < mCount; i++) {
if (mPtr[i]) {
mPtr[i]->TraceJS(trc);
mPtr[i]->AutoTrace(trc);
}
}
}
virtual void MarkAfterJSFinalize()
{
for (PRUint32 i = 0; i < mCount; i++) {
if (mPtr[i])
mPtr[i]->Mark();
}
}
private:
T** mPtr;
PRUint32 mCount;
};
DEFINE_AUTO_MARKING_ARRAY_PTR_TYPE(AutoMarkingNativeInterfacePtrArrayPtr,
XPCNativeInterface)
typedef ArrayAutoMarkingPtr<XPCNativeInterface> AutoMarkingNativeInterfacePtrArrayPtr;
// Note: It looked like I would need one of these AutoMarkingPtr types for
// XPCNativeScriptableInfo in order to manage marking its

View File

@ -27,8 +27,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=726949
is(t, window.top, "Should have gotten the right thing back");
desc = Cu.evalInSandbox('Object.getOwnPropertyDescriptor(Object.getPrototypeOf(this), "Cu")', s);
isnot(desc, undefined,
"Should have an own 'Cu' property");
is(desc.value, Cu, "Should have the right value");
"Should have an own 'Cu' property");
is(desc.value, Cu, "Should have the right value");
var loc = Cu.evalInSandbox('location', s);
is(loc.href, location.href, "Should have the right location");
} catch (e) {
ok(false, "Should not get an exception: " + e);
}

View File

@ -374,10 +374,6 @@ nsFileControlFrame::CaptureMouseListener::HandleEvent(nsIDOMEvent* aMouseEvent)
rv = capturePicker->Init(win, title, mMode);
NS_ENSURE_SUCCESS(rv, rv);
// Tell our text control frame to remember the currently focused value.
nsTextControlFrame* textControlFrame = mFrame->GetTextControlFrame();
textControlFrame->InitFocusedValue();
// Show dialog
PRUint32 result;
rv = capturePicker->Show(&result);
@ -408,16 +404,15 @@ nsFileControlFrame::CaptureMouseListener::HandleEvent(nsIDOMEvent* aMouseEvent)
// uneditable text box with the file name inside.
// Set new selected files
if (newFiles.Count()) {
// Tell our text control frame that this update of the value is a user
// Tell our input element that this update of the value is a user
// initiated change. Otherwise it'll think that the value is being set by
// a script and not fire onchange when it should.
bool oldState = textControlFrame->GetFireChangeEventState();
textControlFrame->SetFireChangeEventState(true);
inputElement->SetFiles(newFiles, true);
textControlFrame->SetFireChangeEventState(oldState);
// May need to fire an onchange here
textControlFrame->CheckFireOnChange();
inputElement->SetFiles(newFiles, true);
// Should fire a change event here since the SetFiles() call above ensures
// a different value from the mFocusedValue of the inputElement.
inputElement->FireChangeEventIfNeeded();
}
return NS_OK;
@ -478,12 +473,9 @@ nsFileControlFrame::BrowseMouseListener::HandleEvent(nsIDOMEvent* aEvent)
nsCOMPtr<nsIDOMFileList> fileList;
dataTransfer->GetFiles(getter_AddRefs(fileList));
nsTextControlFrame* textControlFrame = mFrame->GetTextControlFrame();
bool oldState = textControlFrame->GetFireChangeEventState();
textControlFrame->SetFireChangeEventState(true);
inputElement->SetFiles(fileList, true);
textControlFrame->SetFireChangeEventState(oldState);
textControlFrame->CheckFireOnChange();
inputElement->FireChangeEventIfNeeded();
}
return NS_OK;

View File

@ -113,8 +113,8 @@ protected:
public:
NS_DECL_ISUPPORTS
MouseListener(nsFileControlFrame* aFrame) :
mFrame(aFrame)
MouseListener(nsFileControlFrame* aFrame)
: mFrame(aFrame)
{}
void ForgetFrame() {
@ -148,15 +148,21 @@ protected:
class CaptureMouseListener: public MouseListener {
public:
CaptureMouseListener(nsFileControlFrame* aFrame) : MouseListener(aFrame),
mMode(0) {};
CaptureMouseListener(nsFileControlFrame* aFrame)
: MouseListener(aFrame)
, mMode(0)
{}
NS_DECL_NSIDOMEVENTLISTENER
PRUint32 mMode;
};
class BrowseMouseListener: public MouseListener {
public:
BrowseMouseListener(nsFileControlFrame* aFrame) : MouseListener(aFrame) {};
BrowseMouseListener(nsFileControlFrame* aFrame)
: MouseListener(aFrame)
{}
NS_DECL_NSIDOMEVENTLISTENER
static bool IsValidDropData(nsIDOMDragEvent* aEvent);

View File

@ -60,11 +60,6 @@ public:
NS_IMETHOD GetTextLength(PRInt32* aTextLength) = 0;
/**
* Fire onChange if the value has changed since it was focused or since it
* was last fired.
*/
NS_IMETHOD CheckFireOnChange() = 0;
NS_IMETHOD SetSelectionStart(PRInt32 aSelectionStart) = 0;
NS_IMETHOD SetSelectionEnd(PRInt32 aSelectionEnd) = 0;

View File

@ -169,7 +169,6 @@ nsTextControlFrame::nsTextControlFrame(nsIPresShell* aShell, nsStyleContext* aCo
: nsStackFrame(aShell, aContext)
, mUseEditor(false)
, mIsProcessing(false)
, mFireChangeEventState(false)
#ifdef DEBUG
, mInEditorInitialization(false)
#endif
@ -699,8 +698,6 @@ void nsTextControlFrame::SetFocus(bool aOn, bool aRepaint)
}
}
InitFocusedValue();
nsCOMPtr<nsISelection> ourSel;
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
getter_AddRefs(ourSel));
@ -1381,28 +1378,6 @@ nsTextControlFrame::GetMaxLength(PRInt32* aSize)
return false;
}
nsresult
nsTextControlFrame::InitFocusedValue()
{
return GetText(mFocusedValue);
}
NS_IMETHODIMP
nsTextControlFrame::CheckFireOnChange()
{
nsString value;
GetText(value);
if (!mFocusedValue.Equals(value))
{
mFocusedValue = value;
// Dispatch the change event.
nsContentUtils::DispatchTrustedEvent(mContent->OwnerDoc(), mContent,
NS_LITERAL_STRING("change"), true,
false);
}
return NS_OK;
}
// END IMPLEMENTING NS_IFORMCONTROLFRAME
NS_IMETHODIMP

View File

@ -143,7 +143,6 @@ public:
NS_IMETHOD GetEditor(nsIEditor **aEditor);
NS_IMETHOD GetTextLength(PRInt32* aTextLength);
NS_IMETHOD CheckFireOnChange();
NS_IMETHOD SetSelectionStart(PRInt32 aSelectionStart);
NS_IMETHOD SetSelectionEnd(PRInt32 aSelectionEnd);
NS_IMETHOD SetSelectionRange(PRInt32 aSelectionStart,
@ -192,18 +191,6 @@ public:
public: //for methods who access nsTextControlFrame directly
void SetValueChanged(bool aValueChanged);
/** Called when the frame is focused, to remember the value for onChange. */
nsresult InitFocusedValue();
void SetFireChangeEventState(bool aNewState)
{
mFireChangeEventState = aNewState;
}
bool GetFireChangeEventState() const
{
return mFireChangeEventState;
}
// called by the focus listener
nsresult MaybeBeginSecureKeyboardInput();
@ -212,16 +199,9 @@ public: //for methods who access nsTextControlFrame directly
NS_STACK_CLASS class ValueSetter {
public:
ValueSetter(nsTextControlFrame* aFrame,
nsIEditor* aEditor,
bool aHasFocusValue)
nsIEditor* aEditor)
: mFrame(aFrame)
, mEditor(aEditor)
// This method isn't used for user-generated changes, except for calls
// from nsFileControlFrame which sets mFireChangeEventState==true and
// restores it afterwards (ie. we want 'change' events for those changes).
// Focused value must be updated to prevent incorrect 'change' events,
// but only if user hasn't changed the value.
, mFocusValueInit(!mFrame->mFireChangeEventState && aHasFocusValue)
, mCanceled(false)
{
MOZ_ASSERT(aFrame);
@ -244,17 +224,11 @@ public: //for methods who access nsTextControlFrame directly
if (mCanceled) {
return;
}
if (mFocusValueInit) {
// Reset mFocusedValue so the onchange event doesn't fire incorrectly.
mFrame->InitFocusedValue();
}
}
private:
nsTextControlFrame* mFrame;
nsCOMPtr<nsIEditor> mEditor;
bool mFocusValueInit;
bool mOuterTransaction;
bool mCanceled;
};
@ -415,9 +389,6 @@ private:
// these packed bools could instead use the high order bits on mState, saving 4 bytes
bool mUseEditor;
bool mIsProcessing;
// Calls to SetValue will be treated as user values (i.e. trigger onChange
// eventually) when mFireChangeEventState==true, this is used by nsFileControlFrame.
bool mFireChangeEventState;
// Keep track if we have asked a placeholder node creation.
bool mUsePlaceholder;
@ -426,7 +397,6 @@ private:
friend class EditorInitializerEntryTracker;
#endif
nsString mFocusedValue;
nsRevocableEventPtr<ScrollOnFocusEvent> mScrollEvent;
};

View File

@ -190,15 +190,17 @@ public abstract class Layer {
public static class RenderContext {
public final RectF viewport;
public final FloatSize pageSize;
public final IntSize screenSize;
public final float zoomFactor;
public final int positionHandle;
public final int textureHandle;
public final FloatBuffer coordBuffer;
public RenderContext(RectF aViewport, FloatSize aPageSize, float aZoomFactor,
public RenderContext(RectF aViewport, FloatSize aPageSize, IntSize aScreenSize, float aZoomFactor,
int aPositionHandle, int aTextureHandle, FloatBuffer aCoordBuffer) {
viewport = aViewport;
pageSize = aPageSize;
screenSize = aScreenSize;
zoomFactor = aZoomFactor;
positionHandle = aPositionHandle;
textureHandle = aTextureHandle;

View File

@ -124,6 +124,9 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
private int mSampleHandle;
private int mTMatrixHandle;
private int mSurfaceWidth;
private int mSurfaceHeight;
// column-major matrix applied to each vertex to shift the viewport from
// one ranging from (-1, -1),(1,1) to (0,0),(1,1) and to scale all sizes by
// a factor of 2 to fill up the screen
@ -344,11 +347,14 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
}
private RenderContext createContext(RectF viewport, FloatSize pageSize, float zoomFactor) {
return new RenderContext(viewport, pageSize, zoomFactor, mPositionHandle, mTextureHandle,
return new RenderContext(viewport, pageSize, new IntSize(mSurfaceWidth, mSurfaceHeight), zoomFactor, mPositionHandle, mTextureHandle,
mCoordBuffer);
}
public void onSurfaceChanged(GL10 gl, final int width, final int height) {
mSurfaceWidth = width;
mSurfaceHeight = height;
GLES20.glViewport(0, 0, width, height);
if (mFrameRateLayer != null) {

View File

@ -157,7 +157,12 @@ public class PluginLayer extends TileLayer
// Viewport has changed from the last update
if (mLastViewport != null && mSurfaceView != null && !mShowPlaceholder && sUsePlaceholder) {
// Attempt to figure out if this is a full page plugin or near to it. If so, we don't show the placeholder because
// it just performs badly (flickering).
boolean fullPagePlugin = (mLayoutParams.width >= (context.screenSize.width * 0.90f) ||
mLayoutParams.height >= (context.screenSize.height * 0.90f));
if (!fullPagePlugin && mLastViewport != null && mSurfaceView != null && !mShowPlaceholder && sUsePlaceholder) {
// We have a SurfaceView that we can snapshot for a placeholder, and we are
// not currently showing a placeholder.

View File

@ -414,8 +414,7 @@ nsHttpConnection::SetupNPN(PRUint8 caps)
mNPNComplete = true;
if (mConnInfo->UsingSSL() &&
!mConnInfo->UsingHttpProxy()) {
if (mConnInfo->UsingSSL()) {
LOG(("nsHttpConnection::SetupNPN Setting up "
"Next Protocol Negotiation"));
nsCOMPtr<nsISupports> securityInfo;

View File

@ -1193,7 +1193,6 @@ nsHttpConnectionMgr::RestrictConnections(nsConnectionEntry *ent)
bool doRestrict = ent->mConnInfo->UsingSSL() &&
gHttpHandler->IsSpdyEnabled() &&
!ent->mConnInfo->UsingHttpProxy() &&
(!ent->mTestedSpdy || ent->mUsingSpdy) &&
(ent->mHalfOpens.Length() || ent->mActiveConns.Length());
@ -2273,6 +2272,13 @@ nsHttpConnectionMgr::OnMsgSpeculativeConnect(PRInt32, void *param)
nsConnectionEntry *ent =
GetOrCreateConnectionEntry(trans->ConnectionInfo());
// If spdy has previously made a preferred entry for this host via
// the ip pooling rules. If so, connect to the preferred host instead of
// the one directly passed in here.
nsConnectionEntry *preferredEntry = GetSpdyPreferredEnt(ent);
if (preferredEntry)
ent = preferredEntry;
if (!ent->mIdleConns.Length() && !RestrictConnections(ent) &&
!AtActiveConnectionLimit(ent, trans->Caps())) {
CreateTransport(ent, trans, trans->Caps(), true);
@ -2694,7 +2700,8 @@ nsHttpConnectionMgr::nsHalfOpenSocket::OnTransportStatus(nsITransport *trans,
// if we are doing spdy coalescing and haven't recorded the ip address
// for this entry before then make the hash key if our dns lookup
// just completed
// just completed. We can't do coalescing if using a proxy because the
// ip addresses are not available to the client.
if (status == nsISocketTransport::STATUS_CONNECTED_TO &&
gHttpHandler->IsSpdyEnabled() &&

View File

@ -1226,6 +1226,12 @@ nsHttpTransaction::HandleContentStart()
LOG(("this response should not contain a body.\n"));
break;
}
if (mResponseHead->Status() == 200 &&
mConnection->IsProxyConnectInProgress()) {
// successful CONNECTs do not have response bodies
mNoContent = true;
}
mConnection->SetLastTransactionExpectedNoContent(mNoContent);
if (mInvalidResponseBytesRead)
gHttpHandler->ConnMgr()->PipelineFeedbackInfo(

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,300 +0,0 @@
# This file was generated by Autom4te Sun May 1 09:53:53 UTC 2011.
# It contains the lists of macros which have been traced.
# It can be safely removed.
@request = (
bless( [
'0',
1,
[
'/usr/share/autoconf'
],
[
'/usr/share/autoconf/autoconf/autoconf.m4f',
'/usr/share/aclocal/argz.m4',
'/usr/share/aclocal/libtool.m4',
'/usr/share/aclocal/ltdl.m4',
'/usr/share/aclocal/ltoptions.m4',
'/usr/share/aclocal/ltsugar.m4',
'/usr/share/aclocal/ltversion.m4',
'/usr/share/aclocal/lt~obsolete.m4',
'/usr/share/aclocal-1.11/amversion.m4',
'/usr/share/aclocal-1.11/as.m4',
'/usr/share/aclocal-1.11/auxdir.m4',
'/usr/share/aclocal-1.11/cond.m4',
'/usr/share/aclocal-1.11/depend.m4',
'/usr/share/aclocal-1.11/depout.m4',
'/usr/share/aclocal-1.11/header.m4',
'/usr/share/aclocal-1.11/init.m4',
'/usr/share/aclocal-1.11/install-sh.m4',
'/usr/share/aclocal-1.11/lead-dot.m4',
'/usr/share/aclocal-1.11/maintainer.m4',
'/usr/share/aclocal-1.11/make.m4',
'/usr/share/aclocal-1.11/minuso.m4',
'/usr/share/aclocal-1.11/missing.m4',
'/usr/share/aclocal-1.11/mkdirp.m4',
'/usr/share/aclocal-1.11/options.m4',
'/usr/share/aclocal-1.11/runlog.m4',
'/usr/share/aclocal-1.11/sanity.m4',
'/usr/share/aclocal-1.11/silent.m4',
'/usr/share/aclocal-1.11/strip.m4',
'/usr/share/aclocal-1.11/substnot.m4',
'/usr/share/aclocal-1.11/tar.m4',
'acinclude.m4',
'configure.in'
],
{
'AM_ENABLE_STATIC' => 1,
'AC_LIBTOOL_LANG_RC_CONFIG' => 1,
'_LT_AC_SHELL_INIT' => 1,
'AC_DEFUN' => 1,
'LIBUNWIND___THREAD' => 1,
'_LT_AC_LANG_CXX_CONFIG' => 1,
'AC_PROG_LIBTOOL' => 1,
'AM_PROG_MKDIR_P' => 1,
'AM_AUTOMAKE_VERSION' => 1,
'AM_SUBST_NOTMAKE' => 1,
'AM_MISSING_PROG' => 1,
'AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH' => 1,
'_LT_AC_LANG_C_CONFIG' => 1,
'AM_PROG_INSTALL_STRIP' => 1,
'_m4_warn' => 1,
'AC_LIBTOOL_OBJDIR' => 1,
'gl_FUNC_ARGZ' => 1,
'LTOBSOLETE_VERSION' => 1,
'AM_SANITY_CHECK' => 1,
'AC_LIBTOOL_LANG_GCJ_CONFIG' => 1,
'AC_LIBTOOL_PROG_COMPILER_PIC' => 1,
'LT_LIB_M' => 1,
'_LT_AC_CHECK_DLFCN' => 1,
'AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE' => 1,
'LTSUGAR_VERSION' => 1,
'_LT_PROG_LTMAIN' => 1,
'LT_SYS_SYMBOL_USCORE' => 1,
'_AM_PROG_TAR' => 1,
'AC_LIBTOOL_GCJ' => 1,
'_LT_WITH_SYSROOT' => 1,
'LT_SYS_DLOPEN_DEPLIBS' => 1,
'LT_FUNC_DLSYM_USCORE' => 1,
'AC_LIBTOOL_CONFIG' => 1,
'_LT_AC_LANG_F77' => 1,
'AC_LTDL_DLLIB' => 1,
'_AM_SUBST_NOTMAKE' => 1,
'_AM_AUTOCONF_VERSION' => 1,
'AM_DISABLE_SHARED' => 1,
'_LT_PROG_ECHO_BACKSLASH' => 1,
'_LTDL_SETUP' => 1,
'_LT_AC_LANG_CXX' => 1,
'AM_PROG_LIBTOOL' => 1,
'AM_PROG_LD' => 1,
'_LT_AC_FILE_LTDLL_C' => 1,
'AC_LIB_LTDL' => 1,
'AU_DEFUN' => 1,
'AC_PROG_NM' => 1,
'AC_LIBTOOL_DLOPEN' => 1,
'AC_PROG_LD' => 1,
'AC_PROG_LD_GNU' => 1,
'AC_ENABLE_FAST_INSTALL' => 1,
'AC_LIBTOOL_FC' => 1,
'LTDL_CONVENIENCE' => 1,
'_AM_SET_OPTION' => 1,
'AC_LTDL_PREOPEN' => 1,
'_LT_LINKER_BOILERPLATE' => 1,
'_LT_PREPARE_SED_QUOTE_VARS' => 1,
'AC_LIBTOOL_LANG_CXX_CONFIG' => 1,
'AC_LIBTOOL_PROG_CC_C_O' => 1,
'gl_PREREQ_ARGZ' => 1,
'LT_SUPPORTED_TAG' => 1,
'AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
'LT_PROG_RC' => 1,
'LT_SYS_MODULE_EXT' => 1,
'AC_DEFUN_ONCE' => 1,
'_LT_AC_LANG_GCJ' => 1,
'AC_LTDL_OBJDIR' => 1,
'_LT_PATH_TOOL_PREFIX' => 1,
'AC_LIBTOOL_RC' => 1,
'_LT_AC_PROG_ECHO_BACKSLASH' => 1,
'AC_DISABLE_FAST_INSTALL' => 1,
'AM_SILENT_RULES' => 1,
'include' => 1,
'_LT_AC_TRY_DLOPEN_SELF' => 1,
'_LT_AC_SYS_LIBPATH_AIX' => 1,
'LT_AC_PROG_SED' => 1,
'AM_ENABLE_SHARED' => 1,
'LTDL_INSTALLABLE' => 1,
'_LT_AC_LANG_GCJ_CONFIG' => 1,
'AC_ENABLE_SHARED' => 1,
'CHECK_ATOMIC_OPS' => 1,
'_LT_REQUIRED_DARWIN_CHECKS' => 1,
'AC_LIBTOOL_SYS_HARD_LINK_LOCKS' => 1,
'AC_ENABLE_STATIC' => 1,
'AM_PROG_CC_C_O' => 1,
'_LT_AC_TAGVAR' => 1,
'AC_LIBTOOL_LANG_F77_CONFIG' => 1,
'AM_CONDITIONAL' => 1,
'LT_LIB_DLLOAD' => 1,
'LTVERSION_VERSION' => 1,
'_LT_PROG_CXX' => 1,
'_LT_PROG_F77' => 1,
'LTDL_INIT' => 1,
'm4_include' => 1,
'AM_PROG_INSTALL_SH' => 1,
'AC_PROG_EGREP' => 1,
'AC_PATH_MAGIC' => 1,
'_AC_AM_CONFIG_HEADER_HOOK' => 1,
'AC_LTDL_SYSSEARCHPATH' => 1,
'AM_MAKE_INCLUDE' => 1,
'LT_CMD_MAX_LEN' => 1,
'_LT_AC_TAGCONFIG' => 1,
'm4_pattern_forbid' => 1,
'_LT_LINKER_OPTION' => 1,
'AC_LIBTOOL_COMPILER_OPTION' => 1,
'AC_DISABLE_SHARED' => 1,
'_LT_COMPILER_BOILERPLATE' => 1,
'AC_LIBTOOL_WIN32_DLL' => 1,
'AC_LIBTOOL_SETUP' => 1,
'AC_PROG_LD_RELOAD_FLAG' => 1,
'AC_LTDL_DLSYM_USCORE' => 1,
'AM_MISSING_HAS_RUN' => 1,
'LT_LANG' => 1,
'LT_SYS_DLSEARCH_PATH' => 1,
'LT_CONFIG_LTDL_DIR' => 1,
'AC_LIBTOOL_DLOPEN_SELF' => 1,
'LT_OUTPUT' => 1,
'AC_LIBTOOL_PROG_LD_SHLIBS' => 1,
'AC_WITH_LTDL' => 1,
'AC_LIBTOOL_LINKER_OPTION' => 1,
'LT_AC_PROG_RC' => 1,
'AC_LIBTOOL_CXX' => 1,
'LT_INIT' => 1,
'LT_AC_PROG_GCJ' => 1,
'LT_SYS_DLOPEN_SELF' => 1,
'_LT_AC_PROG_CXXCPP' => 1,
'AM_DEP_TRACK' => 1,
'AM_DISABLE_STATIC' => 1,
'AM_CONFIG_HEADER' => 1,
'_AC_PROG_LIBTOOL' => 1,
'_AM_IF_OPTION' => 1,
'AC_PATH_TOOL_PREFIX' => 1,
'm4_pattern_allow' => 1,
'AC_LIBTOOL_F77' => 1,
'AM_SET_LEADING_DOT' => 1,
'_LT_PROG_FC' => 1,
'LT_AC_PROG_EGREP' => 1,
'_AM_DEPENDENCIES' => 1,
'AC_LIBTOOL_LANG_C_CONFIG' => 1,
'LTOPTIONS_VERSION' => 1,
'_LT_AC_SYS_COMPILER' => 1,
'AM_PROG_NM' => 1,
'AC_LIBLTDL_CONVENIENCE' => 1,
'AC_DEPLIBS_CHECK_METHOD' => 1,
'AC_LIBLTDL_INSTALLABLE' => 1,
'jm_MAINTAINER_MODE' => 1,
'AM_SET_CURRENT_AUTOMAKE_VERSION' => 1,
'AC_LTDL_ENABLE_INSTALL' => 1,
'LT_PROG_GCJ' => 1,
'AC_LIBTOOL_SYS_DYNAMIC_LINKER' => 1,
'AM_INIT_AUTOMAKE' => 1,
'AC_DISABLE_STATIC' => 1,
'LT_PATH_NM' => 1,
'AM_MAINTAINER_MODE' => 1,
'AC_LTDL_SHLIBEXT' => 1,
'_LT_AC_LOCK' => 1,
'_LT_AC_LANG_RC_CONFIG' => 1,
'LT_SYS_MODULE_PATH' => 1,
'LT_WITH_LTDL' => 1,
'AC_LIBTOOL_POSTDEP_PREDEP' => 1,
'AC_LTDL_SHLIBPATH' => 1,
'AM_PROG_AS' => 1,
'AM_AUX_DIR_EXPAND' => 1,
'AC_LIBTOOL_PROG_COMPILER_NO_RTTI' => 1,
'_LT_AC_LANG_F77_CONFIG' => 1,
'_LT_COMPILER_OPTION' => 1,
'_AM_SET_OPTIONS' => 1,
'AM_RUN_LOG' => 1,
'_AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
'AC_LIBTOOL_PICMODE' => 1,
'AC_LTDL_SYS_DLOPEN_DEPLIBS' => 1,
'AC_LIBTOOL_SYS_OLD_ARCHIVE' => 1,
'AC_CHECK_LIBM' => 1,
'LT_PATH_LD' => 1,
'AC_LIBTOOL_SYS_LIB_STRIP' => 1,
'_AM_MANGLE_OPTION' => 1,
'AC_LIBTOOL_SYS_MAX_CMD_LEN' => 1,
'AC_LTDL_SYMBOL_USCORE' => 1,
'AM_SET_DEPDIR' => 1,
'_LT_CC_BASENAME' => 1,
'_LT_LIBOBJ' => 1
}
], 'Autom4te::Request' ),
bless( [
'1',
1,
[
'/usr/share/autoconf'
],
[
'/usr/share/autoconf/autoconf/autoconf.m4f',
'aclocal.m4',
'configure.in'
],
{
'_LT_AC_TAGCONFIG' => 1,
'AM_PROG_F77_C_O' => 1,
'm4_pattern_forbid' => 1,
'AC_INIT' => 1,
'_AM_COND_IF' => 1,
'AC_CANONICAL_TARGET' => 1,
'AC_SUBST' => 1,
'AC_CONFIG_LIBOBJ_DIR' => 1,
'AC_FC_SRCEXT' => 1,
'AC_CANONICAL_HOST' => 1,
'AC_PROG_LIBTOOL' => 1,
'AM_INIT_AUTOMAKE' => 1,
'AM_PATH_GUILE' => 1,
'AC_CONFIG_SUBDIRS' => 1,
'AM_AUTOMAKE_VERSION' => 1,
'LT_CONFIG_LTDL_DIR' => 1,
'AC_REQUIRE_AUX_FILE' => 1,
'AC_CONFIG_LINKS' => 1,
'm4_sinclude' => 1,
'LT_SUPPORTED_TAG' => 1,
'AM_MAINTAINER_MODE' => 1,
'AM_NLS' => 1,
'AM_GNU_GETTEXT_INTL_SUBDIR' => 1,
'AM_MAKEFILE_INCLUDE' => 1,
'_m4_warn' => 1,
'AM_PROG_CXX_C_O' => 1,
'_AM_COND_ENDIF' => 1,
'_AM_MAKEFILE_INCLUDE' => 1,
'AM_ENABLE_MULTILIB' => 1,
'AM_SILENT_RULES' => 1,
'AM_PROG_MOC' => 1,
'AC_CONFIG_FILES' => 1,
'LT_INIT' => 1,
'include' => 1,
'AM_PROG_AR' => 1,
'AM_GNU_GETTEXT' => 1,
'AC_LIBSOURCE' => 1,
'AM_PROG_FC_C_O' => 1,
'AC_CANONICAL_BUILD' => 1,
'AC_FC_FREEFORM' => 1,
'AH_OUTPUT' => 1,
'_AM_SUBST_NOTMAKE' => 1,
'AC_CONFIG_AUX_DIR' => 1,
'sinclude' => 1,
'AM_PROG_CC_C_O' => 1,
'm4_pattern_allow' => 1,
'AM_XGETTEXT_OPTION' => 1,
'AC_CANONICAL_SYSTEM' => 1,
'AM_CONDITIONAL' => 1,
'AC_CONFIG_HEADERS' => 1,
'AC_DEFINE_TRACE_LITERAL' => 1,
'AM_POT_TOOLS' => 1,
'm4_include' => 1,
'_AM_COND_ELSE' => 1,
'AC_SUBST_TRACE' => 1
}
], 'Autom4te::Request' )
);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -6,14 +6,13 @@ cd `dirname $0`
source upstream.info
hg rm -f src
rm -rf src
git clone "$UPSTREAM_REPO" src
cd src
git checkout "$UPSTREAM_COMMIT"
autoreconf -i
rm -rf .git .gitignore
rm -rf .git .gitignore autom4te.cache
cd ..
hg add src
hg addremove -q src
echo "libunwind has now been updated. Don't forget to run hg commit!"

View File

@ -7,14 +7,17 @@ topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = $(NULL)
# Include config.mk explicitly so we can override FINAL_TARGET.
include $(topsrcdir)/config/config.mk
# config.mk sets FINAL_TARGET to $(DIST)/bin, but we want to copy build products
# into a WebappRT-specific subdirectory, so we redefine it here.
FINAL_TARGET = $(DIST)/bin/webapprt
DIRS = $(NULL)
ifneq (,$(filter WINNT,$(OS_ARCH)))
DIRS += win
else

View File

@ -7,12 +7,12 @@ topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
# This switches $(INSTALL) to copy mode, like $(SYSINSTALL), so things that
# shouldn't get 755 perms need $(IFLAGS1) for either way of calling nsinstall.
NSDISTMODE = copy
include $(topsrcdir)/config/config.mk
PROGRAM = webapprt-stub$(BIN_SUFFIX)
CMMSRCS = webapprt.mm

View File

@ -912,6 +912,23 @@ NextPowerOfTwo(int value) {
return value + 1;
}
#define MAX_LOCK_ATTEMPTS 10
static bool LockWindowWithRetry(void* window, unsigned char** bits, int* width, int* height, int* format, int* stride)
{
int count = 0;
while (count < MAX_LOCK_ATTEMPTS) {
if (AndroidBridge::Bridge()->LockWindow(window, bits, width, height, format, stride))
return true;
count++;
usleep(500);
}
return false;
}
NS_EXPORT jobject JNICALL
Java_org_mozilla_gecko_GeckoAppShell_getSurfaceBits(JNIEnv* jenv, jclass, jobject surface)
{
@ -931,15 +948,14 @@ Java_org_mozilla_gecko_GeckoAppShell_getSurfaceBits(JNIEnv* jenv, jclass, jobjec
int srcWidth, srcHeight, format, srcStride;
// So we lock/unlock once here in order to get whatever is currently the front buffer. It sucks.
while (!AndroidBridge::Bridge()->LockWindow(window, &bits, &srcWidth, &srcHeight, &format, &srcStride)) {
usleep(1000);
}
if (!LockWindowWithRetry(window, &bits, &srcWidth, &srcHeight, &format, &srcStride))
return nsnull;
AndroidBridge::Bridge()->UnlockWindow(window);
// This is lock will result in the front buffer, since the last unlock rotated it to the back. Probably.
while (!AndroidBridge::Bridge()->LockWindow(window, &bits, &srcWidth, &srcHeight, &format, &srcStride)) {
usleep(1000);
}
if (!LockWindowWithRetry(window, &bits, &srcWidth, &srcHeight, &format, &srcStride))
return nsnull;
// These are from android.graphics.PixelFormat
int bpp;