mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:30:27 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- code style, spacing (d4f024213a)
- Bug 1205586 - new Date().toLocale{,Date,Time}String() should return appropriately differing strings as the local time zone/default locale change. r=till (cf46706e94)
- Bug 1204025 - Change Symbol.length to be 0 instead of 1. r=jorendorff (f1e3f45756)
- remove some PM esr38 diffs (f38809c3fa)
- Bug 1177018 - Send mouse move events generated via nsIPresShell::SynthesizeMouseMove() to the child process through a different IPDL message than real mouse move events. r=smaug (7029fe2d3b)
- Bug 1186135 - change active flag per channel. r=ehsan (239d99b7cc)
- Bug 1175940 - UIResolutionChanged should not trigger sync messages from content to chrome. r=mconley (147fbfd33a)
- Bug 1156662 - Identical code for different branches. r=bz (8487a27847)
- Bug 1183954 - Fix Notification.data structured cloning on workers. r=robertbindar,mccr8 (82187ef6c2)
- Bug 1189389 - nsIStructuredCloneContainer should use StructuredCloneHelper, r=smaug (6cddb9453a)
This commit is contained in:
@@ -26,7 +26,7 @@ namespace dom {
|
||||
class SpeakerManagerService;
|
||||
#endif
|
||||
|
||||
#define NUMBER_OF_AUDIO_CHANNELS (uint32_t)AudioChannel::Publicnotification + 1
|
||||
#define NUMBER_OF_AUDIO_CHANNELS (uint32_t)AudioChannel::EndGuard_
|
||||
|
||||
class AudioChannelService final : public nsIAudioChannelService
|
||||
, public nsIObserver
|
||||
|
||||
@@ -125,7 +125,6 @@ void
|
||||
StructuredCloneHelperInternal::Shutdown()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(!mShutdownCalled, "Shutdown already called!");
|
||||
mShutdownCalled = true;
|
||||
#endif
|
||||
|
||||
@@ -163,7 +162,6 @@ StructuredCloneHelperInternal::Read(JSContext* aCx,
|
||||
MOZ_ASSERT(!mShutdownCalled, "This method cannot be called after Shutdown.");
|
||||
|
||||
bool ok = mBuffer->read(aCx, aValue, &gCallbacks, this);
|
||||
mBuffer = nullptr;
|
||||
return ok;
|
||||
}
|
||||
|
||||
@@ -247,7 +245,11 @@ StructuredCloneHelper::Read(nsISupports* aParent,
|
||||
aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
|
||||
}
|
||||
|
||||
mBlobImplArray.Clear();
|
||||
// If we are tranferring something, we cannot call 'Read()' more than once.
|
||||
if (mSupportsTransferring) {
|
||||
mBlobImplArray.Clear();
|
||||
Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -257,6 +259,19 @@ StructuredCloneHelper::ReadFromBuffer(nsISupports* aParent,
|
||||
size_t aBufferLength,
|
||||
JS::MutableHandle<JS::Value> aValue,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
ReadFromBuffer(aParent, aCx, aBuffer, aBufferLength,
|
||||
JS_STRUCTURED_CLONE_VERSION, aValue, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
StructuredCloneHelper::ReadFromBuffer(nsISupports* aParent,
|
||||
JSContext* aCx,
|
||||
uint64_t* aBuffer,
|
||||
size_t aBufferLength,
|
||||
uint32_t aAlgorithmVersion,
|
||||
JS::MutableHandle<JS::Value> aValue,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(!mBuffer, "ReadFromBuffer() must be called without a Write().");
|
||||
MOZ_ASSERT(aBuffer);
|
||||
@@ -264,9 +279,8 @@ StructuredCloneHelper::ReadFromBuffer(nsISupports* aParent,
|
||||
mozilla::AutoRestore<nsISupports*> guard(mParent);
|
||||
mParent = aParent;
|
||||
|
||||
if (!JS_ReadStructuredClone(aCx, aBuffer, aBufferLength,
|
||||
JS_STRUCTURED_CLONE_VERSION, aValue,
|
||||
&gCallbacks, this)) {
|
||||
if (!JS_ReadStructuredClone(aCx, aBuffer, aBufferLength, aAlgorithmVersion,
|
||||
aValue, &gCallbacks, this)) {
|
||||
JS_ClearPendingException(aCx);
|
||||
aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
|
||||
}
|
||||
|
||||
@@ -159,10 +159,24 @@ public:
|
||||
JS::MutableHandle<JS::Value> aValue,
|
||||
ErrorResult &aRv);
|
||||
|
||||
void ReadFromBuffer(nsISupports* aParent,
|
||||
JSContext* aCx,
|
||||
uint64_t* aBuffer,
|
||||
size_t aBufferLength,
|
||||
uint32_t aAlgorithmVersion,
|
||||
JS::MutableHandle<JS::Value> aValue,
|
||||
ErrorResult &aRv);
|
||||
|
||||
// Use this method to free a buffer generated by MoveToBuffer().
|
||||
void FreeBuffer(uint64_t* aBuffer,
|
||||
size_t aBufferLength);
|
||||
|
||||
bool HasClonedDOMObjects() const
|
||||
{
|
||||
return !mBlobImplArray.IsEmpty() ||
|
||||
!mClonedImages.IsEmpty();
|
||||
}
|
||||
|
||||
nsTArray<nsRefPtr<BlobImpl>>& BlobImpls()
|
||||
{
|
||||
MOZ_ASSERT(mSupportsCloning, "Blobs cannot be taken/set if cloning is not supported.");
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "jsapi.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "js/StructuredClone.h"
|
||||
#include "xpcpublic.h"
|
||||
|
||||
#include "mozilla/Base64.h"
|
||||
#include "mozilla/dom/StructuredCloneHelper.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
NS_IMPL_ADDREF(nsStructuredCloneContainer)
|
||||
NS_IMPL_RELEASE(nsStructuredCloneContainer)
|
||||
@@ -31,60 +31,44 @@ NS_INTERFACE_MAP_BEGIN(nsStructuredCloneContainer)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
nsStructuredCloneContainer::nsStructuredCloneContainer()
|
||||
: mData(nullptr), mSize(0), mVersion(0)
|
||||
: StructuredCloneHelper(CloningSupported, TransferringNotSupported)
|
||||
, mState(eNotInitialized) , mData(nullptr), mSize(0), mVersion(0)
|
||||
{
|
||||
}
|
||||
|
||||
nsStructuredCloneContainer::~nsStructuredCloneContainer()
|
||||
{
|
||||
free(mData);
|
||||
if (mData) {
|
||||
free(mData);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
nsStructuredCloneContainer::InitFromJSVal(JS::Handle<JS::Value> aData,
|
||||
JSContext* aCx)
|
||||
{
|
||||
NS_ENSURE_STATE(!mData);
|
||||
|
||||
uint64_t* jsBytes = nullptr;
|
||||
bool success = false;
|
||||
if (aData.isPrimitive()) {
|
||||
success = JS_WriteStructuredClone(aCx, aData, &jsBytes, &mSize,
|
||||
nullptr, nullptr,
|
||||
JS::UndefinedHandleValue);
|
||||
} else {
|
||||
success = JS_WriteStructuredClone(aCx, aData, &jsBytes, &mSize,
|
||||
nullptr, nullptr,
|
||||
JS::UndefinedHandleValue);
|
||||
}
|
||||
NS_ENSURE_STATE(success);
|
||||
NS_ENSURE_STATE(jsBytes);
|
||||
|
||||
// Copy jsBytes into our own buffer.
|
||||
mData = (uint64_t*) malloc(mSize);
|
||||
if (!mData) {
|
||||
mSize = 0;
|
||||
mVersion = 0;
|
||||
|
||||
JS_ClearStructuredClone(jsBytes, mSize, nullptr, nullptr);
|
||||
if (mState != eNotInitialized) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
else {
|
||||
mVersion = JS_STRUCTURED_CLONE_VERSION;
|
||||
|
||||
ErrorResult rv;
|
||||
Write(aCx, aData, rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
memcpy(mData, jsBytes, mSize);
|
||||
|
||||
JS_ClearStructuredClone(jsBytes, mSize, nullptr, nullptr);
|
||||
mState = eInitializedFromJSVal;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
nsStructuredCloneContainer::InitFromBase64(const nsAString &aData,
|
||||
uint32_t aFormatVersion,
|
||||
JSContext *aCx)
|
||||
JSContext* aCx)
|
||||
{
|
||||
NS_ENSURE_STATE(!mData);
|
||||
if (mState != eNotInitialized) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_ConvertUTF16toUTF8 data(aData);
|
||||
|
||||
@@ -99,28 +83,56 @@ nsStructuredCloneContainer::InitFromBase64(const nsAString &aData,
|
||||
|
||||
mSize = binaryData.Length();
|
||||
mVersion = aFormatVersion;
|
||||
|
||||
mState = eInitializedFromBase64;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsStructuredCloneContainer::DeserializeToVariant(JSContext *aCx,
|
||||
nsIVariant **aData)
|
||||
nsStructuredCloneContainer::DeserializeToJsval(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aValue)
|
||||
{
|
||||
aValue.setNull();
|
||||
JS::Rooted<JS::Value> jsStateObj(aCx);
|
||||
|
||||
if (mState == eInitializedFromJSVal) {
|
||||
ErrorResult rv;
|
||||
Read(nullptr, aCx, &jsStateObj, rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(mState == eInitializedFromBase64);
|
||||
MOZ_ASSERT(mData);
|
||||
|
||||
ErrorResult rv;
|
||||
ReadFromBuffer(nullptr, aCx, mData, mSize, mVersion, &jsStateObj, rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
}
|
||||
|
||||
aValue.set(jsStateObj);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsStructuredCloneContainer::DeserializeToVariant(JSContext* aCx,
|
||||
nsIVariant** aData)
|
||||
{
|
||||
NS_ENSURE_STATE(mData);
|
||||
NS_ENSURE_ARG_POINTER(aData);
|
||||
*aData = nullptr;
|
||||
|
||||
if (mState == eNotInitialized) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Deserialize to a JS::Value.
|
||||
JS::Rooted<JS::Value> jsStateObj(aCx);
|
||||
bool hasTransferable = false;
|
||||
bool success = JS_ReadStructuredClone(aCx, mData, mSize, mVersion,
|
||||
&jsStateObj, nullptr, nullptr) &&
|
||||
JS_StructuredCloneHasTransferables(mData, mSize,
|
||||
&hasTransferable);
|
||||
// We want to be sure that mData doesn't contain transferable objects
|
||||
MOZ_ASSERT(!hasTransferable);
|
||||
NS_ENSURE_STATE(success && !hasTransferable);
|
||||
nsresult rv = DeserializeToJsval(aCx, &jsStateObj);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Now wrap the JS::Value as an nsIVariant.
|
||||
nsCOMPtr<nsIVariant> varStateObj;
|
||||
@@ -129,31 +141,64 @@ nsStructuredCloneContainer::DeserializeToVariant(JSContext *aCx,
|
||||
xpconnect->JSValToVariant(aCx, jsStateObj, getter_AddRefs(varStateObj));
|
||||
NS_ENSURE_STATE(varStateObj);
|
||||
|
||||
NS_ADDREF(*aData = varStateObj);
|
||||
varStateObj.forget(aData);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
nsStructuredCloneContainer::GetDataAsBase64(nsAString &aOut)
|
||||
{
|
||||
NS_ENSURE_STATE(mData);
|
||||
aOut.Truncate();
|
||||
|
||||
nsAutoCString binaryData(reinterpret_cast<char*>(mData), mSize);
|
||||
if (mState == eNotInitialized) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
uint64_t* data;
|
||||
size_t size;
|
||||
|
||||
if (mState == eInitializedFromJSVal) {
|
||||
if (HasClonedDOMObjects()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
data = BufferData();
|
||||
size = BufferSize();
|
||||
} else {
|
||||
MOZ_ASSERT(mState == eInitializedFromBase64);
|
||||
MOZ_ASSERT(mData);
|
||||
|
||||
data = mData;
|
||||
size = mSize;
|
||||
}
|
||||
|
||||
nsAutoCString binaryData(reinterpret_cast<char*>(data), size);
|
||||
nsAutoCString base64Data;
|
||||
nsresult rv = Base64Encode(binaryData, base64Data);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
aOut.Assign(NS_ConvertASCIItoUTF16(base64Data));
|
||||
CopyASCIItoUTF16(base64Data, aOut);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsStructuredCloneContainer::GetSerializedNBytes(uint64_t *aSize)
|
||||
NS_IMETHODIMP
|
||||
nsStructuredCloneContainer::GetSerializedNBytes(uint64_t* aSize)
|
||||
{
|
||||
NS_ENSURE_STATE(mData);
|
||||
NS_ENSURE_ARG_POINTER(aSize);
|
||||
|
||||
if (mState == eNotInitialized) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (mState == eInitializedFromJSVal) {
|
||||
*aSize = BufferSize();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mState == eInitializedFromBase64);
|
||||
|
||||
// mSize is a size_t, while aSize is a uint64_t. We rely on an implicit cast
|
||||
// here so that we'll get a compile error if a size_t-to-uint64_t cast is
|
||||
// narrowing.
|
||||
@@ -162,11 +207,21 @@ nsStructuredCloneContainer::GetSerializedNBytes(uint64_t *aSize)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsStructuredCloneContainer::GetFormatVersion(uint32_t *aFormatVersion)
|
||||
NS_IMETHODIMP
|
||||
nsStructuredCloneContainer::GetFormatVersion(uint32_t* aFormatVersion)
|
||||
{
|
||||
NS_ENSURE_STATE(mData);
|
||||
NS_ENSURE_ARG_POINTER(aFormatVersion);
|
||||
|
||||
if (mState == eNotInitialized) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (mState == eInitializedFromJSVal) {
|
||||
*aFormatVersion = JS_STRUCTURED_CLONE_VERSION;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mState == eInitializedFromBase64);
|
||||
*aFormatVersion = mVersion;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "nsIStructuredCloneContainer.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/StructuredCloneHelper.h"
|
||||
|
||||
#define NS_STRUCTUREDCLONECONTAINER_CONTRACTID \
|
||||
"@mozilla.org/docshell/structured-clone-container;1"
|
||||
@@ -20,7 +21,9 @@
|
||||
{0xb8, 0x5f, 0x13, 0xce, 0xd8, 0x89, 0xee, 0xec} \
|
||||
}
|
||||
|
||||
class nsStructuredCloneContainer final : public nsIStructuredCloneContainer
|
||||
class nsStructuredCloneContainer final
|
||||
: public nsIStructuredCloneContainer
|
||||
, public mozilla::dom::StructuredCloneHelper
|
||||
{
|
||||
public:
|
||||
nsStructuredCloneContainer();
|
||||
@@ -31,6 +34,12 @@ class nsStructuredCloneContainer final : public nsIStructuredCloneContainer
|
||||
private:
|
||||
~nsStructuredCloneContainer();
|
||||
|
||||
enum {
|
||||
eNotInitialized = 0,
|
||||
eInitializedFromJSVal,
|
||||
eInitializedFromBase64,
|
||||
} mState;
|
||||
|
||||
uint64_t* mData;
|
||||
|
||||
// This needs to be size_t rather than a PR-type so it matches the JS API.
|
||||
|
||||
@@ -27,7 +27,7 @@ interface nsIDocument;
|
||||
* string containing a copy of the container's serialized data, using
|
||||
* getDataAsBase64.
|
||||
*/
|
||||
[scriptable, uuid(63eeafec-63f5-42c3-aea9-5c04678784e7)]
|
||||
[scriptable, uuid(c664aae7-0d67-4155-a2dd-a3861778626f)]
|
||||
interface nsIStructuredCloneContainer : nsISupports
|
||||
{
|
||||
/**
|
||||
@@ -45,9 +45,17 @@ interface nsIStructuredCloneContainer : nsISupports
|
||||
[implicit_jscontext]
|
||||
void initFromBase64(in AString aData,in unsigned long aFormatVersion);
|
||||
|
||||
/**
|
||||
* Deserializes this structured clone container returning it as a jsval.
|
||||
* Can be called on main and worker threads.
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
jsval deserializeToJsval();
|
||||
|
||||
/**
|
||||
* Deserialize the object this container holds, returning it wrapped as
|
||||
* an nsIVariant.
|
||||
* Main thread only!
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
nsIVariant deserializeToVariant();
|
||||
|
||||
+14
-1
@@ -621,6 +621,14 @@ child:
|
||||
* they are 'compressed' by dumping the oldest one.
|
||||
*/
|
||||
RealMouseMoveEvent(WidgetMouseEvent event) compress;
|
||||
/**
|
||||
* Mouse move events with |reason == eSynthesized| are sent via a separate
|
||||
* message because they do not generate DOM 'mousemove' events, and the
|
||||
* 'compress' attribute on RealMouseMoveEvent() could result in a
|
||||
* |reason == eReal| event being dropped in favour of an |eSynthesized|
|
||||
* event, and thus a DOM 'mousemove' event to be lost.
|
||||
*/
|
||||
SynthMouseMoveEvent(WidgetMouseEvent event);
|
||||
RealMouseButtonEvent(WidgetMouseEvent event);
|
||||
RealKeyEvent(WidgetKeyboardEvent event, MaybeNativeKeyBinding keyBinding);
|
||||
MouseWheelEvent(WidgetWheelEvent event, ScrollableLayerGuid aGuid, uint64_t aInputBlockId);
|
||||
@@ -713,8 +721,13 @@ child:
|
||||
/**
|
||||
* Tell the child that the UI resolution changed for the containing
|
||||
* window.
|
||||
* To avoid some sync messages from child to parent, we also send the dpi
|
||||
* and default scale with the notification.
|
||||
* If we don't know the dpi and default scale, we just pass in a negative
|
||||
* value (-1) but in the majority of the cases this saves us from two
|
||||
* sync requests from the child to the parent.
|
||||
*/
|
||||
UIResolutionChanged();
|
||||
UIResolutionChanged(float dpi, double scale);
|
||||
|
||||
/**
|
||||
* Tell the child that the system theme has changed, and that a repaint
|
||||
|
||||
+15
-7
@@ -8,7 +8,6 @@
|
||||
|
||||
#include "TabChild.h"
|
||||
|
||||
#include "AudioChannelService.h"
|
||||
#include "gfxPrefs.h"
|
||||
#ifdef ACCESSIBILITY
|
||||
#include "mozilla/a11y/DocAccessibleChild.h"
|
||||
@@ -601,7 +600,6 @@ TabChild::TabChild(nsIContentChild* aManager,
|
||||
, mDefaultScale(0)
|
||||
, mIPCOpen(true)
|
||||
, mParentIsActive(false)
|
||||
, mAudioChannelActive(false)
|
||||
{
|
||||
// In the general case having the TabParent tell us if APZ is enabled or not
|
||||
// doesn't really work because the TabParent itself may not have a reference
|
||||
@@ -631,6 +629,10 @@ TabChild::TabChild(nsIContentChild* aManager,
|
||||
observerService->AddObserver(this, topic.get(), false);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t idx = 0; idx < NUMBER_OF_AUDIO_CHANNELS; idx++) {
|
||||
mAudioChannelsActive.AppendElement(false);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@@ -714,8 +716,8 @@ TabChild::Observe(nsISupports *aSubject,
|
||||
|
||||
nsAutoString activeStr(aData);
|
||||
bool active = activeStr.EqualsLiteral("active");
|
||||
if (active != mAudioChannelActive) {
|
||||
mAudioChannelActive = active;
|
||||
if (active != mAudioChannelsActive[audioChannel]) {
|
||||
mAudioChannelsActive[audioChannel] = active;
|
||||
unused << SendAudioChannelActivityNotification(audioChannel, active);
|
||||
}
|
||||
}
|
||||
@@ -755,7 +757,7 @@ TabChild::Init()
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> docShellItem(do_QueryInterface(WebNavigation()));
|
||||
docShellItem->SetItemType(nsIDocShellTreeItem::typeContentWrapper);
|
||||
|
||||
|
||||
nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(WebNavigation());
|
||||
if (!baseWindow) {
|
||||
NS_ERROR("mWebNav doesn't QI to nsIBaseWindow");
|
||||
@@ -1875,6 +1877,12 @@ TabChild::RecvRealMouseMoveEvent(const WidgetMouseEvent& event)
|
||||
return RecvRealMouseButtonEvent(event);
|
||||
}
|
||||
|
||||
bool
|
||||
TabChild::RecvSynthMouseMoveEvent(const WidgetMouseEvent& event)
|
||||
{
|
||||
return RecvRealMouseButtonEvent(event);
|
||||
}
|
||||
|
||||
bool
|
||||
TabChild::RecvRealMouseButtonEvent(const WidgetMouseEvent& event)
|
||||
{
|
||||
@@ -2939,12 +2947,12 @@ TabChild::RecvRequestNotifyAfterRemotePaint()
|
||||
}
|
||||
|
||||
bool
|
||||
TabChild::RecvUIResolutionChanged()
|
||||
TabChild::RecvUIResolutionChanged(const float& aDpi, const double& aScale)
|
||||
{
|
||||
ScreenIntSize oldScreenSize = GetInnerSize();
|
||||
mDPI = 0;
|
||||
mDefaultScale = 0;
|
||||
static_cast<PuppetWidget*>(mPuppetWidget.get())->ClearBackingScaleCache();
|
||||
static_cast<PuppetWidget*>(mPuppetWidget.get())->UpdateBackingScaleCache(aDpi, aScale);
|
||||
nsCOMPtr<nsIDocument> document(GetDocument());
|
||||
nsCOMPtr<nsIPresShell> presShell = document->GetShell();
|
||||
if (presShell) {
|
||||
|
||||
+10
-7
@@ -34,6 +34,7 @@
|
||||
#include "mozilla/layers/CompositorTypes.h"
|
||||
#include "nsIWebBrowserChrome3.h"
|
||||
#include "mozilla/dom/ipc/IdType.h"
|
||||
#include "AudioChannelService.h"
|
||||
#include "PuppetWidget.h"
|
||||
|
||||
class nsICachedFileDescriptorListener;
|
||||
@@ -42,22 +43,22 @@ class nsIDOMWindowUtils;
|
||||
namespace mozilla {
|
||||
namespace layout {
|
||||
class RenderFrameChild;
|
||||
}
|
||||
} // namespace layout
|
||||
|
||||
namespace layers {
|
||||
class APZEventState;
|
||||
class ImageCompositeNotification;
|
||||
struct SetTargetAPZCCallback;
|
||||
struct SetAllowedTouchBehaviorCallback;
|
||||
}
|
||||
} // namespace layers
|
||||
|
||||
namespace widget {
|
||||
struct AutoCacheNativeKeyCommands;
|
||||
}
|
||||
} // namespace widget
|
||||
|
||||
namespace plugins {
|
||||
class PluginWidgetChild;
|
||||
}
|
||||
} // namespace plugins
|
||||
|
||||
namespace dom {
|
||||
|
||||
@@ -241,7 +242,7 @@ public:
|
||||
static already_AddRefed<TabChild> FindTabChild(const TabId& aTabId);
|
||||
|
||||
public:
|
||||
/**
|
||||
/**
|
||||
* This is expected to be called off the critical path to content
|
||||
* startup. This is an opportunity to load things that are slow
|
||||
* on the critical path.
|
||||
@@ -333,6 +334,7 @@ public:
|
||||
const int32_t& aModifiers,
|
||||
const bool& aIgnoreRootScrollFrame) override;
|
||||
virtual bool RecvRealMouseMoveEvent(const mozilla::WidgetMouseEvent& event) override;
|
||||
virtual bool RecvSynthMouseMoveEvent(const mozilla::WidgetMouseEvent& event) override;
|
||||
virtual bool RecvRealMouseButtonEvent(const mozilla::WidgetMouseEvent& event) override;
|
||||
virtual bool RecvRealDragEvent(const WidgetDragEvent& aEvent,
|
||||
const uint32_t& aDragAction,
|
||||
@@ -471,7 +473,7 @@ public:
|
||||
return GetFrom(docShell);
|
||||
}
|
||||
|
||||
virtual bool RecvUIResolutionChanged() override;
|
||||
virtual bool RecvUIResolutionChanged(const float& aDpi, const double& aScale) override;
|
||||
|
||||
virtual bool RecvThemeChanged(nsTArray<LookAndFeelInt>&& aLookAndFeelIntCache) override;
|
||||
|
||||
@@ -637,10 +639,11 @@ private:
|
||||
double mDefaultScale;
|
||||
bool mIPCOpen;
|
||||
bool mParentIsActive;
|
||||
bool mAudioChannelActive;
|
||||
bool mAsyncPanZoomEnabled;
|
||||
CSSSize mUnscaledInnerSize;
|
||||
|
||||
nsAutoTArray<bool, NUMBER_OF_AUDIO_CHANNELS> mAudioChannelsActive;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(TabChild);
|
||||
};
|
||||
|
||||
|
||||
+10
-2
@@ -1092,7 +1092,11 @@ TabParent::UIResolutionChanged()
|
||||
// mDPI being greater than 0, so this invalidates it.
|
||||
mDPI = -1;
|
||||
TryCacheDPIAndScale();
|
||||
unused << SendUIResolutionChanged();
|
||||
// If mDPI was set to -1 to invalidate it and then TryCacheDPIAndScale
|
||||
// fails to cache the values, then mDefaultScale.scale might be invalid.
|
||||
// We don't want to send that value to content. Just send -1 for it too in
|
||||
// that case.
|
||||
unused << SendUIResolutionChanged(mDPI, mDPI < 0 ? -1.0 : mDefaultScale.scale);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1391,7 +1395,11 @@ bool TabParent::SendRealMouseEvent(WidgetMouseEvent& event)
|
||||
}
|
||||
|
||||
if (NS_MOUSE_MOVE == event.mMessage) {
|
||||
return SendRealMouseMoveEvent(event);
|
||||
if (event.reason == WidgetMouseEvent::eSynthesized) {
|
||||
return SendSynthMouseMoveEvent(event);
|
||||
} else {
|
||||
return SendRealMouseMoveEvent(event);
|
||||
}
|
||||
}
|
||||
return SendRealMouseButtonEvent(event);
|
||||
}
|
||||
|
||||
@@ -701,8 +701,8 @@ Notification::Notification(nsIGlobalObject* aGlobal, const nsAString& aID,
|
||||
: DOMEventTargetHelper(),
|
||||
mWorkerPrivate(nullptr), mObserver(nullptr),
|
||||
mID(aID), mTitle(aTitle), mBody(aBody), mDir(aDir), mLang(aLang),
|
||||
mTag(aTag), mIconUrl(aIconUrl), mBehavior(aBehavior), mIsClosed(false),
|
||||
mIsStored(false), mTaskCount(0)
|
||||
mTag(aTag), mIconUrl(aIconUrl), mBehavior(aBehavior), mData(JS::NullValue()),
|
||||
mIsClosed(false), mIsStored(false), mTaskCount(0)
|
||||
{
|
||||
if (NS_IsMainThread()) {
|
||||
// We can only call this on the main thread because
|
||||
@@ -832,13 +832,6 @@ Notification::PersistNotification()
|
||||
nsString alertName;
|
||||
GetAlertName(alertName);
|
||||
|
||||
nsString dataString;
|
||||
nsCOMPtr<nsIStructuredCloneContainer> scContainer;
|
||||
scContainer = GetDataCloneContainer();
|
||||
if (scContainer) {
|
||||
scContainer->GetDataAsBase64(dataString);
|
||||
}
|
||||
|
||||
nsAutoString behavior;
|
||||
if (!mBehavior.ToJSON(behavior)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
@@ -853,7 +846,7 @@ Notification::PersistNotification()
|
||||
mTag,
|
||||
mIconUrl,
|
||||
alertName,
|
||||
dataString,
|
||||
mDataAsBase64,
|
||||
behavior,
|
||||
mScope);
|
||||
|
||||
@@ -918,6 +911,8 @@ Notification::CreateInternal(nsIGlobalObject* aGlobal,
|
||||
|
||||
Notification::~Notification()
|
||||
{
|
||||
mData.setUndefined();
|
||||
mozilla::DropJSObjects(this);
|
||||
AssertIsOnTargetThread();
|
||||
MOZ_ASSERT(!mFeature);
|
||||
MOZ_ASSERT(!mTempRef);
|
||||
@@ -925,15 +920,16 @@ Notification::~Notification()
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(Notification)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(Notification, DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mData)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDataObjectContainer)
|
||||
tmp->mData.setUndefined();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(Notification, DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mData)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDataObjectContainer)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(Notification, DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mData);
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(Notification, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(Notification, DOMEventTargetHelper)
|
||||
|
||||
@@ -1389,13 +1385,6 @@ Notification::ShowInternal()
|
||||
}
|
||||
MOZ_ASSERT(observer);
|
||||
|
||||
// mDataObjectContainer might be uninitialized here because the notification
|
||||
// was constructed with an undefined data property.
|
||||
nsString dataStr;
|
||||
if (mDataObjectContainer) {
|
||||
mDataObjectContainer->GetDataAsBase64(dataStr);
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G
|
||||
nsCOMPtr<nsIAppNotificationService> appNotifier =
|
||||
do_GetService("@mozilla.org/system-alerts-service;1");
|
||||
@@ -1423,7 +1412,7 @@ Notification::ShowInternal()
|
||||
ops.mDir = DirectionToString(mDir);
|
||||
ops.mLang = mLang;
|
||||
ops.mTag = mTag;
|
||||
ops.mData = dataStr;
|
||||
ops.mData = mDataAsBase64;
|
||||
ops.mMozbehavior = mBehavior;
|
||||
ops.mMozbehavior.mSoundFile = soundUrl;
|
||||
|
||||
@@ -1466,7 +1455,7 @@ Notification::ShowInternal()
|
||||
alertService->ShowAlertNotification(iconUrl, mTitle, mBody, true,
|
||||
uniqueCookie, observer, alertName,
|
||||
DirectionToString(mDir), mLang,
|
||||
dataStr, GetPrincipal(),
|
||||
mDataAsBase64, GetPrincipal(),
|
||||
inPrivateBrowsing);
|
||||
}
|
||||
|
||||
@@ -1972,52 +1961,73 @@ Notification::GetOrigin(nsIPrincipal* aPrincipal, nsString& aOrigin)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIStructuredCloneContainer* Notification::GetDataCloneContainer()
|
||||
{
|
||||
return mDataObjectContainer;
|
||||
}
|
||||
|
||||
void
|
||||
Notification::GetData(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aRetval)
|
||||
{
|
||||
if (!mData && mDataObjectContainer) {
|
||||
if (mData.isNull() && !mDataAsBase64.IsEmpty()) {
|
||||
nsresult rv;
|
||||
rv = mDataObjectContainer->DeserializeToVariant(aCx, getter_AddRefs(mData));
|
||||
auto container = new nsStructuredCloneContainer();
|
||||
rv = container->InitFromBase64(mDataAsBase64, JS_STRUCTURED_CLONE_VERSION,
|
||||
aCx);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aRetval.setNull();
|
||||
return;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> data(aCx);
|
||||
rv = container->DeserializeToJsval(aCx, &data);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aRetval.setNull();
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.isGCThing()) {
|
||||
mozilla::HoldJSObjects(this);
|
||||
}
|
||||
mData = data;
|
||||
}
|
||||
if (!mData) {
|
||||
if (mData.isNull()) {
|
||||
aRetval.setNull();
|
||||
return;
|
||||
}
|
||||
VariantToJsval(aCx, mData, aRetval);
|
||||
|
||||
JS::ExposeValueToActiveJS(mData);
|
||||
aRetval.set(mData);
|
||||
}
|
||||
|
||||
void
|
||||
Notification::InitFromJSVal(JSContext* aCx, JS::Handle<JS::Value> aData,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (mDataObjectContainer || aData.isNull()) {
|
||||
if (!mDataAsBase64.IsEmpty() || aData.isNull()) {
|
||||
return;
|
||||
}
|
||||
mDataObjectContainer = new nsStructuredCloneContainer();
|
||||
aRv = mDataObjectContainer->InitFromJSVal(aData, aCx);
|
||||
auto dataObjectContainer = new nsStructuredCloneContainer();
|
||||
aRv = dataObjectContainer->InitFromJSVal(aData, aCx);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
dataObjectContainer->GetDataAsBase64(mDataAsBase64);
|
||||
}
|
||||
|
||||
void Notification::InitFromBase64(JSContext* aCx, const nsAString& aData,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (mDataObjectContainer || aData.IsEmpty()) {
|
||||
if (!mDataAsBase64.IsEmpty() || aData.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// To and fro to ensure it is valid base64.
|
||||
auto container = new nsStructuredCloneContainer();
|
||||
aRv = container->InitFromBase64(aData, JS_STRUCTURED_CLONE_VERSION,
|
||||
aCx);
|
||||
mDataObjectContainer = container;
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
container->GetDataAsBase64(mDataAsBase64);
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
class nsIPrincipal;
|
||||
class nsIStructuredCloneContainer;
|
||||
class nsIVariant;
|
||||
|
||||
namespace mozilla {
|
||||
@@ -126,7 +125,7 @@ public:
|
||||
IMPL_EVENT_HANDLER(close)
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Notification, DOMEventTargetHelper)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(Notification, DOMEventTargetHelper)
|
||||
|
||||
static bool PrefEnabled(JSContext* aCx, JSObject* aObj);
|
||||
// Returns if Notification.get() is allowed for the current global.
|
||||
@@ -205,8 +204,6 @@ public:
|
||||
return mIsStored;
|
||||
}
|
||||
|
||||
nsIStructuredCloneContainer* GetDataCloneContainer();
|
||||
|
||||
static bool RequestPermissionEnabledForScope(JSContext* aCx, JSObject* /* unused */);
|
||||
|
||||
static void RequestPermission(const GlobalObject& aGlobal,
|
||||
@@ -359,11 +356,11 @@ protected:
|
||||
const nsString mLang;
|
||||
const nsString mTag;
|
||||
const nsString mIconUrl;
|
||||
nsCOMPtr<nsIStructuredCloneContainer> mDataObjectContainer;
|
||||
nsString mDataAsBase64;
|
||||
const NotificationBehavior mBehavior;
|
||||
|
||||
// It's null until GetData is first called
|
||||
nsCOMPtr<nsIVariant> mData;
|
||||
JS::Heap<JS::Value> mData;
|
||||
|
||||
nsString mAlertName;
|
||||
nsString mScope;
|
||||
|
||||
@@ -20,7 +20,9 @@ if (self.Notification) {
|
||||
lang: "",
|
||||
body: "This is a notification body",
|
||||
tag: "sometag",
|
||||
icon: "icon.png"
|
||||
icon: "icon.png",
|
||||
data: ["a complex object that should be", { "structured": "cloned" }],
|
||||
mozbehavior: { vibrationPattern: [30, 200, 30] },
|
||||
};
|
||||
var notification = new Notification("This is a title", options);
|
||||
|
||||
@@ -36,6 +38,8 @@ if (self.Notification) {
|
||||
is(notification.body, options.body, "body should get set");
|
||||
is(notification.tag, options.tag, "tag should get set");
|
||||
is(notification.icon, options.icon, "icon should get set");
|
||||
is(notification.data[0], "a complex object that should be", "data item 0 should be a matching string");
|
||||
is(notification.data[1]["structured"], "cloned", "data item 1 should be a matching object literal");
|
||||
|
||||
// store notification in test context
|
||||
this.notification = notification;
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
}
|
||||
|
||||
navigator.serviceWorker.ready.then(function(swr) {
|
||||
swr.showNotification("Hi there. The ServiceWorker should receive a click event for this.");
|
||||
swr.showNotification("Hi there. The ServiceWorker should receive a click event for this.", { data: { complex: ["jsval", 5] }});
|
||||
});
|
||||
|
||||
navigator.serviceWorker.onmessage = function(msg) {
|
||||
testWindow.callback();
|
||||
testWindow.callback(msg.data.result);
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
@@ -9,7 +9,11 @@ onnotificationclick = function(e) {
|
||||
}
|
||||
|
||||
clients.forEach(function(client) {
|
||||
client.postMessage("done");
|
||||
client.postMessage({ result: e.notification.data &&
|
||||
e.notification.data['complex'] &&
|
||||
e.notification.data['complex'][0] == "jsval" &&
|
||||
e.notification.data['complex'][1] == 5 });
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -23,11 +23,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=916893
|
||||
function testFrame(src) {
|
||||
var iframe = document.createElement("iframe");
|
||||
iframe.src = src;
|
||||
window.callback = function() {
|
||||
window.callback = function(result) {
|
||||
window.callback = null;
|
||||
document.body.removeChild(iframe);
|
||||
iframe = null;
|
||||
ok(true, "Got notificationclick event.");
|
||||
ok(result, "Got notificationclick event with correct data.");
|
||||
MockServices.unregister();
|
||||
SimpleTest.finish();
|
||||
};
|
||||
|
||||
+67
-15
@@ -5,9 +5,73 @@
|
||||
/*global intl_DateTimeFormat: false, */
|
||||
|
||||
|
||||
// This cache, once primed, has these properties:
|
||||
//
|
||||
// runtimeDefaultLocale:
|
||||
// Locale information provided by the embedding, guiding SpiderMonkey's
|
||||
// selection of a default locale. See RuntimeDefaultLocale(), whose
|
||||
// value controls the value returned by DefaultLocale() that's what's
|
||||
// *actually* used.
|
||||
// localTZA:
|
||||
// The local time zone's adjustment from UTC. See LocalTZA().
|
||||
// formatters:
|
||||
// A Record storing formatters consistent with the above
|
||||
// runtimeDefaultLocale/localTZA values, for use with the appropriate
|
||||
// ES6 toLocale*String Date method when called with its first two
|
||||
// arguments having the value |undefined|.
|
||||
//
|
||||
// The "formatters" Record has (some subset of) these properties, as determined
|
||||
// by all values of the first argument passed to |GetCachedFormat|:
|
||||
//
|
||||
// dateTimeFormat: for Date's toLocaleString operation
|
||||
// dateFormat: for Date's toLocaleDateString operation
|
||||
// timeFormat: for Date's toLocaleTimeString operation
|
||||
//
|
||||
// Using this cache, then, requires 1) verifying the current
|
||||
// runtimeDefaultLocale/localTZA are consistent with cached values, then
|
||||
// 2) seeing if the desired formatter is cached and returning it if so, or else
|
||||
// 3) create the desired formatter and store and return it.
|
||||
var dateTimeFormatCache = new Record();
|
||||
|
||||
|
||||
/**
|
||||
* Get a cached DateTimeFormat formatter object, created like so:
|
||||
*
|
||||
* var opts = ToDateTimeOptions(undefined, required, defaults);
|
||||
* return new Intl.DateTimeFormat(undefined, opts);
|
||||
*
|
||||
* |format| must be a key from the "formatters" Record described above.
|
||||
*/
|
||||
function GetCachedFormat(format, required, defaults) {
|
||||
assert(format === "dateTimeFormat" ||
|
||||
format === "dateFormat" ||
|
||||
format === "timeFormat",
|
||||
"unexpected format key: please update the comment by " +
|
||||
"dateTimeFormatCache");
|
||||
|
||||
var runtimeDefaultLocale = RuntimeDefaultLocale();
|
||||
var localTZA = LocalTZA();
|
||||
|
||||
var formatters;
|
||||
if (dateTimeFormatCache.runtimeDefaultLocale !== runtimeDefaultLocale ||
|
||||
dateTimeFormatCache.localTZA !== localTZA)
|
||||
{
|
||||
formatters = dateTimeFormatCache.formatters = new Record();
|
||||
dateTimeFormatCache.runtimeDefaultLocale = runtimeDefaultLocale;
|
||||
dateTimeFormatCache.localTZA = localTZA;
|
||||
} else {
|
||||
formatters = dateTimeFormatCache.formatters;
|
||||
}
|
||||
|
||||
var fmt = formatters[format];
|
||||
if (fmt === undefined) {
|
||||
var options = ToDateTimeOptions(undefined, required, defaults);
|
||||
fmt = formatters[format] = intl_DateTimeFormat(undefined, options);
|
||||
}
|
||||
|
||||
return fmt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format this Date object into a date and time string, using the locale and
|
||||
* formatting options provided.
|
||||
@@ -30,11 +94,7 @@ function Date_toLocaleString() {
|
||||
if (locales === undefined && options === undefined) {
|
||||
// This cache only optimizes for the old ES5 toLocaleString without
|
||||
// locales and options.
|
||||
if (dateTimeFormatCache.dateTimeFormat === undefined) {
|
||||
options = ToDateTimeOptions(options, "any", "all");
|
||||
dateTimeFormatCache.dateTimeFormat = intl_DateTimeFormat(locales, options);
|
||||
}
|
||||
dateTimeFormat = dateTimeFormatCache.dateTimeFormat;
|
||||
dateTimeFormat = GetCachedFormat("dateTimeFormat", "any", "all");
|
||||
} else {
|
||||
options = ToDateTimeOptions(options, "any", "all");
|
||||
dateTimeFormat = intl_DateTimeFormat(locales, options);
|
||||
@@ -67,11 +127,7 @@ function Date_toLocaleDateString() {
|
||||
if (locales === undefined && options === undefined) {
|
||||
// This cache only optimizes for the old ES5 toLocaleDateString without
|
||||
// locales and options.
|
||||
if (dateTimeFormatCache.dateFormat === undefined) {
|
||||
options = ToDateTimeOptions(options, "date", "date");
|
||||
dateTimeFormatCache.dateFormat = intl_DateTimeFormat(locales, options);
|
||||
}
|
||||
dateTimeFormat = dateTimeFormatCache.dateFormat;
|
||||
dateTimeFormat = GetCachedFormat("dateFormat", "date", "date");
|
||||
} else {
|
||||
options = ToDateTimeOptions(options, "date", "date");
|
||||
dateTimeFormat = intl_DateTimeFormat(locales, options);
|
||||
@@ -104,11 +160,7 @@ function Date_toLocaleTimeString() {
|
||||
if (locales === undefined && options === undefined) {
|
||||
// This cache only optimizes for the old ES5 toLocaleTimeString without
|
||||
// locales and options.
|
||||
if (dateTimeFormatCache.timeFormat === undefined) {
|
||||
options = ToDateTimeOptions(options, "time", "time");
|
||||
dateTimeFormatCache.timeFormat = intl_DateTimeFormat(locales, options);
|
||||
}
|
||||
dateTimeFormat = dateTimeFormatCache.timeFormat;
|
||||
dateTimeFormat = GetCachedFormat("timeFormat", "time", "time");
|
||||
} else {
|
||||
options = ToDateTimeOptions(options, "time", "time");
|
||||
dateTimeFormat = intl_DateTimeFormat(locales, options);
|
||||
|
||||
@@ -62,7 +62,7 @@ SymbolObject::initClass(JSContext* cx, HandleObject obj)
|
||||
return nullptr;
|
||||
|
||||
RootedFunction ctor(cx, global->createConstructor(cx, construct,
|
||||
ClassName(JSProto_Symbol, cx), 1));
|
||||
ClassName(JSProto_Symbol, cx), 0));
|
||||
if (!ctor)
|
||||
return nullptr;
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ UNIFIED_SOURCES += [
|
||||
'testClassGetter.cpp',
|
||||
'testCloneScript.cpp',
|
||||
'testContexts.cpp',
|
||||
'testDateToLocaleString.cpp',
|
||||
'testDebugger.cpp',
|
||||
'testDeepFreeze.cpp',
|
||||
'testDefineGetterSetterNonEnumerable.cpp',
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "jsapi-tests/tests.h"
|
||||
|
||||
BEGIN_TEST(testDateToLocaleString)
|
||||
{
|
||||
// This test should only attempt to run if we have Intl support: necessary
|
||||
// to properly assume that changes to the default locale will predictably
|
||||
// affect the behavior of the locale-sensitive Date methods tested here.
|
||||
JS::Rooted<JS::Value> haveIntl(cx);
|
||||
EVAL("typeof Intl !== 'undefined'", &haveIntl);
|
||||
if (!haveIntl.toBoolean())
|
||||
return true;
|
||||
|
||||
// Pervasive assumption: our Intl support includes "de" (German) and
|
||||
// "en" (English) and treats them differently for purposes of
|
||||
// Date.prototype.toLocale{,Date,Time}String behavior.
|
||||
|
||||
// Start with German.
|
||||
CHECK(JS_SetDefaultLocale(rt, "de"));
|
||||
|
||||
// The (constrained) Date object we'll use to test behavior.
|
||||
EXEC("var d = new Date(Date.UTC(2015, 9 - 1, 17));");
|
||||
|
||||
// Test that toLocaleString behavior changes with default locale changes.
|
||||
EXEC("var deAll = d.toLocaleString();");
|
||||
|
||||
CHECK(JS_SetDefaultLocale(rt, "en"));
|
||||
EXEC("if (d.toLocaleString() === deAll) \n"
|
||||
" throw 'toLocaleString results should have changed with system locale change';");
|
||||
|
||||
// Test that toLocaleDateString behavior changes with default locale changes.
|
||||
EXEC("var enDate = d.toLocaleDateString();");
|
||||
|
||||
CHECK(JS_SetDefaultLocale(rt, "de"));
|
||||
EXEC("if (d.toLocaleDateString() === enDate) \n"
|
||||
" throw 'toLocaleDateString results should have changed with system locale change';");
|
||||
|
||||
// Test that toLocaleTimeString behavior changes with default locale changes.
|
||||
EXEC("var deTime = d.toLocaleTimeString();");
|
||||
|
||||
CHECK(JS_SetDefaultLocale(rt, "en"));
|
||||
EXEC("if (d.toLocaleTimeString() === deTime) \n"
|
||||
" throw 'toLocaleTimeString results should have changed with system locale change';");
|
||||
|
||||
JS_ResetDefaultLocale(rt);
|
||||
return true;
|
||||
}
|
||||
END_TEST(testDateToLocaleString)
|
||||
+13
-13
@@ -556,10 +556,10 @@ XDRRelazificationInfo(XDRState<mode>* xdr, HandleFunction fun, HandleScript scri
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
FindScopeObjectIndex(JSScript *script, NestedScopeObject& scope)
|
||||
FindScopeObjectIndex(JSScript* script, NestedScopeObject& scope)
|
||||
{
|
||||
ObjectArray *objects = script->objects();
|
||||
HeapPtrObject *vector = objects->vector;
|
||||
ObjectArray* objects = script->objects();
|
||||
HeapPtrObject* vector = objects->vector;
|
||||
unsigned length = objects->length;
|
||||
for (unsigned i = 0; i < length; ++i) {
|
||||
if (vector[i] == &scope)
|
||||
@@ -965,11 +965,11 @@ js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript
|
||||
* after the enclosing block has been XDR'd.
|
||||
*/
|
||||
for (i = 0; i != nobjects; ++i) {
|
||||
HeapPtrObject *objp = &script->objects()->vector[i];
|
||||
HeapPtrObject* objp = &script->objects()->vector[i];
|
||||
XDRClassKind classk;
|
||||
|
||||
if (mode == XDR_ENCODE) {
|
||||
JSObject *obj = *objp;
|
||||
JSObject* obj = *objp;
|
||||
if (obj->is<BlockObject>())
|
||||
classk = CK_BlockObject;
|
||||
else if (obj->is<StaticWithObject>())
|
||||
@@ -2655,19 +2655,19 @@ JSScript::partiallyInit(ExclusiveContext* cx, HandleScript script, uint32_t ncon
|
||||
|
||||
if (nobjects != 0) {
|
||||
script->objects()->length = nobjects;
|
||||
script->objects()->vector = (HeapPtrObject *)cursor;
|
||||
script->objects()->vector = (HeapPtrObject*)cursor;
|
||||
cursor += nobjects * sizeof(script->objects()->vector[0]);
|
||||
}
|
||||
|
||||
if (nregexps != 0) {
|
||||
script->regexps()->length = nregexps;
|
||||
script->regexps()->vector = (HeapPtrObject *)cursor;
|
||||
script->regexps()->vector = (HeapPtrObject*)cursor;
|
||||
cursor += nregexps * sizeof(script->regexps()->vector[0]);
|
||||
}
|
||||
|
||||
if (ntrynotes != 0) {
|
||||
script->trynotes()->length = ntrynotes;
|
||||
script->trynotes()->vector = reinterpret_cast<JSTryNote *>(cursor);
|
||||
script->trynotes()->vector = reinterpret_cast<JSTryNote*>(cursor);
|
||||
size_t vectorSize = ntrynotes * sizeof(script->trynotes()->vector[0]);
|
||||
#ifdef DEBUG
|
||||
memset(cursor, 0, vectorSize);
|
||||
@@ -3250,7 +3250,7 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri
|
||||
|
||||
AutoObjectVector objects(cx);
|
||||
if (nobjects != 0) {
|
||||
HeapPtrObject *vector = src->objects()->vector;
|
||||
HeapPtrObject* vector = src->objects()->vector;
|
||||
for (unsigned i = 0; i < nobjects; i++) {
|
||||
RootedObject obj(cx, vector[i]);
|
||||
RootedObject clone(cx);
|
||||
@@ -3360,13 +3360,13 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri
|
||||
MOZ_ASSERT_IF(vector[i].isMarkable(), vector[i].toString()->isAtom());
|
||||
}
|
||||
if (nobjects != 0) {
|
||||
HeapPtrObject *vector = Rebase<HeapPtrObject>(dst, src, src->objects()->vector);
|
||||
HeapPtrObject* vector = Rebase<HeapPtrObject>(dst, src, src->objects()->vector);
|
||||
dst->objects()->vector = vector;
|
||||
for (unsigned i = 0; i < nobjects; ++i)
|
||||
vector[i].init(&objects[i]->as<NativeObject>());
|
||||
}
|
||||
if (nregexps != 0) {
|
||||
HeapPtrObject *vector = Rebase<HeapPtrObject>(dst, src, src->regexps()->vector);
|
||||
HeapPtrObject* vector = Rebase<HeapPtrObject>(dst, src, src->regexps()->vector);
|
||||
dst->regexps()->vector = vector;
|
||||
for (unsigned i = 0; i < nregexps; ++i)
|
||||
vector[i].init(®exps[i]->as<NativeObject>());
|
||||
@@ -4064,8 +4064,8 @@ LazyScript::CreateRaw(ExclusiveContext* cx, HandleFunction fun,
|
||||
return new (res) LazyScript(fun, table.forget(), packed, begin, end, lineno, column);
|
||||
}
|
||||
|
||||
/* static */ LazyScript *
|
||||
LazyScript::CreateRaw(ExclusiveContext *cx, HandleFunction fun,
|
||||
/* static */ LazyScript*
|
||||
LazyScript::CreateRaw(ExclusiveContext* cx, HandleFunction fun,
|
||||
uint32_t numFreeVariables, uint32_t numInnerFunctions, JSVersion version,
|
||||
uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column)
|
||||
{
|
||||
|
||||
+2
-3
@@ -1525,7 +1525,6 @@ RopeMatch(JSContext* cx, JSRope* text, JSLinearString* pat, int* match)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* ES6 draft rc4 21.1.3.7. */
|
||||
static bool
|
||||
str_includes(JSContext* cx, unsigned argc, Value* vp)
|
||||
@@ -2274,8 +2273,8 @@ DoMatchLocal(JSContext* cx, const CallArgs& args, RegExpStatics* res, HandleLine
|
||||
|
||||
/* ES5 15.5.4.10 step 8. */
|
||||
static bool
|
||||
DoMatchGlobal(JSContext* cx, const CallArgs& args, RegExpStatics* res,
|
||||
HandleLinearString input, StringRegExpGuard& g)
|
||||
DoMatchGlobal(JSContext* cx, const CallArgs& args, RegExpStatics* res, HandleLinearString input,
|
||||
StringRegExpGuard& g)
|
||||
{
|
||||
// Step 8a.
|
||||
//
|
||||
|
||||
@@ -8,7 +8,7 @@ assertEq(desc.configurable, true);
|
||||
assertEq(desc.enumerable, false);
|
||||
assertEq(desc.writable, true);
|
||||
assertEq(typeof Symbol, "function");
|
||||
assertEq(Symbol.length, 1);
|
||||
assertEq(Symbol.length, 0);
|
||||
|
||||
desc = Object.getOwnPropertyDescriptor(Symbol, "prototype");
|
||||
assertEq(desc.configurable, false);
|
||||
|
||||
@@ -1261,6 +1261,16 @@ intrinsic_RuntimeDefaultLocale(JSContext* cx, unsigned argc, Value* vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
intrinsic_LocalTZA(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
MOZ_ASSERT(args.length() == 0, "the LocalTZA intrinsic takes no arguments");
|
||||
|
||||
args.rval().setDouble(cx->runtime()->dateTimeInfo.localTZA());
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
intrinsic_IsConstructing(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
@@ -1382,6 +1392,7 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
||||
JS_FN("_ConstructorForTypedArray", intrinsic_ConstructorForTypedArray, 1,0),
|
||||
JS_FN("DecompileArg", intrinsic_DecompileArg, 2,0),
|
||||
JS_FN("RuntimeDefaultLocale", intrinsic_RuntimeDefaultLocale, 0,0),
|
||||
JS_FN("LocalTZA", intrinsic_LocalTZA, 0,0),
|
||||
|
||||
JS_INLINABLE_FN("_IsConstructing", intrinsic_IsConstructing, 0,0,
|
||||
IntrinsicIsConstructing),
|
||||
|
||||
@@ -105,18 +105,20 @@ this.BrowserTestUtils = {
|
||||
* @resolves The tab switched to.
|
||||
*/
|
||||
switchTab(tabbrowser, tab) {
|
||||
let promise = new Promise(resolve => {
|
||||
tabbrowser.addEventListener("TabSwitchDone", function onSwitch() {
|
||||
tabbrowser.removeEventListener("TabSwitchDone", onSwitch);
|
||||
TestUtils.executeSoon(() => resolve(tabbrowser.selectedTab));
|
||||
});
|
||||
});
|
||||
|
||||
if (typeof tab == "function") {
|
||||
tab();
|
||||
}
|
||||
else {
|
||||
tabbrowser.selectedTab = tab;
|
||||
}
|
||||
|
||||
//XXX this is esr38, we do not have e10s, this is never async, we do not pass go
|
||||
// and do not collect, err, I mean, we continue without waiting for an event:
|
||||
return new Promise(resolve => {
|
||||
TestUtils.executeSoon(() => resolve(tabbrowser.selectedTab));
|
||||
});
|
||||
return promise;
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -196,10 +196,11 @@ public:
|
||||
virtual bool NeedsPaint() override;
|
||||
|
||||
virtual TabChild* GetOwningTabChild() override { return mTabChild; }
|
||||
virtual void ClearBackingScaleCache()
|
||||
|
||||
void UpdateBackingScaleCache(float aDpi, double aScale)
|
||||
{
|
||||
mDPI = -1;
|
||||
mDefaultScale = -1;
|
||||
mDPI = aDpi;
|
||||
mDefaultScale = aScale;
|
||||
}
|
||||
|
||||
nsIntSize GetScreenDimensions();
|
||||
|
||||
Reference in New Issue
Block a user