This commit is contained in:
Wes Kocher 2015-01-21 14:14:21 -08:00
Родитель 52b08e3604 c0d4e14e92
Коммит b0e827c8f4
99 изменённых файлов: 1145 добавлений и 909 удалений

Просмотреть файл

@ -22,5 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please # changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more. # don't change CLOBBER for WebIDL changes any more.
Bug 1100184 - Lots of file moves from the /netwerk flattening and zero faith Bug 1115998 - (DOMString or sequence<DOMString>) needs binding flush (Bug 1103153)
in the build system to properly handle them.

Просмотреть файл

@ -12,7 +12,7 @@
namespace mozilla { namespace mozilla {
namespace a11y { namespace a11y {
MOZ_BEGIN_ENUM_CLASS(RelationType) enum class RelationType {
/** /**
* This object is labelled by a target object. * This object is labelled by a target object.
@ -131,7 +131,7 @@ MOZ_BEGIN_ENUM_CLASS(RelationType)
LAST = CONTAINING_APPLICATION LAST = CONTAINING_APPLICATION
MOZ_END_ENUM_CLASS(RelationType) };
} // namespace a11y } // namespace a11y
} // namespace mozilla } // namespace mozilla

Просмотреть файл

@ -84,6 +84,14 @@ function test() {
} }
}); });
window.messageManager.addMessageListener("Test:ActivateEvent", function(message) {
ok(message.data.ok, "Test:ActivateEvent");
});
window.messageManager.addMessageListener("Test:DeactivateEvent", function(message) {
ok(message.data.ok, "Test:DeactivateEvent");
});
browser1.addEventListener("load", check, true); browser1.addEventListener("load", check, true);
browser2.addEventListener("load", check, true); browser2.addEventListener("load", check, true);
browser1.contentWindow.location = testPage; browser1.contentWindow.location = testPage;
@ -132,6 +140,25 @@ function childFunction()
sendAsyncMessage("Test:FocusReceived", { }); sendAsyncMessage("Test:FocusReceived", { });
}, false); }, false);
var windowGotActivate = false;
var windowGotDeactivate = false;
addEventListener("activate", function() {
sendAsyncMessage("Test:ActivateEvent", { ok: !windowGotActivate });
windowGotActivate = false;
});
addEventListener("deactivate", function() {
sendAsyncMessage("Test:DeactivateEvent", { ok: !windowGotDeactivate });
windowGotDeactivate = false;
});
content.addEventListener("activate", function() {
windowGotActivate = true;;
});
content.addEventListener("deactivate", function() {
windowGotDeactivate = true;
});
content.setInterval(function () { content.setInterval(function () {
if (!expectingResponse) { if (!expectingResponse) {
return; return;

Просмотреть файл

@ -31,6 +31,7 @@ skip-if = e10s # Bug 1053965 "cw.ensureSnippetsMapThen is not a function", also
[browser_addons.js] [browser_addons.js]
[browser_blocklist.js] [browser_blocklist.js]
[browser_share.js] [browser_share.js]
skip-if = true # bug 1115131
[browser_social_activation.js] [browser_social_activation.js]
skip-if = e10s # Bug 933103 synthesizeMouseAtCenter not e10s friendly skip-if = e10s # Bug 933103 synthesizeMouseAtCenter not e10s friendly
[browser_social_chatwindow.js] [browser_social_chatwindow.js]

Просмотреть файл

@ -3620,7 +3620,8 @@ nsresult
nsContentUtils::DispatchEvent(nsIDocument* aDoc, nsISupports* aTarget, nsContentUtils::DispatchEvent(nsIDocument* aDoc, nsISupports* aTarget,
const nsAString& aEventName, const nsAString& aEventName,
bool aCanBubble, bool aCancelable, bool aCanBubble, bool aCancelable,
bool aTrusted, bool *aDefaultAction) bool aTrusted, bool *aDefaultAction,
bool aOnlyChromeDispatch)
{ {
nsCOMPtr<nsIDOMEvent> event; nsCOMPtr<nsIDOMEvent> event;
nsCOMPtr<EventTarget> target; nsCOMPtr<EventTarget> target;
@ -3628,6 +3629,7 @@ nsContentUtils::DispatchEvent(nsIDocument* aDoc, nsISupports* aTarget,
aCancelable, aTrusted, getter_AddRefs(event), aCancelable, aTrusted, getter_AddRefs(event),
getter_AddRefs(target)); getter_AddRefs(target));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = aOnlyChromeDispatch;
bool dummy; bool dummy;
return target->DispatchEvent(event, aDefaultAction ? aDefaultAction : &dummy); return target->DispatchEvent(event, aDefaultAction ? aDefaultAction : &dummy);
@ -3664,6 +3666,17 @@ nsContentUtils::DispatchChromeEvent(nsIDocument *aDoc,
return rv; return rv;
} }
nsresult
nsContentUtils::DispatchEventOnlyToChrome(nsIDocument* aDoc,
nsISupports* aTarget,
const nsAString& aEventName,
bool aCanBubble, bool aCancelable,
bool* aDefaultAction)
{
return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
true, aDefaultAction, true);
}
/* static */ /* static */
Element* Element*
nsContentUtils::MatchElementId(nsIContent *aContent, const nsIAtom* aId) nsContentUtils::MatchElementId(nsIContent *aContent, const nsIAtom* aId)

Просмотреть файл

@ -987,7 +987,10 @@ public:
/** /**
* This method creates and dispatches a trusted event to the chrome * This method creates and dispatches a trusted event to the chrome
* event handler. * event handler (the parent object of the DOM Window in the event target
* chain). Note, chrome event handler is used even if aTarget is a chrome
* object. Use DispatchEventOnlyToChrome if the normal event dispatching is
* wanted in case aTarget is a chrome object.
* Works only with events which can be created by calling * Works only with events which can be created by calling
* nsIDOMDocument::CreateEvent() with parameter "Events". * nsIDOMDocument::CreateEvent() with parameter "Events".
* @param aDocument The document which will be used to create the event, * @param aDocument The document which will be used to create the event,
@ -1007,6 +1010,32 @@ public:
bool aCancelable, bool aCancelable,
bool *aDefaultAction = nullptr); bool *aDefaultAction = nullptr);
/**
* This method creates and dispatches a trusted event.
* If aTarget is not a chrome object, the nearest chrome object in the
* propagation path will be used as the start of the event target chain.
* This method is different than DispatchChromeEvent, which always dispatches
* events to chrome event handler. DispatchEventOnlyToChrome works like
* DispatchTrustedEvent in the case aTarget is a chrome object.
* Works only with events which can be created by calling
* nsIDOMDocument::CreateEvent() with parameter "Events".
* @param aDoc The document which will be used to create the event.
* @param aTarget The target of the event, should be QIable to
* nsIDOMEventTarget.
* @param aEventName The name of the event.
* @param aCanBubble Whether the event can bubble.
* @param aCancelable Is the event cancelable.
* @param aDefaultAction Set to true if default action should be taken,
* see nsIDOMEventTarget::DispatchEvent.
*/
static nsresult DispatchEventOnlyToChrome(nsIDocument* aDoc,
nsISupports* aTarget,
const nsAString& aEventName,
bool aCanBubble,
bool aCancelable,
bool *aDefaultAction = nullptr);
/** /**
* Determines if an event attribute name (such as onclick) is valid for * Determines if an event attribute name (such as onclick) is valid for
* a given element type. Types are from the EventNameType enumeration * a given element type. Types are from the EventNameType enumeration
@ -1252,7 +1281,7 @@ public:
* @param aDiscoverMode Set to eRecurseIntoChildren to descend recursively * @param aDiscoverMode Set to eRecurseIntoChildren to descend recursively
* into children. * into children.
*/ */
enum TextContentDiscoverMode MOZ_ENUM_TYPE(uint8_t) { enum TextContentDiscoverMode : uint8_t {
eRecurseIntoChildren, eDontRecurseIntoChildren eRecurseIntoChildren, eDontRecurseIntoChildren
}; };
@ -2046,7 +2075,7 @@ public:
*/ */
static bool IsAutocompleteEnabled(nsIDOMHTMLInputElement* aInput); static bool IsAutocompleteEnabled(nsIDOMHTMLInputElement* aInput);
enum AutocompleteAttrState MOZ_ENUM_TYPE(uint8_t) enum AutocompleteAttrState : uint8_t
{ {
eAutocompleteAttrState_Unknown = 1, eAutocompleteAttrState_Unknown = 1,
eAutocompleteAttrState_Invalid, eAutocompleteAttrState_Invalid,
@ -2253,7 +2282,8 @@ private:
bool aCanBubble, bool aCanBubble,
bool aCancelable, bool aCancelable,
bool aTrusted, bool aTrusted,
bool *aDefaultAction = nullptr); bool *aDefaultAction = nullptr,
bool aOnlyChromeDispatch = false);
static void InitializeModifierStrings(); static void InitializeModifierStrings();

Просмотреть файл

@ -1145,11 +1145,12 @@ nsFocusManager::ActivateOrDeactivate(nsPIDOMWindow* aWindow, bool aActive)
aWindow->ActivateOrDeactivate(aActive); aWindow->ActivateOrDeactivate(aActive);
// Send the activate event. // Send the activate event.
nsContentUtils::DispatchTrustedEvent(aWindow->GetExtantDoc(), nsContentUtils::DispatchEventOnlyToChrome(aWindow->GetExtantDoc(),
aWindow, aWindow,
aActive ? NS_LITERAL_STRING("activate") : aActive ?
NS_LITERAL_STRING("deactivate"), NS_LITERAL_STRING("activate") :
true, true, nullptr); NS_LITERAL_STRING("deactivate"),
true, true, nullptr);
// Look for any remote child frames, iterate over them and send the activation notification. // Look for any remote child frames, iterate over them and send the activation notification.
nsContentUtils::CallOnAllRemoteChildren(aWindow, ActivateOrDeactivateChild, nsContentUtils::CallOnAllRemoteChildren(aWindow, ActivateOrDeactivateChild,

Просмотреть файл

@ -461,7 +461,7 @@ GetWrapperCache(const SmartPtr<T>& aObject)
return GetWrapperCache(aObject.get()); return GetWrapperCache(aObject.get());
} }
struct ParentObject { struct MOZ_STACK_CLASS ParentObject {
template<class T> template<class T>
ParentObject(T* aObject) : ParentObject(T* aObject) :
mObject(aObject), mObject(aObject),
@ -482,7 +482,9 @@ struct ParentObject {
mUseXBLScope(false) mUseXBLScope(false)
{} {}
nsISupports* const mObject; // We don't want to make this an nsCOMPtr because of performance reasons, but
// it's safe because ParentObject is a stack class.
nsISupports* const MOZ_NON_OWNING_REF mObject;
nsWrapperCache* const mWrapperCache; nsWrapperCache* const mWrapperCache;
bool mUseXBLScope; bool mUseXBLScope;
}; };

Просмотреть файл

@ -187,7 +187,7 @@ public:
MOZ_ASSERT(mActor); MOZ_ASSERT(mActor);
} }
NS_IMETHODIMP Run() NS_IMETHODIMP Run() MOZ_OVERRIDE
{ {
MOZ_ASSERT(mActor); MOZ_ASSERT(mActor);
if (mActor->IsActorDestroyed()) { if (mActor->IsActorDestroyed()) {
@ -221,7 +221,7 @@ public:
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP Cancel() NS_IMETHODIMP Cancel() MOZ_OVERRIDE
{ {
mActor = nullptr; mActor = nullptr;
return NS_OK; return NS_OK;
@ -247,13 +247,13 @@ public:
MOZ_ASSERT(mBC); MOZ_ASSERT(mBC);
} }
NS_IMETHODIMP Run() NS_IMETHODIMP Run() MOZ_OVERRIDE
{ {
mBC->Shutdown(); mBC->Shutdown();
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP Cancel() NS_IMETHODIMP Cancel() MOZ_OVERRIDE
{ {
mBC = nullptr; mBC = nullptr;
return NS_OK; return NS_OK;
@ -278,7 +278,7 @@ public:
MOZ_ASSERT(mActor); MOZ_ASSERT(mActor);
} }
NS_IMETHODIMP Run() NS_IMETHODIMP Run() MOZ_OVERRIDE
{ {
MOZ_ASSERT(mActor); MOZ_ASSERT(mActor);
if (!mActor->IsActorDestroyed()) { if (!mActor->IsActorDestroyed()) {
@ -287,7 +287,7 @@ public:
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP Cancel() NS_IMETHODIMP Cancel() MOZ_OVERRIDE
{ {
mActor = nullptr; mActor = nullptr;
return NS_OK; return NS_OK;

Просмотреть файл

@ -42,7 +42,7 @@ private:
~BroadcastChannelChild(); ~BroadcastChannelChild();
void ActorDestroy(ActorDestroyReason aWhy); virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
// This raw pointer is actually the parent object. // This raw pointer is actually the parent object.
// It's set to null when the parent object is deleted. // It's set to null when the parent object is deleted.

Просмотреть файл

@ -37,7 +37,6 @@ StaticRefPtr<CameraPreferences> CameraPreferences::sObserver;
NS_IMPL_ISUPPORTS(CameraPreferences, nsIObserver); NS_IMPL_ISUPPORTS(CameraPreferences, nsIObserver);
#endif #endif
#ifdef CAMERAPREFERENCES_HAVE_SEPARATE_UINT32_AND_NSRESULT
/* static */ /* static */
nsresult nsresult
CameraPreferences::UpdatePref(const char* aPref, nsresult& aVal) CameraPreferences::UpdatePref(const char* aPref, nsresult& aVal)
@ -49,7 +48,6 @@ CameraPreferences::UpdatePref(const char* aPref, nsresult& aVal)
} }
return rv; return rv;
} }
#endif
/* static */ /* static */
nsresult nsresult
@ -156,7 +154,6 @@ CameraPreferences::PreferenceChanged(const char* aPref, void* aClosure)
nsresult rv; nsresult rv;
switch (p.mValueType) { switch (p.mValueType) {
case kPrefValueIsNsResult: case kPrefValueIsNsResult:
#ifdef CAMERAPREFERENCES_HAVE_SEPARATE_UINT32_AND_NSRESULT
{ {
nsresult& v = *p.mValue.mAsNsResult; nsresult& v = *p.mValue.mAsNsResult;
rv = UpdatePref(aPref, v); rv = UpdatePref(aPref, v);
@ -165,7 +162,6 @@ CameraPreferences::PreferenceChanged(const char* aPref, void* aClosure)
} }
} }
break; break;
#endif
case kPrefValueIsUint32: case kPrefValueIsUint32:
{ {
@ -331,7 +327,6 @@ CameraPreferences::GetPref(const char* aPref, nsACString& aVal)
return true; return true;
} }
#ifdef CAMERAPREFERENCES_HAVE_SEPARATE_UINT32_AND_NSRESULT
/* static */ /* static */
bool bool
CameraPreferences::GetPref(const char* aPref, nsresult& aVal) CameraPreferences::GetPref(const char* aPref, nsresult& aVal)
@ -359,7 +354,6 @@ CameraPreferences::GetPref(const char* aPref, nsresult& aVal)
aVal = v; aVal = v;
return true; return true;
} }
#endif
/* static */ /* static */
bool bool

Просмотреть файл

@ -12,13 +12,6 @@
#include "mozilla/StaticPtr.h" #include "mozilla/StaticPtr.h"
#endif #endif
#if defined(MOZ_HAVE_CXX11_STRONG_ENUMS) || defined(MOZ_HAVE_CXX11_ENUM_TYPE)
// Older compilers that don't support strongly-typed enums
// just typedef uint32_t to nsresult, which results in conflicting
// overloaded members in CameraPreferences.
#define CAMERAPREFERENCES_HAVE_SEPARATE_UINT32_AND_NSRESULT
#endif
namespace mozilla { namespace mozilla {
template<class T> class StaticAutoPtr; template<class T> class StaticAutoPtr;
@ -38,9 +31,7 @@ public:
static void Shutdown(); static void Shutdown();
static bool GetPref(const char* aPref, nsACString& aVal); static bool GetPref(const char* aPref, nsACString& aVal);
#ifdef CAMERAPREFERENCES_HAVE_SEPARATE_UINT32_AND_NSRESULT
static bool GetPref(const char* aPref, nsresult& aVal); static bool GetPref(const char* aPref, nsresult& aVal);
#endif
static bool GetPref(const char* aPref, uint32_t& aVal); static bool GetPref(const char* aPref, uint32_t& aVal);
static bool GetPref(const char* aPref, bool& aVal); static bool GetPref(const char* aPref, bool& aVal);
@ -49,9 +40,7 @@ protected:
static uint32_t PrefToIndex(const char* aPref); static uint32_t PrefToIndex(const char* aPref);
static void PreferenceChanged(const char* aPref, void* aClosure); static void PreferenceChanged(const char* aPref, void* aClosure);
#ifdef CAMERAPREFERENCES_HAVE_SEPARATE_UINT32_AND_NSRESULT
static nsresult UpdatePref(const char* aPref, nsresult& aVar); static nsresult UpdatePref(const char* aPref, nsresult& aVar);
#endif
static nsresult UpdatePref(const char* aPref, uint32_t& aVar); static nsresult UpdatePref(const char* aPref, uint32_t& aVar);
static nsresult UpdatePref(const char* aPref, nsACString& aVar); static nsresult UpdatePref(const char* aPref, nsACString& aVar);
static nsresult UpdatePref(const char* aPref, bool& aVar); static nsresult UpdatePref(const char* aPref, bool& aVar);

Просмотреть файл

@ -162,7 +162,7 @@ public:
nsString mTypeString; // for non-main-threads nsString mTypeString; // for non-main-threads
uint16_t mEventType; uint16_t mEventType;
enum ListenerType MOZ_ENUM_TYPE(uint8_t) enum ListenerType : uint8_t
{ {
eNativeListener = 0, eNativeListener = 0,
eJSEventListener, eJSEventListener,

Просмотреть файл

@ -429,7 +429,7 @@ protected:
/** /**
* Computes the default action for the aEvent with the prefs. * Computes the default action for the aEvent with the prefs.
*/ */
enum Action MOZ_ENUM_TYPE(uint8_t) enum Action : uint8_t
{ {
ACTION_NONE = 0, ACTION_NONE = 0,
ACTION_SCROLL, ACTION_SCROLL,

Просмотреть файл

@ -323,13 +323,24 @@ RTCPeerConnection.prototype = {
init: function(win) { this._win = win; }, init: function(win) { this._win = win; },
__init: function(rtcConfig) { __init: function(rtcConfig) {
this._winID = this._win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID;
if (!rtcConfig.iceServers || if (!rtcConfig.iceServers ||
!Services.prefs.getBoolPref("media.peerconnection.use_document_iceservers")) { !Services.prefs.getBoolPref("media.peerconnection.use_document_iceservers")) {
rtcConfig.iceServers = rtcConfig.iceServers =
JSON.parse(Services.prefs.getCharPref("media.peerconnection.default_iceservers")); JSON.parse(Services.prefs.getCharPref("media.peerconnection.default_iceservers"));
} }
this._winID = this._win.QueryInterface(Ci.nsIInterfaceRequestor) // Normalize iceServers input
.getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID; rtcConfig.iceServers.forEach(server => {
if (typeof server.urls === "string") {
server.urls = [server.urls];
} else if (!server.urls && server.url) {
// TODO: Remove support for legacy iceServer.url eventually (Bug 1116766)
server.urls = [server.url];
this.logWarning("RTCIceServer.url is deprecated! Use urls instead.", null, 0);
}
});
this._mustValidateRTCConfiguration(rtcConfig, this._mustValidateRTCConfiguration(rtcConfig,
"RTCPeerConnection constructor passed invalid RTCConfiguration"); "RTCPeerConnection constructor passed invalid RTCConfiguration");
if (_globalPCList._networkdown || !this._win.navigator.onLine) { if (_globalPCList._networkdown || !this._win.navigator.onLine) {
@ -432,10 +443,11 @@ RTCPeerConnection.prototype = {
}, },
/** /**
* An RTCConfiguration looks like this: * An RTCConfiguration may look like this:
* *
* { "iceServers": [ { url:"stun:stun.example.org" }, * { "iceServers": [ { urls: "stun:stun.example.org", },
* { url:"turn:turn.example.org", * { url: "stun:stun.example.org", }, // deprecated version
* { urls: ["turn:turn1.x.org", "turn:turn2.x.org"],
* username:"jib", credential:"mypass"} ] } * username:"jib", credential:"mypass"} ] }
* *
* WebIDL normalizes structure for us, so we test well-formed stun/turn urls, * WebIDL normalizes structure for us, so we test well-formed stun/turn urls,
@ -456,27 +468,29 @@ RTCPeerConnection.prototype = {
}; };
rtcConfig.iceServers.forEach(server => { rtcConfig.iceServers.forEach(server => {
if (!server.url) { if (!server.urls) {
throw new this._win.DOMException(msg + " - missing url", "InvalidAccessError"); throw new this._win.DOMException(msg + " - missing urls", "InvalidAccessError");
} }
let url = nicerNewURI(server.url); server.urls.forEach(urlStr => {
if (url.scheme in { turn:1, turns:1 }) { let url = nicerNewURI(urlStr);
if (!server.username) { if (url.scheme in { turn:1, turns:1 }) {
throw new this._win.DOMException(msg + " - missing username: " + server.url, if (!server.username) {
"InvalidAccessError"); throw new this._win.DOMException(msg + " - missing username: " + urlStr,
"InvalidAccessError");
}
if (!server.credential) {
throw new this._win.DOMException(msg + " - missing credential: " + urlStr,
"InvalidAccessError");
}
} }
if (!server.credential) { else if (!(url.scheme in { stun:1, stuns:1 })) {
throw new this._win.DOMException(msg + " - missing credential: " + server.url, throw new this._win.DOMException(msg + " - improper scheme: " + url.scheme,
"InvalidAccessError"); "SyntaxError");
} }
} if (url.scheme in { stuns:1, turns:1 }) {
else if (!(url.scheme in { stun:1, stuns:1 })) { this.logWarning(url.scheme.toUpperCase() + " is not yet supported.", null, 0);
throw new this._win.DOMException(msg + " - improper scheme: " + url.scheme, }
"SyntaxError"); });
}
if (url.scheme in { stuns:1, turns:1 }) {
this.logWarning(url.scheme.toUpperCase() + " is not yet supported.", null, 0);
}
}); });
}, },

Просмотреть файл

@ -14,78 +14,66 @@
title: "RTCConfiguration valid/invalid permutations" title: "RTCConfiguration valid/invalid permutations"
}); });
makePC = function (config, expect_success) { makePC = (config, expected_error) => {
var exception = null; var exception;
var pc = null; try {
new mozRTCPeerConnection(config).close();
try { } catch (e) {
pc = new mozRTCPeerConnection(config); exception = e;
} catch (e) { }
exception = e; is((exception? exception.name : "success"), expected_error || "success",
} "mozRTCPeerConnection(" + JSON.stringify(config) + ")");
if (pc !== null) {
pc.close();
}
pc = null
if (expect_success) {
ok(!exception, "mozRTCPeerConnection(" +
JSON.stringify(config) + ") succeeds");
} else {
ok(exception, "mozRTCPeerConnection(" +
JSON.stringify(config) + ") throws");
}
} }
// This is a test of the iceServers parsing code + readable errors // This is a test of the iceServers parsing code + readable errors
runNetworkTest(function () { runNetworkTest(function () {
var pcs = null;
var exception = null; var exception = null;
var config;
try { try {
pcs = new mozRTCPeerConnection(); new mozRTCPeerConnection().close();
} catch (e) { } catch (e) {
exception = e; exception = e;
} }
ok(!exception, "mozRTCPeerConnection() succeeds"); ok(!exception, "mozRTCPeerConnection() succeeds");
if (pcs !== null) {
pcs.close();
}
pcs = null;
exception = null; exception = null;
makePC(1, false); makePC();
makePC({}, true); makePC(1, "TypeError");
makePC({ iceServers: [] }, true); makePC({});
makePC({ iceServers: [{ url:"" }] }, false); makePC({ iceServers: [] });
makePC({ iceServers: [{ urls:"" }] }, "SyntaxError");
makePC({ iceServers: [ makePC({ iceServers: [
{ url:"stun:127.0.0.1" }, { urls:"stun:127.0.0.1" },
{ url:"stuns:localhost", foo:"" }, { urls:"stun:localhost", foo:"" },
{ url:"turn:[::1]:3478", username:"p", credential:"p" }, { urls: ["stun:127.0.0.1", "stun:localhost"] },
{ url:"turns:localhost:3478?transport=udp", username:"p", credential:"p" } { urls:"stuns:localhost", foo:"" },
]}, true); { urls:"turn:[::1]:3478", username:"p", credential:"p" },
{ urls:"turn:localhost:3478?transport=udp", username:"p", credential:"p" },
{ urls: ["turn:[::1]:3478", "turn:localhost"], username:"p", credential:"p" },
{ urls:"turns:localhost:3478?transport=udp", username:"p", credential:"p" },
{ url:"stun:localhost", foo:"" },
{ url:"turn:localhost", username:"p", credential:"p" }
]});
makePC({ iceServers: [{ url:"turns:localhost:3478", username:"p" }] }, false); makePC({ iceServers: [{ urls: ["stun:127.0.0.1", ""] }] }, "SyntaxError");
makePC({ iceServers: [{ url:"turns:localhost:3478", credential:"p" }] }, false); makePC({ iceServers: [{ urls:"turns:localhost:3478", username:"p" }] }, "InvalidAccessError");
makePC({ iceServers: [{ url:"http:0.0.0.0" }] }, false); makePC({ iceServers: [{ url:"turns:localhost:3478", credential:"p" }] }, "InvalidAccessError");
makePC({ iceServers: [{ urls:"http:0.0.0.0" }] }, "SyntaxError");
try { try {
pcs = new mozRTCPeerConnection({ iceServers: [{ url:"http:0.0.0.0" }] }); new mozRTCPeerConnection({ iceServers: [{ url:"http:0.0.0.0" }] }).close();
} catch (e) { } catch (e) {
ok(e.message.indexOf("http") > 0, ok(e.message.indexOf("http") > 0,
"mozRTCPeerConnection() constructor has readable exceptions"); "mozRTCPeerConnection() constructor has readable exceptions");
} }
if (pcs !== null) {
pcs.close();
}
pcs = null;
networkTestFinished(); networkTestFinished();
}); });

Просмотреть файл

@ -23,7 +23,7 @@ namespace dom {
// This is an internal helper class and should not be used outside of this header. // This is an internal helper class and should not be used outside of this header.
struct AudioTimelineEvent { struct AudioTimelineEvent {
enum Type MOZ_ENUM_TYPE(uint32_t) { enum Type : uint32_t {
SetValue, SetValue,
LinearRamp, LinearRamp,
ExponentialRamp, ExponentialRamp,

Просмотреть файл

@ -48,18 +48,33 @@ NetworkStatsDB.prototype = {
return this.newTxn(txn_type, store_name, callback, successCb, errorCb); return this.newTxn(txn_type, store_name, callback, successCb, errorCb);
}, },
/**
* The onupgradeneeded handler of the IDBOpenDBRequest.
* This function is called in IndexedDBHelper open() method.
*
* @param {IDBTransaction} aTransaction
* {IDBDatabase} aDb
* {64-bit integer} aOldVersion The version number on local storage.
* {64-bit integer} aNewVersion The version number to be upgraded to.
*
* @note Be careful with the database upgrade pattern.
* Because IndexedDB operations are performed asynchronously, we must
* apply a recursive approach instead of an iterative approach while
* upgrading versions.
*/
upgradeSchema: function upgradeSchema(aTransaction, aDb, aOldVersion, aNewVersion) { upgradeSchema: function upgradeSchema(aTransaction, aDb, aOldVersion, aNewVersion) {
if (DEBUG) { if (DEBUG) {
debug("upgrade schema from: " + aOldVersion + " to " + aNewVersion + " called!"); debug("upgrade schema from: " + aOldVersion + " to " + aNewVersion + " called!");
} }
let db = aDb; let db = aDb;
let objectStore; let objectStore;
for (let currVersion = aOldVersion; currVersion < aNewVersion; currVersion++) {
if (currVersion == 0) {
/**
* Create the initial database schema.
*/
// An array of upgrade functions for each version.
let upgradeSteps = [
function upgrade0to1() {
if (DEBUG) debug("Upgrade 0 to 1: Create object stores and indexes.");
// Create the initial database schema.
objectStore = db.createObjectStore(DEPRECATED_STORE_NAME, { keyPath: ["connectionType", "timestamp"] }); objectStore = db.createObjectStore(DEPRECATED_STORE_NAME, { keyPath: ["connectionType", "timestamp"] });
objectStore.createIndex("connectionType", "connectionType", { unique: false }); objectStore.createIndex("connectionType", "connectionType", { unique: false });
objectStore.createIndex("timestamp", "timestamp", { unique: false }); objectStore.createIndex("timestamp", "timestamp", { unique: false });
@ -67,10 +82,18 @@ NetworkStatsDB.prototype = {
objectStore.createIndex("txBytes", "txBytes", { unique: false }); objectStore.createIndex("txBytes", "txBytes", { unique: false });
objectStore.createIndex("rxTotalBytes", "rxTotalBytes", { unique: false }); objectStore.createIndex("rxTotalBytes", "rxTotalBytes", { unique: false });
objectStore.createIndex("txTotalBytes", "txTotalBytes", { unique: false }); objectStore.createIndex("txTotalBytes", "txTotalBytes", { unique: false });
if (DEBUG) {
debug("Created object stores and indexes"); upgradeNextVersion();
} },
} else if (currVersion == 2) {
function upgrade1to2() {
if (DEBUG) debug("Upgrade 1 to 2: Do nothing.");
upgradeNextVersion();
},
function upgrade2to3() {
if (DEBUG) debug("Upgrade 2 to 3: Add keyPath appId to object store.");
// In order to support per-app traffic data storage, the original // In order to support per-app traffic data storage, the original
// objectStore needs to be replaced by a new objectStore with new // objectStore needs to be replaced by a new objectStore with new
// key path ("appId") and new index ("appId"). // key path ("appId") and new index ("appId").
@ -99,11 +122,13 @@ NetworkStatsDB.prototype = {
objectStore.createIndex("rxTotalBytes", "rxTotalBytes", { unique: false }); objectStore.createIndex("rxTotalBytes", "rxTotalBytes", { unique: false });
objectStore.createIndex("txTotalBytes", "txTotalBytes", { unique: false }); objectStore.createIndex("txTotalBytes", "txTotalBytes", { unique: false });
if (DEBUG) { upgradeNextVersion();
debug("Created object stores and indexes for version 3"); },
}
} else if (currVersion == 3) { function upgrade3to4() {
// Delete redundent indexes (leave "network" only). if (DEBUG) debug("Upgrade 3 to 4: Delete redundant indexes.");
// Delete redundant indexes (leave "network" only).
objectStore = aTransaction.objectStore(DEPRECATED_STORE_NAME); objectStore = aTransaction.objectStore(DEPRECATED_STORE_NAME);
if (objectStore.indexNames.contains("appId")) { if (objectStore.indexNames.contains("appId")) {
objectStore.deleteIndex("appId"); objectStore.deleteIndex("appId");
@ -127,10 +152,12 @@ NetworkStatsDB.prototype = {
objectStore.deleteIndex("txTotalBytes"); objectStore.deleteIndex("txTotalBytes");
} }
if (DEBUG) { upgradeNextVersion();
debug("Deleted redundent indexes for version 4"); },
}
} else if (currVersion == 4) { function upgrade4to5() {
if (DEBUG) debug("Upgrade 4 to 5: Create object store for alarms.");
// In order to manage alarms, it is necessary to use a global counter // In order to manage alarms, it is necessary to use a global counter
// (totalBytes) that will increase regardless of the system reboot. // (totalBytes) that will increase regardless of the system reboot.
objectStore = aTransaction.objectStore(DEPRECATED_STORE_NAME); objectStore = aTransaction.objectStore(DEPRECATED_STORE_NAME);
@ -143,6 +170,8 @@ NetworkStatsDB.prototype = {
objectStore.openCursor().onsuccess = function(event) { objectStore.openCursor().onsuccess = function(event) {
let cursor = event.target.result; let cursor = event.target.result;
if (!cursor){ if (!cursor){
// upgrade4to5 completed now.
upgradeNextVersion();
return; return;
} }
@ -188,11 +217,11 @@ NetworkStatsDB.prototype = {
objectStore = db.createObjectStore(ALARMS_STORE_NAME, { keyPath: "id", autoIncrement: true }); objectStore = db.createObjectStore(ALARMS_STORE_NAME, { keyPath: "id", autoIncrement: true });
objectStore.createIndex("alarm", ['networkId','threshold'], { unique: false }); objectStore.createIndex("alarm", ['networkId','threshold'], { unique: false });
objectStore.createIndex("manifestURL", "manifestURL", { unique: false }); objectStore.createIndex("manifestURL", "manifestURL", { unique: false });
},
function upgrade5to6() {
if (DEBUG) debug("Upgrade 5 to 6: Add keyPath serviceType to object store.");
if (DEBUG) {
debug("Created alarms store for version 5");
}
} else if (currVersion == 5) {
// In contrast to "per-app" traffic data, "system-only" traffic data // In contrast to "per-app" traffic data, "system-only" traffic data
// refers to data which can not be identified by any applications. // refers to data which can not be identified by any applications.
// To further support "system-only" data storage, the data can be // To further support "system-only" data storage, the data can be
@ -209,6 +238,8 @@ NetworkStatsDB.prototype = {
let cursor = event.target.result; let cursor = event.target.result;
if (!cursor) { if (!cursor) {
db.deleteObjectStore(DEPRECATED_STORE_NAME); db.deleteObjectStore(DEPRECATED_STORE_NAME);
// upgrade5to6 completed now.
upgradeNextVersion();
return; return;
} }
@ -217,11 +248,11 @@ NetworkStatsDB.prototype = {
newObjectStore.put(newStats); newObjectStore.put(newStats);
cursor.continue(); cursor.continue();
}; };
},
function upgrade6to7() {
if (DEBUG) debug("Upgrade 6 to 7: Replace alarm threshold by relativeThreshold.");
if (DEBUG) {
debug("Added new key 'serviceType' for version 6");
}
} else if (currVersion == 6) {
// Replace threshold attribute of alarm index by relativeThreshold in alarms DB. // Replace threshold attribute of alarm index by relativeThreshold in alarms DB.
// Now alarms are indexed by relativeThreshold, which is the threshold relative // Now alarms are indexed by relativeThreshold, which is the threshold relative
// to current system stats. // to current system stats.
@ -239,6 +270,7 @@ NetworkStatsDB.prototype = {
alarmsStore.openCursor().onsuccess = function(event) { alarmsStore.openCursor().onsuccess = function(event) {
let cursor = event.target.result; let cursor = event.target.result;
if (!cursor) { if (!cursor) {
upgrade6to7_updateTotalBytes();
return; return;
} }
@ -250,75 +282,132 @@ NetworkStatsDB.prototype = {
cursor.continue(); cursor.continue();
} }
// Previous versions save accumulative totalBytes, increasing althought the system function upgrade6to7_updateTotalBytes() {
// reboots or resets stats. But is necessary to reset the total counters when reset if (DEBUG) debug("Upgrade 6 to 7: Update TotalBytes.");
// through 'clearInterfaceStats'. // Previous versions save accumulative totalBytes, increasing although the system
let statsStore = aTransaction.objectStore(STATS_STORE_NAME); // reboots or resets stats. But is necessary to reset the total counters when reset
let networks = []; // through 'clearInterfaceStats'.
// Find networks stored in the database. let statsStore = aTransaction.objectStore(STATS_STORE_NAME);
statsStore.index("network").openKeyCursor(null, "nextunique").onsuccess = function(event) { let networks = [];
let cursor = event.target.result;
if (cursor) {
networks.push(cursor.key);
cursor.continue();
return;
}
networks.forEach(function(network) { // Find networks stored in the database.
let lowerFilter = [0, "", network, 0]; statsStore.index("network").openKeyCursor(null, "nextunique").onsuccess = function(event) {
let upperFilter = [0, "", network, ""]; let cursor = event.target.result;
let range = IDBKeyRange.bound(lowerFilter, upperFilter, false, false);
// Find number of samples for a given network. // Store each network into an array.
statsStore.count(range).onsuccess = function(event) { if (cursor) {
// If there are more samples than the max allowed, there is no way to know networks.push(cursor.key);
// when does reset take place. cursor.continue();
if (event.target.result >= VALUES_MAX_LENGTH) { return;
return; }
}
let last = null; // Start to deal with each network.
// Reset detected if the first sample totalCounters are different than bytes let pending = networks.length;
// counters. If so, the total counters should be recalculated.
statsStore.openCursor(range).onsuccess = function(event) { if (pending === 0) {
let cursor = event.target.result; // Found no records of network. upgrade6to7 completed now.
if (!cursor) { upgradeNextVersion();
return;
}
networks.forEach(function(network) {
let lowerFilter = [0, "", network, 0];
let upperFilter = [0, "", network, ""];
let range = IDBKeyRange.bound(lowerFilter, upperFilter, false, false);
// Find number of samples for a given network.
statsStore.count(range).onsuccess = function(event) {
let recordCount = event.target.result;
// If there are more samples than the max allowed, there is no way to know
// when does reset take place.
if (recordCount === 0 || recordCount >= VALUES_MAX_LENGTH) {
pending--;
if (pending === 0) {
upgradeNextVersion();
}
return; return;
} }
if (!last) {
if (cursor.value.rxTotalBytes == cursor.value.rxBytes && let last = null;
cursor.value.txTotalBytes == cursor.value.txBytes) { // Reset detected if the first sample totalCounters are different than bytes
// counters. If so, the total counters should be recalculated.
statsStore.openCursor(range).onsuccess = function(event) {
let cursor = event.target.result;
if (!cursor) {
pending--;
if (pending === 0) {
upgradeNextVersion();
}
return;
}
if (!last) {
if (cursor.value.rxTotalBytes == cursor.value.rxBytes &&
cursor.value.txTotalBytes == cursor.value.txBytes) {
pending--;
if (pending === 0) {
upgradeNextVersion();
}
return;
}
cursor.value.rxTotalBytes = cursor.value.rxBytes;
cursor.value.txTotalBytes = cursor.value.txBytes;
cursor.update(cursor.value);
last = cursor.value;
cursor.continue();
return; return;
} }
cursor.value.rxTotalBytes = cursor.value.rxBytes; // Recalculate the total counter for last / current sample
cursor.value.txTotalBytes = cursor.value.txBytes; cursor.value.rxTotalBytes = last.rxTotalBytes + cursor.value.rxBytes;
cursor.value.txTotalBytes = last.txTotalBytes + cursor.value.txBytes;
cursor.update(cursor.value); cursor.update(cursor.value);
last = cursor.value; last = cursor.value;
cursor.continue(); cursor.continue();
return;
} }
// Recalculate the total counter for last / current sample
cursor.value.rxTotalBytes = last.rxTotalBytes + cursor.value.rxBytes;
cursor.value.txTotalBytes = last.txTotalBytes + cursor.value.txBytes;
cursor.update(cursor.value);
last = cursor.value;
cursor.continue();
} }
} }, this); // end of networks.forEach()
}, this); }; // end of statsStore.index("network").openKeyCursor().onsuccess callback
}; } // end of function upgrade6to7_updateTotalBytes
} else if (currVersion == 7) { },
function upgrade7to8() {
if (DEBUG) debug("Upgrade 7 to 8: Create index serviceType.");
// Create index for 'ServiceType' in order to make it retrievable. // Create index for 'ServiceType' in order to make it retrievable.
let statsStore = aTransaction.objectStore(STATS_STORE_NAME); let statsStore = aTransaction.objectStore(STATS_STORE_NAME);
statsStore.createIndex("serviceType", "serviceType", { unique: false }); statsStore.createIndex("serviceType", "serviceType", { unique: false });
},
];
if (DEBUG) { let index = aOldVersion;
debug("Create index of 'serviceType' for version 8"); let outer = this;
}
function upgradeNextVersion() {
if (index == aNewVersion) {
debug("Upgrade finished.");
return;
}
try {
var i = index++;
if (DEBUG) debug("Upgrade step: " + i + "\n");
upgradeSteps[i].call(outer);
} catch (ex) {
dump("Caught exception " + ex);
throw ex;
return;
} }
} }
if (aNewVersion > upgradeSteps.length) {
debug("No migration steps for the new version!");
aTransaction.abort();
return;
}
upgradeNextVersion();
}, },
importData: function importData(aStats) { importData: function importData(aStats) {

Просмотреть файл

@ -1557,6 +1557,10 @@ nsPluginHost::ClearSiteData(nsIPluginTag* plugin, const nsACString& domain,
nsPluginTag* tag = static_cast<nsPluginTag*>(plugin); nsPluginTag* tag = static_cast<nsPluginTag*>(plugin);
if (!tag->IsEnabled()) {
return NS_ERROR_NOT_AVAILABLE;
}
// We only ensure support for clearing Flash site data for now. // We only ensure support for clearing Flash site data for now.
// We will also attempt to clear data for any plugin that happens // We will also attempt to clear data for any plugin that happens
// to be loaded already. // to be loaded already.

Просмотреть файл

@ -90,8 +90,7 @@ SVGCircleElement::GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
if (r <= 0.f) { if (r <= 0.f) {
// Rendering of the element is disabled // Rendering of the element is disabled
aBounds->MoveTo(x, y); *aBounds = Rect(aTransform * Point(x, y), Size());
aBounds->SetEmpty();
return true; return true;
} }

Просмотреть файл

@ -101,8 +101,7 @@ SVGEllipseElement::GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
if (rx <= 0.f || ry <= 0.f) { if (rx <= 0.f || ry <= 0.f) {
// Rendering of the element is disabled // Rendering of the element is disabled
aBounds->MoveTo(x, y); *aBounds = Rect(aTransform * Point(x, y), Size());
aBounds->SetEmpty();
return true; return true;
} }

Просмотреть файл

@ -226,6 +226,23 @@ SVGImageElement::IsAttributeMapped(const nsIAtom* name) const
/* For the purposes of the update/invalidation logic pretend to /* For the purposes of the update/invalidation logic pretend to
be a rectangle. */ be a rectangle. */
bool
SVGImageElement::GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
const Matrix& aTransform)
{
Rect rect;
GetAnimatedLengthValues(&rect.x, &rect.y, &rect.width,
&rect.height, nullptr);
if (rect.IsEmpty()) {
// Rendering of the element disabled
rect.SetEmpty(); // Make sure width/height are zero and not negative
}
*aBounds = aTransform.TransformBounds(rect);
return true;
}
TemporaryRef<Path> TemporaryRef<Path>
SVGImageElement::BuildPath(PathBuilder* aBuilder) SVGImageElement::BuildPath(PathBuilder* aBuilder)
{ {

Просмотреть файл

@ -53,6 +53,8 @@ public:
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* name) const MOZ_OVERRIDE; NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* name) const MOZ_OVERRIDE;
// nsSVGPathGeometryElement methods: // nsSVGPathGeometryElement methods:
virtual bool GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
const Matrix& aTransform) MOZ_OVERRIDE;
virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder) MOZ_OVERRIDE; virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder) MOZ_OVERRIDE;
// nsSVGSVGElement methods: // nsSVGSVGElement methods:

Просмотреть файл

@ -17,7 +17,7 @@
namespace mozilla { namespace mozilla {
// Alignment Types // Alignment Types
enum SVGAlign MOZ_ENUM_TYPE(uint8_t) { enum SVGAlign : uint8_t {
SVG_PRESERVEASPECTRATIO_UNKNOWN = 0, SVG_PRESERVEASPECTRATIO_UNKNOWN = 0,
SVG_PRESERVEASPECTRATIO_NONE = 1, SVG_PRESERVEASPECTRATIO_NONE = 1,
SVG_PRESERVEASPECTRATIO_XMINYMIN = 2, SVG_PRESERVEASPECTRATIO_XMINYMIN = 2,
@ -37,7 +37,7 @@ const uint16_t SVG_ALIGN_MIN_VALID = SVG_PRESERVEASPECTRATIO_NONE;
const uint16_t SVG_ALIGN_MAX_VALID = SVG_PRESERVEASPECTRATIO_XMAXYMAX; const uint16_t SVG_ALIGN_MAX_VALID = SVG_PRESERVEASPECTRATIO_XMAXYMAX;
// Meet-or-slice Types // Meet-or-slice Types
enum SVGMeetOrSlice MOZ_ENUM_TYPE(uint8_t) { enum SVGMeetOrSlice : uint8_t {
SVG_MEETORSLICE_UNKNOWN = 0, SVG_MEETORSLICE_UNKNOWN = 0,
SVG_MEETORSLICE_MEET = 1, SVG_MEETORSLICE_MEET = 1,
SVG_MEETORSLICE_SLICE = 2 SVG_MEETORSLICE_SLICE = 2

Просмотреть файл

@ -122,7 +122,8 @@ SVGRectElement::GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
if (rect.IsEmpty()) { if (rect.IsEmpty()) {
// Rendering of the element disabled // Rendering of the element disabled
rect.SetEmpty(); // Make sure width/height are zero and not negative rect.SetEmpty(); // Make sure width/height are zero and not negative
*aBounds = rect; // We still want the x/y position from 'rect' // We still want the x/y position from 'rect'
*aBounds = aTransform.TransformBounds(rect);
return true; return true;
} }

Просмотреть файл

@ -1247,5 +1247,33 @@ SVGSVGElement::ClearTransformProperty()
return UnsetProperty(nsGkAtoms::transform); return UnsetProperty(nsGkAtoms::transform);
} }
int32_t
SVGSVGElement::GetIntrinsicWidth()
{
if (mLengthAttributes[ATTR_WIDTH].IsPercentage()) {
return -1;
}
// Passing |this| as a SVGSVGElement* invokes the variant of GetAnimValue
// that uses the passed argument as the context, but that's fine since we
// know the length isn't a percentage so the context won't be used (and we
// need to pass the element to be able to resolve em/ex units).
float width = mLengthAttributes[ATTR_WIDTH].GetAnimValue(this);
return nsSVGUtils::ClampToInt(width);
}
int32_t
SVGSVGElement::GetIntrinsicHeight()
{
if (mLengthAttributes[ATTR_HEIGHT].IsPercentage()) {
return -1;
}
// Passing |this| as a SVGSVGElement* invokes the variant of GetAnimValue
// that uses the passed argument as the context, but that's fine since we
// know the length isn't a percentage so the context won't be used (and we
// need to pass the element to be able to resolve em/ex units).
float height = mLengthAttributes[ATTR_HEIGHT].GetAnimValue(this);
return nsSVGUtils::ClampToInt(height);
}
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla

Просмотреть файл

@ -147,6 +147,15 @@ public:
// public helpers: // public helpers:
/**
* Returns -1 if the width/height is a percentage, else returns the user unit
* length clamped to fit in a int32_t.
* XXX see bug 1112533 comment 3 - we should fix drawImage so that we can
* change these methods to make zero the error flag for percentages.
*/
int32_t GetIntrinsicWidth();
int32_t GetIntrinsicHeight();
/** /**
* Returns true if this element has a base/anim value for its "viewBox" * Returns true if this element has a base/anim value for its "viewBox"
* attribute that defines a viewBox rectangle with finite values, or * attribute that defines a viewBox rectangle with finite values, or

Просмотреть файл

@ -8,7 +8,8 @@
*/ */
dictionary RTCIceServer { dictionary RTCIceServer {
DOMString url; (DOMString or sequence<DOMString>) urls;
DOMString url; //deprecated
DOMString? credential = null; DOMString? credential = null;
DOMString? username = null; DOMString? username = null;
}; };

Просмотреть файл

@ -125,8 +125,11 @@ SVGTurbulenceRenderer<Type,Stitch,f32x4_t,i32x4_t,u8x16_t>::InitFromSeed(int32_t
float gradient[4][sBSize][2]; float gradient[4][sBSize][2];
for (int32_t k = 0; k < 4; k++) { for (int32_t k = 0; k < 4; k++) {
for (int32_t i = 0; i < sBSize; i++) { for (int32_t i = 0; i < sBSize; i++) {
float a = float((rand.Next() % (sBSize + sBSize)) - sBSize) / sBSize; float a, b;
float b = float((rand.Next() % (sBSize + sBSize)) - sBSize) / sBSize; do {
a = float((rand.Next() % (sBSize + sBSize)) - sBSize) / sBSize;
b = float((rand.Next() % (sBSize + sBSize)) - sBSize) / sBSize;
} while (a == 0 && b == 0);
float s = sqrt(a * a + b * b); float s = sqrt(a * a + b * b);
gradient[k][i][0] = a / s; gradient[k][i][0] = a / s;
gradient[k][i][1] = b / s; gradient[k][i][1] = b / s;

Просмотреть файл

@ -1050,6 +1050,7 @@ CompositorD3D11::BeginFrame(const nsIntRegion& aInvalidRegion,
return; return;
} }
nsIntSize oldSize = mSize;
UpdateRenderTarget(); UpdateRenderTarget();
// Failed to create a render target or the view. // Failed to create a render target or the view.
@ -1069,7 +1070,13 @@ CompositorD3D11::BeginFrame(const nsIntRegion& aInvalidRegion,
nsIntRect intRect = nsIntRect(nsIntPoint(0, 0), mSize); nsIntRect intRect = nsIntRect(nsIntPoint(0, 0), mSize);
// Sometimes the invalid region is larger than we want to draw. // Sometimes the invalid region is larger than we want to draw.
nsIntRegion invalidRegionSafe; nsIntRegion invalidRegionSafe;
invalidRegionSafe.And(aInvalidRegion, intRect);
if (mSize != oldSize) {
invalidRegionSafe = intRect;
} else {
invalidRegionSafe.And(aInvalidRegion, intRect);
}
nsIntRect invalidRect = invalidRegionSafe.GetBounds(); nsIntRect invalidRect = invalidRegionSafe.GetBounds();
mInvalidRect = IntRect(invalidRect.x, invalidRect.y, invalidRect.width, invalidRect.height); mInvalidRect = IntRect(invalidRect.x, invalidRect.y, invalidRect.width, invalidRect.height);
mInvalidRegion = invalidRegionSafe; mInvalidRegion = invalidRegionSafe;

Просмотреть файл

@ -239,7 +239,7 @@ private:
DECL_GFX_PREF(Live, "image.high_quality_downscaling.min_factor", ImageHQDownscalingMinFactor, uint32_t, 1000); DECL_GFX_PREF(Live, "image.high_quality_downscaling.min_factor", ImageHQDownscalingMinFactor, uint32_t, 1000);
DECL_GFX_PREF(Live, "image.high_quality_upscaling.max_size", ImageHQUpscalingMaxSize, uint32_t, 20971520); DECL_GFX_PREF(Live, "image.high_quality_upscaling.max_size", ImageHQUpscalingMaxSize, uint32_t, 20971520);
DECL_GFX_PREF(Once, "image.mem.decode_bytes_at_a_time", ImageMemDecodeBytesAtATime, uint32_t, 200000); DECL_GFX_PREF(Once, "image.mem.decode_bytes_at_a_time", ImageMemDecodeBytesAtATime, uint32_t, 200000);
DECL_GFX_PREF(Live, "image.mem.decodeondraw", ImageMemDecodeOnDraw, bool, false); DECL_GFX_PREF(Live, "image.mem.decodeondraw", ImageMemDecodeOnDraw, bool, true);
DECL_GFX_PREF(Live, "image.mem.discardable", ImageMemDiscardable, bool, false); DECL_GFX_PREF(Live, "image.mem.discardable", ImageMemDiscardable, bool, false);
DECL_GFX_PREF(Once, "image.mem.surfacecache.discard_factor", ImageMemSurfaceCacheDiscardFactor, uint32_t, 1); DECL_GFX_PREF(Once, "image.mem.surfacecache.discard_factor", ImageMemSurfaceCacheDiscardFactor, uint32_t, 1);
DECL_GFX_PREF(Once, "image.mem.surfacecache.max_size_kb", ImageMemSurfaceCacheMaxSizeKB, uint32_t, 100 * 1024); DECL_GFX_PREF(Once, "image.mem.surfacecache.max_size_kb", ImageMemSurfaceCacheMaxSizeKB, uint32_t, 100 * 1024);

Просмотреть файл

@ -68,45 +68,6 @@ SVGDocumentWrapper::DestroyViewer()
} }
} }
bool
SVGDocumentWrapper::GetWidthOrHeight(Dimension aDimension,
int32_t& aResult)
{
SVGSVGElement* rootElem = GetRootSVGElem();
NS_ABORT_IF_FALSE(rootElem, "root elem missing or of wrong type");
// Get the width or height SVG object
nsRefPtr<SVGAnimatedLength> domAnimLength;
if (aDimension == eWidth) {
domAnimLength = rootElem->Width();
} else {
NS_ABORT_IF_FALSE(aDimension == eHeight, "invalid dimension");
domAnimLength = rootElem->Height();
}
NS_ENSURE_TRUE(domAnimLength, false);
// Get the animated value from the object
nsRefPtr<DOMSVGLength> domLength = domAnimLength->AnimVal();
NS_ENSURE_TRUE(domLength, false);
// Check if it's a percent value (and fail if so)
uint16_t unitType;
nsresult rv = domLength->GetUnitType(&unitType);
NS_ENSURE_SUCCESS(rv, false);
if (unitType == nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE) {
return false;
}
// Non-percent value - woot! Grab it & return it.
float floatLength;
rv = domLength->GetValue(&floatLength);
NS_ENSURE_SUCCESS(rv, false);
aResult = nsSVGUtils::ClampToInt(floatLength);
return true;
}
nsIFrame* nsIFrame*
SVGDocumentWrapper::GetRootLayoutFrame() SVGDocumentWrapper::GetRootLayoutFrame()
{ {

Просмотреть файл

@ -52,21 +52,6 @@ public:
eHeight eHeight
}; };
/**
* Looks up the value of the wrapped SVG document's |width| or |height|
* attribute in CSS pixels, and returns it by reference. If the document has
* a percent value for the queried attribute, then this method fails
* (returns false).
*
* @param aDimension Indicates whether the width or height is desired.
* @param[out] aResult If this method succeeds, then this outparam will be
populated with the width or height in CSS pixels.
* @return false to indicate failure, if the queried attribute has a
* percent value. Otherwise, true.
*
*/
bool GetWidthOrHeight(Dimension aDimension, int32_t& aResult);
/** /**
* Returns the wrapped document, or nullptr on failure. (No AddRef.) * Returns the wrapped document, or nullptr on failure. (No AddRef.)
*/ */

Просмотреть файл

@ -472,17 +472,14 @@ NS_IMETHODIMP
VectorImage::GetWidth(int32_t* aWidth) VectorImage::GetWidth(int32_t* aWidth)
{ {
if (mError || !mIsFullyLoaded) { if (mError || !mIsFullyLoaded) {
*aWidth = 0; *aWidth = -1;
return NS_ERROR_FAILURE; } else {
SVGSVGElement* rootElem = mSVGDocumentWrapper->GetRootSVGElem();
MOZ_ASSERT(rootElem, "Should have a root SVG elem, since we finished "
"loading without errors");
*aWidth = rootElem->GetIntrinsicWidth();
} }
return *aWidth >= 0 ? NS_OK : NS_ERROR_FAILURE;
if (!mSVGDocumentWrapper->GetWidthOrHeight(SVGDocumentWrapper::eWidth,
*aWidth)) {
*aWidth = 0;
return NS_ERROR_FAILURE;
}
return NS_OK;
} }
//****************************************************************************** //******************************************************************************
@ -541,17 +538,14 @@ NS_IMETHODIMP
VectorImage::GetHeight(int32_t* aHeight) VectorImage::GetHeight(int32_t* aHeight)
{ {
if (mError || !mIsFullyLoaded) { if (mError || !mIsFullyLoaded) {
*aHeight = 0; *aHeight = -1;
return NS_ERROR_FAILURE; } else {
SVGSVGElement* rootElem = mSVGDocumentWrapper->GetRootSVGElem();
MOZ_ASSERT(rootElem, "Should have a root SVG elem, since we finished "
"loading without errors");
*aHeight = rootElem->GetIntrinsicHeight();
} }
return *aHeight >= 0 ? NS_OK : NS_ERROR_FAILURE;
if (!mSVGDocumentWrapper->GetWidthOrHeight(SVGDocumentWrapper::eHeight,
*aHeight)) {
*aHeight = 0;
return NS_ERROR_FAILURE;
}
return NS_OK;
} }
//****************************************************************************** //******************************************************************************
@ -663,17 +657,20 @@ VectorImage::GetFrame(uint32_t aWhichFrame,
if (aWhichFrame > FRAME_MAX_VALUE) if (aWhichFrame > FRAME_MAX_VALUE)
return nullptr; return nullptr;
if (mError) if (mError || !mIsFullyLoaded)
return nullptr; return nullptr;
// Look up height & width // Look up height & width
// ---------------------- // ----------------------
nsIntSize imageIntSize; SVGSVGElement* svgElem = mSVGDocumentWrapper->GetRootSVGElem();
if (!mSVGDocumentWrapper->GetWidthOrHeight(SVGDocumentWrapper::eWidth, MOZ_ASSERT(svgElem, "Should have a root SVG elem, since we finished "
imageIntSize.width) || "loading without errors");
!mSVGDocumentWrapper->GetWidthOrHeight(SVGDocumentWrapper::eHeight, nsIntSize imageIntSize(svgElem->GetIntrinsicWidth(),
imageIntSize.height)) { svgElem->GetIntrinsicHeight());
// We'll get here if our SVG doc has a percent-valued width or height.
if (imageIntSize.IsEmpty()) {
// We'll get here if our SVG doc has a percent-valued or negative width or
// height.
return nullptr; return nullptr;
} }

Просмотреть файл

@ -9,9 +9,8 @@ SOURCES += [
] ]
FINAL_LIBRARY = 'xul' FINAL_LIBRARY = 'xul'
CXXFLAGS += CONFIG['MOZ_ICU_CFLAGS']
LOCAL_INCLUDES += [ LOCAL_INCLUDES += [
'../icu/source/common',
'../icu/source/i18n',
'../locale', '../locale',
'../lwbrk', '../lwbrk',
'../strres', '../strres',

Просмотреть файл

@ -11,10 +11,9 @@ UNIFIED_SOURCES += [
] ]
FINAL_LIBRARY = 'xul' FINAL_LIBRARY = 'xul'
CXXFLAGS += CONFIG['MOZ_ICU_CFLAGS']
LOCAL_INCLUDES += [ LOCAL_INCLUDES += [
'..', '..',
'../../icu/source/common',
'../../icu/source/i18n',
] ]
FAIL_ON_WARNINGS = True FAIL_ON_WARNINGS = True

Просмотреть файл

@ -3052,18 +3052,6 @@ MOZ_ARG_WITH_STRING(wrap-malloc,
[ --with-wrap-malloc=DIR Location of malloc wrapper library], [ --with-wrap-malloc=DIR Location of malloc wrapper library],
WRAP_LDFLAGS="${WRAP_LDFLAGS} $withval") WRAP_LDFLAGS="${WRAP_LDFLAGS} $withval")
dnl ========================================================
dnl = Use compacting GC
dnl ========================================================
dnl Compact the heap by moving GC things when doing a shrinking colletion.
MOZ_ARG_ENABLE_BOOL(gccompacting,
[ --enable-gccompacting Compact the heap by moving GC things],
JSGC_COMPACTING=1,
JSGC_COMPACTING= )
if test -n "$JSGC_COMPACTING"; then
AC_DEFINE(JSGC_COMPACTING)
fi
dnl ======================================================== dnl ========================================================
dnl = Use a smaller chunk size for GC chunks dnl = Use a smaller chunk size for GC chunks
dnl ======================================================== dnl ========================================================

Просмотреть файл

@ -3257,6 +3257,8 @@ EmitDestructuringDeclsWithEmitter(ExclusiveContext *cx, BytecodeEmitter *bce, JS
MOZ_ASSERT(element->pn_kid->isKind(PNK_NAME)); MOZ_ASSERT(element->pn_kid->isKind(PNK_NAME));
target = element->pn_kid; target = element->pn_kid;
} }
if (target->isKind(PNK_ASSIGN))
target = target->pn_left;
if (target->isKind(PNK_NAME)) { if (target->isKind(PNK_NAME)) {
if (!EmitName(cx, bce, prologOp, target)) if (!EmitName(cx, bce, prologOp, target))
return false; return false;
@ -3276,6 +3278,8 @@ EmitDestructuringDeclsWithEmitter(ExclusiveContext *cx, BytecodeEmitter *bce, JS
ParseNode *target = member->isKind(PNK_MUTATEPROTO) ? member->pn_kid : member->pn_right; ParseNode *target = member->isKind(PNK_MUTATEPROTO) ? member->pn_kid : member->pn_right;
if (target->isKind(PNK_ASSIGN))
target = target->pn_left;
if (target->isKind(PNK_NAME)) { if (target->isKind(PNK_NAME)) {
if (!EmitName(cx, bce, prologOp, target)) if (!EmitName(cx, bce, prologOp, target))
return false; return false;
@ -3341,7 +3345,7 @@ EmitDestructuringOpsHelper(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode
* lhs expression. (Same post-condition as EmitDestructuringOpsHelper) * lhs expression. (Same post-condition as EmitDestructuringOpsHelper)
*/ */
static bool static bool
EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, VarEmitOption emitOption) EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *target, VarEmitOption emitOption)
{ {
MOZ_ASSERT(emitOption != DefineVars); MOZ_ASSERT(emitOption != DefineVars);
@ -3349,10 +3353,12 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn,
// destructuring initialiser-form, call ourselves to handle it, then pop // destructuring initialiser-form, call ourselves to handle it, then pop
// the matched value. Otherwise emit an lvalue bytecode sequence followed // the matched value. Otherwise emit an lvalue bytecode sequence followed
// by an assignment op. // by an assignment op.
if (pn->isKind(PNK_SPREAD)) if (target->isKind(PNK_SPREAD))
pn = pn->pn_kid; target = target->pn_kid;
if (pn->isKind(PNK_ARRAY) || pn->isKind(PNK_OBJECT)) { else if (target->isKind(PNK_ASSIGN))
if (!EmitDestructuringOpsHelper(cx, bce, pn, emitOption)) target = target->pn_left;
if (target->isKind(PNK_ARRAY) || target->isKind(PNK_OBJECT)) {
if (!EmitDestructuringOpsHelper(cx, bce, target, emitOption))
return false; return false;
if (emitOption == InitializeVars) { if (emitOption == InitializeVars) {
// Per its post-condition, EmitDestructuringOpsHelper has left the // Per its post-condition, EmitDestructuringOpsHelper has left the
@ -3363,15 +3369,15 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn,
} else if (emitOption == PushInitialValues) { } else if (emitOption == PushInitialValues) {
// The lhs is a simple name so the to-be-destructured value is // The lhs is a simple name so the to-be-destructured value is
// its initial value and there is nothing to do. // its initial value and there is nothing to do.
MOZ_ASSERT(pn->getOp() == JSOP_SETLOCAL || pn->getOp() == JSOP_INITLEXICAL); MOZ_ASSERT(target->getOp() == JSOP_SETLOCAL || target->getOp() == JSOP_INITLEXICAL);
MOZ_ASSERT(pn->pn_dflags & PND_BOUND); MOZ_ASSERT(target->pn_dflags & PND_BOUND);
} else { } else {
switch (pn->getKind()) { switch (target->getKind()) {
case PNK_NAME: case PNK_NAME:
if (!BindNameToSlot(cx, bce, pn)) if (!BindNameToSlot(cx, bce, target))
return false; return false;
switch (pn->getOp()) { switch (target->getOp()) {
case JSOP_SETNAME: case JSOP_SETNAME:
case JSOP_STRICTSETNAME: case JSOP_STRICTSETNAME:
case JSOP_SETGNAME: case JSOP_SETGNAME:
@ -3388,11 +3394,11 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn,
// but the operands are on the stack in the wrong order for // but the operands are on the stack in the wrong order for
// JSOP_SETPROP, so we have to add a JSOP_SWAP. // JSOP_SETPROP, so we have to add a JSOP_SWAP.
jsatomid atomIndex; jsatomid atomIndex;
if (!bce->makeAtomIndex(pn->pn_atom, &atomIndex)) if (!bce->makeAtomIndex(target->pn_atom, &atomIndex))
return false; return false;
if (!pn->isOp(JSOP_SETCONST)) { if (!target->isOp(JSOP_SETCONST)) {
bool global = pn->isOp(JSOP_SETGNAME) || pn->isOp(JSOP_STRICTSETGNAME); bool global = target->isOp(JSOP_SETGNAME) || target->isOp(JSOP_STRICTSETGNAME);
JSOp bindOp = global ? JSOP_BINDGNAME : JSOP_BINDNAME; JSOp bindOp = global ? JSOP_BINDGNAME : JSOP_BINDNAME;
if (!EmitIndex32(cx, bindOp, atomIndex, bce)) if (!EmitIndex32(cx, bindOp, atomIndex, bce))
return false; return false;
@ -3400,7 +3406,7 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn,
return false; return false;
} }
if (!EmitIndexOp(cx, pn->getOp(), atomIndex, bce)) if (!EmitIndexOp(cx, target->getOp(), atomIndex, bce))
return false; return false;
break; break;
} }
@ -3408,7 +3414,7 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn,
case JSOP_SETLOCAL: case JSOP_SETLOCAL:
case JSOP_SETARG: case JSOP_SETARG:
case JSOP_INITLEXICAL: case JSOP_INITLEXICAL:
if (!EmitVarOp(cx, pn, pn->getOp(), bce)) if (!EmitVarOp(cx, target, target->getOp(), bce))
return false; return false;
break; break;
@ -3427,12 +3433,12 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn,
// In `[a.x] = [b]`, per spec, `b` is evaluated before `a`. Then we // In `[a.x] = [b]`, per spec, `b` is evaluated before `a`. Then we
// need a property set -- but the operands are on the stack in the // need a property set -- but the operands are on the stack in the
// wrong order for JSOP_SETPROP, so we have to add a JSOP_SWAP. // wrong order for JSOP_SETPROP, so we have to add a JSOP_SWAP.
if (!EmitTree(cx, bce, pn->pn_expr)) if (!EmitTree(cx, bce, target->pn_expr))
return false; return false;
if (Emit1(cx, bce, JSOP_SWAP) < 0) if (Emit1(cx, bce, JSOP_SWAP) < 0)
return false; return false;
JSOp setOp = bce->sc->strict ? JSOP_STRICTSETPROP : JSOP_SETPROP; JSOp setOp = bce->sc->strict ? JSOP_STRICTSETPROP : JSOP_SETPROP;
if (!EmitAtomOp(cx, pn, setOp, bce)) if (!EmitAtomOp(cx, target, setOp, bce))
return false; return false;
break; break;
} }
@ -3443,14 +3449,14 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn,
// `[a[x]] = [b]`, is handled much the same way. The JSOP_SWAP // `[a[x]] = [b]`, is handled much the same way. The JSOP_SWAP
// is emitted by EmitElemOperands. // is emitted by EmitElemOperands.
JSOp setOp = bce->sc->strict ? JSOP_STRICTSETELEM : JSOP_SETELEM; JSOp setOp = bce->sc->strict ? JSOP_STRICTSETELEM : JSOP_SETELEM;
if (!EmitElemOp(cx, pn, setOp, bce)) if (!EmitElemOp(cx, target, setOp, bce))
return false; return false;
break; break;
} }
case PNK_CALL: case PNK_CALL:
MOZ_ASSERT(pn->pn_xflags & PNX_SETCALL); MOZ_ASSERT(target->pn_xflags & PNX_SETCALL);
if (!EmitTree(cx, bce, pn)) if (!EmitTree(cx, bce, target))
return false; return false;
// Pop the call return value. Below, we pop the RHS too, balancing // Pop the call return value. Below, we pop the RHS too, balancing
@ -3500,6 +3506,33 @@ EmitIteratorNext(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn=nullp
return true; return true;
} }
/**
* EmitDefault will check if the value on top of the stack is "undefined".
* If so, it will replace that value on the stack with the value defined by |defaultExpr|.
*/
static bool
EmitDefault(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *defaultExpr)
{
if (Emit1(cx, bce, JSOP_DUP) < 0) // VALUE VALUE
return false;
if (Emit1(cx, bce, JSOP_UNDEFINED) < 0) // VALUE VALUE UNDEFINED
return false;
if (Emit1(cx, bce, JSOP_STRICTEQ) < 0) // VALUE EQL?
return false;
// Emit source note to enable ion compilation.
if (NewSrcNote(cx, bce, SRC_IF) < 0)
return false;
ptrdiff_t jump = EmitJump(cx, bce, JSOP_IFEQ, 0); // VALUE
if (jump < 0)
return false;
if (Emit1(cx, bce, JSOP_POP) < 0) // .
return false;
if (!EmitTree(cx, bce, defaultExpr)) // DEFAULTVALUE
return false;
SetJumpOffsetAt(bce, jump);
return true;
}
static bool static bool
EmitDestructuringOpsArrayHelper(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pattern, EmitDestructuringOpsArrayHelper(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pattern,
VarEmitOption emitOption) VarEmitOption emitOption)
@ -3526,7 +3559,14 @@ EmitDestructuringOpsArrayHelper(ExclusiveContext *cx, BytecodeEmitter *bce, Pars
* current property name "label" on the left of a colon in the object * current property name "label" on the left of a colon in the object
* initializer. * initializer.
*/ */
if (member->isKind(PNK_SPREAD)) { ParseNode *pndefault = nullptr;
ParseNode *elem = member;
if (elem->isKind(PNK_ASSIGN)) {
pndefault = elem->pn_right;
elem = elem->pn_left;
}
if (elem->isKind(PNK_SPREAD)) {
/* Create a new array with the rest of the iterator */ /* Create a new array with the rest of the iterator */
ptrdiff_t off = EmitN(cx, bce, JSOP_NEWARRAY, 3); // ... OBJ? ITER ARRAY ptrdiff_t off = EmitN(cx, bce, JSOP_NEWARRAY, 3); // ... OBJ? ITER ARRAY
if (off < 0) if (off < 0)
@ -3581,8 +3621,11 @@ EmitDestructuringOpsArrayHelper(ExclusiveContext *cx, BytecodeEmitter *bce, Pars
return false; return false;
} }
if (pndefault && !EmitDefault(cx, bce, pndefault))
return false;
// Destructure into the pattern the element contains. // Destructure into the pattern the element contains.
ParseNode *subpattern = member; ParseNode *subpattern = elem;
if (subpattern->isKind(PNK_ELISION)) { if (subpattern->isKind(PNK_ELISION)) {
// The value destructuring into an elision just gets ignored. // The value destructuring into an elision just gets ignored.
if (Emit1(cx, bce, JSOP_POP) < 0) // ... OBJ? ITER if (Emit1(cx, bce, JSOP_POP) < 0) // ... OBJ? ITER
@ -3684,6 +3727,12 @@ EmitDestructuringOpsObjectHelper(ExclusiveContext *cx, BytecodeEmitter *bce, Par
if (needsGetElem && !EmitElemOpBase(cx, bce, JSOP_GETELEM)) // ... OBJ PROP if (needsGetElem && !EmitElemOpBase(cx, bce, JSOP_GETELEM)) // ... OBJ PROP
return false; return false;
if (subpattern->isKind(PNK_ASSIGN)) {
if (!EmitDefault(cx, bce, subpattern->pn_right))
return false;
subpattern = subpattern->pn_left;
}
// Destructure PROP per this member's subpattern. // Destructure PROP per this member's subpattern.
int32_t depthBefore = bce->stackDepth; int32_t depthBefore = bce->stackDepth;
if (!EmitDestructuringLHS(cx, bce, subpattern, emitOption)) if (!EmitDestructuringLHS(cx, bce, subpattern, emitOption))

Просмотреть файл

@ -3385,6 +3385,8 @@ Parser<FullParseHandler>::checkDestructuringObject(BindData<FullParseHandler> *d
MOZ_ASSERT(member->isKind(PNK_COLON) || member->isKind(PNK_SHORTHAND)); MOZ_ASSERT(member->isKind(PNK_COLON) || member->isKind(PNK_SHORTHAND));
expr = member->pn_right; expr = member->pn_right;
} }
if (expr->isKind(PNK_ASSIGN))
expr = expr->pn_left;
bool ok; bool ok;
if (expr->isKind(PNK_ARRAY) || expr->isKind(PNK_OBJECT)) { if (expr->isKind(PNK_ARRAY) || expr->isKind(PNK_OBJECT)) {
@ -3429,6 +3431,8 @@ Parser<FullParseHandler>::checkDestructuringArray(BindData<FullParseHandler> *da
report(ParseError, false, target, JSMSG_BAD_DESTRUCT_TARGET); report(ParseError, false, target, JSMSG_BAD_DESTRUCT_TARGET);
return false; return false;
} }
} else if (target->isKind(PNK_ASSIGN)) {
target = target->pn_left;
} }
bool ok; bool ok;

Просмотреть файл

@ -143,7 +143,6 @@ void
CheckHashTablesAfterMovingGC(JSRuntime *rt); CheckHashTablesAfterMovingGC(JSRuntime *rt);
#endif #endif
#ifdef JSGC_COMPACTING
struct MovingTracer : JSTracer { struct MovingTracer : JSTracer {
explicit MovingTracer(JSRuntime *rt) : JSTracer(rt, Visit, TraceWeakMapKeysValues) {} explicit MovingTracer(JSRuntime *rt) : JSTracer(rt, Visit, TraceWeakMapKeysValues) {}
@ -152,7 +151,6 @@ struct MovingTracer : JSTracer {
return trc->callback == Visit; return trc->callback == Visit;
} }
}; };
#endif
} /* namespace gc */ } /* namespace gc */
} /* namespace js */ } /* namespace js */

Просмотреть файл

@ -34,11 +34,8 @@ struct FinalizePhase;
class MarkingValidator; class MarkingValidator;
struct AutoPrepareForTracing; struct AutoPrepareForTracing;
class AutoTraceSession; class AutoTraceSession;
#ifdef JSGC_COMPACTING
struct ArenasToUpdate; struct ArenasToUpdate;
struct MovingTracer; struct MovingTracer;
#endif
class ChunkPool class ChunkPool
{ {
@ -297,11 +294,7 @@ class GCRuntime
bool isHeapMajorCollecting() { return heapState == js::MajorCollecting; } bool isHeapMajorCollecting() { return heapState == js::MajorCollecting; }
bool isHeapMinorCollecting() { return heapState == js::MinorCollecting; } bool isHeapMinorCollecting() { return heapState == js::MinorCollecting; }
bool isHeapCollecting() { return isHeapMajorCollecting() || isHeapMinorCollecting(); } bool isHeapCollecting() { return isHeapMajorCollecting() || isHeapMinorCollecting(); }
#ifdef JSGC_COMPACTING
bool isHeapCompacting() { return isHeapMajorCollecting() && state() == COMPACT; } bool isHeapCompacting() { return isHeapMajorCollecting() && state() == COMPACT; }
#else
bool isHeapCompacting() { return false; }
#endif
bool triggerGC(JS::gcreason::Reason reason); bool triggerGC(JS::gcreason::Reason reason);
void maybeAllocTriggerZoneGC(Zone *zone, const AutoLockGC &lock); void maybeAllocTriggerZoneGC(Zone *zone, const AutoLockGC &lock);
@ -437,11 +430,9 @@ class GCRuntime
void disableGenerationalGC(); void disableGenerationalGC();
void enableGenerationalGC(); void enableGenerationalGC();
#ifdef JSGC_COMPACTING
void disableCompactingGC(); void disableCompactingGC();
void enableCompactingGC(); void enableCompactingGC();
bool isCompactingGCEnabled(); bool isCompactingGCEnabled();
#endif
void setGrayRootsTracer(JSTraceDataOp traceOp, void *data); void setGrayRootsTracer(JSTraceDataOp traceOp, void *data);
bool addBlackRootsTracer(JSTraceDataOp traceOp, void *data); bool addBlackRootsTracer(JSTraceDataOp traceOp, void *data);
@ -604,19 +595,17 @@ class GCRuntime
void assertBackgroundSweepingFinished(); void assertBackgroundSweepingFinished();
bool shouldCompact(); bool shouldCompact();
bool compactPhase(bool lastGC); bool compactPhase(bool lastGC);
#ifdef JSGC_COMPACTING
void sweepTypesAfterCompacting(Zone *zone); void sweepTypesAfterCompacting(Zone *zone);
void sweepZoneAfterCompacting(Zone *zone); void sweepZoneAfterCompacting(Zone *zone);
ArenaHeader *relocateArenas(); ArenaHeader *relocateArenas();
void updateAllCellPointersParallel(ArenasToUpdate &source); void updateAllCellPointersParallel(MovingTracer *trc);
void updateAllCellPointersSerial(MovingTracer *trc, ArenasToUpdate &source); void updateAllCellPointersSerial(MovingTracer *trc);
void updatePointersToRelocatedCells(); void updatePointersToRelocatedCells();
void releaseRelocatedArenas(ArenaHeader *relocatedList); void releaseRelocatedArenas(ArenaHeader *relocatedList);
void releaseRelocatedArenasWithoutUnlocking(ArenaHeader *relocatedList, const AutoLockGC& lock); void releaseRelocatedArenasWithoutUnlocking(ArenaHeader *relocatedList, const AutoLockGC& lock);
#ifdef DEBUG #ifdef DEBUG
void protectRelocatedArenas(ArenaHeader *relocatedList); void protectRelocatedArenas(ArenaHeader *relocatedList);
void unprotectRelocatedArenas(ArenaHeader *relocatedList); void unprotectRelocatedArenas(ArenaHeader *relocatedList);
#endif
#endif #endif
void finishCollection(); void finishCollection();
@ -811,13 +800,11 @@ class GCRuntime
*/ */
unsigned generationalDisabled; unsigned generationalDisabled;
#ifdef JSGC_COMPACTING
/* /*
* Some code cannot tolerate compacting GC so it can be disabled with this * Some code cannot tolerate compacting GC so it can be disabled with this
* counter. * counter.
*/ */
unsigned compactingDisabled; unsigned compactingDisabled;
#endif
/* /*
* This is true if we are in the middle of a brain transplant (e.g., * This is true if we are in the middle of a brain transplant (e.g.,
@ -918,9 +905,7 @@ class GCRuntime
size_t noGCOrAllocationCheck; size_t noGCOrAllocationCheck;
#ifdef JSGC_COMPACTING
ArenaHeader* relocatedArenasToRelease; ArenaHeader* relocatedArenasToRelease;
#endif
#endif #endif

Просмотреть файл

@ -642,10 +642,8 @@ struct ArenaHeader
void unmarkAll(); void unmarkAll();
#ifdef JSGC_COMPACTING
size_t countUsedCells(); size_t countUsedCells();
size_t countFreeCells(); size_t countFreeCells();
#endif
}; };
static_assert(ArenaZoneOffset == offsetof(ArenaHeader, zone), static_assert(ArenaZoneOffset == offsetof(ArenaHeader, zone),
"The hardcoded API zone offset must match the actual offset."); "The hardcoded API zone offset must match the actual offset.");

Просмотреть файл

@ -161,18 +161,14 @@ CheckMarkedThing(JSTracer *trc, T **thingp)
T *thing = *thingp; T *thing = *thingp;
MOZ_ASSERT(*thingp); MOZ_ASSERT(*thingp);
#ifdef JSGC_COMPACTING
thing = MaybeForwarded(thing); thing = MaybeForwarded(thing);
#endif
/* This function uses data that's not available in the nursery. */ /* This function uses data that's not available in the nursery. */
if (IsInsideNursery(thing)) if (IsInsideNursery(thing))
return; return;
#ifdef JSGC_COMPACTING
MOZ_ASSERT_IF(!MovingTracer::IsMovingTracer(trc) && !Nursery::IsMinorCollectionTracer(trc), MOZ_ASSERT_IF(!MovingTracer::IsMovingTracer(trc) && !Nursery::IsMinorCollectionTracer(trc),
!IsForwarded(*thingp)); !IsForwarded(*thingp));
#endif
/* /*
* Permanent atoms are not associated with this runtime, but will be ignored * Permanent atoms are not associated with this runtime, but will be ignored
@ -184,13 +180,8 @@ CheckMarkedThing(JSTracer *trc, T **thingp)
Zone *zone = thing->zoneFromAnyThread(); Zone *zone = thing->zoneFromAnyThread();
JSRuntime *rt = trc->runtime(); JSRuntime *rt = trc->runtime();
#ifdef JSGC_COMPACTING
MOZ_ASSERT_IF(!MovingTracer::IsMovingTracer(trc), CurrentThreadCanAccessZone(zone)); MOZ_ASSERT_IF(!MovingTracer::IsMovingTracer(trc), CurrentThreadCanAccessZone(zone));
MOZ_ASSERT_IF(!MovingTracer::IsMovingTracer(trc), CurrentThreadCanAccessRuntime(rt)); MOZ_ASSERT_IF(!MovingTracer::IsMovingTracer(trc), CurrentThreadCanAccessRuntime(rt));
#else
MOZ_ASSERT(CurrentThreadCanAccessZone(zone));
MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt));
#endif
MOZ_ASSERT(zone->runtimeFromAnyThread() == trc->runtime()); MOZ_ASSERT(zone->runtimeFromAnyThread() == trc->runtime());
MOZ_ASSERT(trc->hasTracingDetails()); MOZ_ASSERT(trc->hasTracingDetails());
@ -437,10 +428,8 @@ IsMarkedFromAnyThread(T **thingp)
Zone *zone = (*thingp)->asTenured().zoneFromAnyThread(); Zone *zone = (*thingp)->asTenured().zoneFromAnyThread();
if (!zone->isCollectingFromAnyThread() || zone->isGCFinished()) if (!zone->isCollectingFromAnyThread() || zone->isGCFinished())
return true; return true;
#ifdef JSGC_COMPACTING
if (zone->isGCCompacting() && IsForwarded(*thingp)) if (zone->isGCCompacting() && IsForwarded(*thingp))
*thingp = Forwarded(*thingp); *thingp = Forwarded(*thingp);
#endif
return (*thingp)->asTenured().isMarked(); return (*thingp)->asTenured().isMarked();
} }
@ -481,12 +470,10 @@ IsAboutToBeFinalizedFromAnyThread(T **thingp)
return false; return false;
return !thing->asTenured().isMarked(); return !thing->asTenured().isMarked();
} }
#ifdef JSGC_COMPACTING
else if (zone->isGCCompacting() && IsForwarded(thing)) { else if (zone->isGCCompacting() && IsForwarded(thing)) {
*thingp = Forwarded(thing); *thingp = Forwarded(thing);
return false; return false;
} }
#endif
return false; return false;
} }
@ -504,11 +491,10 @@ UpdateIfRelocated(JSRuntime *rt, T **thingp)
return *thingp; return *thingp;
} }
#ifdef JSGC_COMPACTING
Zone *zone = (*thingp)->zone(); Zone *zone = (*thingp)->zone();
if (zone->isGCCompacting() && IsForwarded(*thingp)) if (zone->isGCCompacting() && IsForwarded(*thingp))
*thingp = Forwarded(*thingp); *thingp = Forwarded(*thingp);
#endif
return *thingp; return *thingp;
} }
@ -1815,10 +1801,8 @@ GCMarker::processMarkStackTop(SliceBudget &budget)
// Global objects all have the same trace hook. That hook is safe without barriers // Global objects all have the same trace hook. That hook is safe without barriers
// if the global has no custom trace hook of its own, or has been moved to a different // if the global has no custom trace hook of its own, or has been moved to a different
// compartment, and so can't have one. // compartment, and so can't have one.
MOZ_ASSERT_IF(runtime()->gc.isIncrementalGCEnabled() && MOZ_ASSERT_IF(!(clasp->trace == JS_GlobalObjectTraceHook &&
!(clasp->trace == JS_GlobalObjectTraceHook && (!obj->compartment()->options().getTrace() || !obj->isOwnGlobal())),
(!obj->compartment()->options().getTrace() ||
!obj->isOwnGlobal())),
clasp->flags & JSCLASS_IMPLEMENTS_BARRIERS); clasp->flags & JSCLASS_IMPLEMENTS_BARRIERS);
if (clasp->trace == InlineTypedObject::obj_trace) if (clasp->trace == InlineTypedObject::obj_trace)
goto scan_typed_obj; goto scan_typed_obj;

Просмотреть файл

@ -0,0 +1,166 @@
load(libdir + 'asserts.js');
load(libdir + 'eqArrayHelper.js');
var arrayPattern = '[a = 1, b = 2, c = 3, d = 4, e = 5, f = 6]';
var objectPattern = '{0: a = 1, 1: b = 2, 2: c = 3, 3: d = 4, 4: e = 5, 5: f = 6}';
var nestedPattern = '{a: a = 1, b: [b = 2] = [], c: {c: [c]} = {c: [3]}, d: {d, e} = {d: 4, e: 5}, f: f = 6}';
function testAll(fn) {
assertEqArray(fn(arrayPattern, []), [1, 2, 3, 4, 5, 6]);
assertEqArray(fn(arrayPattern, [2, 3, 4, 5, 6, 7, 8, 9]), [2, 3, 4, 5, 6, 7]);
assertEqArray(fn(arrayPattern, [undefined, 0, false, null, "", undefined]), [1, 0, false, null, "", 6]);
assertEqArray(fn(arrayPattern, [0, false]), [0, false, 3, 4, 5, 6]);
assertEqArray(fn(objectPattern, []), [1, 2, 3, 4, 5, 6]);
assertEqArray(fn(objectPattern, [2, 3, 4, 5, 6, 7, 8, 9]), [2, 3, 4, 5, 6, 7]);
assertEqArray(fn(objectPattern, [undefined, 0, false, null, "", undefined]), [1, 0, false, null, "", 6]);
assertEqArray(fn(objectPattern, [0, false]), [0, false, 3, 4, 5, 6]);
assertEqArray(fn(nestedPattern, {}), [1, 2, 3, 4, 5, 6]);
assertEqArray(fn(nestedPattern, {a: 2, b: [], c: undefined}), [2, 2, 3, 4, 5, 6]);
assertEqArray(fn(nestedPattern, {a: undefined, b: [3], c: {c: [4]}}), [1, 3, 4, 4, 5, 6]);
assertEqArray(fn(nestedPattern, {a: undefined, b: [3], c: {c: [4]}, d: {d: 5, e: 6}}), [1, 3, 4, 5, 6, 6]);
}
function testVar(pattern, input) {
return new Function('input',
'var ' + pattern + ' = input;' +
'return [a, b, c, d, e, f];'
)(input);
}
testAll(testVar);
function testLet(pattern, input) {
return new Function('input',
'let ' + pattern + ' = input;' +
'return [a, b, c, d, e, f];'
)(input);
}
testAll(testLet);
function testConst(pattern, input) {
return new Function('input',
'const ' + pattern + ' = input;' +
'return [a, b, c, d, e, f];'
)(input);
}
testAll(testConst);
function testGlobal(pattern, input) {
return new Function('input',
'(' + pattern + ') = input;' +
'return [a, b, c, d, e, f];'
)(input);
}
testAll(testGlobal);
function testClosure(pattern, input) {
return new Function('input',
'var rest; (function () {' +
'(' + pattern + ') = input;' +
'})();' +
'return [a, b, c, d, e, f];'
)(input);
}
testAll(testClosure);
function testArgument(pattern, input) {
return new Function('input',
'return (function (' + pattern + ') {' +
'return [a, b, c, d, e, f]; })(input);'
)(input);
}
testAll(testArgument);
function testArgumentFunction(pattern, input) {
return new Function(pattern,
'return [a, b, c, d, e, f];'
)(input);
}
// XXX: ES6 requires the `Function` constructor to accept arbitrary
// `BindingElement`s as formal parameters. See Bug 1037939.
// Once fixed, please update the assertions below.
assertThrowsInstanceOf(() => testAll(testArgumentFunction), SyntaxError);
function testThrow(pattern, input) {
return new Function('input',
'try { throw input }' +
'catch(' + pattern + ') {' +
'return [a, b, c, d, e, f]; }'
)(input);
}
testAll(testThrow);
// XXX: Support for let blocks and expressions will be removed in bug 1023609.
// However, they test a special code path in destructuring assignment so having
// these tests here for now seems like a good idea.
function testLetBlock(pattern, input) {
return new Function('input',
'let (' + pattern + ' = input)' +
'{ return [a, b, c, d, e, f]; }'
)(input);
}
testAll(testLetBlock);
function testLetExpression(pattern, input) {
return new Function('input',
'return (let (' + pattern + ' = input) [a, b, c, d, e, f]);'
)(input);
}
testAll(testLetExpression);
// test global const
const [ca = 1, cb = 2] = [];
assertEq(ca, 1);
assertEq(cb, 2);
const {a: {a: cc = 3} = {a: undefined}} = {};
assertEq(cc, 3);
// test that the assignment happens in source order
var a = undefined, b = undefined, c = undefined;
({a: a = 1, c: c = 2, b: b = 3}) = {
get a() {
assertEq(a, undefined);
assertEq(c, undefined);
assertEq(b, undefined);
return undefined;
},
get b() {
assertEq(a, 1);
assertEq(c, 2);
assertEq(b, undefined);
return 4;
},
get c() {
assertEq(a, 1);
assertEq(c, undefined);
assertEq(b, undefined);
return undefined;
}
};
assertEq(b, 4);
assertThrowsInstanceOf(() => { var {a: {a} = null} = {}; }, TypeError);
assertThrowsInstanceOf(() => { var [[a] = 2] = []; }, TypeError);
// destructuring assignment might have duplicate variable names.
var [a = 1, a = 2] = [3];
assertEq(a, 2);
// assignment to properties of default params
[a = {y: 2}, a.x = 1] = [];
assertEq(typeof a, 'object');
assertEq(a.x, 1);
assertEq(a.y, 2);
// defaults are evaluated even if there is no binding
var evaled = false;
({a: {} = (evaled = true, null)}) = {};
assertEq(evaled, true);
evaled = false;
assertThrowsInstanceOf(() => { [[] = (evaled = true, 2)] = [] }, TypeError);
assertEq(evaled, true);
assertThrowsInstanceOf(() => new Function('var [...rest = defaults] = [];'), SyntaxError);

Просмотреть файл

@ -0,0 +1,9 @@
if (!this.hasOwnProperty("SIMD"))
quit();
var float64x2 = SIMD.float64x2;
function test() {
var a = float64x2(1, 2);
}
test();
test();

Просмотреть файл

@ -2530,9 +2530,8 @@ IonBuilder::inlineConstructSimdObject(CallInfo &callInfo, SimdTypeDescr *descr)
case SimdTypeDescr::TYPE_FLOAT32: case SimdTypeDescr::TYPE_FLOAT32:
simdType = MIRType_Float32x4; simdType = MIRType_Float32x4;
break; break;
default: case SimdTypeDescr::TYPE_FLOAT64:
MOZ_CRASH("Unknown SIMD kind when generating MSimdBox instruction."); return InliningStatus_NotInlined; // :TODO: NYI (Bug 1124205)
return InliningStatus_NotInlined;
} }
// We do not inline SIMD constructors if the number of arguments does not // We do not inline SIMD constructors if the number of arguments does not

Просмотреть файл

@ -31,9 +31,6 @@
/* Define to 1 if SpiderMonkey should use small chunks. */ /* Define to 1 if SpiderMonkey should use small chunks. */
#undef JS_GC_SMALL_CHUNK_SIZE #undef JS_GC_SMALL_CHUNK_SIZE
/* Define to 1 if SpiderMonkey should use Compacting GC. */
#undef JSGC_COMPACTING
/* Define to 1 if the <endian.h> header is present and /* Define to 1 if the <endian.h> header is present and
useable. See jscpucfg.h. */ useable. See jscpucfg.h. */
#undef JS_HAVE_ENDIAN_H #undef JS_HAVE_ENDIAN_H

Просмотреть файл

@ -21,7 +21,7 @@ int BarkWhenTracedClass::finalizeCount;
int BarkWhenTracedClass::traceCount; int BarkWhenTracedClass::traceCount;
const JSClass BarkWhenTracedClass::class_ = { const JSClass BarkWhenTracedClass::class_ = {
"BarkWhenTracedClass", 0, "BarkWhenTracedClass", JSCLASS_IMPLEMENTS_BARRIERS,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,

Просмотреть файл

@ -66,10 +66,6 @@ checkSize(JS::HandleObject map, uint32_t expected)
} }
END_TEST(testWeakMap_basicOperations) END_TEST(testWeakMap_basicOperations)
// TODO: this test stores object pointers in a private slot which is not marked
// and so doesn't work with compacting GC.
#ifndef JSGC_COMPACTING
BEGIN_TEST(testWeakMap_keyDelegates) BEGIN_TEST(testWeakMap_keyDelegates)
{ {
JS_SetGCParameter(rt, JSGC_MODE, JSGC_MODE_INCREMENTAL); JS_SetGCParameter(rt, JSGC_MODE, JSGC_MODE_INCREMENTAL);
@ -253,5 +249,3 @@ checkSize(JS::HandleObject map, uint32_t expected)
return true; return true;
} }
END_TEST(testWeakMap_keyDelegates) END_TEST(testWeakMap_keyDelegates)
#endif

Просмотреть файл

@ -649,8 +649,6 @@ JSCompartment::sweepCrossCompartmentWrappers()
} }
} }
#ifdef JSGC_COMPACTING
void JSCompartment::fixupAfterMovingGC() void JSCompartment::fixupAfterMovingGC()
{ {
fixupGlobal(); fixupGlobal();
@ -667,8 +665,6 @@ JSCompartment::fixupGlobal()
global_.set(MaybeForwarded(global)); global_.set(MaybeForwarded(global));
} }
#endif // JSGC_COMPACTING
void void
JSCompartment::purge() JSCompartment::purge()
{ {

Просмотреть файл

@ -398,12 +398,10 @@ struct JSCompartment
void purge(); void purge();
void clearTables(); void clearTables();
#ifdef JSGC_COMPACTING
void fixupInitialShapeTable(); void fixupInitialShapeTable();
void fixupNewTypeObjectTable(js::types::NewTypeObjectTable &table); void fixupNewTypeObjectTable(js::types::NewTypeObjectTable &table);
void fixupAfterMovingGC(); void fixupAfterMovingGC();
void fixupGlobal(); void fixupGlobal();
#endif
bool hasObjectMetadataCallback() const { return objectMetadataCallback; } bool hasObjectMetadataCallback() const { return objectMetadataCallback; }
void setObjectMetadataCallback(js::ObjectMetadataCallback callback); void setObjectMetadataCallback(js::ObjectMetadataCallback callback);

Просмотреть файл

@ -1112,9 +1112,7 @@ GCRuntime::GCRuntime(JSRuntime *rt) :
sliceBudget(SliceBudget::Unlimited), sliceBudget(SliceBudget::Unlimited),
incrementalAllowed(true), incrementalAllowed(true),
generationalDisabled(0), generationalDisabled(0),
#ifdef JSGC_COMPACTING
compactingDisabled(0), compactingDisabled(0),
#endif
manipulatingDeadZones(false), manipulatingDeadZones(false),
objectsMarkedInDeadZones(0), objectsMarkedInDeadZones(0),
poked(false), poked(false),
@ -1134,9 +1132,7 @@ GCRuntime::GCRuntime(JSRuntime *rt) :
#ifdef DEBUG #ifdef DEBUG
inUnsafeRegion(0), inUnsafeRegion(0),
noGCOrAllocationCheck(0), noGCOrAllocationCheck(0),
#ifdef JSGC_COMPACTING
relocatedArenasToRelease(nullptr), relocatedArenasToRelease(nullptr),
#endif
#endif #endif
lock(nullptr), lock(nullptr),
lockOwner(nullptr), lockOwner(nullptr),
@ -1930,15 +1926,9 @@ ArenaLists::allocateFromArenaInner(JS::Zone *zone, ArenaHeader *aheader, AllocKi
bool bool
GCRuntime::shouldCompact() GCRuntime::shouldCompact()
{ {
#ifdef JSGC_COMPACTING
return invocationKind == GC_SHRINK && isCompactingGCEnabled(); return invocationKind == GC_SHRINK && isCompactingGCEnabled();
#else
return false;
#endif
} }
#ifdef JSGC_COMPACTING
void void
GCRuntime::disableCompactingGC() GCRuntime::disableCompactingGC()
{ {
@ -2373,13 +2363,19 @@ namespace gc {
struct ArenasToUpdate struct ArenasToUpdate
{ {
explicit ArenasToUpdate(JSRuntime *rt); enum KindsToUpdate {
FOREGROUND = 1,
BACKGROUND = 2,
ALL = FOREGROUND | BACKGROUND
};
ArenasToUpdate(JSRuntime *rt, KindsToUpdate kinds);
bool done() { return initialized && arena == nullptr; } bool done() { return initialized && arena == nullptr; }
ArenaHeader* next(); ArenaHeader* next();
ArenaHeader *getArenasToUpdate(AutoLockHelperThreadState& lock, unsigned max); ArenaHeader *getArenasToUpdate(AutoLockHelperThreadState& lock, unsigned max);
private: private:
bool initialized; bool initialized;
KindsToUpdate kinds;
GCZonesIter zone; // Current zone to process, unless zone.done() GCZonesIter zone; // Current zone to process, unless zone.done()
unsigned kind; // Current alloc kind to process unsigned kind; // Current alloc kind to process
ArenaHeader *arena; // Next arena to process ArenaHeader *arena; // Next arena to process
@ -2390,16 +2386,25 @@ struct ArenasToUpdate
bool ArenasToUpdate::shouldProcessKind(unsigned kind) bool ArenasToUpdate::shouldProcessKind(unsigned kind)
{ {
MOZ_ASSERT(kind < FINALIZE_LIMIT); MOZ_ASSERT(kind < FINALIZE_LIMIT);
return if (kind == FINALIZE_FAT_INLINE_STRING ||
kind != FINALIZE_FAT_INLINE_STRING && kind == FINALIZE_STRING ||
kind != FINALIZE_STRING && kind == FINALIZE_EXTERNAL_STRING ||
kind != FINALIZE_EXTERNAL_STRING && kind == FINALIZE_SYMBOL)
kind != FINALIZE_SYMBOL; {
return false;
}
if (kind > FINALIZE_OBJECT_LAST || js::gc::IsBackgroundFinalized(AllocKind(kind)))
return (kinds & BACKGROUND) != 0;
else
return (kinds & FOREGROUND) != 0;
} }
ArenasToUpdate::ArenasToUpdate(JSRuntime *rt) ArenasToUpdate::ArenasToUpdate(JSRuntime *rt, KindsToUpdate kinds)
: initialized(false), zone(rt, SkipAtoms) : initialized(false), kinds(kinds), zone(rt, SkipAtoms)
{} {
MOZ_ASSERT(kinds && !(kinds & ~ALL));
}
ArenaHeader * ArenaHeader *
ArenasToUpdate::next() ArenasToUpdate::next()
@ -2526,20 +2531,23 @@ UpdateCellPointersTask::run()
} // namespace js } // namespace js
void void
GCRuntime::updateAllCellPointersParallel(ArenasToUpdate &source) GCRuntime::updateAllCellPointersParallel(MovingTracer *trc)
{ {
AutoDisableProxyCheck noProxyCheck(rt); // These checks assert when run in parallel. AutoDisableProxyCheck noProxyCheck(rt); // These checks assert when run in parallel.
const size_t minTasks = 2; const size_t minTasks = 2;
const size_t maxTasks = 8; const size_t maxTasks = 8;
unsigned taskCount = Min(Max(HelperThreadState().cpuCount / 2, minTasks), unsigned taskCount = Min(Max(HelperThreadState().cpuCount / 2, minTasks),
maxTasks); maxTasks) + 1;
UpdateCellPointersTask updateTasks[maxTasks]; UpdateCellPointersTask updateTasks[maxTasks];
ArenasToUpdate fgArenas(rt, ArenasToUpdate::FOREGROUND);
ArenasToUpdate bgArenas(rt, ArenasToUpdate::BACKGROUND);
AutoLockHelperThreadState lock; AutoLockHelperThreadState lock;
unsigned i; unsigned i;
for (i = 0; i < taskCount && !source.done(); ++i) { for (i = 0; i < taskCount && !bgArenas.done(); ++i) {
updateTasks[i].init(rt, &source, lock); ArenasToUpdate *source = i == 0 ? &fgArenas : &bgArenas;
updateTasks[i].init(rt, source, lock);
startTask(updateTasks[i], gcstats::PHASE_COMPACT_UPDATE_CELLS); startTask(updateTasks[i], gcstats::PHASE_COMPACT_UPDATE_CELLS);
} }
unsigned tasksStarted = i; unsigned tasksStarted = i;
@ -2549,9 +2557,10 @@ GCRuntime::updateAllCellPointersParallel(ArenasToUpdate &source)
} }
void void
GCRuntime::updateAllCellPointersSerial(MovingTracer *trc, ArenasToUpdate &source) GCRuntime::updateAllCellPointersSerial(MovingTracer *trc)
{ {
while (ArenaHeader *arena = source.next()) ArenasToUpdate allArenas(rt, ArenasToUpdate::ALL);
while (ArenaHeader *arena = allArenas.next())
UpdateCellPointers(trc, arena); UpdateCellPointers(trc, arena);
} }
@ -2580,11 +2589,10 @@ GCRuntime::updatePointersToRelocatedCells()
// Iterate through all cells that can contain JSObject pointers to update // Iterate through all cells that can contain JSObject pointers to update
// them. Since updating each cell is independent we try to parallelize this // them. Since updating each cell is independent we try to parallelize this
// as much as possible. // as much as possible.
ArenasToUpdate source(rt);
if (CanUseExtraThreads()) if (CanUseExtraThreads())
updateAllCellPointersParallel(source); updateAllCellPointersParallel(&trc);
else else
updateAllCellPointersSerial(&trc, source); updateAllCellPointersSerial(&trc);
// Mark roots to update them. // Mark roots to update them.
{ {
@ -2697,12 +2705,10 @@ GCRuntime::releaseRelocatedArenasWithoutUnlocking(ArenaHeader *relocatedList, co
} }
} }
#endif // JSGC_COMPACTING
void void
GCRuntime::releaseHeldRelocatedArenas() GCRuntime::releaseHeldRelocatedArenas()
{ {
#if defined(JSGC_COMPACTING) && defined(DEBUG) #ifdef DEBUG
// In debug mode we don't release relocated arenas straight away. Instead // In debug mode we don't release relocated arenas straight away. Instead
// we protect them and hold onto them until the next GC sweep phase to catch // we protect them and hold onto them until the next GC sweep phase to catch
// any pointers to them that didn't get forwarded. // any pointers to them that didn't get forwarded.
@ -5462,9 +5468,6 @@ GCRuntime::endSweepPhase(bool lastGC)
bool bool
GCRuntime::compactPhase(bool lastGC) GCRuntime::compactPhase(bool lastGC)
{ {
#ifndef JSGC_COMPACTING
MOZ_CRASH();
#else
gcstats::AutoPhase ap(stats, gcstats::PHASE_COMPACT); gcstats::AutoPhase ap(stats, gcstats::PHASE_COMPACT);
if (isIncremental) { if (isIncremental) {
@ -5529,8 +5532,6 @@ GCRuntime::compactPhase(bool lastGC)
} }
} }
#endif #endif
#endif // JSGC_COMPACTING
return true; return true;
} }
@ -5690,7 +5691,6 @@ GCRuntime::resetIncrementalGC(const char *reason)
break; break;
} }
#ifdef JSGC_COMPACTING
case COMPACT: { case COMPACT: {
{ {
gcstats::AutoPhase ap(stats, gcstats::PHASE_WAIT_BACKGROUND_THREAD); gcstats::AutoPhase ap(stats, gcstats::PHASE_WAIT_BACKGROUND_THREAD);
@ -5706,7 +5706,6 @@ GCRuntime::resetIncrementalGC(const char *reason)
invocationKind = oldInvocationKind; invocationKind = oldInvocationKind;
break; break;
} }
#endif
default: default:
MOZ_CRASH("Invalid incremental GC state"); MOZ_CRASH("Invalid incremental GC state");
@ -6394,7 +6393,7 @@ GCRuntime::onOutOfMallocMemory(const AutoLockGC &lock)
{ {
// Release any relocated arenas we may be holding on to, without releasing // Release any relocated arenas we may be holding on to, without releasing
// the GC lock. // the GC lock.
#if defined(JSGC_COMPACTING) && defined(DEBUG) #ifdef DEBUG
unprotectRelocatedArenas(relocatedArenasToRelease); unprotectRelocatedArenas(relocatedArenasToRelease);
releaseRelocatedArenasWithoutUnlocking(relocatedArenasToRelease, lock); releaseRelocatedArenasWithoutUnlocking(relocatedArenasToRelease, lock);
relocatedArenasToRelease = nullptr; relocatedArenasToRelease = nullptr;
@ -7115,19 +7114,13 @@ JS::IsIncrementalGCEnabled(JSRuntime *rt)
JS_PUBLIC_API(void) JS_PUBLIC_API(void)
JS::DisableCompactingGC(JSRuntime *rt) JS::DisableCompactingGC(JSRuntime *rt)
{ {
#ifdef JSGC_COMPACTING
rt->gc.disableCompactingGC(); rt->gc.disableCompactingGC();
#endif
} }
JS_PUBLIC_API(bool) JS_PUBLIC_API(bool)
JS::IsCompactingGCEnabled(JSRuntime *rt) JS::IsCompactingGCEnabled(JSRuntime *rt)
{ {
#ifdef JSGC_COMPACTING
return rt->gc.isCompactingGCEnabled(); return rt->gc.isCompactingGCEnabled();
#else
return false;
#endif
} }
JS_PUBLIC_API(bool) JS_PUBLIC_API(bool)

Просмотреть файл

@ -454,11 +454,9 @@ class ArenaList {
return *this; return *this;
} }
#ifdef JSGC_COMPACTING
ArenaHeader *removeRemainingArenas(ArenaHeader **arenap, const AutoLockGC &lock); ArenaHeader *removeRemainingArenas(ArenaHeader **arenap, const AutoLockGC &lock);
ArenaHeader *pickArenasToRelocate(JSRuntime *runtime); ArenaHeader *pickArenasToRelocate(JSRuntime *runtime);
ArenaHeader *relocateArenas(ArenaHeader *toRelocate, ArenaHeader *relocated); ArenaHeader *relocateArenas(ArenaHeader *toRelocate, ArenaHeader *relocated);
#endif
}; };
/* /*
@ -785,9 +783,7 @@ class ArenaLists
MOZ_ASSERT(freeLists[kind].isEmpty()); MOZ_ASSERT(freeLists[kind].isEmpty());
} }
#ifdef JSGC_COMPACTING
ArenaHeader *relocateArenas(ArenaHeader *relocatedList); ArenaHeader *relocateArenas(ArenaHeader *relocatedList);
#endif
void queueForegroundObjectsForSweep(FreeOp *fop); void queueForegroundObjectsForSweep(FreeOp *fop);
void queueForegroundThingsForSweep(FreeOp *fop); void queueForegroundThingsForSweep(FreeOp *fop);
@ -1270,9 +1266,7 @@ inline void
CheckGCThingAfterMovingGC(T *t) CheckGCThingAfterMovingGC(T *t)
{ {
MOZ_ASSERT_IF(t, !IsInsideNursery(t)); MOZ_ASSERT_IF(t, !IsInsideNursery(t));
#ifdef JSGC_COMPACTING
MOZ_ASSERT_IF(t, !IsForwarded(t)); MOZ_ASSERT_IF(t, !IsForwarded(t));
#endif
} }
inline void inline void
@ -1429,16 +1423,11 @@ struct AutoDisableProxyCheck
struct AutoDisableCompactingGC struct AutoDisableCompactingGC
{ {
#ifdef JSGC_COMPACTING
explicit AutoDisableCompactingGC(JSRuntime *rt); explicit AutoDisableCompactingGC(JSRuntime *rt);
~AutoDisableCompactingGC(); ~AutoDisableCompactingGC();
private: private:
gc::GCRuntime &gc; gc::GCRuntime &gc;
#else
explicit AutoDisableCompactingGC(JSRuntime *rt) {}
~AutoDisableCompactingGC() {}
#endif
}; };
void void

Просмотреть файл

@ -4891,8 +4891,6 @@ JSCompartment::sweepNewTypeObjectTable(NewTypeObjectTable &table)
} }
} }
#ifdef JSGC_COMPACTING
void void
JSCompartment::fixupNewTypeObjectTable(NewTypeObjectTable &table) JSCompartment::fixupNewTypeObjectTable(NewTypeObjectTable &table)
{ {
@ -4966,8 +4964,6 @@ TypeObject::fixupAfterMovingGC()
} }
} }
#endif // JSGC_COMPACTING
#ifdef JSGC_HASH_TABLE_CHECKS #ifdef JSGC_HASH_TABLE_CHECKS
void void

Просмотреть файл

@ -293,7 +293,7 @@ public:
}; };
/* Flags and other state stored in TypeSet::flags */ /* Flags and other state stored in TypeSet::flags */
enum MOZ_ENUM_TYPE(uint32_t) { enum : uint32_t {
TYPE_FLAG_UNDEFINED = 0x1, TYPE_FLAG_UNDEFINED = 0x1,
TYPE_FLAG_NULL = 0x2, TYPE_FLAG_NULL = 0x2,
TYPE_FLAG_BOOLEAN = 0x4, TYPE_FLAG_BOOLEAN = 0x4,
@ -352,7 +352,7 @@ enum MOZ_ENUM_TYPE(uint32_t) {
typedef uint32_t TypeFlags; typedef uint32_t TypeFlags;
/* Flags and other state stored in TypeObject::flags */ /* Flags and other state stored in TypeObject::flags */
enum MOZ_ENUM_TYPE(uint32_t) { enum : uint32_t {
/* Whether this type object is associated with some allocation site. */ /* Whether this type object is associated with some allocation site. */
OBJECT_FLAG_FROM_ALLOCATION_SITE = 0x1, OBJECT_FLAG_FROM_ALLOCATION_SITE = 0x1,
@ -925,10 +925,7 @@ class TypeNewScript
void trace(JSTracer *trc); void trace(JSTracer *trc);
void sweep(); void sweep();
#ifdef JSGC_COMPACTING
void fixupAfterMovingGC(); void fixupAfterMovingGC();
#endif
void registerNewObject(PlainObject *res); void registerNewObject(PlainObject *res);
void unregisterNewObject(PlainObject *res); void unregisterNewObject(PlainObject *res);
@ -1241,9 +1238,7 @@ struct TypeObject : public gc::TenuredCell
flags_ |= generation << OBJECT_FLAG_GENERATION_SHIFT; flags_ |= generation << OBJECT_FLAG_GENERATION_SHIFT;
} }
#ifdef JSGC_COMPACTING
void fixupAfterMovingGC(); void fixupAfterMovingGC();
#endif
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const; size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;

Просмотреть файл

@ -1232,32 +1232,10 @@ NewObject(ExclusiveContext *cx, types::TypeObject *type_, JSObject *parent, gc::
obj = nobj; obj = nobj;
} }
/*
* This will cancel an already-running incremental GC from doing any more
* slices, and it will prevent any future incremental GCs.
*/
bool globalWithoutCustomTrace = clasp->trace == JS_GlobalObjectTraceHook && bool globalWithoutCustomTrace = clasp->trace == JS_GlobalObjectTraceHook &&
!cx->compartment()->options().getTrace(); !cx->compartment()->options().getTrace();
if (clasp->trace && if (clasp->trace && !globalWithoutCustomTrace)
!globalWithoutCustomTrace && MOZ_RELEASE_ASSERT(clasp->flags & JSCLASS_IMPLEMENTS_BARRIERS);
!(clasp->flags & JSCLASS_IMPLEMENTS_BARRIERS))
{
if (!cx->shouldBeJSContext())
return nullptr;
JSRuntime *rt = cx->asJSContext()->runtime();
rt->gc.disallowIncrementalGC();
#ifdef DEBUG
if (rt->gc.gcMode() == JSGC_MODE_INCREMENTAL) {
fprintf(stderr,
"The class %s has a trace hook but does not declare the\n"
"JSCLASS_IMPLEMENTS_BARRIERS flag. Please ensure that it correctly\n"
"implements write barriers and then set the flag.\n",
clasp->name);
MOZ_CRASH();
}
#endif
}
probes::CreateObject(cx, obj); probes::CreateObject(cx, obj);
return obj; return obj;
@ -2928,13 +2906,18 @@ js::NonProxyLookupOwnProperty(JSContext *cx, LookupGenericOp lookup,
MaybeRooted<JSObject*, allowGC>::template downcastHandle<NativeObject>(obj); MaybeRooted<JSObject*, allowGC>::template downcastHandle<NativeObject>(obj);
bool done; bool done;
if (!LookupOwnPropertyInline<allowGC>(cx, nobj, id, objp, propp, &done)) if (!LookupOwnPropertyInline<allowGC>(cx, nobj, id, propp, &done))
return false; return false;
if (!done) { if (!done) {
objp.set(nullptr); objp.set(nullptr);
propp.set(nullptr); propp.set(nullptr);
return true; return true;
} }
if (propp)
objp.set(obj);
else
objp.set(nullptr);
} }
if (!propp) if (!propp)

Просмотреть файл

@ -235,8 +235,6 @@ Shape::finalize(FreeOp *fop)
fop->delete_(kids.toHash()); fop->delete_(kids.toHash());
} }
#ifdef JSGC_COMPACTING
void void
Shape::fixupDictionaryShapeAfterMovingGC() Shape::fixupDictionaryShapeAfterMovingGC()
{ {
@ -322,8 +320,6 @@ Shape::fixupAfterMovingGC()
fixupShapeTreeAfterMovingGC(); fixupShapeTreeAfterMovingGC();
} }
#endif // JSGC_COMPACTING
void void
ShapeGetterSetterRef::mark(JSTracer *trc) ShapeGetterSetterRef::mark(JSTracer *trc)
{ {

Просмотреть файл

@ -20,8 +20,7 @@
#include "js/TypeDecls.h" #include "js/TypeDecls.h"
#if (defined(JS_GC_ZEAL)) || \ #if (defined(JS_GC_ZEAL)) || defined(DEBUG)
(defined(JSGC_COMPACTING) && defined(DEBUG))
# define JSGC_HASH_TABLE_CHECKS # define JSGC_HASH_TABLE_CHECKS
#endif #endif

Просмотреть файл

@ -357,6 +357,12 @@ ShellInterruptCallback(JSContext *cx)
if (!gServiceInterrupt) if (!gServiceInterrupt)
return true; return true;
// Reset gServiceInterrupt. CancelExecution or InterruptIf will set it to
// true to distinguish watchdog or user triggered interrupts.
// Do this first to prevent other interrupts that may occur while the
// user-supplied callback is executing from re-entering the handler.
gServiceInterrupt = false;
bool result; bool result;
RootedValue interruptFunc(cx, *gInterruptFunc); RootedValue interruptFunc(cx, *gInterruptFunc);
if (!interruptFunc.isNull()) { if (!interruptFunc.isNull()) {
@ -379,10 +385,6 @@ ShellInterruptCallback(JSContext *cx)
if (!result && gExitCode == 0) if (!result && gExitCode == 0)
gExitCode = EXITCODE_TIMEOUT; gExitCode = EXITCODE_TIMEOUT;
// Reset gServiceInterrupt. CancelExecution or InterruptIf will set it to
// true to distinguish watchdog or user triggered interrupts.
gServiceInterrupt = false;
return result; return result;
} }

Просмотреть файл

@ -112,6 +112,11 @@ function compOfBlock(left, right) Pattern({ type: "ComprehensionBlock", left: le
function arrPatt(elts) Pattern({ type: "ArrayPattern", elements: elts }) function arrPatt(elts) Pattern({ type: "ArrayPattern", elements: elts })
function objPatt(elts) Pattern({ type: "ObjectPattern", properties: elts }) function objPatt(elts) Pattern({ type: "ObjectPattern", properties: elts })
function assignElem(target, defaultExpr = null, targetIdent = typeof target == 'string' ? ident(target) : target) defaultExpr ? aExpr('=', targetIdent, defaultExpr) : targetIdent
function assignProp(property, target, defaultExpr = null, shorthand = !target, targetProp = target || ident(property)) Pattern({
type: "Property", key: ident(property), shorthand,
value: defaultExpr ? aExpr('=', targetProp, defaultExpr) : targetProp })
function localSrc(src) "(function(){ " + src + " })" function localSrc(src) "(function(){ " + src + " })"
function localPatt(patt) program([exprStmt(funExpr(null, [], blockStmt([patt])))]) function localPatt(patt) program([exprStmt(funExpr(null, [], blockStmt([patt])))])
function blockSrc(src) "(function(){ { " + src + " } })" function blockSrc(src) "(function(){ { " + src + " } })"
@ -235,7 +240,7 @@ assertDecl("function f(a,b,c) { function b() { } }",
funDecl(ident("f"), [ident("a"),ident("b"),ident("c")], blockStmt([funDecl(ident("b"), [], blockStmt([]))]))); funDecl(ident("f"), [ident("a"),ident("b"),ident("c")], blockStmt([funDecl(ident("b"), [], blockStmt([]))])));
assertDecl("function f(a,[x,y]) { function a() { } }", assertDecl("function f(a,[x,y]) { function a() { } }",
funDecl(ident("f"), funDecl(ident("f"),
[ident("a"), arrPatt([ident("x"), ident("y")])], [ident("a"), arrPatt([assignElem("x"), assignElem("y")])],
blockStmt([funDecl(ident("a"), [], blockStmt([]))]))); blockStmt([funDecl(ident("a"), [], blockStmt([]))])));
// Bug 632027: array holes should reflect as null // Bug 632027: array holes should reflect as null
@ -269,7 +274,7 @@ assertExpr("a => b => a", arrowExpr([ident("a")], arrowExpr([ident("b")], ident(
assertExpr("a => {}", arrowExpr([ident("a")], blockStmt([]))); assertExpr("a => {}", arrowExpr([ident("a")], blockStmt([])));
assertExpr("a => ({})", arrowExpr([ident("a")], objExpr([]))); assertExpr("a => ({})", arrowExpr([ident("a")], objExpr([])));
assertExpr("(a, b, c) => {}", arrowExpr([ident("a"), ident("b"), ident("c")], blockStmt([]))); assertExpr("(a, b, c) => {}", arrowExpr([ident("a"), ident("b"), ident("c")], blockStmt([])));
assertExpr("([a, b]) => {}", arrowExpr([arrPatt([ident("a"), ident("b")])], blockStmt([]))); assertExpr("([a, b]) => {}", arrowExpr([arrPatt([assignElem("a"), assignElem("b")])], blockStmt([])));
assertExpr("(++x)", updExpr("++", ident("x"), true)); assertExpr("(++x)", updExpr("++", ident("x"), true));
assertExpr("(x++)", updExpr("++", ident("x"), false)); assertExpr("(x++)", updExpr("++", ident("x"), false));
assertExpr("(+x)", unExpr("+", ident("x"))); assertExpr("(+x)", unExpr("+", ident("x")));
@ -566,9 +571,9 @@ assertStmt("function f() { var x = 42; var x = 43; }",
varDecl([{ id: ident("x"), init: lit(43) }])]))); varDecl([{ id: ident("x"), init: lit(43) }])])));
assertDecl("var {x:y} = foo;", varDecl([{ id: objPatt([{ key: ident("x"), value: ident("y"), shorthand: false }]), assertDecl("var {x:y} = foo;", varDecl([{ id: objPatt([assignProp("x", ident("y"))]),
init: ident("foo") }])); init: ident("foo") }]));
assertDecl("var {x} = foo;", varDecl([{ id: objPatt([{ key: ident("x"), value: ident("x"), shorthand: true }]), assertDecl("var {x} = foo;", varDecl([{ id: objPatt([assignProp("x")]),
init: ident("foo") }])); init: ident("foo") }]));
// Bug 632030: redeclarations between var and funargs, var and function // Bug 632030: redeclarations between var and funargs, var and function
@ -581,16 +586,16 @@ assertProg("f.p = 1; var f; f.p; function f(){}",
funDecl(ident("f"), [], blockStmt([]))]); funDecl(ident("f"), [], blockStmt([]))]);
// global let is var // global let is var
assertGlobalDecl("let {x:y} = foo;", varDecl([{ id: objPatt([{ key: ident("x"), value: ident("y") }]), assertGlobalDecl("let {x:y} = foo;", varDecl([{ id: objPatt([assignProp("x", ident("y"))]),
init: ident("foo") }])); init: ident("foo") }]));
// function-global let is let // function-global let is let
assertLocalDecl("let {x:y} = foo;", letDecl([{ id: objPatt([{ key: ident("x"), value: ident("y") }]), assertLocalDecl("let {x:y} = foo;", letDecl([{ id: objPatt([assignProp("x", ident("y"))]),
init: ident("foo") }])); init: ident("foo") }]));
// block-local let is let // block-local let is let
assertBlockDecl("let {x:y} = foo;", letDecl([{ id: objPatt([{ key: ident("x"), value: ident("y") }]), assertBlockDecl("let {x:y} = foo;", letDecl([{ id: objPatt([assignProp("x", ident("y"))]),
init: ident("foo") }])); init: ident("foo") }]));
assertDecl("const {x:y} = foo;", constDecl([{ id: objPatt([{ key: ident("x"), value: ident("y") }]), assertDecl("const {x:y} = foo;", constDecl([{ id: objPatt([assignProp("x", ident("y"))]),
init: ident("foo") }])); init: ident("foo") }]));
@ -670,16 +675,23 @@ function testParamPatternCombinations(makePattSrc, makePattPatt) {
} }
testParamPatternCombinations(function(n) ("{a" + n + ":x" + n + "," + "b" + n + ":y" + n + "," + "c" + n + ":z" + n + "}"), testParamPatternCombinations(function(n) ("{a" + n + ":x" + n + "," + "b" + n + ":y" + n + "," + "c" + n + ":z" + n + "}"),
function(n) (objPatt([{ key: ident("a" + n), value: ident("x" + n) }, function(n) (objPatt([assignProp("a" + n, ident("x" + n)),
{ key: ident("b" + n), value: ident("y" + n) }, assignProp("b" + n, ident("y" + n)),
{ key: ident("c" + n), value: ident("z" + n) }]))); assignProp("c" + n, ident("z" + n))])));
testParamPatternCombinations(function(n) ("{a" + n + ":x" + n + " = 10," + "b" + n + ":y" + n + " = 10," + "c" + n + ":z" + n + " = 10}"),
function(n) (objPatt([assignProp("a" + n, ident("x" + n), lit(10)),
assignProp("b" + n, ident("y" + n), lit(10)),
assignProp("c" + n, ident("z" + n), lit(10))])));
testParamPatternCombinations(function(n) ("[x" + n + "," + "y" + n + "," + "z" + n + "]"), testParamPatternCombinations(function(n) ("[x" + n + "," + "y" + n + "," + "z" + n + "]"),
function(n) (arrPatt([ident("x" + n), ident("y" + n), ident("z" + n)]))); function(n) (arrPatt([assignElem("x" + n), assignElem("y" + n), assignElem("z" + n)])));
testParamPatternCombinations(function(n) ("[a" + n + ", ..." + "b" + n + "]"), testParamPatternCombinations(function(n) ("[a" + n + ", ..." + "b" + n + "]"),
function(n) (arrPatt([ident("a" + n), spread(ident("b" + n))]))); function(n) (arrPatt([assignElem("a" + n), spread(ident("b" + n))])));
testParamPatternCombinations(function(n) ("[a" + n + ", " + "b" + n + " = 10]"),
function(n) (arrPatt([assignElem("a" + n), assignElem("b" + n, lit(10))])));
// destructuring variable declarations // destructuring variable declarations
@ -712,19 +724,28 @@ function testVarPatternCombinations(makePattSrc, makePattPatt) {
} }
testVarPatternCombinations(function (n) ("{a" + n + ":x" + n + "," + "b" + n + ":y" + n + "," + "c" + n + ":z" + n + "} = 0"), testVarPatternCombinations(function (n) ("{a" + n + ":x" + n + "," + "b" + n + ":y" + n + "," + "c" + n + ":z" + n + "} = 0"),
function (n) ({ id: objPatt([{ key: ident("a" + n), value: ident("x" + n) }, function (n) ({ id: objPatt([assignProp("a" + n, ident("x" + n)),
{ key: ident("b" + n), value: ident("y" + n) }, assignProp("b" + n, ident("y" + n)),
{ key: ident("c" + n), value: ident("z" + n) }]), assignProp("c" + n, ident("z" + n))]),
init: lit(0) }));
testVarPatternCombinations(function (n) ("{a" + n + ":x" + n + " = 10," + "b" + n + ":y" + n + " = 10," + "c" + n + ":z" + n + " = 10} = 0"),
function (n) ({ id: objPatt([assignProp("a" + n, ident("x" + n), lit(10)),
assignProp("b" + n, ident("y" + n), lit(10)),
assignProp("c" + n, ident("z" + n), lit(10))]),
init: lit(0) })); init: lit(0) }));
testVarPatternCombinations(function(n) ("[x" + n + "," + "y" + n + "," + "z" + n + "] = 0"), testVarPatternCombinations(function(n) ("[x" + n + "," + "y" + n + "," + "z" + n + "] = 0"),
function(n) ({ id: arrPatt([ident("x" + n), ident("y" + n), ident("z" + n)]), function(n) ({ id: arrPatt([assignElem("x" + n), assignElem("y" + n), assignElem("z" + n)]),
init: lit(0) })); init: lit(0) }));
testVarPatternCombinations(function(n) ("[a" + n + ", ..." + "b" + n + "] = 0"), testVarPatternCombinations(function(n) ("[a" + n + ", ..." + "b" + n + "] = 0"),
function(n) ({ id: arrPatt([ident("a" + n), spread(ident("b" + n))]), function(n) ({ id: arrPatt([assignElem("a" + n), spread(ident("b" + n))]),
init: lit(0) })); init: lit(0) }));
testVarPatternCombinations(function(n) ("[a" + n + ", " + "b" + n + " = 10] = 0"),
function(n) ({ id: arrPatt([assignElem("a" + n), assignElem("b" + n, lit(10))]),
init: lit(0) }));
// destructuring assignment // destructuring assignment
function testAssignmentCombinations(makePattSrc, makePattPatt) { function testAssignmentCombinations(makePattSrc, makePattPatt) {
@ -746,18 +767,18 @@ function testAssignmentCombinations(makePattSrc, makePattPatt) {
testAssignmentCombinations(function (n) ("{a" + n + ":x" + n + "," + "b" + n + ":y" + n + "," + "c" + n + ":z" + n + "} = 0"), testAssignmentCombinations(function (n) ("{a" + n + ":x" + n + "," + "b" + n + ":y" + n + "," + "c" + n + ":z" + n + "} = 0"),
function (n) (aExpr("=", function (n) (aExpr("=",
objPatt([{ key: ident("a" + n), value: ident("x" + n) }, objPatt([assignProp("a" + n, ident("x" + n)),
{ key: ident("b" + n), value: ident("y" + n) }, assignProp("b" + n, ident("y" + n)),
{ key: ident("c" + n), value: ident("z" + n) }]), assignProp("c" + n, ident("z" + n))]),
lit(0)))); lit(0))));
// destructuring in for-in and for-each-in loop heads // destructuring in for-in and for-each-in loop heads
var axbycz = objPatt([{ key: ident("a"), value: ident("x") }, var axbycz = objPatt([assignProp("a", ident("x")),
{ key: ident("b"), value: ident("y") }, assignProp("b", ident("y")),
{ key: ident("c"), value: ident("z") }]); assignProp("c", ident("z"))]);
var xyz = arrPatt([ident("x"), ident("y"), ident("z")]); var xyz = arrPatt([assignElem("x"), assignElem("y"), assignElem("z")]);
assertStmt("for (var {a:x,b:y,c:z} in foo);", forInStmt(varDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt)); assertStmt("for (var {a:x,b:y,c:z} in foo);", forInStmt(varDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));
assertStmt("for (let {a:x,b:y,c:z} in foo);", forInStmt(letDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt)); assertStmt("for (let {a:x,b:y,c:z} in foo);", forInStmt(letDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));

Просмотреть файл

@ -400,38 +400,30 @@ NewNativeObjectWithClassProto(ExclusiveContext *cx, const js::Class *clasp, JSOb
/* /*
* Call obj's resolve hook. * Call obj's resolve hook.
* *
* cx, id, and flags are the parameters initially passed to the ongoing lookup; * cx and id are the parameters initially passed to the ongoing lookup;
* objp and propp are its out parameters. obj is an object along the prototype * propp and recursedp are its out parameters.
* chain from where the lookup started.
* *
* There are four possible outcomes: * There are four possible outcomes:
* *
* - On failure, report an error or exception and return false. * - On failure, report an error or exception and return false.
* *
* - If we are already resolving a property of *curobjp, set *recursedp = true, * - If we are already resolving a property of obj, set *recursedp = true,
* and return true. * and return true.
* *
* - If the resolve hook finds or defines the sought property, set *objp and * - If the resolve hook finds or defines the sought property, set propp
* *propp appropriately, set *recursedp = false, and return true. * appropriately, set *recursedp = false, and return true.
* *
* - Otherwise no property was resolved. Set *propp = nullptr and * - Otherwise no property was resolved. Set propp to nullptr and
* *recursedp = false and return true. * *recursedp = false and return true.
*/ */
static MOZ_ALWAYS_INLINE bool static MOZ_ALWAYS_INLINE bool
CallResolveOp(JSContext *cx, HandleNativeObject obj, HandleId id, MutableHandleObject objp, CallResolveOp(JSContext *cx, HandleNativeObject obj, HandleId id, MutableHandleShape propp,
MutableHandleShape propp, bool *recursedp) bool *recursedp)
{ {
/* // Avoid recursion on (obj, id) already being resolved on cx.
* Avoid recursion on (obj, id) already being resolved on cx.
*
* Once we have successfully added an entry for (obj, key) to
* cx->resolvingTable, control must go through cleanup: before
* returning. But note that JS_DHASH_ADD may find an existing
* entry, in which case we bail to suppress runaway recursion.
*/
AutoResolving resolving(cx, obj, id); AutoResolving resolving(cx, obj, id);
if (resolving.alreadyStarted()) { if (resolving.alreadyStarted()) {
/* Already resolving id in obj -- suppress recursion. */ // Already resolving id in obj, suppress recursion.
*recursedp = true; *recursedp = true;
return true; return true;
} }
@ -444,18 +436,14 @@ CallResolveOp(JSContext *cx, HandleNativeObject obj, HandleId id, MutableHandleO
if (!resolved) if (!resolved)
return true; return true;
objp.set(obj);
if (JSID_IS_INT(id) && obj->containsDenseElement(JSID_TO_INT(id))) { if (JSID_IS_INT(id) && obj->containsDenseElement(JSID_TO_INT(id))) {
MarkDenseOrTypedArrayElementFound<CanGC>(propp); MarkDenseOrTypedArrayElementFound<CanGC>(propp);
return true; return true;
} }
if (Shape *shape = obj->lookup(cx, id)) MOZ_ASSERT(!IsAnyTypedArray(obj));
propp.set(shape);
else
objp.set(nullptr);
propp.set(obj->lookup(cx, id));
return true; return true;
} }
@ -464,13 +452,11 @@ static MOZ_ALWAYS_INLINE bool
LookupOwnPropertyInline(ExclusiveContext *cx, LookupOwnPropertyInline(ExclusiveContext *cx,
typename MaybeRooted<NativeObject*, allowGC>::HandleType obj, typename MaybeRooted<NativeObject*, allowGC>::HandleType obj,
typename MaybeRooted<jsid, allowGC>::HandleType id, typename MaybeRooted<jsid, allowGC>::HandleType id,
typename MaybeRooted<JSObject*, allowGC>::MutableHandleType objp,
typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp, typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp,
bool *donep) bool *donep)
{ {
// Check for a native dense element. // Check for a native dense element.
if (JSID_IS_INT(id) && obj->containsDenseElement(JSID_TO_INT(id))) { if (JSID_IS_INT(id) && obj->containsDenseElement(JSID_TO_INT(id))) {
objp.set(obj);
MarkDenseOrTypedArrayElementFound<allowGC>(propp); MarkDenseOrTypedArrayElementFound<allowGC>(propp);
*donep = true; *donep = true;
return true; return true;
@ -483,10 +469,8 @@ LookupOwnPropertyInline(ExclusiveContext *cx,
uint64_t index; uint64_t index;
if (IsTypedArrayIndex(id, &index)) { if (IsTypedArrayIndex(id, &index)) {
if (index < AnyTypedArrayLength(obj)) { if (index < AnyTypedArrayLength(obj)) {
objp.set(obj);
MarkDenseOrTypedArrayElementFound<allowGC>(propp); MarkDenseOrTypedArrayElementFound<allowGC>(propp);
} else { } else {
objp.set(nullptr);
propp.set(nullptr); propp.set(nullptr);
} }
*donep = true; *donep = true;
@ -496,7 +480,6 @@ LookupOwnPropertyInline(ExclusiveContext *cx,
// Check for a native property. // Check for a native property.
if (Shape *shape = obj->lookup(cx, id)) { if (Shape *shape = obj->lookup(cx, id)) {
objp.set(obj);
propp.set(shape); propp.set(shape);
*donep = true; *donep = true;
return true; return true;
@ -512,7 +495,6 @@ LookupOwnPropertyInline(ExclusiveContext *cx,
if (!CallResolveOp(cx->asJSContext(), if (!CallResolveOp(cx->asJSContext(),
MaybeRooted<NativeObject*, allowGC>::toHandle(obj), MaybeRooted<NativeObject*, allowGC>::toHandle(obj),
MaybeRooted<jsid, allowGC>::toHandle(id), MaybeRooted<jsid, allowGC>::toHandle(id),
MaybeRooted<JSObject*, allowGC>::toMutableHandle(objp),
MaybeRooted<Shape*, allowGC>::toMutableHandle(propp), MaybeRooted<Shape*, allowGC>::toMutableHandle(propp),
&recursed)) &recursed))
{ {
@ -520,7 +502,6 @@ LookupOwnPropertyInline(ExclusiveContext *cx,
} }
if (recursed) { if (recursed) {
objp.set(nullptr);
propp.set(nullptr); propp.set(nullptr);
*donep = true; *donep = true;
return true; return true;
@ -532,6 +513,7 @@ LookupOwnPropertyInline(ExclusiveContext *cx,
} }
} }
propp.set(nullptr);
*donep = false; *donep = false;
return true; return true;
} }
@ -584,10 +566,15 @@ LookupPropertyInline(ExclusiveContext *cx,
while (true) { while (true) {
bool done; bool done;
if (!LookupOwnPropertyInline<allowGC>(cx, current, id, objp, propp, &done)) if (!LookupOwnPropertyInline<allowGC>(cx, current, id, propp, &done))
return false; return false;
if (done) if (done) {
if (propp)
objp.set(current);
else
objp.set(nullptr);
return true; return true;
}
typename MaybeRooted<JSObject*, allowGC>::RootType proto(cx, current->getProto()); typename MaybeRooted<JSObject*, allowGC>::RootType proto(cx, current->getProto());

Просмотреть файл

@ -1458,14 +1458,8 @@ static bool
NativeLookupOwnProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId id, NativeLookupOwnProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId id,
MutableHandle<Shape*> shapep) MutableHandle<Shape*> shapep)
{ {
RootedObject pobj(cx);
bool done; bool done;
return LookupOwnPropertyInline<CanGC>(cx, obj, id, shapep, &done);
if (!LookupOwnPropertyInline<CanGC>(cx, obj, id, &pobj, shapep, &done))
return false;
if (!done || pobj != obj)
shapep.set(nullptr);
return true;
} }
template <AllowGC allowGC> template <AllowGC allowGC>
@ -2072,13 +2066,9 @@ js::NativeSetProperty(JSContext *cx, HandleNativeObject obj, HandleObject receiv
for (;;) { for (;;) {
// Steps 2-3. ('done' is a SpiderMonkey-specific thing, used below.) // Steps 2-3. ('done' is a SpiderMonkey-specific thing, used below.)
bool done; bool done;
RootedObject ancestor(cx); if (!LookupOwnPropertyInline<CanGC>(cx, pobj, id, &shape, &done))
if (!LookupOwnPropertyInline<CanGC>(cx, pobj, id, &ancestor, &shape, &done))
return false; return false;
if (!done || ancestor != pobj)
shape = nullptr;
if (shape) { if (shape) {
// Steps 5-6. // Steps 5-6.
return SetExistingProperty(cx, obj, receiver, id, pobj, shape, vp, strict); return SetExistingProperty(cx, obj, receiver, id, pobj, shape, vp, strict);

Просмотреть файл

@ -224,14 +224,12 @@ GetShapeAttributes(JSObject *obj, Shape *shape)
return shape->attributes(); return shape->attributes();
} }
#ifdef JSGC_COMPACTING
inline void inline void
BaseShape::fixupAfterMovingGC() BaseShape::fixupAfterMovingGC()
{ {
if (hasTable()) if (hasTable())
table().fixupAfterMovingGC(); table().fixupAfterMovingGC();
} }
#endif
} /* namespace js */ } /* namespace js */

Просмотреть файл

@ -256,7 +256,6 @@ ShapeTable::search(jsid id, bool adding)
MOZ_CRASH("Shape::search failed to find an expected entry."); MOZ_CRASH("Shape::search failed to find an expected entry.");
} }
#ifdef JSGC_COMPACTING
void void
ShapeTable::fixupAfterMovingGC() ShapeTable::fixupAfterMovingGC()
{ {
@ -268,7 +267,6 @@ ShapeTable::fixupAfterMovingGC()
entry.setPreservingCollision(Forwarded(shape)); entry.setPreservingCollision(Forwarded(shape));
} }
} }
#endif
bool bool
ShapeTable::change(int log2Delta, ExclusiveContext *cx) ShapeTable::change(int log2Delta, ExclusiveContext *cx)
@ -1693,7 +1691,6 @@ JSCompartment::sweepInitialShapeTable()
} }
} }
#ifdef JSGC_COMPACTING
void void
JSCompartment::fixupInitialShapeTable() JSCompartment::fixupInitialShapeTable()
{ {
@ -1732,7 +1729,6 @@ JSCompartment::fixupInitialShapeTable()
} }
} }
} }
#endif // JSGC_COMPACTING
void void
AutoRooterGetterSetter::Inner::trace(JSTracer *trc) AutoRooterGetterSetter::Inner::trace(JSTracer *trc)

Просмотреть файл

@ -227,10 +227,8 @@ class ShapeTable {
bool change(int log2Delta, ExclusiveContext *cx); bool change(int log2Delta, ExclusiveContext *cx);
Entry &search(jsid id, bool adding); Entry &search(jsid id, bool adding);
#ifdef JSGC_COMPACTING
/* Update entries whose shapes have been moved */ /* Update entries whose shapes have been moved */
void fixupAfterMovingGC(); void fixupAfterMovingGC();
#endif
private: private:
Entry &getEntry(uint32_t i) const { Entry &getEntry(uint32_t i) const {
@ -530,9 +528,7 @@ class BaseShape : public gc::TenuredCell
gc::MarkObject(trc, &metadata, "metadata"); gc::MarkObject(trc, &metadata, "metadata");
} }
#ifdef JSGC_COMPACTING
void fixupAfterMovingGC(); void fixupAfterMovingGC();
#endif
private: private:
static void staticAsserts() { static void staticAsserts() {
@ -1061,9 +1057,7 @@ class Shape : public gc::TenuredCell
inline Shape *search(ExclusiveContext *cx, jsid id); inline Shape *search(ExclusiveContext *cx, jsid id);
inline Shape *searchLinear(jsid id); inline Shape *searchLinear(jsid id);
#ifdef JSGC_COMPACTING
void fixupAfterMovingGC(); void fixupAfterMovingGC();
#endif
/* For JIT usage */ /* For JIT usage */
static inline size_t offsetOfBase() { return offsetof(Shape, base_); } static inline size_t offsetOfBase() { return offsetof(Shape, base_); }
@ -1071,10 +1065,8 @@ class Shape : public gc::TenuredCell
static inline uint32_t fixedSlotsMask() { return FIXED_SLOTS_MASK; } static inline uint32_t fixedSlotsMask() { return FIXED_SLOTS_MASK; }
private: private:
#ifdef JSGC_COMPACTING
void fixupDictionaryShapeAfterMovingGC(); void fixupDictionaryShapeAfterMovingGC();
void fixupShapeTreeAfterMovingGC(); void fixupShapeTreeAfterMovingGC();
#endif
static void staticAsserts() { static void staticAsserts() {
JS_STATIC_ASSERT(offsetof(Shape, base_) == offsetof(js::shadow::Shape, base)); JS_STATIC_ASSERT(offsetof(Shape, base_) == offsetof(js::shadow::Shape, base));

Просмотреть файл

@ -65,7 +65,7 @@ using JS::CanonicalizeNaN;
// a stable ID, it need not be at the end of the list and should not be used for // a stable ID, it need not be at the end of the list and should not be used for
// sizing data structures. // sizing data structures.
enum StructuredDataType MOZ_ENUM_TYPE(uint32_t) { enum StructuredDataType : uint32_t {
/* Structured data types provided by the engine */ /* Structured data types provided by the engine */
SCTAG_FLOAT_MAX = 0xFFF00000, SCTAG_FLOAT_MAX = 0xFFF00000,
SCTAG_NULL = 0xFFFF0000, SCTAG_NULL = 0xFFFF0000,

Просмотреть файл

@ -1065,9 +1065,12 @@ public:
static void static void
TraceWrappedNativesInAllScopes(JSTracer* trc, XPCJSRuntime* rt); TraceWrappedNativesInAllScopes(JSTracer* trc, XPCJSRuntime* rt);
void TraceInside(JSTracer *trc) { void TraceSelf(JSTracer *trc) {
MOZ_ASSERT(mGlobalJSObject); MOZ_ASSERT(mGlobalJSObject);
mGlobalJSObject.trace(trc, "XPCWrappedNativeScope::mGlobalJSObject"); mGlobalJSObject.trace(trc, "XPCWrappedNativeScope::mGlobalJSObject");
}
void TraceInside(JSTracer *trc) {
if (mContentXBLScope) if (mContentXBLScope)
mContentXBLScope.trace(trc, "XPCWrappedNativeScope::mXBLScope"); mContentXBLScope.trace(trc, "XPCWrappedNativeScope::mXBLScope");
for (size_t i = 0; i < mAddonScopes.Length(); i++) for (size_t i = 0; i < mAddonScopes.Length(); i++)
@ -1847,7 +1850,7 @@ public:
mScriptableInfo->Mark(); mScriptableInfo->Mark();
} }
GetScope()->TraceInside(trc); GetScope()->TraceSelf(trc);
} }
void TraceJS(JSTracer *trc) { void TraceJS(JSTracer *trc) {
@ -2162,7 +2165,7 @@ public:
if (HasProto()) if (HasProto())
GetProto()->TraceSelf(trc); GetProto()->TraceSelf(trc);
else else
GetScope()->TraceInside(trc); GetScope()->TraceSelf(trc);
if (mFlatJSObject && JS_IsGlobalObject(mFlatJSObject)) if (mFlatJSObject && JS_IsGlobalObject(mFlatJSObject))
{ {
xpc::TraceXPCGlobal(trc, mFlatJSObject); xpc::TraceXPCGlobal(trc, mFlatJSObject);

Просмотреть файл

@ -2343,11 +2343,14 @@ ContainerState::PopPaintedLayerData()
EventRegions regions; EventRegions regions;
regions.mHitRegion = ScaleRegionToOutsidePixels(data->mHitRegion); regions.mHitRegion = ScaleRegionToOutsidePixels(data->mHitRegion);
// Points whose hit-region status we're not sure about need to be dispatched // Points whose hit-region status we're not sure about need to be dispatched
// to the content thread. // to the content thread. If a point is in both maybeHitRegion and hitRegion
// then it's not a "maybe" any more, and doesn't go into the dispatch-to-
// content region.
nsIntRegion maybeHitRegion = ScaleRegionToOutsidePixels(data->mMaybeHitRegion); nsIntRegion maybeHitRegion = ScaleRegionToOutsidePixels(data->mMaybeHitRegion);
regions.mDispatchToContentHitRegion.Sub(maybeHitRegion, regions.mHitRegion); regions.mDispatchToContentHitRegion.Sub(maybeHitRegion, regions.mHitRegion);
regions.mDispatchToContentHitRegion.Or(regions.mDispatchToContentHitRegion, regions.mDispatchToContentHitRegion.OrWith(
ScaleRegionToOutsidePixels(data->mDispatchToContentHitRegion)); ScaleRegionToOutsidePixels(data->mDispatchToContentHitRegion));
regions.mHitRegion.OrWith(maybeHitRegion);
nsIntPoint translation = -GetTranslationForPaintedLayer(data->mLayer); nsIntPoint translation = -GetTranslationForPaintedLayer(data->mLayer);
regions.mHitRegion.MoveBy(translation); regions.mHitRegion.MoveBy(translation);

Просмотреть файл

@ -56,8 +56,4 @@ LOCAL_INCLUDES += [
if CONFIG['ENABLE_INTL_API']: if CONFIG['ENABLE_INTL_API']:
# nsNumberControlFrame.cpp requires ICUUtils.h which in turn requires # nsNumberControlFrame.cpp requires ICUUtils.h which in turn requires
# i18n/unum.h # i18n/unum.h
LOCAL_INCLUDES += [ CXXFLAGS += CONFIG['MOZ_ICU_CFLAGS']
'../../intl/icu/source/common',
'../../intl/icu/source/i18n',
]

Просмотреть файл

@ -1469,7 +1469,7 @@ void nsDisplayComboboxFocus::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx) nsRenderingContext* aCtx)
{ {
static_cast<nsComboboxControlFrame*>(mFrame) static_cast<nsComboboxControlFrame*>(mFrame)
->PaintFocus(*aCtx, ToReferenceFrame()); ->PaintFocus(*aCtx->GetDrawTarget(), ToReferenceFrame());
} }
void void
@ -1511,7 +1511,7 @@ nsComboboxControlFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
DisplaySelectionOverlay(aBuilder, aLists.Content()); DisplaySelectionOverlay(aBuilder, aLists.Content());
} }
void nsComboboxControlFrame::PaintFocus(nsRenderingContext& aRenderingContext, void nsComboboxControlFrame::PaintFocus(DrawTarget& aDrawTarget,
nsPoint aPt) nsPoint aPt)
{ {
/* Do we need to do anything? */ /* Do we need to do anything? */
@ -1519,13 +1519,12 @@ void nsComboboxControlFrame::PaintFocus(nsRenderingContext& aRenderingContext,
if (eventStates.HasState(NS_EVENT_STATE_DISABLED) || sFocused != this) if (eventStates.HasState(NS_EVENT_STATE_DISABLED) || sFocused != this)
return; return;
gfxContext* gfx = aRenderingContext.ThebesContext(); int32_t appUnitsPerDevPixel = PresContext()->AppUnitsPerDevPixel();
gfx->Save();
nsRect clipRect = mDisplayFrame->GetRect() + aPt; nsRect clipRect = mDisplayFrame->GetRect() + aPt;
gfx->Clip(NSRectToSnappedRect(clipRect, aDrawTarget.PushClipRect(NSRectToSnappedRect(clipRect,
PresContext()->AppUnitsPerDevPixel(), appUnitsPerDevPixel,
*aRenderingContext.GetDrawTarget())); aDrawTarget));
// REVIEW: Why does the old code paint mDisplayFrame again? We've // REVIEW: Why does the old code paint mDisplayFrame again? We've
// already painted it in the children above. So clipping it here won't do // already painted it in the children above. So clipping it here won't do
@ -1540,12 +1539,10 @@ void nsComboboxControlFrame::PaintFocus(nsRenderingContext& aRenderingContext,
nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1); nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
clipRect.width -= onePixel; clipRect.width -= onePixel;
clipRect.height -= onePixel; clipRect.height -= onePixel;
Rect r = Rect r = ToRect(nsLayoutUtils::RectToGfxRect(clipRect, appUnitsPerDevPixel));
ToRect(nsLayoutUtils::RectToGfxRect(clipRect, PresContext()->AppUnitsPerDevPixel())); StrokeSnappedEdgesOfRect(r, aDrawTarget, color, strokeOptions);
StrokeSnappedEdgesOfRect(r, *aRenderingContext.GetDrawTarget(),
color, strokeOptions);
gfx->Restore(); aDrawTarget.PopClip();
} }
//--------------------------------------------------------- //---------------------------------------------------------

Просмотреть файл

@ -37,6 +37,12 @@ class nsComboboxDisplayFrame;
class nsIDOMEventListener; class nsIDOMEventListener;
class nsIScrollableFrame; class nsIScrollableFrame;
namespace mozilla {
namespace gfx {
class DrawTarget;
}
}
class nsComboboxControlFrame MOZ_FINAL : public nsBlockFrame, class nsComboboxControlFrame MOZ_FINAL : public nsBlockFrame,
public nsIFormControlFrame, public nsIFormControlFrame,
public nsIComboboxControlFrame, public nsIComboboxControlFrame,
@ -45,6 +51,8 @@ class nsComboboxControlFrame MOZ_FINAL : public nsBlockFrame,
public nsIRollupListener, public nsIRollupListener,
public nsIStatefulFrame public nsIStatefulFrame
{ {
typedef mozilla::gfx::DrawTarget DrawTarget;
public: public:
friend nsContainerFrame* NS_NewComboboxControlFrame(nsIPresShell* aPresShell, friend nsContainerFrame* NS_NewComboboxControlFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext, nsStyleContext* aContext,
@ -84,7 +92,7 @@ public:
const nsRect& aDirtyRect, const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) MOZ_OVERRIDE; const nsDisplayListSet& aLists) MOZ_OVERRIDE;
void PaintFocus(nsRenderingContext& aRenderingContext, nsPoint aPt); void PaintFocus(DrawTarget& aDrawTarget, nsPoint aPt);
// XXXbz this is only needed to prevent the quirk percent height stuff from // XXXbz this is only needed to prevent the quirk percent height stuff from
// leaking out of the combobox. We may be able to get rid of this as more // leaking out of the combobox. We may be able to get rid of this as more

Просмотреть файл

@ -2916,8 +2916,9 @@ void
SVGTextDrawPathCallbacks::HandleTextGeometry() SVGTextDrawPathCallbacks::HandleTextGeometry()
{ {
if (IsClipPathChild()) { if (IsClipPathChild()) {
gfx->SetColor(gfxRGBA(1.0f, 1.0f, 1.0f, 1.0f)); RefPtr<Path> path = gfx->GetPath();
gfx->Fill(); ColorPattern white(Color(1.f, 1.f, 1.f, 1.f)); // for masking, so no ToDeviceColor
gfx->GetDrawTarget()->Fill(path, white);
} else { } else {
// Normal painting. // Normal painting.
gfxContextMatrixAutoSaveRestore saveMatrix(gfx); gfxContextMatrixAutoSaveRestore saveMatrix(gfx);
@ -2984,11 +2985,15 @@ SVGTextDrawPathCallbacks::FillGeometry()
GeneralPattern fillPattern; GeneralPattern fillPattern;
MakeFillPattern(&fillPattern); MakeFillPattern(&fillPattern);
if (fillPattern.GetPattern()) { if (fillPattern.GetPattern()) {
gfx->SetFillRule( RefPtr<Path> path = gfx->GetPath();
nsSVGUtils::ToFillRule( FillRule fillRule = nsSVGUtils::ToFillRule(IsClipPathChild() ?
IsClipPathChild() ? mFrame->StyleSVG()->mClipRule :
mFrame->StyleSVG()->mClipRule : mFrame->StyleSVG()->mFillRule)); mFrame->StyleSVG()->mFillRule);
gfx->Fill(fillPattern); if (fillRule != path->GetFillRule()) {
RefPtr<PathBuilder> builder = path->CopyToBuilder(fillRule);
path = builder->Finish();
}
gfx->GetDrawTarget()->Fill(path, fillPattern);
} }
} }

Просмотреть файл

@ -468,20 +468,32 @@ PeerConnectionImpl::ConvertRTCConfiguration(const RTCConfiguration& aSrc,
IceConfiguration *aDst) IceConfiguration *aDst)
{ {
#ifdef MOZILLA_INTERNAL_API #ifdef MOZILLA_INTERNAL_API
if (!aSrc.mIceServers.WasPassed()) { if (aSrc.mIceServers.WasPassed()) {
return NS_OK; for (size_t i = 0; i < aSrc.mIceServers.Value().Length(); i++) {
nsresult rv = AddIceServer(aSrc.mIceServers.Value()[i], aDst);
NS_ENSURE_SUCCESS(rv, rv);
}
} }
for (uint32_t i = 0; i < aSrc.mIceServers.Value().Length(); i++) { #endif
const RTCIceServer& server = aSrc.mIceServers.Value()[i]; return NS_OK;
NS_ENSURE_TRUE(server.mUrl.WasPassed(), NS_ERROR_UNEXPECTED); }
nsresult
PeerConnectionImpl::AddIceServer(const RTCIceServer &aServer,
IceConfiguration *aDst)
{
#ifdef MOZILLA_INTERNAL_API
NS_ENSURE_STATE(aServer.mUrls.WasPassed());
NS_ENSURE_STATE(aServer.mUrls.Value().IsStringSequence());
auto &urls = aServer.mUrls.Value().GetAsStringSequence();
for (size_t i = 0; i < urls.Length(); i++) {
// Without STUN/TURN handlers, NS_NewURI returns nsSimpleURI rather than // Without STUN/TURN handlers, NS_NewURI returns nsSimpleURI rather than
// nsStandardURL. To parse STUN/TURN URI's to spec // nsStandardURL. To parse STUN/TURN URI's to spec
// http://tools.ietf.org/html/draft-nandakumar-rtcweb-stun-uri-02#section-3 // http://tools.ietf.org/html/draft-nandakumar-rtcweb-stun-uri-02#section-3
// http://tools.ietf.org/html/draft-petithuguenin-behave-turn-uri-03#section-3 // http://tools.ietf.org/html/draft-petithuguenin-behave-turn-uri-03#section-3
// we parse out the query-string, and use ParseAuthority() on the rest // we parse out the query-string, and use ParseAuthority() on the rest
nsRefPtr<nsIURI> url; nsRefPtr<nsIURI> url;
nsresult rv = NS_NewURI(getter_AddRefs(url), server.mUrl.Value()); nsresult rv = NS_NewURI(getter_AddRefs(url), urls[i]);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
bool isStun = false, isStuns = false, isTurn = false, isTurns = false; bool isStun = false, isStuns = false, isTurn = false, isTurns = false;
url->SchemeIs("stun", &isStun); url->SchemeIs("stun", &isStun);
@ -542,8 +554,8 @@ PeerConnectionImpl::ConvertRTCConfiguration(const RTCConfiguration& aSrc,
port = (isStuns || isTurns)? 5349 : 3478; port = (isStuns || isTurns)? 5349 : 3478;
if (isTurn || isTurns) { if (isTurn || isTurns) {
NS_ConvertUTF16toUTF8 credential(server.mCredential); NS_ConvertUTF16toUTF8 credential(aServer.mCredential);
NS_ConvertUTF16toUTF8 username(server.mUsername); NS_ConvertUTF16toUTF8 username(aServer.mUsername);
// Bug 1039655 - TURN TCP is not e10s ready // Bug 1039655 - TURN TCP is not e10s ready
if ((transport == kNrIceTransportTcp) && if ((transport == kNrIceTransportTcp) &&

Просмотреть файл

@ -78,6 +78,7 @@ class DOMMediaStream;
namespace dom { namespace dom {
struct RTCConfiguration; struct RTCConfiguration;
struct RTCIceServer;
struct RTCOfferOptions; struct RTCOfferOptions;
#ifdef USE_FAKE_MEDIA_STREAMS #ifdef USE_FAKE_MEDIA_STREAMS
typedef Fake_MediaStreamTrack MediaStreamTrack; typedef Fake_MediaStreamTrack MediaStreamTrack;
@ -118,6 +119,7 @@ namespace mozilla {
using mozilla::dom::PeerConnectionObserver; using mozilla::dom::PeerConnectionObserver;
using mozilla::dom::RTCConfiguration; using mozilla::dom::RTCConfiguration;
using mozilla::dom::RTCIceServer;
using mozilla::dom::RTCOfferOptions; using mozilla::dom::RTCOfferOptions;
using mozilla::DOMMediaStream; using mozilla::DOMMediaStream;
using mozilla::NrIceCtx; using mozilla::NrIceCtx;
@ -259,6 +261,8 @@ public:
static PeerConnectionImpl* CreatePeerConnection(); static PeerConnectionImpl* CreatePeerConnection();
static nsresult ConvertRTCConfiguration(const RTCConfiguration& aSrc, static nsresult ConvertRTCConfiguration(const RTCConfiguration& aSrc,
IceConfiguration *aDst); IceConfiguration *aDst);
static nsresult AddIceServer(const RTCIceServer& aServer,
IceConfiguration* aDst);
already_AddRefed<DOMMediaStream> MakeMediaStream(uint32_t aHint); already_AddRefed<DOMMediaStream> MakeMediaStream(uint32_t aHint);
nsresult CreateRemoteSourceStreamInfo(nsRefPtr<RemoteSourceStreamInfo>* aInfo, nsresult CreateRemoteSourceStreamInfo(nsRefPtr<RemoteSourceStreamInfo>* aInfo,

Просмотреть файл

@ -14,31 +14,6 @@
#if defined(__cplusplus) #if defined(__cplusplus)
/**
* MOZ_ENUM_TYPE specifies the underlying numeric type for an enum. It's
* specified by placing MOZ_ENUM_TYPE(type) immediately after the enum name in
* its declaration, and before the opening curly brace, like
*
* enum MyEnum MOZ_ENUM_TYPE(uint16_t)
* {
* A,
* B = 7,
* C
* };
*
* In supporting compilers, the macro will expand to ": uint16_t". The
* compiler will allocate exactly two bytes for MyEnum and will require all
* enumerators to have values between 0 and 65535. (Thus specifying "B =
* 100000" instead of "B = 7" would fail to compile.) In old compilers the
* macro expands to the empty string, and the underlying type is generally
* undefined.
*/
#ifdef MOZ_HAVE_CXX11_ENUM_TYPE
# define MOZ_ENUM_TYPE(type) : type
#else
# define MOZ_ENUM_TYPE(type) /* no support */
#endif
/** /**
* MOZ_BEGIN_ENUM_CLASS and MOZ_END_ENUM_CLASS provide access to the * MOZ_BEGIN_ENUM_CLASS and MOZ_END_ENUM_CLASS provide access to the
* strongly-typed enumeration feature of C++11 ("enum class"). If supported * strongly-typed enumeration feature of C++11 ("enum class"). If supported
@ -155,7 +130,7 @@
class Name \ class Name \
{ \ { \
public: \ public: \
enum Enum MOZ_ENUM_TYPE(type) \ enum Enum : type \
{ {
# define MOZ_END_NESTED_ENUM_CLASS(Name) \ # define MOZ_END_NESTED_ENUM_CLASS(Name) \
}; \ }; \

Просмотреть файл

@ -26,18 +26,15 @@
# define __has_extension __has_feature /* compatibility, for older versions of clang */ # define __has_extension __has_feature /* compatibility, for older versions of clang */
# endif # endif
# if __has_extension(cxx_strong_enums) # if __has_extension(cxx_strong_enums)
# define MOZ_HAVE_CXX11_ENUM_TYPE
# define MOZ_HAVE_CXX11_STRONG_ENUMS # define MOZ_HAVE_CXX11_STRONG_ENUMS
# endif # endif
#elif defined(__GNUC__) #elif defined(__GNUC__)
# if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L # if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
# if MOZ_GCC_VERSION_AT_LEAST(4, 6, 3) # if MOZ_GCC_VERSION_AT_LEAST(4, 6, 3)
# define MOZ_HAVE_CXX11_ENUM_TYPE
# define MOZ_HAVE_CXX11_STRONG_ENUMS # define MOZ_HAVE_CXX11_STRONG_ENUMS
# endif # endif
# endif # endif
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
# define MOZ_HAVE_CXX11_ENUM_TYPE
# define MOZ_HAVE_CXX11_STRONG_ENUMS # define MOZ_HAVE_CXX11_STRONG_ENUMS
#endif #endif

Просмотреть файл

@ -563,7 +563,7 @@ pref("media.fragmented-mp4.android-media-codec.enabled", true);
pref("media.fragmented-mp4.android-media-codec.preferred", true); pref("media.fragmented-mp4.android-media-codec.preferred", true);
// optimize images memory usage // optimize images memory usage
pref("image.mem.decodeondraw", false); pref("image.mem.decodeondraw", true);
#ifdef NIGHTLY_BUILD #ifdef NIGHTLY_BUILD
// Shumway component (SWF player) is disabled by default. Also see bug 904346. // Shumway component (SWF player) is disabled by default. Also see bug 904346.

Просмотреть файл

@ -7,7 +7,7 @@ const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Messaging.jsm"); Cu.import("resource://gre/modules/Messaging.jsm");
const CONFIG = { iceServers: [{ "url": "stun:stun.services.mozilla.com" }] }; const CONFIG = { iceServers: [{ "urls": ["stun:stun.services.mozilla.com"] }] };
let log = Cu.import("resource://gre/modules/AndroidLog.jsm", let log = Cu.import("resource://gre/modules/AndroidLog.jsm",
{}).AndroidLog.d.bind(null, "TabMirror"); {}).AndroidLog.d.bind(null, "TabMirror");

Просмотреть файл

@ -360,7 +360,7 @@ pref("media.peerconnection.video.start_bitrate", 300);
pref("media.peerconnection.video.max_bitrate", 2000); pref("media.peerconnection.video.max_bitrate", 2000);
#endif #endif
pref("media.navigator.permission.disabled", false); pref("media.navigator.permission.disabled", false);
pref("media.peerconnection.default_iceservers", "[{\"url\": \"stun:stun.services.mozilla.com\"}]"); pref("media.peerconnection.default_iceservers", "[{\"urls\": [\"stun:stun.services.mozilla.com\"]}]");
pref("media.peerconnection.ice.loopback", false); // Set only for testing in offline environments. pref("media.peerconnection.ice.loopback", false); // Set only for testing in offline environments.
pref("media.peerconnection.use_document_iceservers", true); pref("media.peerconnection.use_document_iceservers", true);
// Do not enable identity before ensuring that the UX cannot be spoofed // Do not enable identity before ensuring that the UX cannot be spoofed
@ -3789,7 +3789,7 @@ pref("image.mem.discardable", true);
// Prevents images from automatically being decoded on load, instead allowing // Prevents images from automatically being decoded on load, instead allowing
// them to be decoded on demand when they are drawn. // them to be decoded on demand when they are drawn.
pref("image.mem.decodeondraw", false); pref("image.mem.decodeondraw", true);
// Allows image locking of decoded image data in content processes. // Allows image locking of decoded image data in content processes.
pref("image.mem.allow_locking_in_content_processes", true); pref("image.mem.allow_locking_in_content_processes", true);

Просмотреть файл

@ -2183,8 +2183,10 @@ HttpBaseChannel::SetupReplacementChannel(nsIURI *newURI,
nsCOMPtr<nsIURI> uri; nsCOMPtr<nsIURI> uri;
mRedirects[i]->GetURI(getter_AddRefs(uri)); mRedirects[i]->GetURI(getter_AddRefs(uri));
nsCString spec; nsCString spec;
uri->GetSpec(spec); if (uri) {
LOG(("HttpBaseChannel::SetupReplacementChannel adding redirect %s " uri->GetSpec(spec);
}
LOG(("HttpBaseChannel::SetupReplacementChannel adding redirect \'%s\' "
"[this=%p]", spec.get(), this)); "[this=%p]", spec.get(), this));
#endif #endif
httpInternal->AddRedirect(mRedirects[i]); httpInternal->AddRedirect(mRedirects[i]);

Просмотреть файл

@ -1,5 +1,6 @@
[DEFAULT] [DEFAULT]
skip-if = buildapp == 'b2g' || e10s skip-if = buildapp == 'b2g' || e10s || toolkit == 'android' # Android: Bug 1111137 & 1078267
support-files = support-files =
method.sjs method.sjs
partial_content.sjs partial_content.sjs
@ -10,7 +11,6 @@ support-files =
[test_partially_cached_content.html] [test_partially_cached_content.html]
[test_uri_scheme.html] [test_uri_scheme.html]
[test_user_agent_overrides.html] [test_user_agent_overrides.html]
skip-if = toolkit == 'android' # Bug 1111137
[test_user_agent_updates.html] [test_user_agent_updates.html]
[test_user_agent_updates_reset.html] [test_user_agent_updates_reset.html]
[test_xhr_method_case.html] [test_xhr_method_case.html]

Просмотреть файл

@ -263,8 +263,10 @@ fail-if = os == "android"
# spdy and http2 unit tests require us to have node available to run the spdy and http2 server # spdy and http2 unit tests require us to have node available to run the spdy and http2 server
[test_spdy.js] [test_spdy.js]
run-if = hasNode run-if = hasNode
run-sequentially = node server exceptions dont replay well
[test_http2.js] [test_http2.js]
run-if = hasNode run-if = hasNode
run-sequentially = node server exceptions dont replay well
[test_speculative_connect.js] [test_speculative_connect.js]
[test_standardurl.js] [test_standardurl.js]
[test_standardurl_port.js] [test_standardurl_port.js]

Просмотреть файл

@ -0,0 +1,105 @@
# 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/.
config = {
"suite_definitions": {
"mochitest": {
"run_filename": "runtestsremote.py",
"testsdir": "mochitest",
"options": ["--autorun", "--close-when-done", "--dm_trans=adb",
"--console-level=INFO", "--app=%(app)s", "--remote-webserver=%(remote_webserver)s",
"--xre-path=%(xre_path)s", "--utility-path=%(utility_path)s",
"--http-port=%(http_port)s", "--ssl-port=%(ssl_port)s",
"--certificate-path=%(certs_path)s", "--symbols-path=%(symbols_path)s",
"--quiet", "--log-raw=%(raw_log_file)s",
"--total-chunks=16",
"--run-only-tests=android23.json",
],
},
"mochitest-gl": {
"run_filename": "runtestsremote.py",
"testsdir": "mochitest",
"options": ["--autorun", "--close-when-done", "--dm_trans=adb",
"--console-level=INFO", "--app=%(app)s", "--remote-webserver=%(remote_webserver)s",
"--xre-path=%(xre_path)s", "--utility-path=%(utility_path)s",
"--http-port=%(http_port)s", "--ssl-port=%(ssl_port)s",
"--certificate-path=%(certs_path)s", "--symbols-path=%(symbols_path)s",
"--quiet", "--log-raw=%(raw_log_file)s",
"--total-chunks=2",
"--test-manifest=gl.json",
],
},
"robocop": {
"run_filename": "runtestsremote.py",
"testsdir": "mochitest",
"options": ["--autorun", "--close-when-done", "--dm_trans=adb",
"--console-level=INFO", "--app=%(app)s", "--remote-webserver=%(remote_webserver)s",
"--xre-path=%(xre_path)s", "--utility-path=%(utility_path)s",
"--http-port=%(http_port)s", "--ssl-port=%(ssl_port)s",
"--certificate-path=%(certs_path)s", "--symbols-path=%(symbols_path)s",
"--quiet", "--log-raw=%(raw_log_file)s",
"--total-chunks=4",
"--robocop-path=../..",
"--robocop-ids=fennec_ids.txt",
"--robocop=robocop.ini",
],
},
"reftest": {
"run_filename": "remotereftest.py",
"testsdir": "reftest",
"options": [ "--app=%(app)s", "--ignore-window-size",
"--dm_trans=adb",
"--bootstrap",
"--remote-webserver=%(remote_webserver)s", "--xre-path=%(xre_path)s",
"--utility-path=%(utility_path)s", "--http-port=%(http_port)s",
"--ssl-port=%(ssl_port)s", "--httpd-path", "%(modules_dir)s",
"--symbols-path=%(symbols_path)s",
"--total-chunks=16",
"tests/layout/reftests/reftest.list",
],
},
"crashtest": {
"run_filename": "remotereftest.py",
"testsdir": "reftest",
"options": [ "--app=%(app)s", "--ignore-window-size",
"--dm_trans=adb",
"--bootstrap",
"--remote-webserver=%(remote_webserver)s", "--xre-path=%(xre_path)s",
"--utility-path=%(utility_path)s", "--http-port=%(http_port)s",
"--ssl-port=%(ssl_port)s", "--httpd-path", "%(modules_dir)s",
"--symbols-path=%(symbols_path)s",
"--total-chunks=2",
"tests/testing/crashtest/crashtests.list",
],
},
"jsreftest": {
"run_filename": "remotereftest.py",
"testsdir": "reftest",
"options": [ "--app=%(app)s", "--ignore-window-size",
"--dm_trans=adb",
"--bootstrap",
"--remote-webserver=%(remote_webserver)s", "--xre-path=%(xre_path)s",
"--utility-path=%(utility_path)s", "--http-port=%(http_port)s",
"--ssl-port=%(ssl_port)s", "--httpd-path", "%(modules_dir)s",
"--symbols-path=%(symbols_path)s",
"../jsreftest/tests/jstests.list",
"--total-chunks=6",
"--extra-profile-file=jsreftest/tests/user.js",
],
},
"xpcshell": {
"run_filename": "remotexpcshelltests.py",
"testsdir": "xpcshell",
"options": [
"--dm_trans=adb",
"--xre-path=%(xre_path)s", "--testing-modules-dir=%(modules_dir)s",
"--apk=%(installer_path)s", "--no-logfiles",
"--symbols-path=%(symbols_path)s",
"--manifest=tests/xpcshell.ini",
"--log-raw=%(raw_log_file)s",
"--total-chunks=3",
],
},
}, # end suite_definitions
}

Просмотреть файл

@ -5,7 +5,7 @@
}, },
"global": { "global": {
"talos_repo": "https://hg.mozilla.org/build/talos", "talos_repo": "https://hg.mozilla.org/build/talos",
"talos_revision": "ebc4327b8cb8" "talos_revision": "39c9c9b33cfc"
}, },
"extra_options": { "extra_options": {
"android": [ "--apkPath=%(apk_path)s" ] "android": [ "--apkPath=%(apk_path)s" ]
@ -39,7 +39,8 @@
"tests": ["tpaint"] "tests": ["tpaint"]
}, },
"other-snow-e10s": { "other-snow-e10s": {
"tests": ["tpaint"] "tests": ["tpaint"],
"talos_options": ["--e10s"]
}, },
"other_nol64": { "other_nol64": {
"tests": ["a11yr", "ts_paint", "tpaint", "sessionrestore", "sessionrestore_no_auto_restore"] "tests": ["a11yr", "ts_paint", "tpaint", "sessionrestore", "sessionrestore_no_auto_restore"]
@ -80,7 +81,8 @@
"tests": ["glterrain"] "tests": ["glterrain"]
}, },
"g1-snow-e10s": { "g1-snow-e10s": {
"tests": ["glterrain"] "tests": ["glterrain"],
"talos_options": ["--e10s"]
}, },
"svgr": { "svgr": {
"tests": ["tsvgx", "tsvgr_opacity", "tart", "tscrollx", "cart"] "tests": ["tsvgx", "tsvgr_opacity", "tart", "tscrollx", "cart"]
@ -93,7 +95,8 @@
"tests": ["tsvgx", "tscrollx"] "tests": ["tsvgx", "tscrollx"]
}, },
"svgr-snow-e10s": { "svgr-snow-e10s": {
"tests": ["tsvgx", "tscrollx"] "tests": ["tsvgx", "tscrollx"],
"talos_options": ["--e10s"]
}, },
"tp5o": { "tp5o": {
"tests": ["tp5o"], "tests": ["tp5o"],

Просмотреть файл

@ -186,8 +186,16 @@ class FirefoxBrowser(Browser):
# TODO: Maybe only set this if certutil won't launch? # TODO: Maybe only set this if certutil won't launch?
env = os.environ.copy() env = os.environ.copy()
certutil_dir = os.path.dirname(self.binary) certutil_dir = os.path.dirname(self.binary)
env["LD_LIBRARY_PATH"] = certutil_dir if mozinfo.isMac:
env["PATH"] = os.path.pathsep.join([certutil_dir, env["PATH"]]) env_var = "DYLD_LIBRARY_PATH"
elif mozinfo.isUnix:
env_var = "LD_LIBRARY_PATH"
else:
env_var = "PATH"
env[env_var] = (os.path.pathsep.join([certutil_dir, env[env_var]])
if env_var in env else certutil_dir)
def certutil(*args): def certutil(*args):
cmd = [self.certutil_binary] + list(args) cmd = [self.certutil_binary] + list(args)

Просмотреть файл

@ -28,5 +28,6 @@ skip-if = toolkit == 'android' #TIMED_OUT
[test_videocontrols_audio.html] [test_videocontrols_audio.html]
[test_videocontrols_audio_direction.html] [test_videocontrols_audio_direction.html]
[test_videocontrols_standalone.html] [test_videocontrols_standalone.html]
skip-if = android_version == '10' # bug 1075573
[test_videocontrols_video_direction.html] [test_videocontrols_video_direction.html]
[test_bug898940.html] [test_bug898940.html]

Просмотреть файл

@ -76,7 +76,7 @@ public:
nsresult GetStatus(uint16_t *aStatus); nsresult GetStatus(uint16_t *aStatus);
private: private:
enum LoadStatus MOZ_ENUM_TYPE(uint16_t) { enum LoadStatus : uint16_t {
UNINITIALIZED = 0U, UNINITIALIZED = 0U,
REQUESTED = 1U, REQUESTED = 1U,
RECEIVING = 2U, RECEIVING = 2U,

Просмотреть файл

@ -32,7 +32,7 @@ namespace mozilla {
typedef uint8_t EventClassIDType; typedef uint8_t EventClassIDType;
enum EventClassID MOZ_ENUM_TYPE(EventClassIDType) enum EventClassID : EventClassIDType
{ {
// The event class name will be: // The event class name will be:
// eBasicEventClass for WidgetEvent // eBasicEventClass for WidgetEvent
@ -77,7 +77,7 @@ enum CodeNameIndex
#define NS_DEFINE_COMMAND(aName, aCommandStr) , Command##aName #define NS_DEFINE_COMMAND(aName, aCommandStr) , Command##aName
typedef int8_t CommandInt; typedef int8_t CommandInt;
enum Command MOZ_ENUM_TYPE(CommandInt) enum Command : CommandInt
{ {
CommandDoNothing CommandDoNothing

Просмотреть файл

@ -30,7 +30,8 @@
#include "mozilla/StaticPtr.h" #include "mozilla/StaticPtr.h"
#include "cutils/properties.h" #include "cutils/properties.h"
#include "gfx2DGlue.h" #include "gfx2DGlue.h"
#include "nsWindow.h" #include "gfxPlatform.h"
#include "VsyncSource.h"
#if ANDROID_VERSION >= 17 #if ANDROID_VERSION >= 17
#include "libdisplay/FramebufferSurface.h" #include "libdisplay/FramebufferSurface.h"
@ -227,7 +228,8 @@ HwcComposer2D::Vsync(int aDisplay, nsecs_t aVsyncTimestamp)
LOGE("Non-uniform vsync interval: %lld\n", vsyncInterval); LOGE("Non-uniform vsync interval: %lld\n", vsyncInterval);
} }
mLastVsyncTime = aVsyncTimestamp; mLastVsyncTime = aVsyncTimestamp;
nsWindow::NotifyVsync(vsyncTime);
gfxPlatform::GetPlatform()->GetHardwareVsync()->GetGlobalDisplay().NotifyVsync(vsyncTime);
} }
// Called on the "invalidator" thread (run from HAL). // Called on the "invalidator" thread (run from HAL).

Просмотреть файл

@ -215,21 +215,6 @@ nsWindow::DoDraw(void)
} }
} }
/* static */ void
nsWindow::NotifyVsync(TimeStamp aVsyncTimestamp)
{
if (!gFocusedWindow) {
return;
}
CompositorVsyncDispatcher* vsyncDispatcher = gFocusedWindow->GetCompositorVsyncDispatcher();
// During bootup, there is a delay between when the nsWindow is created
// and when the Compositor is created, but vsync is already turned on
if (vsyncDispatcher) {
vsyncDispatcher->NotifyVsync(aVsyncTimestamp);
}
}
/*static*/ nsEventStatus /*static*/ nsEventStatus
nsWindow::DispatchInputEvent(WidgetGUIEvent& aEvent) nsWindow::DispatchInputEvent(WidgetGUIEvent& aEvent)
{ {

Просмотреть файл

@ -50,7 +50,6 @@ public:
nsWindow(); nsWindow();
virtual ~nsWindow(); virtual ~nsWindow();
static void NotifyVsync(mozilla::TimeStamp aVsyncTimestamp);
static void DoDraw(void); static void DoDraw(void);
static nsEventStatus DispatchInputEvent(mozilla::WidgetGUIEvent& aEvent); static nsEventStatus DispatchInputEvent(mozilla::WidgetGUIEvent& aEvent);
static void DispatchTouchInput(mozilla::MultiTouchInput& aInput); static void DispatchTouchInput(mozilla::MultiTouchInput& aInput);

Просмотреть файл

@ -225,7 +225,7 @@ struct nsIMEUpdatePreference {
typedef uint8_t Notifications; typedef uint8_t Notifications;
enum MOZ_ENUM_TYPE(Notifications) enum : Notifications
{ {
NOTIFY_NOTHING = 0, NOTIFY_NOTHING = 0,
NOTIFY_SELECTION_CHANGE = 1 << 0, NOTIFY_SELECTION_CHANGE = 1 << 0,
@ -519,7 +519,7 @@ struct SizeConstraints {
// Update values in GeckoEditable.java if you make changes here. // Update values in GeckoEditable.java if you make changes here.
// XXX Negative values are used in Android... // XXX Negative values are used in Android...
typedef int8_t IMEMessageType; typedef int8_t IMEMessageType;
enum IMEMessage MOZ_ENUM_TYPE(IMEMessageType) enum IMEMessage : IMEMessageType
{ {
// An editable content is getting focus // An editable content is getting focus
NOTIFY_IME_OF_FOCUS = 1, NOTIFY_IME_OF_FOCUS = 1,

Просмотреть файл

@ -480,7 +480,7 @@ protected:
struct PendingAction MOZ_FINAL struct PendingAction MOZ_FINAL
{ {
enum ActionType MOZ_ENUM_TYPE(uint8_t) enum ActionType : uint8_t
{ {
COMPOSITION_START, COMPOSITION_START,
COMPOSITION_UPDATE, COMPOSITION_UPDATE,
@ -635,7 +635,7 @@ protected:
nsTextStore::Selection& mSelection; nsTextStore::Selection& mSelection;
// The minimum offset of modified part of the text. // The minimum offset of modified part of the text.
enum MOZ_ENUM_TYPE(uint32_t) enum : uint32_t
{ {
NOT_MODIFIED = UINT32_MAX NOT_MODIFIED = UINT32_MAX
}; };

Просмотреть файл

@ -136,7 +136,7 @@
* #define's for compatibility with old code. * #define's for compatibility with old code.
*/ */
#include "ErrorListCxxDefines.h" #include "ErrorListCxxDefines.h"
#elif defined(MOZ_HAVE_CXX11_ENUM_TYPE) #elif defined(__cplusplus)
typedef enum tag_nsresult : uint32_t typedef enum tag_nsresult : uint32_t
{ {
#undef ERROR #undef ERROR
@ -144,21 +144,6 @@
#include "ErrorList.h" #include "ErrorList.h"
#undef ERROR #undef ERROR
} nsresult; } nsresult;
#elif defined(__cplusplus)
/*
* We're C++ in an old compiler lacking enum classes *and* typed enums (likely
* gcc < 4.5.1 as clang/MSVC have long supported one or both), or compiler
* support is unknown. Yet nsresult must have unsigned 32-bit representation.
* So just make it a typedef, and implement the constants with global consts.
*/
typedef uint32_t nsresult;
const nsresult
#undef ERROR
#define ERROR(key, val) key = val
#include "ErrorList.h"
#undef ERROR
;
#else #else
/* /*
* C doesn't have any way to fix the type underlying an enum, and enum * C doesn't have any way to fix the type underlying an enum, and enum

Просмотреть файл

@ -3,8 +3,9 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "TestHarness.h" #include <algorithm>
#include "nsIAsyncInputStream.h"
#include "nsIAsyncOutputStream.h"
#include "nsIThread.h" #include "nsIThread.h"
#include "nsIRunnable.h" #include "nsIRunnable.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
@ -13,76 +14,11 @@
#include "nsCRT.h" #include "nsCRT.h"
#include "nsIPipe.h" // new implementation #include "nsIPipe.h" // new implementation
#include "mozilla/Monitor.h" #include "mozilla/ReentrantMonitor.h"
#include "gtest/gtest.h"
using namespace mozilla; using namespace mozilla;
/** NS_NewPipe2 reimplemented, because it's not exported by XPCOM */
nsresult TP_NewPipe2(nsIAsyncInputStream** input,
nsIAsyncOutputStream** output,
bool nonBlockingInput,
bool nonBlockingOutput,
uint32_t segmentSize,
uint32_t segmentCount,
nsIMemory* segmentAlloc)
{
nsCOMPtr<nsIPipe> pipe = do_CreateInstance("@mozilla.org/pipe;1");
if (!pipe)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = pipe->Init(nonBlockingInput,
nonBlockingOutput,
segmentSize,
segmentCount,
segmentAlloc);
if (NS_FAILED(rv))
return rv;
pipe->GetInputStream(input);
pipe->GetOutputStream(output);
return NS_OK;
}
/** NS_NewPipe reimplemented, because it's not exported by XPCOM */
#define TP_DEFAULT_SEGMENT_SIZE 4096
nsresult TP_NewPipe(nsIInputStream **pipeIn,
nsIOutputStream **pipeOut,
uint32_t segmentSize = 0,
uint32_t maxSize = 0,
bool nonBlockingInput = false,
bool nonBlockingOutput = false,
nsIMemory *segmentAlloc = nullptr);
nsresult TP_NewPipe(nsIInputStream **pipeIn,
nsIOutputStream **pipeOut,
uint32_t segmentSize,
uint32_t maxSize,
bool nonBlockingInput,
bool nonBlockingOutput,
nsIMemory *segmentAlloc)
{
if (segmentSize == 0)
segmentSize = TP_DEFAULT_SEGMENT_SIZE;
// Handle maxSize of UINT32_MAX as a special case
uint32_t segmentCount;
if (maxSize == UINT32_MAX)
segmentCount = UINT32_MAX;
else
segmentCount = maxSize / segmentSize;
nsIAsyncInputStream *in;
nsIAsyncOutputStream *out;
nsresult rv = TP_NewPipe2(&in, &out, nonBlockingInput, nonBlockingOutput,
segmentSize, segmentCount, segmentAlloc);
if (NS_FAILED(rv)) return rv;
*pipeIn = in;
*pipeOut = out;
return NS_OK;
}
#define KEY 0xa7
#define ITERATIONS 33333 #define ITERATIONS 33333
char kTestPattern[] = "My hovercraft is full of eels.\n"; char kTestPattern[] = "My hovercraft is full of eels.\n";
@ -104,11 +40,11 @@ WriteAll(nsIOutputStream *os, const char *buf, uint32_t bufLen, uint32_t *lenWri
return NS_OK; return NS_OK;
} }
class nsReceiver : public nsIRunnable { class nsReceiver MOZ_FINAL : public nsIRunnable {
public: public:
NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_THREADSAFE_ISUPPORTS
NS_IMETHOD Run() { NS_IMETHOD Run() MOZ_OVERRIDE {
nsresult rv; nsresult rv;
char buf[101]; char buf[101];
uint32_t count; uint32_t count;
@ -136,11 +72,14 @@ public:
return rv; return rv;
} }
nsReceiver(nsIInputStream* in) : mIn(in), mCount(0) { explicit nsReceiver(nsIInputStream* in) : mIn(in), mCount(0) {
} }
uint32_t GetBytesRead() { return mCount; } uint32_t GetBytesRead() { return mCount; }
private:
~nsReceiver() {}
protected: protected:
nsCOMPtr<nsIInputStream> mIn; nsCOMPtr<nsIInputStream> mIn;
uint32_t mCount; uint32_t mCount;
@ -151,7 +90,7 @@ NS_IMPL_ISUPPORTS(nsReceiver, nsIRunnable)
nsresult nsresult
TestPipe(nsIInputStream* in, nsIOutputStream* out) TestPipe(nsIInputStream* in, nsIOutputStream* out)
{ {
nsCOMPtr<nsReceiver> receiver = new nsReceiver(in); nsRefPtr<nsReceiver> receiver = new nsReceiver(in);
if (!receiver) if (!receiver)
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
@ -188,18 +127,18 @@ TestPipe(nsIInputStream* in, nsIOutputStream* out)
printf("wrote %d bytes, time = %dms\n", total, printf("wrote %d bytes, time = %dms\n", total,
PR_IntervalToMilliseconds(end - start)); PR_IntervalToMilliseconds(end - start));
NS_ASSERTION(receiver->GetBytesRead() == total, "didn't read everything"); EXPECT_EQ(receiver->GetBytesRead(), total);
return NS_OK; return NS_OK;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
class nsShortReader : public nsIRunnable { class nsShortReader MOZ_FINAL : public nsIRunnable {
public: public:
NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_THREADSAFE_ISUPPORTS
NS_IMETHOD Run() { NS_IMETHOD Run() MOZ_OVERRIDE {
nsresult rv; nsresult rv;
char buf[101]; char buf[101];
uint32_t count; uint32_t count;
@ -230,24 +169,24 @@ public:
return rv; return rv;
} }
nsShortReader(nsIInputStream* in) : mIn(in), mReceived(0) { explicit nsShortReader(nsIInputStream* in) : mIn(in), mReceived(0) {
mMon = new Monitor("nsShortReader"); mMon = new ReentrantMonitor("nsShortReader");
} }
void Received(uint32_t count) { void Received(uint32_t count) {
MonitorAutoEnter mon(*mMon); ReentrantMonitorAutoEnter mon(*mMon);
mReceived += count; mReceived += count;
mon.Notify(); mon.Notify();
} }
uint32_t WaitForReceipt(const uint32_t aWriteCount) { uint32_t WaitForReceipt(const uint32_t aWriteCount) {
MonitorAutoEnter mon(*mMon); ReentrantMonitorAutoEnter mon(*mMon);
uint32_t result = mReceived; uint32_t result = mReceived;
while (result < aWriteCount) { while (result < aWriteCount) {
mon.Wait(); mon.Wait();
NS_ASSERTION(mReceived > result, "failed to receive"); EXPECT_TRUE(mReceived > result);
result = mReceived; result = mReceived;
} }
@ -255,10 +194,13 @@ public:
return result; return result;
} }
private:
~nsShortReader() {}
protected: protected:
nsCOMPtr<nsIInputStream> mIn; nsCOMPtr<nsIInputStream> mIn;
uint32_t mReceived; uint32_t mReceived;
Monitor* mMon; ReentrantMonitor* mMon;
}; };
NS_IMPL_ISUPPORTS(nsShortReader, nsIRunnable) NS_IMPL_ISUPPORTS(nsShortReader, nsIRunnable)
@ -266,7 +208,7 @@ NS_IMPL_ISUPPORTS(nsShortReader, nsIRunnable)
nsresult nsresult
TestShortWrites(nsIInputStream* in, nsIOutputStream* out) TestShortWrites(nsIInputStream* in, nsIOutputStream* out)
{ {
nsCOMPtr<nsShortReader> receiver = new nsShortReader(in); nsRefPtr<nsShortReader> receiver = new nsShortReader(in);
if (!receiver) if (!receiver)
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
@ -282,10 +224,10 @@ TestShortWrites(nsIInputStream* in, nsIOutputStream* out)
char* buf = PR_smprintf("%d %s", i, kTestPattern); char* buf = PR_smprintf("%d %s", i, kTestPattern);
uint32_t len = strlen(buf); uint32_t len = strlen(buf);
len = len * rand() / RAND_MAX; len = len * rand() / RAND_MAX;
len = XPCOM_MAX(1, len); len = std::min(1u, len);
rv = WriteAll(out, buf, len, &writeCount); rv = WriteAll(out, buf, len, &writeCount);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
NS_ASSERTION(writeCount == len, "didn't write enough"); EXPECT_EQ(writeCount, len);
total += writeCount; total += writeCount;
if (gTrace) if (gTrace)
@ -297,9 +239,9 @@ TestShortWrites(nsIInputStream* in, nsIOutputStream* out)
#ifdef DEBUG #ifdef DEBUG
const uint32_t received = const uint32_t received =
#endif
receiver->WaitForReceipt(writeCount); receiver->WaitForReceipt(writeCount);
NS_ASSERTION(received == writeCount, "received wrong amount"); EXPECT_EQ(received, writeCount);
#endif
} }
rv = out->Close(); rv = out->Close();
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
@ -313,12 +255,12 @@ TestShortWrites(nsIInputStream* in, nsIOutputStream* out)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
class nsPump : public nsIRunnable class nsPump MOZ_FINAL : public nsIRunnable
{ {
public: public:
NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_THREADSAFE_ISUPPORTS
NS_IMETHOD Run() { NS_IMETHOD Run() MOZ_OVERRIDE {
nsresult rv; nsresult rv;
uint32_t count; uint32_t count;
while (true) { while (true) {
@ -346,6 +288,9 @@ public:
: mIn(in), mOut(out), mCount(0) { : mIn(in), mOut(out), mCount(0) {
} }
private:
~nsPump() {}
protected: protected:
nsCOMPtr<nsIInputStream> mIn; nsCOMPtr<nsIInputStream> mIn;
nsCOMPtr<nsIOutputStream> mOut; nsCOMPtr<nsIOutputStream> mOut;
@ -354,35 +299,36 @@ protected:
NS_IMPL_ISUPPORTS(nsPump, nsIRunnable) NS_IMPL_ISUPPORTS(nsPump, nsIRunnable)
nsresult TEST(Pipes, ChainedPipes)
TestChainedPipes()
{ {
nsresult rv; nsresult rv;
printf("TestChainedPipes\n"); if (gTrace) {
printf("TestChainedPipes\n");
}
nsCOMPtr<nsIInputStream> in1; nsCOMPtr<nsIInputStream> in1;
nsCOMPtr<nsIOutputStream> out1; nsCOMPtr<nsIOutputStream> out1;
rv = TP_NewPipe(getter_AddRefs(in1), getter_AddRefs(out1), 20, 1999); rv = NS_NewPipe(getter_AddRefs(in1), getter_AddRefs(out1), 20, 1999);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return;
nsCOMPtr<nsIInputStream> in2; nsCOMPtr<nsIInputStream> in2;
nsCOMPtr<nsIOutputStream> out2; nsCOMPtr<nsIOutputStream> out2;
rv = TP_NewPipe(getter_AddRefs(in2), getter_AddRefs(out2), 200, 401); rv = NS_NewPipe(getter_AddRefs(in2), getter_AddRefs(out2), 200, 401);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return;
nsCOMPtr<nsPump> pump = new nsPump(in1, out2); nsRefPtr<nsPump> pump = new nsPump(in1, out2);
if (pump == nullptr) return NS_ERROR_OUT_OF_MEMORY; if (pump == nullptr) return;
nsCOMPtr<nsIThread> thread; nsCOMPtr<nsIThread> thread;
rv = NS_NewThread(getter_AddRefs(thread), pump); rv = NS_NewThread(getter_AddRefs(thread), pump);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return;
nsCOMPtr<nsReceiver> receiver = new nsReceiver(in2); nsRefPtr<nsReceiver> receiver = new nsReceiver(in2);
if (receiver == nullptr) return NS_ERROR_OUT_OF_MEMORY; if (receiver == nullptr) return;
nsCOMPtr<nsIThread> receiverThread; nsCOMPtr<nsIThread> receiverThread;
rv = NS_NewThread(getter_AddRefs(receiverThread), receiver); rv = NS_NewThread(getter_AddRefs(receiverThread), receiver);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return;
uint32_t total = 0; uint32_t total = 0;
for (uint32_t i = 0; i < ITERATIONS; i++) { for (uint32_t i = 0; i < ITERATIONS; i++) {
@ -390,10 +336,10 @@ TestChainedPipes()
char* buf = PR_smprintf("%d %s", i, kTestPattern); char* buf = PR_smprintf("%d %s", i, kTestPattern);
uint32_t len = strlen(buf); uint32_t len = strlen(buf);
len = len * rand() / RAND_MAX; len = len * rand() / RAND_MAX;
len = XPCOM_MAX(1, len); len = std::max(1u, len);
rv = WriteAll(out1, buf, len, &writeCount); rv = WriteAll(out1, buf, len, &writeCount);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return;
NS_ASSERTION(writeCount == len, "didn't write enough"); EXPECT_EQ(writeCount, len);
total += writeCount; total += writeCount;
if (gTrace) if (gTrace)
@ -401,14 +347,14 @@ TestChainedPipes()
PR_smprintf_free(buf); PR_smprintf_free(buf);
} }
printf("wrote total of %d bytes\n", total); if (gTrace) {
printf("wrote total of %d bytes\n", total);
}
rv = out1->Close(); rv = out1->Close();
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return;
thread->Shutdown(); thread->Shutdown();
receiverThread->Shutdown(); receiverThread->Shutdown();
return NS_OK;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -420,50 +366,26 @@ RunTests(uint32_t segSize, uint32_t segCount)
nsCOMPtr<nsIInputStream> in; nsCOMPtr<nsIInputStream> in;
nsCOMPtr<nsIOutputStream> out; nsCOMPtr<nsIOutputStream> out;
uint32_t bufSize = segSize * segCount; uint32_t bufSize = segSize * segCount;
printf("Testing New Pipes: segment size %d buffer size %d\n", segSize, bufSize); if (gTrace) {
printf("Testing New Pipes: segment size %d buffer size %d\n", segSize, bufSize);
printf("Testing long writes...\n"); printf("Testing long writes...\n");
rv = TP_NewPipe(getter_AddRefs(in), getter_AddRefs(out), segSize, bufSize); }
NS_ASSERTION(NS_SUCCEEDED(rv), "TP_NewPipe failed"); rv = NS_NewPipe(getter_AddRefs(in), getter_AddRefs(out), segSize, bufSize);
EXPECT_TRUE(NS_SUCCEEDED(rv));
rv = TestPipe(in, out); rv = TestPipe(in, out);
NS_ASSERTION(NS_SUCCEEDED(rv), "TestPipe failed"); EXPECT_TRUE(NS_SUCCEEDED(rv));
printf("Testing short writes...\n"); if (gTrace) {
rv = TP_NewPipe(getter_AddRefs(in), getter_AddRefs(out), segSize, bufSize); printf("Testing short writes...\n");
NS_ASSERTION(NS_SUCCEEDED(rv), "TP_NewPipe failed"); }
rv = NS_NewPipe(getter_AddRefs(in), getter_AddRefs(out), segSize, bufSize);
EXPECT_TRUE(NS_SUCCEEDED(rv));
rv = TestShortWrites(in, out); rv = TestShortWrites(in, out);
NS_ASSERTION(NS_SUCCEEDED(rv), "TestPipe failed"); EXPECT_TRUE(NS_SUCCEEDED(rv));
} }
//////////////////////////////////////////////////////////////////////////////// TEST(Pipes, Main)
#if 0
extern void
TestSegmentedBuffer();
#endif
int
main(int argc, char* argv[])
{ {
nsresult rv;
nsCOMPtr<nsIServiceManager> servMgr;
rv = NS_InitXPCOM2(getter_AddRefs(servMgr), nullptr, nullptr);
if (NS_FAILED(rv)) return rv;
if (argc > 1 && nsCRT::strcmp(argv[1], "-trace") == 0)
gTrace = true;
rv = TestChainedPipes();
NS_ASSERTION(NS_SUCCEEDED(rv), "TestChainedPipes failed");
RunTests(16, 1); RunTests(16, 1);
RunTests(4096, 16); RunTests(4096, 16);
servMgr = 0;
rv = NS_ShutdownXPCOM(nullptr);
NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed");
return 0;
} }
////////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -7,6 +7,7 @@
#include "nsTPriorityQueue.h" #include "nsTPriorityQueue.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "gtest/gtest.h"
template<class T, class Compare> template<class T, class Compare>
void void
@ -16,32 +17,13 @@ CheckPopSequence(const nsTPriorityQueue<T, Compare>& aQueue,
nsTPriorityQueue<T, Compare> copy(aQueue); nsTPriorityQueue<T, Compare> copy(aQueue);
for (uint32_t i = 0; i < aSequenceLength; i++) { for (uint32_t i = 0; i < aSequenceLength; i++) {
if (copy.IsEmpty()) { EXPECT_FALSE(copy.IsEmpty());
printf("Number of elements in the queue is too short by %d.\n",
aSequenceLength - i);
exit(-1);
}
T pop = copy.Pop(); T pop = copy.Pop();
if (pop != aExpectedSequence[i]) { EXPECT_EQ(pop, aExpectedSequence[i]);
printf("Unexpected value in pop sequence at position %d\n", i);
printf(" Sequence:");
for (size_t j = 0; j < aSequenceLength; j++) {
printf(" %d", aExpectedSequence[j]);
if (j == i) {
printf("**");
}
}
printf("\n ** Got %d instead\n", pop);
exit(-1);
}
} }
if (!copy.IsEmpty()) { EXPECT_TRUE(copy.IsEmpty());
printf("Number of elements in the queue is too long by %d.\n",
copy.Length());
exit(-1);
}
} }
template<class A> template<class A>
@ -52,11 +34,11 @@ public:
} }
}; };
int main() TEST(PriorityQueue, Main)
{ {
nsTPriorityQueue<int> queue; nsTPriorityQueue<int> queue;
NS_ABORT_IF_FALSE(queue.IsEmpty(), "Queue not initially empty"); EXPECT_TRUE(queue.IsEmpty());
queue.Push(8); queue.Push(8);
queue.Push(6); queue.Push(6);
@ -64,9 +46,9 @@ int main()
queue.Push(2); queue.Push(2);
queue.Push(10); queue.Push(10);
queue.Push(6); queue.Push(6);
NS_ABORT_IF_FALSE(queue.Top() == 2, "Unexpected queue top"); EXPECT_EQ(queue.Top(), 2);
NS_ABORT_IF_FALSE(queue.Length() == 6, "Unexpected queue length"); EXPECT_EQ(queue.Length(), 6u);
NS_ABORT_IF_FALSE(!queue.IsEmpty(), "Queue empty when populated"); EXPECT_FALSE(queue.IsEmpty());
int expected[] = { 2, 4, 6, 6, 8, 10 }; int expected[] = { 2, 4, 6, 6, 8, 10 };
CheckPopSequence(queue, expected, sizeof(expected) / sizeof(expected[0])); CheckPopSequence(queue, expected, sizeof(expected) / sizeof(expected[0]));
@ -77,7 +59,7 @@ int main()
CheckPopSequence(queue2, expected, sizeof(expected) / sizeof(expected[0])); CheckPopSequence(queue2, expected, sizeof(expected) / sizeof(expected[0]));
queue.Clear(); queue.Clear();
NS_ABORT_IF_FALSE(queue.IsEmpty(), "Queue not emptied by Clear"); EXPECT_TRUE(queue.IsEmpty());
// try same sequence with a max heap // try same sequence with a max heap
nsTPriorityQueue<int, MaxCompare<int> > max_queue; nsTPriorityQueue<int, MaxCompare<int> > max_queue;
@ -87,10 +69,8 @@ int main()
max_queue.Push(2); max_queue.Push(2);
max_queue.Push(10); max_queue.Push(10);
max_queue.Push(6); max_queue.Push(6);
NS_ABORT_IF_FALSE(max_queue.Top() == 10, "Unexpected queue top for max heap"); EXPECT_EQ(max_queue.Top(), 10);
int expected_max[] = { 10, 8, 6, 6, 4, 2 }; int expected_max[] = { 10, 8, 6, 6, 4, 2 };
CheckPopSequence(max_queue, expected_max, CheckPopSequence(max_queue, expected_max,
sizeof(expected_max) / sizeof(expected_max[0])); sizeof(expected_max) / sizeof(expected_max[0]));
return 0;
} }

Просмотреть файл

@ -7,8 +7,9 @@
#include "nsIInputStream.h" #include "nsIInputStream.h"
#include "nsIOutputStream.h" #include "nsIOutputStream.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "gtest/gtest.h"
int main() TEST(TestStorageStreams, Main)
{ {
char kData[4096]; char kData[4096];
memset(kData, 0, sizeof(kData)); memset(kData, 0, sizeof(kData));
@ -17,94 +18,75 @@ int main()
nsCOMPtr<nsIStorageStream> stor; nsCOMPtr<nsIStorageStream> stor;
rv = NS_NewStorageStream(4096, UINT32_MAX, getter_AddRefs(stor)); rv = NS_NewStorageStream(4096, UINT32_MAX, getter_AddRefs(stor));
if (NS_FAILED(rv)) EXPECT_TRUE(NS_SUCCEEDED(rv));
return -1;
nsCOMPtr<nsIOutputStream> out; nsCOMPtr<nsIOutputStream> out;
rv = stor->GetOutputStream(0, getter_AddRefs(out)); rv = stor->GetOutputStream(0, getter_AddRefs(out));
if (NS_FAILED(rv)) EXPECT_TRUE(NS_SUCCEEDED(rv));
return -1;
uint32_t n; uint32_t n;
rv = out->Write(kData, sizeof(kData), &n); rv = out->Write(kData, sizeof(kData), &n);
if (NS_FAILED(rv)) EXPECT_TRUE(NS_SUCCEEDED(rv));
return -1;
rv = out->Write(kData, sizeof(kData), &n); rv = out->Write(kData, sizeof(kData), &n);
if (NS_FAILED(rv)) EXPECT_TRUE(NS_SUCCEEDED(rv));
return -1;
rv = out->Close(); rv = out->Close();
if (NS_FAILED(rv)) EXPECT_TRUE(NS_SUCCEEDED(rv));
return -1;
out = nullptr; out = nullptr;
nsCOMPtr<nsIInputStream> in; nsCOMPtr<nsIInputStream> in;
rv = stor->NewInputStream(0, getter_AddRefs(in)); rv = stor->NewInputStream(0, getter_AddRefs(in));
if (NS_FAILED(rv)) EXPECT_TRUE(NS_SUCCEEDED(rv));
return -1;
char buf[4096]; char buf[4096];
// consume contents of input stream // consume contents of input stream
do { do {
rv = in->Read(buf, sizeof(buf), &n); rv = in->Read(buf, sizeof(buf), &n);
if (NS_FAILED(rv)) EXPECT_TRUE(NS_SUCCEEDED(rv));
return -1;
} while (n != 0); } while (n != 0);
rv = in->Close(); rv = in->Close();
if (NS_FAILED(rv)) EXPECT_TRUE(NS_SUCCEEDED(rv));
return -1;
in = nullptr; in = nullptr;
// now, write 3 more full 4k segments + 11 bytes, starting at 8192 // now, write 3 more full 4k segments + 11 bytes, starting at 8192
// total written equals 20491 bytes // total written equals 20491 bytes
rv = stor->GetOutputStream(8192, getter_AddRefs(out)); rv = stor->GetOutputStream(8192, getter_AddRefs(out));
if (NS_FAILED(rv)) EXPECT_TRUE(NS_SUCCEEDED(rv));
return -1;
rv = out->Write(kData, sizeof(kData), &n); rv = out->Write(kData, sizeof(kData), &n);
if (NS_FAILED(rv)) EXPECT_TRUE(NS_SUCCEEDED(rv));
return -1;
rv = out->Write(kData, sizeof(kData), &n); rv = out->Write(kData, sizeof(kData), &n);
if (NS_FAILED(rv)) EXPECT_TRUE(NS_SUCCEEDED(rv));
return -1;
rv = out->Write(kData, sizeof(kData), &n); rv = out->Write(kData, sizeof(kData), &n);
if (NS_FAILED(rv)) EXPECT_TRUE(NS_SUCCEEDED(rv));
return -1;
rv = out->Write(kData, 11, &n); rv = out->Write(kData, 11, &n);
if (NS_FAILED(rv)) EXPECT_TRUE(NS_SUCCEEDED(rv));
return -1;
rv = out->Close(); rv = out->Close();
if (NS_FAILED(rv)) EXPECT_TRUE(NS_SUCCEEDED(rv));
return -1;
out = nullptr; out = nullptr;
// now, read all // now, read all
rv = stor->NewInputStream(0, getter_AddRefs(in)); rv = stor->NewInputStream(0, getter_AddRefs(in));
if (NS_FAILED(rv)) EXPECT_TRUE(NS_SUCCEEDED(rv));
return -1;
// consume contents of input stream // consume contents of input stream
do { do {
rv = in->Read(buf, sizeof(buf), &n); rv = in->Read(buf, sizeof(buf), &n);
if (NS_FAILED(rv)) EXPECT_TRUE(NS_SUCCEEDED(rv));
return -1;
} while (n != 0); } while (n != 0);
rv = in->Close(); rv = in->Close();
if (NS_FAILED(rv)) EXPECT_TRUE(NS_SUCCEEDED(rv));
return -1;
in = nullptr; in = nullptr;
return 0;
} }

Просмотреть файл

@ -8,7 +8,10 @@ UNIFIED_SOURCES += [
'TestCRT.cpp', 'TestCRT.cpp',
'TestEncoding.cpp', 'TestEncoding.cpp',
'TestExpirationTracker.cpp', 'TestExpirationTracker.cpp',
'TestPipes.cpp',
'TestPriorityQueue.cpp',
'TestSnappyStreams.cpp', 'TestSnappyStreams.cpp',
'TestStorageStream.cpp',
'TestStrings.cpp', 'TestStrings.cpp',
] ]

Просмотреть файл

@ -80,9 +80,6 @@ if CONFIG['MOZ_MEMORY']:
# XXX Make these tests work in libxul builds. # XXX Make these tests work in libxul builds.
#CPP_UNIT_TESTS += [ #CPP_UNIT_TESTS += [
# 'TestPipes',
# 'TestPriorityQueue',
# 'TestStorageStream',
# 'TestSynchronization', # 'TestSynchronization',
# 'TestTArray', # 'TestTArray',
# 'TestThreadPool', # 'TestThreadPool',