Merge m-i to m-c, a=merge

This commit is contained in:
Phil Ringnalda 2015-09-13 11:58:18 -07:00
commit 3cfa3e89c4
176 changed files with 2141 additions and 945 deletions

View File

@ -32,7 +32,7 @@
@APPNAME@/Contents/Info.plist
@APPNAME@/Contents/PkgInfo
@APPNAME@/Contents/Plug-Ins/
@RESPATH@/b2g.icns
@RESPATH@/@MOZ_APP_NAME@.icns
@RESPATH@/@LPROJ_ROOT@.lproj/*
#endif

View File

@ -1747,6 +1747,9 @@ pref("security.mixed_content.block_active_content", true);
// 1 = allow MITM for certificate pinning checks.
pref("security.cert_pinning.enforcement_level", 1);
// 2 = allow SHA-1 only before 2016-01-01
pref("security.pki.sha1_enforcement_level", 2);
// Required blocklist freshness for OneCRL OCSP bypass
// (default is 1.25x extensions.blocklist.interval, or 30 hours)
pref("security.onecrl.maximum_staleness_in_seconds", 108000);

View File

@ -52,12 +52,15 @@ add_task(function* test() {
}
let win1 = yield BrowserTestUtils.openNewBrowserWindow();
yield new Promise(resolve => waitForFocus(resolve, win1));
yield new Promise(resolve => testPopupBlockerMenuItem(false, win1, resolve));
let win2 = yield BrowserTestUtils.openNewBrowserWindow({private: true});
yield new Promise(resolve => waitForFocus(resolve, win2));
yield new Promise(resolve => testPopupBlockerMenuItem(true, win2, resolve));
let win3 = yield BrowserTestUtils.openNewBrowserWindow();
yield new Promise(resolve => waitForFocus(resolve, win3));
yield new Promise(resolve => testPopupBlockerMenuItem(false, win3, resolve));
// Cleanup

View File

@ -57,7 +57,9 @@ function test() {
}
function testOnWindow(aIsPrivate, aCallback) {
let win = whenNewWindowLoaded({ private: aIsPrivate }, aCallback);
let win = whenNewWindowLoaded({ private: aIsPrivate }, function() {
waitForFocus(aCallback, win);
});
windowsToClose.push(win);
}

View File

@ -284,6 +284,8 @@ static CustomTypeAnnotation NonHeapClass =
CustomTypeAnnotation("moz_nonheap_class", "non-heap");
static CustomTypeAnnotation HeapClass =
CustomTypeAnnotation("moz_heap_class", "heap");
static CustomTypeAnnotation NonTemporaryClass =
CustomTypeAnnotation("moz_non_temporary_class", "non-temporary");
static CustomTypeAnnotation MustUse =
CustomTypeAnnotation("moz_must_use", "must-use");
static CustomTypeAnnotation NonMemMovable =
@ -845,6 +847,7 @@ DiagnosticsMatcher::DiagnosticsMatcher() {
astMatcher.addMatcher(
callExpr(callee(functionDecl(heapAllocator()))).bind("node"),
&scopeChecker);
astMatcher.addMatcher(parmVarDecl().bind("parm_vardecl"), &scopeChecker);
astMatcher.addMatcher(
callExpr(allOf(hasDeclaration(noArithmeticExprInArgs()),
@ -973,6 +976,12 @@ enum AllocationVariety {
AV_Heap,
};
// XXX Currently the Decl* in the AutomaticTemporaryMap is unused, but it
// probably will be used at some point in the future, in order to produce better
// error messages.
typedef DenseMap<const MaterializeTemporaryExpr *, const Decl *> AutomaticTemporaryMap;
AutomaticTemporaryMap AutomaticTemporaries;
void DiagnosticsMatcher::ScopeChecker::run(
const MatchFinder::MatchResult &Result) {
DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
@ -982,6 +991,20 @@ void DiagnosticsMatcher::ScopeChecker::run(
SourceLocation Loc;
QualType T;
if (const ParmVarDecl *D = Result.Nodes.getNodeAs<ParmVarDecl>("parm_vardecl")) {
if (const Expr *Default = D->getDefaultArg()) {
if (const MaterializeTemporaryExpr *E = dyn_cast<MaterializeTemporaryExpr>(Default)) {
// We have just found a ParmVarDecl which has, as its default argument,
// a MaterializeTemporaryExpr. We mark that MaterializeTemporaryExpr as
// automatic, by adding it to the AutomaticTemporaryMap.
// Reporting on this type will occur when the MaterializeTemporaryExpr
// is matched against.
AutomaticTemporaries[E] = D;
}
}
return;
}
// Determine the type of allocation which we detected
if (const VarDecl *D = Result.Nodes.getNodeAs<VarDecl>("node")) {
if (D->hasGlobalStorage()) {
@ -1000,9 +1023,39 @@ void DiagnosticsMatcher::ScopeChecker::run(
T = E->getAllocatedType();
Loc = E->getLocStart();
}
} else if (const Expr *E =
} else if (const MaterializeTemporaryExpr *E =
Result.Nodes.getNodeAs<MaterializeTemporaryExpr>("node")) {
Variety = AV_Temporary;
// Temporaries can actually have varying storage durations, due to temporary
// lifetime extension. We consider the allocation variety of this temporary
// to be the same as the allocation variety of its lifetime.
// XXX We maybe should mark these lifetimes as being due to a temporary
// which has had its lifetime extended, to improve the error messages.
switch (E->getStorageDuration()) {
case SD_FullExpression:
{
// Check if this temporary is allocated as a default argument!
// if it is, we want to pretend that it is automatic.
AutomaticTemporaryMap::iterator AutomaticTemporary = AutomaticTemporaries.find(E);
if (AutomaticTemporary != AutomaticTemporaries.end()) {
Variety = AV_Automatic;
} else {
Variety = AV_Temporary;
}
}
break;
case SD_Automatic:
Variety = AV_Automatic;
break;
case SD_Thread:
case SD_Static:
Variety = AV_Global;
break;
case SD_Dynamic:
assert(false && "I don't think that this ever should occur...");
Variety = AV_Heap;
break;
}
T = E->getType().getUnqualifiedType();
Loc = E->getLocStart();
} else if (const CallExpr *E = Result.Nodes.getNodeAs<CallExpr>("node")) {
@ -1024,6 +1077,8 @@ void DiagnosticsMatcher::ScopeChecker::run(
DiagnosticIDs::Error, "variable of type %0 only valid on the heap");
unsigned NonHeapID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Error, "variable of type %0 is not valid on the heap");
unsigned NonTemporaryID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Error, "variable of type %0 is not valid in a temporary");
unsigned StackNoteID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Note,
@ -1053,6 +1108,8 @@ void DiagnosticsMatcher::ScopeChecker::run(
case AV_Temporary:
GlobalClass.reportErrorIfPresent(Diag, T, Loc, GlobalID, TemporaryNoteID);
HeapClass.reportErrorIfPresent(Diag, T, Loc, HeapID, TemporaryNoteID);
NonTemporaryClass.reportErrorIfPresent(Diag, T, Loc,
NonTemporaryID, TemporaryNoteID);
break;
case AV_Heap:

View File

@ -0,0 +1,70 @@
#define MOZ_NON_TEMPORARY_CLASS __attribute__((annotate("moz_non_temporary_class")))
#define MOZ_IMPLICIT __attribute__((annotate("moz_implicit")))
#include <stddef.h>
struct MOZ_NON_TEMPORARY_CLASS NonTemporary {
int i;
NonTemporary() {}
MOZ_IMPLICIT NonTemporary(int i) {}
NonTemporary(int i, int j) {}
void *operator new(size_t x) throw() { return 0; }
void *operator new(size_t blah, char *buffer) { return buffer; }
};
template <class T>
struct MOZ_NON_TEMPORARY_CLASS TemplateClass {
T i;
};
void gobble(void *) { }
void gobbleref(const NonTemporary&) { }
template <class T>
void gobbleanyref(const T&) { }
void misuseNonTemporaryClass(int len) {
NonTemporary invalid;
NonTemporary alsoInvalid[2];
static NonTemporary invalidStatic;
static NonTemporary alsoInvalidStatic[2];
gobble(&invalid);
gobble(&invalidStatic);
gobble(&alsoInvalid[0]);
gobbleref(NonTemporary()); // expected-error {{variable of type 'NonTemporary' is not valid in a temporary}} expected-note {{value incorrectly allocated in a temporary}}
gobbleref(NonTemporary(10, 20)); // expected-error {{variable of type 'NonTemporary' is not valid in a temporary}} expected-note {{value incorrectly allocated in a temporary}}
gobbleref(NonTemporary(10)); // expected-error {{variable of type 'NonTemporary' is not valid in a temporary}} expected-note {{value incorrectly allocated in a temporary}}
gobbleref(10); // expected-error {{variable of type 'NonTemporary' is not valid in a temporary}} expected-note {{value incorrectly allocated in a temporary}}
gobbleanyref(TemplateClass<int>()); // expected-error {{variable of type 'TemplateClass<int>' is not valid in a temporary}} expected-note {{value incorrectly allocated in a temporary}}
gobble(new NonTemporary);
gobble(new NonTemporary[10]);
gobble(new TemplateClass<int>);
gobble(len <= 5 ? &invalid : new NonTemporary);
char buffer[sizeof(NonTemporary)];
gobble(new (buffer) NonTemporary);
}
void defaultArg(const NonTemporary& arg = NonTemporary()) {
}
NonTemporary invalidStatic;
struct RandomClass {
NonTemporary nonstaticMember; // expected-note {{'RandomClass' is a non-temporary type because member 'nonstaticMember' is a non-temporary type 'NonTemporary'}}
static NonTemporary staticMember;
};
struct MOZ_NON_TEMPORARY_CLASS RandomNonTemporaryClass {
NonTemporary nonstaticMember;
static NonTemporary staticMember;
};
struct BadInherit : NonTemporary {}; // expected-note {{'BadInherit' is a non-temporary type because it inherits from a non-temporary type 'NonTemporary'}}
void useStuffWrongly() {
gobbleanyref(BadInherit()); // expected-error {{variable of type 'BadInherit' is not valid in a temporary}} expected-note {{value incorrectly allocated in a temporary}}
gobbleanyref(RandomClass()); // expected-error {{variable of type 'RandomClass' is not valid in a temporary}} expected-note {{value incorrectly allocated in a temporary}}
}

View File

@ -24,6 +24,7 @@ SOURCES += [
'TestNoExplicitMoveConstructor.cpp',
'TestNonHeapClass.cpp',
'TestNonMemMovable.cpp',
'TestNonTemporaryClass.cpp',
'TestNoRefcountedInsideLambdas.cpp',
'TestStackClass.cpp',
'TestTrivialCtorDtor.cpp',

View File

@ -29,7 +29,7 @@ namespace mozilla {
// cc->Collect();
// ...
// }
class MOZ_STACK_CLASS AutoGlobalTimelineMarker
class MOZ_RAII AutoGlobalTimelineMarker
{
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER;

View File

@ -28,7 +28,7 @@ namespace mozilla {
// nsresult rv = ParseTheCSSFile(mFile);
// ...
// }
class MOZ_STACK_CLASS AutoTimelineMarker
class MOZ_RAII AutoTimelineMarker
{
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER;

View File

@ -35,7 +35,6 @@
#include "nsContentUtils.h"
#include "mozilla/Preferences.h"
#include "xpcpublic.h"
#include "nsCORSListenerProxy.h"
#include "nsWrapperCacheInlines.h"
#include "mozilla/Attributes.h"
#include "nsError.h"

View File

@ -814,6 +814,7 @@ nsIContent::PreHandleEvent(EventChainPreVisitor& aVisitor)
case eFormReset:
case eResize:
case eScroll:
case NS_SELECT_START:
stopEvent = true;
break;
case eUnidentifiedEvent:
@ -827,8 +828,7 @@ nsIContent::PreHandleEvent(EventChainPreVisitor& aVisitor)
eventType.EqualsLiteral("load") ||
eventType.EqualsLiteral("reset") ||
eventType.EqualsLiteral("resize") ||
eventType.EqualsLiteral("scroll") ||
eventType.EqualsLiteral("selectstart")) {
eventType.EqualsLiteral("scroll")) {
stopEvent = true;
}
}

View File

@ -10,7 +10,6 @@
#include "HTMLLinkElement.h"
#include "nsContentPolicyUtils.h"
#include "nsContentUtils.h"
#include "nsCORSListenerProxy.h"
#include "nsIChannel.h"
#include "nsIContentPolicy.h"
#include "nsIContentSecurityPolicy.h"

View File

@ -68,6 +68,7 @@
#include "nsComponentManagerUtils.h"
#include "nsIStringStream.h"
#include "nsIHttpChannel.h"
#include "nsIHttpChannelInternal.h"
#include "TimeManager.h"
#include "DeviceStorage.h"
#include "nsIDOMNavigatorSystemMessages.h"
@ -1322,18 +1323,24 @@ Navigator::SendBeacon(const nsAString& aUrl,
nsCOMPtr<nsIInterfaceRequestor> soc = nsContentUtils::SameOriginChecker();
channel->SetNotificationCallbacks(soc);
nsCOMPtr<nsIChannel> preflightChannel;
nsCOMPtr<nsIHttpChannelInternal> internalChannel =
do_QueryInterface(channel);
if (!internalChannel) {
aRv.Throw(NS_ERROR_FAILURE);
return false;
}
nsTArray<nsCString> unsafeHeaders;
unsafeHeaders.AppendElement(NS_LITERAL_CSTRING("Content-Type"));
rv = NS_StartCORSPreflight(channel,
beaconListener,
doc->NodePrincipal(),
true,
unsafeHeaders,
getter_AddRefs(preflightChannel));
} else {
rv = channel->AsyncOpen2(beaconListener);
rv = internalChannel->SetCorsPreflightParameters(unsafeHeaders,
true,
doc->NodePrincipal());
if (NS_WARN_IF(NS_FAILED(rv))) {
aRv.Throw(rv);
return false;
}
}
rv = channel->AsyncOpen2(beaconListener);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return false;

View File

@ -412,7 +412,7 @@ private:
* passed as a parameter. AutoJSContext will take care of finding the most
* appropriate JS context and release it when leaving the stack.
*/
class MOZ_STACK_CLASS AutoJSContext {
class MOZ_RAII AutoJSContext {
public:
explicit AutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
operator JSContext*() const;
@ -434,7 +434,7 @@ protected:
* Use ThreadsafeAutoJSContext when you want an AutoJSContext but might be
* running on a worker thread.
*/
class MOZ_STACK_CLASS ThreadsafeAutoJSContext {
class MOZ_RAII ThreadsafeAutoJSContext {
public:
explicit ThreadsafeAutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
operator JSContext*() const;
@ -452,7 +452,7 @@ private:
*
* Note - This is deprecated. Please use AutoJSAPI instead.
*/
class MOZ_STACK_CLASS AutoSafeJSContext : public AutoJSContext {
class MOZ_RAII AutoSafeJSContext : public AutoJSContext {
public:
explicit AutoSafeJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
private:
@ -462,7 +462,7 @@ private:
/**
* Like AutoSafeJSContext but can be used safely on worker threads.
*/
class MOZ_STACK_CLASS ThreadsafeAutoSafeJSContext {
class MOZ_RAII ThreadsafeAutoSafeJSContext {
public:
explicit ThreadsafeAutoSafeJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
operator JSContext*() const;

View File

@ -2651,7 +2651,7 @@ private:
#endif
};
class MOZ_STACK_CLASS nsAutoScriptBlocker {
class MOZ_RAII nsAutoScriptBlocker {
public:
explicit nsAutoScriptBlocker(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) {
MOZ_GUARD_OBJECT_NOTIFIER_INIT;

View File

@ -634,7 +634,7 @@ AllDescendantsOfType(nsIDocShellTreeItem* aParentItem, int32_t aType)
* A class that automatically sets mInShow to false when it goes
* out of scope.
*/
class MOZ_STACK_CLASS AutoResetInShow {
class MOZ_RAII AutoResetInShow {
private:
nsFrameLoader* mFrameLoader;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
@ -989,7 +989,7 @@ nsFrameLoader::SwapWithOtherRemoteLoader(nsFrameLoader* aOther,
return NS_OK;
}
class MOZ_STACK_CLASS AutoResetInFrameSwap final
class MOZ_RAII AutoResetInFrameSwap final
{
public:
AutoResetInFrameSwap(nsFrameLoader* aThisFrameLoader,

View File

@ -882,6 +882,8 @@ GK_ATOM(onscanningstatechanged, "onscanningstatechanged")
GK_ATOM(onscostatuschanged, "onscostatuschanged")
GK_ATOM(onscroll, "onscroll")
GK_ATOM(onselect, "onselect")
GK_ATOM(onselectionchange, "onselectionchange")
GK_ATOM(onselectstart, "onselectstart")
GK_ATOM(onsending, "onsending")
GK_ATOM(onsent, "onsent")
GK_ATOM(onset, "onset")

View File

@ -31,6 +31,7 @@
#include "mozilla/dom/RangeBinding.h"
#include "mozilla/dom/DOMRect.h"
#include "mozilla/dom/ShadowRoot.h"
#include "mozilla/dom/Selection.h"
#include "mozilla/Telemetry.h"
#include "mozilla/Likely.h"
#include "nsCSSFrameConstructor.h"
@ -194,6 +195,26 @@ nsRange::~nsRange()
DoSetRange(nullptr, 0, nullptr, 0, nullptr);
}
nsRange::nsRange(nsINode* aNode)
: mRoot(nullptr)
, mStartOffset(0)
, mEndOffset(0)
, mIsPositioned(false)
, mIsDetached(false)
, mMaySpanAnonymousSubtrees(false)
, mIsGenerated(false)
, mStartOffsetWasIncremented(false)
, mEndOffsetWasIncremented(false)
, mEnableGravitationOnElementRemoval(true)
#ifdef DEBUG
, mAssertNextInsertOrAppendIndex(-1)
, mAssertNextInsertOrAppendNode(nullptr)
#endif
{
MOZ_ASSERT(aNode, "range isn't in a document!");
mOwner = aNode->OwnerDoc();
}
/* static */
nsresult
nsRange::CreateRange(nsINode* aStartParent, int32_t aStartOffset,
@ -269,6 +290,10 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsRange)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner);
tmp->Reset();
// This needs to be unlinked after Reset() is called, as it controls
// the result of IsInSelection() which is used by tmp->Reset().
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSelection);
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsRange)
@ -276,6 +301,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsRange)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStartParent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEndParent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRoot)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSelection)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@ -879,14 +905,20 @@ nsRange::DoSetRange(nsINode* aStartN, int32_t aStartOffset,
RegisterCommonAncestor(newCommonAncestor);
} else {
NS_ASSERTION(!mIsPositioned, "unexpected disconnected nodes");
mInSelection = false;
mSelection = nullptr;
}
}
}
// This needs to be the last thing this function does. See comment
// in ParentChainChanged.
// This needs to be the last thing this function does, other than notifying
// selection listeners. See comment in ParentChainChanged.
mRoot = aRoot;
// Notify any selection listeners. This has to occur last because otherwise the world
// could be observed by a selection listener while the range was in an invalid state.
if (mSelection) {
mSelection->NotifySelectionListeners();
}
}
static int32_t
@ -897,6 +929,28 @@ IndexOf(nsINode* aChild)
return parent ? parent->IndexOf(aChild) : -1;
}
void
nsRange::SetSelection(mozilla::dom::Selection* aSelection)
{
if (mSelection == aSelection) {
return;
}
// At least one of aSelection and mSelection must be null
// aSelection will be null when we are removing from a selection
// and a range can't be in more than one selection at a time,
// thus mSelection must be null too.
MOZ_ASSERT(!aSelection || !mSelection);
mSelection = aSelection;
nsINode* commonAncestor = GetCommonAncestor();
NS_ASSERTION(commonAncestor, "unexpected disconnected nodes");
if (mSelection) {
RegisterCommonAncestor(commonAncestor);
} else {
UnregisterCommonAncestor(commonAncestor);
}
}
nsINode*
nsRange::GetCommonAncestor() const
{

View File

@ -28,6 +28,7 @@ namespace dom {
class DocumentFragment;
class DOMRect;
class DOMRectList;
class Selection;
} // namespace dom
} // namespace mozilla
@ -42,26 +43,7 @@ class nsRange final : public nsIDOMRange,
virtual ~nsRange();
public:
explicit nsRange(nsINode* aNode)
: mRoot(nullptr)
, mStartOffset(0)
, mEndOffset(0)
, mIsPositioned(false)
, mIsDetached(false)
, mMaySpanAnonymousSubtrees(false)
, mInSelection(false)
, mIsGenerated(false)
, mStartOffsetWasIncremented(false)
, mEndOffsetWasIncremented(false)
, mEnableGravitationOnElementRemoval(true)
#ifdef DEBUG
, mAssertNextInsertOrAppendIndex(-1)
, mAssertNextInsertOrAppendNode(nullptr)
#endif
{
MOZ_ASSERT(aNode, "range isn't in a document!");
mOwner = aNode->OwnerDoc();
}
explicit nsRange(nsINode* aNode);
static nsresult CreateRange(nsIDOMNode* aStartParent, int32_t aStartOffset,
nsIDOMNode* aEndParent, int32_t aEndOffset,
@ -129,31 +111,18 @@ public:
}
/**
* Return true iff this range is part of at least one Selection object
* Return true iff this range is part of a Selection object
* and isn't detached.
*/
bool IsInSelection() const
{
return mInSelection;
return !!mSelection;
}
/**
* Called when the range is added/removed from a Selection.
*/
void SetInSelection(bool aInSelection)
{
if (mInSelection == aInSelection) {
return;
}
mInSelection = aInSelection;
nsINode* commonAncestor = GetCommonAncestor();
NS_ASSERTION(commonAncestor, "unexpected disconnected nodes");
if (mInSelection) {
RegisterCommonAncestor(commonAncestor);
} else {
UnregisterCommonAncestor(commonAncestor);
}
}
void SetSelection(mozilla::dom::Selection* aSelection);
/**
* Return true if this range was generated.
@ -349,13 +318,13 @@ protected:
nsCOMPtr<nsINode> mRoot;
nsCOMPtr<nsINode> mStartParent;
nsCOMPtr<nsINode> mEndParent;
nsRefPtr<mozilla::dom::Selection> mSelection;
int32_t mStartOffset;
int32_t mEndOffset;
bool mIsPositioned : 1;
bool mIsDetached : 1;
bool mMaySpanAnonymousSubtrees : 1;
bool mInSelection : 1;
bool mIsGenerated : 1;
bool mStartOffsetWasIncremented : 1;
bool mEndOffsetWasIncremented : 1;

View File

@ -486,7 +486,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXMLHttpRequest,
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContext)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChannel)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResponseXML)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCORSPreflightChannel)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mXMLParserStreamListener)
@ -508,7 +507,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXMLHttpRequest,
NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mChannel)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mResponseXML)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCORSPreflightChannel)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mXMLParserStreamListener)
@ -1210,9 +1208,6 @@ nsXMLHttpRequest::CloseRequestWithError(const nsAString& aType,
if (mChannel) {
mChannel->Cancel(NS_BINDING_ABORTED);
}
if (mCORSPreflightChannel) {
mCORSPreflightChannel->Cancel(NS_BINDING_ABORTED);
}
if (mTimeoutTimer) {
mTimeoutTimer->Cancel();
}
@ -2347,7 +2342,6 @@ nsXMLHttpRequest::ChangeStateToDone()
// methods/members will not throw.
// This matches what IE does.
mChannel = nullptr;
mCORSPreflightChannel = nullptr;
}
}
@ -2891,36 +2885,33 @@ nsXMLHttpRequest::Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
// Check to see if this initial OPTIONS request has already been cached
// in our special Access Control Cache.
rv = NS_StartCORSPreflight(mChannel, listener,
mPrincipal, withCredentials,
mCORSUnsafeHeaders,
getter_AddRefs(mCORSPreflightChannel));
rv = internalHttpChannel->SetCorsPreflightParameters(mCORSUnsafeHeaders,
withCredentials, mPrincipal);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
mIsMappedArrayBuffer = false;
if (mResponseType == XML_HTTP_RESPONSE_TYPE_ARRAYBUFFER &&
Preferences::GetBool("dom.mapped_arraybuffer.enabled", false)) {
nsCOMPtr<nsIURI> uri;
nsAutoCString scheme;
rv = mChannel->GetURI(getter_AddRefs(uri));
if (NS_SUCCEEDED(rv)) {
uri->GetScheme(scheme);
if (scheme.LowerCaseEqualsLiteral("app") ||
scheme.LowerCaseEqualsLiteral("jar")) {
mIsMappedArrayBuffer = true;
}
mIsMappedArrayBuffer = false;
if (mResponseType == XML_HTTP_RESPONSE_TYPE_ARRAYBUFFER &&
Preferences::GetBool("dom.mapped_arraybuffer.enabled", false)) {
nsCOMPtr<nsIURI> uri;
nsAutoCString scheme;
rv = mChannel->GetURI(getter_AddRefs(uri));
if (NS_SUCCEEDED(rv)) {
uri->GetScheme(scheme);
if (scheme.LowerCaseEqualsLiteral("app") ||
scheme.LowerCaseEqualsLiteral("jar")) {
mIsMappedArrayBuffer = true;
}
}
// Start reading from the channel
rv = mChannel->AsyncOpen(listener, nullptr);
}
if (NS_FAILED(rv)) {
// Start reading from the channel
rv = mChannel->AsyncOpen(listener, nullptr);
if (NS_WARN_IF(NS_FAILED(rv))) {
// Drop our ref to the channel to avoid cycles
mChannel = nullptr;
mCORSPreflightChannel = nullptr;
return rv;
}
@ -3013,19 +3004,6 @@ nsXMLHttpRequest::SetRequestHeader(const nsACString& header,
return NS_ERROR_DOM_SYNTAX_ERR;
}
// Check that we haven't already opened the channel. We can't rely on
// the channel throwing from mChannel->SetRequestHeader since we might
// still be waiting for mCORSPreflightChannel to actually open mChannel
if (mCORSPreflightChannel) {
bool pending;
nsresult rv = mCORSPreflightChannel->IsPending(&pending);
NS_ENSURE_SUCCESS(rv, rv);
if (pending) {
return NS_ERROR_IN_PROGRESS;
}
}
if (!mChannel) // open() initializes mChannel, and open()
return NS_ERROR_FAILURE; // must be called before first setRequestHeader()

View File

@ -643,7 +643,6 @@ protected:
nsCOMPtr<nsIPrincipal> mPrincipal;
nsCOMPtr<nsIChannel> mChannel;
nsCOMPtr<nsIDocument> mResponseXML;
nsCOMPtr<nsIChannel> mCORSPreflightChannel;
nsTArray<nsCString> mCORSUnsafeHeaders;
nsCOMPtr<nsIStreamListener> mXMLParserStreamListener;

View File

@ -2266,7 +2266,7 @@ void DoTraceSequence(JSTracer* trc, InfallibleTArray<T>& seq)
// Rooter class for sequences; this is what we mostly use in the codegen
template<typename T>
class MOZ_STACK_CLASS SequenceRooter : private JS::CustomAutoRooter
class MOZ_RAII SequenceRooter : private JS::CustomAutoRooter
{
public:
SequenceRooter(JSContext *aCx, FallibleTArray<T>* aSequence
@ -2325,7 +2325,7 @@ public:
// Rooter class for MozMap; this is what we mostly use in the codegen.
template<typename T>
class MOZ_STACK_CLASS MozMapRooter : private JS::CustomAutoRooter
class MOZ_RAII MozMapRooter : private JS::CustomAutoRooter
{
public:
MozMapRooter(JSContext *aCx, MozMap<T>* aMozMap
@ -2371,8 +2371,8 @@ private:
};
template<typename T>
class MOZ_STACK_CLASS RootedUnion : public T,
private JS::CustomAutoRooter
class MOZ_RAII RootedUnion : public T,
private JS::CustomAutoRooter
{
public:
explicit RootedUnion(JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) :

View File

@ -15,7 +15,7 @@ namespace mozilla {
namespace dom {
template<typename T>
class MOZ_STACK_CLASS RootedDictionary : public T,
class MOZ_RAII RootedDictionary : public T,
private JS::CustomAutoRooter
{
public:
@ -32,7 +32,7 @@ public:
};
template<typename T>
class MOZ_STACK_CLASS NullableRootedDictionary : public Nullable<T>,
class MOZ_RAII NullableRootedDictionary : public Nullable<T>,
private JS::CustomAutoRooter
{
public:

View File

@ -327,7 +327,7 @@ class TypedArrayCreator
// A class for rooting an existing TypedArray struct
template<typename ArrayType>
class MOZ_STACK_CLASS TypedArrayRooter : private JS::CustomAutoRooter
class MOZ_RAII TypedArrayRooter : private JS::CustomAutoRooter
{
public:
TypedArrayRooter(JSContext* cx,
@ -349,7 +349,7 @@ private:
// And a specialization for dealing with nullable typed arrays
template<typename Inner> struct Nullable;
template<typename ArrayType>
class MOZ_STACK_CLASS TypedArrayRooter<Nullable<ArrayType> > :
class MOZ_RAII TypedArrayRooter<Nullable<ArrayType> > :
private JS::CustomAutoRooter
{
public:
@ -373,8 +373,8 @@ private:
// Class for easily setting up a rooted typed array object on the stack
template<typename ArrayType>
class MOZ_STACK_CLASS RootedTypedArray : public ArrayType,
private TypedArrayRooter<ArrayType>
class MOZ_RAII RootedTypedArray : public ArrayType,
private TypedArrayRooter<ArrayType>
{
public:
explicit RootedTypedArray(JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) :

View File

@ -350,6 +350,10 @@ EVENT(lostpointercapture,
ePointerLostCapture,
EventNameType_All,
ePointerEventClass)
EVENT(selectstart,
NS_SELECT_START,
EventNameType_HTMLXUL,
eBasicEventClass)
// Not supported yet; probably never because "wheel" is a better idea.
// EVENT(mousewheel)
@ -584,6 +588,10 @@ DOCUMENT_ONLY_EVENT(readystatechange,
eReadyStateChange,
EventNameType_HTMLXUL,
eBasicEventClass)
DOCUMENT_ONLY_EVENT(selectionchange,
NS_SELECTION_CHANGE,
EventNameType_HTMLXUL,
eBasicEventClass)
NON_IDL_EVENT(MozMouseHittest,
eMouseHitTest,

View File

@ -618,18 +618,19 @@ FetchDriver::HttpFetch(bool aCORSFlag, bool aCORSPreflightFlag, bool aAuthentica
if (aCORSPreflightFlag) {
MOZ_ASSERT(mRequest->Mode() != RequestMode::No_cors,
"FetchDriver::ContinueFetch() should ensure that the request is not no-cors");
nsCOMPtr<nsIChannel> preflightChannel;
MOZ_ASSERT(httpChan, "CORS preflight can only be used with HTTP channels");
nsAutoTArray<nsCString, 5> unsafeHeaders;
mRequest->Headers()->GetUnsafeHeaders(unsafeHeaders);
rv = NS_StartCORSPreflight(chan, listener, mPrincipal,
useCredentials,
unsafeHeaders,
getter_AddRefs(preflightChannel));
} else {
rv = chan->AsyncOpen(listener, nullptr);
nsCOMPtr<nsIHttpChannelInternal> internalChan = do_QueryInterface(httpChan);
rv = internalChan->SetCorsPreflightParameters(unsafeHeaders, useCredentials, mPrincipal);
if (NS_WARN_IF(NS_FAILED(rv))) {
return FailWithNetworkError();
}
}
rv = chan->AsyncOpen(listener, nullptr);
if (NS_WARN_IF(NS_FAILED(rv))) {
return FailWithNetworkError();
}

View File

@ -53,7 +53,6 @@
#include "nsIContentPolicy.h"
#include "nsContentPolicyUtils.h"
#include "nsCORSListenerProxy.h"
#include "nsCycleCollectionParticipant.h"
#include "nsICachingChannel.h"
#include "nsLayoutUtils.h"

View File

@ -93,6 +93,9 @@ public:
return NS_OK;
}
AutoHideSelectionChanges hideSelectionChanges
(mFrame->GetConstFrameSelection());
if (mFrame) {
// SetSelectionRange leads to Selection::AddRange which flushes Layout -
// need to block script to avoid nested PrepareEditor calls (bug 642800).
@ -1248,6 +1251,8 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
return NS_OK;
}
AutoHideSelectionChanges hideSelectionChanges(GetConstFrameSelection());
// Don't attempt to initialize recursively!
InitializationGuard guard(*this);
if (guard.IsInitializingRecursively()) {

View File

@ -562,37 +562,16 @@ nsresult ChannelMediaResource::OpenChannel(nsIStreamListener** aStreamListener)
nsresult rv = mChannel->SetNotificationCallbacks(mListener.get());
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIStreamListener> listener = mListener.get();
// Ensure that if we're loading cross domain, that the server is sending
// an authorizing Access-Control header.
MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
NS_ENSURE_TRUE(owner, NS_ERROR_FAILURE);
dom::HTMLMediaElement* element = owner->GetMediaElement();
NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
if (element->ShouldCheckAllowOrigin()) {
nsRefPtr<nsCORSListenerProxy> crossSiteListener =
new nsCORSListenerProxy(mListener,
element->NodePrincipal(),
false);
NS_ENSURE_TRUE(crossSiteListener, NS_ERROR_OUT_OF_MEMORY);
rv = crossSiteListener->Init(mChannel, DataURIHandling::Allow);
NS_ENSURE_SUCCESS(rv, rv);
listener = crossSiteListener;
} else {
rv = nsContentUtils::GetSecurityManager()->
CheckLoadURIWithPrincipal(element->NodePrincipal(),
mURI,
nsIScriptSecurityManager::STANDARD);
NS_ENSURE_SUCCESS(rv, rv);
}
rv = SetupChannelHeaders();
NS_ENSURE_SUCCESS(rv, rv);
rv = mChannel->AsyncOpen(listener, nullptr);
rv = mChannel->AsyncOpen2(mListener);
NS_ENSURE_SUCCESS(rv, rv);
// Tell the media element that we are fetching data from a channel.
MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
NS_ENSURE_TRUE(owner, NS_ERROR_FAILURE);
dom::HTMLMediaElement* element = owner->GetMediaElement();
element->DownloadResumed(true);
}
@ -869,14 +848,9 @@ ChannelMediaResource::RecreateChannel()
nsCOMPtr<nsILoadGroup> loadGroup = element->GetDocumentLoadGroup();
NS_ENSURE_TRUE(loadGroup, NS_ERROR_NULL_POINTER);
nsSecurityFlags securityFlags = nsILoadInfo::SEC_NORMAL;
if (nsContentUtils::ChannelShouldInheritPrincipal(element->NodePrincipal(),
mURI,
false, // aInheritForAboutBlank
false // aForceInherit
)) {
securityFlags = nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
}
nsSecurityFlags securityFlags = element->ShouldCheckAllowOrigin()
? nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS
: nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS;
MOZ_ASSERT(element->IsAnyOfHTMLElements(nsGkAtoms::audio, nsGkAtoms::video));
nsContentPolicyType contentPolicyType = element->IsHTMLElement(nsGkAtoms::audio) ?
@ -1374,20 +1348,16 @@ nsresult FileMediaResource::Open(nsIStreamListener** aStreamListener)
rv = NS_GetStreamForBlobURI(mURI, getter_AddRefs(mInput));
}
} else {
// Ensure that we never load a local file from some page on a
// web server.
MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
NS_ENSURE_TRUE(owner, NS_ERROR_FAILURE);
dom::HTMLMediaElement* element = owner->GetMediaElement();
NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
rv = nsContentUtils::GetSecurityManager()->
CheckLoadURIWithPrincipal(element->NodePrincipal(),
mURI,
nsIScriptSecurityManager::STANDARD);
NS_ENSURE_SUCCESS(rv, rv);
rv = mChannel->Open(getter_AddRefs(mInput));
#ifdef DEBUG
{
nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
MOZ_ASSERT((loadInfo->GetSecurityMode() &
nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) == 0,
"can not enforce CORS when calling Open2()");
}
#endif
rv = mChannel->Open2(getter_AddRefs(mInput));
}
NS_ENSURE_SUCCESS(rv, rv);
@ -1451,14 +1421,9 @@ already_AddRefed<MediaResource> FileMediaResource::CloneData(MediaDecoder* aDeco
nsCOMPtr<nsILoadGroup> loadGroup = element->GetDocumentLoadGroup();
NS_ENSURE_TRUE(loadGroup, nullptr);
nsSecurityFlags securityFlags = nsILoadInfo::SEC_NORMAL;
if (nsContentUtils::ChannelShouldInheritPrincipal(element->NodePrincipal(),
mURI,
false, // aInheritForAboutBlank
false // aForceInherit
)) {
securityFlags = nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
}
nsSecurityFlags securityFlags = element->ShouldCheckAllowOrigin()
? nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS
: nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS;
MOZ_ASSERT(element->IsAnyOfHTMLElements(nsGkAtoms::audio, nsGkAtoms::video));
nsContentPolicyType contentPolicyType = element->IsHTMLElement(nsGkAtoms::audio) ?

View File

@ -794,7 +794,7 @@ protected:
* us.
*/
template<class T>
class MOZ_STACK_CLASS AutoPinned {
class MOZ_RAII AutoPinned {
public:
explicit AutoPinned(T* aResource MOZ_GUARD_OBJECT_NOTIFIER_PARAM) : mResource(aResource) {
MOZ_GUARD_OBJECT_NOTIFIER_INIT;

View File

@ -306,7 +306,7 @@ public:
return sIsLoadModuleOnStack;
}
class MOZ_STACK_CLASS NotifyLoadingModule
class MOZ_RAII NotifyLoadingModule
{
public:
explicit NotifyLoadingModule(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)

View File

@ -18,12 +18,10 @@ EXPORTS.mozilla.dom += [
EXPORTS += [
'nsContentSecurityManager.h',
'nsCORSListenerProxy.h'
]
UNIFIED_SOURCES += [
'nsContentSecurityManager.cpp',
'nsCORSListenerProxy.cpp',
'nsCSPContext.cpp',
'nsCSPParser.cpp',
'nsCSPService.cpp',

View File

@ -29,12 +29,14 @@
#include "nsIUploadChannel.h"
#include "nsIScriptError.h"
#include "nsIWebNavigation.h"
#include "nsMimeTypes.h"
#include "nsNetUtil.h"
#include "nsNullPrincipal.h"
#include "nsIContentPolicy.h"
#include "nsSupportsPrimitives.h"
#include "nsThreadUtils.h"
#include "nsString.h"
#include "nsStringStream.h"
#include "mozilla/Logging.h"
#include "mozilla/dom/CSPReportBinding.h"
#include "mozilla/dom/CSPDictionariesBinding.h"

View File

@ -66,7 +66,7 @@ NS_INTERFACE_MAP_END
// Helper class: AutoChangeLengthNotifier
// Stack-based helper class to pair calls to WillChangeLengthList and
// DidChangeLengthList.
class MOZ_STACK_CLASS AutoChangeLengthNotifier
class MOZ_RAII AutoChangeLengthNotifier
{
public:
explicit AutoChangeLengthNotifier(DOMSVGLength* aLength MOZ_GUARD_OBJECT_NOTIFIER_PARAM)

View File

@ -79,7 +79,7 @@ DOMSVGLengthList::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto)
// Helper class: AutoChangeLengthListNotifier
// Stack-based helper class to pair calls to WillChangeLengthList and
// DidChangeLengthList.
class MOZ_STACK_CLASS AutoChangeLengthListNotifier
class MOZ_RAII AutoChangeLengthListNotifier
{
public:
explicit AutoChangeLengthListNotifier(DOMSVGLengthList* aLengthList MOZ_GUARD_OBJECT_NOTIFIER_PARAM)

View File

@ -53,7 +53,7 @@ NS_INTERFACE_MAP_END
// Helper class: AutoChangeNumberNotifier
// Stack-based helper class to pair calls to WillChangeNumberList and
// DidChangeNumberList.
class MOZ_STACK_CLASS AutoChangeNumberNotifier
class MOZ_RAII AutoChangeNumberNotifier
{
public:
explicit AutoChangeNumberNotifier(DOMSVGNumber* aNumber MOZ_GUARD_OBJECT_NOTIFIER_PARAM)

View File

@ -80,7 +80,7 @@ DOMSVGNumberList::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto)
// Helper class: AutoChangeNumberListNotifier
// Stack-based helper class to pair calls to WillChangeNumberList and
// DidChangeNumberList.
class MOZ_STACK_CLASS AutoChangeNumberListNotifier
class MOZ_RAII AutoChangeNumberListNotifier
{
public:
explicit AutoChangeNumberListNotifier(DOMSVGNumberList* aNumberList MOZ_GUARD_OBJECT_NOTIFIER_PARAM)

View File

@ -45,7 +45,7 @@ NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(DOMSVGPathSeg, Release)
// Helper class: AutoChangePathSegNotifier
// Stack-based helper class to pair calls to WillChangePathSegList
// and DidChangePathSegList.
class MOZ_STACK_CLASS AutoChangePathSegNotifier
class MOZ_RAII AutoChangePathSegNotifier
{
public:
explicit AutoChangePathSegNotifier(DOMSVGPathSeg* aPathSeg MOZ_GUARD_OBJECT_NOTIFIER_PARAM)

View File

@ -55,7 +55,7 @@ NS_INTERFACE_MAP_END
// Helper class: AutoChangePathSegListNotifier
// Stack-based helper class to pair calls to WillChangePathSegList and
// DidChangePathSegList.
class MOZ_STACK_CLASS AutoChangePathSegListNotifier
class MOZ_RAII AutoChangePathSegListNotifier
{
public:
explicit AutoChangePathSegListNotifier(DOMSVGPathSegList* aPathSegList MOZ_GUARD_OBJECT_NOTIFIER_PARAM)

View File

@ -23,7 +23,7 @@ namespace mozilla {
// Helper class: AutoChangePointNotifier
// Stack-based helper class to pair calls to WillChangePointList and
// DidChangePointList.
class MOZ_STACK_CLASS AutoChangePointNotifier
class MOZ_RAII AutoChangePointNotifier
{
public:
explicit AutoChangePointNotifier(DOMSVGPoint* aPoint MOZ_GUARD_OBJECT_NOTIFIER_PARAM)

View File

@ -73,7 +73,7 @@ NS_INTERFACE_MAP_END
// Helper class: AutoChangePointListNotifier
// Stack-based helper class to pair calls to WillChangePointList and
// DidChangePointList.
class MOZ_STACK_CLASS AutoChangePointListNotifier
class MOZ_RAII AutoChangePointListNotifier
{
public:
explicit AutoChangePointListNotifier(DOMSVGPointList* aPointList MOZ_GUARD_OBJECT_NOTIFIER_PARAM)

View File

@ -43,7 +43,7 @@ NS_INTERFACE_MAP_END
// Helper class: AutoChangeStringListNotifier
// Stack-based helper class to pair calls to WillChangeStringListList and
// DidChangeStringListList.
class MOZ_STACK_CLASS AutoChangeStringListNotifier
class MOZ_RAII AutoChangeStringListNotifier
{
public:
explicit AutoChangeStringListNotifier(DOMSVGStringList* aStringList MOZ_GUARD_OBJECT_NOTIFIER_PARAM)

View File

@ -81,7 +81,7 @@ DOMSVGTransformList::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto
// Helper class: AutoChangeTransformListNotifier
// Stack-based helper class to pair calls to WillChangeTransformList and
// DidChangeTransformList.
class MOZ_STACK_CLASS AutoChangeTransformListNotifier
class MOZ_RAII AutoChangeTransformListNotifier
{
public:
explicit AutoChangeTransformListNotifier(DOMSVGTransformList* aTransformList MOZ_GUARD_OBJECT_NOTIFIER_PARAM)

View File

@ -407,7 +407,7 @@ private:
// Helper class to automatically manage temporary changes to an SVG document's
// state for rendering purposes.
class MOZ_STACK_CLASS AutoSVGRenderingState
class MOZ_RAII AutoSVGRenderingState
{
public:
AutoSVGRenderingState(const Maybe<SVGImageContext>& aSVGContext,

View File

@ -71,7 +71,7 @@ SVGTransform::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
// Helper class: AutoChangeTransformNotifier
// Stack-based helper class to pair calls to WillChangeTransformList
// and DidChangeTransformList.
class MOZ_STACK_CLASS AutoChangeTransformNotifier
class MOZ_RAII AutoChangeTransformNotifier
{
public:
explicit AutoChangeTransformNotifier(SVGTransform* aTransform MOZ_GUARD_OBJECT_NOTIFIER_PARAM)

View File

@ -0,0 +1,414 @@
<!doctype html>
<html>
<head>
<title>Testing Selection Events</title>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<div id="normal">
<span id="inner">A bunch of text in a span inside of a div which should be selected</span>
</div>
<div id="ce" contenteditable>
This is a random block of text
</div>
<input type="text" id="input" value="XXXXXXXXXXXXXXXXXXX" width="200"> <br>
<textarea id="textarea" width="200">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</textarea>
<script>
// Call the testing methods from the parent window
var is = parent.is;
var ok = parent.ok;
// spin() spins the event loop for two cycles, giving time for
// selectionchange events to be fired, and handled by our listeners.
function spin() {
return new Promise(function(a) {
parent.SimpleTest.executeSoon(function() {
parent.SimpleTest.executeSoon(a)
});
});
}
// The main test
parent.add_task(function *() {
yield spin();
var selectstart = 0;
var selectionchange = 0;
var inputSelectionchange = 0;
var textareaSelectionchange = 0;
var cancel = false;
var selectstartTarget = null;
document.addEventListener('selectstart', function(aEvent) {
console.log("originaltarget", aEvent.originalTarget, "new", selectstartTarget);
is(aEvent.originalTarget, selectstartTarget,
"The original target of selectstart");
selectstartTarget = null;
console.log(selectstart);
selectstart++;
if (cancel) {
aEvent.preventDefault();
}
});
document.addEventListener('selectionchange', function(aEvent) {
is(aEvent.originalTarget, document,
"The original target of selectionchange should be the document");
console.log(selectionchange);
selectionchange++;
});
function elt(aId) { return document.getElementById(aId); }
function reset() {
selectstart = 0;
selectionchange = 0;
inputSelectionchange = 0;
textareaSelectionchange = 0;
cancel = false;
}
elt("input").addEventListener('selectionchange', function(aEvent) {
is (aEvent.originalTarget, elt("input"),
"The original target of selectionchange should be the input");
console.log(inputSelectionchange);
inputSelectionchange++;
});
elt("textarea").addEventListener('selectionchange', function(aEvent) {
is (aEvent.originalTarget, elt("textarea"),
"The original target of selectionchange should be the textarea");
console.log(textareaSelectionchange);
textareaSelectionchange++;
});
function* mouseAction(aElement, aOffset, aType,
aSelStart, aSelChng, aISelChng, aTSelChng,
aYOffset)
{
if (aType == "click") { // You can simulate a click event by sending undefined
aType = undefined;
}
if (!aYOffset) {
aYOffset = 10;
}
synthesizeMouse(aElement, aOffset, aYOffset, { type: aType });
yield spin();
is(selectstart, aSelStart,
"SelStart Mouse Action (" + aOffset + " - " + aType + ")");
is(selectionchange, aSelChng,
"SelChng Mouse Action (" + aOffset + " - " + aType + ")");
is(inputSelectionchange, aISelChng || 0,
"ISelChng Mouse Action (" + aOffset + " - " + aType + ")");
is(textareaSelectionchange, aTSelChng || 0,
"TSelChng Mouse Action (" + aOffset + " - " + aType + ")");
reset();
}
function* keyAction(aKey, aShift, aAccel,
aSelStart, aSelChng, aISelChng, aTSelChng)
{
synthesizeKey(aKey, { shiftKey: aShift, accelKey: aAccel });
yield spin();
is(selectstart, aSelStart,
"SelStart Key Action (" + aKey + " - " + aShift + " - " + aAccel + ")");
is(selectionchange, aSelChng,
"SelChng Key Action (" + aKey + " - " + aShift + " - " + aAccel + ")");
is(inputSelectionchange, aISelChng || 0,
"ISelChng Key Action (" + aKey + " - " + aShift + " - " + aAccel + ")");
is(textareaSelectionchange, aTSelChng || 0,
"TSelChng Key Action (" + aKey + " - " + aShift + " - " + aAccel + ")");
reset();
}
var selection = document.getSelection();
function isCollapsed() {
is(selection.isCollapsed, true, "Selection is collapsed");
}
function isNotCollapsed() {
is(selection.isCollapsed, false, "Selection is not collapsed");
}
// Focus the contenteditable text
yield* mouseAction(elt("ce"), 100, "click", 0, 1);
isCollapsed();
// Move the selection to the right, this should only fire selectstart once
selectstartTarget = elt("ce").firstChild;
yield* keyAction("VK_RIGHT", true, false, 1, 1);
isNotCollapsed();
yield* keyAction("VK_RIGHT", true, false, 0, 1);
isNotCollapsed();
// Move it back so that the selection is empty again
yield* keyAction("VK_LEFT", true, false, 0, 1);
isNotCollapsed();
yield* keyAction("VK_LEFT", true, false, 0, 1);
isCollapsed();
// Going from empty to non-empty should fire selectstart again
selectstartTarget = elt("ce").firstChild;
yield* keyAction("VK_LEFT", true, false, 1, 1);
isNotCollapsed();
function* mouseMoves(aElement, aTarget) {
// Select a region
yield* mouseAction(aElement, 50, "mousedown", 0, 1);
isCollapsed();
selectstartTarget = aTarget;
yield* mouseAction(aElement, 100, "mousemove", 1, 1);
isNotCollapsed();
// Moving it more shouldn't trigger a start (move back to empty)
yield* mouseAction(aElement, 75, "mousemove", 0, 1);
isNotCollapsed();
yield* mouseAction(aElement, 50, "mousemove", 0, 1);
isCollapsed();
// Wiggling the mouse a little such that it doesn't select any
// characters shouldn't trigger a selection
yield* mouseAction(aElement, 50, "mousemove", 0, 0, 0, 0, 11);
isCollapsed();
// Moving the mouse again from an empty selection should trigger a
// selectstart
selectstartTarget = aTarget;
yield* mouseAction(aElement, 25, "mousemove", 1, 1);
isNotCollapsed();
// Releasing the mouse shouldn't do anything
yield* mouseAction(aElement, 25, "mouseup", 0, 0);
isNotCollapsed();
// And neither should moving your mouse around when the mouse
// button isn't pressed
yield* mouseAction(aElement, 50, "mousemove", 0, 0);
isNotCollapsed();
// Clicking in an random location should move the selection, but not perform a
// selectstart
yield* mouseAction(aElement, 50, "click", 0, 1);
isCollapsed();
// Clicking there again should do nothing
yield* mouseAction(aElement, 50, "click", 0, 0);
isCollapsed();
// Selecting a region, and canceling the selectstart should mean that the
// selection remains collapsed
yield* mouseAction(aElement, 75, "mousedown", 0, 1);
isCollapsed();
cancel = true;
selectstartTarget = aTarget;
yield* mouseAction(aElement, 100, "mousemove", 1, 1);
isCollapsed();
yield* mouseAction(aElement, 100, "mouseup", 0, 0);
isCollapsed();
}
// Should work both on normal
yield* mouseMoves(elt("inner"), elt("inner").firstChild);
// and contenteditable fields
yield* mouseMoves(elt("ce"), elt("ce").firstChild);
// and fields with elements in them
yield* mouseMoves(elt("normal"), elt("inner").firstChild);
yield* mouseAction(elt("inner"), 50, "click", 0, 1);
isCollapsed();
reset();
// Select all should fire both selectstart and change
selectstartTarget = document.body;
yield* keyAction("A", false, true, 1, 1);
isNotCollapsed();
// Clear the selection
yield* mouseAction(elt("inner"), 50, "click", 0, 1);
isCollapsed();
// Even if we already have a selection
yield* mouseAction(elt("inner"), 75, "mousedown", 0, 1);
isCollapsed();
selectstartTarget = elt("inner").firstChild;
yield* mouseAction(elt("inner"), 100, "mousemove", 1, 1);
isNotCollapsed();
yield* mouseAction(elt("inner"), 100, "mouseup", 0, 0);
isNotCollapsed();
selectstartTarget = document.body;
yield* keyAction("A", false, true, 1, 1);
isNotCollapsed();
// Clear the selection
yield* mouseAction(elt("inner"), 50, "click", 0, 1);
isCollapsed();
// Make sure that a synthesized selection change doesn't fire selectstart
var s = document.getSelection();
s.removeAllRanges();
yield spin();
is(selectstart, 0, "Synthesized range removals shouldn't fire selectstart");
is(selectionchange, 1, "Synthesized range removals should change selectionchange");
reset();
isCollapsed();
var range = document.createRange();
range.selectNode(elt("inner"));
s.addRange(range);
yield spin();
is(selectstart, 0, "Synthesized range additions shouldn't fire selectstart");
is(selectionchange, 1, "Synthesized range additions should change selectionchange");
reset();
isNotCollapsed();
// Change the range, without replacing
range.selectNode(elt("ce"));
yield spin();
is(selectstart, 0, "Synthesized range mutations shouldn't fire selectstart");
is(selectionchange, 1, "Synthesized range mutations should change selectionchange");
reset();
isNotCollapsed();
// Remove the range
s.removeAllRanges();
yield spin();
is(selectstart, 0, "Synthesized range removal");
is(selectionchange, 1, "Synthesized range removal");
reset();
isCollapsed();
/*
Selection events mouse move on input type=text
*/
// Select a region
yield* mouseAction(elt("input"), 50, "mousedown", 0, 1, 1, 0);
selectstartTarget = elt("input");
yield* mouseAction(elt("input"), 100, "mousemove", 1, 0, 1, 0);
// Moving it more shouldn't trigger a start (move back to empty)
yield* mouseAction(elt("input"), 75, "mousemove", 0, 0, 1, 0);
yield* mouseAction(elt("input"), 50, "mousemove", 0, 0, 1, 0);
// Wiggling the mouse a little such that it doesn't select any
// characters shouldn't trigger a selection
yield* mouseAction(elt("input"), 50, "mousemove", 0, 0, 0, 0, 11);
// Moving the mouse again from an empty selection should trigger a
// selectstart
selectstartTarget = elt("input");
yield* mouseAction(elt("input"), 25, "mousemove", 1, 0, 1, 0);
// Releasing the mouse shouldn't do anything
yield* mouseAction(elt("input"), 25, "mouseup", 0, 0, 0, 0);
// And neither should moving your mouse around when the mouse
// button isn't pressed
yield* mouseAction(elt("input"), 50, "mousemove", 0, 0, 0, 0);
// Clicking in an random location should move the selection, but
// not perform a selectstart
yield* mouseAction(elt("input"), 50, "click", 0, 0, 1, 0);
// Clicking there again should do nothing
yield* mouseAction(elt("input"), 50, "click", 0, 0, 0, 0);
// Selecting a region, and canceling the selectstart should mean that the
// selection remains collapsed
yield* mouseAction(elt("input"), 75, "mousedown", 0, 0, 1, 0);
cancel = true;
selectstartTarget = elt("input");
yield* mouseAction(elt("input"), 100, "mousemove", 1, 0, 1, 0);
yield* mouseAction(elt("input"), 100, "mouseup", 0, 0, 0, 0);
// Select a region
// XXX For some reason we fire 2 selectchange events on the body
// when switching from the input to the text area.
yield* mouseAction(elt("textarea"), 50, "mousedown", 0, 2, 0, 1);
selectstartTarget = elt("textarea");
yield* mouseAction(elt("textarea"), 100, "mousemove", 1, 0, 0, 1);
// Moving it more shouldn't trigger a start (move back to empty)
yield* mouseAction(elt("textarea"), 75, "mousemove", 0, 0, 0, 1);
yield* mouseAction(elt("textarea"), 50, "mousemove", 0, 0, 0, 1);
// Wiggling the mouse a little such that it doesn't select any
// characters shouldn't trigger a selection
yield* mouseAction(elt("textarea"), 50, "mousemove", 0, 0, 0, 0, 11);
// Moving the mouse again from an empty selection should trigger a
// selectstart
selectstartTarget = elt("textarea");
yield* mouseAction(elt("textarea"), 25, "mousemove", 1, 0, 0, 1);
// Releasing the mouse shouldn't do anything
yield* mouseAction(elt("textarea"), 25, "mouseup", 0, 0, 0, 0);
// And neither should moving your mouse around when the mouse
// button isn't pressed
yield* mouseAction(elt("textarea"), 50, "mousemove", 0, 0, 0, 0);
// Clicking in an random location should move the selection, but not perform a
// selectstart
yield* mouseAction(elt("textarea"), 50, "click", 0, 0, 0, 1);
// Clicking there again should do nothing
yield* mouseAction(elt("textarea"), 50, "click", 0, 0, 0, 0);
// Selecting a region, and canceling the selectstart should mean that the
// selection remains collapsed
yield* mouseAction(elt("textarea"), 75, "mousedown", 0, 0, 0, 1);
cancel = true;
selectstartTarget = elt("textarea");
yield* mouseAction(elt("textarea"), 100, "mousemove", 1, 0, 0, 1);
yield* mouseAction(elt("textarea"), 100, "mouseup", 0, 0, 0, 0);
// Marking the input and textarea as display: none and then as visible again
// shouldn't trigger any changes, although the nodes will be re-framed
elt("input").setAttribute("style", "display: none;");
yield spin();
is(selectstart, 0, "idn - ss 1");
is(selectionchange, 0, "idn - sc 1");
is(inputSelectionchange, 0, "idn - isc 1");
is(textareaSelectionchange, 0, "idn - tsc 1");
reset();
elt("input").setAttribute("style", "");
yield spin();
is(selectstart, 0, "idn - ss 2");
is(selectionchange, 0, "idn - sc 2");
is(inputSelectionchange, 0, "idn - isc 2");
is(textareaSelectionchange, 0, "idn - tsc 2");
reset();
elt("textarea").setAttribute("style", "display: none;");
yield spin();
is(selectstart, 0, "tdn - ss 1");
is(selectionchange, 0, "tdn - sc 1");
is(inputSelectionchange, 0, "tdn - isc 1");
is(textareaSelectionchange, 0, "tdn - tsc 1");
reset();
elt("textarea").setAttribute("style", "");
yield spin();
is(selectstart, 0, "tdn - ss 2");
is(selectionchange, 0, "tdn - sc 2");
is(inputSelectionchange, 0, "tdn - isc 2");
is(textareaSelectionchange, 0, "tdn - tsc 2");
reset();
});
</script>
</body>
</html>

View File

@ -44,6 +44,7 @@ support-files =
workerStorageAllowed.js
workerStoragePrevented.js
storagePermissionsUtils.js
frameSelectEvents.html
[test_497898.html]
skip-if = ((buildapp == 'mulet' || buildapp == 'b2g') && toolkit != 'gonk') || toolkit == 'android' #Bug 931116, b2g desktop specific, initial triage
@ -120,3 +121,5 @@ skip-if = buildapp == 'b2g' # Bug 1184427 - no SSL certs on b2g
skip-if = buildapp == 'b2g' # Bug 1184427 - no SSL certs on b2g
[test_storagePermissionsLimitForeign.html]
skip-if = buildapp == 'b2g' # Bug 1184427 - no SSL certs on b2g
[test_selectevents.html]
skip-if = buildapp == 'b2g' || buildapp == 'mulet' # Mouse doesn't select in the same way on b2g

View File

@ -0,0 +1,32 @@
<!doctype html>
<html>
<head>
<title>Testing Selection Events</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<iframe width="500"></iframe>
<script>
add_task(function* () {
// Push the correct preferences for the test
yield new Promise((done) => {
SpecialPowers.pushPrefEnv({'set': [['dom.select_events.enabled', true]]}, done);
});
// Start the actual test
yield new Promise((done) => {
var iframe = document.querySelector('iframe');
iframe.addEventListener('load', done);
iframe.setAttribute('src', 'frameSelectEvents.html');
});
// The child iframe will call add_task before we reach this point,
// and will handle the rest of the test.
});
</script>
</body>
</html>

View File

@ -151,6 +151,7 @@ partial interface Document {
attribute EventHandler onpaste;
attribute EventHandler onbeforescriptexecute;
attribute EventHandler onafterscriptexecute;
/**
* True if this document is synthetic : stand alone image, video, audio file,
* etc.

View File

@ -89,6 +89,9 @@ interface GlobalEventHandlers {
attribute EventHandler onvolumechange;
attribute EventHandler onwaiting;
[Pref="dom.select_events.enabled"]
attribute EventHandler onselectstart;
// Pointer events handlers
[Pref="dom.w3c_pointer_events.enabled"]
attribute EventHandler onpointercancel;

View File

@ -543,7 +543,7 @@ class EventRunnable final : public MainThreadProxyRunnable
nsresult mResponseResult;
public:
class StateDataAutoRooter : private JS::CustomAutoRooter
class MOZ_RAII StateDataAutoRooter : private JS::CustomAutoRooter
{
XMLHttpRequest::StateData* mStateData;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER

View File

@ -31,7 +31,7 @@ class Selection;
* stack based helper class for batching a collection of txns inside a
* placeholder txn.
*/
class MOZ_STACK_CLASS nsAutoPlaceHolderBatch
class MOZ_RAII nsAutoPlaceHolderBatch
{
private:
nsCOMPtr<nsIEditor> mEd;
@ -58,7 +58,7 @@ class MOZ_STACK_CLASS nsAutoPlaceHolderBatch
* Note: I changed this to use placeholder batching so that we get
* proper selection save/restore across undo/redo.
*/
class MOZ_STACK_CLASS nsAutoEditBatch : public nsAutoPlaceHolderBatch
class MOZ_RAII nsAutoEditBatch : public nsAutoPlaceHolderBatch
{
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
public:
@ -74,7 +74,7 @@ class MOZ_STACK_CLASS nsAutoEditBatch : public nsAutoPlaceHolderBatch
* stack based helper class for saving/restoring selection. Note that this
* assumes that the nodes involved are still around afterwards!
*/
class MOZ_STACK_CLASS nsAutoSelectionReset
class MOZ_RAII nsAutoSelectionReset
{
private:
/** ref-counted reference to the selection that we are supposed to restore */
@ -96,7 +96,7 @@ class MOZ_STACK_CLASS nsAutoSelectionReset
/***************************************************************************
* stack based helper class for StartOperation()/EndOperation() sandwich
*/
class MOZ_STACK_CLASS nsAutoRules
class MOZ_RAII nsAutoRules
{
public:
@ -131,7 +131,7 @@ class MOZ_STACK_CLASS nsAutoRules
* stack based helper class for turning off active selection adjustment
* by low level transactions
*/
class MOZ_STACK_CLASS nsAutoTxnsConserveSelection
class MOZ_RAII nsAutoTxnsConserveSelection
{
public:
@ -163,7 +163,7 @@ class MOZ_STACK_CLASS nsAutoTxnsConserveSelection
/***************************************************************************
* stack based helper class for batching reflow and paint requests.
*/
class MOZ_STACK_CLASS nsAutoUpdateViewBatch
class MOZ_RAII nsAutoUpdateViewBatch
{
public:
@ -197,7 +197,7 @@ class nsBoolDomIterFunctor
virtual bool operator()(nsINode* aNode) const = 0;
};
class MOZ_STACK_CLASS nsDOMIterator
class MOZ_RAII nsDOMIterator
{
public:
explicit nsDOMIterator(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
@ -214,7 +214,7 @@ class MOZ_STACK_CLASS nsDOMIterator
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
class MOZ_STACK_CLASS nsDOMSubtreeIterator : public nsDOMIterator
class MOZ_RAII nsDOMSubtreeIterator : public nsDOMIterator
{
public:
explicit nsDOMSubtreeIterator(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);

View File

@ -831,6 +831,14 @@ nsTextEditRules::WillDeleteSelection(Selection* aSelection,
}
nsresult res = NS_OK;
// If the current selection is empty (e.g the user presses backspace with
// a collapsed selection), then we want to avoid sending the selectstart
// event to the user, so we hide selection changes. However, we still
// want to send a single selectionchange event to the document, so we
// batch the selectionchange events, such that a single event fires after
// the AutoHideSelectionChanges destructor has been run.
SelectionBatcher selectionBatcher(aSelection);
AutoHideSelectionChanges hideSelection(aSelection);
nsAutoScriptBlocker scriptBlocker;
if (IsPasswordEditor())

View File

@ -946,13 +946,20 @@ mozInlineSpellChecker::ReplaceWord(nsIDOMNode *aNode, int32_t aOffset,
if (range)
{
// This range was retrieved from the spellchecker selection. As
// ranges cannot be shared between selections, we must clone it
// before adding it to the editor's selection.
nsCOMPtr<nsIDOMRange> editorRange;
res = range->CloneRange(getter_AddRefs(editorRange));
NS_ENSURE_SUCCESS(res, res);
nsAutoPlaceHolderBatch phb(editor, nullptr);
nsCOMPtr<nsISelection> selection;
res = editor->GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(res, res);
selection->RemoveAllRanges();
selection->AddRange(range);
selection->AddRange(editorRange);
editor->DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
nsCOMPtr<nsIPlaintextEditor> textEditor(do_QueryReferent(mEditor));

View File

@ -277,7 +277,7 @@ private:
namespace {
class MOZ_STACK_CLASS MaybeScriptBlocker {
class MOZ_RAII MaybeScriptBlocker {
public:
explicit MaybeScriptBlocker(MessageChannel *aChannel, bool aBlock
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)

View File

@ -23,7 +23,7 @@ namespace ipc {
* current thread will be neutered. It is safe to nest multiple instances of
* this class.
*/
class MOZ_STACK_CLASS NeuteredWindowRegion
class MOZ_RAII NeuteredWindowRegion
{
public:
explicit NeuteredWindowRegion(bool aDoNeuter MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
@ -46,7 +46,7 @@ private:
* disabling neutering for the remainder of its enclosing block.
* @see NeuteredWindowRegion
*/
class MOZ_STACK_CLASS DeneuteredWindowRegion
class MOZ_RAII DeneuteredWindowRegion
{
public:
DeneuteredWindowRegion(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);

View File

@ -20,7 +20,7 @@
* This stopwatch is active iff JSRuntime::stopwatch.isActive is set.
* Upon destruction, update JSRuntime::stopwatch.data.totalCPOWTime.
*/
class MOZ_STACK_CLASS CPOWTimer final {
class MOZ_RAII CPOWTimer final {
public:
explicit inline CPOWTimer(JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
~CPOWTimer();

View File

@ -654,7 +654,7 @@ namespace JS {
* specialization, define a RootedBase<T> specialization containing them.
*/
template <typename T>
class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
class MOZ_RAII Rooted : public js::RootedBase<T>
{
static_assert(!mozilla::IsConvertible<T, Traceable*>::value,
"Rooted takes pointer or Traceable types but not Traceable* type");
@ -777,7 +777,7 @@ class HandleBase<JSObject*>
/* Interface substitute for Rooted<T> which does not root the variable's memory. */
template <typename T>
class FakeRooted : public RootedBase<T>
class MOZ_RAII FakeRooted : public RootedBase<T>
{
public:
template <typename CX>

View File

@ -482,7 +482,7 @@ class LifoAlloc
};
};
class LifoAllocScope
class MOZ_NON_TEMPORARY_CLASS LifoAllocScope
{
LifoAlloc* lifoAlloc;
LifoAlloc::Mark mark;

View File

@ -92,7 +92,7 @@ IsIncrementalGCSafe(JSRuntime* rt);
#ifdef JS_GC_ZEAL
class AutoStopVerifyingBarriers
class MOZ_RAII AutoStopVerifyingBarriers
{
GCRuntime* gc;
bool restartPreVerifier;
@ -152,7 +152,7 @@ struct MovingTracer : JS::CallbackTracer
#endif
};
class AutoMaybeStartBackgroundAllocation
class MOZ_RAII AutoMaybeStartBackgroundAllocation
{
private:
JSRuntime* runtime;
@ -176,7 +176,7 @@ class AutoMaybeStartBackgroundAllocation
};
// In debug builds, set/unset the GC sweeping flag for the current thread.
struct AutoSetThreadIsSweeping
struct MOZ_RAII AutoSetThreadIsSweeping
{
#ifdef DEBUG
explicit AutoSetThreadIsSweeping(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)

View File

@ -331,7 +331,7 @@ struct Statistics
double computeMMU(int64_t resolution) const;
};
struct AutoGCSlice
struct MOZ_RAII AutoGCSlice
{
AutoGCSlice(Statistics& stats, const ZoneGCStats& zoneStats, JSGCInvocationKind gckind,
SliceBudget budget, JS::gcreason::Reason reason
@ -347,7 +347,7 @@ struct AutoGCSlice
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
struct AutoPhase
struct MOZ_RAII AutoPhase
{
AutoPhase(Statistics& stats, Phase phase
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
@ -391,7 +391,7 @@ struct AutoPhase
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
struct AutoSCC
struct MOZ_RAII AutoSCC
{
AutoSCC(Statistics& stats, unsigned scc
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)

View File

@ -518,7 +518,7 @@ FinishAllOffThreadCompilations(JSCompartment* comp)
}
}
class AutoLazyLinkExitFrame
class MOZ_RAII AutoLazyLinkExitFrame
{
JitActivation* jitActivation_;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER

View File

@ -75,7 +75,7 @@ class IonSpewer
}
};
class AutoLockIonSpewerOutput
class MOZ_RAII AutoLockIonSpewerOutput
{
private:
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER

View File

@ -505,7 +505,7 @@ CodeGeneratorMIPS::visitMulI(LMulI* ins)
// Result is -0 if lhs or rhs is negative.
// In that case result must be double value so bailout
Register scratch = SecondScratchReg;
masm.ma_or(scratch, ToRegister(lhs), ToRegister(rhs));
masm.as_or(scratch, ToRegister(lhs), ToRegister(rhs));
bailoutCmp32(Assembler::Signed, scratch, scratch, ins->snapshot());
masm.bind(&done);
@ -796,19 +796,19 @@ CodeGeneratorMIPS::visitBitOpI(LBitOpI* ins)
if (rhs->isConstant())
masm.ma_or(ToRegister(dest), ToRegister(lhs), Imm32(ToInt32(rhs)));
else
masm.ma_or(ToRegister(dest), ToRegister(lhs), ToRegister(rhs));
masm.as_or(ToRegister(dest), ToRegister(lhs), ToRegister(rhs));
break;
case JSOP_BITXOR:
if (rhs->isConstant())
masm.ma_xor(ToRegister(dest), ToRegister(lhs), Imm32(ToInt32(rhs)));
else
masm.ma_xor(ToRegister(dest), ToRegister(lhs), ToRegister(rhs));
masm.as_xor(ToRegister(dest), ToRegister(lhs), ToRegister(rhs));
break;
case JSOP_BITAND:
if (rhs->isConstant())
masm.ma_and(ToRegister(dest), ToRegister(lhs), Imm32(ToInt32(rhs)));
else
masm.ma_and(ToRegister(dest), ToRegister(lhs), ToRegister(rhs));
masm.as_and(ToRegister(dest), ToRegister(lhs), ToRegister(rhs));
break;
default:
MOZ_CRASH("unexpected binary opcode");
@ -1647,7 +1647,7 @@ CodeGeneratorMIPS::visitBitAndAndBranch(LBitAndAndBranch* lir)
if (lir->right()->isConstant())
masm.ma_and(ScratchRegister, ToRegister(lir->left()), Imm32(ToInt32(lir->right())));
else
masm.ma_and(ScratchRegister, ToRegister(lir->left()), ToRegister(lir->right()));
masm.as_and(ScratchRegister, ToRegister(lir->left()), ToRegister(lir->right()));
emitBranch(ScratchRegister, ScratchRegister, Assembler::NonZero, lir->ifTrue(),
lir->ifFalse());
}

View File

@ -25,7 +25,7 @@ MacroAssembler::not32(Register reg)
void
MacroAssembler::and32(Register src, Register dest)
{
ma_and(dest, dest, src);
as_and(dest, dest, src);
}
void

View File

@ -393,12 +393,6 @@ MacroAssemblerMIPS::ma_and(Register rd, Register rs)
as_and(rd, rd, rs);
}
void
MacroAssemblerMIPS::ma_and(Register rd, Register rs, Register rt)
{
as_and(rd, rs, rt);
}
void
MacroAssemblerMIPS::ma_and(Register rd, Imm32 imm)
{
@ -423,12 +417,6 @@ MacroAssemblerMIPS::ma_or(Register rd, Register rs)
as_or(rd, rd, rs);
}
void
MacroAssemblerMIPS::ma_or(Register rd, Register rs, Register rt)
{
as_or(rd, rs, rt);
}
void
MacroAssemblerMIPS::ma_or(Register rd, Imm32 imm)
{
@ -453,12 +441,6 @@ MacroAssemblerMIPS::ma_xor(Register rd, Register rs)
as_xor(rd, rd, rs);
}
void
MacroAssemblerMIPS::ma_xor(Register rd, Register rs, Register rt)
{
as_xor(rd, rs, rt);
}
void
MacroAssemblerMIPS::ma_xor(Register rd, Imm32 imm)
{
@ -490,12 +472,6 @@ MacroAssemblerMIPS::ma_addu(Register rd, Register rs, Imm32 imm)
}
}
void
MacroAssemblerMIPS::ma_addu(Register rd, Register rs, Register rt)
{
as_addu(rd, rs, rt);
}
void
MacroAssemblerMIPS::ma_addu(Register rd, Register rs)
{
@ -549,12 +525,6 @@ MacroAssemblerMIPS::ma_addTestOverflow(Register rd, Register rs, Imm32 imm, Labe
}
// Subtract.
void
MacroAssemblerMIPS::ma_subu(Register rd, Register rs, Register rt)
{
as_subu(rd, rs, rt);
}
void
MacroAssemblerMIPS::ma_subu(Register rd, Register rs, Imm32 imm)
{
@ -578,7 +548,7 @@ MacroAssemblerMIPS::ma_subTestOverflow(Register rd, Register rs, Register rt, La
Label goodSubtraction;
// Use second scratch. The instructions generated by ma_b don't use the
// second scratch register.
ma_subu(rd, rs, rt);
as_subu(rd, rs, rt);
as_xor(ScratchRegister, rs, rt); // If same sign, no overflow
ma_b(ScratchRegister, Imm32(0), &goodSubtraction, Assembler::GreaterThanOrEqual, ShortJump);
@ -1544,7 +1514,7 @@ MacroAssemblerMIPSCompat::sub32(Imm32 imm, Register dest)
void
MacroAssemblerMIPSCompat::sub32(Register src, Register dest)
{
ma_subu(dest, dest, src);
as_subu(dest, dest, src);
}
void
@ -1563,7 +1533,7 @@ MacroAssemblerMIPSCompat::addPtr(const Address& src, Register dest)
void
MacroAssemblerMIPSCompat::subPtr(Register src, Register dest)
{
ma_subu(dest, dest, src);
as_subu(dest, dest, src);
}
void
@ -2544,7 +2514,7 @@ MacroAssemblerMIPSCompat::loadConstantDouble(double dp, FloatRegister dest)
void
MacroAssemblerMIPSCompat::branchTestInt32Truthy(bool b, const ValueOperand& value, Label* label)
{
ma_and(ScratchRegister, value.payloadReg(), value.payloadReg());
as_and(ScratchRegister, value.payloadReg(), value.payloadReg());
ma_b(ScratchRegister, ScratchRegister, label, b ? NonZero : Zero);
}

View File

@ -110,19 +110,16 @@ class MacroAssemblerMIPS : public Assembler
// and
void ma_and(Register rd, Register rs);
void ma_and(Register rd, Register rs, Register rt);
void ma_and(Register rd, Imm32 imm);
void ma_and(Register rd, Register rs, Imm32 imm);
// or
void ma_or(Register rd, Register rs);
void ma_or(Register rd, Register rs, Register rt);
void ma_or(Register rd, Imm32 imm);
void ma_or(Register rd, Register rs, Imm32 imm);
// xor
void ma_xor(Register rd, Register rs);
void ma_xor(Register rd, Register rs, Register rt);
void ma_xor(Register rd, Imm32 imm);
void ma_xor(Register rd, Register rs, Imm32 imm);
@ -143,14 +140,12 @@ class MacroAssemblerMIPS : public Assembler
// arithmetic based ops
// add
void ma_addu(Register rd, Register rs, Imm32 imm);
void ma_addu(Register rd, Register rs, Register rt);
void ma_addu(Register rd, Register rs);
void ma_addu(Register rd, Imm32 imm);
void ma_addTestOverflow(Register rd, Register rs, Register rt, Label* overflow);
void ma_addTestOverflow(Register rd, Register rs, Imm32 imm, Label* overflow);
// subtract
void ma_subu(Register rd, Register rs, Register rt);
void ma_subu(Register rd, Register rs, Imm32 imm);
void ma_subu(Register rd, Imm32 imm);
void ma_subTestOverflow(Register rd, Register rs, Register rt, Label* overflow);

View File

@ -97,13 +97,13 @@ ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
break;
}
case JSOP_BITOR:
masm.ma_or(R0.payloadReg() , R0.payloadReg(), R1.payloadReg());
masm.as_or(R0.payloadReg() , R0.payloadReg(), R1.payloadReg());
break;
case JSOP_BITXOR:
masm.ma_xor(R0.payloadReg() , R0.payloadReg(), R1.payloadReg());
masm.as_xor(R0.payloadReg() , R0.payloadReg(), R1.payloadReg());
break;
case JSOP_BITAND:
masm.ma_and(R0.payloadReg() , R0.payloadReg(), R1.payloadReg());
masm.as_and(R0.payloadReg() , R0.payloadReg(), R1.payloadReg());
break;
case JSOP_LSH:
// MIPS will only use 5 lowest bits in R1 as shift offset.

View File

@ -441,7 +441,7 @@ JitRuntime::generateArgumentsRectifier(JSContext* cx, void** returnAddrOut)
masm.andPtr(Imm32(CalleeTokenMask), numArgsReg);
masm.load16ZeroExtend(Address(numArgsReg, JSFunction::offsetOfNargs()), numArgsReg);
masm.ma_subu(t1, numArgsReg, s3);
masm.as_subu(t1, numArgsReg, s3);
// Get the topmost argument.
masm.ma_sll(t0, s3, Imm32(3)); // t0 <- nargs * 8
@ -1191,7 +1191,7 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
// Store return frame in lastProfilingFrame.
// scratch2 := StackPointer + Descriptor.size*1 + JitFrameLayout::Size();
masm.ma_addu(scratch2, StackPointer, scratch1);
masm.as_addu(scratch2, StackPointer, scratch1);
masm.ma_addu(scratch2, scratch2, Imm32(JitFrameLayout::Size()));
masm.storePtr(scratch2, lastProfilingFrame);
masm.ret();
@ -1225,7 +1225,7 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
//
masm.bind(&handle_BaselineStub);
{
masm.ma_addu(scratch3, StackPointer, scratch1);
masm.as_addu(scratch3, StackPointer, scratch1);
Address stubFrameReturnAddr(scratch3,
JitFrameLayout::Size() +
BaselineStubFrameLayout::offsetOfReturnAddress());
@ -1282,7 +1282,7 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
masm.bind(&handle_Rectifier);
{
// scratch2 := StackPointer + Descriptor.size*1 + JitFrameLayout::Size();
masm.ma_addu(scratch2, StackPointer, scratch1);
masm.as_addu(scratch2, StackPointer, scratch1);
masm.add32(Imm32(JitFrameLayout::Size()), scratch2);
masm.loadPtr(Address(scratch2, RectifierFrameLayout::offsetOfDescriptor()), scratch3);
masm.ma_srl(scratch1, scratch3, Imm32(FRAMESIZE_SHIFT));
@ -1303,7 +1303,7 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
masm.storePtr(scratch3, lastProfilingCallSite);
// scratch3 := RectFrame + Rect-Descriptor.Size + RectifierFrameLayout::Size()
masm.ma_addu(scratch3, scratch2, scratch1);
masm.as_addu(scratch3, scratch2, scratch1);
masm.add32(Imm32(RectifierFrameLayout::Size()), scratch3);
masm.storePtr(scratch3, lastProfilingFrame);
masm.ret();
@ -1318,7 +1318,7 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
masm.bind(&checkOk);
}
#endif
masm.ma_addu(scratch3, scratch2, scratch1);
masm.as_addu(scratch3, scratch2, scratch1);
Address stubFrameReturnAddr(scratch3, RectifierFrameLayout::Size() +
BaselineStubFrameLayout::offsetOfReturnAddress());
masm.loadPtr(stubFrameReturnAddr, scratch2);
@ -1350,7 +1350,7 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
masm.bind(&handle_IonAccessorIC);
{
// scratch2 := StackPointer + Descriptor.size + JitFrameLayout::Size()
masm.ma_addu(scratch2, StackPointer, scratch1);
masm.as_addu(scratch2, StackPointer, scratch1);
masm.addPtr(Imm32(JitFrameLayout::Size()), scratch2);
// scratch3 := AccFrame-Descriptor.Size
@ -1374,7 +1374,7 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
// lastProfilingFrame := AccessorFrame + AccFrame-Descriptor.Size +
// IonAccessorICFrameLayout::Size()
masm.ma_addu(scratch1, scratch2, scratch3);
masm.as_addu(scratch1, scratch2, scratch3);
masm.addPtr(Imm32(IonAccessorICFrameLayout::Size()), scratch1);
masm.storePtr(scratch1, lastProfilingFrame);
masm.ret();

View File

@ -67,7 +67,7 @@ class JS_PUBLIC_API(AutoCheckRequestDepth)
/* AutoValueArray roots an internal fixed-size array of Values. */
template <size_t N>
class AutoValueArray : public AutoGCRooter
class MOZ_RAII AutoValueArray : public AutoGCRooter
{
const size_t length_;
Value elements_[N];
@ -99,7 +99,7 @@ class AutoValueArray : public AutoGCRooter
};
template<class T>
class AutoVectorRooterBase : protected AutoGCRooter
class MOZ_RAII AutoVectorRooterBase : protected AutoGCRooter
{
typedef js::Vector<T, 8> VectorImpl;
VectorImpl vector;
@ -196,7 +196,7 @@ class AutoVectorRooterBase : protected AutoGCRooter
};
template <typename T>
class MOZ_STACK_CLASS AutoVectorRooter : public AutoVectorRooterBase<T>
class MOZ_RAII AutoVectorRooter : public AutoVectorRooterBase<T>
{
public:
explicit AutoVectorRooter(JSContext* cx
@ -225,7 +225,7 @@ using IdVector = js::TraceableVector<jsid>;
using ScriptVector = js::TraceableVector<JSScript*>;
template<class Key, class Value>
class AutoHashMapRooter : protected AutoGCRooter
class MOZ_RAII AutoHashMapRooter : protected AutoGCRooter
{
private:
typedef js::HashMap<Key, Value> HashMapImpl;
@ -349,7 +349,7 @@ class AutoHashMapRooter : protected AutoGCRooter
};
template<class T>
class AutoHashSetRooter : protected AutoGCRooter
class MOZ_RAII AutoHashSetRooter : protected AutoGCRooter
{
private:
typedef js::HashSet<T> HashSetImpl;
@ -460,7 +460,7 @@ class AutoHashSetRooter : protected AutoGCRooter
/*
* Custom rooting behavior for internal and external clients.
*/
class JS_PUBLIC_API(CustomAutoRooter) : private AutoGCRooter
class MOZ_RAII JS_PUBLIC_API(CustomAutoRooter) : private AutoGCRooter
{
public:
template <typename CX>
@ -1070,7 +1070,7 @@ AssertHeapIsIdle(JSContext* cx);
} /* namespace js */
class JSAutoRequest
class MOZ_RAII JSAutoRequest
{
public:
explicit JSAutoRequest(JSContext* cx
@ -1409,7 +1409,7 @@ JS_RefreshCrossCompartmentWrappers(JSContext* cx, JS::Handle<JSObject*> obj);
* the corresponding JS_LeaveCompartment call.
*/
class JS_PUBLIC_API(JSAutoCompartment)
class MOZ_RAII JS_PUBLIC_API(JSAutoCompartment)
{
JSContext* cx_;
JSCompartment* oldCompartment_;
@ -1423,7 +1423,7 @@ class JS_PUBLIC_API(JSAutoCompartment)
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
class JS_PUBLIC_API(JSAutoNullableCompartment)
class MOZ_RAII JS_PUBLIC_API(JSAutoNullableCompartment)
{
JSContext* cx_;
JSCompartment* oldCompartment_;
@ -4227,7 +4227,7 @@ JS_GetStringEncodingLength(JSContext* cx, JSString* str);
JS_PUBLIC_API(size_t)
JS_EncodeStringToBuffer(JSContext* cx, JSString* str, char* buffer, size_t length);
class JSAutoByteString
class MOZ_RAII JSAutoByteString
{
public:
JSAutoByteString(JSContext* cx, JSString* str
@ -5039,7 +5039,7 @@ HideScriptedCaller(JSContext* cx);
extern JS_PUBLIC_API(void)
UnhideScriptedCaller(JSContext* cx);
class AutoHideScriptedCaller
class MOZ_RAII AutoHideScriptedCaller
{
public:
explicit AutoHideScriptedCaller(JSContext* cx

View File

@ -33,7 +33,7 @@ typedef HashSet<JSObject*> ObjectSet;
typedef HashSet<Shape*> ShapeSet;
/* Detects cycles when traversing an object graph. */
class AutoCycleDetector
class MOZ_RAII AutoCycleDetector
{
JSContext* cx;
RootedObject obj;
@ -466,7 +466,7 @@ struct JSContext : public js::ExclusiveContext,
namespace js {
struct AutoResolving {
struct MOZ_RAII AutoResolving {
public:
enum Kind {
LOOKUP,
@ -670,7 +670,7 @@ using ShapeVector = js::TraceableVector<Shape*>;
using StringVector = js::TraceableVector<JSString*>;
/* AutoArrayRooter roots an external array of Values. */
class AutoArrayRooter : private JS::AutoGCRooter
class MOZ_RAII AutoArrayRooter : private JS::AutoGCRooter
{
public:
AutoArrayRooter(JSContext* cx, size_t len, Value* vec
@ -749,7 +749,7 @@ class AutoAssertNoException
/* Exposed intrinsics for the JITs. */
bool intrinsic_IsSuspendedStarGenerator(JSContext* cx, unsigned argc, Value* vp);
class AutoLockForExclusiveAccess
class MOZ_RAII AutoLockForExclusiveAccess
{
JSRuntime* runtime;

View File

@ -185,7 +185,7 @@ using NewObjectMetadataState = mozilla::Variant<ImmediateMetadata,
DelayMetadata,
PendingMetadata>;
class MOZ_STACK_CLASS AutoSetNewObjectMetadata : private JS::CustomAutoRooter
class MOZ_RAII AutoSetNewObjectMetadata : private JS::CustomAutoRooter
{
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER;
@ -764,7 +764,7 @@ ExclusiveContext::global() const
return Handle<GlobalObject*>::fromMarkedLocation(compartment_->global_.unsafeGet());
}
class AssertCompartmentUnchanged
class MOZ_RAII AssertCompartmentUnchanged
{
public:
explicit AssertCompartmentUnchanged(JSContext* cx
@ -862,7 +862,7 @@ struct WrapperValue
Value value;
};
class AutoWrapperVector : public JS::AutoVectorRooterBase<WrapperValue>
class MOZ_RAII AutoWrapperVector : public JS::AutoVectorRooterBase<WrapperValue>
{
public:
explicit AutoWrapperVector(JSContext* cx
@ -875,7 +875,7 @@ class AutoWrapperVector : public JS::AutoVectorRooterBase<WrapperValue>
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
class AutoWrapperRooter : private JS::AutoGCRooter {
class MOZ_RAII AutoWrapperRooter : private JS::AutoGCRooter {
public:
AutoWrapperRooter(JSContext* cx, WrapperValue v
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)

View File

@ -2694,7 +2694,7 @@ typedef void
JS_FRIEND_API(void)
SetCTypesActivityCallback(JSRuntime* rt, CTypesActivityCallback cb);
class JS_FRIEND_API(AutoCTypesActivityCallback) {
class MOZ_RAII JS_FRIEND_API(AutoCTypesActivityCallback) {
private:
JSContext* cx;
CTypesActivityCallback callback;

View File

@ -1374,7 +1374,7 @@ NewMemoryStatisticsObject(JSContext* cx);
#ifdef DEBUG
/* Use this to avoid assertions when manipulating the wrapper map. */
class AutoDisableProxyCheck
class MOZ_RAII AutoDisableProxyCheck
{
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER;
gc::GCRuntime& gc;

View File

@ -168,7 +168,7 @@ ImplicitCast(U& u)
}
template<typename T>
class AutoScopedAssign
class MOZ_RAII AutoScopedAssign
{
public:
AutoScopedAssign(T* addr, const T& value

View File

@ -3400,7 +3400,7 @@ runOffThreadScript(JSContext* cx, unsigned argc, Value* vp)
return JS_ExecuteScript(cx, script, args.rval());
}
struct FreeOnReturn
struct MOZ_RAII FreeOnReturn
{
JSContext* cx;
const char* ptr;

View File

@ -1824,7 +1824,7 @@ Debugger::slowPathPromiseHook(JSContext* cx, Hook hook, HandleObject promise)
/*** Debugger code invalidation for observing execution ******************************************/
class MOZ_STACK_CLASS ExecutionObservableCompartments : public Debugger::ExecutionObservableSet
class MOZ_RAII ExecutionObservableCompartments : public Debugger::ExecutionObservableSet
{
HashSet<JSCompartment*> compartments_;
HashSet<Zone*> zones_;
@ -1858,7 +1858,7 @@ class MOZ_STACK_CLASS ExecutionObservableCompartments : public Debugger::Executi
// represents the stack frames that need to be bailed out or marked as
// debuggees, and the scripts that need to be recompiled, taking inlining into
// account.
class MOZ_STACK_CLASS ExecutionObservableFrame : public Debugger::ExecutionObservableSet
class MOZ_RAII ExecutionObservableFrame : public Debugger::ExecutionObservableSet
{
AbstractFramePtr frame_;
@ -1919,7 +1919,7 @@ class MOZ_STACK_CLASS ExecutionObservableFrame : public Debugger::ExecutionObser
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
class MOZ_STACK_CLASS ExecutionObservableScript : public Debugger::ExecutionObservableSet
class MOZ_RAII ExecutionObservableScript : public Debugger::ExecutionObservableSet
{
RootedScript script_;

View File

@ -412,7 +412,7 @@ struct AutoEnqueuePendingParseTasksAfterGC {
bool
StartOffThreadCompression(ExclusiveContext* cx, SourceCompressionTask* task);
class AutoLockHelperThreadState
class MOZ_RAII AutoLockHelperThreadState
{
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
@ -428,7 +428,7 @@ class AutoLockHelperThreadState
}
};
class AutoUnlockHelperThreadState
class MOZ_RAII AutoUnlockHelperThreadState
{
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER

View File

@ -375,7 +375,7 @@ namespace js {
// All mutable state is stored in `Runtime::stopwatch` (per-process
// performance stats and logistics) and in `PerformanceGroup` (per
// group performance stats).
class AutoStopwatch final
class MOZ_RAII AutoStopwatch final
{
// The context with which this object was initialized.
// Non-null.

View File

@ -186,7 +186,7 @@ class RegExpStatics
}
};
class AutoRegExpStaticsBuffer : private JS::CustomAutoRooter
class MOZ_RAII AutoRegExpStaticsBuffer : private JS::CustomAutoRooter
{
public:
explicit AutoRegExpStaticsBuffer(JSContext* cx

View File

@ -1864,7 +1864,7 @@ FreeOp::freeLater(void* p)
* Note that the lock may be temporarily released by use of AutoUnlockGC when
* passed a non-const reference to this class.
*/
class MOZ_STACK_CLASS AutoLockGC
class MOZ_RAII AutoLockGC
{
public:
explicit AutoLockGC(JSRuntime* rt
@ -1903,7 +1903,7 @@ class MOZ_STACK_CLASS AutoLockGC
AutoLockGC& operator=(const AutoLockGC&) = delete;
};
class MOZ_STACK_CLASS AutoUnlockGC
class MOZ_RAII AutoUnlockGC
{
public:
explicit AutoUnlockGC(AutoLockGC& lock
@ -1926,7 +1926,7 @@ class MOZ_STACK_CLASS AutoUnlockGC
AutoUnlockGC& operator=(const AutoUnlockGC&) = delete;
};
class MOZ_STACK_CLASS AutoKeepAtoms
class MOZ_RAII AutoKeepAtoms
{
PerThreadData* pt;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
@ -2095,7 +2095,7 @@ extern const JSSecurityCallbacks NullSecurityCallbacks;
// Debugging RAII class which marks the current thread as performing an Ion
// compilation, for use by CurrentThreadCan{Read,Write}CompilationData
class AutoEnterIonCompilation
class MOZ_RAII AutoEnterIonCompilation
{
public:
explicit AutoEnterIonCompilation(bool safeForMinorGC

View File

@ -227,7 +227,7 @@ class AutoSPSLock
* This class is used to suppress profiler sampling during
* critical sections where stack state is not valid.
*/
class AutoSuppressProfilerSampling
class MOZ_RAII AutoSuppressProfilerSampling
{
public:
explicit AutoSuppressProfilerSampling(JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
@ -260,7 +260,7 @@ SPSProfiler::stringsReset()
* that we're about to enter JS function calls. This is the only time in which a
* valid stack pointer is pushed to the sampling stack.
*/
class SPSEntryMarker
class MOZ_RAII SPSEntryMarker
{
public:
explicit SPSEntryMarker(JSRuntime* rt,
@ -279,7 +279,7 @@ class SPSEntryMarker
* being entered via OSR. It marks the current top pseudostack entry as
* OSR-ed
*/
class SPSBaselineOSRMarker
class MOZ_RAII SPSBaselineOSRMarker
{
public:
explicit SPSBaselineOSRMarker(JSRuntime* rt, bool hasSPSFrame

View File

@ -181,7 +181,7 @@ class SavedStacks {
// Similar to mozilla::ReentrancyGuard, but instead of asserting against
// reentrancy, just change the behavior of SavedStacks::saveCurrentStack to
// return a nullptr SavedFrame.
struct MOZ_STACK_CLASS AutoReentrancyGuard {
struct MOZ_RAII AutoReentrancyGuard {
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER;
SavedStacks& stacks;

View File

@ -825,7 +825,7 @@ CloneNestedScopeObject(JSContext* cx, HandleObject enclosingScope, Handle<Nested
// whether the current scope is within the extent of this initial frame.
// Here, "frame" means a single activation of: a function, eval, or global
// code.
class ScopeIter
class MOZ_RAII ScopeIter
{
StaticScopeIter<CanGC> ssi_;
RootedObject scope_;

View File

@ -982,7 +982,7 @@ StackBaseShape::StackBaseShape(Shape* shape)
compartment(shape->compartment())
{}
class AutoRooterGetterSetter
class MOZ_RAII AutoRooterGetterSetter
{
class Inner : private JS::CustomAutoRooter
{

View File

@ -439,7 +439,7 @@ inline void TraceLogStopEventPrivate(TraceLoggerThread* logger, uint32_t id) {
}
// Automatic logging at the start and end of function call.
class AutoTraceLog
class MOZ_RAII AutoTraceLog
{
#ifdef JS_TRACE_LOGGING
TraceLoggerThread* logger;

View File

@ -24,7 +24,7 @@ using mozilla::NativeEndian;
TraceLoggerGraphState* traceLoggerGraphState = nullptr;
class AutoTraceLoggerGraphStateLock
class MOZ_RAII AutoTraceLoggerGraphStateLock
{
TraceLoggerGraphState* graph;

View File

@ -3040,7 +3040,7 @@ private:
/******************************************************************************
* Handles pre/post script processing.
*/
class MOZ_STACK_CLASS AutoScriptEvaluate
class MOZ_RAII AutoScriptEvaluate
{
public:
/**
@ -3077,7 +3077,7 @@ private:
};
/***************************************************************************/
class MOZ_STACK_CLASS AutoResolveName
class MOZ_RAII AutoResolveName
{
public:
AutoResolveName(XPCCallContext& ccx, JS::HandleId name

View File

@ -46,6 +46,7 @@
#include "nsStyleSet.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/MathAlgorithms.h"
#include "nsFrameSelection.h"
#define DEFAULT_COLUMN_WIDTH 20
@ -259,6 +260,13 @@ nsTextControlFrame::EnsureEditorInitialized()
// Make sure that editor init doesn't do things that would kill us off
// (especially off the script blockers it'll create for its DOM mutations).
{
nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
MOZ_ASSERT(txtCtrl, "Content not a text control element");
// Hide selection changes during the initialization, as webpages should not
// be aware of these initializations
AutoHideSelectionChanges hideSelectionChanges(txtCtrl->GetConstFrameSelection());
nsAutoScriptBlocker scriptBlocker;
// Time to mess with our security context... See comments in GetValue()
@ -288,8 +296,6 @@ nsTextControlFrame::EnsureEditorInitialized()
#endif
// Create an editor for the frame, if one doesn't already exist
nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
NS_ASSERTION(txtCtrl, "Content not a text control element");
nsresult rv = txtCtrl->CreateEditor();
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_STATE(weakFrame.IsAlive());

View File

@ -108,7 +108,7 @@ public:
* into multiple ranges to exclude those before adding the resulting ranges
* to this Selection.
*/
nsresult AddItem(nsRange* aRange, int32_t* aOutIndex);
nsresult AddItem(nsRange* aRange, int32_t* aOutIndex, bool aNoStartSelect = false);
nsresult RemoveItem(nsRange* aRange);
nsresult RemoveCollapsedRanges();
nsresult Clear(nsPresContext* aPresContext);
@ -204,6 +204,9 @@ public:
int16_t aVPercent, int16_t aHPercent,
mozilla::ErrorResult& aRv);
void AddSelectionChangeBlocker();
void RemoveSelectionChangeBlocker();
bool IsBlockingSelectionChangeEvents() const;
private:
friend class ::nsAutoScrollTimer;
@ -217,7 +220,7 @@ public:
nsresult NotifySelectionListeners();
friend struct AutoApplyUserSelectStyle;
struct MOZ_STACK_CLASS AutoApplyUserSelectStyle
struct MOZ_RAII AutoApplyUserSelectStyle
{
explicit AutoApplyUserSelectStyle(Selection* aSelection
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
@ -229,6 +232,7 @@ public:
AutoRestore<bool> mSavedValue;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
private:
friend struct mozilla::AutoPrepareFocusRange;
class ScrollSelectionIntoViewEvent;
@ -282,6 +286,8 @@ private:
int32_t* aStartIndex, int32_t* aEndIndex);
RangeData* FindRangeData(nsIDOMRange* aRange);
void UserSelectRangesToAdd(nsRange* aItem, nsTArray<nsRefPtr<nsRange> >& rangesToAdd);
/**
* Helper method for AddItem.
*/
@ -312,9 +318,14 @@ private:
SelectionType mType;
/**
* True if the current selection operation was initiated by user action.
* It determines whether we exclude -moz-user-select:none nodes or not.
* It determines whether we exclude -moz-user-select:none nodes or not,
* as well as whether selectstart events will be fired.
*/
bool mApplyUserSelectStyle;
// Non-zero if we don't want any changes we make to the selection to be
// visible to content. If non-zero, content won't be notified about changes.
uint32_t mSelectionChangeBlockerCount;
};
// Stack-class to turn on/off selection batching.
@ -339,6 +350,33 @@ public:
}
};
class MOZ_STACK_CLASS AutoHideSelectionChanges final
{
private:
nsRefPtr<Selection> mSelection;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
public:
explicit AutoHideSelectionChanges(const nsFrameSelection* aFrame);
explicit AutoHideSelectionChanges(Selection* aSelection
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: mSelection(aSelection)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
mSelection = aSelection;
if (mSelection) {
mSelection->AddSelectionChangeBlocker();
}
}
~AutoHideSelectionChanges()
{
if (mSelection) {
mSelection->RemoveSelectionChangeBlocker();
}
}
};
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,57 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_SelectionChangeListener_h_
#define mozilla_SelectionChangeListener_h_
#include "nsISelectionListener.h"
#include "nsISelectionPrivate.h"
#include "mozilla/Attributes.h"
namespace mozilla {
namespace dom {
class SelectionChangeListener final : public nsISelectionListener
{
public:
// SelectionChangeListener has to participate in cycle collection because
// it holds strong references to nsINodes in its mOldRanges array.
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(SelectionChangeListener)
NS_DECL_NSISELECTIONLISTENER
// This field is used to keep track of the ranges which were present in the
// selection when the selectionchange event was previously fired. This allows
// for the selectionchange event to only be fired when a selection is actually
// changed.
struct RawRangeData
{
// These properties are not void*s to avoid the potential situation where the
// nsINode is freed, and a new nsINode is allocated with the same address, which
// could potentially break the comparison logic. In reality, this is extremely
// unlikely to occur (potentially impossible), but these nsCOMPtrs are safer.
// They are never dereferenced.
nsCOMPtr<nsINode> mStartParent;
nsCOMPtr<nsINode> mEndParent;
// XXX These are int32_ts on nsRange, but uint32_ts in the return value
// of GetStart_, so I use uint32_ts here. See bug 1194256.
uint32_t mStartOffset;
uint32_t mEndOffset;
explicit RawRangeData(const nsRange* aRange);
bool Equals(const nsRange* aRange);
};
private:
nsTArray<RawRangeData> mOldRanges;
~SelectionChangeListener() {}
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_SelectionChangeListener_h_

View File

@ -3623,7 +3623,7 @@ nsFlexContainerFrame::Reflow(nsPresContext* aPresContext,
// RAII class to clean up a list of FlexLines.
// Specifically, this removes each line from the list, deletes all the
// FlexItems in its list, and deletes the FlexLine.
class MOZ_STACK_CLASS AutoFlexLineListClearer
class MOZ_RAII AutoFlexLineListClearer
{
public:
explicit AutoFlexLineListClearer(LinkedList<FlexLine>& aLines

View File

@ -752,6 +752,8 @@ private:
bool mDesiredPosSet;
int8_t mCaretMovementStyle;
static bool sSelectionEventsEnabled;
};
#endif /* nsFrameSelection_h___ */

View File

@ -68,6 +68,7 @@ static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID);
#include "nsISelectionController.h"//for the enums
#include "nsAutoCopyListener.h"
#include "SelectionChangeListener.h"
#include "nsCopySupport.h"
#include "nsIClipboard.h"
#include "nsIFrameInlines.h"
@ -79,6 +80,7 @@ static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID);
#include "mozilla/dom/ShadowRoot.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/SelectionBinding.h"
#include "mozilla/AsyncEventDispatcher.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -332,7 +334,7 @@ IsValidSelectionPoint(nsFrameSelection *aFrameSel, nsINode *aNode)
}
namespace mozilla {
struct MOZ_STACK_CLASS AutoPrepareFocusRange
struct MOZ_RAII AutoPrepareFocusRange
{
AutoPrepareFocusRange(Selection* aSelection,
bool aContinueSelection,
@ -412,7 +414,7 @@ struct MOZ_STACK_CLASS AutoPrepareFocusRange
while (i--) {
range = aSelection->mRanges[i].mRange;
if (range->IsGenerated()) {
range->SetInSelection(false);
range->SetSelection(nullptr);
aSelection->selectFrames(presContext, range, false);
aSelection->mRanges.RemoveElementAt(i);
}
@ -814,6 +816,16 @@ nsFrameSelection::Init(nsIPresShell *aShell, nsIContent *aLimiter)
mLimiter = aLimiter;
mCaretMovementStyle =
Preferences::GetInt("bidi.edit.caret_movement_style", 2);
// This should only ever be initialized on the main thread, so we are OK here.
static bool prefCachesInitialized = false;
if (!prefCachesInitialized) {
prefCachesInitialized = true;
Preferences::AddBoolVarCache(&sSelectionEventsEnabled,
"dom.select_events.enabled", false);
}
// Set touch caret as selection listener
nsRefPtr<TouchCaret> touchCaret = mShell->GetTouchCaret();
if (touchCaret) {
@ -839,8 +851,21 @@ nsFrameSelection::Init(nsIPresShell *aShell, nsIContent *aLimiter)
mDomSelections[index]->AddSelectionListener(eventHub);
}
}
if (sSelectionEventsEnabled) {
int8_t index =
GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
if (mDomSelections[index]) {
// The Selection instance will hold a strong reference to its selectionchangelistener
// so we don't have to worry about that!
nsRefPtr<SelectionChangeListener> listener = new SelectionChangeListener;
mDomSelections[index]->AddSelectionListener(listener);
}
}
}
bool nsFrameSelection::sSelectionEventsEnabled = false;
nsresult
nsFrameSelection::MoveCaret(nsDirection aDirection,
bool aContinueSelection,
@ -3307,6 +3332,7 @@ Selection::Selection()
, mDirection(eDirNext)
, mType(nsISelectionController::SELECTION_NORMAL)
, mApplyUserSelectStyle(false)
, mSelectionChangeBlockerCount(0)
{
}
@ -3316,6 +3342,7 @@ Selection::Selection(nsFrameSelection* aList)
, mDirection(eDirNext)
, mType(nsISelectionController::SELECTION_NORMAL)
, mApplyUserSelectStyle(false)
, mSelectionChangeBlockerCount(0)
{
}
@ -3325,7 +3352,7 @@ Selection::~Selection()
uint32_t count = mRanges.Length();
for (uint32_t i = 0; i < count; ++i) {
mRanges[i].mRange->SetInSelection(false);
mRanges[i].mRange->SetSelection(nullptr);
}
if (mAutoScrollTimer) {
@ -3647,8 +3674,24 @@ Selection::SubtractRange(RangeData* aRange, nsRange* aSubtract,
return NS_OK;
}
void
Selection::UserSelectRangesToAdd(nsRange* aItem, nsTArray<nsRefPtr<nsRange>>& aRangesToAdd)
{
aItem->ExcludeNonSelectableNodes(&aRangesToAdd);
if (aRangesToAdd.IsEmpty()) {
ErrorResult err;
nsINode* node = aItem->GetStartContainer(err);
if (node && node->IsContent() && node->AsContent()->GetEditingHost()) {
// A contenteditable node with user-select:none, for example.
// Allow it to have a collapsed selection (for the caret).
aItem->Collapse(GetDirection() == eDirPrevious);
aRangesToAdd.AppendElement(aItem);
}
}
}
nsresult
Selection::AddItem(nsRange* aItem, int32_t* aOutIndex)
Selection::AddItem(nsRange* aItem, int32_t* aOutIndex, bool aNoStartSelect)
{
if (!aItem)
return NS_ERROR_NULL_POINTER;
@ -3657,20 +3700,60 @@ Selection::AddItem(nsRange* aItem, int32_t* aOutIndex)
NS_ASSERTION(aOutIndex, "aOutIndex can't be null");
// XXX Rename mApplyUserSelectStyle? Not the best name (as it is also being
// used to detect here whether the event is user initiated for the purposes of
// dispatching the selectstart event).
if (mApplyUserSelectStyle) {
nsAutoTArray<nsRefPtr<nsRange>, 4> rangesToAdd;
aItem->ExcludeNonSelectableNodes(&rangesToAdd);
if (rangesToAdd.IsEmpty()) {
ErrorResult err;
nsINode* node = aItem->GetStartContainer(err);
if (node && node->IsContent() && node->AsContent()->GetEditingHost()) {
// A contenteditable node with user-select:none, for example.
// Allow it to have a collapsed selection (for the caret).
aItem->Collapse(GetDirection() == eDirPrevious);
rangesToAdd.AppendElement(aItem);
}
}
*aOutIndex = -1;
if (!aNoStartSelect && mType == nsISelectionController::SELECTION_NORMAL &&
nsFrameSelection::sSelectionEventsEnabled && Collapsed() &&
!IsBlockingSelectionChangeEvents()) {
// First, we generate the ranges to add with a scratch range, which is a
// clone of the original range passed in. We do this seperately, because the
// selectstart event could have caused the world to change, and required
// ranges to be re-generated
nsRefPtr<nsRange> scratchRange = aItem->CloneRange();
UserSelectRangesToAdd(scratchRange, rangesToAdd);
bool newRangesNonEmpty = rangesToAdd.Length() > 1 ||
(rangesToAdd.Length() == 1 && !rangesToAdd[0]->Collapsed());
MOZ_ASSERT(!newRangesNonEmpty || nsContentUtils::IsSafeToRunScript());
if (newRangesNonEmpty && nsContentUtils::IsSafeToRunScript()) {
// We consider a selection to be starting if we are currently collapsed,
// and the selection is becoming uncollapsed, and this is caused by a user
// initiated event.
bool defaultAction = true;
// Get the first element which isn't in a native anonymous subtree
nsCOMPtr<nsINode> target = aItem->GetStartParent();
while (target && target->IsInNativeAnonymousSubtree()) {
target = target->GetParent();
}
nsContentUtils::DispatchTrustedEvent(GetParentObject(), target,
NS_LITERAL_STRING("selectstart"),
true, true, &defaultAction);
if (!defaultAction) {
return NS_OK;
}
// As we just dispatched an event to the DOM, something could have
// changed under our feet. Re-generate the rangesToAdd array, and ensure
// that the range we are about to add is still valid.
if (!aItem->IsPositioned()) {
return NS_ERROR_UNEXPECTED;
}
}
// The scratch ranges we generated may be invalid now, throw them out
rangesToAdd.ClearAndRetainStorage();
}
// Generate the ranges to add
UserSelectRangesToAdd(aItem, rangesToAdd);
size_t newAnchorFocusIndex =
GetDirection() == eDirPrevious ? 0 : rangesToAdd.Length() - 1;
for (size_t i = 0; i < rangesToAdd.Length(); ++i) {
@ -3702,7 +3785,7 @@ Selection::AddItemInternal(nsRange* aItem, int32_t* aOutIndex)
if (mRanges.Length() == 0) {
if (!mRanges.AppendElement(RangeData(aItem)))
return NS_ERROR_OUT_OF_MEMORY;
aItem->SetInSelection(true);
aItem->SetSelection(this);
*aOutIndex = 0;
return NS_OK;
@ -3742,7 +3825,7 @@ Selection::AddItemInternal(nsRange* aItem, int32_t* aOutIndex)
// The new range doesn't overlap any existing ranges
if (!mRanges.InsertElementAt(startIndex, RangeData(aItem)))
return NS_ERROR_OUT_OF_MEMORY;
aItem->SetInSelection(true);
aItem->SetSelection(this);
*aOutIndex = startIndex;
return NS_OK;
}
@ -3764,7 +3847,7 @@ Selection::AddItemInternal(nsRange* aItem, int32_t* aOutIndex)
// Remove all the overlapping ranges
for (int32_t i = startIndex; i < endIndex; ++i) {
mRanges[i].mRange->SetInSelection(false);
mRanges[i].mRange->SetSelection(nullptr);
}
mRanges.RemoveElementsAt(startIndex, endIndex - startIndex);
@ -3789,7 +3872,7 @@ Selection::AddItemInternal(nsRange* aItem, int32_t* aOutIndex)
return NS_ERROR_OUT_OF_MEMORY;
for (uint32_t i = 0; i < temp.Length(); ++i) {
temp[i].mRange->SetInSelection(true);
temp[i].mRange->SetSelection(this);
}
*aOutIndex = startIndex + insertionPoint;
@ -3818,7 +3901,7 @@ Selection::RemoveItem(nsRange* aItem)
return NS_ERROR_INVALID_ARG;
mRanges.RemoveElementAt(idx);
aItem->SetInSelection(false);
aItem->SetSelection(nullptr);
return NS_OK;
}
@ -3843,7 +3926,7 @@ Selection::Clear(nsPresContext* aPresContext)
setAnchorFocusRange(-1);
for (uint32_t i = 0; i < mRanges.Length(); ++i) {
mRanges[i].mRange->SetInSelection(false);
mRanges[i].mRange->SetSelection(nullptr);
selectFrames(aPresContext, mRanges[i].mRange, false);
}
mRanges.Clear();
@ -5064,12 +5147,14 @@ Selection::SetAnchorFocusToRange(nsRange* aRange)
{
NS_ENSURE_STATE(mAnchorFocusRange);
bool collapsed = Collapsed();
nsresult res = RemoveItem(mAnchorFocusRange);
if (NS_FAILED(res))
return res;
int32_t aOutIndex = -1;
res = AddItem(aRange, &aOutIndex);
res = AddItem(aRange, &aOutIndex, !collapsed);
if (NS_FAILED(res))
return res;
setAnchorFocusRange(aOutIndex);
@ -5471,19 +5556,16 @@ Selection::SelectAllChildren(nsIDOMNode* aParentNode)
void
Selection::SelectAllChildren(nsINode& aNode, ErrorResult& aRv)
{
if (mFrameSelection)
{
if (mFrameSelection) {
mFrameSelection->PostReason(nsISelectionListener::SELECTALL_REASON);
}
SelectionBatcher batch(this);
Collapse(aNode, 0, aRv);
if (aRv.Failed()) {
return;
}
if (mFrameSelection)
{
mFrameSelection->PostReason(nsISelectionListener::SELECTALL_REASON);
}
Extend(aNode, aNode.GetChildCount(), aRv);
}
@ -5926,7 +6008,26 @@ Selection::EndBatchChanges()
return NS_OK;
}
void
Selection::AddSelectionChangeBlocker()
{
mSelectionChangeBlockerCount++;
}
void
Selection::RemoveSelectionChangeBlocker()
{
MOZ_ASSERT(mSelectionChangeBlockerCount > 0,
"mSelectionChangeBlockerCount has an invalid value - "
"maybe you have a mismatched RemoveSelectionChangeBlocker?");
mSelectionChangeBlockerCount--;
}
bool
Selection::IsBlockingSelectionChangeEvents() const
{
return mSelectionChangeBlockerCount > 0;
}
NS_IMETHODIMP
Selection::DeleteFromDocument()
@ -6159,6 +6260,13 @@ Selection::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
return mozilla::dom::SelectionBinding::Wrap(aCx, this, aGivenProto);
}
// AutoHideSelectionChanges
AutoHideSelectionChanges::AutoHideSelectionChanges(const nsFrameSelection* aFrame)
: AutoHideSelectionChanges(aFrame ?
aFrame->GetSelection(nsISelectionController::SELECTION_NORMAL) :
nullptr)
{}
// nsAutoCopyListener
nsAutoCopyListener* nsAutoCopyListener::sInstance = nullptr;
@ -6218,3 +6326,131 @@ nsAutoCopyListener::NotifySelectionChanged(nsIDOMDocument *aDoc,
return nsCopySupport::HTMLCopy(aSel, doc,
nsIClipboard::kSelectionClipboard, false);
}
// SelectionChangeListener
SelectionChangeListener::RawRangeData::RawRangeData(const nsRange* aRange)
{
mozilla::ErrorResult rv;
mStartParent = aRange->GetStartContainer(rv);
rv.SuppressException();
mEndParent = aRange->GetEndContainer(rv);
rv.SuppressException();
mStartOffset = aRange->GetStartOffset(rv);
rv.SuppressException();
mEndOffset = aRange->GetEndOffset(rv);
rv.SuppressException();
}
bool
SelectionChangeListener::RawRangeData::Equals(const nsRange* aRange)
{
mozilla::ErrorResult rv;
bool eq = mStartParent == aRange->GetStartContainer(rv);
rv.SuppressException();
eq = eq && mEndParent == aRange->GetEndContainer(rv);
rv.SuppressException();
eq = eq && mStartOffset == aRange->GetStartOffset(rv);
rv.SuppressException();
eq = eq && mEndOffset == aRange->GetEndOffset(rv);
rv.SuppressException();
return eq;
}
inline void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
SelectionChangeListener::RawRangeData& aField,
const char* aName,
uint32_t aFlags = 0)
{
ImplCycleCollectionTraverse(aCallback, aField.mStartParent, "mStartParent", aFlags);
ImplCycleCollectionTraverse(aCallback, aField.mEndParent, "mEndParent", aFlags);
}
NS_IMPL_CYCLE_COLLECTION_CLASS(SelectionChangeListener)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(SelectionChangeListener)
tmp->mOldRanges.Clear();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(SelectionChangeListener)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOldRanges);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SelectionChangeListener)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY(nsISelectionListener)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(SelectionChangeListener)
NS_IMPL_CYCLE_COLLECTING_RELEASE(SelectionChangeListener)
NS_IMETHODIMP
SelectionChangeListener::NotifySelectionChanged(nsIDOMDocument* aDoc,
nsISelection* aSel, int16_t aReason)
{
// This cast is valid as nsISelection is a builtinclass which is only
// implemented by Selection.
nsRefPtr<Selection> sel = static_cast<Selection*>(aSel);
// Check if the ranges have actually changed
// Don't bother checking this if we are hiding changes.
if (mOldRanges.Length() == sel->RangeCount() && !sel->IsBlockingSelectionChangeEvents()) {
bool changed = false;
for (size_t i = 0; i < mOldRanges.Length(); i++) {
if (!mOldRanges[i].Equals(sel->GetRangeAt(i))) {
changed = true;
break;
}
}
if (!changed) {
return NS_OK;
}
}
// The ranges have actually changed, update the mOldRanges array
mOldRanges.ClearAndRetainStorage();
for (size_t i = 0; i < sel->RangeCount(); i++) {
mOldRanges.AppendElement(RawRangeData(sel->GetRangeAt(i)));
}
// If we are hiding changes, then don't do anything else. We do this after we
// update mOldRanges so that changes after the changes stop being hidden don't
// incorrectly trigger a change, even though they didn't change anything
if (sel->IsBlockingSelectionChangeEvents()) {
return NS_OK;
}
nsCOMPtr<nsINode> target;
// Check if we should be firing this event to a different node than the
// document. The limiter of the nsFrameSelection will be within the native
// anonymous subtree of the node we want to fire the event on. We need to
// climb up the parent chain to escape the native anonymous subtree, and then
// fire the event.
if (nsFrameSelection* fs = sel->GetFrameSelection()) {
if (nsCOMPtr<nsIContent> root = fs->GetLimiter()) {
while (root && root->IsInNativeAnonymousSubtree()) {
root = root->GetParent();
}
target = root.forget();
}
}
// If we didn't get a target before, we can instead fire the event at the document.
if (!target) {
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDoc);
target = doc.forget();
}
if (target) {
nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(target, NS_LITERAL_STRING("selectionchange"), false);
asyncDispatcher->PostDOMEvent();
}
return NS_OK;
}

View File

@ -428,7 +428,7 @@ protected:
* state (in a CSSParserInputState object), and it restores the parser to
* that state when destructed, unless "DoNotRestore()" has been called.
*/
class MOZ_STACK_CLASS nsAutoCSSParserInputStateRestorer {
class MOZ_RAII nsAutoCSSParserInputStateRestorer {
public:
explicit nsAutoCSSParserInputStateRestorer(CSSParserImpl* aParser
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
@ -476,7 +476,7 @@ protected:
* XXXdholbert we could also change this & report errors, if needed. Might
* want to customize the error reporting somehow though.
*/
class MOZ_STACK_CLASS nsAutoScannerChanger {
class MOZ_RAII nsAutoScannerChanger {
public:
nsAutoScannerChanger(CSSParserImpl* aParser,
const nsAString& aStringToScan

View File

@ -225,7 +225,7 @@ struct MOZ_STACK_CLASS TreeMatchContext {
}
/* Helper class for maintaining the ancestor state */
class MOZ_STACK_CLASS AutoAncestorPusher {
class MOZ_RAII AutoAncestorPusher {
public:
explicit AutoAncestorPusher(TreeMatchContext& aTreeMatchContext
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
@ -295,7 +295,7 @@ struct MOZ_STACK_CLASS TreeMatchContext {
* in cases where we may or may not want to be skipping flex/grid-item
* style fixup for a particular chunk of code).
*/
class MOZ_STACK_CLASS AutoParentDisplayBasedStyleFixupSkipper {
class MOZ_RAII AutoParentDisplayBasedStyleFixupSkipper {
public:
explicit AutoParentDisplayBasedStyleFixupSkipper(TreeMatchContext& aTreeMatchContext,
bool aSkipParentDisplayBasedStyleFixup = true

View File

@ -104,7 +104,7 @@ public:
// automatically sets and clears the mInUse flag on the clip path frame
// (to prevent nasty reference loops). It's easy to mess this up
// and break things, so this helper makes the code far more robust.
class MOZ_STACK_CLASS AutoClipPathReferencer
class MOZ_RAII AutoClipPathReferencer
{
public:
explicit AutoClipPathReferencer(nsSVGClipPathFrame *aFrame

View File

@ -27,7 +27,7 @@ NS_NewSVGFilterFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
NS_IMPL_FRAMEARENA_HELPERS(nsSVGFilterFrame)
class MOZ_STACK_CLASS nsSVGFilterFrame::AutoFilterReferencer
class MOZ_RAII nsSVGFilterFrame::AutoFilterReferencer
{
public:
explicit AutoFilterReferencer(nsSVGFilterFrame *aFrame MOZ_GUARD_OBJECT_NOTIFIER_PARAM)

View File

@ -24,7 +24,7 @@ using namespace mozilla::dom;
//----------------------------------------------------------------------
// Helper classes
class MOZ_STACK_CLASS nsSVGGradientFrame::AutoGradientReferencer
class MOZ_RAII nsSVGGradientFrame::AutoGradientReferencer
{
public:
explicit AutoGradientReferencer(nsSVGGradientFrame *aFrame

View File

@ -110,7 +110,7 @@ private:
// prevent nasty reference loops) as well as the reference to the marked
// frame and its coordinate context. It's easy to mess this up
// and break things, so this helper makes the code far more robust.
class MOZ_STACK_CLASS AutoMarkerReferencer
class MOZ_RAII AutoMarkerReferencer
{
public:
AutoMarkerReferencer(nsSVGMarkerFrame *aFrame,

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