mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-20 00:35:44 +00:00
Merge autoland to mozilla-central. a=merge
This commit is contained in:
commit
d503a7df4f
@ -86,7 +86,6 @@ const whitelist = {
|
||||
"data:,ChromeUtils.import('resource://gre/modules/ExtensionProcessScript.jsm')",
|
||||
"resource://devtools/client/jsonview/converter-observer.js",
|
||||
"resource://gre/modules/WebRequestContent.js",
|
||||
"resource://webcompat/aboutPageProcessScript.js",
|
||||
]),
|
||||
};
|
||||
|
||||
@ -98,11 +97,16 @@ const intermittently_loaded_whitelist = {
|
||||
"resource://gre/modules/nsAsyncShutdown.jsm",
|
||||
"resource://gre/modules/sessionstore/Utils.jsm",
|
||||
|
||||
// Webcompat about:config front-end
|
||||
// Webcompat about:config front-end. This is presently nightly-only and
|
||||
// part of a system add-on which may not load early enough for the test.
|
||||
"resource://webcompat/AboutCompat.jsm",
|
||||
]),
|
||||
frameScripts: new Set([]),
|
||||
processScripts: new Set([]),
|
||||
processScripts: new Set([
|
||||
// Webcompat about:config front-end. This is presently nightly-only and
|
||||
// part of a system add-on which may not load early enough for the test.
|
||||
"resource://webcompat/aboutPageProcessScript.js",
|
||||
]),
|
||||
};
|
||||
|
||||
const blacklist = {
|
||||
|
@ -1,193 +0,0 @@
|
||||
Index: include/clang/Basic/BuiltinsAArch64.def
|
||||
===================================================================
|
||||
--- a/clang/include/clang/Basic/BuiltinsAArch64.def
|
||||
+++ b/clang/include/clang/Basic/BuiltinsAArch64.def
|
||||
@@ -203,8 +203,8 @@
|
||||
|
||||
TARGET_HEADER_BUILTIN(_ReadWriteBarrier, "v", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(__getReg, "ULLii", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
-TARGET_HEADER_BUILTIN(_ReadStatusReg, "ii", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
-TARGET_HEADER_BUILTIN(_WriteStatusReg, "vii", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
+TARGET_HEADER_BUILTIN(_ReadStatusReg, "LLii", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
+TARGET_HEADER_BUILTIN(_WriteStatusReg, "viLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_AddressOfReturnAddress, "v*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
|
||||
#undef BUILTIN
|
||||
Index: lib/CodeGen/CGBuiltin.cpp
|
||||
===================================================================
|
||||
--- a/clang/lib/CodeGen/CGBuiltin.cpp
|
||||
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
|
||||
@@ -7062,19 +7062,16 @@
|
||||
llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName);
|
||||
|
||||
llvm::Type *RegisterType = Int64Ty;
|
||||
- llvm::Type *ValueType = Int32Ty;
|
||||
llvm::Type *Types[] = { RegisterType };
|
||||
|
||||
if (BuiltinID == AArch64::BI_ReadStatusReg) {
|
||||
llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::read_register, Types);
|
||||
- llvm::Value *Call = Builder.CreateCall(F, Metadata);
|
||||
|
||||
- return Builder.CreateTrunc(Call, ValueType);
|
||||
+ return Builder.CreateCall(F, Metadata);
|
||||
}
|
||||
|
||||
llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::write_register, Types);
|
||||
llvm::Value *ArgValue = EmitScalarExpr(E->getArg(1));
|
||||
- ArgValue = Builder.CreateZExt(ArgValue, RegisterType);
|
||||
|
||||
return Builder.CreateCall(F, { Metadata, ArgValue });
|
||||
}
|
||||
Index: lib/Headers/intrin.h
|
||||
===================================================================
|
||||
--- a/clang/lib/Headers/intrin.h
|
||||
+++ b/clang/lib/Headers/intrin.h
|
||||
@@ -554,8 +554,8 @@
|
||||
#if defined(__aarch64__)
|
||||
unsigned __int64 __getReg(int);
|
||||
long _InterlockedAdd(long volatile *Addend, long Value);
|
||||
-int _ReadStatusReg(int);
|
||||
-void _WriteStatusReg(int, int);
|
||||
+__int64 _ReadStatusReg(int);
|
||||
+void _WriteStatusReg(int, __int64);
|
||||
|
||||
static inline unsigned short _byteswap_ushort (unsigned short val) {
|
||||
return __builtin_bswap16(val);
|
||||
Index: test/CodeGen/arm64-microsoft-status-reg.cpp
|
||||
===================================================================
|
||||
--- a/clang/test/CodeGen/arm64-microsoft-status-reg.cpp
|
||||
+++ b/clang/test/CodeGen/arm64-microsoft-status-reg.cpp
|
||||
@@ -23,87 +23,101 @@
|
||||
#define ARM64_TPIDRRO_EL0 ARM64_SYSREG(3,3,13, 0,3) // Thread ID Register, User Read Only [CP15_TPIDRURO]
|
||||
#define ARM64_TPIDR_EL1 ARM64_SYSREG(3,0,13, 0,4) // Thread ID Register, Privileged Only [CP15_TPIDRPRW]
|
||||
|
||||
-void check_ReadWriteStatusReg(int v) {
|
||||
- int ret;
|
||||
+// From intrin.h
|
||||
+__int64 _ReadStatusReg(int);
|
||||
+void _WriteStatusReg(int, __int64);
|
||||
+
|
||||
+void check_ReadWriteStatusReg(__int64 v) {
|
||||
+ __int64 ret;
|
||||
ret = _ReadStatusReg(ARM64_CNTVCT);
|
||||
-// CHECK-ASM: mrs x8, CNTVCT_EL0
|
||||
-// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD2:.*]])
|
||||
+// CHECK-ASM: mrs x0, CNTVCT_EL0
|
||||
+// CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2:.*]])
|
||||
+// CHECK-IR-NEXT: store i64 %[[VAR]]
|
||||
|
||||
ret = _ReadStatusReg(ARM64_PMCCNTR_EL0);
|
||||
-// CHECK-ASM: mrs x8, PMCCNTR_EL0
|
||||
-// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD3:.*]])
|
||||
+// CHECK-ASM: mrs x0, PMCCNTR_EL0
|
||||
+// CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD3:.*]])
|
||||
+// CHECK-IR-NEXT: store i64 %[[VAR]]
|
||||
|
||||
ret = _ReadStatusReg(ARM64_PMSELR_EL0);
|
||||
-// CHECK-ASM: mrs x8, PMSELR_EL0
|
||||
-// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD4:.*]])
|
||||
+// CHECK-ASM: mrs x0, PMSELR_EL0
|
||||
+// CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD4:.*]])
|
||||
+// CHECK-IR-NEXT: store i64 %[[VAR]]
|
||||
|
||||
ret = _ReadStatusReg(ARM64_PMXEVCNTR_EL0);
|
||||
-// CHECK-ASM: mrs x8, PMXEVCNTR_EL0
|
||||
-// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD5:.*]])
|
||||
+// CHECK-ASM: mrs x0, PMXEVCNTR_EL0
|
||||
+// CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD5:.*]])
|
||||
+// CHECK-IR-NEXT: store i64 %[[VAR]]
|
||||
|
||||
ret = _ReadStatusReg(ARM64_PMXEVCNTRn_EL0(0));
|
||||
-// CHECK-ASM: mrs x8, PMEVCNTR0_EL0
|
||||
-// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD6:.*]])
|
||||
+// CHECK-ASM: mrs x0, PMEVCNTR0_EL0
|
||||
+// CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD6:.*]])
|
||||
+// CHECK-IR-NEXT: store i64 %[[VAR]]
|
||||
|
||||
ret = _ReadStatusReg(ARM64_PMXEVCNTRn_EL0(1));
|
||||
-// CHECK-ASM: mrs x8, PMEVCNTR1_EL0
|
||||
-// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD7:.*]])
|
||||
+// CHECK-ASM: mrs x0, PMEVCNTR1_EL0
|
||||
+// CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD7:.*]])
|
||||
+// CHECK-IR-NEXT: store i64 %[[VAR]]
|
||||
|
||||
ret = _ReadStatusReg(ARM64_PMXEVCNTRn_EL0(30));
|
||||
-// CHECK-ASM: mrs x8, PMEVCNTR30_EL0
|
||||
-// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD8:.*]])
|
||||
+// CHECK-ASM: mrs x0, PMEVCNTR30_EL0
|
||||
+// CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD8:.*]])
|
||||
+// CHECK-IR-NEXT: store i64 %[[VAR]]
|
||||
|
||||
ret = _ReadStatusReg(ARM64_TPIDR_EL0);
|
||||
-// CHECK-ASM: mrs x8, TPIDR_EL0
|
||||
-// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD9:.*]])
|
||||
+// CHECK-ASM: mrs x0, TPIDR_EL0
|
||||
+// CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD9:.*]])
|
||||
+// CHECK-IR-NEXT: store i64 %[[VAR]]
|
||||
|
||||
ret = _ReadStatusReg(ARM64_TPIDRRO_EL0);
|
||||
-// CHECK-ASM: mrs x8, TPIDRRO_EL0
|
||||
-// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD10:.*]])
|
||||
+// CHECK-ASM: mrs x0, TPIDRRO_EL0
|
||||
+// CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD10:.*]])
|
||||
+// CHECK-IR-NEXT: store i64 %[[VAR]]
|
||||
|
||||
ret = _ReadStatusReg(ARM64_TPIDR_EL1);
|
||||
-// CHECK-ASM: mrs x8, TPIDR_EL1
|
||||
-// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD11:.*]])
|
||||
+// CHECK-ASM: mrs x0, TPIDR_EL1
|
||||
+// CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD11:.*]])
|
||||
+// CHECK-IR-NEXT: store i64 %[[VAR]]
|
||||
|
||||
|
||||
_WriteStatusReg(ARM64_CNTVCT, v);
|
||||
-// CHECK-ASM: msr S3_3_C14_C0_2, x8
|
||||
+// CHECK-ASM: msr S3_3_C14_C0_2, x0
|
||||
// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD2:.*]], i64 {{%.*}})
|
||||
|
||||
_WriteStatusReg(ARM64_PMCCNTR_EL0, v);
|
||||
-// CHECK-ASM: msr PMCCNTR_EL0, x8
|
||||
+// CHECK-ASM: msr PMCCNTR_EL0, x0
|
||||
// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD3:.*]], i64 {{%.*}})
|
||||
|
||||
_WriteStatusReg(ARM64_PMSELR_EL0, v);
|
||||
-// CHECK-ASM: msr PMSELR_EL0, x8
|
||||
+// CHECK-ASM: msr PMSELR_EL0, x0
|
||||
// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD4:.*]], i64 {{%.*}})
|
||||
|
||||
_WriteStatusReg(ARM64_PMXEVCNTR_EL0, v);
|
||||
-// CHECK-ASM: msr PMXEVCNTR_EL0, x8
|
||||
+// CHECK-ASM: msr PMXEVCNTR_EL0, x0
|
||||
// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD5:.*]], i64 {{%.*}})
|
||||
|
||||
_WriteStatusReg(ARM64_PMXEVCNTRn_EL0(0), v);
|
||||
-// CHECK-ASM: msr PMEVCNTR0_EL0, x8
|
||||
+// CHECK-ASM: msr PMEVCNTR0_EL0, x0
|
||||
// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD6:.*]], i64 {{%.*}})
|
||||
|
||||
_WriteStatusReg(ARM64_PMXEVCNTRn_EL0(1), v);
|
||||
-// CHECK-ASM: msr PMEVCNTR1_EL0, x8
|
||||
+// CHECK-ASM: msr PMEVCNTR1_EL0, x0
|
||||
// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD7:.*]], i64 {{%.*}})
|
||||
|
||||
_WriteStatusReg(ARM64_PMXEVCNTRn_EL0(30), v);
|
||||
-// CHECK-ASM: msr PMEVCNTR30_EL0, x8
|
||||
+// CHECK-ASM: msr PMEVCNTR30_EL0, x0
|
||||
// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD8:.*]], i64 {{%.*}})
|
||||
|
||||
_WriteStatusReg(ARM64_TPIDR_EL0, v);
|
||||
-// CHECK-ASM: msr TPIDR_EL0, x8
|
||||
+// CHECK-ASM: msr TPIDR_EL0, x0
|
||||
// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD9:.*]], i64 {{%.*}})
|
||||
|
||||
_WriteStatusReg(ARM64_TPIDRRO_EL0, v);
|
||||
-// CHECK-ASM: msr TPIDRRO_EL0, x8
|
||||
+// CHECK-ASM: msr TPIDRRO_EL0, x0
|
||||
// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD10:.*]], i64 {{%.*}})
|
||||
|
||||
_WriteStatusReg(ARM64_TPIDR_EL1, v);
|
||||
-// CHECK-ASM: msr TPIDR_EL1, x8
|
||||
+// CHECK-ASM: msr TPIDR_EL1, x0
|
||||
// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD11:.*]], i64 {{%.*}})
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
{
|
||||
"llvm_revision": "353414",
|
||||
"llvm_revision": "355016",
|
||||
"stages": "3",
|
||||
"build_libcxx": false,
|
||||
"build_type": "Release",
|
||||
"assertions": false,
|
||||
"llvm_repo": "https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_800/rc2",
|
||||
"clang_repo": "https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_800/rc2",
|
||||
"lld_repo": "https://llvm.org/svn/llvm-project/lld/tags/RELEASE_800/rc2",
|
||||
"compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/tags/RELEASE_800/rc2",
|
||||
"libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_800/rc2",
|
||||
"llvm_repo": "https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_800/rc3",
|
||||
"clang_repo": "https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_800/rc3",
|
||||
"lld_repo": "https://llvm.org/svn/llvm-project/lld/tags/RELEASE_800/rc3",
|
||||
"compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/tags/RELEASE_800/rc3",
|
||||
"libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_800/rc3",
|
||||
"python_path": "c:/mozilla-build/python/python.exe",
|
||||
"cc": "cl.exe",
|
||||
"cxx": "cl.exe",
|
||||
@ -17,7 +17,6 @@
|
||||
"workaround-issue38586.patch",
|
||||
"unpoison-thread-stacks.patch",
|
||||
"downgrade-mangling-error.patch",
|
||||
"loosen-msvc-detection.patch",
|
||||
"D57636.diff"
|
||||
"loosen-msvc-detection.patch"
|
||||
]
|
||||
}
|
||||
|
@ -7500,20 +7500,17 @@ void nsContentUtils::TransferableToIPCTransferable(
|
||||
} else if (nsCOMPtr<nsISupportsCString> ctext = do_QueryInterface(data)) {
|
||||
nsAutoCString dataAsString;
|
||||
ctext->GetData(dataAsString);
|
||||
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
||||
item->flavor() = flavorStr;
|
||||
|
||||
Shmem dataAsShmem = ConvertToShmem(aChild, aParent, dataAsString);
|
||||
if (!dataAsShmem.IsReadable() || !dataAsShmem.Size<char>()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
||||
item->flavor() = flavorStr;
|
||||
item->data() = dataAsShmem;
|
||||
} else if (nsCOMPtr<nsIInputStream> stream = do_QueryInterface(data)) {
|
||||
// Images to be pasted on the clipboard are nsIInputStreams
|
||||
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
||||
item->flavor() = flavorStr;
|
||||
|
||||
nsCString imageData;
|
||||
NS_ConsumeStream(stream, UINT32_MAX, imageData);
|
||||
|
||||
@ -7522,6 +7519,8 @@ void nsContentUtils::TransferableToIPCTransferable(
|
||||
continue;
|
||||
}
|
||||
|
||||
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
||||
item->flavor() = flavorStr;
|
||||
item->data() = imageDataShmem;
|
||||
} else if (nsCOMPtr<imgIContainer> image = do_QueryInterface(data)) {
|
||||
// Images to be placed on the clipboard are imgIContainers.
|
||||
@ -7570,13 +7569,17 @@ void nsContentUtils::TransferableToIPCTransferable(
|
||||
if (aInSyncMessage) {
|
||||
nsAutoCString type;
|
||||
if (IsFileImage(file, type)) {
|
||||
IPCDataTransferItem* item =
|
||||
aIPCDataTransfer->items().AppendElement();
|
||||
item->flavor() = type;
|
||||
nsAutoCString data;
|
||||
SlurpFileToString(file, data);
|
||||
|
||||
Shmem dataAsShmem = ConvertToShmem(aChild, aParent, data);
|
||||
if (!dataAsShmem.IsReadable() || !dataAsShmem.Size<char>()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IPCDataTransferItem* item =
|
||||
aIPCDataTransfer->items().AppendElement();
|
||||
item->flavor() = type;
|
||||
item->data() = dataAsShmem;
|
||||
}
|
||||
|
||||
|
@ -409,10 +409,6 @@ Index::Index(const IndiceWrapper& aIndices, ByteStream* aSource,
|
||||
if (!haveSync) {
|
||||
continue;
|
||||
}
|
||||
if (indice.start_composition == indice.end_composition) {
|
||||
// Ignore this sample as it doesn't account for the buffered range.
|
||||
continue;
|
||||
}
|
||||
Sample sample;
|
||||
sample.mByteRange =
|
||||
MediaByteRange(indice.start_offset, indice.end_offset);
|
||||
@ -561,9 +557,11 @@ TimeIntervals Index::ConvertByteRangesToTimeRanges(
|
||||
}
|
||||
}
|
||||
if (end > start) {
|
||||
timeRanges += TimeInterval(
|
||||
TimeUnit::FromMicroseconds(mDataOffset[start].mTime.start),
|
||||
TimeUnit::FromMicroseconds(mDataOffset[end - 1].mTime.end));
|
||||
for (uint32_t i = start; i < end; i++) {
|
||||
timeRanges += TimeInterval(
|
||||
TimeUnit::FromMicroseconds(mDataOffset[i].mTime.start),
|
||||
TimeUnit::FromMicroseconds(mDataOffset[i].mTime.end));
|
||||
}
|
||||
}
|
||||
if (end < mDataOffset.Length()) {
|
||||
// Find samples in partial block contained in the byte range.
|
||||
|
@ -20,12 +20,12 @@
|
||||
#include "mozilla/layers/IAPZCTreeManager.h" // for IAPZCTreeManager
|
||||
#include "mozilla/layers/LayersTypes.h"
|
||||
#include "mozilla/layers/KeyboardMap.h" // for KeyboardMap
|
||||
#include "mozilla/layers/TouchCounter.h" // for TouchCounter
|
||||
#include "mozilla/RecursiveMutex.h" // for RecursiveMutex
|
||||
#include "mozilla/RefPtr.h" // for RefPtr
|
||||
#include "mozilla/TimeStamp.h" // for mozilla::TimeStamp
|
||||
#include "mozilla/UniquePtr.h" // for UniquePtr
|
||||
#include "nsCOMPtr.h" // for already_AddRefed
|
||||
#include "TouchCounter.h" // for TouchCounter
|
||||
|
||||
#if defined(MOZ_WIDGET_ANDROID)
|
||||
# include "mozilla/layers/AndroidDynamicToolbarAnimator.h"
|
||||
|
@ -14,9 +14,9 @@
|
||||
#include "mozilla/layers/APZUtils.h"
|
||||
#include "mozilla/layers/LayersTypes.h" // for TouchBehaviorFlags
|
||||
#include "mozilla/layers/AsyncDragMetrics.h"
|
||||
#include "mozilla/layers/TouchCounter.h"
|
||||
#include "mozilla/TimeStamp.h" // for TimeStamp
|
||||
#include "nsTArray.h" // for nsTArray
|
||||
#include "TouchCounter.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
@ -11,10 +11,10 @@
|
||||
#include "DragTracker.h"
|
||||
#include "InputData.h"
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "mozilla/layers/TouchCounter.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsTArray.h"
|
||||
#include "TouchCounter.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
81
gfx/layers/apz/test/mochitest/helper_zoom_prevented.html
Normal file
81
gfx/layers/apz/test/mochitest/helper_zoom_prevented.html
Normal file
@ -0,0 +1,81 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<title>Checking prevent-default for zooming</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
function* testPreventDefault(testDriver, aTouchStartToCancel) {
|
||||
var initial_resolution = getResolution();
|
||||
ok(initial_resolution > 0,
|
||||
"The initial_resolution is " + initial_resolution + ", which is some sane value");
|
||||
|
||||
// preventDefault exactly one touchstart based on the value of aTouchStartToCancel
|
||||
var touchStartCount = 0;
|
||||
var canceller = function(e) {
|
||||
dump("touchstart listener hit, count: " + touchStartCount + "\n");
|
||||
touchStartCount++;
|
||||
if (touchStartCount == aTouchStartToCancel) {
|
||||
dump("calling preventDefault on touchstart\n");
|
||||
e.preventDefault();
|
||||
document.documentElement.removeEventListener("touchstart", canceller, {passive: false});
|
||||
}
|
||||
};
|
||||
document.documentElement.addEventListener("touchstart", canceller, {passive: false});
|
||||
|
||||
var waitForTouchEnd = function(e) {
|
||||
dump("touchend listener hit\n");
|
||||
setTimeout(testDriver, 0);
|
||||
};
|
||||
document.documentElement.addEventListener("touchend", waitForTouchEnd, {passive: true, once: true});
|
||||
|
||||
// Ensure that APZ gets updated hit-test info
|
||||
yield waitForAllPaints(testDriver);
|
||||
|
||||
var zoom_in = [
|
||||
[ { x: 125, y: 250 }, { x: 175, y: 350 } ],
|
||||
[ { x: 120, y: 220 }, { x: 180, y: 380 } ],
|
||||
[ { x: 115, y: 190 }, { x: 185, y: 410 } ],
|
||||
[ { x: 110, y: 160 }, { x: 190, y: 440 } ],
|
||||
[ { x: 105, y: 130 }, { x: 195, y: 470 } ],
|
||||
[ { x: 100, y: 100 }, { x: 200, y: 500 } ],
|
||||
];
|
||||
|
||||
var touchIds = [0, 1];
|
||||
yield* synthesizeNativeTouchSequences(document.body, zoom_in, null, touchIds);
|
||||
|
||||
yield; // wait for the touchend listener to fire
|
||||
|
||||
// Flush state and get the resolution we're at now
|
||||
yield waitForApzFlushedRepaints(testDriver);
|
||||
let final_resolution = getResolution();
|
||||
is(final_resolution, initial_resolution, "The final resolution (" + final_resolution + ") matches the initial resolution");
|
||||
}
|
||||
|
||||
function* test(testDriver) {
|
||||
// Register a listener that fails the test if the APZ:TransformEnd event fires,
|
||||
// because this test shouldn't actually be triggering any transforms
|
||||
SpecialPowers.Services.obs.addObserver(function() {
|
||||
ok(false, "The test fired an unexpected APZ:TransformEnd");
|
||||
}, "APZ:TransformEnd");
|
||||
|
||||
yield* testPreventDefault(testDriver, 1);
|
||||
yield* testPreventDefault(testDriver, 2);
|
||||
}
|
||||
|
||||
waitUntilApzStable()
|
||||
.then(runContinuation(test))
|
||||
.then(subtestDone);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
Here is some text to stare at as the test runs. It serves no functional
|
||||
purpose, but gives you an idea of the zoom level. It's harder to tell what
|
||||
the zoom level is when the page is just solid white.
|
||||
</body>
|
||||
</html>
|
@ -32,6 +32,9 @@ var prefs = [
|
||||
// Pinch-zooming currently requires meta viewport support (this requirement
|
||||
// will eventually be removed).
|
||||
["dom.meta-viewport.enabled", true],
|
||||
// Increase the content response timeout because some tests do preventDefault
|
||||
// and we want to make sure APZ actually waits for them.
|
||||
["apz.content_response_timeout", 60000],
|
||||
];
|
||||
|
||||
// Increase the tap timeouts so the double-tap is still detected in case of
|
||||
@ -45,6 +48,7 @@ var doubletap_prefs = [
|
||||
var subtests = [
|
||||
{"file": "helper_bug1280013.html", "prefs": prefs},
|
||||
{"file": "helper_basic_zoom.html", "prefs": prefs},
|
||||
{"file": "helper_zoom_prevented.html", "prefs": prefs},
|
||||
{"file": "helper_zoomed_pan.html", "prefs": prefs},
|
||||
{"file": "helper_fixed_position_scroll_hittest.html", "prefs": prefs},
|
||||
{"file": "helper_basic_doubletap_zoom.html", "prefs": doubletap_prefs},
|
||||
|
@ -104,6 +104,7 @@ APZEventState::APZEventState(nsIWidget* aWidget,
|
||||
mPendingTouchPreventedResponse(false),
|
||||
mPendingTouchPreventedBlockId(0),
|
||||
mEndTouchIsClick(false),
|
||||
mFirstTouchCancelled(false),
|
||||
mTouchEndCancelled(false),
|
||||
mLastTouchIdentifier(0) {
|
||||
nsresult rv;
|
||||
@ -337,6 +338,22 @@ void APZEventState::ProcessTouchEvent(const WidgetTouchEvent& aEvent,
|
||||
// for events that went through APZ (which should be all of them).
|
||||
MOZ_ASSERT(aEvent.mFlags.mHandledByAPZ);
|
||||
|
||||
// If the first touchstart event was preventDefaulted, ensure that any
|
||||
// subsequent additional touchstart events also get preventDefaulted. This
|
||||
// ensures that e.g. pinch zooming is prevented even if just the first
|
||||
// touchstart was prevented by content.
|
||||
if (mTouchCounter.GetActiveTouchCount() == 0) {
|
||||
mFirstTouchCancelled = isTouchPrevented;
|
||||
} else {
|
||||
if (mFirstTouchCancelled && !isTouchPrevented) {
|
||||
APZES_LOG(
|
||||
"Propagating prevent-default from first-touch for block %" PRIu64
|
||||
"\n",
|
||||
aInputBlockId);
|
||||
}
|
||||
isTouchPrevented |= mFirstTouchCancelled;
|
||||
}
|
||||
|
||||
if (isTouchPrevented) {
|
||||
mContentReceivedInputBlockCallback(aGuid, aInputBlockId,
|
||||
isTouchPrevented);
|
||||
@ -373,6 +390,11 @@ void APZEventState::ProcessTouchEvent(const WidgetTouchEvent& aEvent,
|
||||
break;
|
||||
}
|
||||
|
||||
mTouchCounter.Update(aEvent);
|
||||
if (mTouchCounter.GetActiveTouchCount() == 0) {
|
||||
mFirstTouchCancelled = false;
|
||||
}
|
||||
|
||||
if (sentContentResponse && !isTouchPrevented &&
|
||||
aApzResponse == nsEventStatus_eConsumeDoDefault &&
|
||||
gfxPrefs::PointerEventsEnabled()) {
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "mozilla/layers/GeckoContentController.h" // for APZStateChange
|
||||
#include "mozilla/layers/ScrollableLayerGuid.h" // for ScrollableLayerGuid
|
||||
#include "mozilla/layers/TouchCounter.h" // for TouchCounter
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsISupportsImpl.h" // for NS_INLINE_DECL_REFCOUNTING
|
||||
@ -94,10 +95,12 @@ class APZEventState {
|
||||
nsWeakPtr mWidget;
|
||||
RefPtr<ActiveElementManager> mActiveElementManager;
|
||||
ContentReceivedInputBlockCallback mContentReceivedInputBlockCallback;
|
||||
TouchCounter mTouchCounter;
|
||||
bool mPendingTouchPreventedResponse;
|
||||
ScrollableLayerGuid mPendingTouchPreventedGuid;
|
||||
uint64_t mPendingTouchPreventedBlockId;
|
||||
bool mEndTouchIsClick;
|
||||
bool mFirstTouchCancelled;
|
||||
bool mTouchEndCancelled;
|
||||
int32_t mLastTouchIdentifier;
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "TouchCounter.h"
|
||||
|
||||
#include "InputData.h"
|
||||
#include "mozilla/TouchEvents.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
@ -24,7 +25,7 @@ void TouchCounter::Update(const MultiTouchInput& aInput) {
|
||||
// touch-end event contains only released touches
|
||||
mActiveTouchCount -= aInput.mTouches.Length();
|
||||
} else {
|
||||
NS_WARNING("Got an unexpected touchend/touchcancel");
|
||||
NS_WARNING("Got an unexpected touchend");
|
||||
mActiveTouchCount = 0;
|
||||
}
|
||||
break;
|
||||
@ -36,6 +37,37 @@ void TouchCounter::Update(const MultiTouchInput& aInput) {
|
||||
}
|
||||
}
|
||||
|
||||
void TouchCounter::Update(const WidgetTouchEvent& aEvent) {
|
||||
switch (aEvent.mMessage) {
|
||||
case eTouchStart:
|
||||
// touch-start event contains all active touches of the current session
|
||||
mActiveTouchCount = aEvent.mTouches.Length();
|
||||
break;
|
||||
case eTouchEnd: {
|
||||
// touch-end contains all touches, but ones being lifted are marked as
|
||||
// changed
|
||||
uint32_t liftedTouches = 0;
|
||||
for (const auto& touch : aEvent.mTouches) {
|
||||
if (touch->mChanged) {
|
||||
liftedTouches++;
|
||||
}
|
||||
}
|
||||
if (mActiveTouchCount >= liftedTouches) {
|
||||
mActiveTouchCount -= liftedTouches;
|
||||
} else {
|
||||
NS_WARNING("Got an unexpected touchend");
|
||||
mActiveTouchCount = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case eTouchCancel:
|
||||
mActiveTouchCount = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t TouchCounter::GetActiveTouchCount() const { return mActiveTouchCount; }
|
||||
|
||||
} // namespace layers
|
@ -16,11 +16,14 @@ class MultiTouchInput;
|
||||
namespace layers {
|
||||
|
||||
// TouchCounter simply tracks the number of active touch points. Feed it
|
||||
// your input events to update the internal state.
|
||||
// your input events to update the internal state. Generally you should
|
||||
// only be calling one of the Update functions, depending on which type
|
||||
// of touch inputs you have access to.
|
||||
class TouchCounter {
|
||||
public:
|
||||
TouchCounter();
|
||||
void Update(const MultiTouchInput& aInput);
|
||||
void Update(const WidgetTouchEvent& aEvent);
|
||||
uint32_t GetActiveTouchCount() const;
|
||||
|
||||
private:
|
@ -118,6 +118,7 @@ EXPORTS.mozilla.layers += [
|
||||
'apz/util/InputAPZContext.h',
|
||||
'apz/util/ScrollLinkedEffectDetector.h',
|
||||
'apz/util/TouchActionHelper.h',
|
||||
'apz/util/TouchCounter.h',
|
||||
'AsyncCanvasRenderer.h',
|
||||
'AtomicRefCountedWithFinalize.h',
|
||||
'AxisPhysicsModel.h',
|
||||
@ -336,7 +337,6 @@ UNIFIED_SOURCES += [
|
||||
'apz/src/PotentialCheckerboardDurationTracker.cpp',
|
||||
'apz/src/QueuedInput.cpp',
|
||||
'apz/src/SimpleVelocityTracker.cpp',
|
||||
'apz/src/TouchCounter.cpp',
|
||||
'apz/src/WheelScrollAnimation.cpp',
|
||||
'apz/testutil/APZTestData.cpp',
|
||||
'apz/util/ActiveElementManager.cpp',
|
||||
@ -350,6 +350,7 @@ UNIFIED_SOURCES += [
|
||||
'apz/util/InputAPZContext.cpp',
|
||||
'apz/util/ScrollLinkedEffectDetector.cpp',
|
||||
'apz/util/TouchActionHelper.cpp',
|
||||
'apz/util/TouchCounter.cpp',
|
||||
'AsyncCanvasRenderer.cpp',
|
||||
'AxisPhysicsModel.cpp',
|
||||
'AxisPhysicsMSDModel.cpp',
|
||||
|
@ -1209,6 +1209,24 @@ static bool StartGC(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool FinishGC(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
if (args.length() > 0) {
|
||||
RootedObject callee(cx, &args.callee());
|
||||
ReportUsageErrorASCII(cx, callee, "Wrong number of arguments");
|
||||
return false;
|
||||
}
|
||||
|
||||
JSRuntime* rt = cx->runtime();
|
||||
if (rt->gc.isIncrementalGCInProgress()) {
|
||||
rt->gc.finishGC(JS::GCReason::DEBUG_GC);
|
||||
}
|
||||
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool GCSlice(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
@ -5853,6 +5871,10 @@ gc::ZealModeHelpText),
|
||||
" If 'shrinking' is passesd as the optional second argument, perform a\n"
|
||||
" shrinking GC rather than a normal GC."),
|
||||
|
||||
JS_FN_HELP("finishgc", FinishGC, 0, 0,
|
||||
"finishgc()",
|
||||
" Finish an in-progress incremental GC, if none is running then do nothing."),
|
||||
|
||||
JS_FN_HELP("gcslice", GCSlice, 1, 0,
|
||||
"gcslice([n])",
|
||||
" Start or continue an an incremental GC, running a slice that processes about n objects."),
|
||||
|
@ -13,6 +13,7 @@ function basicSweeping() {
|
||||
wm1.set(hold, {'name': 'val2'});
|
||||
wm1.set({'name': 'obj3'}, {'name': 'val3'});
|
||||
|
||||
finishgc();
|
||||
startgc(100000, 'shrinking');
|
||||
gcslice();
|
||||
|
||||
@ -36,6 +37,7 @@ function weakGraph() {
|
||||
wm1.set(obj4, obj1); // This edge will be cleared
|
||||
obj1 = obj3 = obj4 = undefined;
|
||||
|
||||
finishgc();
|
||||
startgc(100000, 'shrinking');
|
||||
gcslice();
|
||||
|
||||
@ -64,6 +66,7 @@ function deadWeakMap() {
|
||||
obj1 = obj3 = obj4 = undefined;
|
||||
wm1 = undefined;
|
||||
|
||||
finishgc();
|
||||
startgc(100000, 'shrinking');
|
||||
gcslice();
|
||||
|
||||
@ -91,6 +94,7 @@ function deadKeys() {
|
||||
obj1 = obj3 = undefined;
|
||||
var initialCount = finalizeCount();
|
||||
|
||||
finishgc();
|
||||
startgc(100000, 'shrinking');
|
||||
gcslice();
|
||||
|
||||
@ -124,6 +128,7 @@ function weakKeysRealloc() {
|
||||
obj2 = undefined;
|
||||
|
||||
var initialCount = finalizeCount();
|
||||
finishgc();
|
||||
startgc(100000, 'shrinking');
|
||||
gcslice();
|
||||
assertEq(finalizeCount(), initialCount + 1);
|
||||
@ -142,6 +147,7 @@ function deletedKeys() {
|
||||
for (var i = 0; i < 1000; i++)
|
||||
wm.set(g.Object.create(null), i);
|
||||
|
||||
finishgc();
|
||||
startgc(100, 'shrinking');
|
||||
for (var key of nondeterministicGetWeakMapKeys(wm)) {
|
||||
if (wm.get(key) % 2)
|
||||
@ -171,6 +177,7 @@ function incrementalAdds() {
|
||||
obj2 = undefined;
|
||||
|
||||
var obj3 = [];
|
||||
finishgc();
|
||||
startgc(100, 'shrinking');
|
||||
var M = 10;
|
||||
var N = 800;
|
||||
|
@ -2091,12 +2091,6 @@ JSObject* BaselineCompilerHandler::maybeNoCloneSingletonObject() {
|
||||
return script()->getObject(pc());
|
||||
}
|
||||
|
||||
typedef JSObject* (*SingletonObjectLiteralFn)(JSContext*, HandleScript,
|
||||
jsbytecode*);
|
||||
static const VMFunction SingletonObjectLiteralInfo =
|
||||
FunctionInfo<SingletonObjectLiteralFn>(SingletonObjectLiteralOperation,
|
||||
"SingletonObjectLiteralOperation");
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emit_JSOP_OBJECT() {
|
||||
// If we know we don't have to clone the object literal, just push it
|
||||
@ -2112,7 +2106,8 @@ bool BaselineCodeGen<Handler>::emit_JSOP_OBJECT() {
|
||||
pushBytecodePCArg();
|
||||
pushScriptArg(R2.scratchReg());
|
||||
|
||||
if (!callVM(SingletonObjectLiteralInfo)) {
|
||||
using Fn = JSObject* (*)(JSContext*, HandleScript, jsbytecode*);
|
||||
if (!callVM<Fn, SingletonObjectLiteralOperation>()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2134,12 +2129,6 @@ bool BaselineCompilerCodeGen::emit_JSOP_CALLSITEOBJ() {
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef ArrayObject* (*ProcessCallSiteObjFn)(JSContext*, HandleScript,
|
||||
jsbytecode*);
|
||||
static const VMFunction ProcessCallSiteObjInfo =
|
||||
FunctionInfo<ProcessCallSiteObjFn>(ProcessCallSiteObjOperation,
|
||||
"ProcessCallSiteObjOperation");
|
||||
|
||||
template <>
|
||||
bool BaselineInterpreterCodeGen::emit_JSOP_CALLSITEOBJ() {
|
||||
prepareVMCall();
|
||||
@ -2147,7 +2136,8 @@ bool BaselineInterpreterCodeGen::emit_JSOP_CALLSITEOBJ() {
|
||||
pushBytecodePCArg();
|
||||
pushScriptArg(R2.scratchReg());
|
||||
|
||||
if (!callVM(ProcessCallSiteObjInfo)) {
|
||||
using Fn = ArrayObject* (*)(JSContext*, HandleScript, jsbytecode*);
|
||||
if (!callVM<Fn, ProcessCallSiteObjOperation>()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2157,15 +2147,13 @@ bool BaselineInterpreterCodeGen::emit_JSOP_CALLSITEOBJ() {
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef JSObject* (*CloneRegExpObjectFn)(JSContext*, Handle<RegExpObject*>);
|
||||
static const VMFunction CloneRegExpObjectInfo =
|
||||
FunctionInfo<CloneRegExpObjectFn>(CloneRegExpObject, "CloneRegExpObject");
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emit_JSOP_REGEXP() {
|
||||
prepareVMCall();
|
||||
pushScriptObjectArg(ScriptObjectType::RegExp);
|
||||
if (!callVM(CloneRegExpObjectInfo)) {
|
||||
|
||||
using Fn = JSObject* (*)(JSContext*, Handle<RegExpObject*>);
|
||||
if (!callVM<Fn, CloneRegExpObject>()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2175,10 +2163,6 @@ bool BaselineCodeGen<Handler>::emit_JSOP_REGEXP() {
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef JSObject* (*LambdaFn)(JSContext*, HandleFunction, HandleObject);
|
||||
static const VMFunction LambdaInfo =
|
||||
FunctionInfo<LambdaFn>(js::Lambda, "Lambda");
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emit_JSOP_LAMBDA() {
|
||||
prepareVMCall();
|
||||
@ -2187,7 +2171,8 @@ bool BaselineCodeGen<Handler>::emit_JSOP_LAMBDA() {
|
||||
pushArg(R0.scratchReg());
|
||||
pushScriptObjectArg(ScriptObjectType::Function);
|
||||
|
||||
if (!callVM(LambdaInfo)) {
|
||||
using Fn = JSObject* (*)(JSContext*, HandleFunction, HandleObject);
|
||||
if (!callVM<Fn, js::Lambda>()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2197,11 +2182,6 @@ bool BaselineCodeGen<Handler>::emit_JSOP_LAMBDA() {
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef JSObject* (*LambdaArrowFn)(JSContext*, HandleFunction, HandleObject,
|
||||
HandleValue);
|
||||
static const VMFunction LambdaArrowInfo =
|
||||
FunctionInfo<LambdaArrowFn>(js::LambdaArrow, "LambdaArrow");
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emit_JSOP_LAMBDA_ARROW() {
|
||||
// Keep pushed newTarget in R0.
|
||||
@ -2214,7 +2194,9 @@ bool BaselineCodeGen<Handler>::emit_JSOP_LAMBDA_ARROW() {
|
||||
pushArg(R2.scratchReg());
|
||||
pushScriptObjectArg(ScriptObjectType::Function);
|
||||
|
||||
if (!callVM(LambdaArrowInfo)) {
|
||||
using Fn =
|
||||
JSObject* (*)(JSContext*, HandleFunction, HandleObject, HandleValue);
|
||||
if (!callVM<Fn, js::LambdaArrow>()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2224,11 +2206,6 @@ bool BaselineCodeGen<Handler>::emit_JSOP_LAMBDA_ARROW() {
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef bool (*SetFunNameFn)(JSContext*, HandleFunction, HandleValue,
|
||||
FunctionPrefixKind);
|
||||
static const VMFunction SetFunNameInfo =
|
||||
FunctionInfo<SetFunNameFn>(js::SetFunctionName, "SetFunName");
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emit_JSOP_SETFUNNAME() {
|
||||
frame.popRegsAndSync(2);
|
||||
@ -2243,7 +2220,10 @@ bool BaselineCodeGen<Handler>::emit_JSOP_SETFUNNAME() {
|
||||
pushUint8BytecodeOperandArg();
|
||||
pushArg(R1);
|
||||
pushArg(R0.scratchReg());
|
||||
return callVM(SetFunNameInfo);
|
||||
|
||||
using Fn =
|
||||
bool (*)(JSContext*, HandleFunction, HandleValue, FunctionPrefixKind);
|
||||
return callVM<Fn, SetFunctionName>();
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
@ -2469,11 +2449,6 @@ bool BaselineInterpreterCodeGen::emit_JSOP_NEWARRAY() {
|
||||
MOZ_CRASH("NYI: interpreter JSOP_NEWARRAY");
|
||||
}
|
||||
|
||||
typedef ArrayObject* (*NewArrayCopyOnWriteFn)(JSContext*, HandleArrayObject,
|
||||
gc::InitialHeap);
|
||||
const VMFunction NewArrayCopyOnWriteInfo = FunctionInfo<NewArrayCopyOnWriteFn>(
|
||||
js::NewDenseCopyOnWriteArray, "NewDenseCopyOnWriteArray");
|
||||
|
||||
template <>
|
||||
bool BaselineCompilerCodeGen::emit_JSOP_NEWARRAY_COPYONWRITE() {
|
||||
// This is like the interpreter implementation, but we can call
|
||||
@ -2491,7 +2466,8 @@ bool BaselineCompilerCodeGen::emit_JSOP_NEWARRAY_COPYONWRITE() {
|
||||
pushArg(Imm32(gc::DefaultHeap));
|
||||
pushArg(ImmGCPtr(obj));
|
||||
|
||||
if (!callVM(NewArrayCopyOnWriteInfo)) {
|
||||
using Fn = ArrayObject* (*)(JSContext*, HandleArrayObject, gc::InitialHeap);
|
||||
if (!callVM<Fn, js::NewDenseCopyOnWriteArray>()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2501,12 +2477,6 @@ bool BaselineCompilerCodeGen::emit_JSOP_NEWARRAY_COPYONWRITE() {
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef ArrayObject* (*NewArrayCopyOnWriteOperationFn)(JSContext*, HandleScript,
|
||||
jsbytecode*);
|
||||
const VMFunction NewArrayCopyOnWriteOperationInfo =
|
||||
FunctionInfo<NewArrayCopyOnWriteOperationFn>(
|
||||
NewArrayCopyOnWriteOperation, "NewArrayCopyOnWriteOperation");
|
||||
|
||||
template <>
|
||||
bool BaselineInterpreterCodeGen::emit_JSOP_NEWARRAY_COPYONWRITE() {
|
||||
prepareVMCall();
|
||||
@ -2514,7 +2484,8 @@ bool BaselineInterpreterCodeGen::emit_JSOP_NEWARRAY_COPYONWRITE() {
|
||||
pushBytecodePCArg();
|
||||
pushScriptArg(R2.scratchReg());
|
||||
|
||||
if (!callVM(NewArrayCopyOnWriteOperationInfo)) {
|
||||
using Fn = ArrayObject* (*)(JSContext*, HandleScript, jsbytecode*);
|
||||
if (!callVM<Fn, NewArrayCopyOnWriteOperation>()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2608,11 +2579,6 @@ bool BaselineCodeGen<Handler>::emit_JSOP_INITHIDDENELEM() {
|
||||
return emit_JSOP_INITELEM();
|
||||
}
|
||||
|
||||
typedef bool (*MutateProtoFn)(JSContext* cx, HandlePlainObject obj,
|
||||
HandleValue newProto);
|
||||
static const VMFunction MutateProtoInfo =
|
||||
FunctionInfo<MutateProtoFn>(MutatePrototype, "MutatePrototype");
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emit_JSOP_MUTATEPROTO() {
|
||||
// Keep values on the stack for the decompiler.
|
||||
@ -2626,7 +2592,8 @@ bool BaselineCodeGen<Handler>::emit_JSOP_MUTATEPROTO() {
|
||||
pushArg(R1);
|
||||
pushArg(R0.scratchReg());
|
||||
|
||||
if (!callVM(MutateProtoInfo)) {
|
||||
using Fn = bool (*)(JSContext*, HandlePlainObject, HandleValue);
|
||||
if (!callVM<Fn, MutatePrototype>()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2765,13 +2732,6 @@ bool BaselineCodeGen<Handler>::emit_JSOP_STRICTSETELEM_SUPER() {
|
||||
return emitSetElemSuper(/* strict = */ true);
|
||||
}
|
||||
|
||||
typedef bool (*DeleteElementFn)(JSContext*, HandleValue, HandleValue, bool*);
|
||||
static const VMFunction DeleteElementStrictInfo = FunctionInfo<DeleteElementFn>(
|
||||
DeleteElementJit<true>, "DeleteElementStrict");
|
||||
static const VMFunction DeleteElementNonStrictInfo =
|
||||
FunctionInfo<DeleteElementFn>(DeleteElementJit<false>,
|
||||
"DeleteElementNonStrict");
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emitDelElem(bool strict) {
|
||||
// Keep values on the stack for the decompiler.
|
||||
@ -2783,8 +2743,16 @@ bool BaselineCodeGen<Handler>::emitDelElem(bool strict) {
|
||||
|
||||
pushArg(R1);
|
||||
pushArg(R0);
|
||||
if (!callVM(strict ? DeleteElementStrictInfo : DeleteElementNonStrictInfo)) {
|
||||
return false;
|
||||
|
||||
using Fn = bool (*)(JSContext*, HandleValue, HandleValue, bool*);
|
||||
if (strict) {
|
||||
if (!callVM<Fn, DeleteElementJit<true>>()) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!callVM<Fn, DeleteElementJit<false>>()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
masm.boxNonDouble(JSVAL_TYPE_BOOLEAN, ReturnReg, R1);
|
||||
@ -2930,10 +2898,6 @@ bool BaselineCodeGen<Handler>::emit_JSOP_BINDGNAME() {
|
||||
return emitBindName(JSOP_BINDGNAME);
|
||||
}
|
||||
|
||||
typedef JSObject* (*BindVarFn)(JSContext*, JSObject*);
|
||||
static const VMFunction BindVarInfo =
|
||||
FunctionInfo<BindVarFn>(BindVarOperation, "BindVarOperation");
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emit_JSOP_BINDVAR() {
|
||||
frame.syncStack(0);
|
||||
@ -2942,7 +2906,8 @@ bool BaselineCodeGen<Handler>::emit_JSOP_BINDVAR() {
|
||||
prepareVMCall();
|
||||
pushArg(R0.scratchReg());
|
||||
|
||||
if (!callVM(BindVarInfo)) {
|
||||
using Fn = JSObject* (*)(JSContext*, JSObject*);
|
||||
if (!callVM<Fn, BindVarOperation>()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2993,11 +2958,6 @@ bool BaselineCodeGen<Handler>::emit_JSOP_STRICTSETGNAME() {
|
||||
return emit_JSOP_SETPROP();
|
||||
}
|
||||
|
||||
typedef bool (*SetPropertySuperFn)(JSContext*, HandleObject, HandleValue,
|
||||
HandlePropertyName, HandleValue, bool);
|
||||
static const VMFunction SetPropertySuperInfo =
|
||||
FunctionInfo<SetPropertySuperFn>(js::SetPropertySuper, "SetPropertySuper");
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emitSetPropSuper(bool strict) {
|
||||
// Incoming stack is |receiver, obj, rval|. We need to shuffle stack to
|
||||
@ -3017,7 +2977,9 @@ bool BaselineCodeGen<Handler>::emitSetPropSuper(bool strict) {
|
||||
masm.unboxObject(frame.addressOfStackValue(-1), R0.scratchReg());
|
||||
pushArg(R0.scratchReg()); // obj
|
||||
|
||||
if (!callVM(SetPropertySuperInfo)) {
|
||||
using Fn = bool (*)(JSContext*, HandleObject, HandleValue, HandlePropertyName,
|
||||
HandleValue, bool);
|
||||
if (!callVM<Fn, js::SetPropertySuper>()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3080,15 +3042,6 @@ bool BaselineCodeGen<Handler>::emit_JSOP_GETPROP_SUPER() {
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef bool (*DeletePropertyFn)(JSContext*, HandleValue, HandlePropertyName,
|
||||
bool*);
|
||||
static const VMFunction DeletePropertyStrictInfo =
|
||||
FunctionInfo<DeletePropertyFn>(DeletePropertyJit<true>,
|
||||
"DeletePropertyStrict");
|
||||
static const VMFunction DeletePropertyNonStrictInfo =
|
||||
FunctionInfo<DeletePropertyFn>(DeletePropertyJit<false>,
|
||||
"DeletePropertyNonStrict");
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emitDelProp(bool strict) {
|
||||
// Keep value on the stack for the decompiler.
|
||||
@ -3100,9 +3053,15 @@ bool BaselineCodeGen<Handler>::emitDelProp(bool strict) {
|
||||
pushScriptNameArg();
|
||||
pushArg(R0);
|
||||
|
||||
if (!callVM(strict ? DeletePropertyStrictInfo
|
||||
: DeletePropertyNonStrictInfo)) {
|
||||
return false;
|
||||
using Fn = bool (*)(JSContext*, HandleValue, HandlePropertyName, bool*);
|
||||
if (strict) {
|
||||
if (!callVM<Fn, DeletePropertyJit<true>>()) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!callVM<Fn, DeletePropertyJit<false>>()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
masm.boxNonDouble(JSVAL_TYPE_BOOLEAN, ReturnReg, R1);
|
||||
@ -3273,11 +3232,6 @@ bool BaselineCodeGen<Handler>::emit_JSOP_BINDNAME() {
|
||||
return emitBindName(JSOP_BINDNAME);
|
||||
}
|
||||
|
||||
typedef bool (*DeleteNameFn)(JSContext*, HandlePropertyName, HandleObject,
|
||||
MutableHandleValue);
|
||||
static const VMFunction DeleteNameInfo =
|
||||
FunctionInfo<DeleteNameFn>(DeleteNameOperation, "DeleteNameOperation");
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emit_JSOP_DELNAME() {
|
||||
frame.syncStack(0);
|
||||
@ -3288,7 +3242,9 @@ bool BaselineCodeGen<Handler>::emit_JSOP_DELNAME() {
|
||||
pushArg(R0.scratchReg());
|
||||
pushScriptNameArg();
|
||||
|
||||
if (!callVM(DeleteNameInfo)) {
|
||||
using Fn = bool (*)(JSContext*, HandlePropertyName, HandleObject,
|
||||
MutableHandleValue);
|
||||
if (!callVM<Fn, js::DeleteNameOperation>()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3343,12 +3299,6 @@ bool BaselineCompilerCodeGen::emit_JSOP_GETIMPORT() {
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef bool (*GetImportOperationFn)(JSContext*, HandleObject, HandleScript,
|
||||
jsbytecode*, MutableHandleValue);
|
||||
static const VMFunction GetImportOperationInfo =
|
||||
FunctionInfo<GetImportOperationFn>(GetImportOperation,
|
||||
"GetImportOperation");
|
||||
|
||||
template <>
|
||||
bool BaselineInterpreterCodeGen::emit_JSOP_GETIMPORT() {
|
||||
frame.syncStack(0);
|
||||
@ -3361,7 +3311,9 @@ bool BaselineInterpreterCodeGen::emit_JSOP_GETIMPORT() {
|
||||
pushScriptArg(R2.scratchReg());
|
||||
pushArg(R0.scratchReg());
|
||||
|
||||
if (!callVM(GetImportOperationInfo)) {
|
||||
using Fn = bool (*)(JSContext*, HandleObject, HandleScript, jsbytecode*,
|
||||
MutableHandleValue);
|
||||
if (!callVM<Fn, GetImportOperation>()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3386,10 +3338,6 @@ bool BaselineCodeGen<Handler>::emit_JSOP_GETINTRINSIC() {
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef bool (*SetIntrinsicFn)(JSContext*, JSScript*, jsbytecode*, HandleValue);
|
||||
static const VMFunction SetIntrinsicInfo = FunctionInfo<SetIntrinsicFn>(
|
||||
SetIntrinsicOperation, "SetIntrinsicOperation");
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emit_JSOP_SETINTRINSIC() {
|
||||
frame.syncStack(0);
|
||||
@ -3401,13 +3349,10 @@ bool BaselineCodeGen<Handler>::emit_JSOP_SETINTRINSIC() {
|
||||
pushBytecodePCArg();
|
||||
pushScriptArg(R2.scratchReg());
|
||||
|
||||
return callVM(SetIntrinsicInfo);
|
||||
using Fn = bool (*)(JSContext*, JSScript*, jsbytecode*, HandleValue);
|
||||
return callVM<Fn, SetIntrinsicOperation>();
|
||||
}
|
||||
|
||||
typedef bool (*DefVarFn)(JSContext*, HandleObject, HandleScript, jsbytecode*);
|
||||
static const VMFunction DefVarInfo =
|
||||
FunctionInfo<DefVarFn>(DefVarOperation, "DefVarOperation");
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emit_JSOP_DEFVAR() {
|
||||
frame.syncStack(0);
|
||||
@ -3420,14 +3365,10 @@ bool BaselineCodeGen<Handler>::emit_JSOP_DEFVAR() {
|
||||
pushScriptArg(R2.scratchReg());
|
||||
pushArg(R0.scratchReg());
|
||||
|
||||
return callVM(DefVarInfo);
|
||||
using Fn = bool (*)(JSContext*, HandleObject, HandleScript, jsbytecode*);
|
||||
return callVM<Fn, DefVarOperation>();
|
||||
}
|
||||
|
||||
typedef bool (*DefLexicalFn)(JSContext*, HandleObject, HandleScript,
|
||||
jsbytecode*);
|
||||
static const VMFunction DefLexicalInfo =
|
||||
FunctionInfo<DefLexicalFn>(DefLexicalOperation, "DefLexicalOperation");
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emitDefLexical(JSOp op) {
|
||||
MOZ_ASSERT(op == JSOP_DEFCONST || op == JSOP_DEFLET);
|
||||
@ -3442,7 +3383,8 @@ bool BaselineCodeGen<Handler>::emitDefLexical(JSOp op) {
|
||||
pushScriptArg(R2.scratchReg());
|
||||
pushArg(R0.scratchReg());
|
||||
|
||||
return callVM(DefLexicalInfo);
|
||||
using Fn = bool (*)(JSContext*, HandleObject, HandleScript, jsbytecode*);
|
||||
return callVM<Fn, DefLexicalOperation>();
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
@ -3455,11 +3397,6 @@ bool BaselineCodeGen<Handler>::emit_JSOP_DEFLET() {
|
||||
return emitDefLexical(JSOP_DEFLET);
|
||||
}
|
||||
|
||||
typedef bool (*DefFunOperationFn)(JSContext*, HandleScript, HandleObject,
|
||||
HandleFunction);
|
||||
static const VMFunction DefFunOperationInfo =
|
||||
FunctionInfo<DefFunOperationFn>(DefFunOperation, "DefFunOperation");
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emit_JSOP_DEFFUN() {
|
||||
frame.popRegsAndSync(1);
|
||||
@ -3472,15 +3409,10 @@ bool BaselineCodeGen<Handler>::emit_JSOP_DEFFUN() {
|
||||
pushArg(R1.scratchReg());
|
||||
pushScriptArg(R2.scratchReg());
|
||||
|
||||
return callVM(DefFunOperationInfo);
|
||||
using Fn = bool (*)(JSContext*, HandleScript, HandleObject, HandleFunction);
|
||||
return callVM<Fn, DefFunOperation>();
|
||||
}
|
||||
|
||||
typedef bool (*InitPropGetterSetterFn)(JSContext*, jsbytecode*, HandleObject,
|
||||
HandlePropertyName, HandleObject);
|
||||
static const VMFunction InitPropGetterSetterInfo =
|
||||
FunctionInfo<InitPropGetterSetterFn>(InitGetterSetterOperation,
|
||||
"InitPropGetterSetterOperation");
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emitInitPropGetterSetter() {
|
||||
// Keep values on the stack for the decompiler.
|
||||
@ -3496,7 +3428,9 @@ bool BaselineCodeGen<Handler>::emitInitPropGetterSetter() {
|
||||
pushArg(R1.scratchReg());
|
||||
pushBytecodePCArg();
|
||||
|
||||
if (!callVM(InitPropGetterSetterInfo)) {
|
||||
using Fn = bool (*)(JSContext*, jsbytecode*, HandleObject, HandlePropertyName,
|
||||
HandleObject);
|
||||
if (!callVM<Fn, InitPropGetterSetterOperation>()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3524,12 +3458,6 @@ bool BaselineCodeGen<Handler>::emit_JSOP_INITHIDDENPROP_SETTER() {
|
||||
return emitInitPropGetterSetter();
|
||||
}
|
||||
|
||||
typedef bool (*InitElemGetterSetterFn)(JSContext*, jsbytecode*, HandleObject,
|
||||
HandleValue, HandleObject);
|
||||
static const VMFunction InitElemGetterSetterInfo =
|
||||
FunctionInfo<InitElemGetterSetterFn>(InitGetterSetterOperation,
|
||||
"InitElemGetterSetterOperation");
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emitInitElemGetterSetter() {
|
||||
// Load index and value in R0 and R1, but keep values on the stack for the
|
||||
@ -3546,7 +3474,9 @@ bool BaselineCodeGen<Handler>::emitInitElemGetterSetter() {
|
||||
pushArg(R0.scratchReg());
|
||||
pushBytecodePCArg();
|
||||
|
||||
if (!callVM(InitElemGetterSetterInfo)) {
|
||||
using Fn = bool (*)(JSContext*, jsbytecode*, HandleObject, HandleValue,
|
||||
HandleObject);
|
||||
if (!callVM<Fn, InitElemGetterSetterOperation>()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3800,16 +3730,13 @@ bool BaselineInterpreterCodeGen::emit_JSOP_NEWTARGET() {
|
||||
MOZ_CRASH("NYI: interpreter JSOP_NEWTARGET");
|
||||
}
|
||||
|
||||
typedef bool (*ThrowRuntimeLexicalErrorFn)(JSContext* cx, unsigned);
|
||||
static const VMFunction ThrowRuntimeLexicalErrorInfo =
|
||||
FunctionInfo<ThrowRuntimeLexicalErrorFn>(jit::ThrowRuntimeLexicalError,
|
||||
"ThrowRuntimeLexicalError");
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emitThrowConstAssignment() {
|
||||
prepareVMCall();
|
||||
pushArg(Imm32(JSMSG_BAD_CONST_ASSIGN));
|
||||
return callVM(ThrowRuntimeLexicalErrorInfo);
|
||||
|
||||
using Fn = bool (*)(JSContext*, unsigned);
|
||||
return callVM<Fn, jit::ThrowRuntimeLexicalError>();
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
@ -3836,7 +3763,9 @@ bool BaselineCodeGen<Handler>::emitUninitializedLexicalCheck(
|
||||
|
||||
prepareVMCall();
|
||||
pushArg(Imm32(JSMSG_UNINITIALIZED_LEXICAL));
|
||||
if (!callVM(ThrowRuntimeLexicalErrorInfo)) {
|
||||
|
||||
using Fn = bool (*)(JSContext*, unsigned);
|
||||
if (!callVM<Fn, jit::ThrowRuntimeLexicalError>()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -4002,11 +3931,6 @@ bool BaselineCodeGen<Handler>::emit_JSOP_STRICTSPREADEVAL() {
|
||||
return emitSpreadCall(JSOP_STRICTSPREADEVAL);
|
||||
}
|
||||
|
||||
typedef bool (*OptimizeSpreadCallFn)(JSContext*, HandleValue, bool*);
|
||||
static const VMFunction OptimizeSpreadCallInfo =
|
||||
FunctionInfo<OptimizeSpreadCallFn>(OptimizeSpreadCall,
|
||||
"OptimizeSpreadCall");
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emit_JSOP_OPTIMIZE_SPREADCALL() {
|
||||
frame.syncStack(0);
|
||||
@ -4015,7 +3939,8 @@ bool BaselineCodeGen<Handler>::emit_JSOP_OPTIMIZE_SPREADCALL() {
|
||||
prepareVMCall();
|
||||
pushArg(R0);
|
||||
|
||||
if (!callVM(OptimizeSpreadCallInfo)) {
|
||||
using Fn = bool (*)(JSContext*, HandleValue, bool*);
|
||||
if (!callVM<Fn, OptimizeSpreadCall>()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -667,7 +667,6 @@ class BaselineInterpreterGenerator final : private BaselineInterpreterCodeGen {
|
||||
explicit BaselineInterpreterGenerator(JSContext* cx);
|
||||
};
|
||||
|
||||
extern const VMFunction NewArrayCopyOnWriteInfo;
|
||||
extern const VMFunction ImplicitThisInfo;
|
||||
|
||||
} // namespace jit
|
||||
|
@ -6212,6 +6212,12 @@ void CodeGenerator::visitOutOfLineNewArray(OutOfLineNewArray* ool) {
|
||||
masm.jump(ool->rejoin());
|
||||
}
|
||||
|
||||
typedef ArrayObject* (*NewArrayCopyOnWriteFn)(JSContext*, HandleArrayObject,
|
||||
gc::InitialHeap);
|
||||
static const VMFunction NewArrayCopyOnWriteInfo =
|
||||
FunctionInfo<NewArrayCopyOnWriteFn>(js::NewDenseCopyOnWriteArray,
|
||||
"NewDenseCopyOnWriteArray");
|
||||
|
||||
void CodeGenerator::visitNewArrayCopyOnWrite(LNewArrayCopyOnWrite* lir) {
|
||||
Register objReg = ToRegister(lir->output());
|
||||
Register tempReg = ToRegister(lir->temp());
|
||||
@ -6725,7 +6731,7 @@ void CodeGenerator::visitInitElem(LInitElem* lir) {
|
||||
typedef bool (*InitElemGetterSetterFn)(JSContext*, jsbytecode*, HandleObject,
|
||||
HandleValue, HandleObject);
|
||||
static const VMFunction InitElemGetterSetterInfo =
|
||||
FunctionInfo<InitElemGetterSetterFn>(InitGetterSetterOperation,
|
||||
FunctionInfo<InitElemGetterSetterFn>(InitElemGetterSetterOperation,
|
||||
"InitElemGetterSetterOperation");
|
||||
|
||||
void CodeGenerator::visitInitElemGetterSetter(LInitElemGetterSetter* lir) {
|
||||
@ -6757,7 +6763,7 @@ void CodeGenerator::visitMutateProto(LMutateProto* lir) {
|
||||
typedef bool (*InitPropGetterSetterFn)(JSContext*, jsbytecode*, HandleObject,
|
||||
HandlePropertyName, HandleObject);
|
||||
static const VMFunction InitPropGetterSetterInfo =
|
||||
FunctionInfo<InitPropGetterSetterFn>(InitGetterSetterOperation,
|
||||
FunctionInfo<InitPropGetterSetterFn>(InitPropGetterSetterOperation,
|
||||
"InitPropGetterSetterOperation");
|
||||
|
||||
void CodeGenerator::visitInitPropGetterSetter(LInitPropGetterSetter* lir) {
|
||||
|
@ -23,13 +23,38 @@ namespace jit {
|
||||
_(BaselineGetFunctionThis, js::jit::BaselineGetFunctionThis) \
|
||||
_(BaselineThrowInitializedThis, js::jit::BaselineThrowInitializedThis) \
|
||||
_(BaselineThrowUninitializedThis, js::jit::BaselineThrowUninitializedThis) \
|
||||
_(BindVarOperation, js::BindVarOperation) \
|
||||
_(CheckIsCallable, js::jit::CheckIsCallable) \
|
||||
_(CheckOverRecursedBaseline, js::jit::CheckOverRecursedBaseline) \
|
||||
_(CloneRegExpObject, js::CloneRegExpObject) \
|
||||
_(DefFunOperation, js::DefFunOperation) \
|
||||
_(DefLexicalOperation, js::DefLexicalOperation) \
|
||||
_(DefVarOperation, js::DefVarOperation) \
|
||||
_(DeleteElementNonStrict, js::DeleteElementJit<false>) \
|
||||
_(DeleteElementStrict, js::DeleteElementJit<true>) \
|
||||
_(DeleteNameOperation, js::DeleteNameOperation) \
|
||||
_(DeletePropertyNonStrict, js::DeletePropertyJit<false>) \
|
||||
_(DeletePropertyStrict, js::DeletePropertyJit<true>) \
|
||||
_(GetImportOperation, js::GetImportOperation) \
|
||||
_(GetNonSyntacticGlobalThis, js::GetNonSyntacticGlobalThis) \
|
||||
_(InitElemGetterSetterOperation, js::InitElemGetterSetterOperation) \
|
||||
_(InitPropGetterSetterOperation, js::InitPropGetterSetterOperation) \
|
||||
_(InterruptCheck, js::jit::InterruptCheck) \
|
||||
_(IonCompileScriptForBaseline, js::jit::IonCompileScriptForBaseline) \
|
||||
_(Lambda, js::Lambda) \
|
||||
_(LambdaArrow, js::LambdaArrow) \
|
||||
_(MutatePrototype, js::jit::MutatePrototype) \
|
||||
_(NewArrayCopyOnWriteOperation, js::NewArrayCopyOnWriteOperation) \
|
||||
_(NewDenseCopyOnWriteArray, js::NewDenseCopyOnWriteArray) \
|
||||
_(OptimizeSpreadCall, js::OptimizeSpreadCall) \
|
||||
_(ProcessCallSiteObjOperation, js::ProcessCallSiteObjOperation) \
|
||||
_(SetFunctionName, js::SetFunctionName) \
|
||||
_(SetIntrinsicOperation, js::SetIntrinsicOperation) \
|
||||
_(SetPropertySuper, js::SetPropertySuper) \
|
||||
_(SingletonObjectLiteralOperation, js::SingletonObjectLiteralOperation) \
|
||||
_(ThrowBadDerivedReturn, js::jit::ThrowBadDerivedReturn) \
|
||||
_(ThrowCheckIsObject, js::ThrowCheckIsObject)
|
||||
_(ThrowCheckIsObject, js::ThrowCheckIsObject) \
|
||||
_(ThrowRuntimeLexicalError, js::jit::ThrowRuntimeLexicalError)
|
||||
|
||||
enum class VMFunctionId {
|
||||
#define DEF_ID(name, fp) name,
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include "jit/arm64/vixl/Disasm-vixl.h"
|
||||
|
||||
#include "mozilla/Sprintf.h"
|
||||
#include <cstdlib>
|
||||
|
||||
namespace vixl {
|
||||
|
@ -3678,7 +3678,7 @@ static MOZ_NEVER_INLINE JS_HAZ_JSNATIVE_CALLER bool Interpret(JSContext* cx,
|
||||
ReservedRooted<PropertyName*> name(&rootName0, script->getName(REGS.pc));
|
||||
ReservedRooted<JSObject*> val(&rootObject1, ®S.sp[-1].toObject());
|
||||
|
||||
if (!InitGetterSetterOperation(cx, REGS.pc, obj, name, val)) {
|
||||
if (!InitPropGetterSetterOperation(cx, REGS.pc, obj, name, val)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -3696,7 +3696,7 @@ static MOZ_NEVER_INLINE JS_HAZ_JSNATIVE_CALLER bool Interpret(JSContext* cx,
|
||||
ReservedRooted<Value> idval(&rootValue0, REGS.sp[-2]);
|
||||
ReservedRooted<JSObject*> val(&rootObject1, ®S.sp[-1].toObject());
|
||||
|
||||
if (!InitGetterSetterOperation(cx, REGS.pc, obj, idval, val)) {
|
||||
if (!InitElemGetterSetterOperation(cx, REGS.pc, obj, idval, val)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -4932,9 +4932,9 @@ unsigned js::GetInitDataPropAttrs(JSOp op) {
|
||||
MOZ_CRASH("Unknown data initprop");
|
||||
}
|
||||
|
||||
bool js::InitGetterSetterOperation(JSContext* cx, jsbytecode* pc,
|
||||
HandleObject obj, HandleId id,
|
||||
HandleObject val) {
|
||||
static bool InitGetterSetterOperation(JSContext* cx, jsbytecode* pc,
|
||||
HandleObject obj, HandleId id,
|
||||
HandleObject val) {
|
||||
MOZ_ASSERT(val->isCallable());
|
||||
|
||||
JSOp op = JSOp(*pc);
|
||||
@ -4957,16 +4957,17 @@ bool js::InitGetterSetterOperation(JSContext* cx, jsbytecode* pc,
|
||||
return DefineAccessorProperty(cx, obj, id, nullptr, val, attrs);
|
||||
}
|
||||
|
||||
bool js::InitGetterSetterOperation(JSContext* cx, jsbytecode* pc,
|
||||
HandleObject obj, HandlePropertyName name,
|
||||
HandleObject val) {
|
||||
bool js::InitPropGetterSetterOperation(JSContext* cx, jsbytecode* pc,
|
||||
HandleObject obj,
|
||||
HandlePropertyName name,
|
||||
HandleObject val) {
|
||||
RootedId id(cx, NameToId(name));
|
||||
return InitGetterSetterOperation(cx, pc, obj, id, val);
|
||||
}
|
||||
|
||||
bool js::InitGetterSetterOperation(JSContext* cx, jsbytecode* pc,
|
||||
HandleObject obj, HandleValue idval,
|
||||
HandleObject val) {
|
||||
bool js::InitElemGetterSetterOperation(JSContext* cx, jsbytecode* pc,
|
||||
HandleObject obj, HandleValue idval,
|
||||
HandleObject val) {
|
||||
RootedId id(cx);
|
||||
if (!ToPropertyKey(cx, idval, &id)) {
|
||||
return false;
|
||||
|
@ -515,19 +515,18 @@ bool DeleteNameOperation(JSContext* cx, HandlePropertyName name,
|
||||
bool ImplicitThisOperation(JSContext* cx, HandleObject scopeObj,
|
||||
HandlePropertyName name, MutableHandleValue res);
|
||||
|
||||
bool InitGetterSetterOperation(JSContext* cx, jsbytecode* pc, HandleObject obj,
|
||||
HandleId id, HandleObject val);
|
||||
|
||||
bool InitGetterSetterOperation(JSContext* cx, jsbytecode* pc, HandleObject obj,
|
||||
HandlePropertyName name, HandleObject val);
|
||||
bool InitPropGetterSetterOperation(JSContext* cx, jsbytecode* pc,
|
||||
HandleObject obj, HandlePropertyName name,
|
||||
HandleObject val);
|
||||
|
||||
unsigned GetInitDataPropAttrs(JSOp op);
|
||||
|
||||
bool EnterWithOperation(JSContext* cx, AbstractFramePtr frame, HandleValue val,
|
||||
Handle<WithScope*> scope);
|
||||
|
||||
bool InitGetterSetterOperation(JSContext* cx, jsbytecode* pc, HandleObject obj,
|
||||
HandleValue idval, HandleObject val);
|
||||
bool InitElemGetterSetterOperation(JSContext* cx, jsbytecode* pc,
|
||||
HandleObject obj, HandleValue idval,
|
||||
HandleObject val);
|
||||
|
||||
bool SpreadCallOperation(JSContext* cx, HandleScript script, jsbytecode* pc,
|
||||
HandleValue thisv, HandleValue callee, HandleValue arr,
|
||||
|
@ -6659,22 +6659,10 @@ nsresult PresShell::EventHandler::HandleEvent(nsIFrame* aFrame,
|
||||
}
|
||||
|
||||
// frame could be null after dispatching pointer events.
|
||||
if (aGUIEvent->mClass == eTouchEventClass) {
|
||||
if (aGUIEvent->mMessage == eTouchStart) {
|
||||
WidgetTouchEvent* touchEvent = aGUIEvent->AsTouchEvent();
|
||||
if (nsIFrame* newFrame =
|
||||
TouchManager::SuppressInvalidPointsAndGetTargetedFrame(
|
||||
touchEvent)) {
|
||||
eventTargetData.SetFrameAndComputePresShellAndContent(newFrame,
|
||||
aGUIEvent);
|
||||
}
|
||||
} else if (PresShell* newShell =
|
||||
PresShell::GetShellForTouchEvent(aGUIEvent)) {
|
||||
// Touch events (except touchstart) are dispatching to the captured
|
||||
// element. Get correct shell from it.
|
||||
eventTargetData.mPresShell = newShell;
|
||||
}
|
||||
}
|
||||
// XXX Despite of this comment, we update the event target data outside
|
||||
// DispatchPrecedingPointerEvent(). Can we make it call
|
||||
// UpdateTouchEventTarget()?
|
||||
eventTargetData.UpdateTouchEventTarget(aGUIEvent);
|
||||
|
||||
// Handle the event in the correct shell.
|
||||
// We pass the subshell's root frame as the frame to start from. This is
|
||||
@ -10865,3 +10853,32 @@ bool PresShell::EventHandler::EventTargetData::ComputeElementFromFrame(
|
||||
// If we found an element, target it. Otherwise, target *nothing*.
|
||||
return !!mContent;
|
||||
}
|
||||
|
||||
void PresShell::EventHandler::EventTargetData::UpdateTouchEventTarget(
|
||||
WidgetGUIEvent* aGUIEvent) {
|
||||
MOZ_ASSERT(aGUIEvent);
|
||||
|
||||
if (aGUIEvent->mClass != eTouchEventClass) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aGUIEvent->mMessage == eTouchStart) {
|
||||
WidgetTouchEvent* touchEvent = aGUIEvent->AsTouchEvent();
|
||||
nsIFrame* newFrame =
|
||||
TouchManager::SuppressInvalidPointsAndGetTargetedFrame(touchEvent);
|
||||
if (!newFrame) {
|
||||
return; // XXX Why don't we stop handling the event in this case?
|
||||
}
|
||||
SetFrameAndComputePresShellAndContent(newFrame, aGUIEvent);
|
||||
return;
|
||||
}
|
||||
|
||||
PresShell* newPresShell = PresShell::GetShellForTouchEvent(aGUIEvent);
|
||||
if (!newPresShell) {
|
||||
return; // XXX Why don't we stop handling the event in this case?
|
||||
}
|
||||
|
||||
// Touch events (except touchstart) are dispatching to the captured
|
||||
// element. Get correct shell from it.
|
||||
mPresShell = newPresShell;
|
||||
}
|
||||
|
@ -639,6 +639,15 @@ class PresShell final : public nsIPresShell,
|
||||
*/
|
||||
bool ComputeElementFromFrame(WidgetGUIEvent* aGUIEvent);
|
||||
|
||||
/**
|
||||
* UpdateTouchEventTarget() updates mFrame, mPresShell and mContent if
|
||||
* aGUIEvent is a touch event and there is new proper target.
|
||||
*
|
||||
* @param aGUIEvent The handled event. If it's not a touch event,
|
||||
* this method does nothing.
|
||||
*/
|
||||
void UpdateTouchEventTarget(WidgetGUIEvent* aGUIEvent);
|
||||
|
||||
RefPtr<PresShell> mPresShell;
|
||||
nsIFrame* mFrame;
|
||||
nsCOMPtr<nsIContent> mContent;
|
||||
|
@ -35,16 +35,11 @@ package org.mozilla.geckoview {
|
||||
method public void addDrawCallback(@android.support.annotation.NonNull java.lang.Runnable);
|
||||
method public int getClearColor();
|
||||
method @android.support.annotation.Nullable public java.lang.Runnable getFirstPaintCallback();
|
||||
method public void getPixels(@android.support.annotation.NonNull org.mozilla.geckoview.CompositorController.GetPixelsCallback);
|
||||
method public void removeDrawCallback(@android.support.annotation.NonNull java.lang.Runnable);
|
||||
method public void setClearColor(int);
|
||||
method public void setFirstPaintCallback(@android.support.annotation.Nullable java.lang.Runnable);
|
||||
}
|
||||
|
||||
public static interface CompositorController.GetPixelsCallback {
|
||||
method @android.support.annotation.UiThread public void onPixelsResult(int, int, @android.support.annotation.Nullable java.nio.IntBuffer);
|
||||
}
|
||||
|
||||
@android.support.annotation.AnyThread public class ContentBlocking {
|
||||
ctor public ContentBlocking();
|
||||
field public static final int AT_AD = 2;
|
||||
@ -136,6 +131,7 @@ package org.mozilla.geckoview {
|
||||
|
||||
public class GeckoDisplay {
|
||||
ctor protected GeckoDisplay(org.mozilla.geckoview.GeckoSession);
|
||||
method @android.support.annotation.UiThread @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoResult<android.graphics.Bitmap> capturePixels();
|
||||
method @android.support.annotation.UiThread public void screenOriginChanged(int, int);
|
||||
method @android.support.annotation.UiThread public boolean shouldPinOnScreen();
|
||||
method @android.support.annotation.UiThread public void surfaceChanged(@android.support.annotation.NonNull android.view.Surface, int, int);
|
||||
@ -735,6 +731,7 @@ package org.mozilla.geckoview {
|
||||
@android.support.annotation.UiThread public class GeckoView extends android.widget.FrameLayout {
|
||||
ctor public GeckoView(android.content.Context);
|
||||
ctor public GeckoView(android.content.Context, android.util.AttributeSet);
|
||||
method @android.support.annotation.UiThread @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoResult<android.graphics.Bitmap> capturePixels();
|
||||
method public void coverUntilFirstPaint(int);
|
||||
method @android.support.annotation.NonNull public org.mozilla.geckoview.DynamicToolbarAnimator getDynamicToolbarAnimator();
|
||||
method @android.support.annotation.AnyThread @android.support.annotation.NonNull public org.mozilla.gecko.EventDispatcher getEventDispatcher();
|
||||
|
@ -86,6 +86,9 @@
|
||||
|
||||
# GeckoView specific rules.
|
||||
|
||||
# Keep everthing in org.mozilla.geckoview
|
||||
-keep class org.mozilla.geckoview.** { *; }
|
||||
|
||||
-keep class org.mozilla.gecko.SysInfo {
|
||||
*;
|
||||
}
|
||||
|
@ -0,0 +1,6 @@
|
||||
<html>
|
||||
<head><title>Colours</title></head>
|
||||
<body style="background-color:green;">
|
||||
<div id="fullscreen" style="width:100%;height:100%;position:fixed;top:0;left:0;z-index:100;"></div>
|
||||
</body>
|
||||
</html>
|
@ -53,6 +53,7 @@ open class BaseSessionTest(noErrorCollector: Boolean = false) {
|
||||
const val IFRAME_REDIRECT_AUTOMATION = "/assets/www/iframe_redirect_automation.html"
|
||||
const val AUTOPLAY_PATH = "/assets/www/autoplay.html"
|
||||
const val SCROLL_TEST_PATH = "/assets/www/scroll.html"
|
||||
const val COLORS_HTML_PATH = "/assets/www/colors.html"
|
||||
}
|
||||
|
||||
@get:Rule val sessionRule = GeckoSessionTestRule()
|
||||
|
@ -0,0 +1,106 @@
|
||||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
package org.mozilla.geckoview.test
|
||||
|
||||
|
||||
import android.graphics.*
|
||||
import android.support.test.filters.MediumTest
|
||||
import android.support.test.runner.AndroidJUnit4
|
||||
import android.view.Surface
|
||||
import org.hamcrest.Matchers.notNullValue
|
||||
import org.hamcrest.Matchers.nullValue
|
||||
import org.junit.Assert.fail
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.ExpectedException
|
||||
import org.junit.runner.RunWith
|
||||
import org.mozilla.geckoview.GeckoResult
|
||||
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.ReuseSession
|
||||
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.WithDisplay
|
||||
|
||||
const val SCREEN_HEIGHT = 100
|
||||
const val SCREEN_WIDTH = 100
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@MediumTest
|
||||
@ReuseSession(false)
|
||||
class ScreenshotTest : BaseSessionTest() {
|
||||
|
||||
@get:Rule
|
||||
val expectedEx: ExpectedException = ExpectedException.none()
|
||||
|
||||
private fun getComparisonScreenshot(width: Int, height: Int): Bitmap {
|
||||
val screenshotFile = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
||||
val canvas = Canvas(screenshotFile)
|
||||
val paint = Paint()
|
||||
paint.color = Color.rgb(0, 128, 0)
|
||||
canvas.drawRect(0f, 0f, width.toFloat(), height.toFloat(), paint)
|
||||
return screenshotFile
|
||||
}
|
||||
|
||||
private fun assertScreenshotResult(result: GeckoResult<Bitmap>, comparisonImage: Bitmap) {
|
||||
sessionRule.waitForResult(result).let {
|
||||
assertThat("Screenshot is not null",
|
||||
it, notNullValue())
|
||||
assert(it.sameAs(comparisonImage)) { "Screenshots are the same" }
|
||||
}
|
||||
}
|
||||
|
||||
@WithDisplay(height = SCREEN_HEIGHT, width = SCREEN_WIDTH)
|
||||
@Test
|
||||
fun capturePixelsSucceeds() {
|
||||
val screenshotFile = getComparisonScreenshot(SCREEN_WIDTH, SCREEN_HEIGHT)
|
||||
|
||||
sessionRule.session.loadTestPath(COLORS_HTML_PATH)
|
||||
sessionRule.waitForPageStop()
|
||||
|
||||
sessionRule.display?.let {
|
||||
assertScreenshotResult(it.capturePixels(), screenshotFile)
|
||||
}
|
||||
}
|
||||
|
||||
@WithDisplay(height = SCREEN_HEIGHT, width = SCREEN_WIDTH)
|
||||
@Test
|
||||
fun capturePixelsCanBeCalledMultipleTimes() {
|
||||
val screenshotFile = getComparisonScreenshot(SCREEN_WIDTH, SCREEN_HEIGHT)
|
||||
|
||||
sessionRule.session.loadTestPath(COLORS_HTML_PATH)
|
||||
sessionRule.waitForPageStop()
|
||||
|
||||
sessionRule.display?.let {
|
||||
val call1 = it.capturePixels()
|
||||
val call2 = it.capturePixels()
|
||||
val call3 = it.capturePixels()
|
||||
assertScreenshotResult(call1, screenshotFile)
|
||||
assertScreenshotResult(call2, screenshotFile)
|
||||
assertScreenshotResult(call3, screenshotFile)
|
||||
}
|
||||
}
|
||||
|
||||
@WithDisplay(height = SCREEN_HEIGHT, width = SCREEN_WIDTH)
|
||||
@Test
|
||||
fun capturePixelsCompletesCompositorPausedRestarted() {
|
||||
sessionRule.display?.let {
|
||||
it.surfaceDestroyed()
|
||||
val result = it.capturePixels()
|
||||
val texture = SurfaceTexture(0)
|
||||
texture.setDefaultBufferSize(SCREEN_WIDTH, SCREEN_HEIGHT)
|
||||
val surface = Surface(texture)
|
||||
it.surfaceChanged(surface, SCREEN_WIDTH, SCREEN_HEIGHT)
|
||||
sessionRule.waitForResult(result)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun capturePixelsThrowsCompositorNotReady() {
|
||||
expectedEx.expect(IllegalStateException::class.java)
|
||||
expectedEx.expectMessage("Compositor must be ready before pixels can be captured")
|
||||
val session = sessionRule.createClosedSession()
|
||||
val display = session.acquireDisplay()
|
||||
|
||||
sessionRule.waitForResult(display.capturePixels())
|
||||
fail("IllegalStateException expected to be thrown")
|
||||
}
|
||||
}
|
@ -36,6 +36,7 @@ import org.junit.runner.Description;
|
||||
import org.junit.runners.model.Statement;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.net.LocalSocketAddress;
|
||||
@ -958,6 +959,10 @@ public class GeckoSessionTestRule implements TestRule {
|
||||
return RuntimeCreator.getRuntime();
|
||||
}
|
||||
|
||||
public @Nullable GeckoDisplay getDisplay() {
|
||||
return mDisplay;
|
||||
}
|
||||
|
||||
protected static Object setDelegate(final @NonNull Class<?> cls,
|
||||
final @NonNull GeckoSession session,
|
||||
final @Nullable Object delegate)
|
||||
@ -1211,9 +1216,10 @@ public class GeckoSessionTestRule implements TestRule {
|
||||
prepareSession(mMainSession);
|
||||
|
||||
if (mDisplaySize != null) {
|
||||
mDisplayTexture = new SurfaceTexture(0);
|
||||
mDisplaySurface = new Surface(mDisplayTexture);
|
||||
mDisplay = mMainSession.acquireDisplay();
|
||||
mDisplayTexture = new SurfaceTexture(0);
|
||||
mDisplayTexture.setDefaultBufferSize(mDisplaySize.x, mDisplaySize.y);
|
||||
mDisplaySurface = new Surface(mDisplayTexture);
|
||||
mDisplay.surfaceChanged(mDisplaySurface, mDisplaySize.x, mDisplaySize.y);
|
||||
}
|
||||
|
||||
@ -1288,7 +1294,6 @@ public class GeckoSessionTestRule implements TestRule {
|
||||
// We cannot detect initial page load without progress delegate.
|
||||
assertThat("ProgressDelegate cannot be null-delegate when opening session",
|
||||
GeckoSession.ProgressDelegate.class, not(isIn(mNullDelegates)));
|
||||
|
||||
mCallRecordHandler = new CallRecordHandler() {
|
||||
private boolean mIsAboutBlank = !lookForAboutBlank;
|
||||
|
||||
|
@ -8,11 +8,13 @@ package org.mozilla.geckoview;
|
||||
import org.mozilla.gecko.annotation.RobocopTarget;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.UiThread;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -21,13 +23,7 @@ import java.util.List;
|
||||
public final class CompositorController {
|
||||
private final GeckoSession.Compositor mCompositor;
|
||||
|
||||
public interface GetPixelsCallback {
|
||||
@UiThread
|
||||
void onPixelsResult(int width, int height, @Nullable IntBuffer pixels);
|
||||
}
|
||||
|
||||
private List<Runnable> mDrawCallbacks;
|
||||
private GetPixelsCallback mGetPixelsCallback;
|
||||
private int mDefaultClearColor = Color.WHITE;
|
||||
private Runnable mFirstPaintCallback;
|
||||
|
||||
@ -93,32 +89,6 @@ public final class CompositorController {
|
||||
}
|
||||
}
|
||||
|
||||
/* package */ void recvScreenPixels(final int width, final int height,
|
||||
final int[] pixels) {
|
||||
if (mGetPixelsCallback != null) {
|
||||
mGetPixelsCallback.onPixelsResult(width, height, IntBuffer.wrap(pixels));
|
||||
mGetPixelsCallback = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request current pixel values from the compositor. May be called on any thread. Must
|
||||
* not be called again until the callback is invoked.
|
||||
*
|
||||
* @param callback Callback for getting pixels.
|
||||
*/
|
||||
@RobocopTarget
|
||||
public void getPixels(final @NonNull GetPixelsCallback callback) {
|
||||
ThreadUtils.assertOnUiThread();
|
||||
|
||||
if (mCompositor.isReady()) {
|
||||
mGetPixelsCallback = callback;
|
||||
mCompositor.requestScreenPixels();
|
||||
} else {
|
||||
callback.onPixelsResult(0, 0, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current clear color when drawing.
|
||||
*
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
package org.mozilla.geckoview;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.UiThread;
|
||||
import android.view.Surface;
|
||||
@ -118,4 +119,31 @@ public class GeckoDisplay {
|
||||
ThreadUtils.assertOnUiThread();
|
||||
return session.getDisplay() == this && session.shouldPinOnScreen();
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a {@link Bitmap} of the visible portion of the web page currently being
|
||||
* rendered.
|
||||
*
|
||||
* Returned {@link Bitmap} will have the same dimensions as the {@link Surface} the
|
||||
* {@link GeckoDisplay} is currently using.
|
||||
*
|
||||
* If the {@link GeckoSession#isCompositorReady} is false the {@link GeckoResult} will complete
|
||||
* with an {@link IllegalStateException}.
|
||||
*
|
||||
* This function must be called on the UI thread.
|
||||
*
|
||||
* @return A {@link GeckoResult} that completes with a {@link Bitmap} containing
|
||||
* the pixels and size information of the currently visible rendered web page.
|
||||
*/
|
||||
@UiThread
|
||||
public @NonNull GeckoResult<Bitmap> capturePixels() {
|
||||
ThreadUtils.assertOnUiThread();
|
||||
if (!session.isCompositorReady()) {
|
||||
return GeckoResult.fromException(
|
||||
new IllegalStateException("Compositor must be ready before pixels can be captured"));
|
||||
}
|
||||
GeckoResult<Bitmap> result = new GeckoResult<>();
|
||||
session.mCompositor.requestScreenPixels(result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package org.mozilla.geckoview;
|
||||
|
||||
import org.mozilla.gecko.annotation.RobocopTarget;
|
||||
import org.mozilla.gecko.annotation.WrapForJNI;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
|
@ -9,9 +9,6 @@ package org.mozilla.geckoview;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.net.URLConnection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.mozilla.gecko.annotation.WrapForJNI;
|
||||
@ -31,6 +28,7 @@ import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
@ -216,12 +214,7 @@ public class GeckoSession implements Parcelable {
|
||||
public native void setDefaultClearColor(int color);
|
||||
|
||||
@WrapForJNI(calledFrom = "ui", dispatchTo = "current")
|
||||
public native void requestScreenPixels();
|
||||
|
||||
@WrapForJNI(calledFrom = "ui")
|
||||
private void recvScreenPixels(int width, int height, int[] pixels) {
|
||||
GeckoSession.this.recvScreenPixels(width, height, pixels);
|
||||
}
|
||||
/* package */ native void requestScreenPixels(final GeckoResult<Bitmap> result);
|
||||
|
||||
@WrapForJNI(calledFrom = "ui", dispatchTo = "current")
|
||||
public native void enableLayerUpdateNotifications(boolean enable);
|
||||
@ -4364,12 +4357,6 @@ public class GeckoSession implements Parcelable {
|
||||
}
|
||||
}
|
||||
|
||||
/* package */ void recvScreenPixels(int width, int height, int[] pixels) {
|
||||
if (mController != null) {
|
||||
mController.recvScreenPixels(width, height, pixels);
|
||||
}
|
||||
}
|
||||
|
||||
/* package */ boolean isCompositorReady() {
|
||||
return mCompositorReady;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ package org.mozilla.geckoview;
|
||||
import org.mozilla.gecko.AndroidGamepadManager;
|
||||
import org.mozilla.gecko.EventDispatcher;
|
||||
import org.mozilla.gecko.InputMethods;
|
||||
import org.mozilla.gecko.annotation.RobocopTarget;
|
||||
import org.mozilla.gecko.util.ActivityUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
@ -17,6 +18,7 @@ import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Rect;
|
||||
@ -166,6 +168,22 @@ public class GeckoView extends FrameLayout {
|
||||
public boolean shouldPinOnScreen() {
|
||||
return mDisplay != null ? mDisplay.shouldPinOnScreen() : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a {@link Bitmap} of the visible portion of the web page currently being
|
||||
* rendered.
|
||||
*
|
||||
* @return A {@link GeckoResult} that completes with a {@link Bitmap} containing
|
||||
* the pixels and size information of the currently visible rendered web page.
|
||||
*/
|
||||
@UiThread
|
||||
@NonNull GeckoResult<Bitmap> capturePixels() {
|
||||
if (mDisplay == null) {
|
||||
return GeckoResult.fromException(new IllegalStateException("Display must be created before pixels can be captured"));
|
||||
}
|
||||
|
||||
return mDisplay.capturePixels();
|
||||
}
|
||||
}
|
||||
|
||||
public GeckoView(final Context context) {
|
||||
@ -709,4 +727,18 @@ public class GeckoView extends FrameLayout {
|
||||
}
|
||||
mSession.getTextInput().autofill(strValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a {@link Bitmap} of the visible portion of the web page currently being
|
||||
* rendered.
|
||||
*
|
||||
* See {@link GeckoDisplay#capturePixels} for more details.
|
||||
*
|
||||
* @return A {@link GeckoResult} that completes with a {@link Bitmap} containing
|
||||
* the pixels and size information of the currently visible rendered web page.
|
||||
*/
|
||||
@UiThread
|
||||
public @NonNull GeckoResult<Bitmap> capturePixels() {
|
||||
return mDisplay.capturePixels();
|
||||
}
|
||||
}
|
||||
|
@ -73,6 +73,18 @@ exclude: true
|
||||
|
||||
[67.15]: ../GeckoRuntime.html#registerWebExtension-org.mozilla.geckoview.WebExtension-
|
||||
|
||||
- Added API to [`GeckoView`][65.5] to take screenshot of the visible page. Calling [`capturePixels`][67.16] returns a ['GeckoResult'][65.25] that completes to a [`Bitmap`][67.17] of the current [`Surface`][67.18] contents, or an [`IllegalStateException`][67.19] if the [`GeckoSession`][65.9] is not ready to render content.
|
||||
|
||||
[67.16]: ../GeckoView.html#capturePixels
|
||||
[67.17]: https://developer.android.com/reference/android/graphics/Bitmap
|
||||
[67.18]: https://developer.android.com/reference/android/view/Surface
|
||||
[67.19]: https://developer.android.com/reference/java/lang/IllegalStateException
|
||||
|
||||
- Added API to capture a screenshot to [`GeckoDisplay`][67.20]. [`capturePixels`][67.21] returns a ['GeckoResult'][65.25] that completes to a [`Bitmap`][67.16] of the current [`Surface`][67.17] contents, or an [`IllegalStateException`][67.18] if the [`GeckoSession`][65.9] is not ready to render content.
|
||||
|
||||
[67.20]: ../GeckoDisplay.html
|
||||
[67.21]: ../GeckoDisplay.html#capturePixels
|
||||
|
||||
## v66
|
||||
- Removed redundant field `trackingMode` from [`SecurityInformation`][66.6].
|
||||
Use `TrackingProtectionDelegate.onTrackerBlocked` for notification of blocked
|
||||
@ -192,4 +204,4 @@ exclude: true
|
||||
[65.24]: ../CrashReporter.html#sendCrashReport-android.content.Context-android.os.Bundle-java.lang.String-
|
||||
[65.25]: ../GeckoResult.html
|
||||
|
||||
[api-version]: df89fa914cfd095b37e696f3e767b55fc03a4835
|
||||
[api-version]: 0bcb9f0f763b746bb6f27f5d275c351818ab971b
|
||||
|
@ -43,7 +43,6 @@ import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Locale;
|
||||
|
@ -13,6 +13,7 @@ import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@ -20,7 +21,6 @@ import java.util.Map;
|
||||
import java.lang.StringBuffer;
|
||||
import java.lang.Math;
|
||||
|
||||
import org.mozilla.geckoview.CompositorController;
|
||||
import org.mozilla.gecko.gfx.PanningPerfAPI;
|
||||
import org.mozilla.gecko.util.BundleEventListener;
|
||||
import org.mozilla.gecko.util.EventCallback;
|
||||
@ -29,12 +29,13 @@ import org.mozilla.gecko.util.StrictModeContext;
|
||||
import org.mozilla.geckoview.GeckoView;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.Bitmap;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
import com.robotium.solo.Solo;
|
||||
|
||||
public class FennecNativeDriver implements Driver, CompositorController.GetPixelsCallback {
|
||||
public class FennecNativeDriver implements Driver {
|
||||
private static final int FRAME_TIME_THRESHOLD = 25; // allow 25ms per frame (40fps)
|
||||
|
||||
private final Activity mActivity;
|
||||
@ -191,15 +192,10 @@ public class FennecNativeDriver implements Driver, CompositorController.GetPixel
|
||||
}
|
||||
|
||||
private volatile boolean mGotPixelsResult;
|
||||
private int mPixelsWidth;
|
||||
private int mPixelsHeight;
|
||||
private IntBuffer mPixelsResult;
|
||||
private Bitmap mPixelsResult;
|
||||
|
||||
@Override
|
||||
public synchronized void onPixelsResult(int aWidth, int aHeight, IntBuffer aPixels) {
|
||||
mPixelsWidth = aWidth;
|
||||
mPixelsHeight = aHeight;
|
||||
mPixelsResult = aPixels;
|
||||
public synchronized void onPixelsResult(final Bitmap aResult) {
|
||||
mPixelsResult = aResult;
|
||||
mGotPixelsResult = true;
|
||||
notifyAll();
|
||||
}
|
||||
@ -259,7 +255,10 @@ public class FennecNativeDriver implements Driver, CompositorController.GetPixel
|
||||
view.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
view.getSession().getCompositorController().getPixels(FennecNativeDriver.this);
|
||||
view.capturePixels().then( value -> {
|
||||
FennecNativeDriver.this.onPixelsResult(value);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@ -272,13 +271,12 @@ public class FennecNativeDriver implements Driver, CompositorController.GetPixel
|
||||
}
|
||||
}
|
||||
|
||||
final IntBuffer pixelBuffer = mPixelsResult;
|
||||
int w = mPixelsWidth;
|
||||
int h = mPixelsHeight;
|
||||
final ByteBuffer pixelBuffer = ByteBuffer.allocate(mPixelsResult.getByteCount());
|
||||
mPixelsResult.copyPixelsToBuffer(pixelBuffer);
|
||||
int w = mPixelsResult.getWidth();
|
||||
int h = mPixelsResult.getHeight();
|
||||
|
||||
mGotPixelsResult = false;
|
||||
mPixelsWidth = 0;
|
||||
mPixelsHeight = 0;
|
||||
mPixelsResult = null;
|
||||
|
||||
|
||||
@ -291,9 +289,7 @@ public class FennecNativeDriver implements Driver, CompositorController.GetPixel
|
||||
// This allows the screen capture to be examined in the log output in a human
|
||||
// readable format.
|
||||
// logPixels(pixelBuffer, w, h);
|
||||
|
||||
// now we need to (1) flip the image, because GL likes to do things up-side-down,
|
||||
// and (2) rearrange the bits from AGBR-8888 to ARGB-8888.
|
||||
|
||||
pixelBuffer.position(0);
|
||||
String mapFile = mRootPath + "/pixels.map";
|
||||
|
||||
@ -304,13 +300,7 @@ public class FennecNativeDriver implements Driver, CompositorController.GetPixel
|
||||
fos = new FileOutputStream(mapFile);
|
||||
bos = new BufferedOutputStream(fos);
|
||||
dos = new DataOutputStream(bos);
|
||||
|
||||
for (int y = h - 1; y >= 0; y--) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
int agbr = pixelBuffer.get();
|
||||
dos.writeInt((agbr & 0xFF00FF00) | ((agbr >> 16) & 0x000000FF) | ((agbr << 16) & 0x00FF0000));
|
||||
}
|
||||
}
|
||||
dos.write(pixelBuffer.array());
|
||||
} catch (IOException e) {
|
||||
throw new RoboCopException("exception with pixel writer on file: " + mapFile);
|
||||
} finally {
|
||||
|
@ -38,9 +38,6 @@ NS_IMETHODIMP
|
||||
nsCryptoHash::Init(uint32_t algorithm) {
|
||||
HASH_HashType hashType;
|
||||
switch (algorithm) {
|
||||
case nsICryptoHash::MD2:
|
||||
hashType = HASH_AlgMD2;
|
||||
break;
|
||||
case nsICryptoHash::MD5:
|
||||
hashType = HASH_AlgMD5;
|
||||
break;
|
||||
@ -85,8 +82,6 @@ nsCryptoHash::Init(uint32_t algorithm) {
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCryptoHash::InitWithString(const nsACString &aAlgorithm) {
|
||||
if (aAlgorithm.LowerCaseEqualsLiteral("md2")) return Init(nsICryptoHash::MD2);
|
||||
|
||||
if (aAlgorithm.LowerCaseEqualsLiteral("md5")) return Init(nsICryptoHash::MD5);
|
||||
|
||||
if (aAlgorithm.LowerCaseEqualsLiteral("sha1"))
|
||||
|
@ -16,10 +16,11 @@ interface nsICryptoHash : nsISupports
|
||||
/**
|
||||
* Hashing Algorithms. These values are to be used by the
|
||||
* |init| method to indicate which hashing function to
|
||||
* use. These values map directly onto the values defined
|
||||
* in mozilla/security/nss/lib/cryptohi/hasht.h.
|
||||
* use. These values must be identical to the values defined
|
||||
* in security/nss/lib/util/hasht.h in type HASH_HashType.
|
||||
* This allows us to use NSS mapping functions like
|
||||
* HASH_GetHashOidTagByHashType with these values.
|
||||
*/
|
||||
const short MD2 = 1; /* String value: "md2" */
|
||||
const short MD5 = 2; /* String value: "md5" */
|
||||
const short SHA1 = 3; /* String value: "sha1" */
|
||||
const short SHA256 = 4; /* String value: "sha256" */
|
||||
|
@ -8,18 +8,6 @@ const messages = [
|
||||
"",
|
||||
];
|
||||
const ALGORITHMS = [
|
||||
{
|
||||
initString: "md2",
|
||||
initConstant: Ci.nsICryptoHash.MD2,
|
||||
hexHashes: [
|
||||
"03d85a0d629d2c442e987525319fc471",
|
||||
"8350e5a3e24c153df2275c9f80692773",
|
||||
],
|
||||
b64Hashes: [
|
||||
"A9haDWKdLEQumHUlMZ/EcQ==",
|
||||
"g1Dlo+JMFT3yJ1yfgGkncw==",
|
||||
],
|
||||
},
|
||||
{
|
||||
initString: "md5",
|
||||
initConstant: Ci.nsICryptoHash.MD5,
|
||||
|
@ -9,6 +9,15 @@ Unreleased
|
||||
|
||||
### Removed
|
||||
|
||||
- Dropped support for legacy Selenium web element references
|
||||
|
||||
The legacy way of serialising web elements, using `{"ELEMENT": <UUID>}`,
|
||||
has been removed in this release. This may break older Selenium
|
||||
clients and clients which are otherwise not compatible with the
|
||||
WebDriver standard.
|
||||
|
||||
Thanks to Shivam Singhal for this patch.
|
||||
|
||||
- Removed `--webdriver-port` command-line option
|
||||
|
||||
`--webdriver-port <PORT>` was an undocumented alias for `--port`,
|
||||
|
@ -14,7 +14,6 @@ use webdriver::error::{ErrorStatus, WebDriverError, WebDriverResult};
|
||||
use webdriver::httpapi::WebDriverExtensionRoute;
|
||||
|
||||
pub const CHROME_ELEMENT_KEY: &'static str = "chromeelement-9fc5-4b51-a3c8-01716eedeb04";
|
||||
pub const LEGACY_ELEMENT_KEY: &'static str = "ELEMENT";
|
||||
|
||||
pub fn extension_routes() -> Vec<(Method, &'static str, GeckoExtensionRoute)> {
|
||||
return vec![
|
||||
|
@ -1,7 +1,6 @@
|
||||
use crate::command::{
|
||||
AddonInstallParameters, AddonUninstallParameters, GeckoContextParameters,
|
||||
GeckoExtensionCommand, GeckoExtensionRoute, XblLocatorParameters, CHROME_ELEMENT_KEY,
|
||||
LEGACY_ELEMENT_KEY,
|
||||
};
|
||||
use mozprofile::preferences::Pref;
|
||||
use mozprofile::profile::Profile;
|
||||
@ -393,12 +392,10 @@ impl MarionetteSession {
|
||||
let chrome_element = data.get(CHROME_ELEMENT_KEY);
|
||||
let element = data.get(ELEMENT_KEY);
|
||||
let frame = data.get(FRAME_KEY);
|
||||
let legacy_element = data.get(LEGACY_ELEMENT_KEY);
|
||||
let window = data.get(WINDOW_KEY);
|
||||
|
||||
let value = try_opt!(
|
||||
element
|
||||
.or(legacy_element)
|
||||
.or(chrome_element)
|
||||
.or(frame)
|
||||
.or(window),
|
||||
|
@ -929,7 +929,6 @@ mod test {
|
||||
"type":"pointerMove",
|
||||
"duration":100,
|
||||
"origin":{
|
||||
"ELEMENT":"elem",
|
||||
"element-6066-11e4-a52e-4f735466cecf":"elem"
|
||||
},
|
||||
"x":5,
|
||||
@ -951,7 +950,7 @@ mod test {
|
||||
"type":"pointerMove",
|
||||
"duration":100,
|
||||
"origin":{
|
||||
"ELEMENT":"elem"
|
||||
"element-6066-11e4-a52e-4f735466cecf":"elem"
|
||||
},
|
||||
"x":5,
|
||||
"y":10
|
||||
|
@ -474,6 +474,10 @@ button.warning {
|
||||
-moz-box-align: center;
|
||||
}
|
||||
|
||||
.addon-view[type="theme"] .icon:-moz-locale-dir(rtl) {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
.content-container {
|
||||
-moz-box-align: center;
|
||||
}
|
||||
|
10
widget/android/bindings/AndroidGraphics-classes.txt
Normal file
10
widget/android/bindings/AndroidGraphics-classes.txt
Normal file
@ -0,0 +1,10 @@
|
||||
[android.graphics.Bitmap = skip:true]
|
||||
copyPixelsFromBuffer(Ljava/nio/Buffer;)V =
|
||||
createBitmap(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap; =
|
||||
|
||||
[android.graphics.Bitmap$Config = skip:true]
|
||||
valueOf(Ljava/lang/String;)Landroid/graphics/Bitmap$Config; =
|
||||
ALPHA_8 =
|
||||
ARGB_8888 =
|
||||
RGBA_F16 =
|
||||
RGB_565 =
|
2
widget/android/bindings/JavaExceptions-classes.txt
Normal file
2
widget/android/bindings/JavaExceptions-classes.txt
Normal file
@ -0,0 +1,2 @@
|
||||
[java.lang.IllegalStateException = skip:true]
|
||||
<init>(Ljava/lang/String;)V =
|
@ -12,10 +12,12 @@ with Files("**"):
|
||||
generated = [
|
||||
'AccessibilityEvent',
|
||||
'AndroidBuild',
|
||||
'AndroidGraphics',
|
||||
'AndroidInputType',
|
||||
'AndroidRect',
|
||||
'InetAddress',
|
||||
'JavaBuiltins',
|
||||
'JavaExceptions',
|
||||
'KeyEvent',
|
||||
'MediaCodec',
|
||||
'MotionEvent',
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <android/native_window.h>
|
||||
#include <android/native_window_jni.h>
|
||||
#include <math.h>
|
||||
#include <queue>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "mozilla/MiscEvents.h"
|
||||
@ -24,6 +25,8 @@
|
||||
#include "mozilla/Unused.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/layers/RenderTrace.h"
|
||||
#include "mozilla/gfx/DataSurfaceHelpers.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include <algorithm>
|
||||
|
||||
using mozilla::Unused;
|
||||
@ -32,6 +35,9 @@ using mozilla::dom::ContentParent;
|
||||
|
||||
#include "nsWindow.h"
|
||||
|
||||
#include "AndroidGraphics.h"
|
||||
#include "JavaExceptions.h"
|
||||
|
||||
#include "nsIBaseWindow.h"
|
||||
#include "nsIBrowserDOMWindow.h"
|
||||
#include "nsIDOMChromeWindow.h"
|
||||
@ -797,6 +803,7 @@ class nsWindow::LayerViewSupport final
|
||||
GeckoSession::Compositor::WeakRef mCompositor;
|
||||
Atomic<bool, ReleaseAcquire> mCompositorPaused;
|
||||
jni::Object::GlobalRef mSurface;
|
||||
std::queue<java::GeckoResult::GlobalRef> mCapturePixelsResults;
|
||||
|
||||
// In order to use Event::HasSameTypeAs in PostTo(), we cannot make
|
||||
// LayerViewEvent a template because each template instantiation is
|
||||
@ -857,7 +864,11 @@ class nsWindow::LayerViewSupport final
|
||||
|
||||
uiThread->Dispatch(NS_NewRunnableFunction(
|
||||
"LayerViewSupport::OnDetach",
|
||||
[compositor, disposer = RefPtr<Runnable>(aDisposer)] {
|
||||
[compositor, disposer = RefPtr<Runnable>(aDisposer), result = &mCapturePixelsResults] {
|
||||
while (!result->empty()) {
|
||||
result->front()->CompleteExceptionally(java::sdk::IllegalStateException::New("The compositor has detached from the session").Cast<jni::Throwable>());
|
||||
result->pop();
|
||||
}
|
||||
compositor->OnCompositorDetached();
|
||||
disposer->Run();
|
||||
}));
|
||||
@ -882,6 +893,27 @@ class nsWindow::LayerViewSupport final
|
||||
return child.forget();
|
||||
}
|
||||
|
||||
int8_t* FlipScreenPixels(Shmem& aMem, const ScreenIntSize& aSize) {
|
||||
const IntSize size(aSize.width, aSize.height);
|
||||
RefPtr<DataSourceSurface> image = gfx::CreateDataSourceSurfaceFromData(
|
||||
size,
|
||||
SurfaceFormat::B8G8R8A8,
|
||||
aMem.get<uint8_t>(),
|
||||
StrideForFormatAndWidth(SurfaceFormat::B8G8R8A8, aSize.width));
|
||||
RefPtr<DrawTarget> drawTarget = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
|
||||
size, SurfaceFormat::B8G8R8A8);
|
||||
drawTarget->SetTransform(Matrix::Scaling(1.0, -1.0) * Matrix::Translation(0, aSize.height));
|
||||
|
||||
gfx::Rect drawRect(0, 0, aSize.width, aSize.height);
|
||||
drawTarget->DrawSurface(image, drawRect, drawRect);
|
||||
|
||||
RefPtr<SourceSurface> snapshot = drawTarget->Snapshot();
|
||||
RefPtr<DataSourceSurface> data = snapshot->GetDataSurface();
|
||||
DataSourceSurface::ScopedMap* smap =
|
||||
new DataSourceSurface::ScopedMap(data, DataSourceSurface::READ);
|
||||
return reinterpret_cast<int8_t*>(smap->GetData());
|
||||
}
|
||||
|
||||
/**
|
||||
* Compositor methods
|
||||
*/
|
||||
@ -1078,28 +1110,37 @@ class nsWindow::LayerViewSupport final
|
||||
}
|
||||
}
|
||||
|
||||
void RequestScreenPixels() {
|
||||
void RequestScreenPixels(jni::Object::Param aResult) {
|
||||
MOZ_ASSERT(AndroidBridge::IsJavaUiThread());
|
||||
if (RefPtr<UiCompositorControllerChild> child =
|
||||
GetUiCompositorControllerChild()) {
|
||||
child->RequestScreenPixels();
|
||||
mCapturePixelsResults.push(java::GeckoResult::GlobalRef(java::GeckoResult::LocalRef(aResult)));
|
||||
if (mCapturePixelsResults.size() == 1) {
|
||||
if (RefPtr<UiCompositorControllerChild> child =
|
||||
GetUiCompositorControllerChild()) {
|
||||
child->RequestScreenPixels();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RecvScreenPixels(Shmem&& aMem, const ScreenIntSize& aSize) {
|
||||
MOZ_ASSERT(AndroidBridge::IsJavaUiThread());
|
||||
|
||||
auto pixels =
|
||||
mozilla::jni::IntArray::New(aMem.get<int>(), aMem.Size<int>());
|
||||
auto compositor = GeckoSession::Compositor::LocalRef(mCompositor);
|
||||
if (compositor) {
|
||||
compositor->RecvScreenPixels(aSize.width, aSize.height, pixels);
|
||||
auto aResult = java::GeckoResult::LocalRef(mCapturePixelsResults.front());
|
||||
if (aResult) {
|
||||
auto pixels =
|
||||
mozilla::jni::ByteBuffer::New(FlipScreenPixels(aMem, aSize), aMem.Size<int8_t>());
|
||||
auto bitmap = java::sdk::Bitmap::CreateBitmap(aSize.width, aSize.height, java::sdk::Config::ARGB_8888());
|
||||
bitmap->CopyPixelsFromBuffer(pixels);
|
||||
aResult->Complete(bitmap);
|
||||
mCapturePixelsResults.pop();
|
||||
}
|
||||
|
||||
// Pixels have been copied, so Dealloc Shmem
|
||||
if (RefPtr<UiCompositorControllerChild> child =
|
||||
GetUiCompositorControllerChild()) {
|
||||
child->DeallocPixelBuffer(aMem);
|
||||
|
||||
if (!mCapturePixelsResults.empty()) {
|
||||
child->RequestScreenPixels();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user