Merge m-i to m-c

This commit is contained in:
Phil Ringnalda 2013-10-05 17:39:34 -07:00
commit f097865b72
39 changed files with 848 additions and 315 deletions

View File

@ -384,6 +384,10 @@ const kEventConstructors = {
return e;
},
},
TrackEvent: { create: function (aName, aProps) {
return new TrackEvent(aName, aProps);
},
},
TransitionEvent: { create: function (aName, aProps) {
return new TransitionEvent(aName, aProps);
},

View File

@ -1,6 +1,7 @@
<!DOCTYPE HTML>
<html>
<body>
<img id="image1" src="">
<input id="image3" type="image">
</body>
</html>

View File

@ -5,6 +5,8 @@
#include "mozilla/dom/TextTrackList.h"
#include "mozilla/dom/TextTrackListBinding.h"
#include "mozilla/dom/TrackEvent.h"
#include "nsThreadUtils.h"
namespace mozilla {
namespace dom {
@ -54,8 +56,10 @@ TextTrackList::AddTextTrack(HTMLMediaElement* aMediaElement,
{
nsRefPtr<TextTrack> track = new TextTrack(mGlobal, aMediaElement, aKind,
aLabel, aLanguage);
mTextTracks.AppendElement(track);
// TODO: dispatch addtrack event
if (mTextTracks.AppendElement(track)) {
CreateAndDispatchTrackEventRunner(track, NS_LITERAL_STRING("addtrack"));
}
return track.forget();
}
@ -73,9 +77,11 @@ TextTrackList::GetTrackById(const nsAString& aId)
}
void
TextTrackList::RemoveTextTrack(const TextTrack& aTrack)
TextTrackList::RemoveTextTrack(TextTrack& aTrack)
{
mTextTracks.RemoveElement(&aTrack);
if (mTextTracks.RemoveElement(&aTrack)) {
CreateAndDispatchTrackEventRunner(&aTrack, NS_LITERAL_STRING("removetrack"));
}
}
void
@ -86,5 +92,45 @@ TextTrackList::DidSeek()
}
}
class TrackEventRunner MOZ_FINAL: public nsRunnable
{
public:
TrackEventRunner(TextTrackList* aList, TrackEvent* aEvent)
: mList(aList)
, mEvent(aEvent)
{}
NS_IMETHOD Run() MOZ_OVERRIDE
{
return mList->DispatchTrackEvent(mEvent);
}
private:
nsRefPtr<TextTrackList> mList;
nsRefPtr<TrackEvent> mEvent;
};
nsresult
TextTrackList::DispatchTrackEvent(TrackEvent* aEvent)
{
return DispatchTrustedEvent(aEvent);
}
void
TextTrackList::CreateAndDispatchTrackEventRunner(TextTrack* aTrack,
const nsAString& aEventName)
{
TrackEventInitInitializer eventInit;
eventInit.mBubbles = false;
eventInit.mCancelable = false;
eventInit.mTrack = aTrack;
nsRefPtr<TrackEvent> trackEvent =
TrackEvent::Constructor(this, aEventName, eventInit);
// Dispatch the TrackEvent asynchronously.
nsCOMPtr<nsIRunnable> event = new TrackEventRunner(this, trackEvent);
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
}
} // namespace dom
} // namespace mozilla

View File

@ -14,6 +14,9 @@
namespace mozilla {
namespace dom {
class TrackEvent;
class TrackEventRunner;
class TextTrackList MOZ_FINAL : public nsDOMEventTargetHelper
{
public:
@ -50,15 +53,20 @@ public:
mTextTracks.AppendElement(aTextTrack);
}
void RemoveTextTrack(const TextTrack& aTrack);
void RemoveTextTrack(TextTrack& aTrack);
void DidSeek();
nsresult DispatchTrackEvent(TrackEvent* aEvent);
IMPL_EVENT_HANDLER(addtrack)
IMPL_EVENT_HANDLER(removetrack)
private:
nsCOMPtr<nsISupports> mGlobal;
nsTArray< nsRefPtr<TextTrack> > mTextTracks;
void CreateAndDispatchTrackEventRunner(TextTrack* aTrack,
const nsAString& aEventName);
};
} // namespace dom

View File

@ -145,6 +145,7 @@ MOCHITEST_FILES = \
$(filter disabled-for-intermittent-failures--bug-608634, test_error_in_video_document.html) \
test_texttrack.html \
test_texttrackcue.html \
test_trackevent.html \
test_texttrackregion.html \
test_timeupdate_small_files.html \
test_unseekable.html \

View File

@ -0,0 +1,62 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Bug 893309 - Implement TrackEvent</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["media.webvtt.enabled", true]]},
function() {
var video = document.createElement("video");
isnot(video.textTracks, undefined, "HTMLMediaElement::TextTrack() property should be available.")
ok(typeof video.addTextTrack == "function", "HTMLMediaElement::AddTextTrack() function should be available.")
var trackList = video.textTracks;
is(trackList.length, 0, "Length should be 0.");
var evtTextTrack, numOfCalls = 0;
trackList.onaddtrack = function(event) {
ok(event instanceof TrackEvent, "Fired event from onaddtrack should be a TrackEvent");
is(event.type, "addtrack", "Event type should be addtrack");
ok(event.isTrusted, "Event should be trusted!");
ok(!event.bubbles, "Event shouldn't bubble!");
ok(!event.cancelable, "Event shouldn't be cancelable!");
evtTextTrack = event.track;
ok(textTrack[numOfCalls] === evtTextTrack, "Text tracks should be the same");
is(evtTextTrack.label, label[numOfCalls], "Label should be set to "+ label[numOfCalls]);
is(evtTextTrack.language, language[numOfCalls], "Language should be " + language[numOfCalls]);
is(evtTextTrack.kind, kind[numOfCalls], "Kind should be " + kind[numOfCalls]);
if (++numOfCalls == 3) {
SimpleTest.finish();
}
};
var label = ["Oasis", "Coldplay", "t.A.T.u"];
language = ["en-CA", "en-GB", "ru" ];
kind = ["subtitles", "captions", "chapters"];
var textTrack = new Array(3);
for (var i = 0; i < 3; ++i) {
textTrack[i] = video.addTextTrack(kind[i], label[i], language[i]);
is(trackList.length, i + 1, "Length should be " + (i+1));
}
//TODO: Tests for removetrack event to be added along with bug 882677
}
);
</script>
</pre>
</body>
</html>

View File

@ -123,12 +123,14 @@ nsDSURIContentListener::DoContent(const char* aContentType,
if (rv == NS_ERROR_REMOTE_XUL) {
request->Cancel(rv);
*aAbortProcess = true;
return NS_OK;
}
if (NS_FAILED(rv)) {
// it's okay if we don't know how to handle the content
return NS_OK;
if (NS_FAILED(rv)) {
// we don't know how to handle the content
*aContentHandler = nullptr;
return rv;
}
if (loadFlags & nsIChannel::LOAD_RETARGETED_DOCUMENT_URI) {

View File

@ -44,14 +44,17 @@ WebappsRegistry.prototype = {
let app = msg.app;
switch (aMessage.name) {
case "Webapps:Install:Return:OK":
this.removeMessageListeners("Webapps:Install:Return:KO");
Services.DOMRequest.fireSuccess(req, createApplicationObject(this._window, app));
cpmm.sendAsyncMessage("Webapps:Install:Return:Ack",
{ manifestURL : app.manifestURL });
break;
case "Webapps:Install:Return:KO":
this.removeMessageListeners(aMessage.name);
Services.DOMRequest.fireError(req, msg.error || "DENIED");
break;
case "Webapps:GetSelf:Return:OK":
this.removeMessageListeners(aMessage.name);
if (msg.apps.length) {
app = msg.apps[0];
Services.DOMRequest.fireSuccess(req, createApplicationObject(this._window, app));
@ -60,9 +63,11 @@ WebappsRegistry.prototype = {
}
break;
case "Webapps:CheckInstalled:Return:OK":
this.removeMessageListeners(aMessage.name);
Services.DOMRequest.fireSuccess(req, msg.app);
break;
case "Webapps:GetInstalled:Return:OK":
this.removeMessageListeners(aMessage.name);
Services.DOMRequest.fireSuccess(req, convertAppsArray(msg.apps, this._window));
break;
}
@ -155,6 +160,7 @@ WebappsRegistry.prototype = {
let request = this.createRequest();
if (this._ensureForeground(request)) {
this.addMessageListeners("Webapps:Install:Return:KO");
cpmm.sendAsyncMessage("Webapps:Install",
this._prepareInstall(uri, request, aParams, false));
}
@ -164,6 +170,7 @@ WebappsRegistry.prototype = {
getSelf: function() {
let request = this.createRequest();
this.addMessageListeners("Webapps:GetSelf:Return:OK");
cpmm.sendAsyncMessage("Webapps:GetSelf", { origin: this._getOrigin(this._window.location.href),
appId: this._window.document.nodePrincipal.appId,
oid: this._id,
@ -176,6 +183,8 @@ WebappsRegistry.prototype = {
this._window.document.nodePrincipal.checkMayLoad(manifestURL, true, false);
let request = this.createRequest();
this.addMessageListeners("Webapps:CheckInstalled:Return:OK");
cpmm.sendAsyncMessage("Webapps:CheckInstalled", { origin: this._getOrigin(this._window.location.href),
manifestURL: manifestURL.spec,
oid: this._id,
@ -185,6 +194,7 @@ WebappsRegistry.prototype = {
getInstalled: function() {
let request = this.createRequest();
this.addMessageListeners("Webapps:GetInstalled:Return:OK");
cpmm.sendAsyncMessage("Webapps:GetInstalled", { origin: this._getOrigin(this._window.location.href),
oid: this._id,
requestID: this.getRequestId(request) });
@ -213,6 +223,7 @@ WebappsRegistry.prototype = {
let request = this.createRequest();
if (this._ensureForeground(request)) {
this.addMessageListeners("Webapps:Install:Return:KO");
cpmm.sendAsyncMessage("Webapps:InstallPackage",
this._prepareInstall(uri, request, aParams, true));
}
@ -222,10 +233,7 @@ WebappsRegistry.prototype = {
// nsIDOMGlobalPropertyInitializer implementation
init: function(aWindow) {
this.initDOMRequestHelper(aWindow, ["Webapps:Install:Return:OK", "Webapps:Install:Return:KO",
"Webapps:GetInstalled:Return:OK",
"Webapps:GetSelf:Return:OK",
"Webapps:CheckInstalled:Return:OK" ]);
this.initDOMRequestHelper(aWindow, "Webapps:Install:Return:OK");
let util = this._window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
@ -338,16 +346,15 @@ WebappsApplication.prototype = {
this._downloadError = null;
this.initDOMRequestHelper(aWindow, ["Webapps:OfflineCache",
"Webapps:CheckForUpdate:Return:OK",
"Webapps:CheckForUpdate:Return:KO",
"Webapps:Launch:Return:OK",
"Webapps:Launch:Return:KO",
"Webapps:PackageEvent",
"Webapps:ClearBrowserData:Return",
"Webapps:Connect:Return:OK",
"Webapps:Connect:Return:KO",
"Webapps:GetConnections:Return:OK"]);
this.initDOMRequestHelper(aWindow, [
"Webapps:OfflineCache",
"Webapps:CheckForUpdate:Return:OK",
"Webapps:CheckForUpdate:Return:KO",
"Webapps:PackageEvent",
"Webapps:Connect:Return:OK",
"Webapps:Connect:Return:KO",
"Webapps:GetConnections:Return:OK"
]);
cpmm.sendAsyncMessage("Webapps:RegisterForMessages",
{
@ -441,6 +448,8 @@ WebappsApplication.prototype = {
launch: function(aStartPoint) {
let request = this.createRequest();
this.addMessageListeners(["Webapps:Launch:Return:OK",
"Webapps:Launch:Return:KO"]);
cpmm.sendAsyncMessage("Webapps:Launch", { origin: this.origin,
manifestURL: this.manifestURL,
startPoint: aStartPoint || "",
@ -455,6 +464,7 @@ WebappsApplication.prototype = {
let browserChild =
BrowserElementPromptService.getBrowserElementChildForWindow(this._window);
if (browserChild) {
this.addMessageListeners("Webapps:ClearBrowserData:Return");
browserChild.messageManager.sendAsyncMessage(
"Webapps:ClearBrowserData",
{ manifestURL: this.manifestURL,
@ -536,9 +546,13 @@ WebappsApplication.prototype = {
return;
switch (aMessage.name) {
case "Webapps:Launch:Return:KO":
this.removeMessageListeners(["Webapps:Launch:Return:OK",
"Webapps:Launch:Return:KO"]);
Services.DOMRequest.fireError(req, "APP_INSTALL_PENDING");
break;
case "Webapps:Launch:Return:OK":
this.removeMessageListeners(["Webapps:Launch:Return:OK",
"Webapps:Launch:Return:KO"]);
Services.DOMRequest.fireSuccess(req, null);
break;
case "Webapps:CheckForUpdate:Return:KO":
@ -648,6 +662,7 @@ WebappsApplication.prototype = {
}
break;
case "Webapps:ClearBrowserData:Return":
this.removeMessageListeners(aMessage.name);
Services.DOMRequest.fireSuccess(req, null);
break;
case "Webapps:Connect:Return:OK":
@ -691,13 +706,14 @@ WebappsApplication.prototype = {
* mozIDOMApplicationMgmt object
*/
function WebappsApplicationMgmt(aWindow) {
this.initDOMRequestHelper(aWindow, ["Webapps:GetAll:Return:OK",
"Webapps:GetAll:Return:KO",
"Webapps:Uninstall:Return:OK",
"Webapps:Uninstall:Broadcast:Return:OK",
"Webapps:Uninstall:Return:KO",
"Webapps:Install:Return:OK",
"Webapps:GetNotInstalled:Return:OK"]);
this.initDOMRequestHelper(aWindow, [
{ name: "Webapps:GetAll:Return:OK", strongRef: true },
{ name: "Webapps:GetAll:Return:KO", strongRef: true },
{ name: "Webapps:Uninstall:Return:OK", strongRef: true },
{ name: "Webapps:Uninstall:Broadcast:Return:OK", strongRef: true },
{ name: "Webapps:Uninstall:Return:KO", strongRef: true },
{ name: "Webapps:Install:Return:OK", strongRef: true },
{ name: "Webapps:GetNotInstalled:Return:OK", strongRef: true }]);
cpmm.sendAsyncMessage("Webapps:RegisterForMessages",
{

View File

@ -52,7 +52,8 @@ function checkApp(app) {
installed(!!app);
if (app) {
var appName = "Really Rapid Release (APPTYPETOKEN)";
is(app.manifest.name, appName, "Manifest name should be correct");
var manifest = SpecialPowers.wrap(app.manifest);
is(manifest.name, appName, "Manifest name should be correct");
is(app.origin, "http://test", "App origin should be correct");
is(app.installOrigin, "http://mochi.test:8888", "Install origin should be correct");
}

View File

@ -3,12 +3,23 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* Helper object for APIs that deal with DOMRequests and Promises and need to
* release them when the window goes out of scope.
* Helper object for APIs that deal with DOMRequests and Promises.
* It allows objects inheriting from it to create and keep track of DOMRequests
* and Promises objects in the common scenario where requests are created in
* the child, handed out to content and delivered to the parent within an async
* message (containing the identifiers of these requests). The parent may send
* messages back as answers to different requests and the child will use this
* helper to get the right request object. This helper also takes care of
* releasing the requests objects when the window goes out of scope.
*
* DOMRequestIPCHelper also deals with message listeners, allowing to add them
* to the child side of frame and process message manager and removing them
* when needed.
*/
const Cu = Components.utils;
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
this.EXPORTED_SYMBOLS = ["DOMRequestIpcHelper"];
@ -19,45 +30,148 @@ XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
"@mozilla.org/childprocessmessagemanager;1",
"nsIMessageListenerManager");
/**
* We use DOMRequestIpcHelperMessageListener to avoid leaking objects which
* "inherit" from DOMRequestIpcHelper.
*
* The issue is that the message manager will hold a strong ref to the message
* listener we register with it. But we don't want to hold a strong ref to the
* DOMRequestIpcHelper object, because that object may be arbitrarily large.
*
* So instead the message manager holds a strong ref to the
* DOMRequestIpcHelperMessageListener, and that holds a /weak/ ref to its
* DOMRequestIpcHelper.
*
* Additionally, we want to unhook all of these message listeners when the
* appropriate window is destroyed. We use DOMRequestIpcHelperMessageListener
* for this, too.
*/
this.DOMRequestIpcHelperMessageListener = function(aHelper, aWindow, aMessages) {
this._weakHelper = Cu.getWeakReference(aHelper);
this._messages = aMessages;
this._messages.forEach(function(msgName) {
cpmm.addWeakMessageListener(msgName, this);
}, this);
Services.obs.addObserver(this, "inner-window-destroyed", /* weakRef */ true);
// aWindow may be null; in that case, the DOMRequestIpcHelperMessageListener
// is not tied to a particular window and lives forever.
if (aWindow) {
let util = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
this._innerWindowID = util.currentInnerWindowID;
}
this.DOMRequestIpcHelper = function DOMRequestIpcHelper() {
// _listeners keeps a list of messages for which we added a listener and the
// kind of listener that we added (strong or weak). It's an object of this
// form:
// {
// "message1": true,
// "messagen": false
// }
//
// where each property is the name of the message and its value is a boolean
// that indicates if the listener is strong or not.
this._listeners = null;
this._requests = null;
this._window = null;
}
DOMRequestIpcHelperMessageListener.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIMessageListener,
Ci.nsIObserver,
Ci.nsISupportsWeakReference]),
DOMRequestIpcHelper.prototype = {
/**
* An object which "inherits" from DOMRequestIpcHelper, declares its own
* queryInterface method and adds at least one weak listener to the Message
* Manager MUST implement Ci.nsISupportsWeakReference.
*/
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference]),
/**
* 'aMessages' is expected to be an array of either:
* - objects of this form:
* {
* name: "messageName",
* strongRef: false
* }
* where 'name' is the message identifier and 'strongRef' a boolean
* indicating if the listener should be a strong referred one or not.
*
* - or only strings containing the message name, in which case the listener
* will be added as a weak reference by default.
*/
addMessageListeners: function(aMessages) {
if (!aMessages) {
return;
}
if (!this._listeners) {
this._listeners = {};
}
if (!Array.isArray(aMessages)) {
aMessages = [aMessages];
}
aMessages.forEach((aMsg) => {
let name = aMsg.name || aMsg;
// If the listener is already set and it is of the same type we just
// bail out. If it is not of the same type, we throw an exception.
if (this._listeners[name] != undefined) {
if (!!aMsg.strongRef == this._listeners[name]) {
return;
} else {
throw Cr.NS_ERROR_FAILURE;
}
}
aMsg.strongRef ? cpmm.addMessageListener(name, this)
: cpmm.addWeakMessageListener(name, this);
this._listeners[name] = !!aMsg.strongRef;
});
},
/**
* 'aMessages' is expected to be a string or an array of strings containing
* the message names of the listeners to be removed.
*/
removeMessageListeners: function(aMessages) {
if (!this._listeners || !aMessages) {
return;
}
if (!Array.isArray(aMessages)) {
aMessages = [aMessages];
}
aMessages.forEach((aName) => {
if (this._listeners[aName] == undefined) {
return;
}
this._listeners[aName] ? cpmm.removeMessageListener(aName, this)
: cpmm.removeWeakMessageListener(aName, this);
delete this._listeners[aName];
});
},
/**
* Initialize the helper adding the corresponding listeners to the messages
* provided as the second parameter.
*
* 'aMessages' is expected to be an array of either:
*
* - objects of this form:
* {
* name: 'messageName',
* strongRef: false
* }
* where 'name' is the message identifier and 'strongRef' a boolean
* indicating if the listener should be a strong referred one or not.
*
* - or only strings containing the message name, in which case the listener
* will be added as a weak referred one by default.
*/
initDOMRequestHelper: function(aWindow, aMessages) {
if (aMessages) {
this.addMessageListeners(aMessages);
}
this._id = this._getRandomId();
this._window = aWindow;
if (this._window) {
// We don't use this.innerWindowID, but other classes rely on it.
let util = this._window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
this.innerWindowID = util.currentInnerWindowID;
}
Services.obs.addObserver(this, "inner-window-destroyed", false);
},
destroyDOMRequestHelper: function() {
Services.obs.removeObserver(this, "inner-window-destroyed");
if (this._listeners) {
Object.keys(this._listeners).forEach((aName) => {
this._listeners[aName] ? cpmm.removeMessageListener(aName, this)
: cpmm.removeWeakMessageListener(aName, this);
delete this._listeners[aName];
});
}
this._listeners = null;
this._requests = null;
this._window = null;
},
observe: function(aSubject, aTopic, aData) {
if (aTopic !== "inner-window-destroyed") {
@ -65,70 +179,18 @@ DOMRequestIpcHelperMessageListener.prototype = {
}
let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
if (wId != this._innerWindowID) {
if (wId != this.innerWindowID) {
return;
}
this.destroy();
},
receiveMessage: function(aMsg) {
let helper = this._weakHelper.get();
if (helper) {
helper.receiveMessage(aMsg);
} else {
this.destroy();
}
},
destroy: function() {
// DOMRequestIpcHelper.destroy() calls back into this function.
if (this._destroyed) {
return;
}
this._destroyed = true;
Services.obs.removeObserver(this, "inner-window-destroyed");
this._messages.forEach(function(msgName) {
cpmm.removeWeakMessageListener(msgName, this);
}, this);
this._messages = null;
let helper = this._weakHelper.get();
if (helper) {
helper.destroyDOMRequestHelper();
}
}
}
this.DOMRequestIpcHelper = function DOMRequestIpcHelper() {
}
DOMRequestIpcHelper.prototype = {
/**
* An object which "inherits" from DOMRequestIpcHelper and declares its own
* queryInterface method MUST implement Ci.nsISupportsWeakReference.
*/
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference]),
initDOMRequestHelper: function(aWindow, aMessages) {
this._DOMRequestIpcHelperMessageListener =
new DOMRequestIpcHelperMessageListener(this, aWindow, aMessages);
this._window = aWindow;
this._requests = {};
this._id = this._getRandomId();
if (this._window) {
// We don't use this.innerWindowID, but other classes rely on it.
let util = this._window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
this.innerWindowID = util.currentInnerWindowID;
}
this.destroyDOMRequestHelper();
},
getRequestId: function(aRequest) {
if (!this._requests) {
this._requests = {};
}
let id = "id" + this._getRandomId();
this._requests[id] = aRequest;
return id;
@ -141,8 +203,9 @@ DOMRequestIpcHelper.prototype = {
},
getRequest: function(aId) {
if (this._requests[aId])
if (this._requests && this._requests[aId]) {
return this._requests[aId];
}
},
getPromiseResolver: function(aId) {
@ -152,8 +215,9 @@ DOMRequestIpcHelper.prototype = {
},
removeRequest: function(aId) {
if (this._requests[aId])
if (this._requests && this._requests[aId]) {
delete this._requests[aId];
}
},
removePromiseResolver: function(aId) {
@ -163,8 +227,9 @@ DOMRequestIpcHelper.prototype = {
},
takeRequest: function(aId) {
if (!this._requests[aId])
if (!this._requests || !this._requests[aId]) {
return null;
}
let request = this._requests[aId];
delete this._requests[aId];
return request;
@ -177,25 +242,8 @@ DOMRequestIpcHelper.prototype = {
},
_getRandomId: function() {
return Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator).generateUUID().toString();
},
destroyDOMRequestHelper: function() {
// This function is re-entrant --
// DOMRequestIpcHelperMessageListener.destroy() calls back into this
// function, and this.uninit() may also call it.
if (this._destroyed) {
return;
}
this._destroyed = true;
this._DOMRequestIpcHelperMessageListener.destroy();
this._requests = {};
this._window = null;
if(this.uninit) {
this.uninit();
}
return Cc["@mozilla.org/uuid-generator;1"]
.getService(Ci.nsIUUIDGenerator).generateUUID().toString();
},
createRequest: function() {
@ -212,19 +260,27 @@ DOMRequestIpcHelper.prototype = {
},
forEachRequest: function(aCallback) {
Object.keys(this._requests).forEach(function(k) {
if (this.getRequest(k) instanceof this._window.DOMRequest) {
aCallback(k);
if (!this._requests) {
return;
}
Object.keys(this._requests).forEach((aKey) => {
if (this.getRequest(aKey) instanceof this._window.DOMRequest) {
aCallback(aKey);
}
}, this);
});
},
forEachPromiseResolver: function(aCallback) {
Object.keys(this._requests).forEach(function(k) {
if ("resolve" in this.getPromiseResolver(k) &&
"reject" in this.getPromiseResolver(k)) {
aCallback(k);
if (!this._requests) {
return;
}
Object.keys(this._requests).forEach((aKey) => {
if ("resolve" in this.getPromiseResolver(aKey) &&
"reject" in this.getPromiseResolver(aKey)) {
aCallback(aKey);
}
}, this);
});
},
}

View File

@ -17,91 +17,327 @@
<script type="application/javascript">
<![CDATA[
Components.utils.import("resource://gre/modules/DOMRequestHelper.jsm");
function DummyHelperSubclass() {
this.initDOMRequestHelper(window, []);
}
function DummyHelperSubclass() {
}
DummyHelperSubclass.prototype = {
__proto__: DOMRequestIpcHelper.prototype
};
var dummy = new DummyHelperSubclass();
function createPromise() {
ok(Promise, "Promise object should exist");
/**
* Init & destroy.
*/
function initDOMRequestHelperTest(aMessages) {
is(dummy._requests, undefined, "Request is undefined");
is(dummy._messages, undefined, "Messages is undefined");
is(dummy._window, undefined, "Window is undefined");
var promise = dummy.createPromise(function(resolve, reject) {
resolve(true);
});
ok(promise instanceof Promise, "returned a Promise");
promise.then(runTest);
dummy.initDOMRequestHelper(window, aMessages);
ok(dummy._window, "Window exists");
is(dummy._window, window, "Correct window");
if (aMessages) {
is(typeof dummy._listeners, "object", "Listeners is an object");
}
}
function getResolver() {
var id;
var resolver;
var promise = dummy.createPromise(function(resolve, reject) {
var r = { resolve: resolve, reject: reject };
id = dummy.getPromiseResolverId(r);
resolver = r;
ok(typeof id === "string", "id should be string");
r.resolve(true);
}).then(function(unused) {
var r = dummy.getPromiseResolver(id);
ok(resolver === r, "get should succeed");
runTest();
});
function destroyDOMRequestHelperTest() {
dummy.destroyDOMRequestHelper();
is(dummy._requests, undefined, "Request is undefined");
is(dummy._messages, undefined, "Messages is undefined");
is(dummy._window, undefined, "Window is undefined");
}
function removeResolver() {
var id;
var promise = dummy.createPromise(function(resolve, reject) {
var r = { resolve: resolve, reject: reject };
id = dummy.getPromiseResolverId(r);
ok(typeof id === "string", "id should be string");
var resolver = dummy.getPromiseResolver(id);
ok(resolver === r, "resolver get should succeed");
r.resolve(true);
}).then(function(unused) {
dummy.removePromiseResolver(id);
var resolver = dummy.getPromiseResolver(id);
ok(resolver === undefined, "removeResolver: get should fail");
runTest();
/**
* Message listeners.
*/
function checkMessageListeners(aExpectedListeners, aCount) {
ok(true, "Checking message listeners\n" + "Expected listeners " +
JSON.stringify(aExpectedListeners) + " \nExpected count " + aCount);
let count = 0;
Object.keys(dummy._listeners).forEach(function(name) {
count++;
is(aExpectedListeners[name], dummy._listeners[name],
"Message found " + name + " - Same listeners");
});
is(aCount, count, "Correct number of listeners");
}
function takeResolver() {
var id;
var resolver;
var promise = dummy.createPromise(function(resolve, reject) {
var r = { resolve: resolve, reject: reject };
id = dummy.getPromiseResolverId(r);
resolver = r;
ok(typeof id === "string", "id should be string");
var gotR = dummy.getPromiseResolver(id);
ok(gotR === r, "resolver get should succeed");
r.resolve(true);
}).then(function(unused) {
var r = dummy.takePromiseResolver(id);
ok(resolver === r, "take should succeed");
r = dummy.getPromiseResolver(id);
ok(r === undefined, "takeResolver: get should fail");
runTest();
});
function addMessageListenersTest(aMessages, aExpectedListeners, aCount) {
dummy.addMessageListeners(aMessages);
ok(true, JSON.stringify(dummy._listeners));
checkMessageListeners(aExpectedListeners, aCount);
}
var tests = [ createPromise,
getResolver,
removeResolver,
takeResolver,
];
function removeMessageListenersTest(aMessages, aExpectedListeners, aCount) {
dummy.removeMessageListeners(aMessages);
checkMessageListeners(aExpectedListeners, aCount);
}
function runTest() {
/**
* Test steps.
*/
var tests = [
function() {
ok(true, "== InitDOMRequestHelper no messages");
initDOMRequestHelperTest(null);
next();
},
function() {
ok(true, "== DestroyDOMRequestHelper");
destroyDOMRequestHelperTest();
next();
},
function() {
ok(true, "== InitDOMRequestHelper empty array");
initDOMRequestHelperTest([]);
checkMessageListeners({}, 0);
next();
},
function() {
ok(true, "== DestroyDOMRequestHelper");
destroyDOMRequestHelperTest();
next();
},
function() {
ok(true, "== InitDOMRequestHelper with strings array");
initDOMRequestHelperTest(["name1", "nameN"]);
checkMessageListeners({"name1": false, "nameN": false}, 2);
next();
},
function() {
ok(true, "== DestroyDOMRequestHelper");
destroyDOMRequestHelperTest();
next();
},
function() {
ok(true, "== InitDOMRequestHelper with objects array");
initDOMRequestHelperTest([{
name: "name1",
strongRef: false
}, {
name: "nameN",
strongRef: true
}]);
checkMessageListeners({"name1": false, "nameN": true}, 2);
next();
},
function() {
ok(true, "== AddMessageListeners empty array");
addMessageListenersTest([], {"name1": false, "nameN": true}, 2);
next();
},
function() {
ok(true, "== AddMessageListeners null");
addMessageListenersTest(null, {"name1": false, "nameN": true}, 2);
next();
},
function() {
ok(true, "== AddMessageListeners new listener, string only");
addMessageListenersTest("name2", {
"name1": false,
"name2": false,
"nameN": true
}, 3);
next();
},
function() {
ok(true, "== AddMessageListeners new listeners, strings array");
addMessageListenersTest(["name3", "name4"], {
"name1": false,
"name2": false,
"name3": false,
"name4": false,
"nameN": true
}, 5);
next();
},
function() {
ok(true, "== AddMessageListeners new listeners, objects array");
addMessageListenersTest([{
name: "name5",
strongRef: true
}, {
name: "name6",
strongRef: false
}], {
"name1": false,
"name2": false,
"name3": false,
"name4": false,
"name5": true,
"name6": false,
"nameN": true
}, 7);
next();
},
function() {
ok(true, "== RemoveMessageListeners, null");
removeMessageListenersTest(null, {
"name1": false,
"name2": false,
"name3": false,
"name4": false,
"name5": true,
"name6": false,
"nameN": true
}, 7);
next();
},
function() {
ok(true, "== RemoveMessageListeners, one message");
removeMessageListenersTest("name1", {
"name2": false,
"name3": false,
"name4": false,
"name5": true,
"name6": false,
"nameN": true
}, 6);
next();
},
function() {
ok(true, "== RemoveMessageListeners, array of messages");
removeMessageListenersTest(["name2", "name3"], {
"name4": false,
"name5": true,
"name6": false,
"nameN": true
}, 4);
next();
},
function() {
ok(true, "== RemoveMessageListeners, unknown message");
removeMessageListenersTest("unknown", {
"name4": false,
"name5": true,
"name6": false,
"nameN": true
}, 4);
next();
},
function() {
try {
ok(true, "== AddMessageListeners, same message, same kind");
addMessageListenersTest("name4", {
"name4": false,
"name5": true,
"name6": false,
"nameN": true
}, 4);
next();
} catch (ex) {
ok(false, "Unexpected exception " + ex);
}
},
function() {
ok(true, "== AddMessageListeners, same message, different kind");
try {
addMessageListenersTest({name: "name4", strongRef: true}, {
"name4": true,
"name5": true,
"name6": false,
"nameN": true
}, 4);
ok(false, "Should have thrown an exception");
} catch (ex) {
ok(true, "Expected exception");
next();
}
},
function() {
ok(true, "== Test createRequest()");
ok(DOMRequest, "DOMRequest object exists");
var req = dummy.createRequest();
ok(req instanceof DOMRequest, "Returned a DOMRequest");
next();
},
function() {
ok(true, "== Test getRequestId(), removeRequest() and getRequest()");
var req = dummy.createRequest();
var id = dummy.getRequestId(req);
is(typeof id, "string", "id is a string");
var req_ = dummy.getRequest(id);
is(req, req_, "Got correct request");
dummy.removeRequest(id);
req = dummy.getRequest(id);
is(req, null, "No request");
next();
},
function() {
ok(true, "== Test createPromise()");
ok(Promise, "Promise object exists");
var promise = dummy.createPromise(function(resolve, reject) {
resolve(true);
});
ok(promise instanceof Promise, "Returned a Promise");
promise.then(next);
},
function() {
ok(true, "== Test getResolver()");
var id;
var resolver;
var promise = dummy.createPromise(function(resolve, reject) {
var r = { resolve: resolve, reject: reject };
id = dummy.getPromiseResolverId(r);
resolver = r;
ok(typeof id === "string", "id is a string");
r.resolve(true);
}).then(function(unused) {
var r = dummy.getPromiseResolver(id);
ok(resolver === r, "Get succeeded");
next();
});
},
function() {
ok(true, "== Test removeResolver");
var id;
var promise = dummy.createPromise(function(resolve, reject) {
var r = { resolve: resolve, reject: reject };
id = dummy.getPromiseResolverId(r);
ok(typeof id === "string", "id is a string");
var resolver = dummy.getPromiseResolver(id);
ok(true, "Got resolver " + JSON.stringify(resolver));
ok(resolver === r, "Resolver get succeeded");
r.resolve(true);
}).then(function(unused) {
dummy.removePromiseResolver(id);
var resolver = dummy.getPromiseResolver(id);
ok(resolver === undefined, "removeResolver: get failed");
next();
});
},
function() {
ok(true, "== Test takeResolver");
var id;
var resolver;
var promise = dummy.createPromise(function(resolve, reject) {
var r = { resolve: resolve, reject: reject };
id = dummy.getPromiseResolverId(r);
resolver = r;
ok(typeof id === "string", "id is a string");
var gotR = dummy.getPromiseResolver(id);
ok(gotR === r, "resolver get succeeded");
r.resolve(true);
}).then(function(unused) {
var r = dummy.takePromiseResolver(id);
ok(resolver === r, "take should succeed");
r = dummy.getPromiseResolver(id);
ok(r === undefined, "takeResolver: get failed");
next();
});
}
];
function next() {
if (!tests.length) {
SimpleTest.finish();
return;
@ -113,7 +349,7 @@
function start() {
SimpleTest.waitForExplicitFinish();
runTest();
next();
}
]]>
</script>

View File

@ -2886,7 +2886,6 @@
"[[\"forwarddelete\",\"\"]] \"<p>foo[]</p><br><p>bar</p>\" compare innerHTML":true,
"[[\"forwarddelete\",\"\"]] \"<p>foo[]</p><br><br><p>bar</p>\" compare innerHTML":true,
"[[\"forwarddelete\",\"\"]] \"<p>foo[]</p><img src=/img/lion.svg><p>bar\" compare innerHTML":true,
"[[\"forwarddelete\",\"\"]] \"foo[]<img src=/img/lion.svg>bar\" compare innerHTML":true,
"[[\"forwarddelete\",\"\"]] \"foo []&nbsp;\" compare innerHTML":true,
"[[\"forwarddelete\",\"\"]] \"foo []<span>&nbsp;</span> bar\" compare innerHTML":true,
"[[\"forwarddelete\",\"\"]] \"foo <span>&nbsp;</span>[] bar\" compare innerHTML":true,

View File

@ -475,7 +475,8 @@ MozInputContext.prototype = {
QueryInterface: XPCOMUtils.generateQI([
Ci.nsIB2GInputContext,
Ci.nsIObserver
Ci.nsIObserver,
Ci.nsISupportsWeakReference
]),
classInfo: XPCOMUtils.generateCI({

View File

@ -91,7 +91,8 @@ PhoneNumberService.prototype = {
classID : Components.ID("{e2768710-eb17-11e2-91e2-0800200c9a66}"),
contractID : "@mozilla.org/phoneNumberService;1",
QueryInterface : XPCOMUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer]),
QueryInterface : XPCOMUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer,
Ci.nsISupportsWeakReference]),
}
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PhoneNumberService]);

View File

@ -544,6 +544,7 @@ var interfaceNamesInGlobalScope =
"Touch",
"TouchEvent",
"TouchList",
"TrackEvent",
"TransitionEvent",
{name: "TreeColumn", xbl: true},
{name: "TreeColumns", xbl: true},

View File

@ -0,0 +1,17 @@
/* -*- Mode: IDL; 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/.
*/
[Constructor(DOMString type, optional TrackEventInit eventInitDict)]
interface TrackEvent : Event
{
readonly attribute TextTrack? track;
};
dictionary TrackEventInit : EventInit
{
TextTrack? track = null;
};

View File

@ -548,6 +548,7 @@ GENERATED_EVENTS_WEBIDL_FILES = [
'MozInterAppMessageEvent.webidl',
'RTCDataChannelEvent.webidl',
'RTCPeerConnectionIceEvent.webidl',
'TrackEvent.webidl',
'UserProximityEvent.webidl',
]

View File

@ -51,6 +51,7 @@ function initializeOnload() {
var firstimg = document.createElement('img');
firstimg.addEventListener("load", imageLoad, false);
firstimg.addEventListener("error", imageLoad, false);
firstimg.alt = "";
firstimg.src = "bug733553.sjs";
document.getElementById('content').appendChild(firstimg);

View File

@ -20,6 +20,7 @@
var imgURL = document.location.search.substr(1);
document.images[0].onload = onImageLoad;
document.images[0].onerror = onImageLoad;
document.images[0].alt = "";
document.images[0].src = imgURL;
</script>
</body>

View File

@ -20,6 +20,7 @@
var imgURL = document.location.search.substr(1);
document.images[0].onload = onImageLoad;
document.images[0].onerror = onImageLoad;
document.images[0].alt = "";
document.images[0].src = imgURL;
</script>
</body>

View File

@ -20,6 +20,7 @@
var imgURL = document.location.search.substr(1);
document.images[0].onload = onImageLoad;
document.images[0].onerror = onImageLoad;
document.images[0].alt = "";
document.images[0].src = imgURL;
</script>
</body>

View File

@ -20,6 +20,7 @@
var imgURL = document.location.search.substr(1);
document.images[0].onload = onImageLoad;
document.images[0].onerror = onImageLoad;
document.images[0].alt = "";
document.images[0].src = imgURL;
</script>
</body>

View File

@ -839,7 +839,7 @@ EmitGetterCall(JSContext *cx, MacroAssembler &masm,
void *returnAddr)
{
// saveLive()
masm.PushRegsInMask(liveRegs);
MacroAssembler::AfterICSaveLive aic = masm.icSaveLive(liveRegs);
// Remaining registers should basically be free, but we need to use |object| still
// so leave it alone.
@ -890,7 +890,7 @@ EmitGetterCall(JSContext *cx, MacroAssembler &masm,
masm.Push(argUintNReg);
attacher.pushStubCodePointer(masm);
if (!masm.buildOOLFakeExitFrame(returnAddr))
if (!masm.icBuildOOLFakeExitFrame(returnAddr, aic))
return false;
masm.enterFakeExitFrame(ION_FRAME_OOL_NATIVE);
@ -936,7 +936,7 @@ EmitGetterCall(JSContext *cx, MacroAssembler &masm,
masm.loadJSContext(argJSContextReg);
if (!masm.buildOOLFakeExitFrame(returnAddr))
if (!masm.icBuildOOLFakeExitFrame(returnAddr, aic))
return false;
masm.enterFakeExitFrame(ION_FRAME_OOL_PROPERTY_OP);
@ -1292,7 +1292,7 @@ EmitCallProxyGet(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &at
{
JS_ASSERT(output.hasValue());
// saveLive()
masm.PushRegsInMask(liveRegs);
MacroAssembler::AfterICSaveLive aic = masm.icSaveLive(liveRegs);
// Remaining registers should be free, but we need to use |object| still
// so leave it alone.
@ -1329,7 +1329,7 @@ EmitCallProxyGet(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &at
masm.loadJSContext(argJSContextReg);
if (!masm.buildOOLFakeExitFrame(returnAddr))
if (!masm.icBuildOOLFakeExitFrame(returnAddr, aic))
return false;
masm.enterFakeExitFrame(ION_FRAME_OOL_PROXY);
@ -2060,7 +2060,7 @@ EmitCallProxySet(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &at
ConstantOrRegister value, void *returnAddr, bool strict)
{
// saveLive()
masm.PushRegsInMask(liveRegs);
MacroAssembler::AfterICSaveLive aic = masm.icSaveLive(liveRegs);
// Remaining registers should be free, but we need to use |object| still
// so leave it alone.
@ -2098,7 +2098,7 @@ EmitCallProxySet(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &at
masm.loadJSContext(argJSContextReg);
masm.move32(Imm32(strict? 1 : 0), argStrictReg);
if (!masm.buildOOLFakeExitFrame(returnAddr))
if (!masm.icBuildOOLFakeExitFrame(returnAddr, aic))
return false;
masm.enterFakeExitFrame(ION_FRAME_OOL_PROXY);
@ -2266,7 +2266,7 @@ GenerateCallSetter(JSContext *cx, IonScript *ion, MacroAssembler &masm,
// Good to go for invoking setter.
// saveLive()
masm.PushRegsInMask(liveRegs);
MacroAssembler::AfterICSaveLive aic = masm.icSaveLive(liveRegs);
// Remaining registers should basically be free, but we need to use |object| still
// so leave it alone.
@ -2319,7 +2319,7 @@ GenerateCallSetter(JSContext *cx, IonScript *ion, MacroAssembler &masm,
masm.Push(argUintNReg);
attacher.pushStubCodePointer(masm);
if (!masm.buildOOLFakeExitFrame(returnAddr))
if (!masm.icBuildOOLFakeExitFrame(returnAddr, aic))
return false;
masm.enterFakeExitFrame(ION_FRAME_OOL_NATIVE);
@ -2362,7 +2362,7 @@ GenerateCallSetter(JSContext *cx, IonScript *ion, MacroAssembler &masm,
masm.loadJSContext(argJSContextReg);
if (!masm.buildOOLFakeExitFrame(returnAddr))
if (!masm.icBuildOOLFakeExitFrame(returnAddr, aic))
return false;
masm.enterFakeExitFrame(ION_FRAME_OOL_PROPERTY_OP);

View File

@ -237,6 +237,21 @@ class MacroAssembler : public MacroAssemblerSpecific
#endif
}
MacroAssembler(JSContext *cx, IonScript *ion)
: enoughMemory_(true),
embedsNurseryPointers_(false),
sps_(NULL)
{
constructRoot(cx);
ionContext_.construct(cx, (js::jit::TempAllocator *)NULL);
alloc_.construct(cx);
#ifdef JS_CPU_ARM
initWithAllocator();
m_buffer.id = GetIonContext()->getNextAssemblerId();
#endif
setFramePushed(ion->frameSize());
}
void setInstrumentation(IonInstrumentation *sps) {
sps_ = sps;
}
@ -1314,6 +1329,26 @@ class MacroAssembler : public MacroAssemblerSpecific
{
convertTypedOrValueToInt(src, temp, output, fail, IntConversion_ClampToUint8);
}
public:
class AfterICSaveLive {
friend class MacroAssembler;
AfterICSaveLive()
{}
};
AfterICSaveLive icSaveLive(RegisterSet &liveRegs) {
PushRegsInMask(liveRegs);
return AfterICSaveLive();
}
bool icBuildOOLFakeExitFrame(void *fakeReturnAddr, AfterICSaveLive &aic) {
return buildOOLFakeExitFrame(fakeReturnAddr);
}
void icRestoreLive(RegisterSet &liveRegs, AfterICSaveLive &aic) {
PopRegsInMask(liveRegs);
}
};
static inline Assembler::DoubleCondition

View File

@ -1191,7 +1191,6 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
// Builds an exit frame on the stack, with a return address to an internal
// non-function. Returns offset to be passed to markSafepointAt().
bool buildFakeExitFrame(const Register &scratch, uint32_t *offset);
bool buildOOLFakeExitFrame(void *fakeReturnAddr);
void callWithExitFrame(IonCode *target);
void callWithExitFrame(IonCode *target, Register dynStack);
@ -1399,6 +1398,9 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
void passABIArg(const FloatRegister &reg);
void passABIArg(const ValueOperand &regs);
protected:
bool buildOOLFakeExitFrame(void *fakeReturnAddr);
private:
void callWithABIPre(uint32_t *stackAdjust);
void callWithABIPost(uint32_t stackAdjust, Result result);

View File

@ -127,7 +127,7 @@ ToStackIndex(LAllocation *a)
return a->toStackSlot()->slot();
}
JS_ASSERT(-int32_t(sizeof(IonJSFrameLayout)) <= a->toArgument()->index());
return -(sizeof(IonJSFrameLayout) + a->toArgument()->index());
return -int32_t(sizeof(IonJSFrameLayout) + a->toArgument()->index());
}
bool

View File

@ -638,13 +638,6 @@ class MacroAssemblerX86Shared : public Assembler
return addCodeLabel(cl);
}
bool buildOOLFakeExitFrame(void *fakeReturnAddr) {
uint32_t descriptor = MakeFrameDescriptor(framePushed(), IonFrame_OptimizedJS);
Push(Imm32(descriptor));
Push(ImmPtr(fakeReturnAddr));
return true;
}
void callWithExitFrame(IonCode *target) {
uint32_t descriptor = MakeFrameDescriptor(framePushed(), IonFrame_OptimizedJS);
Push(Imm32(descriptor));
@ -661,10 +654,18 @@ class MacroAssemblerX86Shared : public Assembler
CodeOffsetLabel labelForPatch() {
return CodeOffsetLabel(size());
}
void abiret() {
ret();
}
protected:
bool buildOOLFakeExitFrame(void *fakeReturnAddr) {
uint32_t descriptor = MakeFrameDescriptor(framePushed(), IonFrame_OptimizedJS);
Push(Imm32(descriptor));
Push(ImmPtr(fakeReturnAddr));
return true;
}
};
} // namespace jit

View File

@ -544,7 +544,11 @@ TypeSet::unionSets(TypeSet *a, TypeSet *b, LifoAlloc *alloc)
// discarded.
static LifoAlloc *IonAlloc() {
#ifdef JS_ION
return jit::GetIonContext()->temp->lifoAlloc();
#else
MOZ_CRASH();
#endif
}
// Superclass of all constraints generated during Ion compilation. These may
@ -575,8 +579,12 @@ class types::CompilerConstraint
void
CompilerConstraintList::add(CompilerConstraint *constraint)
{
#ifdef JS_ION
if (!constraint || !constraint->expected || !constraints.append(constraint))
setFailed();
#else
MOZ_CRASH();
#endif
}
namespace {
@ -672,16 +680,21 @@ TypeObjectKey::newScript()
bool
TypeObjectKey::unknownProperties()
{
#ifdef JS_ION
JSContext *cx = jit::GetIonContext()->cx;
TypeObject *type = isSingleObject() ? asSingleObject()->getType(cx) : asTypeObject();
if (!type)
MOZ_CRASH();
return type->unknownProperties();
#else
MOZ_CRASH();
#endif
}
HeapTypeSetKey
TypeObjectKey::property(jsid id)
{
#ifdef JS_ION
JSContext *cx = jit::GetIonContext()->cx;
TypeObject *type = isSingleObject() ? asSingleObject()->getType(cx) : asTypeObject();
if (!type)
@ -691,6 +704,9 @@ TypeObjectKey::property(jsid id)
if (!property.actualTypes)
MOZ_CRASH();
return property;
#else
MOZ_CRASH();
#endif
}
bool
@ -938,6 +954,7 @@ class ConstraintDataFreezeObjectFlags
bool
TypeObjectKey::hasFlags(CompilerConstraintList *constraints, TypeObjectFlags flags)
{
#ifdef JS_ION
JS_ASSERT(flags);
JSContext *cx = jit::GetIonContext()->cx;
@ -950,6 +967,9 @@ TypeObjectKey::hasFlags(CompilerConstraintList *constraints, TypeObjectFlags fla
HeapTypeSetKey objectProperty = property(JSID_EMPTY);
constraints->add(IonAlloc()->new_<CompilerConstraintInstance<ConstraintDataFreezeObjectFlags> >(objectProperty, ConstraintDataFreezeObjectFlags(this, flags)));
return false;
#else
MOZ_CRASH();
#endif
}
void
@ -1653,11 +1673,15 @@ bool
types::ArrayPrototypeHasIndexedProperty(CompilerConstraintList *constraints,
HandleScript script)
{
#ifdef JS_ION
JSObject *proto = script->global().getOrCreateArrayPrototype(jit::GetIonContext()->cx);
if (!proto)
return true;
return PrototypeHasIndexedProperty(constraints, proto);
#else
MOZ_CRASH();
#endif
}
bool

View File

@ -1402,8 +1402,10 @@ FinishCompilation(JSContext *cx, JSScript *script, jit::ExecutionMode executionM
class CompilerConstraint;
class CompilerConstraintList
{
#ifdef JS_ION
// Generated constraints.
Vector<CompilerConstraint *, 0, jit::IonAllocPolicy> constraints;
#endif
// OOM during generation of some constraint.
bool failed_;
@ -1416,10 +1418,18 @@ class CompilerConstraintList
void add(CompilerConstraint *constraint);
size_t length() {
#ifdef JS_ION
return constraints.length();
#else
MOZ_CRASH();
#endif
}
CompilerConstraint *get(size_t i) {
#ifdef JS_ION
return constraints[i];
#else
MOZ_CRASH();
#endif
}
bool failed() {

View File

@ -25,7 +25,9 @@
#include "jswatchpoint.h"
#include "jswrapper.h"
#include "assembler/assembler/MacroAssembler.h"
#if defined(JS_ION)
# include "assembler/assembler/MacroAssembler.h"
#endif
#include "jit/AsmJSSignalHandlers.h"
#include "jit/IonCompartment.h"
#include "jit/PcScriptCache.h"

View File

@ -451,9 +451,9 @@ nsImageFrame::ShouldCreateImageFrameFor(Element* aElement,
// - if our special "force icons" style is set, show an icon
// - else if our "do not show placeholders" pref is set, skip the icon
// - else:
// - if QuirksMode, and there is no alt attribute, and this is not an
// <object> (which could not possibly have such an attribute), show an
// icon.
// - if there is a src attribute, there is no alt attribute,
// and this is not an <object> (which could not possibly have
// such an attribute), show an icon.
// - if QuirksMode, and the IMG has a size show an icon.
// - otherwise, skip the icon
bool useSizedBox;
@ -464,31 +464,24 @@ nsImageFrame::ShouldCreateImageFrameFor(Element* aElement,
else if (gIconLoad && gIconLoad->mPrefForceInlineAltText) {
useSizedBox = false;
}
else {
if (aStyleContext->PresContext()->CompatibilityMode() !=
eCompatibility_NavQuirks) {
useSizedBox = false;
}
else {
// We are in quirks mode, so we can just check the tag name; no need to
// check the namespace.
nsIAtom *localName = aElement->Tag();
// Use a sized box if we have no alt text. This means no alt attribute
// and the node is not an object or an input (since those always have alt
// text).
if (!aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::alt) &&
localName != nsGkAtoms::object &&
localName != nsGkAtoms::input) {
useSizedBox = true;
}
else {
// check whether we have fixed size
useSizedBox = HaveFixedSize(aStyleContext->StylePosition());
}
}
else if (aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::src) &&
!aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::alt) &&
!aElement->IsHTML(nsGkAtoms::object) &&
!aElement->IsHTML(nsGkAtoms::input)) {
// Use a sized box if we have no alt text. This means no alt attribute
// and the node is not an object or an input (since those always have alt
// text).
useSizedBox = true;
}
else if (aStyleContext->PresContext()->CompatibilityMode() !=
eCompatibility_NavQuirks) {
useSizedBox = false;
}
else {
// check whether we have fixed size
useSizedBox = HaveFixedSize(aStyleContext->StylePosition());
}
return useSizedBox;
}
@ -720,9 +713,7 @@ nsImageFrame::EnsureIntrinsicSizeAndRatio(nsPresContext* aPresContext)
// invalid image specified
// - make the image big enough for the icon (it may not be
// used if inline alt expansion is used instead)
// XXX: we need this in composer, but it is also good for
// XXX: general quirks mode to always have room for the icon
if (aPresContext->CompatibilityMode() == eCompatibility_NavQuirks) {
if (!(GetStateBits() & NS_FRAME_GENERATED_CONTENT)) {
nscoord edgeLengthToUse =
nsPresContext::CSSPixelsToAppUnits(
ICON_SIZE + (2 * (ICON_PADDING + ALT_BORDER_WIDTH)));

View File

@ -1,3 +1,4 @@
<!DOCTYPE html>
<html>
<body>
<img>

View File

@ -1,6 +1,7 @@
<!DOCTYPE html>
<html>
<body>
<img src="http://www.foo oo.com">
<img src="http://www.foo oo.com" alt="">
<input type="image" src="http://www.foo oo.com">
</body>
</html>

View File

@ -7,35 +7,35 @@
MODULE = 'jemalloc'
CSRCS += [
'arena.c',
'atomic.c',
'base.c',
'bitmap.c',
'chunk.c',
'chunk_dss.c',
'chunk_mmap.c',
'ckh.c',
'ctl.c',
'extent.c',
'hash.c',
'huge.c',
'jemalloc.c',
'mb.c',
'mutex.c',
'prof.c',
'quarantine.c',
'rtree.c',
'stats.c',
'tcache.c',
'tsd.c',
'util.c',
'src/src/arena.c',
'src/src/atomic.c',
'src/src/base.c',
'src/src/bitmap.c',
'src/src/chunk.c',
'src/src/chunk_dss.c',
'src/src/chunk_mmap.c',
'src/src/ckh.c',
'src/src/ctl.c',
'src/src/extent.c',
'src/src/hash.c',
'src/src/huge.c',
'src/src/jemalloc.c',
'src/src/mb.c',
'src/src/mutex.c',
'src/src/prof.c',
'src/src/quarantine.c',
'src/src/rtree.c',
'src/src/stats.c',
'src/src/tcache.c',
'src/src/tsd.c',
'src/src/util.c',
]
# Only OSX needs the zone allocation implementation,
# but only if replace-malloc is not enabled.
if CONFIG['OS_TARGET'] == 'Darwin' and not CONFIG['MOZ_REPLACE_MALLOC']:
CSRCS += [
'zone.c',
'src/src/zone.c',
]
LIBRARY_NAME = 'jemalloc'

View File

@ -7,10 +7,6 @@ FORCE_SHARED_LIB= 1
DEFINES += -DMOZ_NO_MOZALLOC
VPATH += $(topsrcdir)/xpcom/base
VPATH += $(topsrcdir)/nsprpub/lib/libc/src
VPATH += $(topsrcdir)/mfbt
# Disable mozglue.
WRAP_LDFLAGS =
MOZ_GLUE_LDFLAGS=

View File

@ -12,12 +12,12 @@ EXPORTS += [
CPP_SOURCES += [
'DMD.cpp',
'HashFunctions.cpp',
'nsStackWalk.cpp',
'../../../mfbt/HashFunctions.cpp',
'../../../xpcom/base/nsStackWalk.cpp',
]
CSRCS += [
'strcpy.c',
'../../../nsprpub/lib/libc/src/strcpy.c',
]
LIBRARY_NAME = 'dmd'

View File

@ -8,8 +8,8 @@ MODULE = 'memory'
NO_DIST_INSTALL = True
CSRCS += [
'jemalloc_config.c',
'mozjemalloc_compat.c',
'../../build/jemalloc_config.c',
'../../build/mozjemalloc_compat.c',
]
# Android doesn't have pthread_atfork, so just implement a dummy function.

View File

@ -70,6 +70,15 @@
#define SECCOMP_WHITELIST_ADD_ARM_LAST
#endif
/* System calls used by the profiler */
#ifdef MOZ_PROFILING
#define PROFILING_WHITELIST_ADD \
ALLOW_SYSCALL(sigaction), \
ALLOW_SYSCALL(tgkill),
#else
#define PROFILING_WHITELIST_ADD
#endif
/* Syscalls specific to arm that should eventually be removed */
#if defined(__arm__)
#define SECCOMP_WHITELIST_REMOVE_ARM \
@ -151,6 +160,7 @@
ALLOW_SYSCALL(getpriority), \
ALLOW_SYSCALL(setpriority), \
ALLOW_SYSCALL(sched_setscheduler), \
PROFILING_WHITELIST_ADD \
/* Always last and always OK calls */ \
SECCOMP_WHITELIST_ADD_ARM_LAST \
/* restart_syscall is called internally, generally when debugging */ \

View File

@ -41,9 +41,11 @@ interface nsIURIContentListener : nsISupports
* @param aContentHandler nsIStreamListener that will consume the data.
* This should be set to <code>nullptr</code> if
* this content listener can't handle the content
* type.
* type; in this case, doContent should also fail
* (i.e., return failure nsresult).
*
* @return <code>true</code> if the consumer wants to
* @return <code>true</code> if the load should
* be aborted and consumer wants to
* handle the load completely by itself. This
* causes the URI Loader do nothing else...
* <code>false</code> if the URI Loader should