Merge mozilla-inbound to mozilla-central. a=merge

This commit is contained in:
Dorel Luca 2018-08-01 12:51:56 +03:00
commit d0a0ae30d5
104 changed files with 3295 additions and 2783 deletions

View File

@ -197,7 +197,7 @@ def interfaces(iface):
interfaces = []
while iface.base:
interfaces.append(iface)
iface = iface.idl.getName(iface.base, iface.location)
iface = iface.idl.getName(xpidl.TypeId(iface.base), iface.location)
interfaces.append(iface)
interfaces.reverse()
return interfaces

View File

@ -46,6 +46,12 @@ let whitelist = [
{sourceName: /(?:res|gre-resources)\/forms\.css$/i,
errorMessage: /Unknown property.*overflow-clip-box/i,
isFromDevTools: false},
// The '-moz-menulist-button' value is only supported in chrome and UA sheets
// but forms.css is loaded as a document sheet by this test.
// Maybe bug 1261237 will fix this?
{sourceName: /(?:res|gre-resources)\/forms\.css$/i,
errorMessage: /Error in parsing value for \u2018-moz-appearance\u2019/iu,
isFromDevTools: false},
// These variables are declared somewhere else, and error when we load the
// files directly. They're all marked intermittent because their appearance
// in the error console seems to not be consistent.

View File

@ -66,30 +66,6 @@ function promiseNewLocationAndHistoryEntryReplaced(browser, snippet) {
});
}
function promiseHistoryEntryReplacedNonRemote(browser) {
let {listeners} = promiseHistoryEntryReplacedNonRemote;
return new Promise(resolve => {
let shistory = browser.webNavigation.sessionHistory.legacySHistory;
let listener = {
OnHistoryReplaceEntry() {
shistory.removeSHistoryListener(this);
executeSoon(resolve);
},
QueryInterface: ChromeUtils.generateQI([
Ci.nsISHistoryListener,
Ci.nsISupportsWeakReference
])
};
shistory.addSHistoryListener(listener);
listeners.set(browser, listener);
});
}
promiseHistoryEntryReplacedNonRemote.listeners = new WeakMap();
add_task(async function dont_save_empty_tabs() {
let {tab, r} = await createTabWithRandomValue("about:blank");
@ -168,8 +144,10 @@ add_task(async function save_worthy_tabs_nonremote_final() {
await BrowserTestUtils.loadURI(browser, "about:robots");
ok(!browser.isRemoteBrowser, "browser is not remote anymore");
// Wait until the new entry replaces about:blank.
await promiseHistoryEntryReplacedNonRemote(browser);
// Switching remoteness caused a SessionRestore to begin, moving over history
// and initiating the load in the target process. Wait for the full restore
// and load to complete before trying to close the tab.
await promiseTabRestored(tab);
// Remove the tab before the update arrives.
let promise = promiseRemoveTabAndSessionState(tab);

View File

@ -196,6 +196,7 @@ exports.CSS_PROPERTIES = {
"-moz-mac-vibrancy-light",
"-moz-mac-vibrant-titlebar-dark",
"-moz-mac-vibrant-titlebar-light",
"-moz-menulist-button",
"-moz-win-borderless-glass",
"-moz-win-browsertabbar-toolbox",
"-moz-win-communications-toolbox",

View File

@ -60,10 +60,12 @@ function windowLoaded()
ok(succeeded, "Waiting for error page succeeded");
/* 3. now, while we are on the error page, navigate back */
try {
SpecialPowers.wrap(w).back();
// We need the SpecialPowers bit, because this is a cross-origin window
// and we normally can't touch .history on those.
SpecialPowers.wrap(w).history.back();
}
catch(ex) {
ok(false, "w.back() threw " + ex);
ok(false, "w.history.back() threw " + ex);
}
pollForPage(false, function(succeeded) {

View File

@ -92,7 +92,7 @@ function* test()
// Step 5 - Go back. This should result in another onload (because the file is
// not in bfcache) and should be the fourth time we've requested the sjs file.
checkPopupLoadCount();
SpecialPowers.wrap(popup).back();
popup.history.back();
yield undefined;
// This is the check which was failing before we fixed the bug.
@ -111,7 +111,7 @@ function* test()
popup.location = 'file_bug669671.sjs?navigated-2';
yield undefined;
checkPopupLoadCount();
SpecialPowers.wrap(popup).back();
popup.history.back();
yield undefined;
checkPopupLoadCount();
popup.close();
@ -125,7 +125,7 @@ function* test()
popup.location = 'file_bug669671.sjs?navigated-3';
yield undefined;
checkPopupLoadCount();
SpecialPowers.wrap(popup).back();
popup.history.back();
yield undefined;
is(popup.document.body.innerHTML, initialCount + '',
'Load count (should be cached)');

View File

@ -926,43 +926,33 @@ nsGlobalWindowInner::nsGlobalWindowInner(nsGlobalWindowOuter *aOuterWindow)
// Initialize the PRCList (this).
PR_INIT_CLIST(this);
if (aOuterWindow) {
// |this| is an inner window, add this inner window to the outer
// window list of inners.
PR_INSERT_AFTER(this, aOuterWindow);
// add this inner window to the outer window list of inners.
PR_INSERT_AFTER(this, aOuterWindow);
mTimeoutManager =
MakeUnique<mozilla::dom::TimeoutManager>(*nsGlobalWindowInner::Cast(AsInner()));
mTimeoutManager = MakeUnique<dom::TimeoutManager>(*this);
mObserver = new nsGlobalWindowObserver(this);
if (mObserver) {
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
if (os) {
// Watch for online/offline status changes so we can fire events. Use
// a strong reference.
os->AddObserver(mObserver, NS_IOSERVICE_OFFLINE_STATUS_TOPIC,
false);
mObserver = new nsGlobalWindowObserver(this);
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
if (os) {
// Watch for online/offline status changes so we can fire events. Use
// a strong reference.
os->AddObserver(mObserver, NS_IOSERVICE_OFFLINE_STATUS_TOPIC,
false);
os->AddObserver(mObserver, MEMORY_PRESSURE_OBSERVER_TOPIC, false);
os->AddObserver(mObserver, MEMORY_PRESSURE_OBSERVER_TOPIC, false);
if (aOuterWindow->IsTopLevelWindow()) {
os->AddObserver(mObserver, "clear-site-data-reload-needed", false);
}
}
Preferences::AddStrongObserver(mObserver, "intl.accept_languages");
// Watch for storage notifications so we can fire storage events.
RefPtr<StorageNotifierService> sns =
StorageNotifierService::GetOrCreate();
if (sns) {
sns->Register(mObserver);
}
if (aOuterWindow->IsTopLevelWindow()) {
os->AddObserver(mObserver, "clear-site-data-reload-needed", false);
}
} else {
// |this| is an outer window. Outer windows start out frozen and
// remain frozen until they get an inner window.
MOZ_ASSERT(IsFrozen());
}
Preferences::AddStrongObserver(mObserver, "intl.accept_languages");
// Watch for storage notifications so we can fire storage events.
RefPtr<StorageNotifierService> sns =
StorageNotifierService::GetOrCreate();
if (sns) {
sns->Register(mObserver);
}
if (XRE_IsContentProcess()) {
@ -2018,18 +2008,6 @@ nsGlobalWindowInner::DialogsAreBeingAbused()
return false;
}
void
nsGlobalWindowInner::DisableDialogs()
{
FORWARD_TO_OUTER_VOID(DisableDialogs, ());
}
void
nsGlobalWindowInner::EnableDialogs()
{
FORWARD_TO_OUTER_VOID(EnableDialogs, ());
}
nsresult
nsGlobalWindowInner::PostHandleEvent(EventChainPostVisitor& aVisitor)
{
@ -2312,18 +2290,6 @@ nsPIDOMWindowInner::Resume()
nsGlobalWindowInner::Cast(this)->Resume();
}
void
nsPIDOMWindowInner::Freeze()
{
nsGlobalWindowInner::Cast(this)->Freeze();
}
void
nsPIDOMWindowInner::Thaw()
{
nsGlobalWindowInner::Cast(this)->Thaw();
}
void
nsPIDOMWindowInner::SyncStateFromParentWindow()
{
@ -2348,12 +2314,6 @@ nsPIDOMWindowInner::GetController() const
return nsGlobalWindowInner::Cast(this)->GetController();
}
RefPtr<mozilla::dom::ServiceWorker>
nsPIDOMWindowInner::GetOrCreateServiceWorker(const mozilla::dom::ServiceWorkerDescriptor& aDescriptor)
{
return nsGlobalWindowInner::Cast(this)->GetOrCreateServiceWorker(aDescriptor);
}
void
nsPIDOMWindowInner::NoteCalledRegisterForServiceWorkerScope(const nsACString& aScope)
{
@ -2752,16 +2712,6 @@ nsGlobalWindowInner::GetScriptableParent()
FORWARD_TO_OUTER(GetScriptableParent, (), nullptr);
}
/**
* Behavies identically to GetScriptableParent extept that it returns null
* if GetScriptableParent would return this window.
*/
nsPIDOMWindowOuter*
nsGlobalWindowInner::GetScriptableParentOrNull()
{
FORWARD_TO_OUTER(GetScriptableParentOrNull, (), nullptr);
}
/**
* GetScriptableTop is called when script reads window.top.
*
@ -3815,24 +3765,6 @@ nsGlobalWindowInner::Blur(ErrorResult& aError)
FORWARD_TO_OUTER_OR_THROW(BlurOuter, (), aError, );
}
void
nsGlobalWindowInner::Back(ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(BackOuter, (aError), aError, );
}
void
nsGlobalWindowInner::Forward(ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(ForwardOuter, (aError), aError, );
}
void
nsGlobalWindowInner::Home(nsIPrincipal& aSubjectPrincipal, ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(HomeOuter, (aSubjectPrincipal, aError), aError, );
}
void
nsGlobalWindowInner::Stop(ErrorResult& aError)
{
@ -4191,12 +4123,6 @@ nsGlobalWindowInner::Close()
FORWARD_TO_OUTER(Close, (), NS_ERROR_UNEXPECTED);
}
void
nsGlobalWindowInner::ReallyCloseWindow()
{
FORWARD_TO_OUTER_VOID(ReallyCloseWindow, ());
}
bool
nsGlobalWindowInner::IsInModalState()
{
@ -4886,26 +4812,6 @@ nsGlobalWindowInner::DispatchSyncPopState()
return err.StealNSResult();
}
// Find an nsICanvasFrame under aFrame. Only search the principal
// child lists. aFrame must be non-null.
static nsCanvasFrame*
FindCanvasFrame(nsIFrame* aFrame)
{
nsCanvasFrame* canvasFrame = do_QueryFrame(aFrame);
if (canvasFrame) {
return canvasFrame;
}
for (nsIFrame* kid : aFrame->PrincipalChildList()) {
canvasFrame = FindCanvasFrame(kid);
if (canvasFrame) {
return canvasFrame;
}
}
return nullptr;
}
//-------------------------------------------------------
// Tells the HTMLFrame/CanvasFrame that is now has focus
void
@ -4927,26 +4833,19 @@ nsGlobalWindowInner::UpdateCanvasFocus(bool aFocusChanged, nsIContent* aNewConte
Element *rootElement = mDoc->GetRootElement();
if (rootElement) {
if ((mHasFocus || aFocusChanged) &&
(mFocusedElement == rootElement || aNewContent == rootElement)) {
nsIFrame* frame = rootElement->GetPrimaryFrame();
if (frame) {
frame = frame->GetParent();
nsCanvasFrame* canvasFrame = do_QueryFrame(frame);
if (canvasFrame) {
canvasFrame->SetHasFocus(mHasFocus && rootElement == aNewContent);
}
}
if ((mHasFocus || aFocusChanged) &&
(mFocusedElement == rootElement || aNewContent == rootElement)) {
nsCanvasFrame* canvasFrame = presShell->GetCanvasFrame();
if (canvasFrame) {
canvasFrame->SetHasFocus(mHasFocus && rootElement == aNewContent);
}
}
} else {
// Look for the frame the hard way
nsIFrame* frame = presShell->GetRootFrame();
if (frame) {
nsCanvasFrame* canvasFrame = FindCanvasFrame(frame);
if (canvasFrame) {
canvasFrame->SetHasFocus(false);
}
}
// XXXbz I would expect that there is never a canvasFrame in this case...
nsCanvasFrame* canvasFrame = presShell->GetCanvasFrame();
if (canvasFrame) {
canvasFrame->SetHasFocus(false);
}
}
}
@ -8082,6 +7981,10 @@ nsPIDOMWindowInner::MaybeCreateDoc()
void
nsGlobalWindowInner::PropagateClearSiteDataReload(const nsACString& aOrigin)
{
if (!IsCurrentInnerWindow()) {
return;
}
nsIPrincipal* principal = GetPrincipal();
if (!principal) {
return;

View File

@ -275,9 +275,6 @@ public:
static already_AddRefed<nsGlobalWindowInner>
Create(nsGlobalWindowOuter* aOuter, bool aIsChrome);
// callback for close event
void ReallyCloseWindow();
// nsISupports
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@ -352,6 +349,14 @@ public:
void Suspend();
void Resume();
virtual bool IsSuspended() const override;
// Calling Freeze() on a window will automatically Suspend() it. In
// addition, the window and its children are further treated as no longer
// suitable for interaction with the user. For example, it may be marked
// non-visible, cannot be focused, etc. All worker threads are also frozen
// bringing them to a complete stop. A window can have Freeze() called
// multiple times and will only thaw after a matching number of Thaw()
// calls.
void Freeze();
void Thaw();
virtual bool IsFrozen() const override;
@ -449,14 +454,6 @@ public:
// Inner windows only.
bool DialogsAreBeingAbused();
// These functions are used for controlling and determining whether dialogs
// (alert, prompt, confirm) are currently allowed in this window. If you want
// to temporarily disable dialogs, please use TemporarilyDisableDialogs, not
// EnableDialogs/DisableDialogs, because correctly determining whether to
// re-enable dialogs is actually quite difficult.
void EnableDialogs();
void DisableDialogs();
nsIScriptContext *GetContextInternal();
nsGlobalWindowOuter *GetOuterWindowInternal() const;
@ -676,7 +673,6 @@ public:
void GetEvent(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval);
already_AddRefed<nsPIDOMWindowOuter> GetParent(mozilla::ErrorResult& aError);
nsPIDOMWindowOuter* GetScriptableParent() override;
nsPIDOMWindowOuter* GetScriptableParentOrNull() override;
mozilla::dom::Element*
GetFrameElement(nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aError);
@ -887,9 +883,6 @@ public:
bool GetFullScreen(mozilla::ErrorResult& aError);
bool GetFullScreen() override;
void SetFullScreen(bool aFullScreen, mozilla::ErrorResult& aError);
void Back(mozilla::ErrorResult& aError);
void Forward(mozilla::ErrorResult& aError);
void Home(nsIPrincipal& aSubjectPrincipal, mozilla::ErrorResult& aError);
bool Find(const nsAString& aString, bool aCaseSensitive, bool aBackwards,
bool aWrapAround, bool aWholeWord, bool aSearchInFrames,
bool aShowDialog, mozilla::ErrorResult& aError);

View File

@ -306,9 +306,6 @@ using mozilla::TimeStamp;
return GetCurrentInnerWindowInternal()->method args; \
PR_END_MACRO
#define DEFAULT_HOME_PAGE "www.mozilla.org"
#define PREF_BROWSER_STARTUP_HOMEPAGE "browser.startup.homepage"
static LazyLogModule gDOMLeakPRLogOuter("DOMLeakOuter");
static int32_t gOpenPopupSpamCount = 0;
@ -854,13 +851,6 @@ nsGlobalWindowOuter::nsGlobalWindowOuter()
// remain frozen until they get an inner window.
MOZ_ASSERT(IsFrozen());
if (XRE_IsContentProcess()) {
nsCOMPtr<nsIDocShell> docShell = GetDocShell();
if (docShell) {
mTabChild = docShell->GetTabChild();
}
}
// We could have failed the first time through trying
// to create the entropy collector, so we should
// try to get one until we succeed.
@ -1146,7 +1136,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindowOuter)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocalStorage)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSuspendedDoc)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentPrincipal)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTabChild)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDoc)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleService)
@ -1174,7 +1163,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindowOuter)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocalStorage)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSuspendedDoc)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentPrincipal)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTabChild)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDoc)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleService)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleObservers)
@ -1256,12 +1244,6 @@ nsGlobalWindowOuter::GetGlobalJSObject()
return FastGetGlobalJSObject();
}
void
nsGlobalWindowOuter::TraceGlobalJSObject(JSTracer* aTrc)
{
TraceWrapper(aTrc, "active window global");
}
bool
nsGlobalWindowOuter::WouldReuseInnerWindow(nsIDocument* aNewDocument)
{
@ -2183,7 +2165,6 @@ nsGlobalWindowOuter::DetachFromDocShell()
// Remember the document's principal and URI.
mDocumentPrincipal = mDoc->NodePrincipal();
mDocumentURI = mDoc->GetDocumentURI();
mDocBaseURI = mDoc->GetDocBaseURI();
// Release our document reference
DropOuterWindowDocs();
@ -4869,81 +4850,6 @@ nsGlobalWindowOuter::BlurOuter()
}
}
void
nsGlobalWindowOuter::BackOuter(ErrorResult& aError)
{
nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mDocShell));
if (!webNav) {
aError.Throw(NS_ERROR_FAILURE);
return;
}
aError = webNav->GoBack();
}
void
nsGlobalWindowOuter::ForwardOuter(ErrorResult& aError)
{
nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mDocShell));
if (!webNav) {
aError.Throw(NS_ERROR_FAILURE);
return;
}
aError = webNav->GoForward();
}
void
nsGlobalWindowOuter::HomeOuter(nsIPrincipal& aSubjectPrincipal, ErrorResult& aError)
{
if (!mDocShell) {
return;
}
nsAutoString homeURL;
Preferences::GetLocalizedString(PREF_BROWSER_STARTUP_HOMEPAGE, homeURL);
if (homeURL.IsEmpty()) {
// if all else fails, use this
#ifdef DEBUG_seth
printf("all else failed. using %s as the home page\n", DEFAULT_HOME_PAGE);
#endif
homeURL = NS_LITERAL_STRING(DEFAULT_HOME_PAGE);
}
#ifdef MOZ_PHOENIX
{
// Firefox lets the user specify multiple home pages to open in
// individual tabs by separating them with '|'. Since we don't
// have the machinery in place to easily open new tabs from here,
// simply truncate the homeURL at the first '|' character to
// prevent any possibilities of leaking the users list of home
// pages to the first home page.
//
// Once bug https://bugzilla.mozilla.org/show_bug.cgi?id=221445 is
// fixed we can revisit this.
int32_t firstPipe = homeURL.FindChar('|');
if (firstPipe > 0) {
homeURL.Truncate(firstPipe);
}
}
#endif
nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mDocShell));
if (!webNav) {
aError.Throw(NS_ERROR_FAILURE);
return;
}
aError = webNav->LoadURI(homeURL.get(),
nsIWebNavigation::LOAD_FLAGS_NONE,
nullptr,
nullptr,
nullptr,
&aSubjectPrincipal);
}
void
nsGlobalWindowOuter::StopOuter(ErrorResult& aError)
{
@ -6655,12 +6561,6 @@ nsGlobalWindowOuter::SetIsBackgroundInternal(bool aIsBackground)
mIsBackground = aIsBackground;
}
void
nsGlobalWindowOuter::MaybeUpdateTouchState()
{
FORWARD_TO_INNER_VOID(MaybeUpdateTouchState, ());
}
void
nsGlobalWindowOuter::SetChromeEventHandler(EventTarget* aChromeEventHandler)
{
@ -7244,13 +7144,6 @@ nsGlobalWindowOuter::SecurityCheckURL(const char *aURL, nsIURI** aURI)
return NS_OK;
}
bool
nsGlobalWindowOuter::IsPrivateBrowsing()
{
nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(GetDocShell());
return loadContext && loadContext->UsePrivateBrowsing();
}
void
nsGlobalWindowOuter::FlushPendingNotifications(FlushType aType)
{
@ -7336,29 +7229,12 @@ nsGlobalWindowOuter::RestoreWindowState(nsISupports *aState)
return NS_OK;
}
// XXX(nika): Can we remove these?
void
nsGlobalWindowOuter::EventListenerAdded(nsAtom* aType)
{
}
void
nsGlobalWindowOuter::EventListenerRemoved(nsAtom* aType)
{
}
void
nsGlobalWindowOuter::AddSizeOfIncludingThis(nsWindowSizes& aWindowSizes) const
{
aWindowSizes.mDOMOtherSize += aWindowSizes.mState.mMallocSizeOf(this);
}
bool
nsGlobalWindowOuter::UpdateVRDisplays(nsTArray<RefPtr<mozilla::dom::VRDisplay>>& aDevices)
{
FORWARD_TO_INNER(UpdateVRDisplays, (aDevices), false);
}
uint32_t
nsGlobalWindowOuter::GetAutoActivateVRDisplayID()
{
@ -7738,12 +7614,6 @@ nsPIDOMWindowOuter::GetDocumentURI() const
}
nsIURI*
nsPIDOMWindowOuter::GetDocBaseURI() const
{
return mDoc ? mDoc->GetDocBaseURI() : mDocBaseURI.get();
}
void
nsPIDOMWindowOuter::MaybeCreateDoc()
{

View File

@ -245,8 +245,6 @@ public:
return GetWrapperPreserveColor();
}
void TraceGlobalJSObject(JSTracer* aTrc);
virtual nsresult EnsureScriptEnvironment() override;
virtual nsIScriptContext *GetScriptContext() override;
@ -345,8 +343,6 @@ public:
virtual bool CanClose() override;
virtual void ForceClose() override;
virtual void MaybeUpdateTouchState() override;
// Outer windows only.
virtual bool DispatchCustomEvent(const nsAString& aEventName) override;
bool DispatchResizeEvent(const mozilla::CSSIntSize& aSize);
@ -363,11 +359,6 @@ public:
nsIWidget* aWidget, nsIScreen* aScreen);
bool FullScreen() const;
using EventTarget::EventListenerAdded;
virtual void EventListenerAdded(nsAtom* aType) override;
using EventTarget::EventListenerRemoved;
virtual void EventListenerRemoved(nsAtom* aType) override;
// nsIInterfaceRequestor
NS_DECL_NSIINTERFACEREQUESTOR
@ -506,9 +497,6 @@ public:
mAllowScriptsToClose = true;
}
// Update the VR displays for this window
bool UpdateVRDisplays(nsTArray<RefPtr<mozilla::dom::VRDisplay>>& aDisplays);
// Outer windows only.
uint32_t GetAutoActivateVRDisplayID();
// Outer windows only.
@ -674,9 +662,6 @@ public:
bool GetFullScreen() override;
void SetFullScreenOuter(bool aFullScreen, mozilla::ErrorResult& aError);
nsresult SetFullScreen(bool aFullScreen) override;
void BackOuter(mozilla::ErrorResult& aError);
void ForwardOuter(mozilla::ErrorResult& aError);
void HomeOuter(nsIPrincipal& aSubjectPrincipal, mozilla::ErrorResult& aError);
bool FindOuter(const nsAString& aString, bool aCaseSensitive, bool aBackwards,
bool aWrapAround, bool aWholeWord, bool aSearchInFrames,
bool aShowDialog, mozilla::ErrorResult& aError);
@ -915,7 +900,6 @@ public:
already_AddRefed<nsIBaseWindow> GetTreeOwnerWindow();
already_AddRefed<nsIWebBrowserChrome> GetWebBrowserChrome();
nsresult SecurityCheckURL(const char *aURL, nsIURI** aURI);
bool IsPrivateBrowsing();
bool PopupWhitelisted();
PopupControlState RevisePopupAbuseLevel(PopupControlState);
@ -1118,8 +1102,6 @@ protected:
RefPtr<mozilla::dom::Storage> mLocalStorage;
nsCOMPtr<nsIPrincipal> mDocumentPrincipal;
// mTabChild is only ever populated in the content process.
nsCOMPtr<nsITabChild> mTabChild;
uint32_t mSerial;

View File

@ -280,16 +280,6 @@ public:
void Suspend();
void Resume();
// Calling Freeze() on a window will automatically Suspend() it. In
// addition, the window and its children are further treated as no longer
// suitable for interaction with the user. For example, it may be marked
// non-visible, cannot be focused, etc. All worker threads are also frozen
// bringing them to a complete stop. A window can have Freeze() called
// multiple times and will only thaw after a matching number of Thaw()
// calls.
void Freeze();
void Thaw();
// Apply the parent window's suspend, freeze, and modal state to the current
// window.
void SyncStateFromParentWindow();
@ -341,9 +331,6 @@ public:
mozilla::Maybe<mozilla::dom::ClientState> GetClientState() const;
mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor> GetController() const;
RefPtr<mozilla::dom::ServiceWorker>
GetOrCreateServiceWorker(const mozilla::dom::ServiceWorkerDescriptor& aDescriptor);
void NoteCalledRegisterForServiceWorkerScope(const nsACString& aScope);
void NoteDOMContentLoaded();
@ -359,12 +346,6 @@ public:
virtual nsPIDOMWindowOuter* GetScriptableParent() = 0;
virtual already_AddRefed<nsPIWindowRoot> GetTopWindowRoot() = 0;
/**
* Behavies identically to GetScriptableParent extept that it returns null
* if GetScriptableParent would return this window.
*/
virtual nsPIDOMWindowOuter* GetScriptableParentOrNull() = 0;
mozilla::dom::EventTarget* GetChromeEventHandler() const
{
return mChromeEventHandler;
@ -862,7 +843,7 @@ public:
virtual already_AddRefed<nsPIWindowRoot> GetTopWindowRoot() = 0;
/**
* Behavies identically to GetScriptableParent extept that it returns null
* Behaves identically to GetScriptableParent except that it returns null
* if GetScriptableParent would return this window.
*/
virtual nsPIDOMWindowOuter* GetScriptableParentOrNull() = 0;
@ -891,14 +872,11 @@ public:
return mParentTarget;
}
virtual void MaybeUpdateTouchState() {}
nsIDocument* GetExtantDoc() const
{
return mDoc;
}
nsIURI* GetDocumentURI() const;
nsIURI* GetDocBaseURI() const;
nsIDocument* GetDoc()
{
@ -1197,7 +1175,6 @@ protected:
nsCOMPtr<nsIDocument> mDoc; // strong
// Cache the URI when mDoc is cleared.
nsCOMPtr<nsIURI> mDocumentURI; // strong
nsCOMPtr<nsIURI> mDocBaseURI; // strong
nsCOMPtr<mozilla::dom::EventTarget> mParentTarget; // strong

View File

@ -295,20 +295,22 @@ DOMEventTargetHelper::MaybeUpdateKeepAlive()
{
bool shouldBeKeptAlive = false;
if (!mKeepingAliveTypes.mAtoms.IsEmpty()) {
for (uint32_t i = 0; i < mKeepingAliveTypes.mAtoms.Length(); ++i) {
if (HasListenersFor(mKeepingAliveTypes.mAtoms[i])) {
shouldBeKeptAlive = true;
break;
if (NS_SUCCEEDED(CheckInnerWindowCorrectness())) {
if (!mKeepingAliveTypes.mAtoms.IsEmpty()) {
for (uint32_t i = 0; i < mKeepingAliveTypes.mAtoms.Length(); ++i) {
if (HasListenersFor(mKeepingAliveTypes.mAtoms[i])) {
shouldBeKeptAlive = true;
break;
}
}
}
}
if (!shouldBeKeptAlive && !mKeepingAliveTypes.mStrings.IsEmpty()) {
for (uint32_t i = 0; i < mKeepingAliveTypes.mStrings.Length(); ++i) {
if (HasListenersFor(mKeepingAliveTypes.mStrings[i])) {
shouldBeKeptAlive = true;
break;
if (!shouldBeKeptAlive && !mKeepingAliveTypes.mStrings.IsEmpty()) {
for (uint32_t i = 0; i < mKeepingAliveTypes.mStrings.Length(); ++i) {
if (HasListenersFor(mKeepingAliveTypes.mStrings[i])) {
shouldBeKeptAlive = true;
break;
}
}
}
}

View File

@ -304,7 +304,8 @@ interface nsIContentSecurityPolicy : nsISerializable
in nsIURI aRequestOrigin,
in nsISupports aContext,
in ACString aMimeTypeGuess,
in nsIURI aOriginalURIIfRedirect);
in nsIURI aOriginalURIIfRedirect,
in bool aSendViolationReports);
%{ C++
// nsIObserver topic to fire when the policy encounters a violation.

View File

@ -35,6 +35,7 @@ PermissionStatus::PermissionStatus(nsPIDOMWindowInner* aWindow,
, mName(aName)
, mState(PermissionState::Denied)
{
KeepAliveIfHasListenersFor(NS_LITERAL_STRING("change"));
}
nsresult
@ -125,5 +126,18 @@ PermissionStatus::PermissionChanged()
}
}
void
PermissionStatus::DisconnectFromOwner()
{
IgnoreKeepAliveIfHasListenersFor(NS_LITERAL_STRING("change"));
if (mObserver) {
mObserver->RemoveSink(this);
mObserver = nullptr;
}
DOMEventTargetHelper::DisconnectFromOwner();
}
} // namespace dom
} // namespace mozilla

View File

@ -33,6 +33,9 @@ public:
IMPL_EVENT_HANDLER(change)
void
DisconnectFromOwner() override;
private:
~PermissionStatus();

View File

@ -114,45 +114,6 @@ BlockedContentSourceToString(nsCSPContext::BlockedContentSource aSource,
}
}
/**
* Creates a key for use in the ShouldLoad cache.
* Looks like: <uri>!<nsIContentPolicy::LOAD_TYPE>
*/
nsresult
CreateCacheKey_Internal(nsIURI* aContentLocation,
nsContentPolicyType aContentType,
nsACString& outCacheKey)
{
if (!aContentLocation) {
return NS_ERROR_FAILURE;
}
bool isDataScheme = false;
nsresult rv = aContentLocation->SchemeIs("data", &isDataScheme);
NS_ENSURE_SUCCESS(rv, rv);
outCacheKey.Truncate();
if (aContentType != nsIContentPolicy::TYPE_SCRIPT && isDataScheme) {
// For non-script data: URI, use ("data:", aContentType) as the cache key.
outCacheKey.AppendLiteral("data:");
outCacheKey.AppendInt(aContentType);
return NS_OK;
}
nsAutoCString spec;
rv = aContentLocation->GetSpec(spec);
NS_ENSURE_SUCCESS(rv, rv);
// Don't cache for a URI longer than the cutoff size.
if (spec.Length() <= CSP_CACHE_URI_CUTOFF_SIZE) {
outCacheKey.Append(spec);
outCacheKey.AppendLiteral("!");
outCacheKey.AppendInt(aContentType);
}
return NS_OK;
}
/* ===== nsIContentSecurityPolicy impl ====== */
NS_IMETHODIMP
@ -162,6 +123,7 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
nsISupports* aRequestContext,
const nsACString& aMimeTypeGuess,
nsIURI* aOriginalURIIfRedirect,
bool aSendViolationReports,
int16_t* outDecision)
{
if (CSPCONTEXTLOGENABLED()) {
@ -178,8 +140,6 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
// case correctly.
aContentType = nsContentUtils::InternalContentPolicyTypeToExternalOrWorker(aContentType);
nsresult rv = NS_OK;
// This ShouldLoad function is called from nsCSPService::ShouldLoad,
// which already checked a number of things, including:
// * aContentLocation is not null; we can consume this without further checks
@ -188,16 +148,6 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
// * Content Type is not whitelisted (CSP Reports, TYPE_DOCUMENT, etc).
// * Fast Path for Apps
nsAutoCString cacheKey;
rv = CreateCacheKey_Internal(aContentLocation, aContentType, cacheKey);
NS_ENSURE_SUCCESS(rv, rv);
bool isCached = mShouldLoadCache.Get(cacheKey, outDecision);
if (isCached && cacheKey.Length() > 0) {
// this is cached, use the cached value.
return NS_OK;
}
// Default decision, CSP can revise it if there's a policy to enforce
*outDecision = nsIContentPolicy::ACCEPT;
@ -233,18 +183,13 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
nonce,
isPreload,
false, // allow fallback to default-src
true, // send violation reports
aSendViolationReports,
true, // send blocked URI in violation reports
parserCreated);
*outDecision = permitted ? nsIContentPolicy::ACCEPT
: nsIContentPolicy::REJECT_SERVER;
// Done looping, cache any relevant result
if (cacheKey.Length() > 0 && !isPreload) {
mShouldLoadCache.Put(cacheKey, *outDecision);
}
if (CSPCONTEXTLOGENABLED()) {
CSPCONTEXTLOG(("nsCSPContext::ShouldLoad, decision: %s, "
"aContentLocation: %s",
@ -335,7 +280,6 @@ nsCSPContext::~nsCSPContext()
for (uint32_t i = 0; i < mPolicies.Length(); i++) {
delete mPolicies[i];
}
mShouldLoadCache.Clear();
}
NS_IMETHODIMP
@ -430,8 +374,6 @@ nsCSPContext::AppendPolicy(const nsAString& aPolicyString,
}
mPolicies.AppendElement(policy);
// reset cache since effective policy changes
mShouldLoadCache.Clear();
}
return NS_OK;
}

View File

@ -10,7 +10,6 @@
#include "mozilla/dom/nsCSPUtils.h"
#include "mozilla/dom/SecurityPolicyViolationEvent.h"
#include "mozilla/StaticPrefs.h"
#include "nsDataHashtable.h"
#include "nsIChannel.h"
#include "nsIChannelEventSink.h"
#include "nsIClassInfo.h"
@ -172,7 +171,6 @@ class nsCSPContext : public nsIContentSecurityPolicy
uint64_t mInnerWindowID; // used for web console logging
nsTArray<nsCSPPolicy*> mPolicies;
nsCOMPtr<nsIURI> mSelfURI;
nsDataHashtable<nsCStringHashKey, int16_t> mShouldLoadCache;
nsCOMPtr<nsILoadGroup> mCallingChannelLoadGroup;
nsWeakPtr mLoadingContext;
// The CSP hangs off the principal, so let's store a raw pointer of the principal

View File

@ -188,6 +188,7 @@ CSPService::ShouldLoad(nsIURI *aContentLocation,
requestContext,
aMimeTypeGuess,
nullptr, // no redirect, aOriginal URL is null.
aLoadInfo->GetSendCSPViolationEvents(),
aDecision);
NS_ENSURE_SUCCESS(rv, rv);
@ -212,6 +213,7 @@ CSPService::ShouldLoad(nsIURI *aContentLocation,
requestContext,
aMimeTypeGuess,
nullptr, // no redirect, aOriginal URL is null.
aLoadInfo->GetSendCSPViolationEvents(),
aDecision);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -324,6 +326,7 @@ CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel,
requestContext, // nsISupports
EmptyCString(), // ACString - MIME guess
originalUri, // Original nsIURI
true, // aSendViolationReports
&aDecision);
// if the preload policy already denied the load, then there
@ -348,6 +351,7 @@ CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel,
requestContext, // nsISupports
EmptyCString(), // ACString - MIME guess
originalUri, // Original nsIURI
true, // aSendViolationReports
&aDecision);
}

View File

@ -152,7 +152,7 @@ function run_test() {
// shouldLoad creates and sends out the report here.
csp.shouldLoad(Ci.nsIContentPolicy.TYPE_SCRIPT,
NetUtil.newURI("http://blocked.test/foo.js"),
null, null, null, null);
null, null, null, null, true);
});
// test that inline script violations cause a report in report-only policy
@ -202,7 +202,7 @@ function run_test() {
// shouldLoad creates and sends out the report here.
csp.shouldLoad(Ci.nsIContentPolicy.TYPE_IMAGE,
NetUtil.newURI("data:image/png;base64," + base64data),
null, null, null, null);
null, null, null, null, true);
});
// test that only the uri's scheme is reported for globally unique identifiers
@ -211,7 +211,7 @@ function run_test() {
// shouldLoad creates and sends out the report here.
csp.shouldLoad(Ci.nsIContentPolicy.TYPE_SUBDOCUMENT,
NetUtil.newURI("intent://mymaps.com/maps?um=1&ie=UTF-8&fb=1&sll"),
null, null, null, null);
null, null, null, null, true);
});
// test fragment removal
@ -222,7 +222,7 @@ function run_test() {
// shouldLoad creates and sends out the report here.
csp.shouldLoad(Ci.nsIContentPolicy.TYPE_SCRIPT,
NetUtil.newURI(selfSpec + "#bar"),
null, null, null, null);
null, null, null, null, true);
});
// test scheme of ftp:
@ -231,6 +231,6 @@ function run_test() {
// shouldLoad creates and sends out the report here.
csp.shouldLoad(Ci.nsIContentPolicy.TYPE_SCRIPT,
NetUtil.newURI("ftp://blocked.test/profile.png"),
null, null, null, null);
null, null, null, null, true);
});
}

View File

@ -14,7 +14,6 @@
#include "mozilla/dom/SVGLengthBinding.h"
#include "mozilla/dom/SVGMarkerElement.h"
#include "mozilla/dom/SVGMarkerElementBinding.h"
#include "mozilla/Preferences.h"
#include "mozilla/gfx/Matrix.h"
#include "mozilla/FloatingPoint.h"
#include "SVGContentUtils.h"
@ -69,11 +68,6 @@ nsresult
nsSVGOrientType::SetBaseValue(uint16_t aValue,
nsSVGElement *aSVGElement)
{
if (aValue == SVG_MARKER_ORIENT_AUTO_START_REVERSE &&
!SVGMarkerElement::MarkerImprovementsPrefEnabled()) {
return NS_ERROR_DOM_TYPE_ERR;
}
if (aValue == SVG_MARKER_ORIENT_AUTO ||
aValue == SVG_MARKER_ORIENT_ANGLE ||
aValue == SVG_MARKER_ORIENT_AUTO_START_REVERSE) {
@ -226,8 +220,7 @@ SVGMarkerElement::ParseAttribute(int32_t aNameSpaceID, nsAtom* aName,
this, false);
return true;
}
if (aValue.EqualsLiteral("auto-start-reverse") &&
MarkerImprovementsPrefEnabled()) {
if (aValue.EqualsLiteral("auto-start-reverse")) {
mOrientType.SetBaseValue(SVG_MARKER_ORIENT_AUTO_START_REVERSE);
aResult.SetTo(aValue);
mAngleAttributes[ORIENT].SetBaseValue(0.f, SVG_ANGLETYPE_UNSPECIFIED,
@ -386,11 +379,5 @@ SVGMarkerElement::GetViewBoxTransform()
return *mViewBoxToViewportTransform;
}
/* static */ bool
SVGMarkerElement::MarkerImprovementsPrefEnabled()
{
return Preferences::GetBool("svg.marker-improvements.enabled", false);
}
} // namespace dom
} // namespace mozilla

View File

@ -127,9 +127,6 @@ public:
nsSVGOrientType* GetOrientType() { return &mOrientType; }
// Returns the value of svg.marker-improvements.enabled.
static bool MarkerImprovementsPrefEnabled();
// WebIDL
already_AddRefed<SVGAnimatedRect> ViewBox();
already_AddRefed<DOMSVGAnimatedPreserveAspectRatio> PreserveAspectRatio();

View File

@ -371,11 +371,7 @@ function runTests()
SimpleTest.finish();
}
function runTestsWithPref() {
SpecialPowers.pushPrefEnv({ 'set': [['svg.marker-improvements.enabled', true]] }, runTests);
}
window.addEventListener("load", runTestsWithPref);
window.addEventListener("load", runTests);
</script>
</pre>
</body>

View File

@ -88,11 +88,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=892372
SimpleTest.finish();
}
function runTestsWithPref() {
SpecialPowers.pushPrefEnv({ 'set': [['svg.marker-improvements.enabled', true]] }, run);
}
window.addEventListener("load", runTestsWithPref);
window.addEventListener("load", run);
]]>
</script>

View File

@ -1565,7 +1565,7 @@ function doFrameHistoryTests()
}, true);
// make sure that loading a new page and then going back maintains the focus
gChildWindow.location = "data:text/html,<script>window.onload=function() {setTimeout(function () {SpecialPowers.wrap(window).back();}, 0);}</script>";
gChildWindow.location = "data:text/html,<script>window.onload=function() {setTimeout(function () { history.back() }, 0);}</script>";
}
function addFrameSwitchingListeners(frame)

View File

@ -273,10 +273,6 @@ partial interface Window {
[Throws] attribute boolean fullScreen;
[Throws, ChromeOnly] void back();
[Throws, ChromeOnly] void forward();
[Throws, ChromeOnly, NeedsSubjectPrincipal] void home();
// XXX Should this be in nsIDOMChromeWindow?
void updateCommands(DOMString action,
optional Selection? sel = null,

View File

@ -950,6 +950,7 @@ pub extern "C" fn wr_window_new(window_id: WrWindowId,
scene_builder_hooks: Some(Box::new(APZCallbacks::new(window_id))),
sampler: Some(Box::new(SamplerCallback::new(window_id))),
max_texture_size: Some(8192), // Moz2D doesn't like textures bigger than this
clear_color: Some(ColorF::new(0.0, 0.0, 0.0, 0.0)),
..Default::default()
};

View File

@ -616,7 +616,8 @@ static bool
ShouldLoadCachedImage(imgRequest* aImgRequest,
nsISupports* aLoadingContext,
nsIPrincipal* aTriggeringPrincipal,
nsContentPolicyType aPolicyType)
nsContentPolicyType aPolicyType,
bool aSendCSPViolationReports)
{
/* Call content policies on cached images - Bug 1082837
* Cached images are keyed off of the first uri in a redirect chain.
@ -650,6 +651,8 @@ ShouldLoadCachedImage(imgRequest* aImgRequest,
nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK,
aPolicyType);
secCheckLoadInfo->SetSendCSPViolationEvents(aSendCSPViolationReports);
int16_t decision = nsIContentPolicy::REJECT_REQUEST;
rv = NS_CheckContentLoadPolicy(contentLocation,
secCheckLoadInfo,
@ -746,7 +749,8 @@ ValidateSecurityInfo(imgRequest* request, bool forcePrincipalCheck,
}
// Content Policy Check on Cached Images
return ShouldLoadCachedImage(request, aCX, triggeringPrincipal, aPolicyType);
return ShouldLoadCachedImage(request, aCX, triggeringPrincipal, aPolicyType,
/* aSendCSPViolationReports */ false);
}
static nsresult
@ -1797,7 +1801,8 @@ imgLoader::ValidateRequestWithNewChannel(imgRequest* request,
nsContentPolicyType aLoadPolicyType,
imgRequestProxy** aProxyRequest,
nsIPrincipal* aTriggeringPrincipal,
int32_t aCORSMode)
int32_t aCORSMode,
bool* aNewChannelCreated)
{
// now we need to insert a new channel request object inbetween the real
// request and the proxy that basically delays loading the image until it
@ -1853,6 +1858,10 @@ imgLoader::ValidateRequestWithNewChannel(imgRequest* request,
return false;
}
if (aNewChannelCreated) {
*aNewChannelCreated = true;
}
RefPtr<imgRequestProxy> req;
rv = CreateNewProxyForRequest(request, aLoadGroup, aLoadingDocument,
aObserver, aLoadFlags, getter_AddRefs(req));
@ -1917,6 +1926,7 @@ imgLoader::ValidateEntry(imgCacheEntry* aEntry,
nsLoadFlags aLoadFlags,
nsContentPolicyType aLoadPolicyType,
bool aCanMakeNewChannel,
bool* aNewChannelCreated,
imgRequestProxy** aProxyRequest,
nsIPrincipal* aTriggeringPrincipal,
int32_t aCORSMode)
@ -2036,7 +2046,7 @@ imgLoader::ValidateEntry(imgCacheEntry* aEntry,
aCX, aLoadingDocument,
aLoadFlags, aLoadPolicyType,
aProxyRequest, aTriggeringPrincipal,
aCORSMode);
aCORSMode, aNewChannelCreated);
}
return !validateRequest;
@ -2341,10 +2351,12 @@ imgLoader::LoadImage(nsIURI* aURI,
imgCacheTable& cache = GetCache(key);
if (cache.Get(key, getter_AddRefs(entry)) && entry) {
bool newChannelCreated = false;
if (ValidateEntry(entry, aURI, aInitialDocumentURI, aReferrerURI,
aReferrerPolicy, aLoadGroup, aObserver, aLoadingDocument,
aLoadingDocument, requestFlags, aContentPolicyType, true,
_retval, aTriggeringPrincipal, corsmode)) {
&newChannelCreated, _retval, aTriggeringPrincipal,
corsmode)) {
request = entry->GetRequest();
// If this entry has no proxies, its request has no reference to the
@ -2363,6 +2375,18 @@ imgLoader::LoadImage(nsIURI* aURI,
entry->Touch();
if (!newChannelCreated) {
// This is ugly but it's needed to report CSP violations. We have 3
// scenarios:
// - we don't have cache. We are not in this if() stmt. A new channel is
// created and that triggers the CSP checks.
// - We have a cache entry and this is blocked by CSP directives.
DebugOnly<bool> shouldLoad =
ShouldLoadCachedImage(request, aLoadingDocument, aTriggeringPrincipal,
aContentPolicyType,
/* aSendCSPViolationReports */ true);
MOZ_ASSERT(shouldLoad);
}
} else {
// We can't use this entry. We'll try to load it off the network, and if
// successful, overwrite the old entry in the cache with a new one.
@ -2613,7 +2637,7 @@ imgLoader::LoadImageWithChannel(nsIChannel* channel,
if (ValidateEntry(entry, uri, nullptr, nullptr, RP_Unset,
nullptr, aObserver, aCX, doc, requestFlags,
policyType, false, nullptr,
policyType, false, nullptr, nullptr,
nullptr, imgIRequest::CORS_NONE)) {
request = entry->GetRequest();
} else {

View File

@ -413,6 +413,7 @@ private: // methods
nsLoadFlags aLoadFlags,
nsContentPolicyType aContentPolicyType,
bool aCanMakeNewChannel,
bool* aNewChannelCreated,
imgRequestProxy** aProxyRequest,
nsIPrincipal* aLoadingPrincipal,
int32_t aCORSMode);
@ -429,7 +430,8 @@ private: // methods
nsContentPolicyType aContentPolicyType,
imgRequestProxy** aProxyRequest,
nsIPrincipal* aLoadingPrincipal,
int32_t aCORSMode);
int32_t aCORSMode,
bool* aNewChannelCreated);
nsresult CreateNewProxyForRequest(imgRequest* aRequest,
nsILoadGroup* aLoadGroup,

View File

@ -431,6 +431,7 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo,
aLoadInfo->GetInitialSecurityCheckDone(),
aLoadInfo->GetIsInThirdPartyContext(),
aLoadInfo->GetIsDocshellReload(),
aLoadInfo->GetSendCSPViolationEvents(),
aLoadInfo->GetOriginAttributes(),
redirectChainIncludingInternalRedirects,
redirectChain,
@ -587,6 +588,7 @@ LoadInfoArgsToLoadInfo(const OptionalLoadInfoArgs& aOptionalLoadInfoArgs,
loadInfoArgs.initialSecurityCheckDone(),
loadInfoArgs.isInThirdPartyContext(),
loadInfoArgs.isDocshellReload(),
loadInfoArgs.sendCSPViolationEvents(),
loadInfoArgs.originAttributes(),
redirectChainIncludingInternalRedirects,
redirectChain,

View File

@ -266,6 +266,11 @@ def main(argv):
# to be off when it starts.
options.exclude += [os.path.join('debug', 'Script-getOffsetsCoverage-02.js')]
# These tests expect functions to be parsed lazily, but lazy parsing
# is disabled on coverage build.
options.exclude += [os.path.join('debug', 'Debugger-findScripts-uncompleted-01.js')]
options.exclude += [os.path.join('debug', 'Debugger-findScripts-uncompleted-02.js')]
if options.exclude_from:
with open(options.exclude_from) as fh:
for line in fh:

View File

@ -776,16 +776,14 @@ MacroAssembler::nurseryAllocateObject(Register result, Register temp, gc::AllocK
// No explicit check for nursery.isEnabled() is needed, as the comparison
// with the nursery's end will always fail in such cases.
CompileZone* zone = GetJitContext()->realm->zone();
int thingSize = int(gc::Arena::thingSize(allocKind));
int totalSize = thingSize + nDynamicSlots * sizeof(HeapSlot);
size_t thingSize = gc::Arena::thingSize(allocKind);
size_t totalSize = thingSize + nDynamicSlots * sizeof(HeapSlot);
MOZ_ASSERT(totalSize < INT32_MAX);
MOZ_ASSERT(totalSize % gc::CellAlignBytes == 0);
void *ptrNurseryPosition = zone->addressOfNurseryPosition();
loadPtr(AbsoluteAddress(ptrNurseryPosition), result);
computeEffectiveAddress(Address(result, totalSize), temp);
const void *ptrNurseryCurrentEnd = zone->addressOfNurseryCurrentEnd();
branchPtr(Assembler::Below, AbsoluteAddress(ptrNurseryCurrentEnd), temp,
fail);
storePtr(temp, AbsoluteAddress(ptrNurseryPosition));
bumpPointerAllocate(result, temp, fail,
zone->addressOfNurseryPosition(),
zone->addressOfNurseryCurrentEnd(), totalSize, totalSize);
if (nDynamicSlots) {
computeEffectiveAddress(Address(result, thingSize), temp);
@ -962,23 +960,39 @@ MacroAssembler::nurseryAllocateString(Register result, Register temp, gc::AllocK
// with the nursery's end will always fail in such cases.
CompileZone* zone = GetJitContext()->realm->zone();
int thingSize = int(gc::Arena::thingSize(allocKind));
int totalSize = js::Nursery::stringHeaderSize() + thingSize;
size_t thingSize = gc::Arena::thingSize(allocKind);
size_t totalSize = js::Nursery::stringHeaderSize() + thingSize;
MOZ_ASSERT(totalSize < INT32_MAX,
"Nursery allocation too large");
MOZ_ASSERT(totalSize % gc::CellAlignBytes == 0);
// The nursery position (allocation pointer) and the nursery end are stored
bumpPointerAllocate(result, temp, fail,
zone->addressOfStringNurseryPosition(),
zone->addressOfStringNurseryCurrentEnd(), totalSize, thingSize);
storePtr(ImmPtr(zone), Address(result, -js::Nursery::stringHeaderSize()));
}
void
MacroAssembler::bumpPointerAllocate(Register result, Register temp, Label* fail,
void* posAddr, const void* curEndAddr, uint32_t totalSize, uint32_t size)
{
// The position (allocation pointer) and the end pointer are stored
// very close to each other -- specifically, easily within a 32 bit offset.
// Use relative offsets between them, to avoid 64-bit immediate loads.
auto nurseryPosAddr = intptr_t(zone->addressOfStringNurseryPosition());
auto nurseryEndAddr = intptr_t(zone->addressOfStringNurseryCurrentEnd());
movePtr(ImmPtr(zone->addressOfNurseryPosition()), temp);
//
// I tried to optimise this further by using an extra register to avoid
// the final subtraction and hopefully get some more instruction
// parallelism, but it made no difference.
movePtr(ImmPtr(posAddr), temp);
loadPtr(Address(temp, 0), result);
addPtr(Imm32(totalSize), result);
branchPtr(Assembler::Below, Address(temp, nurseryEndAddr - nurseryPosAddr), result, fail);
CheckedInt<int32_t> endOffset = (CheckedInt<uintptr_t>(uintptr_t(curEndAddr)) -
CheckedInt<uintptr_t>(uintptr_t(posAddr))).toChecked<int32_t>();
MOZ_ASSERT(endOffset.isValid(),
"Position and end pointers must be nearby");
branchPtr(Assembler::Below, Address(temp, endOffset.value()), result, fail);
storePtr(result, Address(temp, 0));
subPtr(Imm32(thingSize), result);
storePtr(ImmPtr(zone), Address(result, -js::Nursery::stringHeaderSize()));
subPtr(Imm32(size), result);
}
// Inlined equivalent of gc::AllocateString, jumping to fail if nursery

View File

@ -2279,6 +2279,10 @@ class MacroAssembler : public MacroAssemblerSpecific
bool shouldNurseryAllocate(gc::AllocKind allocKind, gc::InitialHeap initialHeap);
void nurseryAllocateObject(Register result, Register temp, gc::AllocKind allocKind,
size_t nDynamicSlots, Label* fail);
void bumpPointerAllocate(Register result, Register temp, Label* fail,
void* posAddr, const void* curEddAddr,
uint32_t totalSize, uint32_t size);
void freeListAllocate(Register result, Register temp, gc::AllocKind allocKind, Label* fail);
void allocateObject(Register result, Register temp, gc::AllocKind allocKind,
uint32_t nDynamicSlots, gc::InitialHeap initialHeap, Label* fail);

View File

@ -58,7 +58,7 @@ XPCConvert::IsMethodReflectable(const nsXPTMethodInfo& info)
// Reflected methods can't use native types. All native types end up
// getting tagged as void*, so this check is easy.
if (type.TagPart() == nsXPTType::T_VOID)
if (type.Tag() == nsXPTType::T_VOID)
return false;
}
return true;
@ -108,7 +108,7 @@ XPCConvert::NativeData2JS(MutableHandleValue d, const void* s,
if (pErr)
*pErr = NS_ERROR_XPC_BAD_CONVERT_NATIVE;
switch (type.TagPart()) {
switch (type.Tag()) {
case nsXPTType::T_I8 :
d.setInt32(*static_cast<const int8_t*>(s));
return true;
@ -385,10 +385,17 @@ XPCConvert::NativeData2JS(MutableHandleValue d, const void* s,
return true;
}
case nsXPTType::T_ARRAY:
return NativeArray2JS(d, static_cast<const void* const*>(s),
case nsXPTType::T_LEGACY_ARRAY:
return NativeArray2JS(d, *static_cast<const void* const*>(s),
type.ArrayElementType(), iid, arrlen, pErr);
case nsXPTType::T_ARRAY:
{
auto* array = static_cast<const xpt::detail::UntypedTArray*>(s);
return NativeArray2JS(d, array->Elements(), type.ArrayElementType(),
iid, array->Length(), pErr);
}
default:
NS_ERROR("bad type");
return false;
@ -448,7 +455,7 @@ XPCConvert::JSData2Native(void* d, HandleValue s,
bool sizeis = type.Tag() == TD_PSTRING_SIZE_IS ||
type.Tag() == TD_PWSTRING_SIZE_IS;
switch (type.TagPart()) {
switch (type.Tag()) {
case nsXPTType::T_I8 :
return ConvertToPrimitive(cx, s, static_cast<int8_t*>(d));
case nsXPTType::T_I16 :
@ -834,9 +841,70 @@ XPCConvert::JSData2Native(void* d, HandleValue s,
return ok;
}
case nsXPTType::T_LEGACY_ARRAY:
{
void** dest = (void**)d;
const nsXPTType& elty = type.ArrayElementType();
*dest = nullptr;
// FIXME: XPConnect historically has shortcut the JSArray2Native codepath in
// its caller if arrlen is 0, allowing arbitrary values to be passed as
// arrays and interpreted as the empty array (bug 1458987).
//
// NOTE: Once this is fixed, null/undefined should be allowed for arrays if
// arrlen is 0.
if (arrlen == 0) {
return true;
}
bool ok = JSArray2Native(s, elty, iid, pErr, [&] (uint32_t* aLength) -> void* {
// Check that we have enough elements in our array.
if (*aLength < arrlen) {
if (pErr)
*pErr = NS_ERROR_XPC_NOT_ENOUGH_ELEMENTS_IN_ARRAY;
return nullptr;
}
*aLength = arrlen;
// Allocate the backing buffer & return it.
*dest = moz_xmalloc(*aLength * elty.Stride());
if (!*dest) {
if (pErr)
*pErr = NS_ERROR_OUT_OF_MEMORY;
return nullptr;
}
return *dest;
});
if (!ok && *dest) {
// An error occurred, free any allocated backing buffer.
free(*dest);
*dest = nullptr;
}
return ok;
}
case nsXPTType::T_ARRAY:
return JSArray2Native((void**)d, s, arrlen,
type.ArrayElementType(), iid, pErr);
{
auto* dest = (xpt::detail::UntypedTArray*)d;
const nsXPTType& elty = type.ArrayElementType();
bool ok = JSArray2Native(s, elty, iid, pErr, [&] (uint32_t* aLength) -> void* {
if (!dest->SetLength(elty, *aLength)) {
if (pErr)
*pErr = NS_ERROR_OUT_OF_MEMORY;
return nullptr;
}
return dest->Elements();
});
if (!ok) {
// An error occurred, free any allocated backing buffer.
dest->Clear();
}
return ok;
}
default:
NS_ERROR("bad type");
@ -1332,39 +1400,16 @@ XPCConvert::JSValToXPCException(MutableHandleValue s,
// array fun...
static bool
ValidArrayType(const nsXPTType& type)
{
switch (type.Tag()) {
// These types aren't allowed to be in arrays.
case nsXPTType::T_VOID:
case nsXPTType::T_DOMSTRING:
case nsXPTType::T_UTF8STRING:
case nsXPTType::T_CSTRING:
case nsXPTType::T_ASTRING:
case nsXPTType::T_PSTRING_SIZE_IS:
case nsXPTType::T_PWSTRING_SIZE_IS:
case nsXPTType::T_ARRAY:
return false;
default:
return true;
}
}
// static
bool
XPCConvert::NativeArray2JS(MutableHandleValue d, const void* const* s,
XPCConvert::NativeArray2JS(MutableHandleValue d, const void* buf,
const nsXPTType& type, const nsID* iid,
uint32_t count, nsresult* pErr)
{
MOZ_ASSERT(s, "bad param");
MOZ_ASSERT(buf || count == 0, "Must have buf or 0 elements");
AutoJSContext cx;
// XXX add support for putting chars in a string rather than an array
// XXX add support to indicate *which* array element was not convertable
RootedObject array(cx, JS_NewArrayObject(cx, count));
if (!array)
return false;
@ -1372,12 +1417,9 @@ XPCConvert::NativeArray2JS(MutableHandleValue d, const void* const* s,
if (pErr)
*pErr = NS_ERROR_XPC_BAD_CONVERT_NATIVE;
if (!ValidArrayType(type))
return false;
RootedValue current(cx, JS::NullValue());
for (uint32_t i = 0; i < count; ++i) {
if (!NativeData2JS(&current, type.ElementPtr(*s, i), type, iid, 0, pErr) ||
if (!NativeData2JS(&current, type.ElementPtr(buf, i), type, iid, 0, pErr) ||
!JS_DefineElement(cx, array, i, current, JSPROP_ENUMERATE))
return false;
}
@ -1388,223 +1430,125 @@ XPCConvert::NativeArray2JS(MutableHandleValue d, const void* const* s,
return true;
}
// Fast conversion of typed arrays to native using memcpy.
// No float or double canonicalization is done. Called by
// JSarray2Native whenever a TypedArray is met. ArrayBuffers
// are not accepted; create a properly typed array view on them
// first. The element type of array must match the XPCOM
// type in size, type and signedness exactly. As an exception,
// Uint8ClampedArray is allowed for arrays of uint8_t. DataViews
// are not supported.
// static
bool
XPCConvert::JSTypedArray2Native(void** d,
JSObject* jsArray,
uint32_t count,
const nsXPTType& type,
nsresult* pErr)
XPCConvert::JSArray2Native(JS::HandleValue aJSVal,
const nsXPTType& aEltType,
const nsIID* aIID,
nsresult* pErr,
const ArrayAllocFixupLen& aAllocFixupLen)
{
MOZ_ASSERT(jsArray, "bad param");
MOZ_ASSERT(d, "bad param");
MOZ_ASSERT(JS_IsTypedArrayObject(jsArray), "not a typed array");
// Wrap aAllocFixupLen to check length is within bounds & initialize the
// allocated memory if needed.
auto allocFixupLen = [&] (uint32_t* aLength) -> void* {
if (*aLength > (UINT32_MAX / aEltType.Stride())) {
return nullptr; // Byte length doesn't fit in uint32_t
}
// Check the actual length of the input array against the
// given size_is.
uint32_t len = JS_GetTypedArrayLength(jsArray);
if (len < count) {
if (pErr)
*pErr = NS_ERROR_XPC_NOT_ENOUGH_ELEMENTS_IN_ARRAY;
void* buf = aAllocFixupLen(aLength);
return false;
}
uint8_t expected;
switch (JS_GetArrayBufferViewType(jsArray)) {
case js::Scalar::Int8:
expected = nsXPTType::T_I8;
break;
case js::Scalar::Uint8:
case js::Scalar::Uint8Clamped:
expected = nsXPTType::T_U8;
break;
case js::Scalar::Int16:
expected = nsXPTType::T_I16;
break;
case js::Scalar::Uint16:
expected = nsXPTType::T_U16;
break;
case js::Scalar::Int32:
expected = nsXPTType::T_I32;
break;
case js::Scalar::Uint32:
expected = nsXPTType::T_U32;
break;
case js::Scalar::Float32:
expected = nsXPTType::T_FLOAT;
break;
case js::Scalar::Float64:
expected = nsXPTType::T_DOUBLE;
break;
// Yet another array type was defined? It is not supported yet...
default:
if (pErr)
*pErr = NS_ERROR_XPC_BAD_CONVERT_JS;
return false;
}
// Check that the type we got is the type we expected.
if (expected != type.Tag()) {
if (pErr)
*pErr = NS_ERROR_XPC_BAD_CONVERT_JS;
return false;
}
// Check if the size would overflow uint32_t.
if (count > (UINT32_MAX / type.Stride())) {
if (pErr)
*pErr = NS_ERROR_OUT_OF_MEMORY;
return false;
}
// Get the backing memory buffer to copy out of.
JS::AutoCheckCannotGC nogc;
bool isShared;
void* buf = JS_GetArrayBufferViewData(jsArray, &isShared, nogc);
// Require opting in to shared memory - a future project.
if (isShared) {
if (pErr)
*pErr = NS_ERROR_XPC_BAD_CONVERT_JS;
return false;
}
// Allocate the buffer, and copy.
*d = moz_xmalloc(count * type.Stride());
if (!*d) {
if (pErr)
*pErr = NS_ERROR_OUT_OF_MEMORY;
return false;
}
memcpy(*d, buf, count * type.Stride());
if (pErr)
*pErr = NS_OK;
return true;
}
// static
bool
XPCConvert::JSArray2Native(void** d, HandleValue s,
uint32_t count, const nsXPTType& type,
const nsID* iid, nsresult* pErr)
{
MOZ_ASSERT(d, "bad param");
// Ensure the buffer has valid values for each element. We can skip this
// for arithmetic types, as they do not require initialization.
if (buf && !aEltType.IsArithmetic()) {
for (uint32_t i = 0; i < *aLength; ++i) {
InitializeValue(aEltType, aEltType.ElementPtr(buf, i));
}
}
return buf;
};
AutoJSContext cx;
// FIXME: XPConnect historically has shortcut the JSArray2Native codepath in
// its caller if count is 0, allowing arbitrary values to be passed as
// arrays and interpreted as the empty array (bug 1458987).
//
// NOTE: Once this is fixed, null/undefined should be allowed for arrays if
// count is 0.
if (count == 0) {
*d = nullptr;
return true;
}
// XXX add support for getting chars from strings
// XXX add support to indicate *which* array element was not convertable
if (pErr)
*pErr = NS_ERROR_XPC_BAD_CONVERT_JS;
if (!ValidArrayType(type))
return false;
if (s.isNullOrUndefined()) {
if (pErr)
*pErr = NS_ERROR_XPC_NOT_ENOUGH_ELEMENTS_IN_ARRAY;
return false;
}
if (!s.isObject()) {
// JSArray2Native only accepts objects (Array and TypedArray).
if (!aJSVal.isObject()) {
if (pErr)
*pErr = NS_ERROR_XPC_CANT_CONVERT_PRIMITIVE_TO_ARRAY;
return false;
}
RootedObject jsarray(cx, &aJSVal.toObject());
RootedObject jsarray(cx, &s.toObject());
if (pErr)
*pErr = NS_ERROR_XPC_BAD_CONVERT_JS;
// If this is a typed array, then try a fast conversion with memcpy.
if (JS_IsTypedArrayObject(jsarray)) {
return JSTypedArray2Native(d, jsarray, count, type, pErr);
// Fast conversion of typed arrays to native using memcpy. No float or
// double canonicalization is done. ArrayBuffers are not accepted;
// create a properly typed array view on them first. The element type of
// array must match the XPCOM type in size, type and signedness exactly.
// As an exception, Uint8ClampedArray is allowed for arrays of uint8_t.
// DataViews are not supported.
nsXPTTypeTag tag;
switch (JS_GetArrayBufferViewType(jsarray)) {
case js::Scalar::Int8: tag = TD_INT8; break;
case js::Scalar::Uint8: tag = TD_UINT8; break;
case js::Scalar::Uint8Clamped: tag = TD_UINT8; break;
case js::Scalar::Int16: tag = TD_INT16; break;
case js::Scalar::Uint16: tag = TD_UINT16; break;
case js::Scalar::Int32: tag = TD_INT32; break;
case js::Scalar::Uint32: tag = TD_UINT32; break;
case js::Scalar::Float32: tag = TD_FLOAT; break;
case js::Scalar::Float64: tag = TD_DOUBLE; break;
default: return false;
}
if (aEltType.Tag() != tag) {
return false;
}
// Allocate the backing buffer before getting the view data in case
// allocFixupLen can cause GCs.
uint32_t length = JS_GetTypedArrayLength(jsarray);
void* buf = allocFixupLen(&length);
if (!buf) {
return false;
}
// Get the backing memory buffer to copy out of.
JS::AutoCheckCannotGC nogc;
bool isShared = false;
const void* data = JS_GetArrayBufferViewData(jsarray, &isShared, nogc);
// Require opting in to shared memory - a future project.
if (isShared) {
return false;
}
// Directly copy data into the allocated target buffer.
memcpy(buf, data, length * aEltType.Stride());
return true;
}
bool isArray;
if (!JS_IsArrayObject(cx, jsarray, &isArray) || !isArray) {
// If jsarray is not a TypedArrayObject, check for an Array object.
uint32_t length = 0;
bool isArray = false;
if (!JS_IsArrayObject(cx, jsarray, &isArray) || !isArray ||
!JS_GetArrayLength(cx, jsarray, &length)) {
if (pErr)
*pErr = NS_ERROR_XPC_CANT_CONVERT_OBJECT_TO_ARRAY;
return false;
}
uint32_t len;
if (!JS_GetArrayLength(cx, jsarray, &len) || len < count) {
if (pErr)
*pErr = NS_ERROR_XPC_NOT_ENOUGH_ELEMENTS_IN_ARRAY;
return false;
}
if (count > (UINT32_MAX / type.Stride())) {
if (pErr)
*pErr = NS_ERROR_OUT_OF_MEMORY;
return false;
}
// Allocate the destination array, and begin converting elements.
*d = moz_xmalloc(count * type.Stride());
if (!*d) {
if (pErr)
*pErr = NS_ERROR_OUT_OF_MEMORY;
void* buf = allocFixupLen(&length);
if (!buf) {
return false;
}
// Translate each array element separately.
RootedValue current(cx);
uint32_t initedCount;
for (initedCount = 0; initedCount < count; ++initedCount) {
if (!JS_GetElement(cx, jsarray, initedCount, &current) ||
!JSData2Native(type.ElementPtr(*d, initedCount),
current, type, iid, 0, pErr))
break;
for (uint32_t i = 0; i < length; ++i) {
if (!JS_GetElement(cx, jsarray, i, &current) ||
!JSData2Native(aEltType.ElementPtr(buf, i), current,
aEltType, aIID, 0, pErr)) {
// Array element conversion failed. Clean up all elements converted
// before the error. Caller handles freeing 'buf'.
for (uint32_t j = 0; j < i; ++j) {
CleanupValue(aEltType, aEltType.ElementPtr(buf, j));
}
return false;
}
}
// Check if we handled every array element.
if (initedCount == count) {
if (pErr)
*pErr = NS_OK;
return true;
}
// Something failed! Clean up after ourselves.
for (uint32_t i = 0; i < initedCount; ++i) {
CleanupValue(type, type.ElementPtr(*d, i));
}
free(*d);
*d = nullptr;
return false;
return true;
}
/***************************************************************************/
@ -1619,7 +1563,7 @@ xpc::InnerCleanupValue(const nsXPTType& aType, void* aValue, uint32_t aArrayLen)
MOZ_ASSERT(aArrayLen == 0 ||
aType.Tag() == nsXPTType::T_PSTRING_SIZE_IS ||
aType.Tag() == nsXPTType::T_PWSTRING_SIZE_IS ||
aType.Tag() == nsXPTType::T_ARRAY,
aType.Tag() == nsXPTType::T_LEGACY_ARRAY,
"Array lengths may only appear for certain types!");
switch (aType.Tag()) {
@ -1656,8 +1600,8 @@ xpc::InnerCleanupValue(const nsXPTType& aType, void* aValue, uint32_t aArrayLen)
free(*(void**)aValue);
break;
// Array Types
case nsXPTType::T_ARRAY:
// Legacy Array Type
case nsXPTType::T_LEGACY_ARRAY:
{
const nsXPTType& elty = aType.ArrayElementType();
void* elements = *(void**)aValue;
@ -1668,10 +1612,69 @@ xpc::InnerCleanupValue(const nsXPTType& aType, void* aValue, uint32_t aArrayLen)
free(elements);
break;
}
// Array Type
case nsXPTType::T_ARRAY:
{
const nsXPTType& elty = aType.ArrayElementType();
auto* array = (xpt::detail::UntypedTArray*)aValue;
for (uint32_t i = 0; i < array->Length(); ++i) {
CleanupValue(elty, elty.ElementPtr(array->Elements(), i));
}
array->Clear();
break;
}
// Clear the JS::Value to `undefined`
case nsXPTType::T_JSVAL:
((JS::Value*)aValue)->setUndefined();
break;
// Non-arithmetic types requiring no cleanup
case nsXPTType::T_VOID:
break;
default:
MOZ_CRASH("Unknown Type!");
}
// Null out the pointer if we have it.
if (aType.HasPointerRepr()) {
*(void**)aValue = nullptr;
// Clear any non-complex values to the valid '0' state.
if (!aType.IsComplex()) {
aType.ZeroValue(aValue);
}
}
/***************************************************************************/
// Implementation of xpc::InitializeValue.
void
xpc::InitializeValue(const nsXPTType& aType, void* aValue)
{
switch (aType.Tag()) {
// Types which require custom, specific initialization.
case nsXPTType::T_JSVAL:
new (aValue) JS::Value();
MOZ_ASSERT(reinterpret_cast<JS::Value*>(aValue)->isUndefined());
break;
case nsXPTType::T_ASTRING:
case nsXPTType::T_DOMSTRING:
new (aValue) nsString();
break;
case nsXPTType::T_CSTRING:
case nsXPTType::T_UTF8STRING:
new (aValue) nsCString();
break;
case nsXPTType::T_ARRAY:
new (aValue) xpt::detail::UntypedTArray();
break;
// The remaining types all have valid states where all bytes are '0'.
default:
aType.ZeroValue(aValue);
break;
}
}

View File

@ -530,7 +530,10 @@ xpc::CleanupValue(const nsXPTType& aType,
// Check if we can do a cheap early return, and only perform the inner call
// if we can't. We never have to clean up null pointer types or arithmetic
// types.
if (aType.IsArithmetic() || (aType.HasPointerRepr() && !*(void**)aValue)) {
//
// NOTE: We can skip zeroing arithmetic types in CleanupValue, as they are
// already in a valid state.
if (aType.IsArithmetic() || (aType.IsPointer() && !*(void**)aValue)) {
return;
}
xpc::InnerCleanupValue(aType, aValue, aArrayLen);

View File

@ -672,7 +672,7 @@ nsXPCWrappedJSClass::GetArraySizeFromParam(const nsXPTMethodInfo* method,
nsXPTCMiniVariant* nativeParams,
uint32_t* result) const
{
if (type.Tag() != nsXPTType::T_ARRAY &&
if (type.Tag() != nsXPTType::T_LEGACY_ARRAY &&
type.Tag() != nsXPTType::T_PSTRING_SIZE_IS &&
type.Tag() != nsXPTType::T_PWSTRING_SIZE_IS) {
*result = 0;
@ -749,25 +749,27 @@ nsXPCWrappedJSClass::CleanupOutparams(const nsXPTMethodInfo* info,
if (!param.IsOut())
continue;
// Extract the array length so we can use it in CleanupValue.
uint32_t arrayLen = 0;
if (!GetArraySizeFromParam(info, param.Type(), nativeParams, &arrayLen))
continue;
MOZ_ASSERT(param.IsIndirect(), "Outparams are always indirect");
// The inOutOnly flag is necessary because full outparams may contain
// uninitialized junk before the call is made, and we don't want to try
// to clean up uninitialized junk.
if (!inOutOnly || param.IsIn()) {
// Call 'CleanupValue' on parameters which we know to be initialized:
// 1. Complex parameters (initialized by caller)
// 2. 'inout' parameters (initialized by caller)
// 3. 'out' parameters when 'inOutOnly' is 'false' (initialized by us)
//
// We skip non-complex 'out' parameters before the call, as they may
// contain random junk.
if (param.Type().IsComplex() || param.IsIn() || !inOutOnly) {
uint32_t arrayLen = 0;
if (!GetArraySizeFromParam(info, param.Type(), nativeParams, &arrayLen))
continue;
xpc::CleanupValue(param.Type(), nativeParams[i].val.p, arrayLen);
}
// Even if we didn't call CleanupValue, null out any pointers. This is
// just to protect C++ callers which may read garbage if they forget to
// check the error value.
if (param.Type().HasPointerRepr()) {
*(void**)nativeParams[i].val.p = nullptr;
// Ensure our parameters are in a clean state. Complex values are always
// handled by CleanupValue, and others have a valid null representation.
if (!param.Type().IsComplex()) {
param.Type().ZeroValue(nativeParams[i].val.p);
}
}
}

View File

@ -1245,10 +1245,6 @@ CallMethodHelper::Call()
CallMethodHelper::~CallMethodHelper()
{
for (nsXPTCVariant& param : mDispatchParams) {
// Only clean up values which need cleanup.
if (!param.DoesValNeedCleanup())
continue;
uint32_t arraylen = 0;
if (!GetArraySizeFromParam(param.type, UndefinedHandleValue, &arraylen))
continue;
@ -1262,7 +1258,7 @@ CallMethodHelper::GetArraySizeFromParam(const nsXPTType& type,
HandleValue maybeArray,
uint32_t* result)
{
if (type.Tag() != nsXPTType::T_ARRAY &&
if (type.Tag() != nsXPTType::T_LEGACY_ARRAY &&
type.Tag() != nsXPTType::T_PSTRING_SIZE_IS &&
type.Tag() != nsXPTType::T_PWSTRING_SIZE_IS) {
*result = 0;
@ -1477,25 +1473,39 @@ CallMethodHelper::InitializeDispatchParams()
mJSContextIndex = mMethodInfo->IndexOfJSContext();
// iterate through the params to clear flags (for safe cleanup later)
for (uint8_t i = 0; i < paramCount + wantsJSContext + wantsOptArgc; i++) {
nsXPTCVariant* dp = mDispatchParams.AppendElement();
dp->ClearFlags();
dp->val.p = nullptr;
// Allocate enough space in mDispatchParams up-front.
if (!mDispatchParams.AppendElements(paramCount + wantsJSContext + wantsOptArgc)) {
Throw(NS_ERROR_OUT_OF_MEMORY, mCallContext);
return false;
}
// Fill in the JSContext argument
if (wantsJSContext) {
nsXPTCVariant* dp = &mDispatchParams[mJSContextIndex];
dp->type = nsXPTType::T_VOID;
dp->val.p = mCallContext;
}
// Initialize each parameter to a valid state (for safe cleanup later).
for (uint8_t i = 0, paramIdx = 0; i < mDispatchParams.Length(); i++) {
nsXPTCVariant& dp = mDispatchParams[i];
// Fill in the optional_argc argument
if (wantsOptArgc) {
nsXPTCVariant* dp = &mDispatchParams[mOptArgcIndex];
dp->type = nsXPTType::T_U8;
dp->val.u8 = std::min<uint32_t>(mArgc, paramCount) - requiredArgs;
if (i == mJSContextIndex) {
// Fill in the JSContext argument
dp.type = nsXPTType::T_VOID;
dp.val.p = mCallContext;
} else if (i == mOptArgcIndex) {
// Fill in the optional_argc argument
dp.type = nsXPTType::T_U8;
dp.val.u8 = std::min<uint32_t>(mArgc, paramCount) - requiredArgs;
} else {
// Initialize normal arguments.
const nsXPTParamInfo& param = mMethodInfo->Param(paramIdx);
dp.type = param.Type();
xpc::InitializeValue(dp.type, &dp.val);
// Specify the correct storage/calling semantics. This will also set
// the `ptr` field to be self-referential.
if (param.IsIndirect()) {
dp.SetIndirect();
}
// Advance to the next normal parameter.
paramIdx++;
}
}
return true;
@ -1522,40 +1532,8 @@ bool
CallMethodHelper::ConvertIndependentParam(uint8_t i)
{
const nsXPTParamInfo& paramInfo = mMethodInfo->GetParam(i);
const nsXPTType& type = paramInfo.GetType();
const nsXPTType& type = paramInfo.Type();
nsXPTCVariant* dp = GetDispatchParam(i);
dp->type = type;
MOZ_ASSERT(!paramInfo.IsShared(), "[shared] implies [noscript]!");
// Specify the correct storage/calling semantics.
if (paramInfo.IsIndirect())
dp->SetIndirect();
// Some types are always stored within the nsXPTCVariant, and passed
// indirectly, regardless of in/out-ness. These types are stored in the
// nsXPTCVariant's extended value.
switch (type.Tag()) {
// Ensure that the jsval has a valid value.
case nsXPTType::T_JSVAL:
new (&dp->ext.jsval) JS::Value();
MOZ_ASSERT(dp->ext.jsval.isUndefined());
break;
// Initialize our temporary string class values so they can be assigned
// to by the XPCConvert logic.
case nsXPTType::T_ASTRING:
case nsXPTType::T_DOMSTRING:
new (&dp->ext.nsstr) nsString();
break;
case nsXPTType::T_CSTRING:
case nsXPTType::T_UTF8STRING:
new (&dp->ext.nscstr) nsCString();
break;
}
// Flag cleanup for anything that isn't self-contained.
if (!type.IsArithmetic())
dp->SetValNeedsCleanup();
// Even if there's nothing to convert, we still need to examine the
// JSObject container for out-params. If it's null or otherwise invalid,
@ -1641,18 +1619,8 @@ bool
CallMethodHelper::ConvertDependentParam(uint8_t i)
{
const nsXPTParamInfo& paramInfo = mMethodInfo->GetParam(i);
const nsXPTType& type = paramInfo.GetType();
const nsXPTType& type = paramInfo.Type();
nsXPTCVariant* dp = GetDispatchParam(i);
dp->type = type;
// Specify the correct storage/calling semantics.
if (paramInfo.IsIndirect())
dp->SetIndirect();
// Make sure we clean up all of our dependent types. All of them require
// allocations of some kind.
dp->SetValNeedsCleanup();
// Even if there's nothing to convert, we still need to examine the
// JSObject container for out-params. If it's null or otherwise invalid,
@ -1712,14 +1680,18 @@ TraceParam(JSTracer* aTrc, void* aVal, const nsXPTType& aType,
if (aType.Tag() == nsXPTType::T_JSVAL) {
JS::UnsafeTraceRoot(aTrc, (JS::Value*)aVal,
"XPCWrappedNative::CallMethod param");
} else if (aType.Tag() == nsXPTType::T_ARRAY && *(void**)aVal) {
} else if (aType.Tag() == nsXPTType::T_ARRAY) {
auto* array = (xpt::detail::UntypedTArray*)aVal;
const nsXPTType& elty = aType.ArrayElementType();
if (elty.Tag() != nsXPTType::T_JSVAL) {
return;
for (uint32_t i = 0; i < array->Length(); ++i) {
TraceParam(aTrc, elty.ElementPtr(array->Elements(), i), elty);
}
} else if (aType.Tag() == nsXPTType::T_LEGACY_ARRAY && *(void**)aVal) {
const nsXPTType& elty = aType.ArrayElementType();
for (uint32_t i = 0; i < aArrayLen; ++i) {
TraceParam(aTrc, elty.ElementPtr(aVal, i), elty);
TraceParam(aTrc, elty.ElementPtr(*(void**)aVal, i), elty);
}
}
}
@ -1729,9 +1701,8 @@ CallMethodHelper::trace(JSTracer* aTrc)
{
// We need to note each of our initialized parameters which contain jsvals.
for (nsXPTCVariant& param : mDispatchParams) {
if (!param.DoesValNeedCleanup()) {
MOZ_ASSERT(param.type.Tag() != nsXPTType::T_JSVAL,
"JSVals are marked as needing cleanup (even though they don't)");
// We only need to trace parameters which have an innermost JSVAL.
if (param.type.InnermostType().Tag() != nsXPTType::T_JSVAL) {
continue;
}

View File

@ -1963,31 +1963,6 @@ public:
// for the WN case. You probably want UnwrapReflectorToISupports.
static bool GetISupportsFromJSObject(JSObject* obj, nsISupports** iface);
/**
* Convert a native array into a JS::Value.
*
* @param d [out] the resulting JS::Value
* @param s the native array we're working with
* @param type the type of objects in the array
* @param iid the interface of each object in the array that we want
* @param count the number of items in the array
* @param scope the default scope to put on the new JSObjects' parent chain
* @param pErr [out] relevant error code, if any.
*/
static bool NativeArray2JS(JS::MutableHandleValue d, const void* const* s,
const nsXPTType& type, const nsID* iid,
uint32_t count, nsresult* pErr);
static bool JSArray2Native(void** d, JS::HandleValue s,
uint32_t count, const nsXPTType& type,
const nsID* iid, nsresult* pErr);
static bool JSTypedArray2Native(void** d,
JSObject* jsarray,
uint32_t count,
const nsXPTType& type,
nsresult* pErr);
static nsresult JSValToXPCException(JS::MutableHandleValue s,
const char* ifaceName,
const char* methodName,
@ -2002,6 +1977,40 @@ public:
JS::Value* jsExceptionPtr);
private:
/**
* Convert a native array into a JS::Value.
*
* @param d [out] the resulting JS::Value
* @param buf the native buffer containing input values
* @param type the type of objects in the array
* @param iid the interface of each object in the array that we want
* @param count the number of items in the array
* @param scope the default scope to put on the new JSObjects' parent chain
* @param pErr [out] relevant error code, if any.
*/
static bool NativeArray2JS(JS::MutableHandleValue d, const void* buf,
const nsXPTType& type, const nsID* iid,
uint32_t count, nsresult* pErr);
typedef std::function<void* (uint32_t*)> ArrayAllocFixupLen;
/**
* Convert a JS::Value into a native array.
*
* @param aJSVal the JS::Value to convert
* @param aEltType the type of objects in the array
* @param aIID the interface of each object in the array
* @param pErr [out] relevant error code, if any
* @param aAllocFixupLen function called with the JS Array's length to
* allocate the backing buffer. This function may
* modify the length of array to be converted.
*/
static bool JSArray2Native(JS::HandleValue aJSVal,
const nsXPTType& aEltType,
const nsIID* aIID,
nsresult* pErr,
const ArrayAllocFixupLen& aAllocFixupLen);
XPCConvert() = delete;
};
@ -3039,7 +3048,7 @@ nsIPrincipal* GetObjectPrincipal(JSObject* obj);
// value : char[16_t]** (free)
// TD_INTERFACE_TYPE, TD_INTERFACE_IS_TYPE
// value : nsISupports** (release)
// TD_ARRAY (NOTE: aArrayLen should be passed)
// TD_LEGACY_ARRAY (NOTE: aArrayLen should be passed)
// value : void** (cleanup elements & free)
// TD_DOMOBJECT
// value : T** (cleanup)
@ -3060,6 +3069,17 @@ void InnerCleanupValue(const nsXPTType& aType,
void* aValue,
uint32_t aArrayLen);
// In order to be able to safely call CleanupValue on a generated value, the
// data behind it needs to be initialized to a safe value. This method handles
// initializing the backing data to a safe value to use as an argument to
// XPCConvert methods, or xpc::CleanupValue.
//
// The pointer `aValue` must point to a block of memory at least aType.Stride()
// bytes large, and correctly aligned.
//
// This method accepts the same types as xpc::CleanupValue.
void InitializeValue(const nsXPTType& aType, void* aValue);
} // namespace xpc
namespace mozilla {

View File

@ -64,11 +64,19 @@ TestParams.prototype = {
testAUTF8String: f,
testACString: f,
testJsval: f,
testShortSequence: f,
testDoubleSequence: f,
testAStringSequence: f,
testACStringSequence: f,
testInterfaceSequence: f,
testJsvalSequence: f,
testInterfaceIsSequence: f_is,
testShortArray: f_is,
testDoubleArray: f_is,
testStringArray: f_is,
testWstringArray: f_is,
testInterfaceArray: f_is,
testJsvalArray: f_is,
testSizedString: f_is,
testSizedWstring: f_is,
testInterfaceIs: f_is,

View File

@ -28,6 +28,14 @@ nsXPCTestParams::~nsXPCTestParams()
return NS_OK; \
}
#define SEQUENCE_METHOD_IMPL(TAKE_OWNERSHIP) { \
_retval.SwapElements(b); \
b = a; \
for (uint32_t i = 0; i < b.Length(); ++i) \
TAKE_OWNERSHIP(b[i]); \
return NS_OK; \
}
#define TAKE_OWNERSHIP_NOOP(val) {}
#define TAKE_OWNERSHIP_INTERFACE(val) {static_cast<nsISupports*>(val)->AddRef();}
#define TAKE_OWNERSHIP_STRING(val) { \
@ -223,6 +231,13 @@ NS_IMETHODIMP nsXPCTestParams::TestInterfaceArray(uint32_t aLength, nsIXPCTestIn
BUFFER_METHOD_IMPL(nsIXPCTestInterfaceA*, 0, TAKE_OWNERSHIP_INTERFACE);
}
NS_IMETHODIMP nsXPCTestParams::TestJsvalArray(uint32_t aLength, JS::Value *a,
uint32_t* bLength, JS::Value **b,
uint32_t* rvLength, JS::Value **rv)
{
BUFFER_METHOD_IMPL(JS::Value, 0, TAKE_OWNERSHIP_NOOP);
}
NS_IMETHODIMP nsXPCTestParams::TestSizedString(uint32_t aLength, const char * a,
uint32_t* bLength, char * *b,
uint32_t* rvLength, char * *rv)
@ -306,3 +321,68 @@ NS_IMETHODIMP nsXPCTestParams::TestStringArrayOptionalSize(const char * *a, uint
return NS_OK;
}
NS_IMETHODIMP
nsXPCTestParams::TestShortSequence(const nsTArray<short>& a, nsTArray<short>& b, nsTArray<short>& _retval)
{
SEQUENCE_METHOD_IMPL(TAKE_OWNERSHIP_NOOP);
}
NS_IMETHODIMP
nsXPCTestParams::TestDoubleSequence(const nsTArray<double>& a, nsTArray<double>& b, nsTArray<double>& _retval)
{
SEQUENCE_METHOD_IMPL(TAKE_OWNERSHIP_NOOP);
}
NS_IMETHODIMP
nsXPCTestParams::TestInterfaceSequence(const nsTArray<RefPtr<nsIXPCTestInterfaceA>>& a,
nsTArray<RefPtr<nsIXPCTestInterfaceA>>& b,
nsTArray<RefPtr<nsIXPCTestInterfaceA>>& _retval)
{
SEQUENCE_METHOD_IMPL(TAKE_OWNERSHIP_NOOP);
}
NS_IMETHODIMP
nsXPCTestParams::TestAStringSequence(const nsTArray<nsString>& a,
nsTArray<nsString>& b,
nsTArray<nsString>& _retval)
{
SEQUENCE_METHOD_IMPL(TAKE_OWNERSHIP_NOOP);
}
NS_IMETHODIMP
nsXPCTestParams::TestACStringSequence(const nsTArray<nsCString>& a,
nsTArray<nsCString>& b,
nsTArray<nsCString>& _retval)
{
SEQUENCE_METHOD_IMPL(TAKE_OWNERSHIP_NOOP);
}
NS_IMETHODIMP
nsXPCTestParams::TestJsvalSequence(const nsTArray<JS::Value>& a,
nsTArray<JS::Value>& b,
nsTArray<JS::Value>& _retval)
{
SEQUENCE_METHOD_IMPL(TAKE_OWNERSHIP_NOOP);
}
NS_IMETHODIMP
nsXPCTestParams::TestSequenceSequence(const nsTArray<nsTArray<short>>& a,
nsTArray<nsTArray<short>>& b,
nsTArray<nsTArray<short>>& _retval)
{
SEQUENCE_METHOD_IMPL(TAKE_OWNERSHIP_NOOP);
}
NS_IMETHODIMP
nsXPCTestParams::TestInterfaceIsSequence(const nsIID* aIID, const nsTArray<void*>& a,
nsIID** bIID, nsTArray<void*>& b,
nsIID** rvIID, nsTArray<void*>& _retval)
{
// Shuffle around our nsIIDs
*rvIID = (*bIID)->Clone();
*bIID = aIID->Clone();
// Perform the generic sequence shuffle.
SEQUENCE_METHOD_IMPL(TAKE_OWNERSHIP_INTERFACE);
}

View File

@ -39,6 +39,19 @@ interface nsIXPCTestParams : nsISupports {
ACString testACString(in ACString a, inout ACString b);
jsval testJsval(in jsval a, inout jsval b);
// Test various forms of the Array<T> type.
Array<short> testShortSequence(in Array<short> a, inout Array<short> b);
Array<double> testDoubleSequence(in Array<double> a, inout Array<double> b);
Array<nsIXPCTestInterfaceA> testInterfaceSequence(in Array<nsIXPCTestInterfaceA> a, inout Array<nsIXPCTestInterfaceA> b);
Array<AString> testAStringSequence(in Array<AString> a, inout Array<AString> b);
Array<ACString> testACStringSequence(in Array<ACString> a, inout Array<ACString> b);
Array<jsval> testJsvalSequence(in Array<jsval> a, inout Array<jsval> b);
Array<Array<short> > testSequenceSequence(in Array<Array<short> > a, inout Array<Array<short> > b);
void testInterfaceIsSequence(in nsIIDPtr aIID, [iid_is(aIID)] in Array<nsQIResult> a,
inout nsIIDPtr bIID, [iid_is(bIID)] inout Array<nsQIResult> b,
out nsIIDPtr rvIID, [retval, iid_is(rvIID)] out Array<nsQIResult> rv);
//
// Dependent parameters use the same types as above, but are handled much differently.
//
@ -82,6 +95,12 @@ interface nsIXPCTestParams : nsISupports {
out unsigned long rvLength, out nsIIDPtr rvIID,
[retval, array, size_is(rvLength), iid_is(rvIID)] out nsQIResult rv);
// Test arrays of jsvals
void testJsvalArray(in unsigned long aLength, [array, size_is(aLength)] in jsval a,
inout unsigned long bLength, [array, size_is(bLength)] inout jsval b,
out unsigned long rvLength, [retval, array, size_is(rvLength)] out jsval rv);
// Test for out dipper parameters
void testOutAString(out AString o);

View File

@ -163,6 +163,8 @@ function test_component(contractid) {
["we", "are", "being", "sooo", "international", "right", "now"], 7, arrayComparator(standardComparator));
doIsTest("testInterfaceArray", [makeA(), makeA()], 2,
[makeA(), makeA(), makeA(), makeA(), makeA(), makeA()], 6, arrayComparator(interfaceComparator));
doIsTest("testJsvalArray", [{ cheese: 'whiz', apple: 8 }, [1, 5, '3'], /regex/], 3,
['apple', 2.2e10, 3.3e30, { only: "wheedle", except: {} }], 4, arrayComparator(standardComparator));
// Test typed arrays and ArrayBuffer aliasing.
var arrayBuffer = new ArrayBuffer(16);
@ -195,4 +197,24 @@ function test_component(contractid) {
// Test type mismatch (int16 <-> uint16); this should throw BAD_CONVERT_JS.
doTypedArrayMismatchTest("testShortArray", new Uint16Array([0, 7, 4, 3]), 4,
new Uint16Array([1, 5, 6]), 3);
// Test Sequence<T> types.
doTest("testShortSequence", [2, 4, 6], [1, 3, 5, 7], arrayComparator(standardComparator));
doTest("testDoubleSequence", [-10, -0.5], [1, 3, 1e11, -8e-5 ], arrayComparator(fuzzComparator));
doTest("testACStringSequence", ["mary", "hat", "hey", "lid", "tell", "lam"],
["ids", "fleas", "woes", "wide", "has", "know", "!"],
arrayComparator(standardComparator));
doTest("testAStringSequence", ["沒有語言", "的偉大嗎?]"],
["we", "are", "being", "sooo", "international", "right", "now"],
arrayComparator(standardComparator));
doTest("testInterfaceSequence", [makeA(), makeA()],
[makeA(), makeA(), makeA(), makeA(), makeA(), makeA()], arrayComparator(interfaceComparator));
doTest("testJsvalSequence", [{ cheese: 'whiz', apple: 8 }, [1, 5, '3'], /regex/],
['apple', 2.2e10, 3.3e30, { only: "wheedle", except: {} }], arrayComparator(standardComparator));
doIsTest("testInterfaceIsSequence", [makeA(), makeA(), makeA(), makeA(), makeA()], Ci['nsIXPCTestInterfaceA'],
[makeB(), makeB(), makeB()], Ci['nsIXPCTestInterfaceB'],
arrayComparator(interfaceComparator), dotEqualsComparator);
}

View File

@ -264,7 +264,7 @@ fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)||skiaContent,1,800000) == ma
== marker-effects-01.svg marker-effects-01-ref.svg
fuzzy-if(skiaContent,1,100) == marker-viewBox-01.svg marker-viewBox-01-ref.svg
fuzzy-if(skiaContent,1,100) == marker-orientation-01.svg marker-orientation-01-ref.svg
fuzzy-if(skiaContent,1,5) pref(svg.marker-improvements.enabled,true) == marker-orientation-02.svg marker-orientation-02-ref.svg
fuzzy-if(skiaContent,1,5) == marker-orientation-02.svg marker-orientation-02-ref.svg
== marker-orientation-03.svg pass.svg
== marker-orientation-04.svg pass.svg
@ -551,4 +551,4 @@ fuzzy-if(skiaContent,1,100) == tspan-xy-anchor-end-01.svg tspan-xy-anchor-end-re
# currentColor override by color attribute
== currentColor-override-flood.svg pass.svg
== currentColor-override-lighting.svg currentColor-override-lighting-ref.svg
== currentColor-override-stop.svg pass.svg
== currentColor-override-stop.svg pass.svg

View File

@ -78,6 +78,8 @@ enum class StyleAppearance : uint8_t {
Meterbar,
// The meter bar's meter indicator.
Meterchunk,
// The dropdown button(s) that open up a dropdown list.
MozMenulistButton,
// For HTML's <input type=number>
NumberInput,
// A horizontal progress bar.

View File

@ -284,7 +284,7 @@ select > button {
background-image: url("arrow.gif") !important;
background-repeat: no-repeat !important;
background-position: center !important;
-moz-appearance: menulist-button;
-moz-appearance: -moz-menulist-button;
/* Make sure to size correctly if the combobox has a non-auto height. */
block-size: 100% ! important;

View File

@ -16,6 +16,9 @@ const NON_CONTENT_ACCESSIBLE_VALUES = {
"-moz-popup",
"-moz-groupbox",
],
"-moz-appearance": [
"-moz-menulist-button",
],
};
if (!SpecialPowers.getBoolPref("layout.css.xul-box-display-values.content.enabled")) {

View File

@ -30,18 +30,17 @@
#endif
#include "nscore.h"
#include "mozilla/StackWalk.h"
#include "js/HashTable.h"
#include "js/Vector.h"
#include "mozilla/Assertions.h"
#include "mozilla/FastBernoulliTrial.h"
#include "mozilla/HashFunctions.h"
#include "mozilla/HashTable.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/JSONWriter.h"
#include "mozilla/Likely.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/StackWalk.h"
#include "mozilla/Vector.h"
// CodeAddressService is defined entirely in the header, so this does not make
// DMD depend on XPCOM's object file.
@ -96,8 +95,8 @@ static malloc_table_t gMallocTable;
//
// - Direct allocations (the easy case).
//
// - Indirect allocations in js::{Vector,HashSet,HashMap} -- this class serves
// as their AllocPolicy.
// - Indirect allocations in mozilla::{Vector,HashSet,HashMap} -- this class
// serves as their AllocPolicy.
//
// - Other indirect allocations (e.g. MozStackWalk) -- see the comments on
// Thread::mBlockIntercepts and in replace_malloc for how these work.
@ -162,7 +161,6 @@ public:
return p;
}
// This realloc_ is the one we use for direct reallocs within DMD.
static void* realloc_(void* aPtr, size_t aNewSize)
{
void* p = gMallocTable.realloc(aPtr, aNewSize);
@ -170,7 +168,6 @@ public:
return p;
}
// This realloc_ is required for this to be a JS container AllocPolicy.
template <typename T>
static T* pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize)
{
@ -621,7 +618,7 @@ private:
{
typedef const char* Lookup;
static uint32_t hash(const char* const& aS)
static mozilla::HashNumber hash(const char* const& aS)
{
return HashString(aS);
}
@ -632,7 +629,8 @@ private:
}
};
typedef js::HashSet<const char*, StringHasher, InfallibleAllocPolicy> StringHashSet;
typedef mozilla::HashSet<const char*, StringHasher, InfallibleAllocPolicy>
StringHashSet;
StringHashSet mSet;
};
@ -693,7 +691,7 @@ public:
typedef StackTrace* Lookup;
static uint32_t hash(const StackTrace* const& aSt)
static mozilla::HashNumber hash(const StackTrace* const& aSt)
{
return mozilla::HashBytes(aSt->mPcs, aSt->Size());
}
@ -717,19 +715,21 @@ private:
}
};
typedef js::HashSet<StackTrace*, StackTrace, InfallibleAllocPolicy>
typedef mozilla::HashSet<StackTrace*, StackTrace, InfallibleAllocPolicy>
StackTraceTable;
static StackTraceTable* gStackTraceTable = nullptr;
typedef js::HashSet<const StackTrace*, js::DefaultHasher<const StackTrace*>,
InfallibleAllocPolicy>
typedef mozilla::HashSet<const StackTrace*,
mozilla::DefaultHasher<const StackTrace*>,
InfallibleAllocPolicy>
StackTraceSet;
typedef js::HashSet<const void*, js::DefaultHasher<const void*>,
InfallibleAllocPolicy>
typedef mozilla::HashSet<const void*, mozilla::DefaultHasher<const void*>,
InfallibleAllocPolicy>
PointerSet;
typedef js::HashMap<const void*, uint32_t, js::DefaultHasher<const void*>,
InfallibleAllocPolicy>
typedef mozilla::HashMap<const void*, uint32_t,
mozilla::DefaultHasher<const void*>,
InfallibleAllocPolicy>
PointerIdMap;
// We won't GC the stack trace table until it this many elements.
@ -992,7 +992,7 @@ public:
typedef const void* Lookup;
static uint32_t hash(const void* const& aPtr)
static mozilla::HashNumber hash(const void* const& aPtr)
{
return mozilla::HashGeneric(aPtr);
}
@ -1004,7 +1004,8 @@ public:
};
// A table of live blocks where the lookup key is the block address.
typedef js::HashSet<LiveBlock, LiveBlock, InfallibleAllocPolicy> LiveBlockTable;
typedef mozilla::HashSet<LiveBlock, LiveBlock, InfallibleAllocPolicy>
LiveBlockTable;
static LiveBlockTable* gLiveBlockTable = nullptr;
class AggregatedLiveBlockHashPolicy
@ -1012,7 +1013,7 @@ class AggregatedLiveBlockHashPolicy
public:
typedef const LiveBlock* const Lookup;
static uint32_t hash(const LiveBlock* const& aB)
static mozilla::HashNumber hash(const LiveBlock* const& aB)
{
return gOptions->IsDarkMatterMode()
? mozilla::HashGeneric(aB->ReqSize(),
@ -1041,8 +1042,8 @@ public:
// A table of live blocks where the lookup key is everything but the block
// address. For aggregating similar live blocks at output time.
typedef js::HashMap<const LiveBlock*, size_t, AggregatedLiveBlockHashPolicy,
InfallibleAllocPolicy>
typedef mozilla::HashMap<const LiveBlock*, size_t,
AggregatedLiveBlockHashPolicy, InfallibleAllocPolicy>
AggregatedLiveBlockTable;
// A freed heap block.
@ -1088,7 +1089,7 @@ public:
typedef DeadBlock Lookup;
static uint32_t hash(const DeadBlock& aB)
static mozilla::HashNumber hash(const DeadBlock& aB)
{
return mozilla::HashGeneric(aB.ReqSize(),
aB.SlopSize(),
@ -1105,7 +1106,7 @@ public:
// For each unique DeadBlock value we store a count of how many actual dead
// blocks have that value.
typedef js::HashMap<DeadBlock, size_t, DeadBlock, InfallibleAllocPolicy>
typedef mozilla::HashMap<DeadBlock, size_t, DeadBlock, InfallibleAllocPolicy>
DeadBlockTable;
static DeadBlockTable* gDeadBlockTable = nullptr;

File diff suppressed because it is too large Load Diff

View File

@ -3279,9 +3279,6 @@ pref("browser.tabs.remote.separatePrivilegedContentProcess", false);
pref("svg.display-lists.hit-testing.enabled", true);
pref("svg.display-lists.painting.enabled", true);
// Is support for the <marker orient="auto-start-reverse"> feature enabled?
pref("svg.marker-improvements.enabled", true);
// Is support for the new getBBox method from SVG 2 enabled?
// See https://svgwg.org/svg2-draft/single-page.html#types-SVGBoundingBoxOptions
pref("svg.new-getBBox.enabled", false);

View File

@ -122,6 +122,14 @@ public:
return true;
}
#if defined(_M_IX86)
bool WriteAtomic(void* aDestPtr, const uint16_t aValue) const
{
*static_cast<uint16_t*>(aDestPtr) = aValue;
return true;
}
#endif // defined(_M_IX86)
bool Protect(void* aVAddress, size_t aSize, uint32_t aProtFlags,
uint32_t* aPrevProtFlags) const
{

View File

@ -51,8 +51,7 @@ public:
}
// mov edi, edi
fn.WriteShort(0xff8b);
fn.Commit();
fn.CommitAndWriteShort(0xff8b);
}
mPatchedFns.clear();
@ -206,8 +205,7 @@ public:
sizeof(uint16_t));
// Short jump up into our long jump.
writableFn.WriteShort(0xF9EB); // jmp $-5
return writableFn.Commit();
return writableFn.CommitAndWriteShort(0xF9EB); // jmp $-5
}
};

View File

@ -177,6 +177,9 @@ public:
}
mMMPolicy.FlushInstructionCache();
mStartWriteOffset += mLocalBytes.length();
mLocalBytes.clear();
return true;
}
@ -228,6 +231,53 @@ public:
mOffset += sizeof(uint16_t);
}
#if defined(_M_IX86)
private:
template <typename T>
bool CommitAndWriteShortInternal(const T& aMMPolicy, void* aDest, uint16_t aValue);
template <>
bool CommitAndWriteShortInternal<MMPolicyInProcess>(const MMPolicyInProcess& aMMPolicy,
void* aDest, uint16_t aValue)
{
return aMMPolicy.WriteAtomic(aDest, aValue);
}
template <>
bool CommitAndWriteShortInternal<MMPolicyOutOfProcess>(const MMPolicyOutOfProcess& aMMPolicy,
void* aDest, uint16_t aValue)
{
return aMMPolicy.Write(aDest, &aValue, sizeof(uint16_t));
}
public:
/**
* Commits any dirty writes, and then writes a short, atomically if possible.
* This call may succeed in both inproc and outproc cases, but atomicity
* is only guaranteed in the inproc case.
*/
bool CommitAndWriteShort(const uint16_t aValue)
{
// First, commit everything that has been written until now
if (!Commit()) {
return false;
}
// Now immediately write the short, atomically if inproc
bool ok = CommitAndWriteShortInternal(mMMPolicy,
reinterpret_cast<void*>(mFunc +
mStartWriteOffset),
aValue);
if (!ok) {
return false;
}
mMMPolicy.FlushInstructionCache();
mStartWriteOffset += sizeof(uint16_t);
return true;
}
#endif // defined(_M_IX86)
void WriteDisp32(const uintptr_t aAbsTarget)
{
intptr_t diff = static_cast<intptr_t>(aAbsTarget) -

View File

@ -82,6 +82,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
, mInitialSecurityCheckDone(false)
, mIsThirdPartyContext(false)
, mIsDocshellReload(false)
, mSendCSPViolationEvents(true)
, mForcePreflight(false)
, mIsPreflight(false)
, mLoadTriggeredFromExternal(false)
@ -315,6 +316,7 @@ LoadInfo::LoadInfo(nsPIDOMWindowOuter* aOuterWindow,
, mInitialSecurityCheckDone(false)
, mIsThirdPartyContext(false) // NB: TYPE_DOCUMENT implies not third-party.
, mIsDocshellReload(false)
, mSendCSPViolationEvents(true)
, mForcePreflight(false)
, mIsPreflight(false)
, mLoadTriggeredFromExternal(false)
@ -401,6 +403,7 @@ LoadInfo::LoadInfo(const LoadInfo& rhs)
, mInitialSecurityCheckDone(rhs.mInitialSecurityCheckDone)
, mIsThirdPartyContext(rhs.mIsThirdPartyContext)
, mIsDocshellReload(rhs.mIsDocshellReload)
, mSendCSPViolationEvents(rhs.mSendCSPViolationEvents)
, mOriginAttributes(rhs.mOriginAttributes)
, mRedirectChainIncludingInternalRedirects(
rhs.mRedirectChainIncludingInternalRedirects)
@ -447,6 +450,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
bool aInitialSecurityCheckDone,
bool aIsThirdPartyContext,
bool aIsDocshellReload,
bool aSendCSPViolationEvents,
const OriginAttributes& aOriginAttributes,
RedirectHistoryArray& aRedirectChainIncludingInternalRedirects,
RedirectHistoryArray& aRedirectChain,
@ -488,6 +492,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
, mInitialSecurityCheckDone(aInitialSecurityCheckDone)
, mIsThirdPartyContext(aIsThirdPartyContext)
, mIsDocshellReload(aIsDocshellReload)
, mSendCSPViolationEvents(aSendCSPViolationEvents)
, mOriginAttributes(aOriginAttributes)
, mAncestorPrincipals(std::move(aAncestorPrincipals))
, mAncestorOuterWindowIDs(aAncestorOuterWindowIDs)
@ -839,6 +844,20 @@ LoadInfo::SetIsDocshellReload(bool aValue)
return NS_OK;
}
NS_IMETHODIMP
LoadInfo::GetSendCSPViolationEvents(bool* aResult)
{
*aResult = mSendCSPViolationEvents;
return NS_OK;
}
NS_IMETHODIMP
LoadInfo::SetSendCSPViolationEvents(bool aValue)
{
mSendCSPViolationEvents = aValue;
return NS_OK;
}
NS_IMETHODIMP
LoadInfo::GetExternalContentPolicyType(nsContentPolicyType* aResult)
{

View File

@ -124,6 +124,7 @@ private:
bool aInitialSecurityCheckDone,
bool aIsThirdPartyRequest,
bool aIsDocshellReload,
bool aSendCSPViolationEvents,
const OriginAttributes& aOriginAttributes,
RedirectHistoryArray& aRedirectChainIncludingInternalRedirects,
RedirectHistoryArray& aRedirectChain,
@ -194,6 +195,7 @@ private:
bool mInitialSecurityCheckDone;
bool mIsThirdPartyContext;
bool mIsDocshellReload;
bool mSendCSPViolationEvents;
OriginAttributes mOriginAttributes;
RedirectHistoryArray mRedirectChainIncludingInternalRedirects;
RedirectHistoryArray mRedirectChain;

View File

@ -502,6 +502,12 @@ interface nsILoadInfo : nsISupports
*/
readonly attribute nsContentPolicyType externalContentPolicyType;
/**
* CSP uses this parameter to send or not CSP violation events.
* Default value: true.
*/
[infallible] attribute boolean sendCSPViolationEvents;
%{ C++
inline nsContentPolicyType GetExternalContentPolicyType()
{

View File

@ -65,6 +65,7 @@ struct LoadInfoArgs
bool initialSecurityCheckDone;
bool isInThirdPartyContext;
bool isDocshellReload;
bool sendCSPViolationEvents;
OriginAttributes originAttributes;
RedirectHistoryEntryInfo[] redirectChainIncludingInternalRedirects;
RedirectHistoryEntryInfo[] redirectChain;

View File

@ -515,7 +515,6 @@ ${helpers.predefined_type(
products="gecko",
alias="-webkit-appearance:layout.css.webkit-appearance.enabled",
spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-appearance)",
needs_context=False,
animation_value_type="discrete",
)}

View File

@ -20,11 +20,16 @@ use values::specified::{AllowQuirks, Number};
use values::specified::length::{LengthOrPercentage, NonNegativeLength};
#[cfg(feature = "gecko")]
fn moz_display_values_enabled(context: &ParserContext) -> bool {
use gecko_bindings::structs;
fn in_ua_or_chrome_sheet(context: &ParserContext) -> bool {
use stylesheets::Origin;
context.stylesheet_origin == Origin::UserAgent ||
context.chrome_rules_enabled() ||
context.chrome_rules_enabled()
}
#[cfg(feature = "gecko")]
fn moz_display_values_enabled(context: &ParserContext) -> bool {
use gecko_bindings::structs;
in_ua_or_chrome_sheet(context) ||
unsafe {
structs::StaticPrefs_sVarCache_layout_css_xul_display_values_content_enabled
}
@ -33,9 +38,7 @@ fn moz_display_values_enabled(context: &ParserContext) -> bool {
#[cfg(feature = "gecko")]
fn moz_box_display_values_enabled(context: &ParserContext) -> bool {
use gecko_bindings::structs;
use stylesheets::Origin;
context.stylesheet_origin == Origin::UserAgent ||
context.chrome_rules_enabled() ||
in_ua_or_chrome_sheet(context) ||
unsafe {
structs::StaticPrefs_sVarCache_layout_css_xul_box_display_values_content_enabled
}
@ -948,6 +951,9 @@ pub enum Appearance {
Meterbar,
/// The meter bar's meter indicator.
Meterchunk,
/// The "arrowed" part of the dropdown button that open up a dropdown list.
#[parse(condition = "in_ua_or_chrome_sheet")]
MozMenulistButton,
/// For HTML's <input type=number>
NumberInput,
/// A horizontal progress bar.

View File

@ -42,6 +42,10 @@ jobs:
- releases/bouncer_firefox_beta.py
mozilla-release:
- releases/bouncer_firefox_release.py
mozilla-esr60:
- releases/bouncer_firefox_esr.py
jamun:
- releases/dev_bouncer_firefox_esr.py
default:
- releases/dev_bouncer_firefox_beta.py
product-field:

View File

@ -30,8 +30,10 @@ jobs:
by-project:
maple: [32]
birch: [145]
jamun: [724]
mozilla-beta: [32]
mozilla-release: [145]
mozilla-esr60: [806]
default: []
treeherder:
platform: firefox-release/opt

View File

@ -28,32 +28,40 @@ jobs:
by-project:
mozilla-beta: archive.mozilla.org
mozilla-release: archive.mozilla.org
mozilla-esr60: archive.mozilla.org
default: ftp.stage.mozaws.net
download-domain:
by-project:
mozilla-beta: download.mozilla.org
mozilla-release: download.mozilla.org
mozilla-esr60: download.mozilla.org
default: download.mozilla.org
channel-names:
by-project:
maple: ["beta", "beta-localtest", "beta-cdntest"]
birch: ["release", "release-localtest", "release-cdntest"]
jamun: ["esr", "esr-localtest", "esr-cdntest"]
mozilla-beta: ["beta", "beta-localtest", "beta-cdntest"]
mozilla-release: ["release", "release-localtest", "release-cdntest"]
mozilla-esr60: ["esr", "esr-localtest", "esr-cdntest"]
default: []
publish-rules:
by-project:
maple: [32]
birch: [145]
jamun: [724]
mozilla-beta: [32]
mozilla-release: [145]
mozilla-esr60: [806]
default: []
rules-to-update:
by-project:
maple: ["firefox-beta-cdntest", "firefox-beta-localtest"]
birch: ["firefox-release-cdntest", "firefox-release-localtest"]
jamun: ["firefox-esr60-cdntest", "firefox-esr60-localtest"]
mozilla-beta: ["firefox-beta-cdntest", "firefox-beta-localtest"]
mozilla-release: ["firefox-release-cdntest", "firefox-release-localtest"]
mozilla-esr60: ["firefox-esr60-cdntest", "firefox-esr60-localtest"]
default: []
platforms: ["linux", "linux64", "macosx64", "win32", "win64"]
treeherder:

View File

@ -14,6 +14,7 @@ job-defaults:
by-project:
mozilla-beta: scriptworker-prov-v1/bouncer-v1
mozilla-release: scriptworker-prov-v1/bouncer-v1
mozilla-esr60: scriptworker-prov-v1/bouncer-v1
default: scriptworker-prov-v1/bouncer-dev
worker:
implementation: bouncer-submission

View File

@ -59,7 +59,7 @@ jobs:
run:
extra-config:
by-project:
mozilla-(release|beta):
mozilla-(release|beta|esr.*):
stage_product: "firefox"
bucket_name: "net-mozaws-prod-delivery-firefox"
default:

View File

@ -32,7 +32,9 @@ jobs:
channel-names:
by-project:
birch: ["beta", "beta-localtest", "beta-cdntest"]
jamun: ["esr", "esr-localtest", "esr-cdntest"]
mozilla-release: ["beta", "beta-localtest", "beta-cdntest"]
mozilla-esr60: ["esr", "esr-localtest", "esr-cdntest"]
default: []
publish-rules:
by-project:
@ -42,7 +44,9 @@ jobs:
rules-to-update:
by-project:
birch: ["firefox-beta-cdntest", "firefox-beta-localtest"]
jamun: ["firefox-esr60-cdntest", "firefox-esr60-localtest"]
mozilla-release: ["firefox-beta-cdntest", "firefox-beta-localtest"]
mozilla-esr60: ["firefox-esr60-cdntest", "firefox-esr60-localtest"]
default: []
treeherder:
platform: linux64/opt

View File

@ -28,25 +28,33 @@ jobs:
archive-domain:
by-project:
mozilla-release: archive.mozilla.org
mozilla-esr60: archive.mozilla.org
default: ftp.stage.mozaws.net
download-domain:
by-project:
mozilla-release: download.mozilla.org
mozilla-esr60: download.mozilla.org
default: download.mozilla.org
channel-names:
by-project:
birch: ["beta", "beta-localtest", "beta-cdntest"]
jamun: ["esr", "esr-localtest", "esr-cdntest"]
mozilla-release: ["beta", "beta-localtest", "beta-cdntest"]
mozilla-esr60: ["esr", "esr-localtest", "esr-cdntest"]
default: []
publish-rules:
by-project:
birch: [32]
jamun: [724]
mozilla-release: [32]
mozilla-esr60: []
default: []
rules-to-update:
by-project:
birch: ["firefox-beta-cdntest", "firefox-beta-localtest"]
jamun: ["firefox-esr60-cdntest", "firefox-esr60-localtest"]
mozilla-release: ["firefox-beta-cdntest", "firefox-beta-localtest"]
mozilla-esr60: ["firefox-esr60-cdntest", "firefox-esr60-localtest"]
default: []
treeherder:
platform: linux64/opt

View File

@ -54,7 +54,7 @@ job-defaults:
include-version:
by-project:
birch: nonbeta
jamun: beta
jamun: esr
maple: beta
mozilla-beta: beta
mozilla-release: nonbeta

View File

@ -42,6 +42,10 @@ job-defaults:
- "browser/config/version.txt"
- "browser/config/version_display.txt"
- "config/milestone.txt"
jamun:
- "browser/config/version.txt"
- "browser/config/version_display.txt"
- "config/milestone.txt"
push:
by-project:
mozilla-beta: true
@ -50,6 +54,7 @@ job-defaults:
mozilla-esr60: true
maple: true
birch: true
jamun: true
default: false
jobs:

View File

@ -87,7 +87,7 @@ PER_PROJECT_PARAMETERS = {
},
'comm-esr60': {
'target_tasks_method': 'mozilla_beta_tasks',
'target_tasks_method': 'mozilla_esr60_tasks',
'optimize_target_tasks': True,
'include_nightly': True,
},

View File

@ -21,6 +21,7 @@ RELEASE_PROJECTS = {
'mozilla-esr60',
'comm-central',
'comm-beta',
'comm-esr60',
}
RELEASE_PROMOTION_PROJECTS = {

View File

@ -46,7 +46,9 @@ SIGNING_SCOPE_ALIAS_TO_PROJECT = [[
'all-release-branches', set([
'mozilla-beta',
'mozilla-release',
'mozilla-esr60',
'comm-beta',
'comm-esr60',
])
]]
@ -76,12 +78,16 @@ BEETMOVER_SCOPE_ALIAS_TO_PROJECT = [[
'mozilla-central',
'mozilla-beta',
'mozilla-release',
'mozilla-esr60',
'comm-central',
])
], [
'all-release-branches', set([
'mozilla-beta',
'mozilla-release',
'mozilla-esr60',
'comm-beta',
'comm-esr60',
])
]]
@ -170,11 +176,17 @@ BALROG_SCOPE_ALIAS_TO_PROJECT = [[
], [
'beta', set([
'mozilla-beta',
'comm-beta',
])
], [
'release', set([
'mozilla-release',
])
], [
'esr60', set([
'mozilla-esr60',
'comm-esr60',
])
], [
'esr', set([
'mozilla-esr52',
@ -189,6 +201,7 @@ BALROG_SERVER_SCOPES = {
'beta': 'balrog:server:beta',
'release': 'balrog:server:release',
'esr': 'balrog:server:esr',
'esr60': 'balrog:server:esr',
'default': 'balrog:server:dep',
}
@ -442,7 +455,7 @@ def get_release_config(config):
def get_signing_cert_scope_per_platform(build_platform, is_nightly, config):
if 'devedition' in build_platform:
return get_devedition_signing_cert_scope(config)
elif is_nightly or build_platform in ('firefox-source', 'fennec-source'):
elif is_nightly or build_platform in ('firefox-source', 'fennec-source', 'thunderbird-source'):
return get_signing_cert_scope(config)
else:
return add_scope_prefix(config, 'signing:cert:dep-signing')

View File

@ -6,7 +6,8 @@ config = {
"installer": {
"product-name": "Firefox-%(version)s",
"check_uptake": True,
"alias": "firefox-esr-latest",
# convert to firefox-esr-latest when ESR52 stops
"alias": "firefox-esr-next-latest",
"ssl-only": True,
"add-locales": True,
"paths": {
@ -35,7 +36,8 @@ config = {
"installer-ssl": {
"product-name": "Firefox-%(version)s-SSL",
"check_uptake": True,
"alias": "firefox-esr-latest-ssl",
# convert to firefox-esr-latest-ssl when ESR52 stops
"alias": "firefox-esr-next-latest-ssl",
"ssl-only": True,
"add-locales": True,
"paths": {

View File

@ -0,0 +1,31 @@
import os
config = {
"nightly_build": True,
"branch": "mozilla-esr60",
"en_us_binary_url": "http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-mozilla-esr60/",
"update_channel": "esr",
# l10n
"hg_l10n_base": "https://hg.mozilla.org/l10n-central",
# mar
"mar_tools_url": os.environ["MAR_TOOLS_URL"],
# repositories
"repos": [{
"vcs": "hg",
"repo": "https://hg.mozilla.org/build/tools",
"branch": "default",
"dest": "tools",
}, {
"vcs": "hg",
"repo": "https://hg.mozilla.org/releases/mozilla-esr60",
"revision": "%(revision)s",
"dest": "mozilla-esr60",
"clone_upstream_url": "https://hg.mozilla.org/mozilla-unified",
}],
# purge options
'purge_minsize': 12,
'is_automation': True,
}

View File

@ -194424,6 +194424,11 @@
{}
]
],
"clear-site-data/support/iframe_executionContexts.html": [
[
{}
]
],
"clear-site-data/support/page_with_resource.sub.html": [
[
{}
@ -321466,6 +321471,12 @@
{}
]
],
"clear-site-data/executionContexts.sub.html": [
[
"/clear-site-data/executionContexts.sub.html",
{}
]
],
"clear-site-data/navigation-insecure.html": [
[
"/clear-site-data/navigation-insecure.html",
@ -429477,6 +429488,10 @@
"65ca96dbb9d774e97cc3a60f6b6dde952104893b",
"support"
],
"clear-site-data/executionContexts.sub.html": [
"f09a3f73b59994ae82532a4412116815012e4371",
"testharness"
],
"clear-site-data/navigation-insecure.html": [
"9ccd712a222085ae7ef75a52e7f542e996a8eb29",
"testharness"
@ -429497,6 +429512,10 @@
"f7c48bb39579c991af9945d2ac6e98b604b7113b",
"support"
],
"clear-site-data/support/iframe_executionContexts.html": [
"9c20c9e0db5861970e1f72245b47f128be4a4b3d",
"support"
],
"clear-site-data/support/page_with_resource.sub.html": [
"703519a2f6f0e5d11a4fb4fb0e40e5fc3d8624fe",
"support"

View File

@ -1,5 +0,0 @@
[media-src-7_1_2.sub.html]
expected: TIMEOUT
[Test that securitypolicyviolation events are fired]
expected: TIMEOUT

View File

@ -1,5 +0,0 @@
[media-src-7_2_2.sub.html]
expected: TIMEOUT
[Test that securitypolicyviolation events are fired]
expected: TIMEOUT

View File

@ -1,5 +0,0 @@
[media-src-blocked.sub.html]
expected: TIMEOUT
[Test that securitypolicyviolation events are fired]
expected: TIMEOUT

View File

@ -0,0 +1,3 @@
[fetch-csp.https.html]
[Verify CSP control of fetch() in a Service Worker]
expected: FAIL

View File

@ -2,6 +2,3 @@
[Script: Ed25519-with-CSP, passes, valid key, valid signature.]
expected: FAIL
[Script: Ed25519-with-CSP, fails, valid key, valid signature, key not in CSP.]
expected: FAIL

View File

@ -0,0 +1,47 @@
<!DOCTYPE html>
<html>
<head>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
function createAndLoadIframe() {
return new Promise(resolve => {
addEventListener("message", function() {
assert_true(true, "Iframe loaded");
resolve();
}, { once: true });
let ifr = document.createElement('iframe');
document.body.appendChild(ifr);
ifr.src = "https://{{domains[www2]}}:{{ports[https][0]}}/clear-site-data/support/iframe_executionContexts.html";
});
}
function loadClearSiteDataResource(what) {
return new Promise(resolve => {
addEventListener("message", function() {
assert_true(true, "Iframe re-loaded");
resolve();
}, { once: true });
let image = new Image();
image.src = "https://{{domains[www2]}}:{{ports[https][0]}}/clear-site-data/support/echo-clear-site-data.py?" + what;
});
}
promise_test(function(test) {
return createAndLoadIframe()
.then(() => loadClearSiteDataResource("executionContexts"))
}, "executionContexts triggers the reload of contexts");
promise_test(function(test) {
return createAndLoadIframe()
.then(() => loadClearSiteDataResource("*"));
}, "* triggers the reload of contexts");
</script>
</body>
</html>

View File

@ -0,0 +1,8 @@
<!DOCTYPE html>
<html>
<body>
<script>
parent.postMessage("Hello world!", "*");
</script>
</body>
</html>

View File

@ -3,5 +3,5 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
dropmarker {
-moz-appearance: menulist-button;
-moz-appearance: -moz-menulist-button;
}

View File

@ -66,7 +66,7 @@ menulist[editable="true"] {
menulist[editable="true"] > .menulist-dropmarker {
display: -moz-box;
-moz-appearance: menulist-button;
-moz-appearance: -moz-menulist-button;
}
html|*.menulist-editable-input {

View File

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
dropmarker {
-moz-appearance: menulist-button;
-moz-appearance: -moz-menulist-button;
width: 16px;
-moz-box-align: center;
-moz-box-pack: center;

View File

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
dropmarker {
-moz-appearance: menulist-button;
-moz-appearance: -moz-menulist-button;
width: 16px;
height: 16px;
-moz-box-align: center;

View File

@ -3327,6 +3327,7 @@ nsNativeThemeCocoa::ComputeWidgetInfo(nsIFrame* aFrame,
}
case StyleAppearance::MenulistButton:
case StyleAppearance::MozMenulistButton:
return Some(WidgetInfo::Button(
ButtonParams{ComputeControlParams(aFrame, eventState),
ButtonType::eArrowButton}));
@ -3868,6 +3869,7 @@ nsNativeThemeCocoa::CreateWebRenderCommandsForWidget(mozilla::wr::DisplayListBui
case StyleAppearance::Menulist:
case StyleAppearance::MenulistTextfield:
case StyleAppearance::MenulistButton:
case StyleAppearance::MozMenulistButton:
case StyleAppearance::Groupbox:
case StyleAppearance::Textfield:
case StyleAppearance::NumberInput:
@ -4033,6 +4035,7 @@ nsNativeThemeCocoa::GetWidgetBorder(nsDeviceContext* aContext,
case StyleAppearance::Menulist:
case StyleAppearance::MenulistButton:
case StyleAppearance::MozMenulistButton:
result = DirectionAwareMargin(kAquaDropdownBorder, aFrame);
break;
@ -4160,6 +4163,7 @@ nsNativeThemeCocoa::GetWidgetOverflow(nsDeviceContext* aContext, nsIFrame* aFram
case StyleAppearance::Listbox:
case StyleAppearance::Menulist:
case StyleAppearance::MenulistButton:
case StyleAppearance::MozMenulistButton:
case StyleAppearance::MenulistTextfield:
case StyleAppearance::Checkbox:
case StyleAppearance::Radio:
@ -4290,6 +4294,7 @@ nsNativeThemeCocoa::GetMinimumWidgetSize(nsPresContext* aPresContext,
case StyleAppearance::Menulist:
case StyleAppearance::MenulistButton:
case StyleAppearance::MozMenulistButton:
{
SInt32 popupHeight = 0;
::GetThemeMetric(kThemeMetricPopupButtonHeight, &popupHeight);
@ -4616,7 +4621,8 @@ nsNativeThemeCocoa::ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* a
WidgetType aWidgetType)
{
// if this is a dropdown button in a combobox the answer is always no
if (aWidgetType == StyleAppearance::MenulistButton) {
if (aWidgetType == StyleAppearance::MenulistButton ||
aWidgetType == StyleAppearance::MozMenulistButton) {
nsIFrame* parentFrame = aFrame->GetParent();
if (parentFrame && parentFrame->IsComboboxControlFrame())
return false;
@ -4626,6 +4632,7 @@ nsNativeThemeCocoa::ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* a
// Combobox dropdowns don't support native theming in vertical mode.
case StyleAppearance::Menulist:
case StyleAppearance::MenulistButton:
case StyleAppearance::MozMenulistButton:
case StyleAppearance::MenulistText:
case StyleAppearance::MenulistTextfield:
if (aFrame && aFrame->GetWritingMode().IsVertical()) {
@ -4755,6 +4762,7 @@ nsNativeThemeCocoa::WidgetIsContainer(WidgetType aWidgetType)
// flesh this out at some point
switch (aWidgetType) {
case StyleAppearance::MenulistButton:
case StyleAppearance::MozMenulistButton:
case StyleAppearance::Radio:
case StyleAppearance::Checkbox:
case StyleAppearance::Progressbar:

View File

@ -304,7 +304,8 @@ nsNativeThemeGTK::GetGtkWidgetAndState(StyleAppearance aWidgetType, nsIFrame* aF
aWidgetType == StyleAppearance::Dualbutton ||
aWidgetType == StyleAppearance::ToolbarbuttonDropdown ||
aWidgetType == StyleAppearance::Menulist ||
aWidgetType == StyleAppearance::MenulistButton) {
aWidgetType == StyleAppearance::MenulistButton ||
aWidgetType == StyleAppearance::MozMenulistButton) {
aState->active &= aState->inHover;
} else if (aWidgetType == StyleAppearance::Treetwisty ||
aWidgetType == StyleAppearance::Treetwistyopen) {
@ -421,7 +422,8 @@ nsNativeThemeGTK::GetGtkWidgetAndState(StyleAppearance aWidgetType, nsIFrame* aF
aWidgetType == StyleAppearance::Dualbutton ||
aWidgetType == StyleAppearance::ToolbarbuttonDropdown ||
aWidgetType == StyleAppearance::Menulist ||
aWidgetType == StyleAppearance::MenulistButton) {
aWidgetType == StyleAppearance::MenulistButton ||
aWidgetType == StyleAppearance::MozMenulistButton) {
bool menuOpen = IsOpenButton(aFrame);
aState->depressed = IsCheckedButton(aFrame) || menuOpen;
// we must not highlight buttons with open drop down menus on hover.
@ -430,7 +432,9 @@ nsNativeThemeGTK::GetGtkWidgetAndState(StyleAppearance aWidgetType, nsIFrame* aF
// When the input field of the drop down button has focus, some themes
// should draw focus for the drop down button as well.
if (aWidgetType == StyleAppearance::MenulistButton && aWidgetFlags) {
if ((aWidgetType == StyleAppearance::MenulistButton ||
aWidgetType == StyleAppearance::MozMenulistButton) &&
aWidgetFlags) {
*aWidgetFlags = CheckBooleanAttr(aFrame, nsGkAtoms::parentfocused);
}
}
@ -623,6 +627,7 @@ nsNativeThemeGTK::GetGtkWidgetAndState(StyleAppearance aWidgetType, nsIFrame* aF
aGtkWidgetType = MOZ_GTK_DROPDOWN_ENTRY;
break;
case StyleAppearance::MenulistButton:
case StyleAppearance::MozMenulistButton:
aGtkWidgetType = MOZ_GTK_DROPDOWN_ARROW;
break;
case StyleAppearance::ToolbarbuttonDropdown:
@ -1398,6 +1403,7 @@ nsNativeThemeGTK::GetWidgetPadding(nsDeviceContext* aContext,
case StyleAppearance::TabScrollArrowBack:
case StyleAppearance::TabScrollArrowForward:
case StyleAppearance::MenulistButton:
case StyleAppearance::MozMenulistButton:
case StyleAppearance::ToolbarbuttonDropdown:
case StyleAppearance::ButtonArrowUp:
case StyleAppearance::ButtonArrowDown:
@ -1600,6 +1606,7 @@ nsNativeThemeGTK::GetMinimumWidgetSize(nsPresContext* aPresContext,
}
break;
case StyleAppearance::MenulistButton:
case StyleAppearance::MozMenulistButton:
{
moz_gtk_get_combo_box_entry_button_size(&aResult->width,
&aResult->height);
@ -1952,6 +1959,7 @@ nsNativeThemeGTK::ThemeSupportsWidget(nsPresContext* aPresContext,
!IsWidgetStyled(aPresContext, aFrame, aWidgetType);
case StyleAppearance::MenulistButton:
case StyleAppearance::MozMenulistButton:
if (aFrame && aFrame->GetWritingMode().IsVertical()) {
return false;
}
@ -1974,6 +1982,7 @@ nsNativeThemeGTK::WidgetIsContainer(StyleAppearance aWidgetType)
{
// XXXdwh At some point flesh all of this out.
if (aWidgetType == StyleAppearance::MenulistButton ||
aWidgetType == StyleAppearance::MozMenulistButton ||
aWidgetType == StyleAppearance::Radio ||
aWidgetType == StyleAppearance::RangeThumb ||
aWidgetType == StyleAppearance::Checkbox ||

View File

@ -88,6 +88,7 @@ HeadlessThemeGTK::GetWidgetBorder(nsDeviceContext* aContext, nsIFrame* aFrame,
result.left = 7;
break;
case StyleAppearance::MenulistButton:
case StyleAppearance::MozMenulistButton:
result.top = 1;
result.right = 1;
result.bottom = 1;
@ -135,6 +136,7 @@ HeadlessThemeGTK::GetWidgetPadding(nsDeviceContext* aContext,
case StyleAppearance::TabScrollArrowBack:
case StyleAppearance::TabScrollArrowForward:
case StyleAppearance::MenulistButton:
case StyleAppearance::MozMenulistButton:
case StyleAppearance::RangeThumb:
case StyleAppearance::ButtonFocus:
aResult->top = 0;
@ -272,6 +274,7 @@ HeadlessThemeGTK::GetMinimumWidgetSize(nsPresContext* aPresContext,
aResult->height = 27;
break;
case StyleAppearance::MenulistButton:
case StyleAppearance::MozMenulistButton:
aResult->width = 29;
aResult->height = 28;
*aIsOverridable = false;
@ -409,6 +412,7 @@ HeadlessThemeGTK::ThemeSupportsWidget(nsPresContext* aPresContext,
case StyleAppearance::MozGtkInfoBar:
return !IsWidgetStyled(aPresContext, aFrame, aWidgetType);
case StyleAppearance::MenulistButton:
case StyleAppearance::MozMenulistButton:
return (!aFrame || IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XUL)) &&
!IsWidgetStyled(aPresContext, aFrame, aWidgetType);
default:
@ -421,6 +425,7 @@ NS_IMETHODIMP_(bool)
HeadlessThemeGTK::WidgetIsContainer(WidgetType aWidgetType)
{
if (aWidgetType == StyleAppearance::MenulistButton ||
aWidgetType == StyleAppearance::MozMenulistButton ||
aWidgetType == StyleAppearance::Radio ||
aWidgetType == StyleAppearance::RangeThumb ||
aWidgetType == StyleAppearance::Checkbox ||

View File

@ -785,6 +785,7 @@ mozilla::Maybe<nsUXThemeClass> nsNativeThemeWin::GetThemeClass(WidgetType aWidge
return Some(eUXStatus);
case StyleAppearance::Menulist:
case StyleAppearance::MenulistButton:
case StyleAppearance::MozMenulistButton:
return Some(eUXCombobox);
case StyleAppearance::Treeheadercell:
case StyleAppearance::Treeheadersortarrow:
@ -1297,7 +1298,8 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, WidgetType aWidgetType,
return NS_OK;
}
case StyleAppearance::MenulistButton: {
case StyleAppearance::MenulistButton:
case StyleAppearance::MozMenulistButton: {
bool isHTML = IsHTMLContent(aFrame);
nsIFrame* parentFrame = aFrame->GetParent();
bool isMenulist = !isHTML && parentFrame->IsMenuFrame();
@ -1828,7 +1830,8 @@ RENDER_AGAIN:
}
// The following widgets need to be RTL-aware
else if (aWidgetType == StyleAppearance::Resizer ||
aWidgetType == StyleAppearance::MenulistButton)
aWidgetType == StyleAppearance::MenulistButton ||
aWidgetType == StyleAppearance::MozMenulistButton)
{
DrawThemeBGRTLAware(theme, hdc, part, state,
&widgetRect, &clipRect, IsFrameRTL(aFrame));
@ -2258,6 +2261,8 @@ nsNativeThemeWin::GetWidgetOverflow(nsDeviceContext* aContext,
* where, if invalidated, the dropdown control probably won't be repainted.
* This is fairly minor, as by default there is nothing in that area, and
* a border only shows up if the widget is being hovered.
*
* TODO(jwatt): Figure out what do to about StyleAppearance::MozMenulistButton too.
*/
#if 0
/* We explicitly draw dropdown buttons in HTML content 1px bigger up, right,
@ -2351,7 +2356,8 @@ nsNativeThemeWin::GetMinimumWidgetSize(nsPresContext* aPresContext, nsIFrame* aF
case StyleAppearance::ScrollbarbuttonRight:
case StyleAppearance::ScrollbarHorizontal:
case StyleAppearance::ScrollbarVertical:
case StyleAppearance::MenulistButton: {
case StyleAppearance::MenulistButton:
case StyleAppearance::MozMenulistButton: {
rv = ClassicGetMinimumWidgetSize(aFrame, aWidgetType, aResult, aIsOverridable);
ScaleForFrameDPI(aResult, aFrame);
return rv;
@ -2566,7 +2572,9 @@ nsNativeThemeWin::WidgetStateChanged(nsIFrame* aFrame, WidgetType aWidgetType,
// We need to repaint the dropdown arrow in vista HTML combobox controls when
// the control is closed to get rid of the hover effect.
if ((aWidgetType == StyleAppearance::Menulist || aWidgetType == StyleAppearance::MenulistButton) &&
if ((aWidgetType == StyleAppearance::Menulist ||
aWidgetType == StyleAppearance::MenulistButton ||
aWidgetType == StyleAppearance::MozMenulistButton) &&
IsHTMLContent(aFrame))
{
*aShouldRepaint = true;
@ -2643,6 +2651,7 @@ nsNativeThemeWin::WidgetIsContainer(WidgetType aWidgetType)
{
// XXXdwh At some point flesh all of this out.
if (aWidgetType == StyleAppearance::MenulistButton ||
aWidgetType == StyleAppearance::MozMenulistButton ||
aWidgetType == StyleAppearance::Radio ||
aWidgetType == StyleAppearance::Checkbox)
return false;
@ -2788,6 +2797,7 @@ nsNativeThemeWin::ClassicThemeSupportsWidget(nsIFrame* aFrame,
case StyleAppearance::ScalethumbHorizontal:
case StyleAppearance::ScalethumbVertical:
case StyleAppearance::MenulistButton:
case StyleAppearance::MozMenulistButton:
case StyleAppearance::InnerSpinButton:
case StyleAppearance::SpinnerUpbutton:
case StyleAppearance::SpinnerDownbutton:
@ -2998,6 +3008,7 @@ nsNativeThemeWin::ClassicGetMinimumWidgetSize(nsIFrame* aFrame,
*aIsOverridable = false;
break;
case StyleAppearance::MenulistButton:
case StyleAppearance::MozMenulistButton:
(*aResult).width = ::GetSystemMetrics(SM_CXVSCROLL);
break;
case StyleAppearance::Menulist:
@ -3277,7 +3288,8 @@ nsresult nsNativeThemeWin::ClassicGetThemePartAndState(nsIFrame* aFrame, WidgetT
case StyleAppearance::Groupbox:
// these don't use DrawFrameControl
return NS_OK;
case StyleAppearance::MenulistButton: {
case StyleAppearance::MenulistButton:
case StyleAppearance::MozMenulistButton: {
aPart = DFC_SCROLL;
aState = DFCS_SCROLLCOMBOBOX;
@ -3662,6 +3674,7 @@ RENDER_AGAIN:
case StyleAppearance::SpinnerUpbutton:
case StyleAppearance::SpinnerDownbutton:
case StyleAppearance::MenulistButton:
case StyleAppearance::MozMenulistButton:
case StyleAppearance::Resizer: {
int32_t oldTA;
// setup DC to make DrawFrameControl draw correctly
@ -4093,6 +4106,7 @@ nsNativeThemeWin::GetWidgetNativeDrawingFlags(WidgetType aWidgetType)
// except that the graphic in the dropdown button (the downward arrow)
// doesn't get scaled up.
case StyleAppearance::MenulistButton:
case StyleAppearance::MozMenulistButton:
// these are definitely no; they're all graphics that don't get scaled up
case StyleAppearance::Checkbox:
case StyleAppearance::Radio:

View File

@ -4,6 +4,9 @@
* 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/. */
// See the comment at the top of mfbt/HashTable.h for a comparison between
// PLDHashTable and mozilla::HashTable.
#ifndef PLDHashTable_h
#define PLDHashTable_h

View File

@ -39,7 +39,7 @@ struct nsIDataType
VTYPE_WCHAR_STR = TD_PWSTRING ,
VTYPE_INTERFACE = TD_INTERFACE_TYPE ,
VTYPE_INTERFACE_IS = TD_INTERFACE_IS_TYPE,
VTYPE_ARRAY = TD_ARRAY ,
VTYPE_ARRAY = TD_LEGACY_ARRAY ,
VTYPE_STRING_SIZE_IS = TD_PSTRING_SIZE_IS ,
VTYPE_WSTRING_SIZE_IS = TD_PWSTRING_SIZE_IS ,
VTYPE_UTF8STRING = TD_UTF8STRING ,

View File

@ -2550,6 +2550,13 @@ public:
this->AppendElements(aOther);
}
AutoTArray(self_type&& aOther)
: nsTArray<E>()
{
Init();
this->SwapElements(aOther);
}
explicit AutoTArray(const base_type& aOther)
: mAlign()
{
@ -2584,6 +2591,12 @@ public:
return *this;
}
self_type& operator=(self_type&& aOther)
{
base_type::operator=(std::move(aOther));
return *this;
}
template<typename Allocator>
self_type& operator=(const nsTArray_Impl<elem_type, Allocator>& aOther)
{

View File

@ -4,6 +4,9 @@
* 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/. */
// See the comment at the top of mfbt/HashTable.h for a comparison between
// PLDHashTable and mozilla::HashTable.
#ifndef nsTHashtable_h__
#define nsTHashtable_h__

View File

@ -63,10 +63,18 @@ def get_type(type, calltype, iid_is=None, size_is=None):
return ret
if isinstance(type, xpidl.Array):
# NB: For an Array<T> we pass down the iid_is to get the type of T.
# NB: For a Array<T> we pass down the iid_is to get the type of T.
# This allows Arrays of InterfaceIs types to work.
return {
'tag': 'TD_ARRAY',
'element': get_type(type.type, calltype, iid_is),
}
if isinstance(type, xpidl.LegacyArray):
# NB: For a Legacy [array] T we pass down iid_is to get the type of T.
# This allows [array] of InterfaceIs types to work.
return {
'tag': 'TD_LEGACY_ARRAY',
'size_is': size_is,
'element': get_type(type.type, calltype, iid_is),
}

View File

@ -60,7 +60,7 @@ void bar();
m = iface.members[0]
self.assertTrue(isinstance(m, xpidl.Method))
self.assertEqual("bar", m.name)
self.assertEqual("void", m.type)
self.assertEqual(xpidl.TypeId("void"), m.type)
def testMethodParams(self):
i = self.p.parse("""[uuid(abc)] interface foo {
@ -73,15 +73,15 @@ long bar(in long a, in float b, [array] in long c);
m = iface.members[0]
self.assertTrue(isinstance(m, xpidl.Method))
self.assertEqual("bar", m.name)
self.assertEqual("long", m.type)
self.assertEqual(xpidl.TypeId("long"), m.type)
self.assertEqual(3, len(m.params))
self.assertEqual("long", m.params[0].type)
self.assertEqual(xpidl.TypeId("long"), m.params[0].type)
self.assertEqual("in", m.params[0].paramtype)
self.assertEqual("float", m.params[1].type)
self.assertEqual(xpidl.TypeId("float"), m.params[1].type)
self.assertEqual("in", m.params[1].paramtype)
self.assertEqual("long", m.params[2].type)
self.assertEqual(xpidl.TypeId("long"), m.params[2].type)
self.assertEqual("in", m.params[2].paramtype)
self.assertTrue(isinstance(m.params[2].realtype, xpidl.Array))
self.assertTrue(isinstance(m.params[2].realtype, xpidl.LegacyArray))
self.assertEqual("long", m.params[2].realtype.type.name)
def testAttribute(self):
@ -94,7 +94,7 @@ attribute long bar;
a = iface.members[0]
self.assertTrue(isinstance(a, xpidl.Attribute))
self.assertEqual("bar", a.name)
self.assertEqual("long", a.type)
self.assertEqual(xpidl.TypeId("long"), a.type)
def testOverloadedVirtual(self):
i = self.p.parse("""[uuid(abc)] interface foo {

View File

@ -12,6 +12,7 @@ import os.path
import re
from ply import lex
from ply import yacc
from collections import namedtuple
"""A type conforms to the following pattern:
@ -20,7 +21,7 @@ from ply import yacc
def nativeType(self, calltype):
'returns a string representation of the native type
calltype must be 'in', 'out', or 'inout'
calltype must be 'in', 'out', 'inout', or 'element'
Interface members const/method/attribute conform to the following pattern:
@ -131,6 +132,9 @@ class Builtin(object):
return self.nativename.endswith('*')
def nativeType(self, calltype, shared=False, const=False):
if self.name in ["string", "wstring"] and calltype == 'element':
raise IDLError("Use string class types for string Array elements", self.location)
if const:
print >>sys.stderr, IDLError(
"[const] doesn't make sense on builtin types.", self.location, warning=True)
@ -144,7 +148,7 @@ class Builtin(object):
else:
const = ''
return "%s%s %s" % (const, self.nativename,
calltype != 'in' and '*' or '')
'*' if 'out' in calltype else '')
def rustType(self, calltype, shared=False, const=False):
# We want to rewrite any *mut pointers to *const pointers if constness
@ -321,6 +325,7 @@ class Include(object):
class IDL(object):
def __init__(self, productions):
self.hasSequence = False
self.productions = productions
self.deps = []
@ -328,10 +333,19 @@ class IDL(object):
self.namemap.set(object)
def getName(self, id, location):
if id.name == 'Array':
if id.params is None or len(id.params) != 1:
raise IDLError("Array takes exactly 1 parameter", location)
self.hasSequence = True
return Array(self.getName(id.params[0], location), location)
if id.params is not None:
raise IDLError("Generic type '%s' unrecognized" % id.name, location)
try:
return self.namemap[id]
return self.namemap[id.name]
except KeyError:
raise IDLError("type '%s' not found" % id, location)
raise IDLError("type '%s' not found" % id.name, location)
def hasName(self, id):
return id in self.namemap
@ -354,6 +368,8 @@ class IDL(object):
for p in self.productions:
if p.kind == 'include':
yield p
if self.hasSequence:
yield Include("nsTArray.h", BuiltinLocation)
def needsJSTypes(self):
for p in self.productions:
@ -396,12 +412,14 @@ class Typedef(object):
parent.setName(self)
self.realtype = parent.getName(self.type, self.location)
if not isinstance(self.realtype, (Builtin, Native, Typedef)):
raise IDLError("Unsupported typedef target type", self.location)
def isScriptable(self):
return self.realtype.isScriptable()
def nativeType(self, calltype):
return "%s %s" % (self.name,
calltype != 'in' and '*' or '')
return "%s %s" % (self.name, '*' if 'out' in calltype else '')
def rustType(self, calltype):
return "%s%s" % (calltype != 'in' and '*mut ' or '',
@ -440,8 +458,9 @@ class Forward(object):
return True
def nativeType(self, calltype):
return "%s %s" % (self.name,
calltype != 'in' and '* *' or '*')
if calltype == 'element':
return 'RefPtr<%s>' % self.name
return "%s *%s" % (self.name, '*' if 'out' in calltype else '')
def rustType(self, calltype):
if rustBlacklistedForward(self.name):
@ -459,29 +478,19 @@ class Native(object):
modifier = None
specialtype = None
# A tuple type here means that a custom value is used for each calltype:
# (in, out/inout, array element) respectively.
# A `None` here means that the written type should be used as-is.
specialtypes = {
'nsid': None,
'domstring': 'nsAString',
'utf8string': 'nsACString',
'cstring': 'nsACString',
'astring': 'nsAString',
'jsval': 'JS::Value',
'domstring': ('const nsAString&', 'nsAString&', 'nsString'),
'utf8string': ('const nsACString&', 'nsACString&', 'nsCString'),
'cstring': ('const nsACString&', 'nsACString&', 'nsCString'),
'astring': ('const nsAString&', 'nsAString&', 'nsString'),
'jsval': ('JS::HandleValue', 'JS::MutableHandleValue', 'JS::Value'),
'promise': '::mozilla::dom::Promise',
}
# Mappings from C++ native name types to rust native names. Types which
# aren't listed here are incompatible with rust code.
rust_nativenames = {
'void': "libc::c_void",
'char': "u8",
'char16_t': "u16",
'nsID': "nsID",
'nsIID': "nsIID",
'nsCID': "nsCID",
'nsAString': "::nsstring::nsAString",
'nsACString': "::nsstring::nsACString",
}
def __init__(self, name, nativename, attlist, location):
self.name = name
self.nativename = nativename
@ -533,47 +542,75 @@ class Native(object):
def nativeType(self, calltype, const=False, shared=False):
if shared:
if calltype != 'out':
raise IDLError("[shared] only applies to out parameters.")
raise IDLError("[shared] only applies to out parameters.", self.location)
const = True
if self.specialtype not in [None, 'promise'] and calltype == 'in':
if isinstance(self.nativename, tuple):
if calltype == 'in':
return self.nativename[0] + ' '
elif 'out' in calltype:
return self.nativename[1] + ' '
else:
return self.nativename[2] + ' '
# 'in' nsid parameters should be made 'const'
if self.specialtype == 'nsid' and calltype == 'in':
const = True
if self.specialtype == 'jsval':
if calltype == 'out' or calltype == 'inout':
return "JS::MutableHandleValue "
return "JS::HandleValue "
if calltype == 'element':
if self.isRef(calltype):
raise IDLError("[ref] qualified type unsupported in Array<T>", self.location)
# Promises should be held in RefPtr<T> in Array<T>s
if self.specialtype == 'promise':
return 'RefPtr<mozilla::dom::Promise>'
# We don't support nsIDPtr, in Array<T> currently, although
# this or support for Array<nsID> will be needed to replace
# [array] completely.
if self.specialtype == 'nsid':
raise IDLError("Array<nsIDPtr> not yet supported. "
"File an XPConnect bug if you need it.", self.location)
if self.isRef(calltype):
m = '& '
elif self.isPtr(calltype):
m = '*' + ((self.modifier == 'ptr' and calltype != 'in') and '*' or '')
m = '& ' # [ref] is always passed with a single indirection
else:
m = calltype != 'in' and '*' or ''
m = '* ' if 'out' in calltype else ''
if self.isPtr(calltype):
m += '* '
return "%s%s %s" % (const and 'const ' or '', self.nativename, m)
def rustType(self, calltype, const=False, shared=False):
if shared:
if calltype != 'out':
raise IDLError("[shared] only applies to out parameters.")
const = True
# For the most part, 'native' types don't make sense in rust, as they
# are native C++ types. However, we can support a few types here, as
# they're important.
#
# NOTE: This code doesn't try to perfectly match C++ constness, as
# constness doesn't affect ABI, and raw pointers are already unsafe.
if self.specialtype is not None and calltype == 'in':
const = True
if self.modifier not in ['ptr', 'ref']:
raise RustNoncompat('Rust only supports [ref] / [ptr] native types')
if self.nativename not in self.rust_nativenames:
raise RustNoncompat("native type %s is unsupported" % self.nativename)
name = self.rust_nativenames[self.nativename]
prefix = '*mut ' if 'out' in calltype else '*const '
if 'out' in calltype and self.modifier == 'ptr':
prefix += '*mut '
if self.isRef(calltype):
m = const and '&' or '&mut '
elif self.isPtr(calltype):
m = (const and '*const ' or '*mut ')
if self.modifier == 'ptr' and calltype != 'in':
m += '*mut '
else:
m = calltype != 'in' and '*mut ' or ''
return "%s%s" % (m, name)
if self.specialtype == 'nsid':
return prefix + self.nativename
if self.specialtype in ['cstring', 'utf8string']:
if 'element' in calltype:
return '::nsstring::nsCString'
return prefix + '::nsstring::nsACString'
if self.specialtype in ['astring', 'domstring']:
if 'element' in calltype:
return '::nsstring::nsString'
return prefix + '::nsstring::nsAString'
if self.nativename == 'void':
return prefix + 'libc::c_void'
if self.specialtype:
raise RustNoncompat("specialtype %s unsupported" % self.specialtype)
raise RustNoncompat("native type %s unsupported" % self.nativename)
def __str__(self):
return "native %s(%s)\n" % (self.name, self.nativename)
@ -613,11 +650,13 @@ class WebIDL(object):
return True # All DOM objects are script exposed.
def nativeType(self, calltype):
return "%s %s" % (self.native, calltype != 'in' and '* *' or '*')
if calltype == 'element':
return 'RefPtr<%s>' % self.native
return "%s *%s" % (self.native, '*' if 'out' in calltype else '')
def rustType(self, calltype):
# Just expose the type as a void* - we can't do any better.
return "%s*const libc::c_void" % (calltype != 'in' and '*mut ' or '')
return "%s*const libc::c_void" % ('*mut ' if 'out' in calltype else '')
def __str__(self):
return "webidl %s\n" % self.name
@ -662,7 +701,7 @@ class Interface(object):
if hasattr(member, 'doccomments'):
member.doccomments[0:0] = self.doccomments
break
self.doccomments = parent.getName(self.name, None).doccomments
self.doccomments = parent.getName(TypeId(self.name), None).doccomments
if self.attributes.function:
has_method = False
@ -677,7 +716,7 @@ class Interface(object):
parent.setName(self)
if self.base is not None:
realbase = parent.getName(self.base, self.location)
realbase = parent.getName(TypeId(self.base), self.location)
if realbase.kind != 'interface':
raise IDLError("interface '%s' inherits from non-interface type '%s'" %
(self.name, self.base), self.location)
@ -713,12 +752,13 @@ class Interface(object):
return True
def nativeType(self, calltype, const=False):
return "%s%s %s" % (const and 'const ' or '',
self.name,
calltype != 'in' and '* *' or '*')
if calltype == 'element':
return 'RefPtr<%s>' % self.name
return "%s%s *%s" % ('const ' if const else '', self.name,
'*' if 'out' in calltype else '')
def rustType(self, calltype):
return "%s*const %s" % (calltype != 'in' and '*mut ' or '',
def rustType(self, calltype, const=False):
return "%s*const %s" % ('*mut ' if 'out' in calltype else '',
self.name)
def __str__(self):
@ -737,9 +777,9 @@ class Interface(object):
# The constant may be in a base class
iface = self
while name not in iface.namemap and iface is not None:
iface = self.idl.getName(self.base, self.location)
iface = self.idl.getName(TypeId(self.base), self.location)
if iface is None:
raise IDLError("cannot find symbol '%s'" % name)
raise IDLError("cannot find symbol '%s'" % name, self.location)
c = iface.namemap.get(name, location)
if c.kind != 'const':
raise IDLError("symbol '%s' is not a constant", c.location)
@ -748,7 +788,7 @@ class Interface(object):
def needsJSTypes(self):
for m in self.members:
if m.kind == "attribute" and m.type == "jsval":
if m.kind == "attribute" and m.type == TypeId("jsval"):
return True
if m.kind == "method" and m.needsJSTypes():
return True
@ -758,7 +798,7 @@ class Interface(object):
''' Returns the number of entries in the vtable for this interface. '''
total = sum(member.count() for member in self.members)
if self.base is not None:
realbase = self.idl.getName(self.base, self.location)
realbase = self.idl.getName(TypeId(self.base), self.location)
total += realbase.countEntries()
return total
@ -1084,7 +1124,7 @@ class Method(object):
def needsJSTypes(self):
if self.implicit_jscontext:
return True
if self.type == "jsval":
if self.type == TypeId("jsval"):
return True
for p in self.params:
t = p.realtype
@ -1166,7 +1206,7 @@ class Param(object):
def resolve(self, method):
self.realtype = method.iface.idl.getName(self.type, self.location)
if self.array:
self.realtype = Array(self.realtype)
self.realtype = LegacyArray(self.realtype)
if (self.null is not None and
getBuiltinOrNativeTypeName(self.realtype) != '[domstring]'):
raise IDLError("'Null' attribute can only be used on DOMString",
@ -1211,20 +1251,80 @@ class Param(object):
self.name)
class Array(object):
class LegacyArray(object):
def __init__(self, basetype):
self.type = basetype
self.location = self.type.location
def isScriptable(self):
return self.type.isScriptable()
def nativeType(self, calltype, const=False):
return "%s%s*" % (const and 'const ' or '',
self.type.nativeType(calltype))
if 'element' in calltype:
raise IDLError("nested [array] unsupported", self.location)
# For legacy reasons, we have to add a 'const ' to builtin pointer array
# types. (`[array] in string` and `[array] in wstring` parameters)
if calltype == 'in' and isinstance(self.type, Builtin) and self.type.isPointer():
const = True
return "%s%s*%s" % ('const ' if const else '',
self.type.nativeType('legacyelement'),
'*' if 'out' in calltype else '')
def rustType(self, calltype, const=False):
return "%s %s" % (const and '*const' or '*mut',
self.type.rustType(calltype))
return "%s%s%s" % ('*mut ' if 'out' in calltype else '',
'*const ' if const else '*mut ',
self.type.rustType('legacyelement'))
class Array(object):
kind = 'array'
def __init__(self, type, location):
self.type = type
self.location = location
@property
def name(self):
return "Array<%s>" % self.type.name
def resolve(self, idl):
idl.getName(self.type, self.location)
def isScriptable(self):
return self.type.isScriptable()
def nativeType(self, calltype):
if calltype == 'legacyelement':
raise IDLError("[array] Array<T> is unsupported", self.location)
base = 'nsTArray<%s>' % self.type.nativeType('element')
if 'out' in calltype:
return '%s& ' % base
elif 'in' == calltype:
return 'const %s& ' % base
else:
return base
def rustType(self, calltype):
# NOTE: To add Rust support, ensure 'element' is handled correctly in
# all rustType callees.
raise RustNoncompat("Array<...> types")
TypeId = namedtuple('TypeId', 'name params')
# Make str(TypeId) produce a nicer value
TypeId.__str__ = lambda self: \
"%s<%s>" % (self.name, ', '.join(str(p) for p in self.params)) \
if self.params is not None \
else self.name
# Allow skipping 'params' in TypeId(..)
TypeId.__new__.__defaults__ = (None,)
class IDLParser(object):
@ -1267,7 +1367,7 @@ class IDLParser(object):
t_LSHIFT = r'<<'
t_RSHIFT = r'>>'
literals = '"(){}[],;:=|+-*'
literals = '"(){}[]<>,;:=|+-*'
t_ignore = ' \t'
@ -1360,7 +1460,7 @@ class IDLParser(object):
p[0].insert(0, p[1])
def p_typedef(self, p):
"""typedef : TYPEDEF IDENTIFIER IDENTIFIER ';'"""
"""typedef : TYPEDEF type IDENTIFIER ';'"""
p[0] = Typedef(type=p[2],
name=p[3],
location=self.getLocation(p, 1),
@ -1473,7 +1573,7 @@ class IDLParser(object):
p[0] = CDATA(p[1], self.getLocation(p, 1))
def p_member_const(self, p):
"""member : CONST IDENTIFIER IDENTIFIER '=' number ';' """
"""member : CONST type IDENTIFIER '=' number ';' """
p[0] = ConstMember(type=p[2], name=p[3],
value=p[5], location=self.getLocation(p, 1),
doccomments=p.slice[1].doccomments)
@ -1535,7 +1635,7 @@ class IDLParser(object):
p[0] = lambda i: n1(i) | n2(i)
def p_member_att(self, p):
"""member : attributes optreadonly ATTRIBUTE IDENTIFIER IDENTIFIER ';'"""
"""member : attributes optreadonly ATTRIBUTE type IDENTIFIER ';'"""
if 'doccomments' in p[1]:
doccomments = p[1]['doccomments']
elif p[2] is not None:
@ -1551,7 +1651,7 @@ class IDLParser(object):
doccomments=doccomments)
def p_member_method(self, p):
"""member : attributes IDENTIFIER IDENTIFIER '(' paramlist ')' raises ';'"""
"""member : attributes type IDENTIFIER '(' paramlist ')' raises ';'"""
if 'doccomments' in p[1]:
doccomments = p[1]['doccomments']
else:
@ -1584,7 +1684,7 @@ class IDLParser(object):
p[0].insert(0, p[2])
def p_param(self, p):
"""param : attributes paramtype IDENTIFIER IDENTIFIER"""
"""param : attributes paramtype type IDENTIFIER"""
p[0] = Param(paramtype=p[2],
type=p[3],
name=p[4],
@ -1622,6 +1722,25 @@ class IDLParser(object):
p[0] = list(p[3])
p[0].insert(0, p[1])
def p_type_id(self, p):
"""type : IDENTIFIER"""
p[0] = TypeId(name=p[1])
p.slice[0].doccomments = p.slice[1].doccomments
def p_type_generic(self, p):
"""type : IDENTIFIER '<' typelist '>'"""
p[0] = TypeId(name=p[1], params=p[3])
p.slice[0].doccomments = p.slice[1].doccomments
def p_typelist(self, p):
"""typelist : type"""
p[0] = [p[1]]
def p_typelist_continue(self, p):
"""typelist : type ',' typelist"""
p[0] = list(p[3])
p[0].insert(0, p[1])
def p_error(self, t):
if not t:
raise IDLError(

View File

@ -31,6 +31,8 @@ invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
case nsXPTType::T_DOUBLE :
result++;
break;
default:
break;
}
}
return result;
@ -60,6 +62,7 @@ invoke_copy_to_stack(uint32_t paramCount, nsXPTCVariant* s, uint32_t* d)
case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break;
case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break;
case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
default : break;
}
}
}

View File

@ -57,6 +57,7 @@ PrepareAndDispatch(uint32_t methodIndex, nsXPTCStubBase* self, uint32_t* args)
case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); ap++; break;
case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*)ap); ap++; break;
case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
default : break;
}
}

View File

@ -57,6 +57,7 @@ PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args)
case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); ap++; break;
case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*)ap); ap++; break;
case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
default : break;
}
}

View File

@ -45,8 +45,6 @@ static_assert(offsetof(nsXPTCMiniVariant, val) == 0,
struct nsXPTCVariant
{
// No ctors or dtors so that we can use arrays of these on the stack with no
// penalty.
union ExtendedVal
{
// ExtendedVal is an extension on nsXPTCMiniVariant. It contains types
@ -60,6 +58,7 @@ struct nsXPTCVariant
nsCString nscstr;
nsString nsstr;
JS::Value jsval;
xpt::detail::UntypedTArray array;
// This type contains non-standard-layout types, so needs an explicit
// Ctor/Dtor - we'll just delete them.
@ -79,6 +78,12 @@ struct nsXPTCVariant
nsXPTType type;
uint8_t flags;
// Clear to a valid, null state.
nsXPTCVariant() {
memset(this, 0, sizeof(nsXPTCVariant));
type = nsXPTType::T_VOID;
}
enum
{
//
@ -88,22 +93,12 @@ struct nsXPTCVariant
// Indicates that we &val.p should be passed n the stack, i.e. that
// val should be passed by reference.
IS_INDIRECT = 0x1,
// Indicates that the value we hold requires some sort of cleanup (memory
// deallocation, interface release, JS::Value unrooting, etc). The precise
// cleanup that is performed depends on the 'type' field above.
// If the value is an array, this flag specifies whether the elements
// within the array require cleanup (we always clean up the array itself,
// so this flag would be redundant for that purpose).
VAL_NEEDS_CLEANUP = 0x2
};
void ClearFlags() {flags = 0;}
void SetIndirect() {flags |= IS_INDIRECT;}
void SetValNeedsCleanup() {flags |= VAL_NEEDS_CLEANUP;}
bool IsIndirect() const {return 0 != (flags & IS_INDIRECT);}
bool DoesValNeedCleanup() const {return 0 != (flags & VAL_NEEDS_CLEANUP);}
// Implicitly convert to nsXPTCMiniVariant.
operator nsXPTCMiniVariant&() {
@ -113,9 +108,8 @@ struct nsXPTCVariant
return *(const nsXPTCMiniVariant*) &val;
}
// As this type contains an anonymous union, we need to provide explicit
// constructors & destructors.
nsXPTCVariant() { }
// As this type contains an anonymous union, we need to provide an explicit
// destructor.
~nsXPTCVariant() { }
};

View File

@ -265,7 +265,7 @@ def link_to_cpp(interfaces, fd):
def describe_type(type): # Create the type's documentation comment.
tag = type['tag'][3:].lower()
if tag == 'array':
if tag == 'legacy_array':
return '%s[size_is=%d]' % (
describe_type(type['element']), type['size_is'])
elif tag == 'interface_type' or tag == 'domobject':
@ -280,10 +280,15 @@ def link_to_cpp(interfaces, fd):
tag = type['tag']
d1 = d2 = 0
if tag == 'TD_ARRAY':
if tag == 'TD_LEGACY_ARRAY':
d1 = type['size_is']
d2 = lower_extra_type(type['element'])
elif tag == 'TD_ARRAY':
# NOTE: TD_ARRAY can hold 16 bits of type index, while
# TD_LEGACY_ARRAY can only hold 8.
d1, d2 = splitint(lower_extra_type(type['element']))
elif tag == 'TD_INTERFACE_TYPE':
d1, d2 = splitint(interface_idx(type['name']))

View File

@ -18,6 +18,7 @@
#include "mozilla/Assertions.h"
#include "js/Value.h"
#include "nsString.h"
#include "nsTArray.h"
// Forward Declarations
namespace mozilla {
@ -152,6 +153,14 @@ static_assert(sizeof(nsXPTInterfaceInfo) == 28, "wrong size?");
*/
enum nsXPTTypeTag : uint8_t
{
// Arithmetic (POD) Types
// - Do not require cleanup,
// - All bit patterns are valid,
// - Outparams may be uninitialized by caller,
// - Directly supported in xptcall.
//
// NOTE: The name 'Arithmetic' comes from Harbison/Steele. Despite being a tad
// unclear, it is used frequently in xptcall, so is unlikely to be changed.
TD_INT8 = 0,
TD_INT16 = 1,
TD_INT32 = 2,
@ -165,24 +174,42 @@ enum nsXPTTypeTag : uint8_t
TD_BOOL = 10,
TD_CHAR = 11,
TD_WCHAR = 12,
_TD_LAST_ARITHMETIC = TD_WCHAR,
// Pointer Types
// - Require cleanup unless NULL,
// - All-zeros (NULL) bit pattern is valid,
// - Outparams may be uninitialized by caller,
// - Supported in xptcall as raw pointer.
TD_VOID = 13,
TD_PNSIID = 14,
TD_DOMSTRING = 15,
TD_PSTRING = 16,
TD_PWSTRING = 17,
TD_INTERFACE_TYPE = 18,
TD_INTERFACE_IS_TYPE = 19,
TD_ARRAY = 20,
TD_PSTRING_SIZE_IS = 21,
TD_PWSTRING_SIZE_IS = 22,
TD_UTF8STRING = 23,
TD_CSTRING = 24,
TD_ASTRING = 25,
TD_JSVAL = 26,
TD_DOMOBJECT = 27,
TD_PROMISE = 28
TD_PSTRING = 15,
TD_PWSTRING = 16,
TD_INTERFACE_TYPE = 17,
TD_INTERFACE_IS_TYPE = 18,
TD_LEGACY_ARRAY = 19,
TD_PSTRING_SIZE_IS = 20,
TD_PWSTRING_SIZE_IS = 21,
TD_DOMOBJECT = 22,
TD_PROMISE = 23,
_TD_LAST_POINTER = TD_PROMISE,
// Complex Types
// - Require cleanup,
// - Always passed indirectly,
// - Outparams must be initialized by caller,
// - Supported in xptcall due to indirection.
TD_DOMSTRING = 24,
TD_UTF8STRING = 25,
TD_CSTRING = 26,
TD_ASTRING = 27,
TD_JSVAL = 28,
TD_ARRAY = 29,
_TD_LAST_COMPLEX = TD_ARRAY
};
static_assert(_TD_LAST_COMPLEX < 32, "nsXPTTypeTag must fit in 5 bits");
/*
* A nsXPTType is a union used to identify the type of a method argument or
@ -193,27 +220,34 @@ enum nsXPTTypeTag : uint8_t
*/
struct nsXPTType
{
// NOTE: This is uint8_t instead of nsXPTTypeTag so that it can be compared
// with the nsXPTType::* re-exports.
uint8_t Tag() const { return mTag; }
nsXPTTypeTag Tag() const { return static_cast<nsXPTTypeTag>(mTag); }
// The index in the function argument list which should be used when
// determining the iid_is or size_is properties of this dependent type.
uint8_t ArgNum() const {
MOZ_ASSERT(Tag() == TD_INTERFACE_IS_TYPE ||
Tag() == TD_PSTRING_SIZE_IS ||
Tag() == TD_PWSTRING_SIZE_IS ||
Tag() == TD_ARRAY);
Tag() == TD_LEGACY_ARRAY);
return mData1;
}
const nsXPTType& ArrayElementType() const {
MOZ_ASSERT(Tag() == TD_ARRAY);
return xpt::detail::GetType(mData2);
}
private:
// Helper for reading 16-bit data values split between mData1 and mData2.
uint16_t Data16() const { return ((uint16_t)mData1 << 8) | mData2; }
public:
// Get the type of the element in the current array or sequence. Arrays only
// fit 8 bits of type data, while sequences support up to 16 bits of type data
// due to not needing to store an ArgNum.
const nsXPTType& ArrayElementType() const {
if (Tag() == TD_LEGACY_ARRAY) {
return xpt::detail::GetType(mData2);
}
MOZ_ASSERT(Tag() == TD_ARRAY);
return xpt::detail::GetType(Data16());
}
// We store the 16-bit iface value as two 8-bit values in order to
// avoid 16-bit alignment requirements for XPTTypeDescriptor, which
// reduces its size and also the size of XPTParamDescriptor.
@ -227,43 +261,44 @@ public:
return xpt::detail::GetDOMObjectInfo(Data16());
}
// 'Arithmetic' here roughly means that the value is self-contained and
// doesn't depend on anything else in memory (ie: not a pointer, not an
// XPCOM object, not a jsval, etc).
//
// Supposedly this terminology comes from Harbison/Steele, but it's still
// a rather crappy name. We'd change it if it wasn't used all over the
// place in xptcall. :-(
bool IsArithmetic() const { return Tag() <= TD_WCHAR; }
// See the comments in nsXPTTypeTag for an explanation as to what each of
// these categories mean.
bool IsArithmetic() const { return Tag() <= _TD_LAST_ARITHMETIC; }
bool IsPointer() const { return !IsArithmetic() && Tag() <= _TD_LAST_POINTER; }
bool IsComplex() const { return Tag() > _TD_LAST_POINTER; }
bool IsInterfacePointer() const {
return Tag() == TD_INTERFACE_TYPE || Tag() == TD_INTERFACE_IS_TYPE;
}
bool IsArray() const { return Tag() == TD_ARRAY; }
bool IsDependent() const {
return Tag() == TD_INTERFACE_IS_TYPE || Tag() == TD_ARRAY ||
return (Tag() == TD_ARRAY && InnermostType().IsDependent()) ||
Tag() == TD_INTERFACE_IS_TYPE || Tag() == TD_LEGACY_ARRAY ||
Tag() == TD_PSTRING_SIZE_IS || Tag() == TD_PWSTRING_SIZE_IS;
}
// Unwrap a nested type to its innermost value (e.g. through arrays).
const nsXPTType& InnermostType() const {
if (Tag() == TD_ARRAY) {
if (Tag() == TD_LEGACY_ARRAY || Tag() == TD_ARRAY) {
return ArrayElementType().InnermostType();
}
return *this;
}
// Helper methods for working with the type's native representation.
// In-memory size of native type in bytes.
inline size_t Stride() const;
inline bool HasPointerRepr() const;
// Offset the given base pointer to reference the element at the given index.
void* ElementPtr(const void* aBase, uint32_t aIndex) const {
return (char*)aBase + (aIndex * Stride());
}
// Zero out a native value of the given type. The type must not be 'complex'.
void ZeroValue(void* aValue) const {
MOZ_RELEASE_ASSERT(!IsComplex(), "Cannot zero a complex value");
memset(aValue, 0, Stride());
}
// Indexes into the extra types array of a small set of known types.
enum class Idx : uint8_t
{
@ -289,7 +324,7 @@ public:
// Helper methods for fabricating nsXPTType values used by xpconnect.
static nsXPTType MkArrayType(Idx aInner) {
MOZ_ASSERT(aInner <= Idx::INTERFACE_IS_TYPE);
return { TD_ARRAY, false, false, false, 0, (uint8_t)aInner };
return { TD_LEGACY_ARRAY, false, false, false, 0, (uint8_t)aInner };
}
static const nsXPTType& Get(Idx aInner) {
MOZ_ASSERT(aInner <= Idx::INTERFACE_IS_TYPE);
@ -300,42 +335,41 @@ public:
// nsXPTType backwards compatibility //
///////////////////////////////////////
nsXPTType& operator=(uint8_t aPrefix) { mTag = aPrefix; return *this; }
operator uint8_t() const { return TagPart(); };
uint8_t TagPart() const { return mTag; };
nsXPTType& operator=(nsXPTTypeTag aPrefix) { mTag = aPrefix; return *this; }
operator nsXPTTypeTag() const { return Tag(); }
enum // Re-export TD_ interfaces from nsXPTType
{
T_I8 = TD_INT8 ,
T_I16 = TD_INT16 ,
T_I32 = TD_INT32 ,
T_I64 = TD_INT64 ,
T_U8 = TD_UINT8 ,
T_U16 = TD_UINT16 ,
T_U32 = TD_UINT32 ,
T_U64 = TD_UINT64 ,
T_FLOAT = TD_FLOAT ,
T_DOUBLE = TD_DOUBLE ,
T_BOOL = TD_BOOL ,
T_CHAR = TD_CHAR ,
T_WCHAR = TD_WCHAR ,
T_VOID = TD_VOID ,
T_IID = TD_PNSIID ,
T_DOMSTRING = TD_DOMSTRING ,
T_CHAR_STR = TD_PSTRING ,
T_WCHAR_STR = TD_PWSTRING ,
T_INTERFACE = TD_INTERFACE_TYPE ,
T_INTERFACE_IS = TD_INTERFACE_IS_TYPE,
T_ARRAY = TD_ARRAY ,
T_PSTRING_SIZE_IS = TD_PSTRING_SIZE_IS ,
T_PWSTRING_SIZE_IS = TD_PWSTRING_SIZE_IS ,
T_UTF8STRING = TD_UTF8STRING ,
T_CSTRING = TD_CSTRING ,
T_ASTRING = TD_ASTRING ,
T_JSVAL = TD_JSVAL ,
T_DOMOBJECT = TD_DOMOBJECT ,
T_PROMISE = TD_PROMISE
};
#define TD_ALIAS_(name_, value_) static constexpr nsXPTTypeTag name_ = value_
TD_ALIAS_(T_I8 , TD_INT8 );
TD_ALIAS_(T_I16 , TD_INT16 );
TD_ALIAS_(T_I32 , TD_INT32 );
TD_ALIAS_(T_I64 , TD_INT64 );
TD_ALIAS_(T_U8 , TD_UINT8 );
TD_ALIAS_(T_U16 , TD_UINT16 );
TD_ALIAS_(T_U32 , TD_UINT32 );
TD_ALIAS_(T_U64 , TD_UINT64 );
TD_ALIAS_(T_FLOAT , TD_FLOAT );
TD_ALIAS_(T_DOUBLE , TD_DOUBLE );
TD_ALIAS_(T_BOOL , TD_BOOL );
TD_ALIAS_(T_CHAR , TD_CHAR );
TD_ALIAS_(T_WCHAR , TD_WCHAR );
TD_ALIAS_(T_VOID , TD_VOID );
TD_ALIAS_(T_IID , TD_PNSIID );
TD_ALIAS_(T_DOMSTRING , TD_DOMSTRING );
TD_ALIAS_(T_CHAR_STR , TD_PSTRING );
TD_ALIAS_(T_WCHAR_STR , TD_PWSTRING );
TD_ALIAS_(T_INTERFACE , TD_INTERFACE_TYPE );
TD_ALIAS_(T_INTERFACE_IS , TD_INTERFACE_IS_TYPE);
TD_ALIAS_(T_LEGACY_ARRAY , TD_LEGACY_ARRAY );
TD_ALIAS_(T_PSTRING_SIZE_IS , TD_PSTRING_SIZE_IS );
TD_ALIAS_(T_PWSTRING_SIZE_IS , TD_PWSTRING_SIZE_IS );
TD_ALIAS_(T_UTF8STRING , TD_UTF8STRING );
TD_ALIAS_(T_CSTRING , TD_CSTRING );
TD_ALIAS_(T_ASTRING , TD_ASTRING );
TD_ALIAS_(T_JSVAL , TD_JSVAL );
TD_ALIAS_(T_DOMOBJECT , TD_DOMOBJECT );
TD_ALIAS_(T_PROMISE , TD_PROMISE );
TD_ALIAS_(T_ARRAY , TD_ARRAY );
#undef TD_ALIAS_
////////////////////////////////////////////////////////////////
// Ensure these fields are in the same order as xptcodegen.py //
@ -376,15 +410,10 @@ struct nsXPTParamInfo
const nsXPTType& GetType() const { return Type(); } // XXX remove (backcompat)
// Whether this parameter is passed indirectly on the stack. All out/inout
// params are passed indirectly, although some types are passed indirectly
// unconditionally.
// params are passed indirectly, and complex types are always passed
// indirectly.
bool IsIndirect() const {
return IsOut() ||
mType.Tag() == TD_JSVAL ||
mType.Tag() == TD_ASTRING ||
mType.Tag() == TD_DOMSTRING ||
mType.Tag() == TD_CSTRING ||
mType.Tag() == TD_UTF8STRING;
return IsOut() || Type().IsComplex();
}
////////////////////////////////////////////////////////////////
@ -502,6 +531,34 @@ struct nsXPTDOMObjectInfo
namespace xpt {
namespace detail {
// The UntypedTArray type allows low-level access from XPConnect to nsTArray
// internals without static knowledge of the array element type in question.
class UntypedTArray
: public nsTArray_base<nsTArrayFallibleAllocator, nsTArray_CopyWithMemutils>
{
public:
void* Elements() const {
return static_cast<void*>(Hdr() + 1);
}
// Changes the length and capacity to be at least large enough for aTo elements.
bool SetLength(const nsXPTType& aEltTy, uint32_t aTo) {
if (!EnsureCapacity<nsTArrayFallibleAllocator>(aTo, aEltTy.Stride())) {
return false;
}
mHdr->mLength = aTo;
return true;
}
// Free backing memory for the nsTArray object.
void Clear() {
if (mHdr != EmptyHdr() && !UsesAutoArrayBuffer()) {
nsTArrayFallibleAllocator::Free(mHdr);
}
mHdr = EmptyHdr();
}
};
/**
* The compressed representation of constants from XPT. Not part of the public
* interface, as we also need to support Shim interfaces.
@ -593,39 +650,11 @@ GetString(uint32_t aIndex)
} // namespace detail
} // namespace xpt
inline bool
nsXPTType::HasPointerRepr() const
{
// This method should return `true` if the given type would be represented as
// a pointer when not passed indirectly.
switch (Tag()) {
case TD_VOID:
case TD_PNSIID:
case TD_PSTRING:
case TD_PWSTRING:
case TD_INTERFACE_TYPE:
case TD_INTERFACE_IS_TYPE:
case TD_ARRAY:
case TD_PSTRING_SIZE_IS:
case TD_PWSTRING_SIZE_IS:
case TD_DOMOBJECT:
case TD_PROMISE:
return true;
default:
return false;
}
}
inline size_t
nsXPTType::Stride() const
{
// Compute the stride to use when walking an array of the given type.
//
// NOTE: We cast to nsXPTTypeTag here so we get a warning if a type is missed
// in this switch statement. It's important that this method returns a value
// for every possible type.
switch (static_cast<nsXPTTypeTag>(Tag())) {
switch (Tag()) {
case TD_INT8: return sizeof(int8_t);
case TD_INT16: return sizeof(int16_t);
case TD_INT32: return sizeof(int32_t);
@ -639,6 +668,7 @@ nsXPTType::Stride() const
case TD_BOOL: return sizeof(bool);
case TD_CHAR: return sizeof(char);
case TD_WCHAR: return sizeof(char16_t);
case TD_VOID: return sizeof(void*);
case TD_PNSIID: return sizeof(nsIID*);
case TD_DOMSTRING: return sizeof(nsString);
@ -646,15 +676,17 @@ nsXPTType::Stride() const
case TD_PWSTRING: return sizeof(char16_t*);
case TD_INTERFACE_TYPE: return sizeof(nsISupports*);
case TD_INTERFACE_IS_TYPE: return sizeof(nsISupports*);
case TD_ARRAY: return sizeof(void*);
case TD_LEGACY_ARRAY: return sizeof(void*);
case TD_PSTRING_SIZE_IS: return sizeof(char*);
case TD_PWSTRING_SIZE_IS: return sizeof(char16_t*);
case TD_DOMOBJECT: return sizeof(void*);
case TD_PROMISE: return sizeof(void*);
case TD_UTF8STRING: return sizeof(nsCString);
case TD_CSTRING: return sizeof(nsCString);
case TD_ASTRING: return sizeof(nsString);
case TD_JSVAL: return sizeof(JS::Value);
case TD_DOMOBJECT: return sizeof(void*);
case TD_PROMISE: return sizeof(void*);
case TD_ARRAY: return sizeof(xpt::detail::UntypedTArray);
}
MOZ_CRASH("Unknown type");

Some files were not shown because too many files have changed in this diff Show More