Merge m-c to fx-team, a=merge

This commit is contained in:
Wes Kocher 2016-07-05 17:13:25 -07:00
commit 59c25d40ac
102 changed files with 1292 additions and 1189 deletions

View File

@ -81,7 +81,9 @@ addEventListener("blur", function(event) {
LoginManagerContent.onUsernameInput(event);
});
var gLastContextMenuEvent = null; // null or a WeakReference to a contextmenu event
var handleContentContextMenu = function (event) {
gLastContextMenuEvent = null;
let defaultPrevented = event.defaultPrevented;
if (!Services.prefs.getBoolPref("dom.event.contextmenu.enabled")) {
let plugin = null;
@ -96,8 +98,36 @@ var handleContentContextMenu = function (event) {
defaultPrevented = false;
}
if (defaultPrevented)
if (defaultPrevented) {
return;
}
if (event.mozInputSource == Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH) {
// If this was triggered by touch, then we don't want to show the actual
// context menu until we get the APZ:LongTapUp notification. However, we
// will need the |event| object when we get that notification, so we save
// it in a WeakReference. That way it won't leak things if we never get
// the APZ:LongTapUp notification (which is quite possible).
gLastContextMenuEvent = Cu.getWeakReference(event);
return;
}
// For non-touch-derived contextmenu events, we can handle it right away.
showContentContextMenu(event);
}
var showContentContextMenu = function (event) {
if (event == null) {
// If we weren't given an event, then this is being invoked from the
// APZ:LongTapUp observer, and the contextmenu event is stashed in
// gLastContextMenuEvent.
event = (gLastContextMenuEvent ? gLastContextMenuEvent.get() : null);
gLastContextMenuEvent = null;
if (event == null) {
// Still no event? We can't do anything, bail out.
return;
}
}
let addonInfo = {};
let subject = {
@ -215,6 +245,11 @@ Cc["@mozilla.org/eventlistenerservice;1"]
.getService(Ci.nsIEventListenerService)
.addSystemEventListener(global, "contextmenu", handleContentContextMenu, false);
Services.obs.addObserver(showContentContextMenu, "APZ:LongTapUp", false);
addEventListener("unload", () => {
Services.obs.removeObserver(showContentContextMenu, "APZ:LongTapUp")
}, false);
// Values for telemtery bins: see TLS_ERROR_REPORT_UI in Histograms.json
const TLS_ERROR_REPORT_TELEMETRY_UI_SHOWN = 0;
const TLS_ERROR_REPORT_TELEMETRY_EXPANDED = 1;

View File

@ -1386,11 +1386,12 @@ nsresult nsScriptSecurityManager::Init()
JSPrincipalsSubsume,
};
MOZ_ASSERT(!JS_GetSecurityCallbacks(sRuntime));
JS_SetSecurityCallbacks(sRuntime, &securityCallbacks);
JS_InitDestroyPrincipalsCallback(sRuntime, nsJSPrincipals::Destroy);
JSContext* cx = JS_GetContext(sRuntime);
MOZ_ASSERT(!JS_GetSecurityCallbacks(cx));
JS_SetSecurityCallbacks(cx, &securityCallbacks);
JS_InitDestroyPrincipalsCallback(cx, nsJSPrincipals::Destroy);
JS_SetTrustedPrincipals(sRuntime, system);
JS_SetTrustedPrincipals(cx, system);
return NS_OK;
}
@ -1414,8 +1415,8 @@ void
nsScriptSecurityManager::Shutdown()
{
if (sRuntime) {
JS_SetSecurityCallbacks(sRuntime, nullptr);
JS_SetTrustedPrincipals(sRuntime, nullptr);
JS_SetSecurityCallbacks(JS_GetContext(sRuntime), nullptr);
JS_SetTrustedPrincipals(JS_GetContext(sRuntime), nullptr);
sRuntime = nullptr;
}

View File

@ -68,24 +68,6 @@ struct DevTools : public ::testing::Test {
return CycleCollectedJSRuntime::Get()->Runtime();
}
static void setNativeStackQuota(JSRuntime* rt)
{
const size_t MAX_STACK_SIZE =
/* Assume we can't use more than 5e5 bytes of C stack by default. */
#if (defined(DEBUG) && defined(__SUNPRO_CC)) || defined(JS_CPU_SPARC)
/*
* Sun compiler uses a larger stack space for js::Interpret() with
* debug. Use a bigger gMaxStackSize to make "make check" happy.
*/
5000000
#else
500000
#endif
;
JS_SetNativeStackQuota(rt, MAX_STACK_SIZE);
}
static void reportError(JSContext* cx, const char* message, JSErrorReport* report) {
fprintf(stderr, "%s:%u:%s\n",
report->filename ? report->filename : "<no filename>",

View File

@ -1252,8 +1252,8 @@ Animation::DoFinishNotification(SyncNotifyFlag aSyncNotifyFlag)
} else if (!mFinishNotificationTask.IsPending()) {
RefPtr<nsRunnableMethod<Animation>> runnable =
NewRunnableMethod(this, &Animation::DoFinishNotificationImmediately);
runtime->DispatchToMicroTask(runnable);
mFinishNotificationTask = runnable;
runtime->DispatchToMicroTask(do_AddRef(runnable));
mFinishNotificationTask = runnable.forget();
}
}

View File

@ -1540,12 +1540,13 @@ addAsyncAnimTest("tree_ordering", { observe: div, subtree: true }, function*() {
yield await_frame();
assert_records([], "records after assigning same value");
anim.currentTime = 500 * MS_PER_SEC;
anim.currentTime = anim.effect.timing.duration * 2;
anim.finish();
yield await_frame();
assert_records([{ added: [], changed: [], removed: [anim] }],
"records after animation end");
anim.effect.timing.duration = 1000 * MS_PER_SEC;
anim.effect.timing.duration = anim.effect.timing.duration * 3;
yield await_frame();
assert_records([{ added: [anim], changed: [], removed: [] }],
"records after animation restarted");

View File

@ -2309,7 +2309,7 @@ SetMemoryHighWaterMarkPrefChangedCallback(const char* aPrefName, void* aClosure)
{
int32_t highwatermark = Preferences::GetInt(aPrefName, 128);
JS_SetGCParameter(sRuntime, JSGC_MAX_MALLOC_BYTES,
JS_SetGCParameter(JS_GetContext(sRuntime), JSGC_MAX_MALLOC_BYTES,
highwatermark * 1024L * 1024L);
}
@ -2319,7 +2319,7 @@ SetMemoryMaxPrefChangedCallback(const char* aPrefName, void* aClosure)
int32_t pref = Preferences::GetInt(aPrefName, -1);
// handle overflow and negative pref values
uint32_t max = (pref <= 0 || pref >= 0x1000) ? -1 : (uint32_t)pref * 1024 * 1024;
JS_SetGCParameter(sRuntime, JSGC_MAX_BYTES, max);
JS_SetGCParameter(JS_GetContext(sRuntime), JSGC_MAX_BYTES, max);
}
static void
@ -2335,7 +2335,7 @@ SetMemoryGCModePrefChangedCallback(const char* aPrefName, void* aClosure)
} else {
mode = JSGC_MODE_GLOBAL;
}
JS_SetGCParameter(sRuntime, JSGC_MODE, mode);
JS_SetGCParameter(JS_GetContext(sRuntime), JSGC_MODE, mode);
}
static void
@ -2344,14 +2344,14 @@ SetMemoryGCSliceTimePrefChangedCallback(const char* aPrefName, void* aClosure)
int32_t pref = Preferences::GetInt(aPrefName, -1);
// handle overflow and negative pref values
if (pref > 0 && pref < 100000)
JS_SetGCParameter(sRuntime, JSGC_SLICE_TIME_BUDGET, pref);
JS_SetGCParameter(JS_GetContext(sRuntime), JSGC_SLICE_TIME_BUDGET, pref);
}
static void
SetMemoryGCCompactingPrefChangedCallback(const char* aPrefName, void* aClosure)
{
bool pref = Preferences::GetBool(aPrefName);
JS_SetGCParameter(sRuntime, JSGC_COMPACTING_ENABLED, pref);
JS_SetGCParameter(JS_GetContext(sRuntime), JSGC_COMPACTING_ENABLED, pref);
}
static void
@ -2360,28 +2360,28 @@ SetMemoryGCPrefChangedCallback(const char* aPrefName, void* aClosure)
int32_t pref = Preferences::GetInt(aPrefName, -1);
// handle overflow and negative pref values
if (pref >= 0 && pref < 10000)
JS_SetGCParameter(sRuntime, (JSGCParamKey)(intptr_t)aClosure, pref);
JS_SetGCParameter(JS_GetContext(sRuntime), (JSGCParamKey)(intptr_t)aClosure, pref);
}
static void
SetMemoryGCDynamicHeapGrowthPrefChangedCallback(const char* aPrefName, void* aClosure)
{
bool pref = Preferences::GetBool(aPrefName);
JS_SetGCParameter(sRuntime, JSGC_DYNAMIC_HEAP_GROWTH, pref);
JS_SetGCParameter(JS_GetContext(sRuntime), JSGC_DYNAMIC_HEAP_GROWTH, pref);
}
static void
SetMemoryGCDynamicMarkSlicePrefChangedCallback(const char* aPrefName, void* aClosure)
{
bool pref = Preferences::GetBool(aPrefName);
JS_SetGCParameter(sRuntime, JSGC_DYNAMIC_MARK_SLICE, pref);
JS_SetGCParameter(JS_GetContext(sRuntime), JSGC_DYNAMIC_MARK_SLICE, pref);
}
static void
SetMemoryGCRefreshFrameSlicesEnabledPrefChangedCallback(const char* aPrefName, void* aClosure)
{
bool pref = Preferences::GetBool(aPrefName);
JS_SetGCParameter(sRuntime, JSGC_REFRESH_FRAME_SLICES_ENABLED, pref);
JS_SetGCParameter(JS_GetContext(sRuntime), JSGC_REFRESH_FRAME_SLICES_ENABLED, pref);
}

View File

@ -27,7 +27,7 @@ AsyncEventDispatcher::AsyncEventDispatcher(EventTarget* aTarget,
MOZ_ASSERT(mTarget);
RefPtr<Event> event =
EventDispatcher::CreateEvent(aTarget, nullptr, &aEvent, EmptyString());
mEvent = do_QueryInterface(event);
mEvent = event.forget();
NS_ASSERTION(mEvent, "Should never fail to create an event");
mEvent->DuplicatePrivateData();
mEvent->SetTrusted(aEvent.IsTrusted());

View File

@ -55,7 +55,7 @@ public:
{
GetHTMLAttr(nsGkAtoms::srclang, aSrclang);
}
void GetSrclang(nsString& aSrclang) const
void GetSrclang(nsAString& aSrclang) const
{
GetHTMLAttr(nsGkAtoms::srclang, aSrclang);
}
@ -68,7 +68,7 @@ public:
{
GetHTMLAttr(nsGkAtoms::label, aLabel);
}
void GetLabel(nsString& aLabel) const
void GetLabel(nsAString& aLabel) const
{
GetHTMLAttr(nsGkAtoms::label, aLabel);
}

View File

@ -24155,10 +24155,11 @@ NormalJSRuntime::Init()
return false;
}
// Not setting this will cause JS_CHECK_RECURSION to report false positives.
JS_SetNativeStackQuota(mRuntime, 128 * sizeof(size_t) * 1024);
mContext = JS_GetContext(mRuntime);
// Not setting this will cause JS_CHECK_RECURSION to report false positives.
JS_SetNativeStackQuota(mContext, 128 * sizeof(size_t) * 1024);
if (NS_WARN_IF(!JS::InitSelfHostedCode(mContext))) {
return false;
}

View File

@ -138,6 +138,7 @@ using namespace mozilla::layout;
using namespace mozilla::docshell;
using namespace mozilla::widget;
using namespace mozilla::jsipc;
using mozilla::layers::GeckoContentController;
NS_IMPL_ISUPPORTS(ContentListener, nsIDOMEventListener)
@ -1784,27 +1785,39 @@ TabChild::HandleDoubleTap(const CSSPoint& aPoint, const Modifiers& aModifiers,
}
void
TabChild::HandleSingleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid,
bool aCallTakeFocusForClickFromTap)
TabChild::HandleTap(GeckoContentController::TapType aType,
const CSSPoint& aPoint, const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid, const uint64_t& aInputBlockId,
bool aCallTakeFocusForClickFromTap)
{
if (aCallTakeFocusForClickFromTap && mRemoteFrame) {
mRemoteFrame->SendTakeFocusForClickFromTap();
}
if (mGlobal && mTabChildGlobal) {
mAPZEventState->ProcessSingleTap(aPoint, aModifiers, aGuid);
}
}
void
TabChild::HandleLongTap(const CSSPoint& aPoint, const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId)
{
if (mGlobal && mTabChildGlobal) {
mAPZEventState->ProcessLongTap(GetPresShell(), aPoint, aModifiers, aGuid,
aInputBlockId);
switch (aType) {
case GeckoContentController::TapType::eSingleTap:
if (aCallTakeFocusForClickFromTap && mRemoteFrame) {
mRemoteFrame->SendTakeFocusForClickFromTap();
}
if (mGlobal && mTabChildGlobal) {
mAPZEventState->ProcessSingleTap(aPoint, aModifiers, aGuid);
}
break;
case GeckoContentController::TapType::eDoubleTap:
HandleDoubleTap(aPoint, aModifiers, aGuid);
break;
case GeckoContentController::TapType::eLongTap:
if (mGlobal && mTabChildGlobal) {
mAPZEventState->ProcessLongTap(GetPresShell(), aPoint, aModifiers, aGuid,
aInputBlockId);
}
break;
case GeckoContentController::TapType::eLongTapUp:
if (mGlobal && mTabChildGlobal) {
mAPZEventState->ProcessLongTapUp();
}
break;
case GeckoContentController::TapType::eSentinel:
// Should never happen, but we need to handle this case to make the compiler
// happy.
MOZ_ASSERT(false);
break;
}
}

View File

@ -624,17 +624,12 @@ public:
bool aPreventDefault) const;
void SetTargetAPZC(uint64_t aInputBlockId,
const nsTArray<ScrollableLayerGuid>& aTargets) const;
void HandleDoubleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const mozilla::layers::ScrollableLayerGuid& aGuid);
void HandleSingleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const mozilla::layers::ScrollableLayerGuid& aGuid,
bool aCallTakeFocusForClickFromTap);
void HandleLongTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const mozilla::layers::ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId);
void HandleTap(layers::GeckoContentController::TapType aType,
const CSSPoint& aPoint,
const Modifiers& aModifiers,
const mozilla::layers::ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId,
bool aCallTakeFocusForClickFromTap);
void SetAllowedTouchBehavior(uint64_t aInputBlockId,
const nsTArray<TouchBehaviorFlags>& aFlags) const;
@ -689,6 +684,9 @@ protected:
#endif
private:
void HandleDoubleTap(const CSSPoint& aPoint, const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid);
// Notify others that our TabContext has been updated. (At the moment, this
// sets the appropriate origin attributes on our docshell.)
//

View File

@ -299,5 +299,24 @@ TextTrack::NotifyCueUpdated(TextTrackCue *aCue)
SetDirty();
}
void
TextTrack::GetLabel(nsAString& aLabel) const
{
if (mTrackElement) {
mTrackElement->GetLabel(aLabel);
} else {
aLabel = mLabel;
}
}
void
TextTrack::GetLanguage(nsAString& aLanguage) const
{
if (mTrackElement) {
mTrackElement->GetSrclang(aLanguage);
} else {
aLanguage = mLanguage;
}
}
} // namespace dom
} // namespace mozilla

View File

@ -65,14 +65,8 @@ public:
{
return mKind;
}
void GetLabel(nsAString& aLabel) const
{
aLabel = mLabel;
}
void GetLanguage(nsAString& aLanguage) const
{
aLanguage = mLanguage;
}
void GetLabel(nsAString& aLabel) const;
void GetLanguage(nsAString& aLanguage) const;
void GetInBandMetadataTrackDispatchType(nsAString& aType) const
{
aType = mType;

View File

@ -153,10 +153,7 @@ AudioEventTimeline::GetValuesAtTimeHelper(TimeType aTime, float* aBuffer,
const AudioTimelineEvent* previous = nullptr;
// Let's remove old events except the last one: we need it to calculate some curves.
while (mEvents.Length() > 1 &&
aTime > TimeOf(mEvents[1])) {
mEvents.RemoveElementAt(0);
}
CleanupEventsOlderThan(aTime);
for (size_t bufferIndex = 0; bufferIndex < aSize; ++bufferIndex, ++aTime) {

View File

@ -336,6 +336,15 @@ public:
return mEvents.Length();
}
template<class TimeType>
void CleanupEventsOlderThan(TimeType aTime)
{
while (mEvents.Length() > 1 &&
aTime > mEvents[1].template Time<TimeType>()) {
mEvents.RemoveElementAt(0);
}
}
private:
template<class TimeType>
void GetValuesAtTimeHelper(TimeType aTime, float* aBuffer, const size_t aSize);

View File

@ -163,6 +163,15 @@ AudioParam::SendEventToEngine(const AudioTimelineEvent& aEvent)
}
}
void
AudioParam::CleanupOldEvents()
{
MOZ_ASSERT(NS_IsMainThread());
double currentTime = mNode->Context()->CurrentTime();
CleanupEventsOlderThan(currentTime);
}
float
AudioParamTimeline::AudioNodeInputValue(size_t aCounter) const
{

View File

@ -216,8 +216,12 @@ private:
AudioEventTimeline::InsertEvent<double>(event);
SendEventToEngine(event);
CleanupOldEvents();
}
void CleanupOldEvents();
void SendEventToEngine(const AudioTimelineEvent& aEvent);
void DisconnectFromGraphAndDestroyStream();

View File

@ -335,11 +335,9 @@ RegisterGCCallbacks()
return true;
}
JSRuntime *jsRuntime = xpc::GetJSRuntime();
MOZ_ASSERT(jsRuntime != nullptr);
// Register a callback to trace wrapped JSObjects.
if (!JS_AddExtraGCRootsTracer(jsRuntime, TraceJSObjWrappers, nullptr)) {
JSContext* cx = JS_GetContext(xpc::GetJSRuntime());
if (!JS_AddExtraGCRootsTracer(cx, TraceJSObjWrappers, nullptr)) {
return false;
}
@ -357,11 +355,9 @@ UnregisterGCCallbacks()
{
MOZ_ASSERT(sCallbackIsRegistered);
JSRuntime *jsRuntime = xpc::GetJSRuntime();
MOZ_ASSERT(jsRuntime != nullptr);
// Remove tracing callback.
JS_RemoveExtraGCRootsTracer(jsRuntime, TraceJSObjWrappers, nullptr);
JSContext* cx = JS_GetContext(xpc::GetJSRuntime());
JS_RemoveExtraGCRootsTracer(cx, TraceJSObjWrappers, nullptr);
// Remove delayed destruction callback.
if (sCallbackIsRegistered) {

View File

@ -995,7 +995,7 @@ Promise::PerformMicroTaskCheckpoint()
AutoSafeJSContext cx;
do {
nsCOMPtr<nsIRunnable> runnable = microtaskQueue.front();
nsCOMPtr<nsIRunnable> runnable = microtaskQueue.front().forget();
MOZ_ASSERT(runnable);
// This function can re-enter, so we remove the element before calling.
@ -1032,7 +1032,7 @@ Promise::PerformWorkerMicroTaskCheckpoint()
}
}
nsCOMPtr<nsIRunnable> runnable = microtaskQueue->front();
nsCOMPtr<nsIRunnable> runnable = microtaskQueue->front().forget();
MOZ_ASSERT(runnable);
// This function can re-enter, so we remove the element before calling.
@ -1062,7 +1062,7 @@ Promise::PerformWorkerDebuggerMicroTaskCheckpoint()
break;
}
nsCOMPtr<nsIRunnable> runnable = microtaskQueue->front();
nsCOMPtr<nsIRunnable> runnable = microtaskQueue->front().forget();
MOZ_ASSERT(runnable);
// This function can re-enter, so we remove the element before calling.
@ -2697,7 +2697,7 @@ Promise::ResolveInternal(JSContext* aCx,
new PromiseInit(nullptr, thenObj, mozilla::dom::GetIncumbentGlobal());
RefPtr<PromiseResolveThenableJob> task =
new PromiseResolveThenableJob(this, valueObj, thenCallback);
runtime->DispatchToMicroTask(task);
runtime->DispatchToMicroTask(task.forget());
return;
}
}
@ -2812,7 +2812,7 @@ Promise::TriggerPromiseReactions()
for (uint32_t i = 0; i < callbacks.Length(); ++i) {
RefPtr<PromiseReactionJob> task =
new PromiseReactionJob(this, callbacks[i], mResult);
runtime->DispatchToMicroTask(task);
runtime->DispatchToMicroTask(task.forget());
}
}

View File

@ -767,17 +767,17 @@ InitJSContextForWorker(WorkerPrivate* aWorkerPrivate, JSRuntime* aRuntime)
const JSSettings::JSGCSetting& setting = gcSettings[index];
if (setting.IsSet()) {
NS_ASSERTION(setting.value, "Can't handle 0 values!");
JS_SetGCParameter(aRuntime, setting.key, setting.value);
JS_SetGCParameter(workerCx, setting.key, setting.value);
}
}
JS_SetNativeStackQuota(aRuntime, WORKER_CONTEXT_NATIVE_STACK_LIMIT);
JS_SetNativeStackQuota(workerCx, WORKER_CONTEXT_NATIVE_STACK_LIMIT);
// Security policy:
static const JSSecurityCallbacks securityCallbacks = {
ContentSecurityPolicyAllows
};
JS_SetSecurityCallbacks(aRuntime, &securityCallbacks);
JS_SetSecurityCallbacks(workerCx, &securityCallbacks);
// Set up the asm.js cache callbacks
static const JS::AsmJSCacheOps asmJSCacheOps = {
@ -891,8 +891,8 @@ public:
JSContext* cx = JS_GetContext(rt);
js::SetPreserveWrapperCallback(rt, PreserveWrapper);
JS_InitDestroyPrincipalsCallback(rt, DestroyWorkerPrincipals);
js::SetPreserveWrapperCallback(cx, PreserveWrapper);
JS_InitDestroyPrincipalsCallback(cx, DestroyWorkerPrincipals);
JS_SetWrapObjectCallbacks(cx, &WrapObjectCallbacks);
if (mWorkerPrivate->IsDedicatedWorker()) {
JS_SetFutexCanWait(cx);
@ -948,10 +948,12 @@ public:
}
}
virtual void DispatchToMicroTask(nsIRunnable* aRunnable) override
virtual void DispatchToMicroTask(already_AddRefed<nsIRunnable> aRunnable) override
{
RefPtr<nsIRunnable> runnable(aRunnable);
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aRunnable);
MOZ_ASSERT(runnable);
std::queue<nsCOMPtr<nsIRunnable>>* microTaskQueue = nullptr;
@ -973,7 +975,7 @@ public:
microTaskQueue = &mDebuggerPromiseMicroTaskQueue;
}
microTaskQueue->push(aRunnable);
microTaskQueue->push(runnable.forget());
}
private:

View File

@ -6363,7 +6363,7 @@ WorkerPrivate::UpdateJSWorkerMemoryParameterInternal(JSContext* aCx,
// supported though. We really need some way to revert to a default value
// here.
if (aValue) {
JS_SetGCParameter(JS_GetRuntime(aCx), aKey, aValue);
JS_SetGCParameter(aCx, aKey, aValue);
}
for (uint32_t index = 0; index < mChildWorkers.Length(); index++) {

View File

@ -9,10 +9,8 @@ support-files =
window_bug583948.xul
window_bug757137.xul
1061864.html
file_bug1271240_local.xul
file_bug1271240_remote.xul
file_bug1069772_local.xul
file_bug1069772_remote.xul
file_bug1271240.xul
file_bug1069772.xul
[test_bug199692.xul]
[test_bug233643.xul]
@ -36,9 +34,7 @@ support-files =
[test_bug1061864_2.xul]
[test_bug1070049_throw_from_script.xul]
[test_import_xul_to_content.xul]
[test_bug1271240_local.xul]
[test_bug1271240_remote.xul]
skip-if = !e10s
[test_bug1069772_local.xul]
[test_bug1069772_remote.xul]
skip-if = !e10s
[test_bug1271240.xul]
skip-if = os == "android"
[test_bug1069772.xul]
skip-if = os == "android"

View File

@ -41,6 +41,22 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1069772
.then(browser => verifyBrowser(browser, false, false))
.then(browser => verifyVisibility(browser, 'visible'))
// test the transition:
// prerender => visible => hidden => visible
// on a remote browser
.then(() => createPrerenderedBrowser(true))
.then(browser => verifyBrowser(browser, true, true))
.then(browser => verifyVisibility(browser, 'prerender'))
.then(browser => makePrerenderedBrowserActive(browser))
.then(browser => verifyBrowser(browser, false, true))
.then(browser => verifyVisibility(browser, 'visible'))
.then(browser => hideBrowser(browser))
.then(browser => verifyBrowser(browser, false, true))
.then(browser => verifyVisibility(browser, 'hidden'))
.then(browser => showBrowser(browser))
.then(browser => verifyBrowser(browser, false, true))
.then(browser => verifyVisibility(browser, 'visible'))
// finish test
.then(() => {
window.close();

View File

@ -1,127 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1069772
-->
<window title="Mozilla Bug 1069772"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" onload="run();">
<!-- test code goes here -->
<script type="application/javascript">
<![CDATA[
const {interfaces: Ci, classes: Cc, results: Cr, utils: Cu} = Components;
Cu.import("resource://testing-common/ContentTask.jsm");
Cu.import("resource://testing-common/BrowserTestUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
ContentTask.setTestScope(window.opener.wrappedJSObject);
let imports = ['SimpleTest', 'ok', 'is'];
for (let name of imports) {
window[name] = window.opener.wrappedJSObject[name];
}
/** Test for Bug 1069772 **/
function run() {
// test the transition:
// prerender => visible => hidden => visible
// on a remote browser
createPrerenderedBrowser(true)
.then(browser => verifyBrowser(browser, true, true))
.then(browser => verifyVisibility(browser, 'prerender'))
.then(browser => makePrerenderedBrowserActive(browser))
.then(browser => verifyBrowser(browser, false, true))
.then(browser => verifyVisibility(browser, 'visible'))
.then(browser => hideBrowser(browser))
.then(browser => verifyBrowser(browser, false, true))
.then(browser => verifyVisibility(browser, 'hidden'))
.then(browser => showBrowser(browser))
.then(browser => verifyBrowser(browser, false, true))
.then(browser => verifyVisibility(browser, 'visible'))
// finish test
.then(() => {
window.close();
SimpleTest.finish();
});
}
function createPrerenderedBrowser(remote) {
let browser = document.createElement('browser');
browser.setAttribute('type', 'content');
browser.setAttribute('prerendered', true);
browser.setAttribute('remote', remote);
browser.setAttribute('src', 'data:text/html;charset=UTF-8,<html><body>' +
'<iframe id="iframe" src="data:text/html;charset=UTF-8,Hello Frame!">' +
'</iframe></body></html>');
// wait for 'load' and 'pageshow'
let promises = [];
promises.push(BrowserTestUtils.browserLoaded(browser));
promises.push(new Promise(resolve =>
Services.mm.addMessageListener('test:pageshow', resolve)));
Services.mm.loadFrameScript('data:,' +
'addEventListener("pageshow", ' +
'() => sendAsyncMessage("test:pageshow", null), false);',
true);
document.getElementById('stack').appendChild(browser);
return Promise.all(promises).then(() => browser);
}
function verifyBrowser(browser, prerendered, remote) {
let docShellOrTabParent = remote ?
browser.frameLoader.tabParent : browser.frameLoader.docShell;
ok(docShellOrTabParent, 'docShellOrTabParent should not be null');
is(docShellOrTabParent.isPrerendered, prerendered,
'isPrerendered should be ' + prerendered);
return browser;
}
function verifyVisibility(browser, visibility) {
return ContentTask.spawn(browser, visibility, (v) => {
let iframe = content.document.getElementById('iframe');
is(content.document.visibilityState, v, 'check doc.visibilityState');
is(content.document.hidden, v != 'visible', 'check doc.hidden');
is(iframe.contentDocument.visibilityState, v, 'check iframe doc.visibilityState');
is(iframe.contentDocument.hidden, v != 'visible', 'check iframe doc.hidden');
}).then(() => browser);
}
function makePrerenderedBrowserActive(browser) {
let promise = waitForVisibilityChange(browser);
browser.setAttribute('prerendered', false);
browser.makePrerenderedBrowserActive();
return promise.then(() => browser);
}
function hideBrowser(browser) {
let promise = waitForVisibilityChange(browser);
browser.docShellIsActive = false;
return promise.then(() => browser);
}
function showBrowser(browser) {
let promise = waitForVisibilityChange(browser);
browser.docShellIsActive = true;
return promise.then(() => browser);
}
function waitForVisibilityChange(browser) {
return ContentTask.spawn(browser, null, () => {
return new Promise(resolve => {
let iframe = content.document.getElementById('iframe');
iframe.contentDocument.addEventListener('visibilitychange', function listener() {
iframe.contentDocument.removeEventListener('visibilitychange', listener);
resolve();
});
});
});
}
]]>
</script>
<stack id="stack" flex="1" />
</window>

View File

@ -32,6 +32,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1271240
.then(browser => makePrerenderedBrowserActive(browser))
.then(browser => verifyBrowser(browser, false, false))
// test remote, non-prerendered browser
.then(() => createBrowser(false, true))
.then(browser => verifyBrowser(browser, false, true))
// test remote, prerendered browser
.then(() => createBrowser(true, true))
.then(browser => verifyBrowser(browser, true, true))
.then(browser => makePrerenderedBrowserActive(browser))
.then(browser => verifyBrowser(browser, false, true))
// finish test
.then(() => {
opener.postMessage('finish', '*');

View File

@ -1,72 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1271240
-->
<window title="Mozilla Bug 1271240"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" onload="run();">
<!-- test code goes here -->
<script type="application/javascript">
<![CDATA[
function ok(cond, msg) {
opener.wrappedJSObject.ok(cond, msg);
}
function is(actual, expected, msg) {
opener.wrappedJSObject.is(actual, expected, msg);
}
/** Test for Bug 1271240 **/
function run() {
// test remote, non-prerendered browser
createBrowser(false, true)
.then(browser => verifyBrowser(browser, false, true))
// test remote, prerendered browser
.then(() => createBrowser(true, true))
.then(browser => verifyBrowser(browser, true, true))
.then(browser => makePrerenderedBrowserActive(browser))
.then(browser => verifyBrowser(browser, false, true))
// finish test
.then(() => {
opener.postMessage('finish', '*');
window.close();
});
}
function createBrowser(prerendered, remote) {
return new Promise(resolve => {
var browser = document.createElement('browser');
browser.setAttribute('type', 'content');
browser.setAttribute('prerendered', prerendered);
browser.setAttribute('remote', remote);
document.documentElement.appendChild(browser);
browser.loadURI('example.com');
resolve(browser);
});
}
function verifyBrowser(browser, prerendered, remote) {
var docShellOrTabParent = remote ?
browser.frameLoader.tabParent : browser.frameLoader.docShell;
ok(docShellOrTabParent, 'docShellOrTabParent should not be null');
is(docShellOrTabParent.isPrerendered, prerendered,
'isPrerendered should be ' + prerendered);
return browser;
}
function makePrerenderedBrowserActive(browser) {
browser.makePrerenderedBrowserActive();
return browser;
}
]]>
</script>
<!-- <browser type="content-primary" flex="1" id="content" />
<browser type="content-primary" flex="1" id="content-remote" remote="true" /> -->
</window>

View File

@ -24,7 +24,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1069772
/** Test for Bug 1069772 **/
SimpleTest.waitForExplicitFinish();
function loadTest() {
window.open("file_bug1069772_local.xul", "", "width=360,height=240,chrome");
window.open("file_bug1069772.xul", "", "width=360,height=240,chrome");
}
]]>

View File

@ -1,32 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1069772
-->
<window title="Mozilla Bug 1069772"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="loadTest();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml">
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1069772"
target="_blank">Mozilla Bug 1069772</a>
</body>
<!-- test code goes here -->
<script type="application/javascript">
<![CDATA[
/** Test for Bug 1069772 **/
SimpleTest.waitForExplicitFinish();
function loadTest() {
window.open("file_bug1069772_remote.xul", "", "width=360,height=240,chrome");
}
]]>
</script>
</window>

View File

@ -30,7 +30,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1271240
});
function loadTest() {
window.open("file_bug1271240_local.xul", "", "chrome");
window.open("file_bug1271240.xul", "", "chrome");
}
]]>

View File

@ -1,38 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1271240
-->
<window title="Mozilla Bug 1271240"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="loadTest();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml">
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1271240"
target="_blank">Mozilla Bug 1271240</a>
</body>
<!-- test code goes here -->
<script type="application/javascript">
<![CDATA[
/** Test for Bug 1271240 **/
SimpleTest.waitForExplicitFinish();
window.addEventListener('message', (event) => {
if (event.data == 'finish') {
SimpleTest.finish();
}
});
function loadTest() {
window.open("file_bug1271240_remote.xul", "", "chrome");
}
]]>
</script>
</window>

View File

@ -944,6 +944,7 @@ DrawTargetD2D1::Init(ID3D11Texture2D* aTexture, SurfaceFormat aFormat)
ID2D1Device* device = Factory::GetD2D1Device();
if (!device) {
gfxCriticalNote << "[D2D1.1] Failed to obtain a device for DrawTargetD2D1::Init().";
return false;
}
@ -1008,6 +1009,7 @@ DrawTargetD2D1::Init(const IntSize &aSize, SurfaceFormat aFormat)
ID2D1Device* device = Factory::GetD2D1Device();
if (!device) {
gfxCriticalNote << "[D2D1.1] Failed to obtain a device for DrawTargetD2D1::Init().";
return false;
}

View File

@ -1170,6 +1170,16 @@ struct ParamTraits<mozilla::gfx::FilterDescription>
}
};
typedef mozilla::layers::GeckoContentController::TapType TapType;
template <>
struct ParamTraits<TapType>
: public ContiguousEnumSerializer<
TapType,
TapType::eSingleTap,
TapType::eSentinel>
{};
typedef mozilla::layers::GeckoContentController::APZStateChange APZStateChange;
template <>

View File

@ -38,32 +38,31 @@ public:
virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) = 0;
/**
* Requests handling of a double tap. |aPoint| is in CSS pixels, relative to
* the current scroll offset. This should eventually round-trip back to
* AsyncPanZoomController::ZoomToRect with the dimensions that we want to zoom
* to.
* Different types of tap-related events that can be sent in
* the HandleTap function. The names should be relatively self-explanatory.
* Note that the eLongTapUp will always be preceded by an eLongTap, but not
* all eLongTap notifications will be followed by an eLongTapUp (for instance,
* if the user moves their finger after triggering the long-tap but before
* lifting it).
*/
virtual void HandleDoubleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid) = 0;
enum class TapType {
eSingleTap,
eDoubleTap,
eLongTap,
eLongTapUp,
eSentinel,
};
/**
* Requests handling a single tap. |aPoint| is in CSS pixels, relative to the
* current scroll offset. This should simulate and send to content a mouse
* button down, then mouse button up at |aPoint|.
*/
virtual void HandleSingleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid) = 0;
/**
* Requests handling a long tap. |aPoint| is in CSS pixels, relative to the
* Requests handling of a tap event. |aPoint| is in CSS pixels, relative to the
* current scroll offset.
*/
virtual void HandleLongTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId) = 0;
virtual void HandleTap(TapType aType,
const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId) = 0;
/**
* Schedules a runnable to run on the controller/UI thread at some time

View File

@ -99,6 +99,7 @@ namespace layers {
typedef mozilla::layers::AllowedTouchBehavior AllowedTouchBehavior;
typedef GeckoContentController::APZStateChange APZStateChange;
typedef GeckoContentController::TapType TapType;
typedef mozilla::gfx::Point Point;
typedef mozilla::gfx::Matrix4x4 Matrix4x4;
using mozilla::gfx::PointTyped;
@ -1995,7 +1996,7 @@ nsEventStatus AsyncPanZoomController::OnLongPress(const TapGestureInput& aEvent)
return nsEventStatus_eIgnore;
}
uint64_t blockId = GetInputQueue()->InjectNewTouchBlock(this);
controller->HandleLongTap(geckoScreenPoint, aEvent.modifiers, GetGuid(), blockId);
controller->HandleTap(TapType::eLongTap, geckoScreenPoint, aEvent.modifiers, GetGuid(), blockId);
return nsEventStatus_eConsumeNoDefault;
}
}
@ -2004,10 +2005,11 @@ nsEventStatus AsyncPanZoomController::OnLongPress(const TapGestureInput& aEvent)
nsEventStatus AsyncPanZoomController::OnLongPressUp(const TapGestureInput& aEvent) {
APZC_LOG("%p got a long-tap-up in state %d\n", this, mState);
return GenerateSingleTap(aEvent.mPoint, aEvent.modifiers);
return GenerateSingleTap(TapType::eLongTapUp, aEvent.mPoint, aEvent.modifiers);
}
nsEventStatus AsyncPanZoomController::GenerateSingleTap(const ScreenIntPoint& aPoint, mozilla::Modifiers aModifiers) {
nsEventStatus AsyncPanZoomController::GenerateSingleTap(TapType aType,
const ScreenIntPoint& aPoint, mozilla::Modifiers aModifiers) {
RefPtr<GeckoContentController> controller = GetGeckoContentController();
if (controller) {
CSSPoint geckoScreenPoint;
@ -2029,16 +2031,17 @@ nsEventStatus AsyncPanZoomController::GenerateSingleTap(const ScreenIntPoint& aP
touch->SetSingleTapOccurred();
}
// Because this may be being running as part of APZCTreeManager::ReceiveInputEvent,
// calling controller->HandleSingleTap directly might mean that content receives
// calling controller->HandleTap directly might mean that content receives
// the single tap message before the corresponding touch-up. To avoid that we
// schedule the singletap message to run on the next spin of the event loop.
// See bug 965381 for the issue this was causing.
RefPtr<Runnable> runnable =
NewRunnableMethod<CSSPoint,
mozilla::Modifiers,
ScrollableLayerGuid>(controller, &GeckoContentController::HandleSingleTap,
geckoScreenPoint, aModifiers,
GetGuid());
NewRunnableMethod<TapType, CSSPoint, mozilla::Modifiers,
ScrollableLayerGuid, uint64_t>(controller,
&GeckoContentController::HandleTap,
aType, geckoScreenPoint,
aModifiers, GetGuid(),
touch ? touch->GetBlockId() : 0);
controller->PostDelayedTask(runnable.forget(), 0);
return nsEventStatus_eConsumeNoDefault;
@ -2059,14 +2062,14 @@ nsEventStatus AsyncPanZoomController::OnSingleTapUp(const TapGestureInput& aEven
// If mZoomConstraints.mAllowDoubleTapZoom is true we wait for a call to OnSingleTapConfirmed before
// sending event to content
if (!(mZoomConstraints.mAllowDoubleTapZoom && CurrentTouchBlock()->TouchActionAllowsDoubleTapZoom())) {
return GenerateSingleTap(aEvent.mPoint, aEvent.modifiers);
return GenerateSingleTap(TapType::eSingleTap, aEvent.mPoint, aEvent.modifiers);
}
return nsEventStatus_eIgnore;
}
nsEventStatus AsyncPanZoomController::OnSingleTapConfirmed(const TapGestureInput& aEvent) {
APZC_LOG("%p got a single-tap-confirmed in state %d\n", this, mState);
return GenerateSingleTap(aEvent.mPoint, aEvent.modifiers);
return GenerateSingleTap(TapType::eSingleTap, aEvent.mPoint, aEvent.modifiers);
}
nsEventStatus AsyncPanZoomController::OnDoubleTap(const TapGestureInput& aEvent) {
@ -2076,7 +2079,8 @@ nsEventStatus AsyncPanZoomController::OnDoubleTap(const TapGestureInput& aEvent)
if (mZoomConstraints.mAllowDoubleTapZoom && CurrentTouchBlock()->TouchActionAllowsDoubleTapZoom()) {
CSSPoint geckoScreenPoint;
if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) {
controller->HandleDoubleTap(geckoScreenPoint, aEvent.modifiers, GetGuid());
controller->HandleTap(TapType::eDoubleTap, geckoScreenPoint,
aEvent.modifiers, GetGuid(), CurrentTouchBlock()->GetBlockId());
}
}
return nsEventStatus_eConsumeNoDefault;

View File

@ -623,8 +623,11 @@ protected:
static AxisLockMode GetAxisLockMode();
// Helper function for OnSingleTapUp() and OnSingleTapConfirmed().
nsEventStatus GenerateSingleTap(const ScreenIntPoint& aPoint, mozilla::Modifiers aModifiers);
// Helper function for OnSingleTapUp(), OnSingleTapConfirmed(), and
// OnLongPressUp().
nsEventStatus GenerateSingleTap(GeckoContentController::TapType aType,
const ScreenIntPoint& aPoint,
mozilla::Modifiers aModifiers);
// Common processing at the end of a touch block.
void OnTouchEndOrCancel();

View File

@ -40,6 +40,7 @@ using ::testing::AtLeast;
using ::testing::AtMost;
using ::testing::MockFunction;
using ::testing::InSequence;
typedef mozilla::layers::GeckoContentController::TapType TapType;
template<class T>
class ScopedGfxPref {
@ -76,9 +77,7 @@ public:
MOCK_METHOD1(RequestContentRepaint, void(const FrameMetrics&));
MOCK_METHOD2(RequestFlingSnap, void(const FrameMetrics::ViewID& aScrollId, const mozilla::CSSPoint& aDestination));
MOCK_METHOD2(AcknowledgeScrollUpdate, void(const FrameMetrics::ViewID&, const uint32_t& aScrollGeneration));
MOCK_METHOD3(HandleDoubleTap, void(const CSSPoint&, Modifiers, const ScrollableLayerGuid&));
MOCK_METHOD3(HandleSingleTap, void(const CSSPoint&, Modifiers, const ScrollableLayerGuid&));
MOCK_METHOD4(HandleLongTap, void(const CSSPoint&, Modifiers, const ScrollableLayerGuid&, uint64_t));
MOCK_METHOD5(HandleTap, void(TapType, const CSSPoint&, Modifiers, const ScrollableLayerGuid&, uint64_t));
// Can't use the macros with already_AddRefed :(
void PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs) {
RefPtr<Runnable> task = aTask;

View File

@ -170,16 +170,16 @@ TEST_F(APZEventRegionsTester, HitRegionImmediateResponse) {
MockFunction<void(std::string checkPointName)> check;
{
InSequence s;
EXPECT_CALL(*mcc, HandleSingleTap(_, _, left->GetGuid())).Times(1);
EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, _, _, left->GetGuid(), _)).Times(1);
EXPECT_CALL(check, Call("Tapped on left"));
EXPECT_CALL(*mcc, HandleSingleTap(_, _, bottom->GetGuid())).Times(1);
EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, _, _, bottom->GetGuid(), _)).Times(1);
EXPECT_CALL(check, Call("Tapped on bottom"));
EXPECT_CALL(*mcc, HandleSingleTap(_, _, root->GetGuid())).Times(1);
EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, _, _, root->GetGuid(), _)).Times(1);
EXPECT_CALL(check, Call("Tapped on root"));
EXPECT_CALL(check, Call("Tap pending on d-t-c region"));
EXPECT_CALL(*mcc, HandleSingleTap(_, _, bottom->GetGuid())).Times(1);
EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, _, _, bottom->GetGuid(), _)).Times(1);
EXPECT_CALL(check, Call("Tapped on bottom again"));
EXPECT_CALL(*mcc, HandleSingleTap(_, _, left->GetGuid())).Times(1);
EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, _, _, left->GetGuid(), _)).Times(1);
EXPECT_CALL(check, Call("Tapped on left this time"));
}
@ -221,7 +221,7 @@ TEST_F(APZEventRegionsTester, HitRegionAccumulatesChildren) {
// parent layer's hit region. Verify that it comes out of the APZC's
// content controller, which indicates the input events got routed correctly
// to the APZC.
EXPECT_CALL(*mcc, HandleSingleTap(_, _, rootApzc->GetGuid())).Times(1);
EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, _, _, rootApzc->GetGuid(), _)).Times(1);
Tap(manager, ScreenIntPoint(10, 160), TimeDuration::FromMilliseconds(100));
}
@ -264,7 +264,7 @@ TEST_F(APZEventRegionsTester, Bug1117712) {
Tap(manager, ScreenIntPoint(55, 5), TimeDuration::FromMilliseconds(100), nullptr, &inputBlockId);
// But now we tell the APZ that really it hit layers[2], and expect the tap
// to be delivered at the correct coordinates.
EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(55, 5), 0, apzc2->GetGuid())).Times(1);
EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, CSSPoint(55, 5), 0, apzc2->GetGuid(), _)).Times(1);
nsTArray<ScrollableLayerGuid> targets;
targets.AppendElement(apzc2->GetGuid());

View File

@ -207,9 +207,9 @@ protected:
AsyncTransform viewTransformOut;
apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut, TimeDuration::FromMilliseconds(timeDelta));
// Deliver a tap to abort the fling. Ensure that we get a HandleSingleTap
// Deliver a tap to abort the fling. Ensure that we get a SingleTap
// call out of it if and only if the fling is slow.
EXPECT_CALL(*mcc, HandleSingleTap(_, 0, apzc->GetGuid())).Times(tapCallsExpected);
EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, _, 0, apzc->GetGuid(), _)).Times(tapCallsExpected);
Tap(apzc, ScreenIntPoint(10, 10), 0);
while (mcc->RunThroughDelayedTasks());
@ -300,7 +300,7 @@ TEST_F(APZCGestureDetectorTester, ShortPress) {
// touchup is fully processed. The ordering here is important.
EXPECT_CALL(check, Call("pre-tap"));
EXPECT_CALL(check, Call("post-tap"));
EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, CSSPoint(10, 10), 0, apzc->GetGuid(), _)).Times(1);
}
check.Call("pre-tap");
@ -320,7 +320,7 @@ TEST_F(APZCGestureDetectorTester, MediumPress) {
// touchup is fully processed. The ordering here is important.
EXPECT_CALL(check, Call("pre-tap"));
EXPECT_CALL(check, Call("post-tap"));
EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, CSSPoint(10, 10), 0, apzc->GetGuid(), _)).Times(1);
}
check.Call("pre-tap");
@ -356,12 +356,12 @@ protected:
EXPECT_CALL(check, Call("preHandleLongTap"));
blockId++;
EXPECT_CALL(*mcc, HandleLongTap(CSSPoint(10, 10), 0, apzc->GetGuid(), blockId)).Times(1);
EXPECT_CALL(*mcc, HandleTap(TapType::eLongTap, CSSPoint(10, 10), 0, apzc->GetGuid(), blockId)).Times(1);
EXPECT_CALL(check, Call("postHandleLongTap"));
EXPECT_CALL(check, Call("preHandleSingleTap"));
EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
EXPECT_CALL(check, Call("postHandleSingleTap"));
EXPECT_CALL(check, Call("preHandleLongTapUp"));
EXPECT_CALL(*mcc, HandleTap(TapType::eLongTapUp, CSSPoint(10, 10), 0, apzc->GetGuid(), _)).Times(1);
EXPECT_CALL(check, Call("postHandleLongTapUp"));
}
// Manually invoke the longpress while the touch is currently down.
@ -379,11 +379,11 @@ protected:
// Finally, simulate lifting the finger. Since the long-press wasn't
// prevent-defaulted, we should get a long-tap-up event.
check.Call("preHandleSingleTap");
check.Call("preHandleLongTapUp");
status = TouchUp(apzc, ScreenIntPoint(10, 10), mcc->Time());
mcc->RunThroughDelayedTasks();
EXPECT_EQ(nsEventStatus_eConsumeDoDefault, status);
check.Call("postHandleSingleTap");
check.Call("postHandleLongTapUp");
apzc->AssertStateIsReset();
}
@ -417,7 +417,7 @@ protected:
EXPECT_CALL(check, Call("preHandleLongTap"));
blockId++;
EXPECT_CALL(*mcc, HandleLongTap(CSSPoint(touchX, touchStartY), 0, apzc->GetGuid(), blockId)).Times(1);
EXPECT_CALL(*mcc, HandleTap(TapType::eLongTap, CSSPoint(touchX, touchStartY), 0, apzc->GetGuid(), blockId)).Times(1);
EXPECT_CALL(check, Call("postHandleLongTap"));
}
@ -439,7 +439,7 @@ protected:
status = apzc->ReceiveInputEvent(mti, nullptr);
EXPECT_EQ(nsEventStatus_eConsumeDoDefault, status);
EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(touchX, touchEndY), 0, apzc->GetGuid())).Times(0);
EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, CSSPoint(touchX, touchEndY), 0, apzc->GetGuid(), _)).Times(0);
status = TouchUp(apzc, ScreenIntPoint(touchX, touchEndY), mcc->Time());
EXPECT_EQ(nsEventStatus_eConsumeDoDefault, status);
@ -482,8 +482,8 @@ TEST_F(APZCGestureDetectorTester, DoubleTap) {
MakeApzcWaitForMainThread();
MakeApzcZoomable();
EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(0);
EXPECT_CALL(*mcc, HandleDoubleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, CSSPoint(10, 10), 0, apzc->GetGuid(), _)).Times(0);
EXPECT_CALL(*mcc, HandleTap(TapType::eDoubleTap, CSSPoint(10, 10), 0, apzc->GetGuid(), _)).Times(1);
uint64_t blockIds[2];
DoubleTapAndCheckStatus(apzc, ScreenIntPoint(10, 10), &blockIds);
@ -499,8 +499,8 @@ TEST_F(APZCGestureDetectorTester, DoubleTapNotZoomable) {
MakeApzcWaitForMainThread();
MakeApzcUnzoomable();
EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(2);
EXPECT_CALL(*mcc, HandleDoubleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(0);
EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, CSSPoint(10, 10), 0, apzc->GetGuid(), _)).Times(2);
EXPECT_CALL(*mcc, HandleTap(TapType::eDoubleTap, CSSPoint(10, 10), 0, apzc->GetGuid(), _)).Times(0);
uint64_t blockIds[2];
DoubleTapAndCheckStatus(apzc, ScreenIntPoint(10, 10), &blockIds);
@ -516,8 +516,8 @@ TEST_F(APZCGestureDetectorTester, DoubleTapPreventDefaultFirstOnly) {
MakeApzcWaitForMainThread();
MakeApzcZoomable();
EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
EXPECT_CALL(*mcc, HandleDoubleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(0);
EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, CSSPoint(10, 10), 0, apzc->GetGuid(), _)).Times(1);
EXPECT_CALL(*mcc, HandleTap(TapType::eDoubleTap, CSSPoint(10, 10), 0, apzc->GetGuid(), _)).Times(0);
uint64_t blockIds[2];
DoubleTapAndCheckStatus(apzc, ScreenIntPoint(10, 10), &blockIds);
@ -533,8 +533,8 @@ TEST_F(APZCGestureDetectorTester, DoubleTapPreventDefaultBoth) {
MakeApzcWaitForMainThread();
MakeApzcZoomable();
EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(0);
EXPECT_CALL(*mcc, HandleDoubleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(0);
EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, CSSPoint(10, 10), 0, apzc->GetGuid(), _)).Times(0);
EXPECT_CALL(*mcc, HandleTap(TapType::eDoubleTap, CSSPoint(10, 10), 0, apzc->GetGuid(), _)).Times(0);
uint64_t blockIds[2];
DoubleTapAndCheckStatus(apzc, ScreenIntPoint(10, 10), &blockIds);
@ -551,7 +551,7 @@ TEST_F(APZCGestureDetectorTester, DoubleTapPreventDefaultBoth) {
TEST_F(APZCGestureDetectorTester, TapFollowedByPinch) {
MakeApzcZoomable();
EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, CSSPoint(10, 10), 0, apzc->GetGuid(), _)).Times(1);
Tap(apzc, ScreenIntPoint(10, 10), TimeDuration::FromMilliseconds(100));
@ -573,7 +573,7 @@ TEST_F(APZCGestureDetectorTester, TapFollowedByPinch) {
TEST_F(APZCGestureDetectorTester, TapFollowedByMultipleTouches) {
MakeApzcZoomable();
EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, CSSPoint(10, 10), 0, apzc->GetGuid(), _)).Times(1);
Tap(apzc, ScreenIntPoint(10, 10), TimeDuration::FromMilliseconds(100));
@ -600,7 +600,7 @@ TEST_F(APZCGestureDetectorTester, LongPressInterruptedByWheel) {
// Since the wheel block interrupted the long-press, we don't expect
// any long-press notifications. However, this also shouldn't crash, which
// is what it used to do.
EXPECT_CALL(*mcc, HandleLongTap(_, _, _, _)).Times(0);
EXPECT_CALL(*mcc, HandleTap(TapType::eLongTap, _, _, _, _)).Times(0);
uint64_t touchBlockId = 0;
uint64_t wheelBlockId = 0;
@ -615,7 +615,7 @@ TEST_F(APZCGestureDetectorTester, TapTimeoutInterruptedByWheel) {
// In this test, even though the wheel block comes right after the tap, the
// tap should still be dispatched because it completes fully before the wheel
// block arrived.
EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, CSSPoint(10, 10), 0, apzc->GetGuid(), _)).Times(1);
// We make the APZC zoomable so the gesture detector needs to wait to
// distinguish between tap and double-tap. During that timeout is when we

View File

@ -509,9 +509,9 @@ TEST_F(APZHitTestingTester, Bug1148350) {
MockFunction<void(std::string checkPointName)> check;
{
InSequence s;
EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(100, 100), 0, ApzcOf(layers[1])->GetGuid())).Times(1);
EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, CSSPoint(100, 100), 0, ApzcOf(layers[1])->GetGuid(), _)).Times(1);
EXPECT_CALL(check, Call("Tapped without transform"));
EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(100, 100), 0, ApzcOf(layers[1])->GetGuid())).Times(1);
EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, CSSPoint(100, 100), 0, ApzcOf(layers[1])->GetGuid(), _)).Times(1);
EXPECT_CALL(check, Call("Tapped with interleaved transform"));
}

View File

@ -91,7 +91,7 @@ TEST_F(APZCTreeManagerTester, Bug1194876) {
// We want to ensure that ApzcOf(layers[0]) has had its state cleared, because
// otherwise it will do things like dispatch spurious long-tap events.
EXPECT_CALL(*mcc, HandleLongTap(_, _, _, _)).Times(0);
EXPECT_CALL(*mcc, HandleTap(TapType::eLongTap, _, _, _, _)).Times(0);
}
TEST_F(APZCTreeManagerTester, Bug1198900) {

View File

@ -263,6 +263,13 @@ APZEventState::ProcessLongTap(const nsCOMPtr<nsIPresShell>& aPresShell,
}
}
void
APZEventState::ProcessLongTapUp()
{
nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
observerService->NotifyObservers(nullptr, "APZ:LongTapUp", nullptr);
}
void
APZEventState::ProcessTouchEvent(const WidgetTouchEvent& aEvent,
const ScrollableLayerGuid& aGuid,

View File

@ -54,6 +54,7 @@ public:
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId);
void ProcessLongTapUp();
void ProcessTouchEvent(const WidgetTouchEvent& aEvent,
const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId,

View File

@ -118,15 +118,7 @@ ChromeProcessController::HandleDoubleTap(const mozilla::CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid)
{
if (MessageLoop::current() != mUILoop) {
mUILoop->PostTask(NewRunnableMethod
<CSSPoint,
Modifiers,
ScrollableLayerGuid>(this,
&ChromeProcessController::HandleDoubleTap,
aPoint, aModifiers, aGuid));
return;
}
MOZ_ASSERT(MessageLoop::current() == mUILoop);
nsCOMPtr<nsIDocument> document = GetRootContentDocument(aGuid.mScrollId);
if (!document.get()) {
@ -154,40 +146,39 @@ ChromeProcessController::HandleDoubleTap(const mozilla::CSSPoint& aPoint,
}
void
ChromeProcessController::HandleSingleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid)
ChromeProcessController::HandleTap(TapType aType,
const mozilla::CSSPoint& aPoint, Modifiers aModifiers,
const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId)
{
if (MessageLoop::current() != mUILoop) {
mUILoop->PostTask(NewRunnableMethod
<CSSPoint,
Modifiers,
ScrollableLayerGuid>(this,
&ChromeProcessController::HandleSingleTap,
aPoint, aModifiers, aGuid));
mUILoop->PostTask(NewRunnableMethod<TapType, mozilla::CSSPoint, Modifiers,
ScrollableLayerGuid, uint64_t>(this,
&ChromeProcessController::HandleTap,
aType, aPoint, aModifiers, aGuid, aInputBlockId));
return;
}
mAPZEventState->ProcessSingleTap(aPoint, aModifiers, aGuid);
}
void
ChromeProcessController::HandleLongTap(const mozilla::CSSPoint& aPoint, Modifiers aModifiers,
const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId)
{
if (MessageLoop::current() != mUILoop) {
mUILoop->PostTask(NewRunnableMethod
<mozilla::CSSPoint,
Modifiers,
ScrollableLayerGuid,
uint64_t>(this, &ChromeProcessController::HandleLongTap,
aPoint, aModifiers, aGuid, aInputBlockId));
return;
switch (aType) {
case TapType::eSingleTap:
mAPZEventState->ProcessSingleTap(aPoint, aModifiers, aGuid);
break;
case TapType::eDoubleTap:
HandleDoubleTap(aPoint, aModifiers, aGuid);
break;
case TapType::eLongTap:
mAPZEventState->ProcessLongTap(GetPresShell(), aPoint, aModifiers, aGuid,
aInputBlockId);
break;
case TapType::eLongTapUp:
mAPZEventState->ProcessLongTapUp();
break;
case TapType::eSentinel:
// Should never happen, but we need to handle this case branch for the
// compiler to be happy.
MOZ_ASSERT(false);
break;
}
mAPZEventState->ProcessLongTap(GetPresShell(), aPoint, aModifiers, aGuid,
aInputBlockId);
}
void

View File

@ -40,13 +40,10 @@ public:
// GeckoContentController interface
virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) override;
virtual void PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs) override;
virtual void HandleDoubleTap(const mozilla::CSSPoint& aPoint, Modifiers aModifiers,
const ScrollableLayerGuid& aGuid) override;
virtual void HandleSingleTap(const mozilla::CSSPoint& aPoint, Modifiers aModifiers,
const ScrollableLayerGuid& aGuid) override;
virtual void HandleLongTap(const mozilla::CSSPoint& aPoint, Modifiers aModifiers,
const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId) override;
virtual void HandleTap(TapType aType,
const mozilla::CSSPoint& aPoint, Modifiers aModifiers,
const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId) override;
virtual void NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
APZStateChange aChange,
int aArg) override;
@ -63,6 +60,8 @@ private:
nsIPresShell* GetPresShell() const;
nsIDocument* GetRootDocument() const;
nsIDocument* GetRootContentDocument(const FrameMetrics::ViewID& aScrollId) const;
void HandleDoubleTap(const mozilla::CSSPoint& aPoint, Modifiers aModifiers,
const ScrollableLayerGuid& aGuid);
};
} // namespace layers

View File

@ -76,26 +76,24 @@ ClipToContain(gfxContext* aContext, const IntRect& aRect)
return aContext->DeviceToUser(deviceRect).IsEqualInterior(userRect);
}
BasicLayerManager::PushedGroup
BasicLayerManager::PushGroupForLayer(gfxContext* aContext, Layer* aLayer, const nsIntRegion& aRegion)
bool
BasicLayerManager::PushGroupForLayer(gfxContext* aContext, Layer* aLayer, const nsIntRegion& aRegion, PushedGroup& aGroupResult)
{
PushedGroup group;
group.mVisibleRegion = aRegion;
group.mFinalTarget = aContext;
group.mOperator = GetEffectiveOperator(aLayer);
group.mOpacity = aLayer->GetEffectiveOpacity();
aGroupResult.mVisibleRegion = aRegion;
aGroupResult.mFinalTarget = aContext;
aGroupResult.mOperator = GetEffectiveOperator(aLayer);
aGroupResult.mOpacity = aLayer->GetEffectiveOpacity();
// If we need to call PushGroup, we should clip to the smallest possible
// area first to minimize the size of the temporary surface.
bool didCompleteClip = ClipToContain(aContext, aRegion.GetBounds());
bool canPushGroup = group.mOperator == CompositionOp::OP_OVER ||
(group.mOperator == CompositionOp::OP_SOURCE && (aLayer->CanUseOpaqueSurface() || aLayer->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA));
bool canPushGroup = aGroupResult.mOperator == CompositionOp::OP_OVER ||
(aGroupResult.mOperator == CompositionOp::OP_SOURCE && (aLayer->CanUseOpaqueSurface() || aLayer->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA));
if (!canPushGroup) {
aContext->Save();
gfxUtils::ClipToRegion(group.mFinalTarget, group.mVisibleRegion);
gfxUtils::ClipToRegion(aGroupResult.mFinalTarget, aGroupResult.mVisibleRegion);
// PushGroup/PopGroup do not support non operator over.
gfxMatrix oldMat = aContext->CurrentMatrix();
@ -112,16 +110,16 @@ BasicLayerManager::PushGroupForLayer(gfxContext* aContext, Layer* aLayer, const
RefPtr<gfxContext> ctx =
gfxContext::CreateOrNull(dt, ToRect(rect).TopLeft());
if (!ctx) {
gfxDevCrash(LogReason::InvalidContext) << "BasicLayerManager context problem " << gfx::hexa(dt);
return group;
gfxCriticalNote << "BasicLayerManager context problem in PushGroupForLayer " << gfx::hexa(dt);
return false;
}
ctx->SetMatrix(oldMat);
group.mGroupOffset = surfRect.TopLeft();
group.mGroupTarget = ctx;
aGroupResult.mGroupOffset = surfRect.TopLeft();
aGroupResult.mGroupTarget = ctx;
group.mMaskSurface = GetMaskForLayer(aLayer, &group.mMaskTransform);
return group;
aGroupResult.mMaskSurface = GetMaskForLayer(aLayer, &aGroupResult.mMaskTransform);
return true;
}
aContext->Restore();
}
@ -134,7 +132,7 @@ BasicLayerManager::PushGroupForLayer(gfxContext* aContext, Layer* aLayer, const
// destination. Since the User->Device space transform will be applied
// to the mask by PopGroupAndBlend we need to adjust the transform to
// transform the mask to user space.
Matrix currentTransform = ToMatrix(group.mFinalTarget->CurrentMatrix());
Matrix currentTransform = ToMatrix(aGroupResult.mFinalTarget->CurrentMatrix());
currentTransform.Invert();
maskTransform = maskTransform * currentTransform;
}
@ -146,23 +144,24 @@ BasicLayerManager::PushGroupForLayer(gfxContext* aContext, Layer* aLayer, const
// group. We need to make sure that only pixels inside the layer's visible
// region are copied back to the destination. Remember if we've already
// clipped precisely to the visible region.
group.mNeedsClipToVisibleRegion = !didCompleteClip || aRegion.GetNumRects() > 1;
if (group.mNeedsClipToVisibleRegion) {
group.mFinalTarget->Save();
gfxUtils::ClipToRegion(group.mFinalTarget, group.mVisibleRegion);
aGroupResult.mNeedsClipToVisibleRegion = !didCompleteClip || aRegion.GetNumRects() > 1;
if (aGroupResult.mNeedsClipToVisibleRegion) {
aGroupResult.mFinalTarget->Save();
gfxUtils::ClipToRegion(aGroupResult.mFinalTarget, aGroupResult.mVisibleRegion);
}
aContext->PushGroupForBlendBack(gfxContentType::COLOR, group.mOpacity, maskSurf, maskTransform);
aContext->PushGroupForBlendBack(gfxContentType::COLOR, aGroupResult.mOpacity, maskSurf, maskTransform);
} else {
if (aLayer->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA) {
aContext->PushGroupAndCopyBackground(gfxContentType::COLOR_ALPHA, group.mOpacity, maskSurf, maskTransform);
aContext->PushGroupAndCopyBackground(gfxContentType::COLOR_ALPHA, aGroupResult.mOpacity, maskSurf, maskTransform);
} else {
aContext->PushGroupForBlendBack(gfxContentType::COLOR_ALPHA, group.mOpacity, maskSurf, maskTransform);
aContext->PushGroupForBlendBack(gfxContentType::COLOR_ALPHA, aGroupResult.mOpacity, maskSurf, maskTransform);
}
}
group.mGroupTarget = group.mFinalTarget;
return group;
aGroupResult.mGroupTarget = aGroupResult.mFinalTarget;
return true;
}
void
@ -902,10 +901,11 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
if (is2D) {
if (needsGroup) {
PushedGroup pushedGroup =
PushGroupForLayer(aTarget, aLayer, aLayer->GetLocalVisibleRegion().ToUnknownRegion());
PaintSelfOrChildren(paintLayerContext, pushedGroup.mGroupTarget);
PopGroupForLayer(pushedGroup);
PushedGroup pushedGroup;
if (PushGroupForLayer(aTarget, aLayer, aLayer->GetLocalVisibleRegion().ToUnknownRegion(), pushedGroup)) {
PaintSelfOrChildren(paintLayerContext, pushedGroup.mGroupTarget);
PopGroupForLayer(pushedGroup);
}
} else {
PaintSelfOrChildren(paintLayerContext, aTarget);
}

View File

@ -151,7 +151,10 @@ public:
gfx::Matrix mMaskTransform;
};
PushedGroup PushGroupForLayer(gfxContext* aContext, Layer* aLayerContext, const nsIntRegion& aRegion);
// Construct a PushedGroup for a specific layer.
// Return false if it has some errors in PushGroupForLayer(). Then, the
// "aGroupResult" is unavailable for future using.
bool PushGroupForLayer(gfxContext* aContext, Layer* aLayerContext, const nsIntRegion& aRegion, PushedGroup& aGroupResult);
void PopGroupForLayer(PushedGroup& aGroup);

View File

@ -77,19 +77,25 @@ BasicPaintedLayer::PaintThebes(gfxContext* aContext,
bool needsGroup = opacity != 1.0 ||
effectiveOperator != CompositionOp::OP_OVER ||
aMaskLayer;
RefPtr<gfxContext> groupContext;
RefPtr<gfxContext> context = nullptr;
BasicLayerManager::PushedGroup group;
bool availableGroup = false;
if (needsGroup) {
group =
BasicManager()->PushGroupForLayer(aContext, this, toDraw);
groupContext = group.mGroupTarget;
availableGroup =
BasicManager()->PushGroupForLayer(aContext, this, toDraw, group);
if (availableGroup) {
context = group.mGroupTarget;
}
} else {
groupContext = aContext;
context = aContext;
}
SetAntialiasingFlags(this, groupContext->GetDrawTarget());
aCallback(this, groupContext, toDraw, toDraw,
DrawRegionClip::NONE, nsIntRegion(), aCallbackData);
if (needsGroup) {
if (context) {
SetAntialiasingFlags(this, context->GetDrawTarget());
aCallback(this, context, toDraw, toDraw, DrawRegionClip::NONE,
nsIntRegion(), aCallbackData);
}
if (needsGroup && availableGroup) {
BasicManager()->PopGroupForLayer(group);
}

View File

@ -100,32 +100,15 @@ APZChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics)
}
bool
APZChild::RecvHandleDoubleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid)
APZChild::RecvHandleTap(const TapType& aType,
const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId,
const bool& aCallTakeFocusForClickFromTap)
{
mBrowser->HandleDoubleTap(aPoint, aModifiers, aGuid);
return true;
}
bool
APZChild::RecvHandleSingleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid,
const bool& aCallTakeFocusForClickFromTap)
{
mBrowser->HandleSingleTap(aPoint, aModifiers, aGuid,
aCallTakeFocusForClickFromTap);
return true;
}
bool
APZChild::RecvHandleLongTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId)
{
mBrowser->HandleLongTap(aPoint, aModifiers, aGuid, aInputBlockId);
mBrowser->HandleTap(aType, aPoint, aModifiers, aGuid,
aInputBlockId, aCallTakeFocusForClickFromTap);
return true;
}

View File

@ -28,19 +28,12 @@ public:
virtual bool RecvUpdateFrame(const FrameMetrics& frame) override;
virtual bool RecvHandleDoubleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid) override;
virtual bool RecvHandleSingleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid,
const bool& aCallTakeFocusForClickFromTap) override;
virtual bool RecvHandleLongTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId) override;
virtual bool RecvHandleTap(const TapType& aType,
const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId,
const bool& aCallTakeFocusForClickFromTap) override;
virtual bool RecvNotifyAPZStateChange(const ViewID& aViewId,
const APZStateChange& aChange,

View File

@ -16,6 +16,7 @@ using struct mozilla::layers::ScrollableLayerGuid from "FrameMetrics.h";
using mozilla::layers::FrameMetrics::ViewID from "FrameMetrics.h";
using mozilla::layers::MaybeZoomConstraints from "FrameMetrics.h";
using mozilla::layers::TouchBehaviorFlags from "mozilla/layers/APZUtils.h";
using mozilla::layers::GeckoContentController::TapType from "mozilla/layers/GeckoContentController.h";
using mozilla::layers::GeckoContentController::APZStateChange from "mozilla/layers/GeckoContentController.h";
using mozilla::dom::TabId from "mozilla/dom/ipc/IdType.h";
using mozilla::dom::ContentParentId from "mozilla/dom/ipc/IdType.h";
@ -91,9 +92,12 @@ child:
// The following methods correspond to functions on the GeckoContentController
// interface in gfx/layers/apz/public/GeckoContentController.h. Refer to documentation
// in that file for these functions.
async HandleDoubleTap(CSSPoint aPoint, Modifiers aModifiers, ScrollableLayerGuid aGuid);
async HandleSingleTap(CSSPoint aPoint, Modifiers aModifiers, ScrollableLayerGuid aGuid, bool aCallTakeFocusForClickFromTap);
async HandleLongTap(CSSPoint point, Modifiers aModifiers, ScrollableLayerGuid aGuid, uint64_t aInputBlockId);
// The aCallTakeFocusForClickFromTap argument is used for eSingleTap types,
// to request that the child take focus before dispatching the mouse events
// for the tap (otherwise the resulting focus behaviour is incorrect).
async HandleTap(TapType aType, CSSPoint point, Modifiers aModifiers,
ScrollableLayerGuid aGuid, uint64_t aInputBlockId,
bool aCallTakeFocusForClickFromTap);
async NotifyAPZStateChange(ViewID aViewId, APZStateChange aChange, int aArg);
async NotifyFlushComplete();

View File

@ -53,80 +53,37 @@ RemoteContentController::RequestContentRepaint(const FrameMetrics& aFrameMetrics
}
void
RemoteContentController::HandleDoubleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid)
RemoteContentController::HandleTap(TapType aTapType,
const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId)
{
if (MessageLoop::current() != mUILoop) {
// We have to send this message from the "UI thread" (main
// thread).
mUILoop->PostTask(NewRunnableMethod<CSSPoint,
Modifiers,
ScrollableLayerGuid>(this,
&RemoteContentController::HandleDoubleTap,
aPoint, aModifiers, aGuid));
return;
}
if (CanSend()) {
Unused << SendHandleDoubleTap(mBrowserParent->AdjustTapToChildWidget(aPoint),
aModifiers, aGuid);
}
}
void
RemoteContentController::HandleSingleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid)
{
if (MessageLoop::current() != mUILoop) {
// We have to send this message from the "UI thread" (main
// thread).
mUILoop->PostTask(NewRunnableMethod<CSSPoint,
Modifiers,
ScrollableLayerGuid>(this,
&RemoteContentController::HandleSingleTap,
aPoint, aModifiers, aGuid));
mUILoop->PostTask(NewRunnableMethod<TapType, CSSPoint, Modifiers,
ScrollableLayerGuid, uint64_t>(this,
&RemoteContentController::HandleTap,
aTapType, aPoint, aModifiers, aGuid,
aInputBlockId));
return;
}
bool callTakeFocusForClickFromTap;
layout::RenderFrameParent* frame;
if (mBrowserParent && (frame = mBrowserParent->GetRenderFrame()) &&
mLayersId == frame->GetLayersId()) {
// Avoid going over IPC and back for calling TakeFocusForClickFromTap,
// since the right RenderFrameParent is living in this process.
frame->TakeFocusForClickFromTap();
callTakeFocusForClickFromTap = false;
} else {
callTakeFocusForClickFromTap = true;
bool callTakeFocusForClickFromTap = (aTapType == TapType::eSingleTap);
if (callTakeFocusForClickFromTap && mBrowserParent) {
layout::RenderFrameParent* frame = mBrowserParent->GetRenderFrame();
if (frame && mLayersId == frame->GetLayersId()) {
// Avoid going over IPC and back for calling TakeFocusForClickFromTap,
// since the right RenderFrameParent is living in this process.
frame->TakeFocusForClickFromTap();
callTakeFocusForClickFromTap = false;
}
}
if (CanSend()) {
Unused << SendHandleSingleTap(mBrowserParent->AdjustTapToChildWidget(aPoint),
aModifiers, aGuid, callTakeFocusForClickFromTap);
}
}
void
RemoteContentController::HandleLongTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId)
{
if (MessageLoop::current() != mUILoop) {
// We have to send this message from the "UI thread" (main
// thread).
mUILoop->PostTask(NewRunnableMethod<CSSPoint,
Modifiers,
ScrollableLayerGuid,
uint64_t>(this,
&RemoteContentController::HandleLongTap,
aPoint, aModifiers, aGuid, aInputBlockId));
return;
}
if (CanSend()) {
Unused << SendHandleLongTap(mBrowserParent->AdjustTapToChildWidget(aPoint),
aModifiers, aGuid, aInputBlockId);
Unused << SendHandleTap(aTapType, mBrowserParent->AdjustTapToChildWidget(aPoint),
aModifiers, aGuid, aInputBlockId, callTakeFocusForClickFromTap);
}
}

View File

@ -31,6 +31,7 @@ class APZCTreeManager;
class RemoteContentController : public GeckoContentController
, public PAPZParent
{
using GeckoContentController::TapType;
using GeckoContentController::APZStateChange;
public:
@ -42,18 +43,11 @@ public:
// Needs to be called on the main thread.
virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) override;
virtual void HandleDoubleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid) override;
virtual void HandleSingleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid) override;
virtual void HandleLongTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId) override;
virtual void HandleTap(TapType aTapType,
const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId) override;
virtual void PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs) override;

View File

@ -34,7 +34,8 @@ JavaScriptChild::JavaScriptChild(JSRuntime* rt)
JavaScriptChild::~JavaScriptChild()
{
JS_RemoveWeakPointerZoneGroupCallback(rt_, UpdateChildWeakPointersBeforeSweepingZoneGroup);
JSContext* cx = JS_GetContext(rt_);
JS_RemoveWeakPointerZoneGroupCallback(cx, UpdateChildWeakPointersBeforeSweepingZoneGroup);
}
bool
@ -45,7 +46,8 @@ JavaScriptChild::init()
if (!WrapperAnswer::init())
return false;
JS_AddWeakPointerZoneGroupCallback(rt_, UpdateChildWeakPointersBeforeSweepingZoneGroup, this);
JSContext* cx = JS_GetContext(rt_);
JS_AddWeakPointerZoneGroupCallback(cx, UpdateChildWeakPointersBeforeSweepingZoneGroup, this);
return true;
}

View File

@ -38,7 +38,7 @@ JavaScriptParent::JavaScriptParent(JSRuntime* rt)
JavaScriptParent::~JavaScriptParent()
{
JS_RemoveExtraGCRootsTracer(rt_, TraceParent, this);
JS_RemoveExtraGCRootsTracer(JS_GetContext(rt_), TraceParent, this);
}
bool
@ -47,7 +47,7 @@ JavaScriptParent::init()
if (!WrapperOwner::init())
return false;
JS_AddExtraGCRootsTracer(rt_, TraceParent, this);
JS_AddExtraGCRootsTracer(JS_GetContext(rt_), TraceParent, this);
return true;
}

View File

@ -55,7 +55,7 @@ extern JS_PUBLIC_API(void)
JS_HoldPrincipals(JSPrincipals* principals);
extern JS_PUBLIC_API(void)
JS_DropPrincipals(JSRuntime* rt, JSPrincipals* principals);
JS_DropPrincipals(JSContext* cx, JSPrincipals* principals);
// Return whether the first principal subsumes the second. The exact meaning of
// 'subsumes' is left up to the browser. Subsumption is checked inside the JS
@ -76,10 +76,10 @@ struct JSSecurityCallbacks {
};
extern JS_PUBLIC_API(void)
JS_SetSecurityCallbacks(JSRuntime* rt, const JSSecurityCallbacks* callbacks);
JS_SetSecurityCallbacks(JSContext* cx, const JSSecurityCallbacks* callbacks);
extern JS_PUBLIC_API(const JSSecurityCallbacks*)
JS_GetSecurityCallbacks(JSRuntime* rt);
JS_GetSecurityCallbacks(JSContext* cx);
/*
* Code running with "trusted" principals will be given a deeper stack
@ -87,14 +87,14 @@ JS_GetSecurityCallbacks(JSRuntime* rt);
* untrusted script has exhausted the stack. This function sets the
* runtime-wide trusted principal.
*
* This principals is not held (via JS_HoldPrincipals/JS_DropPrincipals) since
* there is no available JSContext. Instead, the caller must ensure that the
* given principals stays valid for as long as 'rt' may point to it. If the
* principals would be destroyed before 'rt', JS_SetTrustedPrincipals must be
* called again, passing nullptr for 'prin'.
* This principals is not held (via JS_HoldPrincipals/JS_DropPrincipals).
* Instead, the caller must ensure that the given principals stays valid for as
* long as 'cx' may point to it. If the principals would be destroyed before
* 'cx', JS_SetTrustedPrincipals must be called again, passing nullptr for
* 'prin'.
*/
extern JS_PUBLIC_API(void)
JS_SetTrustedPrincipals(JSRuntime* rt, JSPrincipals* prin);
JS_SetTrustedPrincipals(JSContext* cx, JSPrincipals* prin);
typedef void
(* JSDestroyPrincipalsOp)(JSPrincipals* principals);
@ -105,7 +105,7 @@ typedef void
* only once per JS runtime.
*/
extern JS_PUBLIC_API(void)
JS_InitDestroyPrincipalsCallback(JSRuntime* rt, JSDestroyPrincipalsOp destroyPrincipals);
JS_InitDestroyPrincipalsCallback(JSContext* cx, JSDestroyPrincipalsOp destroyPrincipals);
/*
* Read a JSPrincipals instance from the given |reader| and initialize the out
@ -126,7 +126,7 @@ using JSReadPrincipalsOp = bool (*)(JSContext* cx, JSStructuredCloneReader* read
* buffer. The initialization can be done only once per JS runtime.
*/
extern JS_PUBLIC_API(void)
JS_InitReadPrincipalsCallback(JSRuntime* rt, JSReadPrincipalsOp read);
JS_InitReadPrincipalsCallback(JSContext* cx, JSReadPrincipalsOp read);
#endif /* js_Principals_h */

View File

@ -722,36 +722,46 @@ FreezeObjectProperty(JSContext* cx, HandleNativeObject obj, uint32_t slot)
}
/* static */ bool
ModuleObject::FreezeArrayProperties(JSContext* cx, HandleModuleObject self)
ModuleObject::Freeze(JSContext* cx, HandleModuleObject self)
{
return FreezeObjectProperty(cx, self, RequestedModulesSlot) &&
FreezeObjectProperty(cx, self, ImportEntriesSlot) &&
FreezeObjectProperty(cx, self, LocalExportEntriesSlot) &&
FreezeObjectProperty(cx, self, IndirectExportEntriesSlot) &&
FreezeObjectProperty(cx, self, StarExportEntriesSlot);
FreezeObjectProperty(cx, self, StarExportEntriesSlot) &&
FreezeObject(cx, self);
}
static inline void
AssertObjectPropertyFrozen(JSContext* cx, HandleNativeObject obj, uint32_t slot)
{
#ifdef DEBUG
static inline bool
IsObjectFrozen(JSContext* cx, HandleObject obj)
{
bool frozen = false;
RootedObject property(cx, &obj->getSlot(slot).toObject());
MOZ_ALWAYS_TRUE(TestIntegrityLevel(cx, property, IntegrityLevel::Frozen, &frozen));
MOZ_ASSERT(frozen);
#endif
MOZ_ALWAYS_TRUE(TestIntegrityLevel(cx, obj, IntegrityLevel::Frozen, &frozen));
return frozen;
}
/* static */ inline void
ModuleObject::AssertArrayPropertiesFrozen(JSContext* cx, HandleModuleObject self)
static inline bool
IsObjectPropertyFrozen(JSContext* cx, HandleNativeObject obj, uint32_t slot)
{
AssertObjectPropertyFrozen(cx, self, RequestedModulesSlot);
AssertObjectPropertyFrozen(cx, self, ImportEntriesSlot);
AssertObjectPropertyFrozen(cx, self, LocalExportEntriesSlot);
AssertObjectPropertyFrozen(cx, self, IndirectExportEntriesSlot);
AssertObjectPropertyFrozen(cx, self, StarExportEntriesSlot);
RootedObject property(cx, &obj->getSlot(slot).toObject());
return IsObjectFrozen(cx, property);
}
/* static */ inline bool
ModuleObject::IsFrozen(JSContext* cx, HandleModuleObject self)
{
return IsObjectPropertyFrozen(cx, self, RequestedModulesSlot) &&
IsObjectPropertyFrozen(cx, self, ImportEntriesSlot) &&
IsObjectPropertyFrozen(cx, self, LocalExportEntriesSlot) &&
IsObjectPropertyFrozen(cx, self, IndirectExportEntriesSlot) &&
IsObjectPropertyFrozen(cx, self, StarExportEntriesSlot) &&
IsObjectFrozen(cx, self);
}
#endif
inline static void
AssertModuleScopesMatch(ModuleObject* module)
{
@ -858,7 +868,7 @@ ModuleObject::noteFunctionDeclaration(ExclusiveContext* cx, HandleAtom name, Han
/* static */ bool
ModuleObject::instantiateFunctionDeclarations(JSContext* cx, HandleModuleObject self)
{
AssertArrayPropertiesFrozen(cx, self);
MOZ_ASSERT(IsFrozen(cx, self));
FunctionDeclarationVector* funDecls = self->functionDeclarations();
if (!funDecls) {
@ -896,7 +906,7 @@ ModuleObject::setEvaluated()
/* static */ bool
ModuleObject::evaluate(JSContext* cx, HandleModuleObject self, MutableHandleValue rval)
{
AssertArrayPropertiesFrozen(cx, self);
MOZ_ASSERT(IsFrozen(cx, self));
RootedScript script(cx, self->script());
RootedModuleEnvironmentObject scope(cx, self->environment());

View File

@ -236,8 +236,10 @@ class ModuleObject : public NativeObject
HandleArrayObject localExportEntries,
HandleArrayObject indiretExportEntries,
HandleArrayObject starExportEntries);
static bool FreezeArrayProperties(JSContext* cx, HandleModuleObject self);
static void AssertArrayPropertiesFrozen(JSContext* cx, HandleModuleObject self);
static bool Freeze(JSContext* cx, HandleModuleObject self);
#ifdef DEBUG
static bool IsFrozen(JSContext* cx, HandleModuleObject self);
#endif
void fixScopesAfterCompartmentMerge(JSContext* cx);
JSScript* script() const;

View File

@ -3349,13 +3349,13 @@ SetGCCallback(JSContext* cx, unsigned argc, Value* vp)
}
if (gcCallback::prevMajorGC) {
JS_SetGCCallback(cx->runtime(), nullptr, nullptr);
JS_SetGCCallback(cx, nullptr, nullptr);
js_delete<gcCallback::MajorGC>(gcCallback::prevMajorGC);
gcCallback::prevMajorGC = nullptr;
}
if (gcCallback::prevMinorGC) {
JS_SetGCCallback(cx->runtime(), nullptr, nullptr);
JS_SetGCCallback(cx, nullptr, nullptr);
js_delete<gcCallback::MinorGC>(gcCallback::prevMinorGC);
gcCallback::prevMinorGC = nullptr;
}
@ -3369,7 +3369,7 @@ SetGCCallback(JSContext* cx, unsigned argc, Value* vp)
info->phases = phases;
info->active = true;
JS_SetGCCallback(cx->runtime(), gcCallback::minorGC, info);
JS_SetGCCallback(cx, gcCallback::minorGC, info);
} else if (strcmp(action.ptr(), "majorGC") == 0) {
if (!JS_GetProperty(cx, opts, "depth", &v))
return false;
@ -3391,7 +3391,7 @@ SetGCCallback(JSContext* cx, unsigned argc, Value* vp)
info->phases = phases;
info->depth = depth;
JS_SetGCCallback(cx->runtime(), gcCallback::majorGC, info);
JS_SetGCCallback(cx, gcCallback::majorGC, info);
} else {
JS_ReportError(cx, "Unknown GC callback action");
return false;

View File

@ -102,6 +102,7 @@ LifoAlloc::getOrCreateChunk(size_t n)
}
// If we get here, we couldn't find an existing BumpChunk to fill the request.
MOZ_ASSERT(fallibleScope_, "[OOM] Cannot allocate a new chunk in an infallible scope.");
BumpChunk* newChunk = BumpChunk::new_(chunkSize);
if (!newChunk)
return nullptr;

View File

@ -801,7 +801,7 @@ frontend::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
// This happens in GlobalHelperThreadState::finishModuleParseTask() when a
// module is compiled off main thread.
if (!ModuleObject::FreezeArrayProperties(cx->asJSContext(), module))
if (!ModuleObject::Freeze(cx->asJSContext(), module))
return nullptr;
return module;

View File

@ -68,10 +68,11 @@ main(int argc, const char** argv)
{
if (!JS_Init()) return 1;
JSRuntime* runtime = checkPtr(JS_NewRuntime(1024 * 1024));
JS_SetGCParameter(runtime, JSGC_MAX_BYTES, 0xffffffff);
JS_SetNativeStackQuota(runtime, 5000000);
JSContext* cx = JS_GetContext(runtime);
JS_SetGCParameter(cx, JSGC_MAX_BYTES, 0xffffffff);
JS_SetNativeStackQuota(cx, 5000000);
checkBool(JS::InitSelfHostedCode(cx));
JS::SetWarningReporter(cx, reportWarning);

View File

@ -0,0 +1,10 @@
// |jit-test| error: TypeError
let moduleRepo = {};
setModuleResolveHook(function(module, specifier) {
return moduleRepo[specifier];
});
let a = moduleRepo['a'] = parseModule("var x = 1; export { x };");
let b = moduleRepo['b'] = parseModule("import { x as y } from 'a';");
a.__proto__ = {15: 1337};
b.declarationInstantiation();

View File

@ -184,7 +184,7 @@ CompileRuntime::isInsideNursery(gc::Cell* cell)
const DOMCallbacks*
CompileRuntime::DOMcallbacks()
{
return GetDOMCallbacks(runtime());
return runtime()->DOMcallbacks;
}
const Nursery&

View File

@ -54,7 +54,7 @@ static const JSWrapObjectCallbacks WrapObjectCallbacks = {
BEGIN_TEST(testBug604087)
{
js::SetWindowProxyClass(cx->runtime(), &OuterWrapperClass);
js::SetWindowProxyClass(cx, &OuterWrapperClass);
js::WrapperOptions options;
options.setClass(&OuterWrapperClass);

View File

@ -48,7 +48,7 @@ CallTrusted(JSContext* cx, unsigned argc, JS::Value* vp)
BEGIN_TEST(testChromeBuffer)
{
JS_SetTrustedPrincipals(rt, &system_principals);
JS_SetTrustedPrincipals(cx, &system_principals);
JS::CompartmentOptions options;
trusted_glob.init(cx, JS_NewGlobalObject(cx, &global_class, &system_principals,

View File

@ -79,7 +79,7 @@ class AutoDropPrincipals
~AutoDropPrincipals()
{
JS_DropPrincipals(rt, principals);
JS_DropPrincipals(JS_GetContext(rt), principals);
}
};
@ -92,7 +92,7 @@ DestroyPrincipals(JSPrincipals* principals)
BEGIN_TEST(test_cloneScriptWithPrincipals)
{
JS_InitDestroyPrincipalsCallback(rt, DestroyPrincipals);
JS_InitDestroyPrincipalsCallback(cx, DestroyPrincipals);
JSPrincipals* principalsA = new Principals();
AutoDropPrincipals dropA(rt, principalsA);

View File

@ -11,7 +11,7 @@ static bool IsCompartmentGCBuffer[BufferSize];
BEGIN_TEST(testGCFinalizeCallback)
{
JS_SetGCParameter(rt, JSGC_MODE, JSGC_MODE_INCREMENTAL);
JS_SetGCParameter(cx, JSGC_MODE, JSGC_MODE_INCREMENTAL);
/* Full GC, non-incremental. */
FinalizeCalls = 0;
@ -147,13 +147,13 @@ virtual bool init() override
if (!JSAPITest::init())
return false;
JS_AddFinalizeCallback(rt, FinalizeCallback, nullptr);
JS_AddFinalizeCallback(cx, FinalizeCallback, nullptr);
return true;
}
virtual void uninit() override
{
JS_RemoveFinalizeCallback(rt, FinalizeCallback);
JS_RemoveFinalizeCallback(cx, FinalizeCallback);
JSAPITest::uninit();
}

View File

@ -162,7 +162,7 @@ BEGIN_TEST(testIncrementalRoots)
// descendants. It shouldn't make it all the way through (it gets a budget
// of 1000, and the graph is about 3000 objects deep).
js::SliceBudget budget(js::WorkBudget(1000));
JS_SetGCParameter(rt, JSGC_MODE, JSGC_MODE_INCREMENTAL);
JS_SetGCParameter(cx, JSGC_MODE, JSGC_MODE_INCREMENTAL);
rt->gc.startDebugGC(GC_NORMAL, budget);
// We'd better be between iGC slices now. There's always a risk that

View File

@ -58,7 +58,7 @@ virtual JSRuntime * createRuntime() override {
JSRuntime* rt = JS_NewRuntime(768 * 1024, 128 * 1024);
if (!rt)
return nullptr;
setNativeStackQuota(rt);
setNativeStackQuota(JS_GetContext(rt));
return rt;
}

View File

@ -33,7 +33,7 @@ BEGIN_TEST(testPinAcrossGC)
sw.str = JS_AtomizeAndPinString(cx, "wrapped chars that another test shouldn't be using");
sw.strOk = false;
CHECK(sw.str);
JS_AddFinalizeCallback(rt, FinalizeCallback, nullptr);
JS_AddFinalizeCallback(cx, FinalizeCallback, nullptr);
JS_GC(rt);
CHECK(sw.strOk);
return true;

View File

@ -22,8 +22,8 @@ virtual JSRuntime * createRuntime() override
JSRuntime* rt = JS_NewRuntime(0);
if (!rt)
return nullptr;
JS_SetGCParameter(rt, JSGC_MAX_BYTES, (uint32_t)-1);
setNativeStackQuota(rt);
JS_SetGCParameter(JS_GetContext(rt), JSGC_MAX_BYTES, (uint32_t)-1);
setNativeStackQuota(JS_GetContext(rt));
return rt;
}
END_TEST(testOOM)

View File

@ -130,9 +130,9 @@ JSSecurityCallbacks StructuredCloneTestPrincipals::securityCallbacks = {
BEGIN_TEST(testStructuredClone_SavedFrame)
{
JS_SetSecurityCallbacks(rt, &StructuredCloneTestPrincipals::securityCallbacks);
JS_InitDestroyPrincipalsCallback(rt, StructuredCloneTestPrincipals::destroy);
JS_InitReadPrincipalsCallback(rt, StructuredCloneTestPrincipals::read);
JS_SetSecurityCallbacks(cx, &StructuredCloneTestPrincipals::securityCallbacks);
JS_InitDestroyPrincipalsCallback(cx, StructuredCloneTestPrincipals::destroy);
JS_InitReadPrincipalsCallback(cx, StructuredCloneTestPrincipals::read);
auto testPrincipals = new StructuredCloneTestPrincipals(42, 0);
CHECK(testPrincipals);

View File

@ -70,7 +70,7 @@ END_TEST(testWeakMap_basicOperations)
BEGIN_TEST(testWeakMap_keyDelegates)
{
JS_SetGCParameter(rt, JSGC_MODE, JSGC_MODE_INCREMENTAL);
JS_SetGCParameter(cx, JSGC_MODE, JSGC_MODE_INCREMENTAL);
JS_GC(rt);
JS::RootedObject map(cx, JS::NewWeakMapObject(cx));
CHECK(map);

View File

@ -267,7 +267,7 @@ class JSAPITest
bool definePrint();
static void setNativeStackQuota(JSRuntime* rt)
static void setNativeStackQuota(JSContext* cx)
{
const size_t MAX_STACK_SIZE =
/* Assume we can't use more than 5e5 bytes of C stack by default. */
@ -282,7 +282,7 @@ class JSAPITest
#endif
;
JS_SetNativeStackQuota(rt, MAX_STACK_SIZE);
JS_SetNativeStackQuota(cx, MAX_STACK_SIZE);
}
virtual JSRuntime * createRuntime() {
@ -290,7 +290,7 @@ class JSAPITest
if (!rt)
return nullptr;
JS::SetWarningReporter(JS_GetContext(rt), &reportWarning);
setNativeStackQuota(rt);
setNativeStackQuota(JS_GetContext(rt));
return rt;
}

View File

@ -1321,15 +1321,15 @@ JS_strdup(JSRuntime* rt, const char* s)
#undef JS_AddRoot
JS_PUBLIC_API(bool)
JS_AddExtraGCRootsTracer(JSRuntime* rt, JSTraceDataOp traceOp, void* data)
JS_AddExtraGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp, void* data)
{
return rt->gc.addBlackRootsTracer(traceOp, data);
return cx->gc.addBlackRootsTracer(traceOp, data);
}
JS_PUBLIC_API(void)
JS_RemoveExtraGCRootsTracer(JSRuntime* rt, JSTraceDataOp traceOp, void* data)
JS_RemoveExtraGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp, void* data)
{
return rt->gc.removeBlackRootsTracer(traceOp, data);
return cx->gc.removeBlackRootsTracer(traceOp, data);
}
JS_PUBLIC_API(void)
@ -1349,58 +1349,58 @@ JS_MaybeGC(JSContext* cx)
}
JS_PUBLIC_API(void)
JS_SetGCCallback(JSRuntime* rt, JSGCCallback cb, void* data)
JS_SetGCCallback(JSContext* cx, JSGCCallback cb, void* data)
{
AssertHeapIsIdle(rt);
rt->gc.setGCCallback(cb, data);
AssertHeapIsIdle(cx);
cx->gc.setGCCallback(cb, data);
}
JS_PUBLIC_API(void)
JS_SetObjectsTenuredCallback(JSRuntime* rt, JSObjectsTenuredCallback cb,
JS_SetObjectsTenuredCallback(JSContext* cx, JSObjectsTenuredCallback cb,
void* data)
{
AssertHeapIsIdle(rt);
rt->gc.setObjectsTenuredCallback(cb, data);
AssertHeapIsIdle(cx);
cx->gc.setObjectsTenuredCallback(cb, data);
}
JS_PUBLIC_API(bool)
JS_AddFinalizeCallback(JSRuntime* rt, JSFinalizeCallback cb, void* data)
JS_AddFinalizeCallback(JSContext* cx, JSFinalizeCallback cb, void* data)
{
AssertHeapIsIdle(rt);
return rt->gc.addFinalizeCallback(cb, data);
AssertHeapIsIdle(cx);
return cx->gc.addFinalizeCallback(cb, data);
}
JS_PUBLIC_API(void)
JS_RemoveFinalizeCallback(JSRuntime* rt, JSFinalizeCallback cb)
JS_RemoveFinalizeCallback(JSContext* cx, JSFinalizeCallback cb)
{
rt->gc.removeFinalizeCallback(cb);
cx->gc.removeFinalizeCallback(cb);
}
JS_PUBLIC_API(bool)
JS_AddWeakPointerZoneGroupCallback(JSRuntime* rt, JSWeakPointerZoneGroupCallback cb, void* data)
JS_AddWeakPointerZoneGroupCallback(JSContext* cx, JSWeakPointerZoneGroupCallback cb, void* data)
{
AssertHeapIsIdle(rt);
return rt->gc.addWeakPointerZoneGroupCallback(cb, data);
AssertHeapIsIdle(cx);
return cx->gc.addWeakPointerZoneGroupCallback(cb, data);
}
JS_PUBLIC_API(void)
JS_RemoveWeakPointerZoneGroupCallback(JSRuntime* rt, JSWeakPointerZoneGroupCallback cb)
JS_RemoveWeakPointerZoneGroupCallback(JSContext* cx, JSWeakPointerZoneGroupCallback cb)
{
rt->gc.removeWeakPointerZoneGroupCallback(cb);
cx->gc.removeWeakPointerZoneGroupCallback(cb);
}
JS_PUBLIC_API(bool)
JS_AddWeakPointerCompartmentCallback(JSRuntime* rt, JSWeakPointerCompartmentCallback cb,
JS_AddWeakPointerCompartmentCallback(JSContext* cx, JSWeakPointerCompartmentCallback cb,
void* data)
{
AssertHeapIsIdle(rt);
return rt->gc.addWeakPointerCompartmentCallback(cb, data);
AssertHeapIsIdle(cx);
return cx->gc.addWeakPointerCompartmentCallback(cb, data);
}
JS_PUBLIC_API(void)
JS_RemoveWeakPointerCompartmentCallback(JSRuntime* rt, JSWeakPointerCompartmentCallback cb)
JS_RemoveWeakPointerCompartmentCallback(JSContext* cx, JSWeakPointerCompartmentCallback cb)
{
rt->gc.removeWeakPointerCompartmentCallback(cb);
cx->gc.removeWeakPointerCompartmentCallback(cb);
}
@ -1418,11 +1418,11 @@ JS_UpdateWeakPointerAfterGCUnbarriered(JSObject** objp)
}
JS_PUBLIC_API(void)
JS_SetGCParameter(JSRuntime* rt, JSGCParamKey key, uint32_t value)
JS_SetGCParameter(JSContext* cx, JSGCParamKey key, uint32_t value)
{
rt->gc.waitBackgroundSweepEnd();
AutoLockGC lock(rt);
MOZ_ALWAYS_TRUE(rt->gc.setParameter(key, value, lock));
cx->gc.waitBackgroundSweepEnd();
AutoLockGC lock(cx);
MOZ_ALWAYS_TRUE(cx->gc.setParameter(key, value, lock));
}
JS_PUBLIC_API(uint32_t)
@ -1439,7 +1439,7 @@ struct JSGCConfig {
};
JS_PUBLIC_API(void)
JS_SetGCParametersBasedOnAvailableMemory(JSRuntime* rt, uint32_t availMem)
JS_SetGCParametersBasedOnAvailableMemory(JSContext* cx, uint32_t availMem)
{
static const JSGCConfig minimal[NumGCConfigs] = {
{JSGC_MAX_MALLOC_BYTES, 6 * 1024 * 1024},
@ -1481,7 +1481,7 @@ JS_SetGCParametersBasedOnAvailableMemory(JSRuntime* rt, uint32_t availMem)
}
for (size_t i = 0; i < NumGCConfigs; i++)
JS_SetGCParameter(rt, config[i].key, config[i].value);
JS_SetGCParameter(cx, config[i].key, config[i].value);
}
@ -1530,9 +1530,10 @@ SetNativeStackQuotaAndLimit(JSRuntime* rt, StackKind kind, size_t stackSize)
}
JS_PUBLIC_API(void)
JS_SetNativeStackQuota(JSRuntime* rt, size_t systemCodeStackSize, size_t trustedScriptStackSize,
JS_SetNativeStackQuota(JSContext* cx, size_t systemCodeStackSize, size_t trustedScriptStackSize,
size_t untrustedScriptStackSize)
{
JSRuntime* rt = cx->runtime();
MOZ_ASSERT(rt->requestDepth == 0);
if (!trustedScriptStackSize)
@ -3267,46 +3268,46 @@ JS_HoldPrincipals(JSPrincipals* principals)
}
JS_PUBLIC_API(void)
JS_DropPrincipals(JSRuntime* rt, JSPrincipals* principals)
JS_DropPrincipals(JSContext* cx, JSPrincipals* principals)
{
int rc = --principals->refcount;
if (rc == 0)
rt->destroyPrincipals(principals);
cx->destroyPrincipals(principals);
}
JS_PUBLIC_API(void)
JS_SetSecurityCallbacks(JSRuntime* rt, const JSSecurityCallbacks* scb)
JS_SetSecurityCallbacks(JSContext* cx, const JSSecurityCallbacks* scb)
{
MOZ_ASSERT(scb != &NullSecurityCallbacks);
rt->securityCallbacks = scb ? scb : &NullSecurityCallbacks;
cx->securityCallbacks = scb ? scb : &NullSecurityCallbacks;
}
JS_PUBLIC_API(const JSSecurityCallbacks*)
JS_GetSecurityCallbacks(JSRuntime* rt)
JS_GetSecurityCallbacks(JSContext* cx)
{
return (rt->securityCallbacks != &NullSecurityCallbacks) ? rt->securityCallbacks : nullptr;
return (cx->securityCallbacks != &NullSecurityCallbacks) ? cx->securityCallbacks : nullptr;
}
JS_PUBLIC_API(void)
JS_SetTrustedPrincipals(JSRuntime* rt, JSPrincipals* prin)
JS_SetTrustedPrincipals(JSContext* cx, JSPrincipals* prin)
{
rt->setTrustedPrincipals(prin);
cx->setTrustedPrincipals(prin);
}
extern JS_PUBLIC_API(void)
JS_InitDestroyPrincipalsCallback(JSRuntime* rt, JSDestroyPrincipalsOp destroyPrincipals)
JS_InitDestroyPrincipalsCallback(JSContext* cx, JSDestroyPrincipalsOp destroyPrincipals)
{
MOZ_ASSERT(destroyPrincipals);
MOZ_ASSERT(!rt->destroyPrincipals);
rt->destroyPrincipals = destroyPrincipals;
MOZ_ASSERT(!cx->destroyPrincipals);
cx->destroyPrincipals = destroyPrincipals;
}
extern JS_PUBLIC_API(void)
JS_InitReadPrincipalsCallback(JSRuntime* rt, JSReadPrincipalsOp read)
JS_InitReadPrincipalsCallback(JSContext* cx, JSReadPrincipalsOp read)
{
MOZ_ASSERT(read);
MOZ_ASSERT(!rt->readPrincipals);
rt->readPrincipals = read;
MOZ_ASSERT(!cx->readPrincipals);
cx->readPrincipals = read;
}
JS_PUBLIC_API(JSFunction*)
@ -6499,18 +6500,18 @@ JSAutoByteString::encodeLatin1(ExclusiveContext* cx, JSString* str)
}
JS_PUBLIC_API(void)
JS::SetLargeAllocationFailureCallback(JSRuntime* rt, JS::LargeAllocationFailureCallback lafc,
JS::SetLargeAllocationFailureCallback(JSContext* cx, JS::LargeAllocationFailureCallback lafc,
void* data)
{
rt->largeAllocationFailureCallback = lafc;
rt->largeAllocationFailureCallbackData = data;
cx->largeAllocationFailureCallback = lafc;
cx->largeAllocationFailureCallbackData = data;
}
JS_PUBLIC_API(void)
JS::SetOutOfMemoryCallback(JSRuntime* rt, OutOfMemoryCallback cb, void* data)
JS::SetOutOfMemoryCallback(JSContext* cx, OutOfMemoryCallback cb, void* data)
{
rt->oomCallback = cb;
rt->oomCallbackData = data;
cx->oomCallback = cb;
cx->oomCallbackData = data;
}
JS_PUBLIC_API(bool)

View File

@ -1598,11 +1598,11 @@ JS_strdup(JSRuntime* rt, const char* s);
* data: the data argument to pass to each invocation of traceOp.
*/
extern JS_PUBLIC_API(bool)
JS_AddExtraGCRootsTracer(JSRuntime* rt, JSTraceDataOp traceOp, void* data);
JS_AddExtraGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp, void* data);
/** Undo a call to JS_AddExtraGCRootsTracer. */
extern JS_PUBLIC_API(void)
JS_RemoveExtraGCRootsTracer(JSRuntime* rt, JSTraceDataOp traceOp, void* data);
JS_RemoveExtraGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp, void* data);
/*
* Garbage collector API.
@ -1614,17 +1614,17 @@ extern JS_PUBLIC_API(void)
JS_MaybeGC(JSContext* cx);
extern JS_PUBLIC_API(void)
JS_SetGCCallback(JSRuntime* rt, JSGCCallback cb, void* data);
JS_SetGCCallback(JSContext* cx, JSGCCallback cb, void* data);
extern JS_PUBLIC_API(void)
JS_SetObjectsTenuredCallback(JSRuntime* rt, JSObjectsTenuredCallback cb,
JS_SetObjectsTenuredCallback(JSContext* cx, JSObjectsTenuredCallback cb,
void* data);
extern JS_PUBLIC_API(bool)
JS_AddFinalizeCallback(JSRuntime* rt, JSFinalizeCallback cb, void* data);
JS_AddFinalizeCallback(JSContext* cx, JSFinalizeCallback cb, void* data);
extern JS_PUBLIC_API(void)
JS_RemoveFinalizeCallback(JSRuntime* rt, JSFinalizeCallback cb);
JS_RemoveFinalizeCallback(JSContext* cx, JSFinalizeCallback cb);
/*
* Weak pointers and garbage collection
@ -1661,17 +1661,17 @@ JS_RemoveFinalizeCallback(JSRuntime* rt, JSFinalizeCallback cb);
*/
extern JS_PUBLIC_API(bool)
JS_AddWeakPointerZoneGroupCallback(JSRuntime* rt, JSWeakPointerZoneGroupCallback cb, void* data);
JS_AddWeakPointerZoneGroupCallback(JSContext* cx, JSWeakPointerZoneGroupCallback cb, void* data);
extern JS_PUBLIC_API(void)
JS_RemoveWeakPointerZoneGroupCallback(JSRuntime* rt, JSWeakPointerZoneGroupCallback cb);
JS_RemoveWeakPointerZoneGroupCallback(JSContext* cx, JSWeakPointerZoneGroupCallback cb);
extern JS_PUBLIC_API(bool)
JS_AddWeakPointerCompartmentCallback(JSRuntime* rt, JSWeakPointerCompartmentCallback cb,
JS_AddWeakPointerCompartmentCallback(JSContext* cx, JSWeakPointerCompartmentCallback cb,
void* data);
extern JS_PUBLIC_API(void)
JS_RemoveWeakPointerCompartmentCallback(JSRuntime* rt, JSWeakPointerCompartmentCallback cb);
JS_RemoveWeakPointerCompartmentCallback(JSContext* cx, JSWeakPointerCompartmentCallback cb);
extern JS_PUBLIC_API(void)
JS_UpdateWeakPointerAfterGC(JS::Heap<JSObject*>* objp);
@ -1764,13 +1764,13 @@ typedef enum JSGCParamKey {
} JSGCParamKey;
extern JS_PUBLIC_API(void)
JS_SetGCParameter(JSRuntime* rt, JSGCParamKey key, uint32_t value);
JS_SetGCParameter(JSContext* cx, JSGCParamKey key, uint32_t value);
extern JS_PUBLIC_API(uint32_t)
JS_GetGCParameter(JSRuntime* rt, JSGCParamKey key);
extern JS_PUBLIC_API(void)
JS_SetGCParametersBasedOnAvailableMemory(JSRuntime* rt, uint32_t availMem);
JS_SetGCParametersBasedOnAvailableMemory(JSContext* cx, uint32_t availMem);
/**
* Create a new JSString whose chars member refers to external memory, i.e.,
@ -1812,7 +1812,7 @@ JS_GetExternalStringFinalizer(JSString* str);
* and before any code is executed and/or interrupts requested.
*/
extern JS_PUBLIC_API(void)
JS_SetNativeStackQuota(JSRuntime* cx, size_t systemCodeStackSize,
JS_SetNativeStackQuota(JSContext* cx, size_t systemCodeStackSize,
size_t trustedScriptStackSize = 0,
size_t untrustedScriptStackSize = 0);
@ -5875,7 +5875,7 @@ typedef void
(* LargeAllocationFailureCallback)(void* data);
extern JS_PUBLIC_API(void)
SetLargeAllocationFailureCallback(JSRuntime* rt, LargeAllocationFailureCallback afc, void* data);
SetLargeAllocationFailureCallback(JSContext* cx, LargeAllocationFailureCallback afc, void* data);
/**
* Unlike the error reporter, which is only called if the exception for an OOM
@ -5892,8 +5892,7 @@ typedef void
(* OutOfMemoryCallback)(JSContext* cx, void* data);
extern JS_PUBLIC_API(void)
SetOutOfMemoryCallback(JSRuntime* rt, OutOfMemoryCallback cb, void* data);
SetOutOfMemoryCallback(JSContext* cx, OutOfMemoryCallback cb, void* data);
/**
* Capture the current call stack as a chain of SavedFrame JSObjects, and set

View File

@ -385,6 +385,10 @@ struct JSCompartment
return runtime_;
}
JSContext* contextFromMainThread() const {
return runtime_->contextFromMainThread();
}
/*
* Nb: global_ might be nullptr, if (a) it's the atoms compartment, or
* (b) the compartment's global has been collected. The latter can happen

View File

@ -510,7 +510,7 @@ ErrorObject::createConstructor(JSContext* cx, JSProtoKey key)
}
JS_FRIEND_API(JSFlatString*)
js::GetErrorTypeName(JSRuntime* rt, int16_t exnType)
js::GetErrorTypeName(JSContext* cx, int16_t exnType)
{
/*
* JSEXN_INTERNALERR returns null to prevent that "InternalError: "
@ -522,7 +522,7 @@ js::GetErrorTypeName(JSRuntime* rt, int16_t exnType)
return nullptr;
}
JSProtoKey key = GetExceptionProtoKey(JSExnType(exnType));
return ClassName(key, rt->contextFromMainThread());
return ClassName(key, cx);
}
void

View File

@ -52,21 +52,21 @@ PerThreadDataFriendFields::PerThreadDataFriendFields()
}
JS_FRIEND_API(void)
js::SetSourceHook(JSRuntime* rt, mozilla::UniquePtr<SourceHook> hook)
js::SetSourceHook(JSContext* cx, mozilla::UniquePtr<SourceHook> hook)
{
rt->sourceHook = Move(hook);
cx->sourceHook = Move(hook);
}
JS_FRIEND_API(mozilla::UniquePtr<SourceHook>)
js::ForgetSourceHook(JSRuntime* rt)
js::ForgetSourceHook(JSContext* cx)
{
return Move(rt->sourceHook);
return Move(cx->sourceHook);
}
JS_FRIEND_API(void)
JS_SetGrayGCRootsTracer(JSRuntime* rt, JSTraceDataOp traceOp, void* data)
JS_SetGrayGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp, void* data)
{
rt->gc.setGrayRootsTracer(traceOp, data);
cx->gc.setGrayRootsTracer(traceOp, data);
}
JS_FRIEND_API(JSObject*)
@ -169,7 +169,7 @@ JS_SetCompartmentPrincipals(JSCompartment* compartment, JSPrincipals* principals
// Clear out the old principals, if any.
if (compartment->principals()) {
JS_DropPrincipals(compartment->runtimeFromMainThread(), compartment->principals());
JS_DropPrincipals(compartment->contextFromMainThread(), compartment->principals());
compartment->setPrincipals(nullptr);
// We'd like to assert that our new principals is always same-origin
// with the old one, but JSPrincipals doesn't give us a way to do that.
@ -540,9 +540,9 @@ js::SetReservedOrProxyPrivateSlotWithBarrier(JSObject* obj, size_t slot, const j
}
void
js::SetPreserveWrapperCallback(JSRuntime* rt, PreserveWrapperCallback callback)
js::SetPreserveWrapperCallback(JSContext* cx, PreserveWrapperCallback callback)
{
rt->preserveWrapperCallback = callback;
cx->preserveWrapperCallback = callback;
}
/*
@ -647,9 +647,9 @@ js::StringToLinearStringSlow(JSContext* cx, JSString* str)
}
JS_FRIEND_API(void)
JS_SetAccumulateTelemetryCallback(JSRuntime* rt, JSAccumulateTelemetryDataCallback callback)
JS_SetAccumulateTelemetryCallback(JSContext* cx, JSAccumulateTelemetryDataCallback callback)
{
rt->setTelemetryCallback(rt, callback);
cx->setTelemetryCallback(cx, callback);
}
JS_FRIEND_API(JSObject*)
@ -1134,10 +1134,10 @@ js::DumpHeap(JSRuntime* rt, FILE* fp, js::DumpHeapNurseryBehaviour nurseryBehavi
}
JS_FRIEND_API(void)
js::SetActivityCallback(JSRuntime* rt, ActivityCallback cb, void* arg)
js::SetActivityCallback(JSContext* cx, ActivityCallback cb, void* arg)
{
rt->activityCallback = cb;
rt->activityCallbackArg = arg;
cx->activityCallback = cb;
cx->activityCallbackArg = arg;
}
JS_FRIEND_API(void)
@ -1195,15 +1195,15 @@ js::GetEnterCompartmentDepth(JSContext* cx)
#endif
JS_FRIEND_API(void)
js::SetDOMCallbacks(JSRuntime* rt, const DOMCallbacks* callbacks)
js::SetDOMCallbacks(JSContext* cx, const DOMCallbacks* callbacks)
{
rt->DOMcallbacks = callbacks;
cx->DOMcallbacks = callbacks;
}
JS_FRIEND_API(const DOMCallbacks*)
js::GetDOMCallbacks(JSRuntime* rt)
js::GetDOMCallbacks(JSContext* cx)
{
return rt->DOMcallbacks;
return cx->DOMcallbacks;
}
static const void* gDOMProxyHandlerFamily = nullptr;
@ -1343,10 +1343,10 @@ js::GetPropertyNameFromPC(JSScript* script, jsbytecode* pc)
}
JS_FRIEND_API(void)
js::SetWindowProxyClass(JSRuntime* rt, const js::Class* clasp)
js::SetWindowProxyClass(JSContext* cx, const js::Class* clasp)
{
MOZ_ASSERT(!rt->maybeWindowProxyClass());
rt->setWindowProxyClass(clasp);
MOZ_ASSERT(!cx->maybeWindowProxyClass());
cx->setWindowProxyClass(clasp);
}
JS_FRIEND_API(void)

View File

@ -45,7 +45,7 @@ class InterpreterFrame;
} /* namespace js */
extern JS_FRIEND_API(void)
JS_SetGrayGCRootsTracer(JSRuntime* rt, JSTraceDataOp traceOp, void* data);
JS_SetGrayGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp, void* data);
extern JS_FRIEND_API(JSObject*)
JS_FindCompilationScope(JSContext* cx, JS::HandleObject obj);
@ -145,7 +145,7 @@ typedef void
(*JSAccumulateTelemetryDataCallback)(int id, uint32_t sample, const char* key);
extern JS_FRIEND_API(void)
JS_SetAccumulateTelemetryCallback(JSRuntime* rt, JSAccumulateTelemetryDataCallback callback);
JS_SetAccumulateTelemetryCallback(JSContext* cx, JSAccumulateTelemetryDataCallback callback);
extern JS_FRIEND_API(bool)
JS_GetIsSecureContext(JSCompartment* compartment);
@ -446,17 +446,17 @@ class SourceHook {
};
/**
* Have |rt| use |hook| to retrieve lazily-retrieved source code. See the
* comments for SourceHook. The runtime takes ownership of the hook, and
* will delete it when the runtime itself is deleted, or when a new hook is
* Have |cx| use |hook| to retrieve lazily-retrieved source code. See the
* comments for SourceHook. The context takes ownership of the hook, and
* will delete it when the context itself is deleted, or when a new hook is
* set.
*/
extern JS_FRIEND_API(void)
SetSourceHook(JSRuntime* rt, mozilla::UniquePtr<SourceHook> hook);
SetSourceHook(JSContext* cx, mozilla::UniquePtr<SourceHook> hook);
/** Remove |rt|'s source hook, and return it. The caller now owns the hook. */
/** Remove |cx|'s source hook, and return it. The caller now owns the hook. */
extern JS_FRIEND_API(mozilla::UniquePtr<SourceHook>)
ForgetSourceHook(JSRuntime* rt);
ForgetSourceHook(JSContext* cx);
extern JS_FRIEND_API(JS::Zone*)
GetCompartmentZone(JSCompartment* comp);
@ -978,7 +978,7 @@ JS_FRIEND_API(bool)
StringIsArrayIndex(JSLinearString* str, uint32_t* indexp);
JS_FRIEND_API(void)
SetPreserveWrapperCallback(JSRuntime* rt, PreserveWrapperCallback callback);
SetPreserveWrapperCallback(JSContext* cx, PreserveWrapperCallback callback);
JS_FRIEND_API(bool)
IsObjectInContextCompartment(JSObject* obj, const JSContext* cx);
@ -1118,7 +1118,7 @@ typedef void
* idle and a request begins.
*/
JS_FRIEND_API(void)
SetActivityCallback(JSRuntime* rt, ActivityCallback cb, void* arg);
SetActivityCallback(JSContext* cx, ActivityCallback cb, void* arg);
typedef bool
(* DOMInstanceClassHasProtoAtDepth)(const Class* instanceClass,
@ -1129,10 +1129,10 @@ struct JSDOMCallbacks {
typedef struct JSDOMCallbacks DOMCallbacks;
extern JS_FRIEND_API(void)
SetDOMCallbacks(JSRuntime* rt, const DOMCallbacks* callbacks);
SetDOMCallbacks(JSContext* cx, const DOMCallbacks* callbacks);
extern JS_FRIEND_API(const DOMCallbacks*)
GetDOMCallbacks(JSRuntime* rt);
GetDOMCallbacks(JSContext* cx);
extern JS_FRIEND_API(JSObject*)
GetTestingFunctions(JSContext* cx);
@ -1155,7 +1155,7 @@ CastToJSFreeOp(FreeOp* fop)
* Returns nullptr for invalid arguments and JSEXN_INTERNALERR
*/
extern JS_FRIEND_API(JSFlatString*)
GetErrorTypeName(JSRuntime* rt, int16_t exnType);
GetErrorTypeName(JSContext* cx, int16_t exnType);
#ifdef JS_DEBUG
extern JS_FRIEND_API(unsigned)
@ -2877,7 +2877,7 @@ ConvertArgsToArray(JSContext* cx, const JS::CallArgs& args);
* functions below.
*/
extern JS_FRIEND_API(void)
SetWindowProxyClass(JSRuntime* rt, const Class* clasp);
SetWindowProxyClass(JSContext* cx, const Class* clasp);
/**
* Associates a WindowProxy with a Window (global object). `windowProxy` must

View File

@ -3510,7 +3510,7 @@ Zone::sweepCompartments(FreeOp* fop, bool keepAtleastOne, bool destroyingRuntime
if (callback)
callback(fop, comp);
if (comp->principals())
JS_DropPrincipals(rt, comp->principals());
JS_DropPrincipals(rt->contextFromMainThread(), comp->principals());
js_delete(comp);
} else {
*write++ = comp;

View File

@ -2949,7 +2949,7 @@ WorkerMain(void* arg)
JS_SetRuntimePrivate(rt, sr.get());
JS_SetFutexCanWait(cx);
JS::SetWarningReporter(cx, WarningReporter);
JS_InitDestroyPrincipalsCallback(rt, ShellPrincipals::destroy);
JS_InitDestroyPrincipalsCallback(cx, ShellPrincipals::destroy);
SetWorkerRuntimeOptions(rt);
if (!JS::InitSelfHostedCode(cx)) {
@ -2966,7 +2966,7 @@ WorkerMain(void* arg)
EnvironmentPreparer environmentPreparer(cx);
JS::SetLargeAllocationFailureCallback(rt, my_LargeAllocFailCallback, (void*)cx);
JS::SetLargeAllocationFailureCallback(cx, my_LargeAllocFailCallback, (void*)cx);
do {
JSAutoRequest ar(cx);
@ -2991,7 +2991,7 @@ WorkerMain(void* arg)
JS_ExecuteScript(cx, script, &result);
} while (0);
JS::SetLargeAllocationFailureCallback(rt, nullptr, nullptr);
JS::SetLargeAllocationFailureCallback(cx, nullptr, nullptr);
#ifdef SPIDERMONKEY_PROMISE
JS::SetGetIncumbentGlobalCallback(rt, nullptr);
@ -4352,7 +4352,7 @@ NewGlobal(JSContext* cx, unsigned argc, Value* vp)
RootedObject global(cx, NewGlobalObject(cx, options, principals));
if (principals)
JS_DropPrincipals(cx->runtime(), principals);
JS_DropPrincipals(cx, principals);
if (!global)
return false;
@ -4462,12 +4462,12 @@ WithSourceHook(JSContext* cx, unsigned argc, Value* vp)
if (!hook)
return false;
mozilla::UniquePtr<SourceHook> savedHook = js::ForgetSourceHook(cx->runtime());
js::SetSourceHook(cx->runtime(), Move(hook));
mozilla::UniquePtr<SourceHook> savedHook = js::ForgetSourceHook(cx);
js::SetSourceHook(cx, Move(hook));
RootedObject fun(cx, &args[1].toObject());
bool result = Call(cx, UndefinedHandleValue, fun, JS::HandleValueArray::empty(), args.rval());
js::SetSourceHook(cx->runtime(), Move(savedHook));
js::SetSourceHook(cx, Move(savedHook));
return result;
}
@ -5873,7 +5873,7 @@ CreateLastWarningObject(JSContext* cx, JSErrorReport* report)
if (report->exnType == JSEXN_WARN)
nameStr = JS_NewStringCopyZ(cx, "Warning");
else
nameStr = GetErrorTypeName(cx->runtime(), report->exnType);
nameStr = GetErrorTypeName(cx, report->exnType);
if (!nameStr)
return false;
RootedValue nameVal(cx, StringValue(nameStr));
@ -6578,7 +6578,7 @@ NewGlobalObject(JSContext* cx, JS::CompartmentOptions& options,
static const js::DOMCallbacks DOMcallbacks = {
InstanceClassHasProtoAtDepth
};
SetDOMCallbacks(cx->runtime(), &DOMcallbacks);
SetDOMCallbacks(cx, &DOMcallbacks);
RootedObject domProto(cx, JS_InitClass(cx, glob, nullptr, &dom_class, dom_constructor,
0, dom_props, dom_methods, nullptr, nullptr));
@ -7019,7 +7019,7 @@ SetWorkerRuntimeOptions(JSRuntime* rt)
}
#endif
JS_SetNativeStackQuota(rt, gMaxStackSize);
JS_SetNativeStackQuota(JS_GetContext(rt), gMaxStackSize);
}
static int
@ -7390,21 +7390,21 @@ main(int argc, char** argv, char** envp)
if (!SetRuntimeOptions(rt, op))
return 1;
JS_SetGCParameter(rt, JSGC_MAX_BYTES, 0xffffffff);
JS_SetGCParameter(cx, JSGC_MAX_BYTES, 0xffffffff);
size_t availMem = op.getIntOption("available-memory");
if (availMem > 0)
JS_SetGCParametersBasedOnAvailableMemory(rt, availMem);
JS_SetGCParametersBasedOnAvailableMemory(cx, availMem);
JS_SetTrustedPrincipals(rt, &ShellPrincipals::fullyTrusted);
JS_SetSecurityCallbacks(rt, &ShellPrincipals::securityCallbacks);
JS_InitDestroyPrincipalsCallback(rt, ShellPrincipals::destroy);
JS_SetTrustedPrincipals(cx, &ShellPrincipals::fullyTrusted);
JS_SetSecurityCallbacks(cx, &ShellPrincipals::securityCallbacks);
JS_InitDestroyPrincipalsCallback(cx, ShellPrincipals::destroy);
JS_SetInterruptCallback(rt, ShellInterruptCallback);
JS::SetBuildIdOp(cx, ShellBuildId);
JS::SetAsmJSCacheOps(cx, &asmJSCacheOps);
JS_SetNativeStackQuota(rt, gMaxStackSize);
JS_SetNativeStackQuota(cx, gMaxStackSize);
JS::dbg::SetDebuggerMallocSizeOf(rt, moz_malloc_size_of);
@ -7419,22 +7419,22 @@ main(int argc, char** argv, char** envp)
EnvironmentPreparer environmentPreparer(cx);
JS_SetGCParameter(rt, JSGC_MODE, JSGC_MODE_INCREMENTAL);
JS_SetGCParameter(cx, JSGC_MODE, JSGC_MODE_INCREMENTAL);
JS::SetLargeAllocationFailureCallback(rt, my_LargeAllocFailCallback, (void*)cx);
JS::SetLargeAllocationFailureCallback(cx, my_LargeAllocFailCallback, (void*)cx);
// Set some parameters to allow incremental GC in low memory conditions,
// as is done for the browser, except in more-deterministic builds or when
// disabled by command line options.
#ifndef JS_MORE_DETERMINISTIC
if (!op.getBoolOption("no-incremental-gc")) {
JS_SetGCParameter(rt, JSGC_DYNAMIC_HEAP_GROWTH, 1);
JS_SetGCParameter(rt, JSGC_DYNAMIC_MARK_SLICE, 1);
JS_SetGCParameter(rt, JSGC_SLICE_TIME_BUDGET, 10);
JS_SetGCParameter(cx, JSGC_DYNAMIC_HEAP_GROWTH, 1);
JS_SetGCParameter(cx, JSGC_DYNAMIC_MARK_SLICE, 1);
JS_SetGCParameter(cx, JSGC_SLICE_TIME_BUDGET, 10);
}
#endif
js::SetPreserveWrapperCallback(rt, DummyPreserveWrapperCallback);
js::SetPreserveWrapperCallback(cx, DummyPreserveWrapperCallback);
result = Shell(cx, &op, envp);
@ -7443,7 +7443,7 @@ main(int argc, char** argv, char** envp)
printf("OOM max count: %" PRIu64 "\n", js::oom::counter);
#endif
JS::SetLargeAllocationFailureCallback(rt, nullptr, nullptr);
JS::SetLargeAllocationFailureCallback(cx, nullptr, nullptr);
#ifdef SPIDERMONKEY_PROMISE
JS::SetGetIncumbentGlobalCallback(rt, nullptr);

View File

@ -1215,7 +1215,7 @@ GlobalHelperThreadState::finishModuleParseTask(JSContext* maybecx, JSRuntime* rt
JSContext* cx = maybecx;
RootedModuleObject module(cx, script->module());
module->fixScopesAfterCompartmentMerge(cx);
if (!ModuleObject::FreezeArrayProperties(cx, module))
if (!ModuleObject::Freeze(cx, module))
return nullptr;
return module;

View File

@ -357,7 +357,7 @@ SavedFrame::finalize(FreeOp* fop, JSObject* obj)
JSPrincipals* p = obj->as<SavedFrame>().getPrincipals();
if (p) {
JSRuntime* rt = obj->runtimeFromMainThread();
JS_DropPrincipals(rt, p);
JS_DropPrincipals(rt->contextFromMainThread(), p);
}
}

View File

@ -1647,10 +1647,10 @@ XPCJSRuntime::~XPCJSRuntime()
// actual JS_DestroyRuntime() call. But destroying the runtime triggers
// one final GC, which can call back into the runtime with various
// callback if we aren't careful. Null out the relevant callbacks.
js::SetActivityCallback(Runtime(), nullptr, nullptr);
JS_RemoveFinalizeCallback(Runtime(), FinalizeCallback);
JS_RemoveWeakPointerZoneGroupCallback(Runtime(), WeakPointerZoneGroupCallback);
JS_RemoveWeakPointerCompartmentCallback(Runtime(), WeakPointerCompartmentCallback);
js::SetActivityCallback(Context(), nullptr, nullptr);
JS_RemoveFinalizeCallback(Context(), FinalizeCallback);
JS_RemoveWeakPointerZoneGroupCallback(Context(), WeakPointerZoneGroupCallback);
JS_RemoveWeakPointerCompartmentCallback(Context(), WeakPointerCompartmentCallback);
// Clear any pending exception. It might be an XPCWrappedJS, and if we try
// to destroy it later we will crash.
@ -3474,7 +3474,7 @@ XPCJSRuntime::Initialize()
// This leaves the maximum-JS_malloc-bytes threshold still in effect
// to cause period, and we hope hygienic, last-ditch GCs from within
// the GC's allocator.
JS_SetGCParameter(runtime, JSGC_MAX_BYTES, 0xffffffff);
JS_SetGCParameter(cx, JSGC_MAX_BYTES, 0xffffffff);
// The JS engine permits us to set different stack limits for system code,
// trusted script, and untrusted script. We have tests that ensure that
@ -3548,7 +3548,7 @@ XPCJSRuntime::Initialize()
// default.
(void) kDefaultStackQuota;
JS_SetNativeStackQuota(runtime,
JS_SetNativeStackQuota(cx,
kStackQuota,
kStackQuota - kSystemCodeBuffer,
kStackQuota - kSystemCodeBuffer - kTrustedScriptBuffer);
@ -3557,19 +3557,19 @@ XPCJSRuntime::Initialize()
JS_SetSizeOfIncludingThisCompartmentCallback(cx, CompartmentSizeOfIncludingThisCallback);
JS_SetCompartmentNameCallback(cx, CompartmentNameCallback);
mPrevGCSliceCallback = JS::SetGCSliceCallback(runtime, GCSliceCallback);
JS_AddFinalizeCallback(runtime, FinalizeCallback, nullptr);
JS_AddWeakPointerZoneGroupCallback(runtime, WeakPointerZoneGroupCallback, this);
JS_AddWeakPointerCompartmentCallback(runtime, WeakPointerCompartmentCallback, this);
JS_AddFinalizeCallback(cx, FinalizeCallback, nullptr);
JS_AddWeakPointerZoneGroupCallback(cx, WeakPointerZoneGroupCallback, this);
JS_AddWeakPointerCompartmentCallback(cx, WeakPointerCompartmentCallback, this);
JS_SetWrapObjectCallbacks(cx, &WrapObjectCallbacks);
js::SetPreserveWrapperCallback(runtime, PreserveWrapper);
js::SetPreserveWrapperCallback(cx, PreserveWrapper);
#ifdef MOZ_ENABLE_PROFILER_SPS
if (PseudoStack* stack = mozilla_get_pseudo_stack())
stack->sampleRuntime(runtime);
#endif
JS_SetAccumulateTelemetryCallback(runtime, AccumulateTelemetryCallback);
js::SetActivityCallback(runtime, ActivityCallback, this);
JS_SetAccumulateTelemetryCallback(cx, AccumulateTelemetryCallback);
js::SetActivityCallback(cx, ActivityCallback, this);
JS_SetInterruptCallback(runtime, InterruptCallback);
js::SetWindowProxyClass(runtime, &OuterWindowProxyClass);
js::SetWindowProxyClass(cx, &OuterWindowProxyClass);
#ifdef MOZ_CRASHREPORTER
js::AutoEnterOOMUnsafeRegion::setAnnotateOOMAllocationSizeCallback(
CrashReporter::AnnotateOOMAllocationSize);
@ -3592,7 +3592,7 @@ XPCJSRuntime::Initialize()
// JS::CompileFunction). In practice, this means content scripts and event
// handlers.
UniquePtr<XPCJSSourceHook> hook(new XPCJSSourceHook);
js::SetSourceHook(runtime, Move(hook));
js::SetSourceHook(cx, Move(hook));
// Set up locale information and callbacks for the newly-created runtime so
// that the various toLocaleString() methods, localeCompare(), and other

View File

@ -1463,10 +1463,10 @@ XRE_XPCShellMain(int argc, char** argv, char** envp,
}
}
const JSSecurityCallbacks* scb = JS_GetSecurityCallbacks(rt);
const JSSecurityCallbacks* scb = JS_GetSecurityCallbacks(cx);
MOZ_ASSERT(scb, "We are assuming that nsScriptSecurityManager::Init() has been run");
shellSecurityCallbacks = *scb;
JS_SetSecurityCallbacks(rt, &shellSecurityCallbacks);
JS_SetSecurityCallbacks(cx, &shellSecurityCallbacks);
#ifdef TEST_TranslateThis
nsCOMPtr<nsIXPCFunctionThisTranslator>
@ -1579,7 +1579,7 @@ XRE_XPCShellMain(int argc, char** argv, char** envp,
}
}
JS_DropPrincipals(rt, gJSPrincipals);
JS_DropPrincipals(cx, gJSPrincipals);
JS_SetAllNonReservedSlotsToUndefined(cx, glob);
JS_SetAllNonReservedSlotsToUndefined(cx, JS_GlobalLexicalScope(glob));
JS_GC(rt);

View File

@ -293,7 +293,7 @@ xpc::ErrorReport::ErrorReportToMessageString(JSErrorReport* aReport,
aString.Truncate();
const char16_t* m = aReport->ucmessage;
if (m) {
JSFlatString* name = js::GetErrorTypeName(CycleCollectedJSRuntime::Get()->Runtime(), aReport->exnType);
JSFlatString* name = js::GetErrorTypeName(CycleCollectedJSRuntime::Get()->Context(), aReport->exnType);
if (name) {
AssignJSFlatString(aString, name);
aString.AppendLiteral(": ");

View File

@ -2678,6 +2678,12 @@ var NativeWindow = {
return;
}
// If the event was already defaultPrevented by somebody (web content, or
// some other part of gecko), then don't do anything with it.
if (event.defaultPrevented) {
return;
}
// Use the highlighted element for the context menu target. When accessibility is
// enabled, elements may not be highlighted so use the event target instead.
this._target = BrowserEventHandler._highlightElement || event.target;

View File

@ -679,7 +679,7 @@ private:
* Not setting this will cause JS_CHECK_RECURSION to report false
* positives
*/
JS_SetNativeStackQuota(mRuntime, 128 * sizeof(size_t) * 1024);
JS_SetNativeStackQuota(mContext, 128 * sizeof(size_t) * 1024);
JS::SetWarningReporter(mContext, PACWarningReporter);

View File

@ -635,6 +635,11 @@ public:
#endif // DESKTOP
#ifdef __NR_getrandom
case __NR_getrandom:
return Allow();
#endif
// nsSystemInfo uses uname (and we cache an instance, so
// the info remains present even if we block the syscall)
case __NR_uname:

View File

@ -296,46 +296,99 @@ function find_(container, strategy, selector, searchFn, opts) {
}
/**
* Find a value by XPATH
* Find a single element by XPath expression.
*
* @param nsIDOMElement root
* Document root
* @param string value
* XPATH search string
* @param nsIDOMElement node
* start node
* @param {DOMElement} root
* Document root
* @param {DOMElement} startNode
* Where in the DOM hiearchy to begin searching.
* @param {string} expr
* XPath search expression.
*
* @return nsIDOMElement
* returns the found element
* @return {DOMElement}
* First element matching expression.
*/
function findByXPath(root, value, node) {
return root.evaluate(value, node, null,
Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
}
element.findByXPath = function(root, startNode, expr) {
let iter = root.evaluate(expr, startNode, null,
Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE, null)
return iter.singleNodeValue;
};
/**
* Find values by XPATH
* Find elements by XPath expression.
*
* @param nsIDOMElement root
* Document root
* @param string value
* XPATH search string
* @param nsIDOMElement node
* start node
* @param {DOMElement} root
* Document root.
* @param {DOMElement} startNode
* Where in the DOM hierarchy to begin searching.
* @param {string} expr
* XPath search expression.
*
* @return object
* returns a list of found nsIDOMElements
* @return {Array.<DOMElement>}
* Sequence of found elements matching expression.
*/
function findByXPathAll(root, value, node) {
let values = root.evaluate(value, node, null,
Ci.nsIDOMXPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
let elements = [];
let element = values.iterateNext();
while (element) {
elements.push(element);
element = values.iterateNext();
element.findByXPathAll = function(root, startNode, expr) {
let rv = [];
let iter = root.evaluate(expr, startNode, null,
Ci.nsIDOMXPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
let el = iter.iterateNext();
while (el) {
rv.push(el);
el = iter.iterateNext();
}
return elements;
return rv;
};
/**
* Find all hyperlinks dscendant of |node| which link text is |s|.
*
* @param {DOMElement} node
* Where in the DOM hierarchy to being searching.
* @param {string} s
* Link text to search for.
*
* @return {Array.<DOMAnchorElement>}
* Sequence of link elements which text is |s|.
*/
element.findByLinkText = function(node, s) {
return filterLinks(node, link => link.text === s);
};
/**
* Find all hyperlinks descendant of |node| which link text contains |s|.
*
* @param {DOMElement} node
* Where in the DOM hierachy to begin searching.
* @param {string} s
* Link text to search for.
*
* @return {Array.<DOMAnchorElement>}
* Sequence of link elements which text containins |s|.
*/
element.findByPartialLinkText = function(node, s) {
return filterLinks(node, link => link.text.indexOf(s) != -1);
};
/**
* Filters all hyperlinks that are descendant of |node| by |predicate|.
*
* @param {DOMElement} node
* Where in the DOM hierarchy to begin searching.
* @param {function(DOMAnchorElement): boolean} predicate
* Function that determines if given link should be included in
* return value or filtered away.
*
* @return {Array.<DOMAnchorElement>}
* Sequence of link elements matching |predicate|.
*/
function filterLinks(node, predicate) {
let rv = [];
for (let link of node.getElementsByTagName("a")) {
if (predicate(link)) {
rv.push(link);
}
}
return rv;
}
/**
@ -364,13 +417,13 @@ function findElement(using, value, rootNode, startNode) {
if (startNode.getElementById) {
return startNode.getElementById(value);
}
return findByXPath(rootNode, `.//*[@id="${value}"]`, startNode);
return element.findByXPath(rootNode, startNode, `.//*[@id="${value}"]`);
case element.Strategy.Name:
if (startNode.getElementsByName) {
return startNode.getElementsByName(value)[0];
}
return findByXPath(rootNode, `.//*[@name="${value}"]`, startNode);
return element.findByXPath(rootNode, startNode, `.//*[@name="${value}"]`);
case element.Strategy.ClassName:
// works for >= Firefox 3
@ -381,24 +434,23 @@ function findElement(using, value, rootNode, startNode) {
return startNode.getElementsByTagName(value)[0];
case element.Strategy.XPath:
return findByXPath(rootNode, value, startNode);
return element.findByXPath(rootNode, startNode, value);
// TODO(ato): Rewrite this, it's hairy:
case element.Strategy.LinkText:
case element.Strategy.PartialLinkText:
let el;
let allLinks = startNode.getElementsByTagName("A");
for (let i = 0; i < allLinks.length && !el; i++) {
let text = allLinks[i].text;
if (using == element.Strategy.PartialLinkText) {
if (text.indexOf(value) != -1) {
el = allLinks[i];
}
} else if (text == value) {
el = allLinks[i];
for (let link of startNode.getElementsByTagName("a")) {
if (link.text === value) {
return link;
}
}
return el;
break;
case element.Strategy.PartialLinkText:
for (let link of startNode.getElementsByTagName("a")) {
if (link.text.indexOf(value) != -1) {
return link;
}
}
break;
case element.Strategy.Selector:
try {
@ -446,13 +498,13 @@ function findElements(using, value, rootNode, startNode) {
// fall through
case element.Strategy.XPath:
return findByXPathAll(rootNode, value, startNode);
return element.findByXPathAll(rootNode, startNode, value);
case element.Strategy.Name:
if (startNode.getElementsByName) {
return startNode.getElementsByName(value);
}
return findByXPathAll(rootNode, `.//*[@name="${value}"]`, startNode);
return element.findByXPathAll(rootNode, startNode, `.//*[@name="${value}"]`);
case element.Strategy.ClassName:
return startNode.getElementsByClassName(value);
@ -461,20 +513,10 @@ function findElements(using, value, rootNode, startNode) {
return startNode.getElementsByTagName(value);
case element.Strategy.LinkText:
return element.findByLinkText(startNode, value);
case element.Strategy.PartialLinkText:
let els = [];
let allLinks = startNode.getElementsByTagName("A");
for (let i = 0; i < allLinks.length; i++) {
let text = allLinks[i].text;
if (using == element.Strategy.PartialLinkText) {
if (text.indexOf(value) != -1) {
els.push(allLinks[i]);
}
} else if (text == value) {
els.push(allLinks[i]);
}
}
return els;
return element.findByPartialLinkText(startNode, value);
case element.Strategy.Selector:
return startNode.querySelectorAll(value);

View File

@ -0,0 +1,466 @@
# 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/.
import re
import urllib
from marionette import MarionetteTestCase, skip
from marionette_driver.marionette import HTMLElement
from marionette_driver.by import By
from marionette_driver.errors import NoSuchElementException, InvalidSelectorException
def inline(doc, doctype="html"):
if doctype == "html":
return "data:text/html;charset=utf-8,%s" % urllib.quote(doc)
elif doctype == "xhtml":
return "data:application/xhtml+xml,%s" % urllib.quote(
r"""<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>XHTML might be the future</title>
</head>
<body>
%s
</body>
</html>""" % doc)
id_html = inline("<p id=foo></p>", doctype="html")
id_xhtml = inline('<p id="foo"></p>', doctype="xhtml")
parent_child_html = inline("<div id=parent><p id=child></p></div>", doctype="html")
parent_child_xhtml = inline('<div id="parent"><p id="child"></p></div>', doctype="xhtml")
children_html = inline("<div><p>foo <p>bar</div>", doctype="html")
children_xhtml = inline("<div><p>foo</p> <p>bar</p></div>", doctype="xhtml")
class_html = inline("<p class='foo bar'>", doctype="html")
class_xhtml = inline('<p class="foo bar"></p>', doctype="xhtml")
name_html = inline("<p name=foo>", doctype="html")
name_xhtml = inline('<p name="foo"></p>', doctype="xhtml")
link_html = inline("<p><a href=#>foo bar</a>", doctype="html")
link_xhtml = inline('<p><a href="#">foo bar</a></p>', doctype="xhtml")
class TestFindElementHTML(MarionetteTestCase):
def setUp(self):
MarionetteTestCase.setUp(self)
self.marionette.set_search_timeout(0)
def test_id(self):
self.marionette.navigate(id_html)
expected = self.marionette.execute_script("return document.querySelector('p')")
found = self.marionette.find_element(By.ID, "foo")
self.assertIsInstance(found, HTMLElement)
self.assertEqual(expected, found)
def test_child_element(self):
self.marionette.navigate(parent_child_html)
parent = self.marionette.find_element(By.ID, "parent")
child = self.marionette.find_element(By.ID, "child")
found = parent.find_element(By.TAG_NAME, "p")
self.assertEqual(found.tag_name, "p")
self.assertIsInstance(found, HTMLElement)
self.assertEqual(child, found)
def test_tag_name(self):
self.marionette.navigate(children_html)
el = self.marionette.execute_script("return document.querySelector('p')")
found = self.marionette.find_element(By.TAG_NAME, "p")
self.assertIsInstance(found, HTMLElement)
self.assertEqual(el, found)
def test_class_name(self):
self.marionette.navigate(class_html)
el = self.marionette.execute_script("return document.querySelector('.foo')")
found = self.marionette.find_element(By.CLASS_NAME, "foo")
self.assertIsInstance(found, HTMLElement)
self.assertEqual(el, found)
def test_by_name(self):
self.marionette.navigate(name_html)
el = self.marionette.execute_script("return document.querySelector('[name=foo]')")
found = self.marionette.find_element(By.NAME, "foo")
self.assertIsInstance(found, HTMLElement)
self.assertEqual(el, found)
def test_css_selector(self):
self.marionette.navigate(children_html)
el = self.marionette.execute_script("return document.querySelector('p')")
found = self.marionette.find_element(By.CSS_SELECTOR, "p")
self.assertIsInstance(found, HTMLElement)
self.assertEqual(el, found)
def test_invalid_css_selector_should_throw(self):
with self.assertRaises(InvalidSelectorException):
self.marionette.find_element(By.CSS_SELECTOR, "#")
def test_link_text(self):
self.marionette.navigate(link_html)
el = self.marionette.execute_script("return document.querySelector('a')")
found = self.marionette.find_element(By.LINK_TEXT, "foo bar")
self.assertIsInstance(found, HTMLElement)
self.assertEqual(el, found)
def test_partial_link_text(self):
self.marionette.navigate(link_html)
el = self.marionette.execute_script("return document.querySelector('a')")
found = self.marionette.find_element(By.PARTIAL_LINK_TEXT, "foo")
self.assertIsInstance(found, HTMLElement)
self.assertEqual(el, found)
def test_xpath(self):
self.marionette.navigate(id_html)
el = self.marionette.execute_script("return document.querySelector('#foo')")
found = self.marionette.find_element(By.XPATH, "id('foo')")
self.assertIsInstance(found, HTMLElement)
self.assertEqual(el, found)
def test_not_found(self):
self.marionette.set_search_timeout(0)
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.CLASS_NAME, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.CSS_SELECTOR, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.ID, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.LINK_TEXT, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.NAME, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.PARTIAL_LINK_TEXT, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.TAG_NAME, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.XPATH, "cheese")
def test_not_found_implicit_wait(self):
self.marionette.set_search_timeout(50)
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.CLASS_NAME, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.CSS_SELECTOR, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.ID, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.LINK_TEXT, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.NAME, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.PARTIAL_LINK_TEXT, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.TAG_NAME, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.XPATH, "cheese")
def test_not_found(self):
self.marionette.set_search_timeout(0)
self.marionette.navigate(id_html)
el = self.marionette.find_element(By.ID, "foo")
self.assertRaises(NoSuchElementException, el.find_element, By.CLASS_NAME, "cheese")
self.assertRaises(NoSuchElementException, el.find_element, By.CSS_SELECTOR, "cheese")
self.assertRaises(NoSuchElementException, el.find_element, By.ID, "cheese")
self.assertRaises(NoSuchElementException, el.find_element, By.LINK_TEXT, "cheese")
self.assertRaises(NoSuchElementException, el.find_element, By.NAME, "cheese")
self.assertRaises(NoSuchElementException, el.find_element, By.PARTIAL_LINK_TEXT, "cheese")
self.assertRaises(NoSuchElementException, el.find_element, By.TAG_NAME, "cheese")
self.assertRaises(NoSuchElementException, el.find_element, By.XPATH, "cheese")
def test_not_found_implicit_wait(self):
self.marionette.set_search_timeout(50)
self.marionette.navigate(id_html)
el = self.marionette.find_element(By.ID, "foo")
self.assertRaises(NoSuchElementException, el.find_element, By.CLASS_NAME, "cheese")
self.assertRaises(NoSuchElementException, el.find_element, By.CSS_SELECTOR, "cheese")
self.assertRaises(NoSuchElementException, el.find_element, By.ID, "cheese")
self.assertRaises(NoSuchElementException, el.find_element, By.LINK_TEXT, "cheese")
self.assertRaises(NoSuchElementException, el.find_element, By.NAME, "cheese")
self.assertRaises(NoSuchElementException, el.find_element, By.PARTIAL_LINK_TEXT, "cheese")
self.assertRaises(NoSuchElementException, el.find_element, By.TAG_NAME, "cheese")
self.assertRaises(NoSuchElementException, el.find_element, By.XPATH, "cheese")
def test_css_selector_scope_doesnt_start_at_rootnode(self):
self.marionette.navigate(parent_child_html)
el = self.marionette.find_element(By.ID, "child")
parent = self.marionette.find_element(By.ID, "parent")
found = parent.find_element(By.CSS_SELECTOR, "p")
self.assertEqual(el, found)
def test_unknown_selector(self):
with self.assertRaises(InvalidSelectorException):
self.marionette.find_elements("foo", "bar")
def test_element_id_is_valid_uuid(self):
self.marionette.navigate(id_html)
el = self.marionette.find_element(By.TAG_NAME, "p")
uuid_regex = re.compile('^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$')
self.assertIsNotNone(re.search(uuid_regex, el.id),
'UUID for the WebElement is not valid. ID is {}'\
.format(el.id))
def test_invalid_xpath_selector(self):
with self.assertRaises(InvalidSelectorException):
self.marionette.find_element(By.XPATH, "count(//input)")
with self.assertRaises(InvalidSelectorException):
parent = self.marionette.execute_script("return document.documentElement")
parent.find_element(By.XPATH, "count(//input)")
def test_invalid_css_selector(self):
with self.assertRaises(InvalidSelectorException):
self.marionette.find_element(By.CSS_SELECTOR, "")
with self.assertRaises(InvalidSelectorException):
parent = self.marionette.execute_script("return document.documentElement")
parent.find_element(By.CSS_SELECTOR, "")
def test_finding_active_element_returns_element(self):
self.marionette.navigate(id_html)
active = self.marionette.execute_script("return document.activeElement")
self.assertEqual(active, self.marionette.get_active_element())
class TestFindElementXHTML(MarionetteTestCase):
def setUp(self):
MarionetteTestCase.setUp(self)
self.marionette.set_search_timeout(0)
def test_id(self):
self.marionette.navigate(id_xhtml)
expected = self.marionette.execute_script("return document.querySelector('p')")
found = self.marionette.find_element(By.ID, "foo")
self.assertIsInstance(found, HTMLElement)
self.assertEqual(expected, found)
def test_child_element(self):
self.marionette.navigate(parent_child_xhtml)
parent = self.marionette.find_element(By.ID, "parent")
child = self.marionette.find_element(By.ID, "child")
found = parent.find_element(By.TAG_NAME, "p")
self.assertEqual(found.tag_name, "p")
self.assertIsInstance(found, HTMLElement)
self.assertEqual(child, found)
def test_tag_name(self):
self.marionette.navigate(children_xhtml)
el = self.marionette.execute_script("return document.querySelector('p')")
found = self.marionette.find_element(By.TAG_NAME, "p")
self.assertIsInstance(found, HTMLElement)
self.assertEqual(el, found)
def test_class_name(self):
self.marionette.navigate(class_xhtml)
el = self.marionette.execute_script("return document.querySelector('.foo')")
found = self.marionette.find_element(By.CLASS_NAME, "foo")
self.assertIsInstance(found, HTMLElement)
self.assertEqual(el, found)
def test_by_name(self):
self.marionette.navigate(name_xhtml)
el = self.marionette.execute_script("return document.querySelector('[name=foo]')")
found = self.marionette.find_element(By.NAME, "foo")
self.assertIsInstance(found, HTMLElement)
self.assertEqual(el, found)
def test_css_selector(self):
self.marionette.navigate(children_xhtml)
el = self.marionette.execute_script("return document.querySelector('p')")
found = self.marionette.find_element(By.CSS_SELECTOR, "p")
self.assertIsInstance(found, HTMLElement)
self.assertEqual(el, found)
def test_link_text(self):
self.marionette.navigate(link_xhtml)
el = self.marionette.execute_script("return document.querySelector('a')")
found = self.marionette.find_element(By.LINK_TEXT, "foo bar")
self.assertIsInstance(found, HTMLElement)
self.assertEqual(el, found)
def test_partial_link_text(self):
self.marionette.navigate(link_xhtml)
el = self.marionette.execute_script("return document.querySelector('a')")
found = self.marionette.find_element(By.PARTIAL_LINK_TEXT, "foo")
self.assertIsInstance(found, HTMLElement)
self.assertEqual(el, found)
def test_xpath(self):
self.marionette.navigate(id_xhtml)
el = self.marionette.execute_script("return document.querySelector('#foo')")
found = self.marionette.find_element(By.XPATH, "id('foo')")
self.assertIsInstance(found, HTMLElement)
self.assertEqual(el, found)
def test_css_selector_scope_does_not_start_at_rootnode(self):
self.marionette.navigate(parent_child_xhtml)
el = self.marionette.find_element(By.ID, "child")
parent = self.marionette.find_element(By.ID, "parent")
found = parent.find_element(By.CSS_SELECTOR, "p")
self.assertEqual(el, found)
def test_active_element(self):
self.marionette.navigate(id_xhtml)
active = self.marionette.execute_script("return document.activeElement")
self.assertEqual(active, self.marionette.get_active_element())
class TestFindElementsHTML(MarionetteTestCase):
def setUp(self):
MarionetteTestCase.setUp(self)
self.marionette.set_search_timeout(0)
def assertItemsIsInstance(self, items, typ):
for item in items:
self.assertIsInstance(item, typ)
def test_child_elements(self):
self.marionette.navigate(children_html)
parent = self.marionette.find_element(By.TAG_NAME, "div")
children = self.marionette.find_elements(By.TAG_NAME, "p")
found = parent.find_elements(By.TAG_NAME, "p")
self.assertItemsIsInstance(found, HTMLElement)
self.assertSequenceEqual(found, children)
def test_tag_name(self):
self.marionette.navigate(children_html)
els = self.marionette.execute_script("return document.querySelectorAll('p')")
found = self.marionette.find_elements(By.TAG_NAME, "p")
self.assertItemsIsInstance(found, HTMLElement)
self.assertSequenceEqual(els, found)
def test_class_name(self):
self.marionette.navigate(class_html)
els = self.marionette.execute_script("return document.querySelectorAll('.foo')")
found = self.marionette.find_elements(By.CLASS_NAME, "foo")
self.assertItemsIsInstance(found, HTMLElement)
self.assertSequenceEqual(els, found)
def test_by_name(self):
self.marionette.navigate(name_html)
els = self.marionette.execute_script("return document.querySelectorAll('[name=foo]')")
found = self.marionette.find_elements(By.NAME, "foo")
self.assertItemsIsInstance(found, HTMLElement)
self.assertSequenceEqual(els, found)
def test_css_selector(self):
self.marionette.navigate(children_html)
els = self.marionette.execute_script("return document.querySelectorAll('p')")
found = self.marionette.find_elements(By.CSS_SELECTOR, "p")
self.assertItemsIsInstance(found, HTMLElement)
self.assertSequenceEqual(els, found)
def test_invalid_css_selector_should_throw(self):
with self.assertRaises(InvalidSelectorException):
self.marionette.find_elements(By.CSS_SELECTOR, "#")
def test_link_text(self):
self.marionette.navigate(link_html)
els = self.marionette.execute_script("return document.querySelectorAll('a')")
found = self.marionette.find_elements(By.LINK_TEXT, "foo bar")
self.assertItemsIsInstance(found, HTMLElement)
self.assertSequenceEqual(els, found)
def test_partial_link_text(self):
self.marionette.navigate(link_html)
els = self.marionette.execute_script("return document.querySelectorAll('a')")
found = self.marionette.find_elements(By.PARTIAL_LINK_TEXT, "foo")
self.assertItemsIsInstance(found, HTMLElement)
self.assertSequenceEqual(els, found)
def test_xpath(self):
self.marionette.navigate(children_html)
els = self.marionette.execute_script("return document.querySelectorAll('p')")
found = self.marionette.find_elements(By.XPATH, ".//p")
self.assertItemsIsInstance(found, HTMLElement)
self.assertSequenceEqual(els, found)
def test_css_selector_scope_doesnt_start_at_rootnode(self):
self.marionette.navigate(parent_child_html)
els = self.marionette.find_elements(By.ID, "child")
parent = self.marionette.find_element(By.ID, "parent")
found = parent.find_elements(By.CSS_SELECTOR, "p")
self.assertSequenceEqual(els, found)
def test_unknown_selector(self):
with self.assertRaises(InvalidSelectorException):
self.marionette.find_element("foo", "bar")
def test_element_id_is_valid_uuid(self):
self.marionette.navigate(id_html)
els = self.marionette.find_elements(By.TAG_NAME, "p")
uuid_regex = re.compile('^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$')
self.assertIsNotNone(re.search(uuid_regex, els[0].id),
'UUID for the WebElement is not valid. ID is {}'\
.format(els[0].id))
def test_invalid_xpath_selector(self):
with self.assertRaises(InvalidSelectorException):
self.marionette.find_elements(By.XPATH, "count(//input)")
with self.assertRaises(InvalidSelectorException):
parent = self.marionette.execute_script("return document.documentElement")
parent.find_elements(By.XPATH, "count(//input)")
def test_invalid_css_selector(self):
with self.assertRaises(InvalidSelectorException):
self.marionette.find_elements(By.CSS_SELECTOR, "")
with self.assertRaises(InvalidSelectorException):
parent = self.marionette.execute_script("return document.documentElement")
parent.find_elements(By.CSS_SELECTOR, "")
class TestFindElementsXHTML(MarionetteTestCase):
def setUp(self):
MarionetteTestCase.setUp(self)
self.marionette.set_search_timeout(0)
def assertItemsIsInstance(self, items, typ):
for item in items:
self.assertIsInstance(item, typ)
def test_child_elements(self):
self.marionette.navigate(children_xhtml)
parent = self.marionette.find_element(By.TAG_NAME, "div")
children = self.marionette.find_elements(By.TAG_NAME, "p")
found = parent.find_elements(By.TAG_NAME, "p")
self.assertItemsIsInstance(found, HTMLElement)
self.assertSequenceEqual(found, children)
def test_tag_name(self):
self.marionette.navigate(children_xhtml)
els = self.marionette.execute_script("return document.querySelectorAll('p')")
found = self.marionette.find_elements(By.TAG_NAME, "p")
self.assertItemsIsInstance(found, HTMLElement)
self.assertSequenceEqual(els, found)
def test_class_name(self):
self.marionette.navigate(class_xhtml)
els = self.marionette.execute_script("return document.querySelectorAll('.foo')")
found = self.marionette.find_elements(By.CLASS_NAME, "foo")
self.assertItemsIsInstance(found, HTMLElement)
self.assertSequenceEqual(els, found)
def test_by_name(self):
self.marionette.navigate(name_xhtml)
els = self.marionette.execute_script("return document.querySelectorAll('[name=foo]')")
found = self.marionette.find_elements(By.NAME, "foo")
self.assertItemsIsInstance(found, HTMLElement)
self.assertSequenceEqual(els, found)
def test_css_selector(self):
self.marionette.navigate(children_xhtml)
els = self.marionette.execute_script("return document.querySelectorAll('p')")
found = self.marionette.find_elements(By.CSS_SELECTOR, "p")
self.assertItemsIsInstance(found, HTMLElement)
self.assertSequenceEqual(els, found)
def test_link_text(self):
self.marionette.navigate(link_xhtml)
els = self.marionette.execute_script("return document.querySelectorAll('a')")
found = self.marionette.find_elements(By.LINK_TEXT, "foo bar")
self.assertItemsIsInstance(found, HTMLElement)
self.assertSequenceEqual(els, found)
def test_partial_link_text(self):
self.marionette.navigate(link_xhtml)
els = self.marionette.execute_script("return document.querySelectorAll('a')")
found = self.marionette.find_elements(By.PARTIAL_LINK_TEXT, "foo")
self.assertItemsIsInstance(found, HTMLElement)
self.assertSequenceEqual(els, found)
@skip("XHTML namespace not yet supported")
def test_xpath(self):
self.marionette.navigate(children_xhtml)
els = self.marionette.execute_script("return document.querySelectorAll('p')")
found = self.marionette.find_elements(By.XPATH, "//xhtml:p")
self.assertItemsIsInstance(found, HTMLElement)
self.assertSequenceEqual(els, found)
def test_css_selector_scope_doesnt_start_at_rootnode(self):
self.marionette.navigate(parent_child_xhtml)
els = self.marionette.find_elements(By.ID, "child")
parent = self.marionette.find_element(By.ID, "parent")
found = parent.find_elements(By.CSS_SELECTOR, "p")
self.assertSequenceEqual(els, found)

View File

@ -1,209 +0,0 @@
# 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/.
import re
from marionette import MarionetteTestCase
from marionette_driver.marionette import HTMLElement
from marionette_driver.by import By
from marionette_driver.errors import NoSuchElementException, InvalidSelectorException
class TestElements(MarionetteTestCase):
def setUp(self):
MarionetteTestCase.setUp(self)
self.marionette.set_search_timeout(0)
url = self.marionette.absolute_url("test.html")
self.marionette.navigate(url)
def test_id(self):
el = self.marionette.execute_script("return window.document.getElementById('mozLink');")
found_el = self.marionette.find_element(By.ID, "mozLink")
self.assertEqual(HTMLElement, type(found_el))
self.assertEqual(el, found_el)
def test_child_element(self):
el = self.marionette.find_element(By.ID, "divLink")
div = self.marionette.find_element(By.ID, "testDiv")
found_el = div.find_element(By.TAG_NAME, "a")
self.assertEqual("a", found_el.tag_name)
self.assertEqual(HTMLElement, type(found_el))
self.assertEqual(el, found_el)
def test_child_elements(self):
el = self.marionette.find_element(By.ID, "divLink2")
div = self.marionette.find_element(By.ID, "testDiv")
found_els = div.find_elements(By.TAG_NAME, "a")
self.assertTrue(el.id in [found_el.id for found_el in found_els])
def test_tag_name(self):
el = self.marionette.execute_script("return window.document.getElementsByTagName('body')[0];")
found_el = self.marionette.find_element(By.TAG_NAME, "body")
self.assertEqual('body', found_el.tag_name)
self.assertEqual(HTMLElement, type(found_el))
self.assertEqual(el, found_el)
found_el = self.marionette.find_elements(By.TAG_NAME, "body")[0]
self.assertEqual('body', found_el.tag_name)
self.assertEqual(HTMLElement, type(found_el))
self.assertEqual(el, found_el)
def test_class_name(self):
el = self.marionette.execute_script("return window.document.getElementsByClassName('linkClass')[0];")
found_el = self.marionette.find_element(By.CLASS_NAME, "linkClass")
self.assertEqual(HTMLElement, type(found_el))
self.assertEqual(el, found_el)
found_el = self.marionette.find_elements(By.CLASS_NAME, "linkClass")[0]
self.assertEqual(HTMLElement, type(found_el))
self.assertEqual(el, found_el)
def test_by_name(self):
el = self.marionette.execute_script("return window.document.getElementsByName('myInput')[0];")
found_el = self.marionette.find_element(By.NAME, "myInput")
self.assertEqual(HTMLElement, type(found_el))
self.assertEqual(el, found_el)
found_el = self.marionette.find_elements(By.NAME, "myInput")[0]
self.assertEqual(HTMLElement, type(found_el))
self.assertEqual(el, found_el)
def test_css_selector(self):
el = self.marionette.execute_script("return window.document.getElementById('testh1');")
found_el = self.marionette.find_element(By.CSS_SELECTOR, "h1")
self.assertEqual(HTMLElement, type(found_el))
self.assertEqual(el, found_el)
found_el = self.marionette.find_elements(By.CSS_SELECTOR, "h1")[0]
self.assertEqual(HTMLElement, type(found_el))
self.assertEqual(el, found_el)
def test_invalid_css_selector_should_throw(self):
with self.assertRaises(InvalidSelectorException):
self.marionette.find_element(By.CSS_SELECTOR, "#")
def test_link_text(self):
el = self.marionette.execute_script("return window.document.getElementById('mozLink');")
found_el = self.marionette.find_element(By.LINK_TEXT, "Click me!")
self.assertEqual(HTMLElement, type(found_el))
self.assertEqual(el, found_el)
found_el = self.marionette.find_elements(By.LINK_TEXT, "Click me!")[0]
self.assertEqual(HTMLElement, type(found_el))
self.assertEqual(el, found_el)
def test_partial_link_text(self):
el = self.marionette.execute_script("return window.document.getElementById('mozLink');")
found_el = self.marionette.find_element(By.PARTIAL_LINK_TEXT, "Click m")
self.assertEqual(HTMLElement, type(found_el))
self.assertEqual(el, found_el)
found_el = self.marionette.find_elements(By.PARTIAL_LINK_TEXT, "Click m")[0]
self.assertEqual(HTMLElement, type(found_el))
self.assertEqual(el, found_el)
def test_xpath(self):
el = self.marionette.execute_script("return window.document.getElementById('mozLink');")
found_el = self.marionette.find_element(By.XPATH, "id('mozLink')")
self.assertEqual(HTMLElement, type(found_el))
self.assertEqual(el, found_el)
found_el = self.marionette.find_elements(By.XPATH, "id('mozLink')")[0]
self.assertEqual(HTMLElement, type(found_el))
self.assertEqual(el, found_el)
def test_not_found(self):
self.marionette.set_search_timeout(0)
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.CLASS_NAME, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.CSS_SELECTOR, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.ID, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.LINK_TEXT, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.NAME, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.PARTIAL_LINK_TEXT, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.TAG_NAME, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.XPATH, "cheese")
def test_not_found_implicit_wait(self):
self.marionette.set_search_timeout(50)
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.CLASS_NAME, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.CSS_SELECTOR, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.ID, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.LINK_TEXT, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.NAME, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.PARTIAL_LINK_TEXT, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.TAG_NAME, "cheese")
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.XPATH, "cheese")
def test_timeout_element(self):
button = self.marionette.find_element(By.ID, "createDivButton")
button.click()
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.ID, "newDiv")
self.assertTrue(True, self.marionette.set_search_timeout(8000))
self.assertEqual(HTMLElement, type(self.marionette.find_element(By.ID, "newDiv")))
def test_timeout_elements(self):
button = self.marionette.find_element(By.ID, "createDivButton")
button.click()
self.assertEqual(len(self.marionette.find_elements(By.ID, "newDiv")), 0)
self.assertTrue(True, self.marionette.set_search_timeout(8000))
self.assertEqual(len(self.marionette.find_elements(By.ID, "newDiv")), 1)
def test_css_selector_scope_doesnt_start_at_rootnode(self):
el = self.marionette.find_element(By.ID, "mozLink")
nav_el = self.marionette.find_element(By.ID, "testDiv")
found_els = nav_el.find_elements(By.CSS_SELECTOR, "a")
self.assertFalse(el.id in [found_el.id for found_el in found_els])
def test_finding_active_element_returns_element(self):
body = self.marionette.find_element(By.TAG_NAME, "body")
self.assertEqual(body, self.marionette.get_active_element())
def test_unknown_selector(self):
with self.assertRaises(InvalidSelectorException):
self.marionette.find_element("foo", "bar")
def test_element_id_is_valid_uuid(self):
el = self.marionette.find_element(By.TAG_NAME, "body")
uuid_regex = re.compile('^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$')
self.assertIsNotNone(re.search(uuid_regex, el.id),
'UUID for the WebElement is not valid. ID is {}'\
.format(el.id))
def test_should_find_elements_by_link_text(self):
url = self.marionette.absolute_url("nestedElements.html")
self.marionette.navigate(url)
element = self.marionette.find_element(By.NAME, "div1")
children = element.find_elements(By.LINK_TEXT, "hello world")
self.assertEqual(len(children), 2)
self.assertEqual("link1", children[0].get_attribute("name"))
self.assertEqual("link2", children[1].get_attribute("name"))
def test_should_throw_invalidselectorexception_when_invalid_xPath_in_driver_find_element(self):
url = self.marionette.absolute_url("formPage.html")
self.marionette.navigate(url)
self.assertRaises(InvalidSelectorException, self.marionette.find_element, By.XPATH, "count(//input)")
def test_should_throw_invalidselectorexception_when_invalid_xpath_in_driver_find_elements(self):
url = self.marionette.absolute_url("formPage.html")
self.marionette.navigate(url)
self.assertRaises(InvalidSelectorException, self.marionette.find_elements, By.XPATH, "count(//input)")
def test_should_throw_invalidselectorexception_when_invalid_xpath_in_element_find_element(self):
url = self.marionette.absolute_url("formPage.html")
self.marionette.navigate(url)
body = self.marionette.find_element(By.TAG_NAME, "body")
self.assertRaises(InvalidSelectorException, body.find_element, By.XPATH, "count(//input)")
def test_should_throw_invalidselectorexception_when_invalid_xpath_in_element_find_elements(self):
url = self.marionette.absolute_url("formPage.html")
self.marionette.navigate(url)
body = self.marionette.find_element(By.TAG_NAME, "body")
self.assertRaises(InvalidSelectorException, body.find_elements, By.XPATH, "count(//input)")
def test_should_throw_invalidselectorexception_when_css_is_empty_in_driver_find_element(self):
self.assertRaises(InvalidSelectorException, self.marionette.find_element, By.CSS_SELECTOR, "")
def test_should_throw_invalidselectorexception_when_css_is_empty_in_driver_find_elements(self):
self.assertRaises(InvalidSelectorException, self.marionette.find_elements, By.CSS_SELECTOR, "")
def test_should_throw_invalidselectorexception_when_css_is_empty_in_element_find_element(self):
body = self.marionette.find_element(By.TAG_NAME, "body")
self.assertRaises(InvalidSelectorException, body.find_element, By.CSS_SELECTOR, "")
def test_should_throw_invalidselectorexception_when_css_is_empty_in_element_find_elements(self):
body = self.marionette.find_element(By.TAG_NAME, "body")
self.assertRaises(InvalidSelectorException, body.find_elements, By.CSS_SELECTOR, "")

View File

@ -39,7 +39,7 @@ skip-if = buildapp == 'b2g'
[test_execute_async_script.py]
[test_execute_script.py]
[test_simpletest_fail.js]
[test_findelement.py]
[test_element_retrieval.py]
[test_findelement_chrome.py]
skip-if = buildapp == 'b2g'

View File

@ -1,8 +0,0 @@
[label.html]
type: testharness
[TextTrack.label]
expected: FAIL
[TextTrack.label, \\u0000]
expected: FAIL

View File

@ -1,8 +0,0 @@
[language.html]
type: testharness
[TextTrack.language]
expected: FAIL
[TextTrack.language, \\u0000]
expected: FAIL

View File

@ -44,16 +44,17 @@ AndroidContentController::NotifyDefaultPrevented(APZCTreeManager* aManager,
}
void
AndroidContentController::HandleSingleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid)
AndroidContentController::HandleTap(TapType aType, const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId)
{
// This function will get invoked first on the Java UI thread, and then
// again on the main thread (because of the code in ChromeProcessController::
// HandleSingleTap). We want to post the SingleTap message once; it can be
// HandleTap). We want to post the SingleTap message once; it can be
// done from either thread but we need access to the callback transform
// so we do it from the main thread.
if (NS_IsMainThread()) {
if (NS_IsMainThread() && aType == TapType::eSingleTap) {
CSSPoint point = mozilla::layers::APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid);
nsIContent* content = nsLayoutUtils::FindContentFor(aGuid.mScrollId);
@ -83,7 +84,7 @@ AndroidContentController::HandleSingleTap(const CSSPoint& aPoint,
});
}
ChromeProcessController::HandleSingleTap(aPoint, aModifiers, aGuid);
ChromeProcessController::HandleTap(aType, aPoint, aModifiers, aGuid, aInputBlockId);
}
void

View File

@ -34,9 +34,8 @@ public:
// ChromeProcessController methods
virtual void Destroy() override;
void HandleSingleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid) override;
void HandleTap(TapType aType, const CSSPoint& aPoint, Modifiers aModifiers,
const ScrollableLayerGuid& aGuid, uint64_t aInputBlockId) override;
void PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs) override;
void UpdateOverscrollVelocity(const float aX, const float aY) override;
void UpdateOverscrollOffset(const float aX, const float aY) override;

View File

@ -5144,6 +5144,14 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
case WM_CONTEXTMENU:
{
// If the context menu is brought up by a touch long-press, then
// the APZ code is responsble for dealing with this, so we don't
// need to do anything.
if (mAPZC && MOUSE_INPUT_SOURCE() == nsIDOMMouseEvent::MOZ_SOURCE_TOUCH) {
result = true;
break;
}
// if the context menu is brought up from the keyboard, |lParam|
// will be -1.
LPARAM pos;

View File

@ -513,11 +513,11 @@ CycleCollectedJSRuntime::Initialize(JSRuntime* aParentRuntime,
}
mJSContext = JS_GetContext(mJSRuntime);
if (!JS_AddExtraGCRootsTracer(mJSRuntime, TraceBlackJS, this)) {
if (!JS_AddExtraGCRootsTracer(mJSContext, TraceBlackJS, this)) {
MOZ_CRASH("JS_AddExtraGCRootsTracer failed");
}
JS_SetGrayGCRootsTracer(mJSRuntime, TraceGrayJS, this);
JS_SetGCCallback(mJSRuntime, GCCallback, this);
JS_SetGrayGCRootsTracer(mJSContext, TraceGrayJS, this);
JS_SetGCCallback(mJSContext, GCCallback, this);
mPrevGCSliceCallback = JS::SetGCSliceCallback(mJSRuntime, GCSliceCallback);
if (NS_IsMainThread()) {
@ -532,9 +532,9 @@ CycleCollectedJSRuntime::Initialize(JSRuntime* aParentRuntime,
mJSRuntime, GCNurseryCollectionCallback);
}
JS_SetObjectsTenuredCallback(mJSRuntime, JSObjectsTenuredCb, this);
JS::SetOutOfMemoryCallback(mJSRuntime, OutOfMemoryCallback, this);
JS::SetLargeAllocationFailureCallback(mJSRuntime,
JS_SetObjectsTenuredCallback(mJSContext, JSObjectsTenuredCb, this);
JS::SetOutOfMemoryCallback(mJSContext, OutOfMemoryCallback, this);
JS::SetLargeAllocationFailureCallback(mJSContext,
LargeAllocationFailureCallback, this);
JS_SetDestroyZoneCallback(mJSContext, XPCStringConvert::FreeZoneCache);
JS_SetSweepZoneCallback(mJSContext, XPCStringConvert::ClearZoneCache);
@ -544,7 +544,7 @@ CycleCollectedJSRuntime::Initialize(JSRuntime* aParentRuntime,
static js::DOMCallbacks DOMcallbacks = {
InstanceClassHasProtoAtDepth
};
SetDOMCallbacks(mJSRuntime, &DOMcallbacks);
SetDOMCallbacks(mJSContext, &DOMcallbacks);
js::SetScriptEnvironmentPreparer(mJSRuntime, &mEnvironmentPreparer);
JS::SetGetIncumbentGlobalCallback(mJSRuntime, GetIncumbentGlobalCallback);
@ -975,7 +975,7 @@ CycleCollectedJSRuntime::EnqueuePromiseJobCallback(JSContext* aCx,
global = xpc::NativeGlobal(aIncumbentGlobal);
}
nsCOMPtr<nsIRunnable> runnable = new PromiseJobRunnable(aJob, aAllocationSite, global);
self->DispatchToMicroTask(runnable);
self->DispatchToMicroTask(runnable.forget());
return true;
}
@ -1680,12 +1680,14 @@ CycleCollectedJSRuntime::PrepareWaitingZonesForGC()
}
void
CycleCollectedJSRuntime::DispatchToMicroTask(nsIRunnable* aRunnable)
CycleCollectedJSRuntime::DispatchToMicroTask(already_AddRefed<nsIRunnable> aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aRunnable);
RefPtr<nsIRunnable> runnable(aRunnable);
mPromiseMicroTaskQueue.push(aRunnable);
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(runnable);
mPromiseMicroTaskQueue.push(runnable.forget());
}
void

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