mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to fx-team, a=merge
This commit is contained in:
commit
81dcce0528
2
CLOBBER
2
CLOBBER
@ -22,4 +22,4 @@
|
||||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Bug 1217261 - Update mp4parse to v0.1.2
|
||||
Bug 479520 - Implement IDNA2008 standard for International Domain Names
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2e89362de40a6c9c36525d36317fa1ae8e67e143"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="75f2236d36cc9f9c02d3596fae3de014007cfd82"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2e89362de40a6c9c36525d36317fa1ae8e67e143"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="75f2236d36cc9f9c02d3596fae3de014007cfd82"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2e89362de40a6c9c36525d36317fa1ae8e67e143"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="75f2236d36cc9f9c02d3596fae3de014007cfd82"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="4ace9aaee0e048dfda11bb787646c59982a3dc80"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2e89362de40a6c9c36525d36317fa1ae8e67e143"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="75f2236d36cc9f9c02d3596fae3de014007cfd82"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="3b9a47b517d345b8d98bc7f787b9a6c2f51ca75d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="1837d370a964a9719160c79155a07980f2ea4bdf"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2e89362de40a6c9c36525d36317fa1ae8e67e143"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="75f2236d36cc9f9c02d3596fae3de014007cfd82"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
@ -129,7 +129,7 @@
|
||||
<!-- Emulator specific things -->
|
||||
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="72ffdf71c68a96309212eb13d63560d66db14c9e"/>
|
||||
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="8d4018ebd33ac3f1a043b2d54bc578028656a659"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="b1f6e6797468ecce33acdb780a84cd0bbb751dd9"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="5a50f96a1d7c788817abb7c57acbb75172c1f48d"/>
|
||||
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="f37bd545063039e30a92f2550ae78c0e6e4e2d08"/>
|
||||
<project name="platform_external_wpa_supplicant_8" path="external/wpa_supplicant_8" remote="b2g" revision="0c6a6547cd1fd302fa2b0f6e375654df36bf0ec4"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="aa763fa9180a222547824ae6b6064e4851c15a86"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2e89362de40a6c9c36525d36317fa1ae8e67e143"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="75f2236d36cc9f9c02d3596fae3de014007cfd82"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2e89362de40a6c9c36525d36317fa1ae8e67e143"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="75f2236d36cc9f9c02d3596fae3de014007cfd82"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="4ace9aaee0e048dfda11bb787646c59982a3dc80"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2e89362de40a6c9c36525d36317fa1ae8e67e143"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="75f2236d36cc9f9c02d3596fae3de014007cfd82"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
|
||||
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"git": {
|
||||
"git_revision": "2e89362de40a6c9c36525d36317fa1ae8e67e143",
|
||||
"git_revision": "75f2236d36cc9f9c02d3596fae3de014007cfd82",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "4a596a387a18b019fc2763b3509940d52154d72c",
|
||||
"revision": "62309a2099d3eb104b4f0fac2d3970ba3403f0e6",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2e89362de40a6c9c36525d36317fa1ae8e67e143"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="75f2236d36cc9f9c02d3596fae3de014007cfd82"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
|
||||
|
@ -18,7 +18,7 @@
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2e89362de40a6c9c36525d36317fa1ae8e67e143"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="75f2236d36cc9f9c02d3596fae3de014007cfd82"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="3b9a47b517d345b8d98bc7f787b9a6c2f51ca75d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="1837d370a964a9719160c79155a07980f2ea4bdf"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2e89362de40a6c9c36525d36317fa1ae8e67e143"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="75f2236d36cc9f9c02d3596fae3de014007cfd82"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
|
||||
|
@ -101,7 +101,7 @@ nsEdgeReadingListExtractor::Extract(const nsAString& aDBPath, nsIArray** aItems)
|
||||
if (urlColumnInfo.cbMax > MAX_URL_LENGTH) {
|
||||
nsCOMPtr<nsIConsoleService> consoleService = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
|
||||
if (consoleService) {
|
||||
consoleService->LogStringMessage(NS_LITERAL_STRING("Edge migration: URL column size increased").get());
|
||||
consoleService->LogStringMessage(MOZ_UTF16("Edge migration: URL column size increased"));
|
||||
}
|
||||
}
|
||||
err = JetGetColumnInfo(sesid, dbid, "ReadingList", "Title", &titleColumnInfo,
|
||||
@ -110,7 +110,7 @@ nsEdgeReadingListExtractor::Extract(const nsAString& aDBPath, nsIArray** aItems)
|
||||
if (titleColumnInfo.cbMax > MAX_TITLE_LENGTH) {
|
||||
nsCOMPtr<nsIConsoleService> consoleService = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
|
||||
if (consoleService) {
|
||||
consoleService->LogStringMessage(NS_LITERAL_STRING("Edge migration: Title column size increased").get());
|
||||
consoleService->LogStringMessage(MOZ_UTF16("Edge migration: Title column size increased"));
|
||||
}
|
||||
}
|
||||
err = JetGetColumnInfo(sesid, dbid, "ReadingList", "AddedDate", &addedDateColumnInfo,
|
||||
|
@ -142,7 +142,6 @@ if test -z "$BUILDING_JS" -o -n "$JS_STANDALONE"; then
|
||||
ICU_CPPFLAGS="$ICU_CPPFLAGS -DUCONFIG_NO_TRANSLITERATION"
|
||||
ICU_CPPFLAGS="$ICU_CPPFLAGS -DUCONFIG_NO_REGULAR_EXPRESSIONS"
|
||||
ICU_CPPFLAGS="$ICU_CPPFLAGS -DUCONFIG_NO_BREAK_ITERATION"
|
||||
ICU_CPPFLAGS="$ICU_CPPFLAGS -DUCONFIG_NO_IDNA"
|
||||
# we don't need to pass data to and from legacy char* APIs
|
||||
ICU_CPPFLAGS="$ICU_CPPFLAGS -DU_CHARSET_IS_UTF8"
|
||||
# make sure to not accidentally pick up system-icu headers
|
||||
|
@ -812,7 +812,18 @@ exports.openFileStream = function (filePath) {
|
||||
}
|
||||
|
||||
exports.isGenerator = function (fn) {
|
||||
return typeof fn === "function" && fn.isGenerator();
|
||||
if (typeof fn !== "function") {
|
||||
return false;
|
||||
}
|
||||
let proto = Object.getPrototypeOf(fn);
|
||||
if (!proto) {
|
||||
return false;
|
||||
}
|
||||
let ctor = proto.constructor;
|
||||
if (!ctor) {
|
||||
return false;
|
||||
}
|
||||
return ctor.name == "GeneratorFunction";
|
||||
};
|
||||
|
||||
exports.isPromise = function (p) {
|
||||
|
@ -4654,6 +4654,10 @@ this.DOMApplicationRegistry = {
|
||||
}
|
||||
|
||||
return this.getManifestFor(aManifestURL).then((aManifest) => {
|
||||
if (!aManifest) {
|
||||
return Promise.reject("NoManifest");
|
||||
}
|
||||
|
||||
let manifest = aEntryPoint && aManifest.entry_points &&
|
||||
aManifest.entry_points[aEntryPoint]
|
||||
? aManifest.entry_points[aEntryPoint]
|
||||
|
@ -131,8 +131,8 @@ public:
|
||||
observerService->NotifyObservers(
|
||||
ToSupports(mWindow),
|
||||
"audio-playback",
|
||||
mActive ? NS_LITERAL_STRING("active").get()
|
||||
: NS_LITERAL_STRING("inactive").get());
|
||||
mActive ? MOZ_UTF16("active")
|
||||
: MOZ_UTF16("inactive"));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -138,7 +138,7 @@ public:
|
||||
|
||||
EncodingRunnable(const nsAString& aType,
|
||||
const nsAString& aOptions,
|
||||
uint8_t* aImageBuffer,
|
||||
UniquePtr<uint8_t[]> aImageBuffer,
|
||||
layers::Image* aImage,
|
||||
imgIEncoder* aEncoder,
|
||||
EncodingCompleteEvent* aEncodingCompleteEvent,
|
||||
@ -147,7 +147,7 @@ public:
|
||||
bool aUsingCustomOptions)
|
||||
: mType(aType)
|
||||
, mOptions(aOptions)
|
||||
, mImageBuffer(aImageBuffer)
|
||||
, mImageBuffer(Move(aImageBuffer))
|
||||
, mImage(aImage)
|
||||
, mEncoder(aEncoder)
|
||||
, mEncodingCompleteEvent(aEncodingCompleteEvent)
|
||||
@ -161,7 +161,7 @@ public:
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
nsresult rv = ImageEncoder::ExtractDataInternal(mType,
|
||||
mOptions,
|
||||
mImageBuffer,
|
||||
mImageBuffer.get(),
|
||||
mFormat,
|
||||
mSize,
|
||||
mImage,
|
||||
@ -175,7 +175,7 @@ public:
|
||||
if (rv == NS_ERROR_INVALID_ARG && mUsingCustomOptions) {
|
||||
rv = ImageEncoder::ExtractDataInternal(mType,
|
||||
EmptyString(),
|
||||
mImageBuffer,
|
||||
mImageBuffer.get(),
|
||||
mFormat,
|
||||
mSize,
|
||||
mImage,
|
||||
@ -220,7 +220,7 @@ public:
|
||||
private:
|
||||
nsAutoString mType;
|
||||
nsAutoString mOptions;
|
||||
nsAutoArrayPtr<uint8_t> mImageBuffer;
|
||||
UniquePtr<uint8_t[]> mImageBuffer;
|
||||
RefPtr<layers::Image> mImage;
|
||||
nsCOMPtr<imgIEncoder> mEncoder;
|
||||
RefPtr<EncodingCompleteEvent> mEncodingCompleteEvent;
|
||||
@ -287,7 +287,7 @@ nsresult
|
||||
ImageEncoder::ExtractDataAsync(nsAString& aType,
|
||||
const nsAString& aOptions,
|
||||
bool aUsingCustomOptions,
|
||||
uint8_t* aImageBuffer,
|
||||
UniquePtr<uint8_t[]> aImageBuffer,
|
||||
int32_t aFormat,
|
||||
const nsIntSize aSize,
|
||||
EncodeCompleteCallback* aEncodeCallback)
|
||||
@ -306,7 +306,7 @@ ImageEncoder::ExtractDataAsync(nsAString& aType,
|
||||
|
||||
nsCOMPtr<nsIRunnable> event = new EncodingRunnable(aType,
|
||||
aOptions,
|
||||
aImageBuffer,
|
||||
Move(aImageBuffer),
|
||||
nullptr,
|
||||
encoder,
|
||||
completeEvent,
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "nsError.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/dom/HTMLCanvasElementBinding.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsSize.h"
|
||||
|
||||
@ -58,7 +59,7 @@ public:
|
||||
static nsresult ExtractDataAsync(nsAString& aType,
|
||||
const nsAString& aOptions,
|
||||
bool aUsingCustomOptions,
|
||||
uint8_t* aImageBuffer,
|
||||
UniquePtr<uint8_t[]> aImageBuffer,
|
||||
int32_t aFormat,
|
||||
const nsIntSize aSize,
|
||||
EncodeCompleteCallback* aEncodeCallback);
|
||||
|
@ -1563,8 +1563,8 @@ WebSocketImpl::Init(JSContext* aCx,
|
||||
}
|
||||
mSecure = true;
|
||||
|
||||
const char16_t* params[] = { reportSpec.get(), NS_LITERAL_STRING("wss").get() };
|
||||
CSP_LogLocalizedStr(NS_LITERAL_STRING("upgradeInsecureRequest").get(),
|
||||
const char16_t* params[] = { reportSpec.get(), MOZ_UTF16("wss") };
|
||||
CSP_LogLocalizedStr(MOZ_UTF16("upgradeInsecureRequest"),
|
||||
params, ArrayLength(params),
|
||||
EmptyString(), // aSourceFile
|
||||
EmptyString(), // aScriptSample
|
||||
|
@ -15,7 +15,6 @@ support-files =
|
||||
skip-if = e10s # Bug ?????? - test directly touches content (contentWindow.iframe.addEventListener)
|
||||
[browser_bug902350.js]
|
||||
tags = mcb
|
||||
skip-if = e10s # Bug ?????? - test e10s utils don't support load events from iframe etc, which this test relies on.
|
||||
[browser_messagemanager_loadprocessscript.js]
|
||||
[browser_messagemanager_targetframeloader.js]
|
||||
[browser_pagehide_on_tab_close.js]
|
||||
|
@ -1303,7 +1303,7 @@ nsGonkCameraControl::StopRecordingImpl()
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
obs->NotifyObservers(mFile, "file-watcher-notify", NS_LITERAL_STRING("modified").get());
|
||||
obs->NotifyObservers(mFile, "file-watcher-notify", MOZ_UTF16("modified"));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1646,26 +1646,24 @@ CanvasRenderingContext2D::SetContextOptions(JSContext* aCx,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
CanvasRenderingContext2D::GetImageBuffer(uint8_t** aImageBuffer,
|
||||
int32_t* aFormat)
|
||||
UniquePtr<uint8_t[]>
|
||||
CanvasRenderingContext2D::GetImageBuffer(int32_t* aFormat)
|
||||
{
|
||||
*aImageBuffer = nullptr;
|
||||
*aFormat = 0;
|
||||
|
||||
EnsureTarget();
|
||||
RefPtr<SourceSurface> snapshot = mTarget->Snapshot();
|
||||
if (!snapshot) {
|
||||
return;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<DataSourceSurface> data = snapshot->GetDataSurface();
|
||||
if (!data || data->GetSize() != IntSize(mWidth, mHeight)) {
|
||||
return;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
*aImageBuffer = SurfaceToPackedBGRA(data);
|
||||
*aFormat = imgIEncoder::INPUT_FORMAT_HOSTARGB;
|
||||
return SurfaceToPackedBGRA(data);
|
||||
}
|
||||
|
||||
nsString CanvasRenderingContext2D::GetHitRegion(const mozilla::gfx::Point& aPoint)
|
||||
@ -1691,15 +1689,15 @@ CanvasRenderingContext2D::GetInputStream(const char *aMimeType,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsAutoArrayPtr<uint8_t> imageBuffer;
|
||||
int32_t format = 0;
|
||||
GetImageBuffer(getter_Transfers(imageBuffer), &format);
|
||||
UniquePtr<uint8_t[]> imageBuffer = GetImageBuffer(&format);
|
||||
if (!imageBuffer) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return ImageEncoder::GetInputStream(mWidth, mHeight, imageBuffer, format,
|
||||
encoder, aEncoderOptions, aStream);
|
||||
return ImageEncoder::GetInputStream(mWidth, mHeight, imageBuffer.get(),
|
||||
format, encoder, aEncoderOptions,
|
||||
aStream);
|
||||
}
|
||||
|
||||
SurfaceFormat
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "mozilla/dom/CanvasPattern.h"
|
||||
#include "mozilla/gfx/Rect.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "gfx2DGlue.h"
|
||||
#include "imgIEncoder.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
@ -526,7 +527,7 @@ public:
|
||||
|
||||
friend class CanvasRenderingContext2DUserData;
|
||||
|
||||
virtual void GetImageBuffer(uint8_t** aImageBuffer, int32_t* aFormat) override;
|
||||
virtual UniquePtr<uint8_t[]> GetImageBuffer(int32_t* aFormat) override;
|
||||
|
||||
|
||||
// Given a point, return hit region ID if it exists
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "ImageEncoder.h"
|
||||
#include "mozilla/dom/CanvasRenderingContext2D.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDOMJSUtils.h"
|
||||
#include "nsIScriptContext.h"
|
||||
@ -49,10 +50,10 @@ CanvasRenderingContextHelper::ToBlob(JSContext* aCx,
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t* imageBuffer = nullptr;
|
||||
UniquePtr<uint8_t[]> imageBuffer;
|
||||
int32_t format = 0;
|
||||
if (mCurrentContext) {
|
||||
mCurrentContext->GetImageBuffer(&imageBuffer, &format);
|
||||
imageBuffer = mCurrentContext->GetImageBuffer(&format);
|
||||
}
|
||||
|
||||
// Encoder callback when encoding is complete.
|
||||
@ -99,7 +100,7 @@ CanvasRenderingContextHelper::ToBlob(JSContext* aCx,
|
||||
aRv = ImageEncoder::ExtractDataAsync(type,
|
||||
params,
|
||||
usingCustomParseOptions,
|
||||
imageBuffer,
|
||||
Move(imageBuffer),
|
||||
format,
|
||||
GetWidthHeight(),
|
||||
callback);
|
||||
|
@ -1052,25 +1052,25 @@ WebGLContext::LoseOldestWebGLContextIfLimitExceeded()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::GetImageBuffer(uint8_t** out_imageBuffer, int32_t* out_format)
|
||||
UniquePtr<uint8_t[]>
|
||||
WebGLContext::GetImageBuffer(int32_t* out_format)
|
||||
{
|
||||
*out_imageBuffer = nullptr;
|
||||
*out_format = 0;
|
||||
|
||||
// Use GetSurfaceSnapshot() to make sure that appropriate y-flip gets applied
|
||||
bool premult;
|
||||
RefPtr<SourceSurface> snapshot =
|
||||
GetSurfaceSnapshot(mOptions.premultipliedAlpha ? nullptr : &premult);
|
||||
if (!snapshot)
|
||||
return;
|
||||
if (!snapshot) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mOptions.premultipliedAlpha || !premult, "We must get unpremult when we ask for it!");
|
||||
|
||||
RefPtr<DataSourceSurface> dataSurface = snapshot->GetDataSurface();
|
||||
|
||||
return gfxUtils::GetImageBuffer(dataSurface, mOptions.premultipliedAlpha,
|
||||
out_imageBuffer, out_format);
|
||||
out_format);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -237,8 +237,7 @@ public:
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
virtual void GetImageBuffer(uint8_t** out_imageBuffer,
|
||||
int32_t* out_format) override;
|
||||
virtual UniquePtr<uint8_t[]> GetImageBuffer(int32_t* out_format) override;
|
||||
NS_IMETHOD GetInputStream(const char* mimeType,
|
||||
const char16_t* encoderOptions,
|
||||
nsIInputStream** out_stream) override;
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "mozilla/dom/HTMLCanvasElement.h"
|
||||
#include "mozilla/dom/OffscreenCanvas.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
#define NS_ICANVASRENDERINGCONTEXTINTERNAL_IID \
|
||||
{ 0xb84f2fed, 0x9d4b, 0x430b, \
|
||||
@ -96,7 +97,7 @@ public:
|
||||
NS_IMETHOD InitializeWithSurface(nsIDocShell *docShell, gfxASurface *surface, int32_t width, int32_t height) = 0;
|
||||
|
||||
// Creates an image buffer. Returns null on failure.
|
||||
virtual void GetImageBuffer(uint8_t** imageBuffer, int32_t* format) = 0;
|
||||
virtual mozilla::UniquePtr<uint8_t[]> GetImageBuffer(int32_t* format) = 0;
|
||||
|
||||
// Gives you a stream containing the image represented by this context.
|
||||
// The format is given in mimeTime, for example "image/png".
|
||||
|
@ -1764,7 +1764,7 @@ HTMLFormElement::GetActionURL(nsIURI** aActionURL,
|
||||
NS_ConvertUTF8toUTF16 reportScheme(scheme);
|
||||
|
||||
const char16_t* params[] = { reportSpec.get(), reportScheme.get() };
|
||||
CSP_LogLocalizedStr(NS_LITERAL_STRING("upgradeInsecureRequest").get(),
|
||||
CSP_LogLocalizedStr(MOZ_UTF16("upgradeInsecureRequest"),
|
||||
params, ArrayLength(params),
|
||||
EmptyString(), // aSourceFile
|
||||
EmptyString(), // aScriptSample
|
||||
|
@ -106,43 +106,22 @@ MediaCodecProxy::~MediaCodecProxy()
|
||||
}
|
||||
|
||||
bool
|
||||
MediaCodecProxy::AskMediaCodecAndWait()
|
||||
MediaCodecProxy::AllocateAudioMediaCodec()
|
||||
{
|
||||
if (mResourceClient || mCodec.get()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strncasecmp(mCodecMime.get(), "video/", 6) == 0) {
|
||||
mozilla::MediaSystemResourceType type =
|
||||
mCodecEncoder ? mozilla::MediaSystemResourceType::VIDEO_ENCODER :
|
||||
mozilla::MediaSystemResourceType::VIDEO_DECODER;
|
||||
mResourceClient = new mozilla::MediaSystemResourceClient(type);
|
||||
mResourceClient->SetListener(this);
|
||||
} else if (strncasecmp(mCodecMime.get(), "audio/", 6) == 0) {
|
||||
if (strncasecmp(mCodecMime.get(), "audio/", 6) == 0) {
|
||||
if (allocateCodec()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mResourceClient) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mozilla::MonitorAutoLock mon(mMediaCodecLock);
|
||||
mPendingRequestMediaResource = true;
|
||||
// request video codec
|
||||
mResourceClient->Acquire();
|
||||
|
||||
while (mPendingRequestMediaResource) {
|
||||
mMediaCodecLock.Wait();
|
||||
}
|
||||
MCP_LOG("AskMediaCodecAndWait complete");
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
MediaCodecProxy::AsyncAskMediaCodec()
|
||||
MediaCodecProxy::AsyncAllocateVideoMediaCodec()
|
||||
{
|
||||
if (mResourceClient || mCodec.get()) {
|
||||
return false;
|
||||
|
@ -138,14 +138,11 @@ public:
|
||||
|
||||
void ReleaseMediaBuffer(MediaBuffer* abuffer);
|
||||
|
||||
// It asks for the OMX codec and blocked until the resource is grant to be
|
||||
// allocated.
|
||||
// Audio codec allocation should use this.
|
||||
bool AskMediaCodecAndWait();
|
||||
// It allocates audio MediaCodec synchronously.
|
||||
bool AllocateAudioMediaCodec();
|
||||
|
||||
// It asks for the OMX codec asynchronously.
|
||||
// Only video codec is supported.
|
||||
bool AsyncAskMediaCodec();
|
||||
// It allocates video MediaCodec asynchronously.
|
||||
bool AsyncAllocateVideoMediaCodec();
|
||||
|
||||
// Free the OMX codec so others can allocate it.
|
||||
void ReleaseMediaCodec();
|
||||
|
@ -1303,12 +1303,12 @@ MediaCodecReader::CreateMediaCodecs()
|
||||
bool isWaiting = false;
|
||||
RefPtr<MediaResourcePromise> p = mMediaResourcePromise.Ensure(__func__);
|
||||
|
||||
if (!CreateMediaCodec(mLooper, mAudioTrack, false, isWaiting, nullptr)) {
|
||||
if (!CreateMediaCodec(mLooper, mAudioTrack, isWaiting, nullptr)) {
|
||||
mMediaResourcePromise.Reject(true, __func__);
|
||||
return p;
|
||||
}
|
||||
|
||||
if (!CreateMediaCodec(mLooper, mVideoTrack, true, isWaiting, mVideoListener)) {
|
||||
if (!CreateMediaCodec(mLooper, mVideoTrack, isWaiting, mVideoListener)) {
|
||||
mMediaResourcePromise.Reject(true, __func__);
|
||||
return p;
|
||||
}
|
||||
@ -1324,7 +1324,6 @@ MediaCodecReader::CreateMediaCodecs()
|
||||
bool
|
||||
MediaCodecReader::CreateMediaCodec(sp<ALooper>& aLooper,
|
||||
Track& aTrack,
|
||||
bool aAsync,
|
||||
bool& aIsWaiting,
|
||||
wp<MediaCodecProxy::CodecResourceListener> aListener)
|
||||
{
|
||||
@ -1362,7 +1361,7 @@ MediaCodecReader::CreateMediaCodec(sp<ALooper>& aLooper,
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!aAsync && aTrack.mCodec->AskMediaCodecAndWait()) {
|
||||
if (aTrack.mType == Track::kAudio && aTrack.mCodec->AllocateAudioMediaCodec()) {
|
||||
// Pending configure() and start() to codecReserved() if the creation
|
||||
// should be asynchronous.
|
||||
if (!aTrack.mCodec->allocated() || !ConfigureMediaCodec(aTrack)){
|
||||
@ -1370,8 +1369,8 @@ MediaCodecReader::CreateMediaCodec(sp<ALooper>& aLooper,
|
||||
DestroyMediaCodec(aTrack);
|
||||
return false;
|
||||
}
|
||||
} else if (aAsync) {
|
||||
if (aTrack.mCodec->AsyncAskMediaCodec()) {
|
||||
} else if (aTrack.mType == Track::kVideo) {
|
||||
if (aTrack.mCodec->AsyncAllocateVideoMediaCodec()) {
|
||||
aIsWaiting = true;
|
||||
} else {
|
||||
NS_WARNING("Couldn't request MediaCodec asynchronously");
|
||||
|
@ -340,7 +340,6 @@ private:
|
||||
RefPtr<MediaResourcePromise> CreateMediaCodecs();
|
||||
static bool CreateMediaCodec(android::sp<android::ALooper>& aLooper,
|
||||
Track& aTrack,
|
||||
bool aAsync,
|
||||
bool& aIsWaiting,
|
||||
android::wp<android::MediaCodecProxy::CodecResourceListener> aListener);
|
||||
static bool ConfigureMediaCodec(Track& aTrack);
|
||||
|
@ -74,7 +74,7 @@ GonkAudioDecoderManager::InitMediaCodecProxy()
|
||||
if (!mDecoder.get()) {
|
||||
return false;
|
||||
}
|
||||
if (!mDecoder->AskMediaCodecAndWait())
|
||||
if (!mDecoder->AllocateAudioMediaCodec())
|
||||
{
|
||||
mDecoder = nullptr;
|
||||
return false;
|
||||
|
@ -124,7 +124,7 @@ GonkVideoDecoderManager::Init()
|
||||
self->codecCanceled();
|
||||
}));
|
||||
mDecoder = MediaCodecProxy::CreateByType(mDecodeLooper, mMimeType.get(), false, mVideoListener);
|
||||
mDecoder->AsyncAskMediaCodec();
|
||||
mDecoder->AsyncAllocateVideoMediaCodec();
|
||||
|
||||
uint32_t capability = MediaCodecProxy::kEmptyCapability;
|
||||
if (mDecoder->getCapability(&capability) == OK && (capability &
|
||||
|
@ -161,6 +161,12 @@ CamerasParent::Observe(nsISupports *aSubject,
|
||||
nsresult
|
||||
CamerasParent::DispatchToVideoCaptureThread(nsRunnable *event)
|
||||
{
|
||||
// Don't try to dispatch if we're already on the right thread.
|
||||
// There's a potential deadlock because the mThreadMonitor is likely
|
||||
// to be taken already.
|
||||
MOZ_ASSERT(!mVideoCaptureThread ||
|
||||
mVideoCaptureThread->thread_id() != PlatformThread::CurrentId());
|
||||
|
||||
MonitorAutoLock lock(mThreadMonitor);
|
||||
|
||||
while(mChildIsAlive && mWebRTCAlive &&
|
||||
@ -184,12 +190,17 @@ CamerasParent::StopVideoCapture()
|
||||
RefPtr<CamerasParent> self(this);
|
||||
RefPtr<nsRunnable> webrtc_runnable =
|
||||
media::NewRunnableFrom([self]() -> nsresult {
|
||||
MonitorAutoLock lock(self->mThreadMonitor);
|
||||
self->CloseEngines();
|
||||
self->mThreadMonitor.NotifyAll();
|
||||
return NS_OK;
|
||||
});
|
||||
DispatchToVideoCaptureThread(webrtc_runnable);
|
||||
MonitorAutoLock lock(self->mThreadMonitor);
|
||||
self->CloseEngines();
|
||||
self->mThreadMonitor.NotifyAll();
|
||||
return NS_OK;
|
||||
});
|
||||
DebugOnly<nsresult> rv = DispatchToVideoCaptureThread(webrtc_runnable);
|
||||
#ifdef DEBUG
|
||||
// It's ok for the dispatch to fail if the cleanup it has to do
|
||||
// has been done already.
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv) || !mWebRTCAlive);
|
||||
#endif
|
||||
// Hold here until the WebRTC thread is gone. We need to dispatch
|
||||
// the thread deletion *now*, or there will be no more possibility
|
||||
// to get to the main thread.
|
||||
@ -393,8 +404,8 @@ CamerasParent::CloseEngines()
|
||||
auto capEngine = mCallbacks[0]->mCapEngine;
|
||||
auto capNum = mCallbacks[0]->mCapturerId;
|
||||
LOG(("Forcing shutdown of engine %d, capturer %d", capEngine, capNum));
|
||||
RecvStopCapture(capEngine, capNum);
|
||||
RecvReleaseCaptureDevice(capEngine, capNum);
|
||||
StopCapture(capEngine, capNum);
|
||||
unused << ReleaseCaptureDevice(capEngine, capNum);
|
||||
}
|
||||
|
||||
for (int i = 0; i < CaptureEngine::MaxEngine; i++) {
|
||||
@ -651,6 +662,17 @@ CamerasParent::RecvAllocateCaptureDevice(const int& aCapEngine,
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
CamerasParent::ReleaseCaptureDevice(const int& aCapEngine,
|
||||
const int& capnum)
|
||||
{
|
||||
int error = -1;
|
||||
if (EnsureInitialized(aCapEngine)) {
|
||||
error = mEngines[aCapEngine].mPtrViECapture->ReleaseCaptureDevice(capnum);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
bool
|
||||
CamerasParent::RecvReleaseCaptureDevice(const int& aCapEngine,
|
||||
const int& numdev)
|
||||
@ -661,10 +683,7 @@ CamerasParent::RecvReleaseCaptureDevice(const int& aCapEngine,
|
||||
RefPtr<CamerasParent> self(this);
|
||||
RefPtr<nsRunnable> webrtc_runnable =
|
||||
media::NewRunnableFrom([self, aCapEngine, numdev]() -> nsresult {
|
||||
int error = -1;
|
||||
if (self->EnsureInitialized(aCapEngine)) {
|
||||
error = self->mEngines[aCapEngine].mPtrViECapture->ReleaseCaptureDevice(numdev);
|
||||
}
|
||||
int error = self->ReleaseCaptureDevice(aCapEngine, numdev);
|
||||
RefPtr<nsIRunnable> ipc_runnable =
|
||||
media::NewRunnableFrom([self, error, numdev]() -> nsresult {
|
||||
if (self->IsShuttingDown()) {
|
||||
@ -748,6 +767,27 @@ CamerasParent::RecvStartCapture(const int& aCapEngine,
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CamerasParent::StopCapture(const int& aCapEngine,
|
||||
const int& capnum)
|
||||
{
|
||||
if (EnsureInitialized(aCapEngine)) {
|
||||
mEngines[aCapEngine].mPtrViECapture->StopCapture(capnum);
|
||||
mEngines[aCapEngine].mPtrViERender->StopRender(capnum);
|
||||
mEngines[aCapEngine].mPtrViERender->RemoveRenderer(capnum);
|
||||
mEngines[aCapEngine].mEngineIsRunning = false;
|
||||
|
||||
for (size_t i = 0; i < mCallbacks.Length(); i++) {
|
||||
if (mCallbacks[i]->mCapEngine == aCapEngine
|
||||
&& mCallbacks[i]->mCapturerId == capnum) {
|
||||
delete mCallbacks[i];
|
||||
mCallbacks.RemoveElementAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CamerasParent::RecvStopCapture(const int& aCapEngine,
|
||||
const int& capnum)
|
||||
@ -757,27 +797,18 @@ CamerasParent::RecvStopCapture(const int& aCapEngine,
|
||||
RefPtr<CamerasParent> self(this);
|
||||
RefPtr<nsRunnable> webrtc_runnable =
|
||||
media::NewRunnableFrom([self, aCapEngine, capnum]() -> nsresult {
|
||||
if (self->EnsureInitialized(aCapEngine)) {
|
||||
self->mEngines[aCapEngine].mPtrViECapture->StopCapture(capnum);
|
||||
self->mEngines[aCapEngine].mPtrViERender->StopRender(capnum);
|
||||
self->mEngines[aCapEngine].mPtrViERender->RemoveRenderer(capnum);
|
||||
self->mEngines[aCapEngine].mEngineIsRunning = false;
|
||||
|
||||
for (size_t i = 0; i < self->mCallbacks.Length(); i++) {
|
||||
if (self->mCallbacks[i]->mCapEngine == aCapEngine
|
||||
&& self->mCallbacks[i]->mCapturerId == capnum) {
|
||||
delete self->mCallbacks[i];
|
||||
self->mCallbacks.RemoveElementAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
self->StopCapture(aCapEngine, capnum);
|
||||
return NS_OK;
|
||||
});
|
||||
if (NS_SUCCEEDED(DispatchToVideoCaptureThread(webrtc_runnable))) {
|
||||
return SendReplySuccess();
|
||||
nsresult rv = DispatchToVideoCaptureThread(webrtc_runnable);
|
||||
if (self->IsShuttingDown()) {
|
||||
return NS_SUCCEEDED(rv);
|
||||
} else {
|
||||
return SendReplyFailure();
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
return SendReplySuccess();
|
||||
} else {
|
||||
return SendReplyFailure();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,9 +119,13 @@ public:
|
||||
protected:
|
||||
virtual ~CamerasParent();
|
||||
|
||||
// We use these helpers for shutdown and for the respective IPC commands.
|
||||
void StopCapture(const int& aCapEngine, const int& capnum);
|
||||
int ReleaseCaptureDevice(const int& aCapEngine, const int& capnum);
|
||||
|
||||
bool SetupEngine(CaptureEngine aCapEngine);
|
||||
void CloseEngines();
|
||||
bool EnsureInitialized(int aEngine);
|
||||
void CloseEngines();
|
||||
void StopIPC();
|
||||
void StopVideoCapture();
|
||||
nsresult DispatchToVideoCaptureThread(nsRunnable *event);
|
||||
|
@ -79,8 +79,8 @@ MediaEngineGonkVideoSource::NotifyPull(MediaStreamGraph* aGraph,
|
||||
// Note: we're not giving up mImage here
|
||||
RefPtr<layers::Image> image = mImage;
|
||||
StreamTime delta = aDesiredTime - aSource->GetEndOfAppendedData(aID);
|
||||
LOGFRAME(("NotifyPull, desired = %ld, delta = %ld %s", (int64_t) aDesiredTime,
|
||||
(int64_t) delta, image ? "" : "<null>"));
|
||||
LOGFRAME(("NotifyPull, desired = %" PRIi64 ", delta = %" PRIi64 " %s",
|
||||
(int64_t) aDesiredTime, (int64_t) delta, image ? "" : "<null>"));
|
||||
|
||||
// Bug 846188 We may want to limit incoming frames to the requested frame rate
|
||||
// mFps - if you want 30FPS, and the camera gives you 60FPS, this could
|
||||
|
@ -319,8 +319,8 @@ MediaEngineRemoteVideoSource::DeliverFrame(unsigned char* buffer,
|
||||
|
||||
#ifdef DEBUG
|
||||
static uint32_t frame_num = 0;
|
||||
LOGFRAME(("frame %d (%dx%d); timestamp %u, ntp_time %lu, render_time %lu", frame_num++,
|
||||
mWidth, mHeight, time_stamp, ntp_time, render_time));
|
||||
LOGFRAME(("frame %d (%dx%d); timestamp %u, ntp_time %" PRIu64 ", render_time %" PRIu64,
|
||||
frame_num++, mWidth, mHeight, time_stamp, ntp_time, render_time));
|
||||
#endif
|
||||
|
||||
// we don't touch anything in 'this' until here (except for snapshot,
|
||||
|
@ -925,6 +925,9 @@ this.PushService = {
|
||||
if (this._state == PUSH_SERVICE_CONNECTION_DISABLE) {
|
||||
return Promise.reject({state: 0, error: "Service not active"});
|
||||
} else if (this._state == PUSH_SERVICE_ACTIVE_OFFLINE) {
|
||||
if (this._service.serviceType() == "WebSocket" && action == "unregister") {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return Promise.reject({state: 0, error: "NetworkError"});
|
||||
}
|
||||
return this._service.request(action, aRecord);
|
||||
|
@ -441,6 +441,10 @@ this.PushServiceHttp2 = {
|
||||
PushRecordHttp2);
|
||||
},
|
||||
|
||||
serviceType: function() {
|
||||
return "http2";
|
||||
},
|
||||
|
||||
hasmainPushService: function() {
|
||||
return this._mainPushService !== null;
|
||||
},
|
||||
|
@ -157,6 +157,10 @@ this.PushServiceWebSocket = {
|
||||
PushRecordWebSocket);
|
||||
},
|
||||
|
||||
serviceType: function() {
|
||||
return "WebSocket";
|
||||
},
|
||||
|
||||
disconnect: function() {
|
||||
this._shutdownWS();
|
||||
},
|
||||
|
@ -776,7 +776,7 @@ nsCSPContext::SendReports(nsISupports* aBlockedContentSource,
|
||||
const char16_t* params[] = { reportURIs[r].get() };
|
||||
CSPCONTEXTLOG(("Could not create nsIURI for report URI %s",
|
||||
reportURICstring.get()));
|
||||
CSP_LogLocalizedStr(NS_LITERAL_STRING("triedToSendReport").get(),
|
||||
CSP_LogLocalizedStr(MOZ_UTF16("triedToSendReport"),
|
||||
params, ArrayLength(params),
|
||||
aSourceFile, aScriptSample, aLineNum, 0,
|
||||
nsIScriptError::errorFlag, "CSP", mInnerWindowID);
|
||||
@ -820,7 +820,7 @@ nsCSPContext::SendReports(nsISupports* aBlockedContentSource,
|
||||
|
||||
if (!isHttpScheme) {
|
||||
const char16_t* params[] = { reportURIs[r].get() };
|
||||
CSP_LogLocalizedStr(NS_LITERAL_STRING("reportURInotHttpsOrHttp2").get(),
|
||||
CSP_LogLocalizedStr(MOZ_UTF16("reportURInotHttpsOrHttp2"),
|
||||
params, ArrayLength(params),
|
||||
aSourceFile, aScriptSample, aLineNum, 0,
|
||||
nsIScriptError::errorFlag, "CSP", mInnerWindowID);
|
||||
@ -904,7 +904,7 @@ nsCSPContext::SendReports(nsISupports* aBlockedContentSource,
|
||||
if (NS_FAILED(rv)) {
|
||||
const char16_t* params[] = { reportURIs[r].get() };
|
||||
CSPCONTEXTLOG(("AsyncOpen failed for report URI %s", params[0]));
|
||||
CSP_LogLocalizedStr(NS_LITERAL_STRING("triedToSendReport").get(),
|
||||
CSP_LogLocalizedStr(MOZ_UTF16("triedToSendReport"),
|
||||
params, ArrayLength(params),
|
||||
aSourceFile, aScriptSample, aLineNum, 0,
|
||||
nsIScriptError::errorFlag, "CSP", mInnerWindowID);
|
||||
@ -994,8 +994,8 @@ class CSPReportSenderRunnable final : public nsRunnable
|
||||
const char16_t* params[] = { mViolatedDirective.get(),
|
||||
blockedDataChar16.get() };
|
||||
|
||||
CSP_LogLocalizedStr(mReportOnlyFlag ? NS_LITERAL_STRING("CSPROViolationWithURI").get() :
|
||||
NS_LITERAL_STRING("CSPViolationWithURI").get(),
|
||||
CSP_LogLocalizedStr(mReportOnlyFlag ? MOZ_UTF16("CSPROViolationWithURI") :
|
||||
MOZ_UTF16("CSPViolationWithURI"),
|
||||
params, ArrayLength(params),
|
||||
mSourceFile, mScriptSample, mLineNum, 0,
|
||||
nsIScriptError::errorFlag, "CSP", mInnerWindowID);
|
||||
@ -1313,7 +1313,7 @@ CSPReportRedirectSink::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
|
||||
NS_ASSERTION(observerService, "Observer service required to log CSP violations");
|
||||
observerService->NotifyObservers(uri,
|
||||
CSP_VIOLATION_TOPIC,
|
||||
NS_LITERAL_STRING("denied redirect while sending violation report").get());
|
||||
MOZ_UTF16("denied redirect while sending violation report"));
|
||||
|
||||
return NS_BINDING_REDIRECTED;
|
||||
}
|
||||
|
@ -1012,7 +1012,7 @@ nsCSPParser::directive()
|
||||
// Make sure that the directive-srcs-array contains at least
|
||||
// one directive and one src.
|
||||
if (mCurDir.Length() < 1) {
|
||||
const char16_t* params[] = { NS_LITERAL_STRING("directive missing").get() };
|
||||
const char16_t* params[] = { MOZ_UTF16("directive missing") };
|
||||
logWarningErrorToConsole(nsIScriptError::warningFlag, "failedToParseUnrecognizedSource",
|
||||
params, ArrayLength(params));
|
||||
return;
|
||||
@ -1029,7 +1029,7 @@ nsCSPParser::directive()
|
||||
// by a directive name but does not include any srcs.
|
||||
if (cspDir->equals(nsIContentSecurityPolicy::UPGRADE_IF_INSECURE_DIRECTIVE)) {
|
||||
if (mCurDir.Length() > 1) {
|
||||
const char16_t* params[] = { NS_LITERAL_STRING("upgrade-insecure-requests").get() };
|
||||
const char16_t* params[] = { MOZ_UTF16("upgrade-insecure-requests") };
|
||||
logWarningErrorToConsole(nsIScriptError::warningFlag,
|
||||
"ignoreSrcForDirective",
|
||||
params, ArrayLength(params));
|
||||
@ -1062,7 +1062,7 @@ nsCSPParser::directive()
|
||||
mHasHashOrNonce && mUnsafeInlineKeywordSrc) {
|
||||
mUnsafeInlineKeywordSrc->invalidate();
|
||||
// log to the console that unsafe-inline will be ignored
|
||||
const char16_t* params[] = { NS_LITERAL_STRING("'unsafe-inline'").get() };
|
||||
const char16_t* params[] = { MOZ_UTF16("'unsafe-inline'") };
|
||||
logWarningErrorToConsole(nsIScriptError::warningFlag, "ignoringSrcWithinScriptSrc",
|
||||
params, ArrayLength(params));
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -18,7 +18,9 @@
|
||||
|
||||
#include "mozilla/HalTypes.h"
|
||||
#include "mozilla/Observer.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsIAudioManager.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "android_audio/AudioSystem.h"
|
||||
@ -53,32 +55,7 @@ enum AudioOutputProfiles {
|
||||
DEVICE_TOTAL_NUMBER = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* We have five sound volume settings from UX spec,
|
||||
* You can see more informations in Bug1068219.
|
||||
* (1) Media : music, video, FM ...
|
||||
* (2) Notification : ringer, notification ...
|
||||
* (3) Alarm : alarm
|
||||
* (4) Telephony : GSM call, WebRTC call
|
||||
* (5) Bluetooth SCO : SCO call
|
||||
**/
|
||||
enum AudioVolumeCategories {
|
||||
VOLUME_MEDIA = 0,
|
||||
VOLUME_NOTIFICATION = 1,
|
||||
VOLUME_ALARM = 2,
|
||||
VOLUME_TELEPHONY = 3,
|
||||
VOLUME_BLUETOOTH_SCO = 4,
|
||||
VOLUME_TOTAL_NUMBER = 5,
|
||||
};
|
||||
|
||||
struct VolumeData {
|
||||
const char* mChannelName;
|
||||
uint32_t mCategory;
|
||||
};
|
||||
|
||||
class RecoverTask;
|
||||
class VolumeInitCallback;
|
||||
class AudioProfileData;
|
||||
|
||||
class AudioManager final : public nsIAudioManager
|
||||
, public nsIObserver
|
||||
@ -90,27 +67,63 @@ public:
|
||||
NS_DECL_NSIAUDIOMANAGER
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
// When audio backend is dead, recovery task needs to read all volume
|
||||
// settings then set back into audio backend.
|
||||
friend class RecoverTask;
|
||||
friend class VolumeInitCallback;
|
||||
|
||||
// Open or close the specific profile
|
||||
void SwitchProfileData(AudioOutputProfiles aProfile, bool aActive);
|
||||
|
||||
// Validate whether the volume index is within the range
|
||||
nsresult ValidateVolumeIndex(uint32_t aCategory, uint32_t aIndex) const;
|
||||
nsresult ValidateVolumeIndex(int32_t aStream, uint32_t aIndex) const;
|
||||
|
||||
// Called when android AudioFlinger in mediaserver is died
|
||||
void HandleAudioFlingerDied();
|
||||
|
||||
void HandleHeadphoneSwitchEvent(const hal::SwitchEvent& aEvent);
|
||||
|
||||
class VolumeStreamState {
|
||||
public:
|
||||
explicit VolumeStreamState(AudioManager& aManager, int32_t aStreamType);
|
||||
int32_t GetStreamType()
|
||||
{
|
||||
return mStreamType;
|
||||
}
|
||||
bool IsDevicesChanged(bool aFromCache = true);
|
||||
void ClearDevicesChanged();
|
||||
uint32_t GetLastDevices()
|
||||
{
|
||||
return mLastDevices;
|
||||
}
|
||||
void InitStreamVolume();
|
||||
uint32_t GetMaxIndex();
|
||||
uint32_t GetDefaultIndex();
|
||||
uint32_t GetVolumeIndex();
|
||||
uint32_t GetVolumeIndex(uint32_t aDevice);
|
||||
void ClearCurrentVolumeUpdated();
|
||||
// Set volume index to all active devices.
|
||||
// Active devices are chosen by android AudioPolicyManager.
|
||||
nsresult SetVolumeIndexToActiveDevices(uint32_t aIndex);
|
||||
// Set volume index to all alias streams. Alias streams have same volume.
|
||||
// It is used to update volume based on audio output profile data.
|
||||
nsresult SetVolumeIndexToAliasStreams(uint32_t aIndex, uint32_t aDevice);
|
||||
// Set volume index to all alias devices in audio output profile.
|
||||
// Alias devices have same volume.
|
||||
nsresult SetVolumeIndexToAliasDevices(uint32_t aIndex, uint32_t aDevice);
|
||||
nsresult SetVolumeIndex(uint32_t aIndex, uint32_t aDevice, bool aUpdateCache = true);
|
||||
// Restore volume index to all devices. Called when AudioFlinger is restarted.
|
||||
void RestoreVolumeIndexToAllDevices();
|
||||
private:
|
||||
AudioManager& mManager;
|
||||
const int32_t mStreamType;
|
||||
uint32_t mLastDevices;
|
||||
bool mIsDevicesChanged;
|
||||
nsDataHashtable<nsUint32HashKey, uint32_t> mVolumeIndexes;
|
||||
};
|
||||
|
||||
protected:
|
||||
int32_t mPhoneState;
|
||||
|
||||
// A bitwise variable for recording what kind of headset/headphone is attached.
|
||||
int32_t mHeadsetState;
|
||||
bool mIsVolumeInited;
|
||||
|
||||
// A bitwise variable for volume update of audio output profiles
|
||||
uint32_t mAudioOutProfileUpdated;
|
||||
|
||||
// Connected devices that are controlled by setDeviceConnectionState()
|
||||
nsDataHashtable<nsUint32HashKey, nsCString> mConnectedDevices;
|
||||
|
||||
bool mSwitchDone;
|
||||
|
||||
@ -120,11 +133,23 @@ protected:
|
||||
#ifdef MOZ_B2G_BT
|
||||
bool mA2dpSwitchDone;
|
||||
#endif
|
||||
uint32_t mCurrentStreamVolumeTbl[AUDIO_STREAM_CNT];
|
||||
nsTArray<UniquePtr<VolumeStreamState> > mStreamStates;
|
||||
uint32_t mLastChannelVolume[AUDIO_STREAM_CNT];
|
||||
|
||||
bool IsFmOutConnected();
|
||||
|
||||
nsresult SetStreamVolumeForProfile(AudioOutputProfiles aProfile,
|
||||
int32_t aStream,
|
||||
uint32_t aIndex);
|
||||
nsresult SetStreamVolumeIndex(int32_t aStream, uint32_t aIndex);
|
||||
nsresult GetStreamVolumeIndex(int32_t aStream, uint32_t *aIndex);
|
||||
|
||||
void UpdateCachedActiveDevicesForStreams();
|
||||
uint32_t GetDevicesForStream(int32_t aStream, bool aFromCache = true);
|
||||
uint32_t GetDeviceForStream(int32_t aStream);
|
||||
// Choose one device as representative of active devices.
|
||||
static uint32_t SelectDeviceFromDevices(uint32_t aOutDevices);
|
||||
|
||||
private:
|
||||
nsAutoPtr<mozilla::hal::SwitchObserver> mObserver;
|
||||
#ifdef MOZ_B2G_RIL
|
||||
@ -132,57 +157,41 @@ private:
|
||||
// mIsMicMuted is only used for toggling mute call to RIL.
|
||||
bool mIsMicMuted;
|
||||
#endif
|
||||
nsTArray<nsAutoPtr<AudioProfileData>> mAudioProfiles;
|
||||
AudioOutputProfiles mPresentProfile;
|
||||
|
||||
void HandleBluetoothStatusChanged(nsISupports* aSubject,
|
||||
const char* aTopic,
|
||||
const nsCString aAddress);
|
||||
void HandleAudioChannelProcessChanged();
|
||||
|
||||
void CreateAudioProfilesData();
|
||||
// Initialize volume index for audio output profile
|
||||
void InitVolumeForProfile(AudioOutputProfiles aProfile,
|
||||
int32_t aStreamType,
|
||||
uint32_t aIndex);
|
||||
|
||||
// Init the volume setting from the init setting callback
|
||||
void InitProfileVolume(AudioOutputProfiles aProfile,
|
||||
uint32_t aCatogory, uint32_t aIndex);
|
||||
|
||||
// Update volume data of profiles
|
||||
void UpdateVolumeToProfile(AudioProfileData* aProfileData);
|
||||
|
||||
// Apply the volume data to device
|
||||
void UpdateVolumeFromProfile(AudioProfileData* aProfileData);
|
||||
|
||||
// Send the volume changing event to Gaia
|
||||
void SendVolumeChangeNotification(AudioProfileData* aProfileData);
|
||||
|
||||
// Update the mPresentProfile and profiles active status
|
||||
void UpdateProfileState(AudioOutputProfiles aProfile, bool aActive);
|
||||
|
||||
// Volume control functions
|
||||
nsresult SetVolumeByCategory(uint32_t aCategory, uint32_t aIndex);
|
||||
uint32_t GetVolumeByCategory(uint32_t aCategory) const;
|
||||
uint32_t GetMaxVolumeByCategory(uint32_t aCategory) const;
|
||||
|
||||
AudioProfileData* FindAudioProfileData(AudioOutputProfiles aProfile);
|
||||
|
||||
// Append the profile to the volume setting string.
|
||||
// Append the audio output profile to the volume setting string.
|
||||
nsAutoCString AppendProfileToVolumeSetting(const char* aName,
|
||||
AudioOutputProfiles aProfile);
|
||||
|
||||
// We store the volume setting in the database, these are related functions.
|
||||
void InitVolumeFromDatabase();
|
||||
void UpdateVolumeSettingToDatabase(nsISettingsServiceLock* aLock,
|
||||
const char* aTopic,
|
||||
uint32_t aVolIndex);
|
||||
void MaybeUpdateVolumeSettingToDatabase(bool aForce = false);
|
||||
|
||||
// Promise functions.
|
||||
void InitProfileVolumeSucceeded();
|
||||
void InitProfileVolumeFailed(const char* aError);
|
||||
|
||||
void AudioOutProfileUpdated(AudioOutputProfiles aProfile);
|
||||
|
||||
void UpdateHeadsetConnectionState(hal::SwitchState aState);
|
||||
void UpdateDeviceConnectionState(bool aIsConnected, uint32_t aDevice, const nsCString& aDeviceName);
|
||||
void SetAllDeviceConnectionStates();
|
||||
|
||||
AudioManager();
|
||||
~AudioManager();
|
||||
|
||||
friend class VolumeInitCallback;
|
||||
friend class VolumeStreamState;
|
||||
friend class GonkAudioPortCallback;
|
||||
};
|
||||
|
||||
} /* namespace gonk */
|
||||
|
@ -969,6 +969,9 @@ public:
|
||||
static status_t getStreamVolumeIndex(audio_stream_type_t stream, int *index);
|
||||
|
||||
static uint32_t getStrategyForStream(stream_type stream);
|
||||
#if ANDROID_VERSION >= 17
|
||||
static audio_devices_t getDevicesForStream(audio_stream_type_t stream);
|
||||
#endif
|
||||
|
||||
static audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc);
|
||||
static status_t registerEffect(effect_descriptor_t *desc,
|
||||
@ -995,6 +998,23 @@ public:
|
||||
static bool isLinearPCM(uint32_t format);
|
||||
static bool isModeInCall();
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
class AudioPortCallback : public RefBase
|
||||
{
|
||||
public:
|
||||
|
||||
AudioPortCallback() {}
|
||||
virtual ~AudioPortCallback() {}
|
||||
|
||||
virtual void onAudioPortListUpdate() = 0;
|
||||
virtual void onAudioPatchListUpdate() = 0;
|
||||
virtual void onServiceDied() = 0;
|
||||
|
||||
};
|
||||
|
||||
static void setAudioPortCallback(sp<AudioPortCallback> callBack);
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
class AudioFlingerClient: public IBinder::DeathRecipient, public BnAudioFlingerClient
|
||||
|
@ -41,6 +41,7 @@ var radioInterface = ril.getRadioInterface(0);
|
||||
ok(radioInterface, "radioInterface.constructor is " + radioInterface.constrctor);
|
||||
|
||||
var _pendingEmulatorShellCmdCount = 0;
|
||||
var _pendingEmulatorCmdCount = 0;
|
||||
|
||||
/**
|
||||
* Send emulator shell command with safe guard.
|
||||
@ -69,6 +70,41 @@ function runEmulatorShellCmdSafe(aCommands) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Send emulator command with safe guard.
|
||||
*
|
||||
* We should only call |finish()| after all emulator command transactions
|
||||
* end, so here comes with the pending counter. Resolve when the emulator
|
||||
* gives positive response, and reject otherwise.
|
||||
*
|
||||
* Fulfill params:
|
||||
* result -- an array of emulator response lines.
|
||||
* Reject params:
|
||||
* result -- an array of emulator response lines.
|
||||
*
|
||||
* @param aCommand
|
||||
* A string command to be passed to emulator through its telnet console.
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function runEmulatorCmdSafe(aCommand) {
|
||||
log(aCommand);
|
||||
return new Promise(function(aResolve, aReject) {
|
||||
++_pendingEmulatorCmdCount;
|
||||
runEmulatorCmd(aCommand, function(aResult) {
|
||||
--_pendingEmulatorCmdCount;
|
||||
|
||||
log("Emulator console response: " + JSON.stringify(aResult));
|
||||
if (Array.isArray(aResult) &&
|
||||
aResult[aResult.length - 1] === "OK") {
|
||||
aResolve(aResult);
|
||||
} else {
|
||||
aReject(aResult);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get mozSettings value specified by @aKey.
|
||||
*
|
||||
@ -286,11 +322,11 @@ function cleanUp() {
|
||||
ok(true, ":: CLEANING UP ::");
|
||||
|
||||
waitFor(finish, function() {
|
||||
return _pendingEmulatorShellCmdCount === 0;
|
||||
return _pendingEmulatorShellCmdCount === 0 &&
|
||||
_pendingEmulatorCmdCount === 0;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Basic test routine helper.
|
||||
*
|
||||
|
@ -17,3 +17,5 @@ disabled = Bug 808783
|
||||
[test_all_network_info.js]
|
||||
[test_network_interface_mtu.js]
|
||||
skip-if = android_version < '19'
|
||||
[test_timezone_changes.js]
|
||||
skip-if = android_version < '19'
|
||||
|
135
dom/system/gonk/tests/marionette/test_timezone_changes.js
Normal file
135
dom/system/gonk/tests/marionette/test_timezone_changes.js
Normal file
@ -0,0 +1,135 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 60000;
|
||||
MARIONETTE_HEAD_JS = 'head.js';
|
||||
|
||||
function init() {
|
||||
let promises = [];
|
||||
|
||||
/*
|
||||
* The initial timezone of the emulator could be anywhere, depends the host
|
||||
* machine. Ensure resetting it to UTC before testing.
|
||||
*/
|
||||
promises.push(runEmulatorCmdSafe('gsm timezone 0'));
|
||||
promises.push(new Promise((aResolve, aReject) => {
|
||||
waitFor(aResolve, () => {
|
||||
return new Date().getTimezoneOffset() === 0;
|
||||
});
|
||||
}));
|
||||
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
function paddingZeros(aNumber, aLength) {
|
||||
let str = '' + aNumber;
|
||||
while (str.length < aLength) {
|
||||
str = '0' + str;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
function verifyDate(aTestDate, aUTCOffsetDate) {
|
||||
// Verify basic properties.
|
||||
is(aUTCOffsetDate.getUTCFullYear(), aTestDate.getFullYear(), 'year');
|
||||
is(aUTCOffsetDate.getUTCMonth(), aTestDate.getMonth(), 'month');
|
||||
is(aUTCOffsetDate.getUTCDate(), aTestDate.getDate(), 'date');
|
||||
is(aUTCOffsetDate.getUTCHours(), aTestDate.getHours(), 'hours');
|
||||
is(aUTCOffsetDate.getUTCMinutes(), aTestDate.getMinutes(), 'minutes');
|
||||
is(aUTCOffsetDate.getUTCMilliseconds(), aTestDate.getMilliseconds(), 'milliseconds');
|
||||
|
||||
// Ensure toLocaleString also uses correct timezone.
|
||||
// It uses ICU's timezone instead of the offset calculated from gecko prtime.
|
||||
let expectedDateString =
|
||||
paddingZeros(aUTCOffsetDate.getUTCMonth() + 1, 2) + '/' +
|
||||
paddingZeros(aUTCOffsetDate.getUTCDate(), 2);
|
||||
let dateString = aTestDate.toLocaleString('en-US', {
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
});
|
||||
let expectedTimeString =
|
||||
paddingZeros(aUTCOffsetDate.getUTCHours(), 2) + ':' +
|
||||
paddingZeros(aUTCOffsetDate.getUTCMinutes(), 2);
|
||||
let timeString = aTestDate.toLocaleString('en-US', {
|
||||
hour12: false,
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
});
|
||||
|
||||
is(expectedDateString, dateString, 'dateString');
|
||||
is(expectedTimeString, timeString, 'timeString');
|
||||
}
|
||||
|
||||
function waitForTimezoneUpdate(aTzOffset,
|
||||
aTestDateInMillis = 86400000, // Use 'UTC 00:00:00, 2nd of Jan, 1970' by default.
|
||||
aTransTzOffset, aTransTestDateInMillis) {
|
||||
return new Promise(function(aResolve, aReject) {
|
||||
window.addEventListener('moztimechange', function onevent(aEvent) {
|
||||
// Since there could be multiple duplicate moztimechange event, wait until
|
||||
// timezone is actually changed to expected value before removing the
|
||||
// listener.
|
||||
let testDate = new Date(aTestDateInMillis);
|
||||
if (testDate.getTimezoneOffset() === aTzOffset) {
|
||||
window.removeEventListener('moztimechange', onevent);
|
||||
|
||||
// The UTC time of offsetDate is the same as the expected local time of
|
||||
// testDate. We'll use it to verify the values.
|
||||
let offsetDate = new Date(aTestDateInMillis - aTzOffset * 60 * 1000);
|
||||
verifyDate(testDate, offsetDate);
|
||||
|
||||
// Verify transition time if given.
|
||||
if (aTransTzOffset !== undefined) {
|
||||
testDate = new Date(aTransTestDateInMillis);
|
||||
is(testDate.getTimezoneOffset(), aTransTzOffset);
|
||||
|
||||
// Verify transition date.
|
||||
offsetDate = new Date(aTransTestDateInMillis - aTransTzOffset * 60 * 1000);
|
||||
verifyDate(testDate, offsetDate);
|
||||
}
|
||||
|
||||
aResolve(aEvent);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function testChangeNitzTimezone(aTzDiff) {
|
||||
let promises = [];
|
||||
|
||||
// aTzOffset should be the expected value for getTimezoneOffset().
|
||||
// Note that getTimezoneOffset() is not so straightforward,
|
||||
// it values (UTC - localtime), so UTC+08:00 returns -480.
|
||||
promises.push(waitForTimezoneUpdate(-aTzDiff * 15));
|
||||
promises.push(runEmulatorCmdSafe('gsm timezone ' + aTzDiff));
|
||||
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
function testChangeOlsonTimezone(aOlsonTz, aTzOffset, aTestDateInMillis,
|
||||
aTransTzOffset, aTransTestDateInMillis) {
|
||||
let promises = [];
|
||||
|
||||
promises.push(waitForTimezoneUpdate(aTzOffset, aTestDateInMillis,
|
||||
aTransTzOffset, aTransTestDateInMillis));
|
||||
promises.push(setSettings('time.timezone', aOlsonTz));
|
||||
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
// Start test
|
||||
startTestBase(function() {
|
||||
return init()
|
||||
.then(() => testChangeNitzTimezone(36)) // UTC+09:00
|
||||
.then(() => testChangeOlsonTimezone('America/New_York',
|
||||
300, 1446357600000, // 2015/11/01 02:00 UTC-04:00 => 01:00 UTC-05:00 (EST)
|
||||
240, 1425798000000)) // 2015/03/08 02:00 UTC-05:00 => 03:00 UTC-04:00 (EDT)
|
||||
.then(() => testChangeNitzTimezone(-22)) // UTC-05:30
|
||||
.then(() => testChangeNitzTimezone(51)) // UTC+12:45
|
||||
.then(() => testChangeOlsonTimezone('Australia/Adelaide',
|
||||
-570, 1428165000000, // 2015/04/05 03:00 UTC+10:30 => 02:00 UTC+09:30 (ACST)
|
||||
-630, 1443889800000)) // 2015/10/04 02:00 UTC+09:30 => 03:00 UTC+10:30 (ACDT)
|
||||
.then(() => testChangeNitzTimezone(-38)) // UTC-09:30
|
||||
.then(() => testChangeNitzTimezone(0)) // UTC
|
||||
.then(() => runEmulatorCmdSafe('gsm timezone auto'));
|
||||
});
|
@ -95,7 +95,7 @@ nsXULContentUtils::Init()
|
||||
|
||||
#define XUL_LITERAL(ident, val) \
|
||||
PR_BEGIN_MACRO \
|
||||
rv = gRDF->GetLiteral(NS_LITERAL_STRING(val).get(), &(ident)); \
|
||||
rv = gRDF->GetLiteral(MOZ_UTF16(val), &(ident)); \
|
||||
if (NS_FAILED(rv)) return rv; \
|
||||
PR_END_MACRO
|
||||
|
||||
|
@ -110,7 +110,7 @@ CopyBGRXSurfaceDataToPackedBGRArray(uint8_t* aSrc, uint8_t* aDst,
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
UniquePtr<uint8_t[]>
|
||||
SurfaceToPackedBGRA(DataSourceSurface *aSurface)
|
||||
{
|
||||
SurfaceFormat format = aSurface->GetFormat();
|
||||
@ -120,25 +120,25 @@ SurfaceToPackedBGRA(DataSourceSurface *aSurface)
|
||||
|
||||
IntSize size = aSurface->GetSize();
|
||||
|
||||
uint8_t* imageBuffer = new (std::nothrow) uint8_t[size.width * size.height * sizeof(uint32_t)];
|
||||
UniquePtr<uint8_t[]> imageBuffer(
|
||||
new (std::nothrow) uint8_t[size.width * size.height * sizeof(uint32_t)]);
|
||||
if (!imageBuffer) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DataSourceSurface::MappedSurface map;
|
||||
if (!aSurface->Map(DataSourceSurface::MapType::READ, &map)) {
|
||||
delete [] imageBuffer;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CopySurfaceDataToPackedArray(map.mData, imageBuffer, size,
|
||||
CopySurfaceDataToPackedArray(map.mData, imageBuffer.get(), size,
|
||||
map.mStride, 4 * sizeof(uint8_t));
|
||||
|
||||
aSurface->Unmap();
|
||||
|
||||
if (format == SurfaceFormat::B8G8R8X8) {
|
||||
// Convert BGRX to BGRA by setting a to 255.
|
||||
ConvertBGRXToBGRA(reinterpret_cast<uint8_t *>(imageBuffer), size, size.width * sizeof(uint32_t));
|
||||
ConvertBGRXToBGRA(imageBuffer.get(), size, size.width * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
return imageBuffer;
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
#include "2D.h"
|
||||
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
@ -25,11 +27,9 @@ CopySurfaceDataToPackedArray(uint8_t* aSrc, uint8_t* aDst, IntSize aSrcSize,
|
||||
int32_t aSrcStride, int32_t aBytesPerPixel);
|
||||
|
||||
/**
|
||||
* Convert aSurface to a packed buffer in BGRA format. The pixel data is
|
||||
* returned in a buffer allocated with new uint8_t[]. The caller then has
|
||||
* ownership of the buffer and is responsible for delete[]'ing it.
|
||||
* Convert aSurface to a packed buffer in BGRA format.
|
||||
*/
|
||||
uint8_t*
|
||||
UniquePtr<uint8_t[]>
|
||||
SurfaceToPackedBGRA(DataSourceSurface *aSurface);
|
||||
|
||||
/**
|
||||
|
@ -110,7 +110,7 @@ struct LayerPropertiesBase : public LayerProperties
|
||||
, mPostXScale(aLayer->GetPostXScale())
|
||||
, mPostYScale(aLayer->GetPostYScale())
|
||||
, mOpacity(aLayer->GetLocalOpacity())
|
||||
, mUseClipRect(!!aLayer->GetClipRect())
|
||||
, mUseClipRect(!!aLayer->GetEffectiveClipRect())
|
||||
{
|
||||
MOZ_COUNT_CTOR(LayerPropertiesBase);
|
||||
if (aLayer->GetMaskLayer()) {
|
||||
@ -121,7 +121,7 @@ struct LayerPropertiesBase : public LayerProperties
|
||||
mAncestorMaskLayers.AppendElement(CloneLayerTreePropertiesInternal(maskLayer, true));
|
||||
}
|
||||
if (mUseClipRect) {
|
||||
mClipRect = *aLayer->GetClipRect();
|
||||
mClipRect = *aLayer->GetEffectiveClipRect();
|
||||
}
|
||||
mTransform = aLayer->GetLocalTransform();
|
||||
}
|
||||
@ -148,7 +148,7 @@ struct LayerPropertiesBase : public LayerProperties
|
||||
bool transformChanged = !mTransform.FuzzyEqualsMultiplicative(mLayer->GetLocalTransform()) ||
|
||||
mLayer->GetPostXScale() != mPostXScale ||
|
||||
mLayer->GetPostYScale() != mPostYScale;
|
||||
const Maybe<ParentLayerIntRect>& otherClip = mLayer->GetClipRect();
|
||||
const Maybe<ParentLayerIntRect>& otherClip = mLayer->GetEffectiveClipRect();
|
||||
nsIntRegion result;
|
||||
|
||||
bool ancestorMaskChanged = mAncestorMaskLayers.Length() != mLayer->GetAncestorMaskLayerCount();
|
||||
|
@ -688,6 +688,7 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
|
||||
switch (aEvent.mInputType) {
|
||||
case MULTITOUCH_INPUT: {
|
||||
MultiTouchInput& touchInput = aEvent.AsMultiTouchInput();
|
||||
touchInput.mHandledByAPZ = true;
|
||||
result = ProcessTouchInput(touchInput, aOutTargetGuid, aOutInputBlockId);
|
||||
break;
|
||||
} case MOUSE_INPUT: {
|
||||
|
@ -97,7 +97,8 @@ InputQueue::ReceiveTouchInput(const RefPtr<AsyncPanZoomController>& aTarget,
|
||||
}
|
||||
|
||||
block = StartNewTouchBlock(aTarget, aTargetConfirmed, false);
|
||||
INPQ_LOG("started new touch block %p for target %p\n", block, aTarget.get());
|
||||
INPQ_LOG("started new touch block %p id %" PRIu64 " for target %p\n",
|
||||
block, block->GetBlockId(), aTarget.get());
|
||||
|
||||
// XXX using the chain from |block| here may be wrong in cases where the
|
||||
// target isn't confirmed and the real target turns out to be something
|
||||
|
@ -262,21 +262,27 @@ APZEventState::ProcessTouchEvent(const WidgetTouchEvent& aEvent,
|
||||
bool isTouchPrevented = TouchManager::gPreventMouseEvents ||
|
||||
aEvent.mFlags.mMultipleActionsPrevented;
|
||||
bool sentContentResponse = false;
|
||||
APZES_LOG("Handling event type %d\n", aEvent.mMessage);
|
||||
switch (aEvent.mMessage) {
|
||||
case eTouchStart: {
|
||||
mTouchEndCancelled = false;
|
||||
if (mPendingTouchPreventedResponse) {
|
||||
// We can enter here if we get two TOUCH_STARTs in a row and didn't
|
||||
// respond to the first one. Respond to it now.
|
||||
mContentReceivedInputBlockCallback(mPendingTouchPreventedGuid,
|
||||
mPendingTouchPreventedBlockId, false);
|
||||
sentContentResponse = true;
|
||||
mPendingTouchPreventedResponse = false;
|
||||
sentContentResponse = SendPendingTouchPreventedResponse(false);
|
||||
// sentContentResponse can be true here if we get two TOUCH_STARTs in a row
|
||||
// and just responded to the first one.
|
||||
if (!aEvent.mFlags.mHandledByAPZ) {
|
||||
// This condition being true means this touchstart is synthetic and is
|
||||
// coming from TabParent.injectTouchEvent.
|
||||
// Since APZ doesn't know about it we don't want to send a response for
|
||||
// this block; we want to just skip over it from the point of view of
|
||||
// prevent-default notifications.
|
||||
break;
|
||||
}
|
||||
if (isTouchPrevented) {
|
||||
mContentReceivedInputBlockCallback(aGuid, aInputBlockId, isTouchPrevented);
|
||||
sentContentResponse = true;
|
||||
} else {
|
||||
APZES_LOG("Event not prevented; pending response for %" PRIu64 " %s\n",
|
||||
aInputBlockId, Stringify(aGuid).c_str());
|
||||
mPendingTouchPreventedResponse = true;
|
||||
mPendingTouchPreventedGuid = aGuid;
|
||||
mPendingTouchPreventedBlockId = aInputBlockId;
|
||||
@ -410,6 +416,8 @@ bool
|
||||
APZEventState::SendPendingTouchPreventedResponse(bool aPreventDefault)
|
||||
{
|
||||
if (mPendingTouchPreventedResponse) {
|
||||
APZES_LOG("Sending response %d for pending guid: %s\n", aPreventDefault,
|
||||
Stringify(mPendingTouchPreventedGuid).c_str());
|
||||
mContentReceivedInputBlockCallback(mPendingTouchPreventedGuid,
|
||||
mPendingTouchPreventedBlockId, aPreventDefault);
|
||||
mPendingTouchPreventedResponse = false;
|
||||
|
@ -69,6 +69,7 @@ public:
|
||||
|
||||
BasicCompositor::BasicCompositor(nsIWidget *aWidget)
|
||||
: mWidget(aWidget)
|
||||
, mDidExternalComposition(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(BasicCompositor);
|
||||
|
||||
@ -509,9 +510,16 @@ BasicCompositor::BeginFrame(const nsIntRegion& aInvalidRegion,
|
||||
IntRect intRect = gfx::IntRect(IntPoint(), mWidgetSize);
|
||||
Rect rect = Rect(0, 0, intRect.width, intRect.height);
|
||||
|
||||
// Sometimes the invalid region is larger than we want to draw.
|
||||
nsIntRegion invalidRegionSafe;
|
||||
invalidRegionSafe.And(aInvalidRegion, intRect);
|
||||
if (mDidExternalComposition) {
|
||||
// We do not know rendered region during external composition, just redraw
|
||||
// whole widget.
|
||||
invalidRegionSafe = intRect;
|
||||
mDidExternalComposition = false;
|
||||
} else {
|
||||
// Sometimes the invalid region is larger than we want to draw.
|
||||
invalidRegionSafe.And(aInvalidRegion, intRect);
|
||||
}
|
||||
|
||||
IntRect invalidRect = invalidRegionSafe.GetBounds();
|
||||
mInvalidRect = IntRect(invalidRect.x, invalidRect.y, invalidRect.width, invalidRect.height);
|
||||
@ -610,5 +618,16 @@ BasicCompositor::EndFrame()
|
||||
mRenderTarget = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
BasicCompositor::EndFrameForExternalComposition(const gfx::Matrix& aTransform)
|
||||
{
|
||||
MOZ_ASSERT(!mTarget);
|
||||
MOZ_ASSERT(!mDrawTarget);
|
||||
MOZ_ASSERT(!mRenderTarget);
|
||||
|
||||
mDidExternalComposition = true;
|
||||
}
|
||||
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
@ -90,12 +90,7 @@ public:
|
||||
gfx::Rect *aClipRectOut = nullptr,
|
||||
gfx::Rect *aRenderBoundsOut = nullptr) override;
|
||||
virtual void EndFrame() override;
|
||||
virtual void EndFrameForExternalComposition(const gfx::Matrix& aTransform) override
|
||||
{
|
||||
MOZ_ASSERT(!mTarget);
|
||||
MOZ_ASSERT(!mDrawTarget);
|
||||
MOZ_ASSERT(!mRenderTarget);
|
||||
}
|
||||
virtual void EndFrameForExternalComposition(const gfx::Matrix& aTransform) override;
|
||||
|
||||
virtual bool SupportsPartialTextureUpdate() override { return true; }
|
||||
virtual bool CanUseCanvasLayerForSize(const gfx::IntSize &aSize) override { return true; }
|
||||
@ -134,6 +129,7 @@ private:
|
||||
|
||||
gfx::IntRect mInvalidRect;
|
||||
nsIntRegion mInvalidRegion;
|
||||
bool mDidExternalComposition;
|
||||
|
||||
uint32_t mMaxTextureSize;
|
||||
};
|
||||
|
@ -431,23 +431,21 @@ ShadowLayerForwarder::RemoveTextureFromCompositableAsync(AsyncTransactionTracker
|
||||
CompositableClient* aCompositable,
|
||||
TextureClient* aTexture)
|
||||
{
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
mPendingAsyncMessages.push_back(OpRemoveTextureAsync(CompositableClient::GetTrackersHolderId(aCompositable->GetIPDLActor()),
|
||||
aAsyncTransactionTracker->GetId(),
|
||||
nullptr, aCompositable->GetIPDLActor(),
|
||||
nullptr, aTexture->GetIPDLActor()));
|
||||
#else
|
||||
if (mTxn->Opened() && !aCompositable->IsDestroyed()) {
|
||||
mTxn->AddEdit(OpRemoveTextureAsync(CompositableClient::GetTrackersHolderId(aCompositable->GetIPDLActor()),
|
||||
aAsyncTransactionTracker->GetId(),
|
||||
nullptr, aCompositable->GetIPDLActor(),
|
||||
nullptr, aTexture->GetIPDLActor()));
|
||||
} else {
|
||||
// If the function is called outside of transaction,
|
||||
// OpRemoveTextureAsync message is stored as pending message.
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
mPendingAsyncMessages.push_back(OpRemoveTextureAsync(CompositableClient::GetTrackersHolderId(aCompositable->GetIPDLActor()),
|
||||
aAsyncTransactionTracker->GetId(),
|
||||
nullptr, aCompositable->GetIPDLActor(),
|
||||
nullptr, aTexture->GetIPDLActor()));
|
||||
#else
|
||||
NS_RUNTIMEABORT("not reached");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
CompositableClient::HoldUntilComplete(aCompositable->GetIPDLActor(),
|
||||
aAsyncTransactionTracker);
|
||||
}
|
||||
|
@ -1547,26 +1547,24 @@ gfxUtils::CopyAsDataURI(DrawTarget* aDT)
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
/* static */ UniquePtr<uint8_t[]>
|
||||
gfxUtils::GetImageBuffer(gfx::DataSourceSurface* aSurface,
|
||||
bool aIsAlphaPremultiplied,
|
||||
uint8_t** outImageBuffer,
|
||||
int32_t* outFormat)
|
||||
{
|
||||
*outImageBuffer = nullptr;
|
||||
*outFormat = 0;
|
||||
|
||||
DataSourceSurface::MappedSurface map;
|
||||
if (!aSurface->Map(DataSourceSurface::MapType::READ, &map))
|
||||
return;
|
||||
return nullptr;
|
||||
|
||||
uint32_t bufferSize = aSurface->GetSize().width * aSurface->GetSize().height * 4;
|
||||
uint8_t* imageBuffer = new (fallible) uint8_t[bufferSize];
|
||||
UniquePtr<uint8_t[]> imageBuffer(new (fallible) uint8_t[bufferSize]);
|
||||
if (!imageBuffer) {
|
||||
aSurface->Unmap();
|
||||
return;
|
||||
return nullptr;
|
||||
}
|
||||
memcpy(imageBuffer, map.mData, bufferSize);
|
||||
memcpy(imageBuffer.get(), map.mData, bufferSize);
|
||||
|
||||
aSurface->Unmap();
|
||||
|
||||
@ -1577,12 +1575,12 @@ gfxUtils::GetImageBuffer(gfx::DataSourceSurface* aSurface,
|
||||
// Yes, it is THAT silly.
|
||||
// Except for different lossy conversions by color,
|
||||
// we could probably just change the label, and not change the data.
|
||||
gfxUtils::ConvertBGRAtoRGBA(imageBuffer, bufferSize);
|
||||
gfxUtils::ConvertBGRAtoRGBA(imageBuffer.get(), bufferSize);
|
||||
format = imgIEncoder::INPUT_FORMAT_RGBA;
|
||||
}
|
||||
|
||||
*outImageBuffer = imageBuffer;
|
||||
*outFormat = format;
|
||||
return imageBuffer;
|
||||
}
|
||||
|
||||
/* static */ nsresult
|
||||
@ -1598,15 +1596,14 @@ gfxUtils::GetInputStream(gfx::DataSourceSurface* aSurface,
|
||||
if (!encoder)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsAutoArrayPtr<uint8_t> imageBuffer;
|
||||
int32_t format = 0;
|
||||
GetImageBuffer(aSurface, aIsAlphaPremultiplied, getter_Transfers(imageBuffer), &format);
|
||||
UniquePtr<uint8_t[]> imageBuffer = GetImageBuffer(aSurface, aIsAlphaPremultiplied, &format);
|
||||
if (!imageBuffer)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return dom::ImageEncoder::GetInputStream(aSurface->GetSize().width,
|
||||
aSurface->GetSize().height,
|
||||
imageBuffer, format,
|
||||
imageBuffer.get(), format,
|
||||
encoder, aEncoderOptions, outStream);
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "imgIContainer.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsColor.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "mozilla/gfx/Rect.h"
|
||||
@ -282,10 +283,9 @@ public:
|
||||
static nsCString GetAsDataURI(DrawTarget* aDT);
|
||||
static nsCString GetAsLZ4Base64Str(DataSourceSurface* aSourceSurface);
|
||||
|
||||
static void GetImageBuffer(DataSourceSurface* aSurface,
|
||||
bool aIsAlphaPremultiplied,
|
||||
uint8_t** outImageBuffer,
|
||||
int32_t* outFormat);
|
||||
static mozilla::UniquePtr<uint8_t[]> GetImageBuffer(DataSourceSurface* aSurface,
|
||||
bool aIsAlphaPremultiplied,
|
||||
int32_t* outFormat);
|
||||
|
||||
static nsresult GetInputStream(DataSourceSurface* aSurface,
|
||||
bool aIsAlphaPremultiplied,
|
||||
|
@ -219,12 +219,17 @@ elif [[ "$VARIANT" = arm64* ]]; then
|
||||
fi
|
||||
|
||||
$COMMAND_PREFIX $MAKE check || exit 1
|
||||
|
||||
RESULT=0
|
||||
|
||||
if $RUN_JITTEST; then
|
||||
$COMMAND_PREFIX $MAKE check-jit-test || exit 1
|
||||
$COMMAND_PREFIX $MAKE check-jit-test || RESULT=$?
|
||||
fi
|
||||
if $RUN_JSAPITESTS; then
|
||||
$COMMAND_PREFIX $OBJDIR/dist/bin/jsapi-tests || exit 1
|
||||
$COMMAND_PREFIX $OBJDIR/dist/bin/jsapi-tests || RESULT=$?
|
||||
fi
|
||||
if $RUN_JSTESTS; then
|
||||
$COMMAND_PREFIX $MAKE check-jstests || exit 1
|
||||
$COMMAND_PREFIX $MAKE check-jstests || RESULT=$?
|
||||
fi
|
||||
|
||||
exit $RESULT
|
||||
|
@ -3145,16 +3145,15 @@ Parser<ParseHandler>::maybeParseDirective(Node list, Node pn, bool* cont)
|
||||
// Request that this function be reparsed as strict.
|
||||
pc->newDirectives->setStrict();
|
||||
return false;
|
||||
} else {
|
||||
// We don't reparse global scopes, so we keep track of the
|
||||
// one possible strict violation that could occur in the
|
||||
// directive prologue -- octal escapes -- and complain now.
|
||||
if (tokenStream.sawOctalEscape()) {
|
||||
report(ParseError, false, null(), JSMSG_DEPRECATED_OCTAL);
|
||||
return false;
|
||||
}
|
||||
pc->sc->strictScript = true;
|
||||
}
|
||||
// We don't reparse global scopes, so we keep track of the one
|
||||
// possible strict violation that could occur in the directive
|
||||
// prologue -- octal escapes -- and complain now.
|
||||
if (tokenStream.sawOctalEscape()) {
|
||||
report(ParseError, false, null(), JSMSG_DEPRECATED_OCTAL);
|
||||
return false;
|
||||
}
|
||||
pc->sc->strictScript = true;
|
||||
}
|
||||
} else if (directive == context->names().useAsm) {
|
||||
if (pc->sc->isFunctionBox())
|
||||
|
24
js/src/jit-test/tests/basic/unboxed-property-enumeration.js
Normal file
24
js/src/jit-test/tests/basic/unboxed-property-enumeration.js
Normal file
@ -0,0 +1,24 @@
|
||||
function O() {
|
||||
this.x = 1;
|
||||
this.y = 2;
|
||||
}
|
||||
function testUnboxed() {
|
||||
var arr = [];
|
||||
for (var i=0; i<100; i++)
|
||||
arr.push(new O);
|
||||
|
||||
var o = arr[arr.length-1];
|
||||
o[0] = 0;
|
||||
o[2] = 2;
|
||||
var sym = Symbol();
|
||||
o[sym] = 1;
|
||||
o.z = 3;
|
||||
Object.defineProperty(o, '3', {value:1,enumerable:false,configurable:false,writable:false});
|
||||
o[4] = 4;
|
||||
|
||||
var props = Reflect.ownKeys(o);
|
||||
assertEq(props[props.length-1], sym);
|
||||
|
||||
assertEq(Object.getOwnPropertyNames(o).join(""), "0234xyz");
|
||||
}
|
||||
testUnboxed();
|
10
js/src/jit-test/tests/gc/bug-1215678.js
Normal file
10
js/src/jit-test/tests/gc/bug-1215678.js
Normal file
@ -0,0 +1,10 @@
|
||||
// |jit-test| error: ReferenceError
|
||||
if (!('oomTest' in this))
|
||||
a;
|
||||
|
||||
enableShellObjectMetadataCallback()
|
||||
oomTest(() => {
|
||||
newGlobal()
|
||||
})
|
||||
gczeal(9, 1);
|
||||
a;
|
12
js/src/jit-test/tests/ion/bug1216157.js
Normal file
12
js/src/jit-test/tests/ion/bug1216157.js
Normal file
@ -0,0 +1,12 @@
|
||||
if (!('oomAfterAllocations' in this))
|
||||
quit();
|
||||
gcslice(0); // Start IGC, but don't mark anything.
|
||||
function f(str) {
|
||||
for (var i = 0; i < 10; i++) {
|
||||
arr = /foo(ba(r))?/.exec(str);
|
||||
var x = arr[oomAfterAllocations(100)] + " " + arr[1] + " " + 1899;
|
||||
}
|
||||
}
|
||||
try {
|
||||
f("foo");
|
||||
} catch(e) {}
|
25
js/src/jit-test/tests/ion/bug1218065.js
Normal file
25
js/src/jit-test/tests/ion/bug1218065.js
Normal file
@ -0,0 +1,25 @@
|
||||
function f() {
|
||||
const b = 0;
|
||||
switch (1) {
|
||||
case b = 0:
|
||||
}
|
||||
}
|
||||
var err;
|
||||
try {
|
||||
f();
|
||||
} catch(e) {
|
||||
err = e;
|
||||
}
|
||||
assertEq(err.name, "TypeError");
|
||||
|
||||
function g() {
|
||||
const z = 0;
|
||||
while (z = 1) {}
|
||||
}
|
||||
err = null;
|
||||
try {
|
||||
g();
|
||||
} catch(e) {
|
||||
err = e;
|
||||
}
|
||||
assertEq(err.name, "TypeError");
|
@ -1441,6 +1441,8 @@ JitCompartment::generateRegExpExecStub(JSContext* cx)
|
||||
Linker linker(masm);
|
||||
AutoFlushICache afc("RegExpExecStub");
|
||||
JitCode* code = linker.newCode<CanGC>(cx, OTHER_CODE);
|
||||
if (!code)
|
||||
return nullptr;
|
||||
|
||||
#ifdef JS_ION_PERF
|
||||
writePerfSpewerJitCodeProfile(code, "RegExpExecStub");
|
||||
@ -1572,6 +1574,8 @@ JitCompartment::generateRegExpTestStub(JSContext* cx)
|
||||
Linker linker(masm);
|
||||
AutoFlushICache afc("RegExpTestStub");
|
||||
JitCode* code = linker.newCode<CanGC>(cx, OTHER_CODE);
|
||||
if (!code)
|
||||
return nullptr;
|
||||
|
||||
#ifdef JS_ION_PERF
|
||||
writePerfSpewerJitCodeProfile(code, "RegExpTestStub");
|
||||
|
@ -1586,10 +1586,6 @@ IonBuilder::snoopControlFlow(JSOp op)
|
||||
case JSOP_THROW:
|
||||
return processThrow();
|
||||
|
||||
case JSOP_THROWSETCONST:
|
||||
case JSOP_THROWSETALIASEDCONST:
|
||||
return processThrowSetConst();
|
||||
|
||||
case JSOP_GOTO:
|
||||
{
|
||||
jssrcnote* sn = info().getNote(gsn, pc);
|
||||
@ -1778,6 +1774,10 @@ IonBuilder::inspectOpcode(JSOp op)
|
||||
current->setLocal(GET_LOCALNO(pc));
|
||||
return true;
|
||||
|
||||
case JSOP_THROWSETCONST:
|
||||
case JSOP_THROWSETALIASEDCONST:
|
||||
return jsop_throwsetconst();
|
||||
|
||||
case JSOP_CHECKLEXICAL:
|
||||
return jsop_checklexical();
|
||||
|
||||
@ -12740,20 +12740,13 @@ IonBuilder::jsop_deffun(uint32_t index)
|
||||
return resumeAfter(deffun);
|
||||
}
|
||||
|
||||
IonBuilder::ControlStatus
|
||||
IonBuilder::processThrowSetConst()
|
||||
bool
|
||||
IonBuilder::jsop_throwsetconst()
|
||||
{
|
||||
current->peek(-1)->setImplicitlyUsedUnchecked();
|
||||
MInstruction* lexicalError = MThrowRuntimeLexicalError::New(alloc(), JSMSG_BAD_CONST_ASSIGN);
|
||||
current->add(lexicalError);
|
||||
if (!resumeAfter(lexicalError))
|
||||
return ControlStatus_Error;
|
||||
|
||||
current->end(MUnreachable::New(alloc()));
|
||||
|
||||
// Make sure no one tries to use this block now.
|
||||
setCurrent(nullptr);
|
||||
return processControlEnd();
|
||||
return resumeAfter(lexicalError);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -263,7 +263,6 @@ class IonBuilder
|
||||
ControlStatus processTryEnd(CFGState& state);
|
||||
ControlStatus processReturn(JSOp op);
|
||||
ControlStatus processThrow();
|
||||
ControlStatus processThrowSetConst();
|
||||
ControlStatus processContinue(JSOp op);
|
||||
ControlStatus processBreak(JSOp op, jssrcnote* sn);
|
||||
ControlStatus maybeLoop(JSOp op, jssrcnote* sn);
|
||||
@ -659,6 +658,7 @@ class IonBuilder
|
||||
bool jsop_deflexical(uint32_t index);
|
||||
bool jsop_deffun(uint32_t index);
|
||||
bool jsop_notearg();
|
||||
bool jsop_throwsetconst();
|
||||
bool jsop_checklexical();
|
||||
bool jsop_checkaliasedlet(ScopeCoordinate sc);
|
||||
bool jsop_funcall(uint32_t argc);
|
||||
|
@ -420,12 +420,14 @@ class MacroAssembler : public MacroAssemblerSpecific
|
||||
// ===============================================================
|
||||
// Stack manipulation functions.
|
||||
|
||||
void PushRegsInMask(LiveRegisterSet set) PER_SHARED_ARCH;
|
||||
void PushRegsInMask(LiveRegisterSet set)
|
||||
DEFINED_ON(arm, arm64, mips32, x86_shared);
|
||||
void PushRegsInMask(LiveGeneralRegisterSet set);
|
||||
|
||||
void PopRegsInMask(LiveRegisterSet set);
|
||||
void PopRegsInMask(LiveGeneralRegisterSet set);
|
||||
void PopRegsInMaskIgnore(LiveRegisterSet set, LiveRegisterSet ignore) PER_SHARED_ARCH;
|
||||
void PopRegsInMaskIgnore(LiveRegisterSet set, LiveRegisterSet ignore)
|
||||
DEFINED_ON(arm, arm64, mips32, x86_shared);
|
||||
|
||||
void Push(const Operand op) DEFINED_ON(x86_shared);
|
||||
void Push(Register reg) PER_SHARED_ARCH;
|
||||
|
@ -793,63 +793,6 @@ MacroAssemblerMIPSShared::asMasm() const
|
||||
// ===============================================================
|
||||
// Stack manipulation functions.
|
||||
|
||||
void
|
||||
MacroAssembler::PushRegsInMask(LiveRegisterSet set)
|
||||
{
|
||||
int32_t diffF = set.fpus().getPushSizeInBytes();
|
||||
int32_t diffG = set.gprs().size() * sizeof(intptr_t);
|
||||
|
||||
reserveStack(diffG);
|
||||
for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) {
|
||||
diffG -= sizeof(intptr_t);
|
||||
storePtr(*iter, Address(StackPointer, diffG));
|
||||
}
|
||||
MOZ_ASSERT(diffG == 0);
|
||||
|
||||
// Double values have to be aligned. We reserve extra space so that we can
|
||||
// start writing from the first aligned location.
|
||||
// We reserve a whole extra double so that the buffer has even size.
|
||||
ma_and(SecondScratchReg, sp, Imm32(~(ABIStackAlignment - 1)));
|
||||
reserveStack(diffF + sizeof(double));
|
||||
|
||||
for (FloatRegisterForwardIterator iter(set.fpus().reduceSetForPush()); iter.more(); iter++) {
|
||||
if ((*iter).code() % 2 == 0)
|
||||
as_sd(*iter, SecondScratchReg, -diffF);
|
||||
diffF -= sizeof(double);
|
||||
}
|
||||
MOZ_ASSERT(diffF == 0);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::PopRegsInMaskIgnore(LiveRegisterSet set, LiveRegisterSet ignore)
|
||||
{
|
||||
int32_t diffG = set.gprs().size() * sizeof(intptr_t);
|
||||
int32_t diffF = set.fpus().getPushSizeInBytes();
|
||||
const int32_t reservedG = diffG;
|
||||
const int32_t reservedF = diffF;
|
||||
|
||||
// Read the buffer form the first aligned location.
|
||||
ma_addu(SecondScratchReg, sp, Imm32(reservedF + sizeof(double)));
|
||||
ma_and(SecondScratchReg, SecondScratchReg, Imm32(~(ABIStackAlignment - 1)));
|
||||
|
||||
for (FloatRegisterForwardIterator iter(set.fpus().reduceSetForPush()); iter.more(); iter++) {
|
||||
if (!ignore.has(*iter) && ((*iter).code() % 2 == 0))
|
||||
// Use assembly l.d because we have alligned the stack.
|
||||
as_ld(*iter, SecondScratchReg, -diffF);
|
||||
diffF -= sizeof(double);
|
||||
}
|
||||
freeStack(reservedF + sizeof(double));
|
||||
MOZ_ASSERT(diffF == 0);
|
||||
|
||||
for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) {
|
||||
diffG -= sizeof(intptr_t);
|
||||
if (!ignore.has(*iter))
|
||||
loadPtr(Address(StackPointer, diffG), *iter);
|
||||
}
|
||||
freeStack(reservedG);
|
||||
MOZ_ASSERT(diffG == 0);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::Push(Register reg)
|
||||
{
|
||||
|
@ -2497,6 +2497,63 @@ MacroAssemblerMIPSCompat::profilerExitFrame()
|
||||
// ===============================================================
|
||||
// Stack manipulation functions.
|
||||
|
||||
void
|
||||
MacroAssembler::PushRegsInMask(LiveRegisterSet set)
|
||||
{
|
||||
int32_t diffF = set.fpus().getPushSizeInBytes();
|
||||
int32_t diffG = set.gprs().size() * sizeof(intptr_t);
|
||||
|
||||
reserveStack(diffG);
|
||||
for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) {
|
||||
diffG -= sizeof(intptr_t);
|
||||
storePtr(*iter, Address(StackPointer, diffG));
|
||||
}
|
||||
MOZ_ASSERT(diffG == 0);
|
||||
|
||||
// Double values have to be aligned. We reserve extra space so that we can
|
||||
// start writing from the first aligned location.
|
||||
// We reserve a whole extra double so that the buffer has even size.
|
||||
ma_and(SecondScratchReg, sp, Imm32(~(ABIStackAlignment - 1)));
|
||||
reserveStack(diffF + sizeof(double));
|
||||
|
||||
for (FloatRegisterForwardIterator iter(set.fpus().reduceSetForPush()); iter.more(); iter++) {
|
||||
if ((*iter).code() % 2 == 0)
|
||||
as_sd(*iter, SecondScratchReg, -diffF);
|
||||
diffF -= sizeof(double);
|
||||
}
|
||||
MOZ_ASSERT(diffF == 0);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::PopRegsInMaskIgnore(LiveRegisterSet set, LiveRegisterSet ignore)
|
||||
{
|
||||
int32_t diffG = set.gprs().size() * sizeof(intptr_t);
|
||||
int32_t diffF = set.fpus().getPushSizeInBytes();
|
||||
const int32_t reservedG = diffG;
|
||||
const int32_t reservedF = diffF;
|
||||
|
||||
// Read the buffer form the first aligned location.
|
||||
ma_addu(SecondScratchReg, sp, Imm32(reservedF + sizeof(double)));
|
||||
ma_and(SecondScratchReg, SecondScratchReg, Imm32(~(ABIStackAlignment - 1)));
|
||||
|
||||
for (FloatRegisterForwardIterator iter(set.fpus().reduceSetForPush()); iter.more(); iter++) {
|
||||
if (!ignore.has(*iter) && ((*iter).code() % 2 == 0))
|
||||
// Use assembly l.d because we have alligned the stack.
|
||||
as_ld(*iter, SecondScratchReg, -diffF);
|
||||
diffF -= sizeof(double);
|
||||
}
|
||||
freeStack(reservedF + sizeof(double));
|
||||
MOZ_ASSERT(diffF == 0);
|
||||
|
||||
for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) {
|
||||
diffG -= sizeof(intptr_t);
|
||||
if (!ignore.has(*iter))
|
||||
loadPtr(Address(StackPointer, diffG), *iter);
|
||||
}
|
||||
freeStack(reservedG);
|
||||
MOZ_ASSERT(diffG == 0);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::reserveStack(uint32_t amount)
|
||||
{
|
||||
|
@ -554,10 +554,8 @@ JitRuntime::generateArgumentsRectifier(JSContext* cx, void** returnAddrOut)
|
||||
AutoFlushICache afc("ArgumentsRectifier");
|
||||
JitCode* code = linker.newCode<NoGC>(cx, OTHER_CODE);
|
||||
|
||||
CodeOffsetLabel returnLabel(returnOffset);
|
||||
returnLabel.fixup(&masm);
|
||||
if (returnAddrOut)
|
||||
*returnAddrOut = (void*) (code->raw() + returnLabel.offset());
|
||||
*returnAddrOut = (void*) (code->raw() + returnOffset);
|
||||
|
||||
#ifdef JS_ION_PERF
|
||||
writePerfSpewerJitCodeProfile(code, "ArgumentsRectifier");
|
||||
@ -1197,7 +1195,7 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
|
||||
{
|
||||
// scratch2 := StackPointer + Descriptor.size*1 + JitFrameLayout::Size();
|
||||
masm.as_daddu(scratch2, StackPointer, scratch1);
|
||||
masm.add32(Imm32(JitFrameLayout::Size()), scratch2);
|
||||
masm.addPtr(Imm32(JitFrameLayout::Size()), scratch2);
|
||||
masm.loadPtr(Address(scratch2, RectifierFrameLayout::offsetOfDescriptor()), scratch3);
|
||||
masm.ma_dsrl(scratch1, scratch3, Imm32(FRAMESIZE_SHIFT));
|
||||
masm.and32(Imm32((1 << FRAMETYPE_BITS) - 1), scratch3);
|
||||
@ -1218,7 +1216,7 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
|
||||
|
||||
// scratch3 := RectFrame + Rect-Descriptor.Size + RectifierFrameLayout::Size()
|
||||
masm.as_daddu(scratch3, scratch2, scratch1);
|
||||
masm.add32(Imm32(RectifierFrameLayout::Size()), scratch3);
|
||||
masm.addPtr(Imm32(RectifierFrameLayout::Size()), scratch3);
|
||||
masm.storePtr(scratch3, lastProfilingFrame);
|
||||
masm.ret();
|
||||
|
||||
|
@ -447,7 +447,6 @@ JSCompartment::wrap(JSContext* cx, MutableHandleObject obj, HandleObject existin
|
||||
if (obj->compartment() == this)
|
||||
return true;
|
||||
|
||||
|
||||
// If we already have a wrapper for this value, use it.
|
||||
RootedValue key(cx, ObjectValue(*obj));
|
||||
if (WrapperMap::Ptr p = crossCompartmentWrappers.lookup(CrossCompartmentKey(key))) {
|
||||
@ -468,15 +467,27 @@ JSCompartment::wrap(JSContext* cx, MutableHandleObject obj, HandleObject existin
|
||||
}
|
||||
}
|
||||
|
||||
obj.set(cb->wrap(cx, existing, obj));
|
||||
if (!obj)
|
||||
RootedObject wrapper(cx, cb->wrap(cx, existing, obj));
|
||||
if (!wrapper)
|
||||
return false;
|
||||
|
||||
// We maintain the invariant that the key in the cross-compartment wrapper
|
||||
// map is always directly wrapped by the value.
|
||||
MOZ_ASSERT(Wrapper::wrappedObject(obj) == &key.get().toObject());
|
||||
MOZ_ASSERT(Wrapper::wrappedObject(wrapper) == &key.get().toObject());
|
||||
|
||||
return putWrapper(cx, CrossCompartmentKey(key), ObjectValue(*obj));
|
||||
if (!putWrapper(cx, CrossCompartmentKey(key), ObjectValue(*wrapper))) {
|
||||
// Enforce the invariant that all cross-compartment wrapper object are
|
||||
// in the map by nuking the wrapper if we couldn't add it.
|
||||
// Unfortunately it's possible for the wrapper to still be marked if we
|
||||
// took this path, for example if the object metadata callback stashes a
|
||||
// reference to it.
|
||||
if (wrapper->is<CrossCompartmentWrapperObject>())
|
||||
NukeCrossCompartmentWrapper(cx, wrapper);
|
||||
return false;
|
||||
}
|
||||
|
||||
obj.set(wrapper);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -135,6 +135,33 @@ Enumerate(JSContext* cx, HandleObject pobj, jsid id,
|
||||
return props->append(id);
|
||||
}
|
||||
|
||||
static bool
|
||||
EnumerateExtraProperties(JSContext* cx, HandleObject obj, unsigned flags, Maybe<IdSet>& ht,
|
||||
AutoIdVector* props)
|
||||
{
|
||||
MOZ_ASSERT(obj->getOps()->enumerate);
|
||||
|
||||
AutoIdVector properties(cx);
|
||||
bool enumerableOnly = !(flags & JSITER_HIDDEN);
|
||||
if (!obj->getOps()->enumerate(cx, obj, properties, enumerableOnly))
|
||||
return false;
|
||||
|
||||
RootedId id(cx);
|
||||
for (size_t n = 0; n < properties.length(); n++) {
|
||||
id = properties[n];
|
||||
|
||||
// The enumerate hook does not indicate whether the properties
|
||||
// it returns are enumerable or not. Since we already passed
|
||||
// `enumerableOnly` to the hook to filter out non-enumerable
|
||||
// properties, it doesn't really matter what we pass here.
|
||||
bool enumerable = true;
|
||||
if (!Enumerate(cx, obj, id, enumerable, flags, ht, props))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
SortComparatorIntegerIds(jsid a, jsid b, bool* lessOrEqualp)
|
||||
{
|
||||
@ -147,7 +174,7 @@ SortComparatorIntegerIds(jsid a, jsid b, bool* lessOrEqualp)
|
||||
|
||||
static bool
|
||||
EnumerateNativeProperties(JSContext* cx, HandleNativeObject pobj, unsigned flags, Maybe<IdSet>& ht,
|
||||
AutoIdVector* props)
|
||||
AutoIdVector* props, Handle<UnboxedPlainObject*> unboxed = nullptr)
|
||||
{
|
||||
bool enumerateSymbols;
|
||||
if (flags & JSITER_SYMBOLSONLY) {
|
||||
@ -207,6 +234,16 @@ EnumerateNativeProperties(JSContext* cx, HandleNativeObject pobj, unsigned flags
|
||||
return false;
|
||||
}
|
||||
|
||||
if (unboxed) {
|
||||
// If |unboxed| is set then |pobj| is the expando for an unboxed
|
||||
// plain object we are enumerating. Add the unboxed properties
|
||||
// themselves here since they are all property names that were
|
||||
// given to the object before any of the expando's properties.
|
||||
MOZ_ASSERT(pobj->is<UnboxedExpandoObject>());
|
||||
if (!EnumerateExtraProperties(cx, unboxed, flags, ht, props))
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t initialLength = props->length();
|
||||
|
||||
/* Collect all unique property names from this object's shape. */
|
||||
@ -331,28 +368,23 @@ Snapshot(JSContext* cx, HandleObject pobj_, unsigned flags, AutoIdVector* props)
|
||||
RootedObject pobj(cx, pobj_);
|
||||
|
||||
do {
|
||||
if (JSNewEnumerateOp enumerate = pobj->getOps()->enumerate) {
|
||||
AutoIdVector properties(cx);
|
||||
bool enumerableOnly = !(flags & JSITER_HIDDEN);
|
||||
if (!enumerate(cx, pobj, properties, enumerableOnly))
|
||||
return false;
|
||||
|
||||
RootedId id(cx);
|
||||
for (size_t n = 0; n < properties.length(); n++) {
|
||||
id = properties[n];
|
||||
|
||||
// The enumerate hook does not indicate whether the properties
|
||||
// it returns are enumerable or not. Since we already passed
|
||||
// `enumerableOnly` to the hook to filter out non-enumerable
|
||||
// properties, it doesn't really matter what we pass here.
|
||||
bool enumerable = true;
|
||||
if (!Enumerate(cx, pobj, id, enumerable, flags, ht, props))
|
||||
if (pobj->getOps()->enumerate) {
|
||||
if (pobj->is<UnboxedPlainObject>() && pobj->as<UnboxedPlainObject>().maybeExpando()) {
|
||||
// Special case unboxed objects with an expando object.
|
||||
RootedNativeObject expando(cx, pobj->as<UnboxedPlainObject>().maybeExpando());
|
||||
if (!EnumerateNativeProperties(cx, expando, flags, ht, props,
|
||||
pobj.as<UnboxedPlainObject>()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pobj->isNative()) {
|
||||
if (!EnumerateNativeProperties(cx, pobj.as<NativeObject>(), flags, ht, props))
|
||||
}
|
||||
} else {
|
||||
if (!EnumerateExtraProperties(cx, pobj, flags, ht, props))
|
||||
return false;
|
||||
|
||||
if (pobj->isNative()) {
|
||||
if (!EnumerateNativeProperties(cx, pobj.as<NativeObject>(), flags, ht, props))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (pobj->isNative()) {
|
||||
// Give the object a chance to resolve all lazy properties
|
||||
|
@ -422,8 +422,6 @@ BytecodeFallsThrough(JSOp op)
|
||||
case JSOP_RETRVAL:
|
||||
case JSOP_FINALYIELDRVAL:
|
||||
case JSOP_THROW:
|
||||
case JSOP_THROWSETCONST:
|
||||
case JSOP_THROWSETALIASEDCONST:
|
||||
case JSOP_TABLESWITCH:
|
||||
return false;
|
||||
case JSOP_GOSUB:
|
||||
|
@ -637,7 +637,7 @@ ProxyObject::trace(JSTracer* trc, JSObject* obj)
|
||||
|
||||
#ifdef DEBUG
|
||||
if (trc->runtime()->gc.isStrictProxyCheckingEnabled() && proxy->is<WrapperObject>()) {
|
||||
JSObject* referent = MaybeForwarded(&proxy->private_().toObject());
|
||||
JSObject* referent = MaybeForwarded(proxy->target());
|
||||
if (referent->compartment() != proxy->compartment()) {
|
||||
/*
|
||||
* Assert that this proxy is tracked in the wrapper map. We maintain
|
||||
|
@ -8022,7 +8022,7 @@ DebuggerEnv_getCallee(JSContext* cx, unsigned argc, Value* vp)
|
||||
return true;
|
||||
|
||||
JSObject& scope = env->as<DebugScopeObject>().scope();
|
||||
if (!scope.is<CallObject>() || scope.is<ModuleEnvironmentObject>())
|
||||
if (!scope.is<CallObject>())
|
||||
return true;
|
||||
|
||||
CallObject& callobj = scope.as<CallObject>();
|
||||
|
@ -27,7 +27,7 @@ NearestEnclosingExtensibleLexicalScope(JSObject* scope)
|
||||
inline void
|
||||
ScopeObject::setAliasedVar(JSContext* cx, ScopeCoordinate sc, PropertyName* name, const Value& v)
|
||||
{
|
||||
MOZ_ASSERT(is<CallObject>() || is<ClonedBlockObject>());
|
||||
MOZ_ASSERT(is<LexicalScopeBase>() || is<ClonedBlockObject>());
|
||||
JS_STATIC_ASSERT(CallObject::RESERVED_SLOTS == BlockObject::RESERVED_SLOTS);
|
||||
|
||||
// name may be null if we don't need to track side effects on the object.
|
||||
@ -48,7 +48,8 @@ ScopeObject::setAliasedVar(JSContext* cx, ScopeCoordinate sc, PropertyName* name
|
||||
}
|
||||
|
||||
inline void
|
||||
CallObject::setAliasedVar(JSContext* cx, AliasedFormalIter fi, PropertyName* name, const Value& v)
|
||||
LexicalScopeBase::setAliasedVar(JSContext* cx, AliasedFormalIter fi, PropertyName* name,
|
||||
const Value& v)
|
||||
{
|
||||
MOZ_ASSERT(name == fi->name());
|
||||
setSlot(fi.scopeSlot(), v);
|
||||
@ -57,7 +58,8 @@ CallObject::setAliasedVar(JSContext* cx, AliasedFormalIter fi, PropertyName* nam
|
||||
}
|
||||
|
||||
inline void
|
||||
CallObject::setAliasedVarFromArguments(JSContext* cx, const Value& argsValue, jsid id, const Value& v)
|
||||
LexicalScopeBase::setAliasedVarFromArguments(JSContext* cx, const Value& argsValue, jsid id,
|
||||
const Value& v)
|
||||
{
|
||||
setSlot(ArgumentsObject::SlotFromMagicScopeSlotValue(argsValue), v);
|
||||
if (isSingleton())
|
||||
@ -65,7 +67,7 @@ CallObject::setAliasedVarFromArguments(JSContext* cx, const Value& argsValue, js
|
||||
}
|
||||
|
||||
inline void
|
||||
CallObject::initRemainingSlotsToUninitializedLexicals(uint32_t begin)
|
||||
LexicalScopeBase::initRemainingSlotsToUninitializedLexicals(uint32_t begin)
|
||||
{
|
||||
uint32_t end = slotSpan();
|
||||
for (uint32_t slot = begin; slot < end; slot++)
|
||||
@ -73,7 +75,7 @@ CallObject::initRemainingSlotsToUninitializedLexicals(uint32_t begin)
|
||||
}
|
||||
|
||||
inline void
|
||||
CallObject::initAliasedLexicalsToThrowOnTouch(JSScript* script)
|
||||
LexicalScopeBase::initAliasedLexicalsToThrowOnTouch(JSScript* script)
|
||||
{
|
||||
initRemainingSlotsToUninitializedLexicals(script->bindings.aliasedBodyLevelLexicalBegin());
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ js::ScopeCoordinateFunctionScript(JSScript* script, jsbytecode* pc)
|
||||
void
|
||||
ScopeObject::setEnclosingScope(HandleObject obj)
|
||||
{
|
||||
MOZ_ASSERT_IF(obj->is<CallObject>() || obj->is<DeclEnvObject>() || obj->is<BlockObject>(),
|
||||
MOZ_ASSERT_IF(obj->is<LexicalScopeBase>() || obj->is<DeclEnvObject>() || obj->is<BlockObject>(),
|
||||
obj->isDelegate());
|
||||
setFixedSlot(SCOPE_CHAIN_SLOT, ObjectValue(*obj));
|
||||
}
|
||||
@ -1755,9 +1755,7 @@ class DebugScopeProxy : public BaseProxyHandler
|
||||
|
||||
static bool isFunctionScope(const JSObject& scope)
|
||||
{
|
||||
return scope.is<CallObject>() &&
|
||||
!scope.is<ModuleEnvironmentObject>() &&
|
||||
!scope.as<CallObject>().isForEval();
|
||||
return scope.is<CallObject>() && !scope.as<CallObject>().isForEval();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2169,7 +2167,7 @@ bool
|
||||
DebugScopeObject::isForDeclarative() const
|
||||
{
|
||||
ScopeObject& s = scope();
|
||||
return s.is<CallObject>() || s.is<BlockObject>() || s.is<DeclEnvObject>();
|
||||
return s.is<LexicalScopeBase>() || s.is<BlockObject>() || s.is<DeclEnvObject>();
|
||||
}
|
||||
|
||||
bool
|
||||
@ -2190,7 +2188,7 @@ DebugScopeObject::isOptimizedOut() const
|
||||
if (s.is<ClonedBlockObject>())
|
||||
return !s.as<ClonedBlockObject>().staticBlock().needsClone();
|
||||
|
||||
if (s.is<CallObject>() && !s.is<ModuleEnvironmentObject>()) {
|
||||
if (s.is<CallObject>()) {
|
||||
return !s.as<CallObject>().isForEval() &&
|
||||
!s.as<CallObject>().callee().needsCallObject() &&
|
||||
!maybeSnapshot();
|
||||
|
@ -221,7 +221,9 @@ ScopeCoordinateFunctionScript(JSScript* script, jsbytecode* pc);
|
||||
* | | |
|
||||
* | | DeclEnvObject Holds name of recursive/needsCallObject named lambda
|
||||
* | |
|
||||
* | CallObject Scope of entire function or strict eval
|
||||
* | LexicalScopeBase Shared base for function and modules scopes
|
||||
* | | |
|
||||
* | | CallObject Scope of entire function or strict eval
|
||||
* | |
|
||||
* | ModuleEnvironmentObject Module top-level scope on run-time scope chain
|
||||
* |
|
||||
@ -287,7 +289,36 @@ class ScopeObject : public NativeObject
|
||||
}
|
||||
};
|
||||
|
||||
class CallObject : public ScopeObject
|
||||
class LexicalScopeBase : public ScopeObject
|
||||
{
|
||||
protected:
|
||||
inline void initRemainingSlotsToUninitializedLexicals(uint32_t begin);
|
||||
inline void initAliasedLexicalsToThrowOnTouch(JSScript* script);
|
||||
|
||||
public:
|
||||
/* Get/set the aliased variable referred to by 'fi'. */
|
||||
const Value& aliasedVar(AliasedFormalIter fi) {
|
||||
return getSlot(fi.scopeSlot());
|
||||
}
|
||||
inline void setAliasedVar(JSContext* cx, AliasedFormalIter fi, PropertyName* name,
|
||||
const Value& v);
|
||||
|
||||
/*
|
||||
* When an aliased var (var accessed by nested closures) is also aliased by
|
||||
* the arguments object, it must of course exist in one canonical location
|
||||
* and that location is always the CallObject. For this to work, the
|
||||
* ArgumentsObject stores special MagicValue in its array for forwarded-to-
|
||||
* CallObject variables. This MagicValue's payload is the slot of the
|
||||
* CallObject to access.
|
||||
*/
|
||||
const Value& aliasedVarFromArguments(const Value& argsValue) {
|
||||
return getSlot(ArgumentsObject::SlotFromMagicScopeSlotValue(argsValue));
|
||||
}
|
||||
inline void setAliasedVarFromArguments(JSContext* cx, const Value& argsValue, jsid id,
|
||||
const Value& v);
|
||||
};
|
||||
|
||||
class CallObject : public LexicalScopeBase
|
||||
{
|
||||
protected:
|
||||
static const uint32_t CALLEE_SLOT = 1;
|
||||
@ -295,9 +326,6 @@ class CallObject : public ScopeObject
|
||||
static CallObject*
|
||||
create(JSContext* cx, HandleScript script, HandleObject enclosing, HandleFunction callee);
|
||||
|
||||
inline void initRemainingSlotsToUninitializedLexicals(uint32_t begin);
|
||||
inline void initAliasedLexicalsToThrowOnTouch(JSScript* script);
|
||||
|
||||
public:
|
||||
static const Class class_;
|
||||
|
||||
@ -347,27 +375,6 @@ class CallObject : public ScopeObject
|
||||
return getFixedSlot(CALLEE_SLOT).toObject().as<JSFunction>();
|
||||
}
|
||||
|
||||
/* Get/set the aliased variable referred to by 'bi'. */
|
||||
const Value& aliasedVar(AliasedFormalIter fi) {
|
||||
return getSlot(fi.scopeSlot());
|
||||
}
|
||||
inline void setAliasedVar(JSContext* cx, AliasedFormalIter fi, PropertyName* name,
|
||||
const Value& v);
|
||||
|
||||
/*
|
||||
* When an aliased var (var accessed by nested closures) is also aliased by
|
||||
* the arguments object, it must of course exist in one canonical location
|
||||
* and that location is always the CallObject. For this to work, the
|
||||
* ArgumentsObject stores special MagicValue in its array for forwarded-to-
|
||||
* CallObject variables. This MagicValue's payload is the slot of the
|
||||
* CallObject to access.
|
||||
*/
|
||||
const Value& aliasedVarFromArguments(const Value& argsValue) {
|
||||
return getSlot(ArgumentsObject::SlotFromMagicScopeSlotValue(argsValue));
|
||||
}
|
||||
inline void setAliasedVarFromArguments(JSContext* cx, const Value& argsValue, jsid id,
|
||||
const Value& v);
|
||||
|
||||
/* For jit access. */
|
||||
static size_t offsetOfCallee() {
|
||||
return getFixedSlotOffset(CALLEE_SLOT);
|
||||
@ -378,13 +385,15 @@ class CallObject : public ScopeObject
|
||||
}
|
||||
};
|
||||
|
||||
class ModuleEnvironmentObject : public CallObject
|
||||
class ModuleEnvironmentObject : public LexicalScopeBase
|
||||
{
|
||||
static const uint32_t MODULE_SLOT = CallObject::CALLEE_SLOT;
|
||||
static const uint32_t MODULE_SLOT = 1;
|
||||
|
||||
public:
|
||||
static const Class class_;
|
||||
|
||||
static const uint32_t RESERVED_SLOTS = 2;
|
||||
|
||||
static ModuleEnvironmentObject* create(ExclusiveContext* cx, HandleModuleObject module);
|
||||
ModuleObject& module();
|
||||
IndirectBindingMap& importBindings();
|
||||
@ -1262,9 +1271,9 @@ JSObject::is<js::NestedScopeObject>() const
|
||||
|
||||
template<>
|
||||
inline bool
|
||||
JSObject::is<js::CallObject>() const
|
||||
JSObject::is<js::LexicalScopeBase>() const
|
||||
{
|
||||
return getClass() == &js::CallObject::class_ ||
|
||||
return is<js::CallObject>() ||
|
||||
is<js::ModuleEnvironmentObject>();
|
||||
}
|
||||
|
||||
@ -1272,7 +1281,7 @@ template<>
|
||||
inline bool
|
||||
JSObject::is<js::ScopeObject>() const
|
||||
{
|
||||
return is<js::CallObject>() ||
|
||||
return is<js::LexicalScopeBase>() ||
|
||||
is<js::DeclEnvObject>() ||
|
||||
is<js::NestedScopeObject>() ||
|
||||
is<js::RuntimeLexicalErrorObject>() ||
|
||||
@ -1343,7 +1352,7 @@ IsStaticGlobalLexicalScope(JSObject* scope)
|
||||
inline const Value&
|
||||
ScopeObject::aliasedVar(ScopeCoordinate sc)
|
||||
{
|
||||
MOZ_ASSERT(is<CallObject>() || is<ClonedBlockObject>());
|
||||
MOZ_ASSERT(is<LexicalScopeBase>() || is<ClonedBlockObject>());
|
||||
return getSlot(sc.slot());
|
||||
}
|
||||
|
||||
|
@ -35,10 +35,7 @@ namespace js {
|
||||
static inline bool
|
||||
IsCacheableNonGlobalScope(JSObject* obj)
|
||||
{
|
||||
bool cacheable =
|
||||
(obj->is<CallObject>() && !obj->is<ModuleEnvironmentObject>()) ||
|
||||
obj->is<BlockObject>() ||
|
||||
obj->is<DeclEnvObject>();
|
||||
bool cacheable = obj->is<CallObject>() || obj->is<BlockObject>() || obj->is<DeclEnvObject>();
|
||||
|
||||
MOZ_ASSERT_IF(cacheable, !obj->getOps()->lookupProperty);
|
||||
return cacheable;
|
||||
|
@ -893,17 +893,8 @@ UnboxedPlainObject::obj_watch(JSContext* cx, HandleObject obj, HandleId id, Hand
|
||||
UnboxedPlainObject::obj_enumerate(JSContext* cx, HandleObject obj, AutoIdVector& properties,
|
||||
bool enumerableOnly)
|
||||
{
|
||||
UnboxedExpandoObject* expando = obj->as<UnboxedPlainObject>().maybeExpando();
|
||||
|
||||
// Add dense elements in the expando first, for consistency with plain objects.
|
||||
if (expando) {
|
||||
for (size_t i = 0; i < expando->getDenseInitializedLength(); i++) {
|
||||
if (!expando->getDenseElement(i).isMagic(JS_ELEMENTS_HOLE)) {
|
||||
if (!properties.append(INT_TO_JSID(i)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Ignore expando properties here, they are special-cased by the property
|
||||
// enumeration code.
|
||||
|
||||
const UnboxedLayout::PropertyVector& unboxed = obj->as<UnboxedPlainObject>().layout().properties();
|
||||
for (size_t i = 0; i < unboxed.length(); i++) {
|
||||
@ -911,19 +902,6 @@ UnboxedPlainObject::obj_enumerate(JSContext* cx, HandleObject obj, AutoIdVector&
|
||||
return false;
|
||||
}
|
||||
|
||||
if (expando) {
|
||||
Vector<jsid> ids(cx);
|
||||
for (Shape::Range<NoGC> r(expando->lastProperty()); !r.empty(); r.popFront()) {
|
||||
if (enumerableOnly && !r.front().enumerable())
|
||||
continue;
|
||||
if (!ids.append(r.front().propid()))
|
||||
return false;
|
||||
}
|
||||
::Reverse(ids.begin(), ids.end());
|
||||
if (!properties.append(ids.begin(), ids.length()))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -63,3 +63,11 @@ skip-if((B2G&&browserIsRemote)||Mulet) == object-fit-scale-down-svg-005.xul obje
|
||||
skip-if((B2G&&browserIsRemote)||Mulet) == object-fit-scale-down-svg-006.xul object-fit-scale-down-svg-006-ref.html
|
||||
skip-if((B2G&&browserIsRemote)||Mulet) == object-position-png-001.xul object-position-png-001-ref.html
|
||||
skip-if((B2G&&browserIsRemote)||Mulet) == object-position-png-002.xul object-position-png-002-ref.html
|
||||
|
||||
# Tests for rendering SVG images in a XUL <treecell>:
|
||||
# XXXdholbert: These are marked as "random" right now, since they might not
|
||||
# render the images they trying to test in time for the reftest snapshot, per
|
||||
# bug 1218954. Once that bug is fixed, we should replace the "random"
|
||||
# annotation with "skip-if((B2G&&browserIsRemote)||Mulet)", like above tests.
|
||||
skip == treecell-image-svg-1a.xul treecell-image-svg-1-ref.xul # bug 1218954
|
||||
skip == treecell-image-svg-1b.xul treecell-image-svg-1-ref.xul # bug 1218954
|
||||
|
17
layout/reftests/xul/treecell-image-svg-1-ref.xul
Normal file
17
layout/reftests/xul/treecell-image-svg-1-ref.xul
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<tree seltype="single" flex="1">
|
||||
<treecols>
|
||||
<treecol flex="1"/>
|
||||
</treecols>
|
||||
<treechildren>
|
||||
<treeitem>
|
||||
<treerow>
|
||||
<treecell src="colors-16x8.png"/>
|
||||
</treerow>
|
||||
</treeitem>
|
||||
</treechildren>
|
||||
</tree>
|
||||
</window>
|
17
layout/reftests/xul/treecell-image-svg-1a.xul
Normal file
17
layout/reftests/xul/treecell-image-svg-1a.xul
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<tree seltype="single" flex="1">
|
||||
<treecols>
|
||||
<treecol flex="1"/>
|
||||
</treecols>
|
||||
<treechildren>
|
||||
<treeitem>
|
||||
<treerow>
|
||||
<treecell src="colors-16x8.svg"/>
|
||||
</treerow>
|
||||
</treeitem>
|
||||
</treechildren>
|
||||
</tree>
|
||||
</window>
|
17
layout/reftests/xul/treecell-image-svg-1b.xul
Normal file
17
layout/reftests/xul/treecell-image-svg-1b.xul
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<tree seltype="single" flex="1">
|
||||
<treecols>
|
||||
<treecol flex="1"/>
|
||||
</treecols>
|
||||
<treechildren>
|
||||
<treeitem>
|
||||
<treerow>
|
||||
<treecell src="colors-16x8-noSize.svg"/>
|
||||
</treerow>
|
||||
</treeitem>
|
||||
</treechildren>
|
||||
</tree>
|
||||
</window>
|
@ -3607,26 +3607,35 @@ nsTreeBodyFrame::PaintImage(int32_t aRowIndex,
|
||||
// Deflate destRect for the border and padding.
|
||||
destRect.Deflate(bp);
|
||||
|
||||
// Get the image source rectangle - the rectangle containing the part of
|
||||
// the image that we are going to display.
|
||||
// sourceRect will be passed as the aSrcRect argument in the DrawImage method.
|
||||
nsRect sourceRect = GetImageSourceRect(imageContext, useImageRegion, image);
|
||||
|
||||
// Let's say that the image is 100 pixels tall and
|
||||
// that the CSS has specified that the destination height should be 50
|
||||
// pixels tall. Let's say that the cell height is only 20 pixels. So, in
|
||||
// those 20 visible pixels, we want to see the top 20/50ths of the image.
|
||||
// So, the sourceRect.height should be 100 * 20 / 50, which is 40 pixels.
|
||||
// Essentially, we are scaling the image as dictated by the CSS destination
|
||||
// height and width, and we are then clipping the scaled image by the cell
|
||||
// width and height.
|
||||
// Compute the area where our whole image would be mapped, to get the
|
||||
// desired subregion onto our actual destRect:
|
||||
nsRect wholeImageDest;
|
||||
CSSIntSize rawImageCSSIntSize;
|
||||
image->GetWidth(&rawImageCSSIntSize.width);
|
||||
image->GetHeight(&rawImageCSSIntSize.height);
|
||||
nsSize rawImageSize(CSSPixel::ToAppUnits(rawImageCSSIntSize));
|
||||
nsRect wholeImageDest =
|
||||
nsLayoutUtils::GetWholeImageDestination(rawImageSize, sourceRect,
|
||||
nsRect(destRect.TopLeft(), imageDestSize));
|
||||
if (NS_SUCCEEDED(image->GetWidth(&rawImageCSSIntSize.width)) &&
|
||||
NS_SUCCEEDED(image->GetHeight(&rawImageCSSIntSize.height))) {
|
||||
// Get the image source rectangle - the rectangle containing the part of
|
||||
// the image that we are going to display. sourceRect will be passed as
|
||||
// the aSrcRect argument in the DrawImage method.
|
||||
nsRect sourceRect = GetImageSourceRect(imageContext, useImageRegion, image);
|
||||
|
||||
// Let's say that the image is 100 pixels tall and that the CSS has
|
||||
// specified that the destination height should be 50 pixels tall. Let's
|
||||
// say that the cell height is only 20 pixels. So, in those 20 visible
|
||||
// pixels, we want to see the top 20/50ths of the image. So, the
|
||||
// sourceRect.height should be 100 * 20 / 50, which is 40 pixels.
|
||||
// Essentially, we are scaling the image as dictated by the CSS
|
||||
// destination height and width, and we are then clipping the scaled
|
||||
// image by the cell width and height.
|
||||
nsSize rawImageSize(CSSPixel::ToAppUnits(rawImageCSSIntSize));
|
||||
wholeImageDest =
|
||||
nsLayoutUtils::GetWholeImageDestination(rawImageSize, sourceRect,
|
||||
nsRect(destRect.TopLeft(),
|
||||
imageDestSize));
|
||||
} else {
|
||||
// GetWidth/GetHeight failed, so we can't easily map a subregion of the
|
||||
// source image onto the destination area. So, just draw the whole image.
|
||||
wholeImageDest = destRect;
|
||||
}
|
||||
|
||||
gfxContext* ctx = aRenderingContext.ThebesContext();
|
||||
if (opacity != 1.0f) {
|
||||
|
@ -5102,7 +5102,7 @@ var BrowserEventHandler = {
|
||||
* - It's a select element showing multiple rows
|
||||
*/
|
||||
if (checkElem) {
|
||||
if ((elem.scrollTopMin != elem.scrollTopMin ||
|
||||
if ((elem.scrollTopMin != elem.scrollTopMax ||
|
||||
elem.scrollLeftMin != elem.scrollLeftMax) &&
|
||||
(this._hasScrollableOverflow(elem) ||
|
||||
elem.matches("textarea")) ||
|
||||
|
@ -69,7 +69,7 @@ CaptivePortalService::PerformCheck()
|
||||
LOG(("CaptivePortalService::PerformCheck - Calling CheckCaptivePortal\n"));
|
||||
mRequestInProgress = true;
|
||||
mCaptivePortalDetector->CheckCaptivePortal(
|
||||
NS_LITERAL_STRING(kInterfaceName).get(), this);
|
||||
MOZ_UTF16(kInterfaceName), this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -164,7 +164,7 @@ CaptivePortalService::Stop()
|
||||
mRequestInProgress = false;
|
||||
mStarted = false;
|
||||
if (mCaptivePortalDetector) {
|
||||
mCaptivePortalDetector->Abort(NS_LITERAL_STRING(kInterfaceName).get());
|
||||
mCaptivePortalDetector->Abort(MOZ_UTF16(kInterfaceName));
|
||||
}
|
||||
mCaptivePortalDetector = nullptr;
|
||||
return NS_OK;
|
||||
@ -281,7 +281,7 @@ CaptivePortalService::Prepare()
|
||||
LOG(("CaptivePortalService::Prepare\n"));
|
||||
// XXX: Finish preparation shouldn't be called until dns and routing is available.
|
||||
if (mCaptivePortalDetector) {
|
||||
mCaptivePortalDetector->FinishPreparation(NS_LITERAL_STRING(kInterfaceName).get());
|
||||
mCaptivePortalDetector->FinishPreparation(MOZ_UTF16(kInterfaceName));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1050,7 +1050,7 @@ nsIOService::SetOffline(bool offline)
|
||||
if (observerService && mConnectivity) {
|
||||
observerService->NotifyObservers(subject,
|
||||
NS_IOSERVICE_OFFLINE_STATUS_TOPIC,
|
||||
NS_LITERAL_STRING(NS_IOSERVICE_ONLINE).get());
|
||||
MOZ_UTF16(NS_IOSERVICE_ONLINE));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1133,7 +1133,7 @@ nsIOService::SetConnectivityInternal(bool aConnectivity)
|
||||
observerService->NotifyObservers(
|
||||
static_cast<nsIIOService *>(this),
|
||||
NS_IOSERVICE_OFFLINE_STATUS_TOPIC,
|
||||
NS_LITERAL_STRING(NS_IOSERVICE_ONLINE).get());
|
||||
MOZ_UTF16(NS_IOSERVICE_ONLINE));
|
||||
} else {
|
||||
// If we were previously online and lost connectivity
|
||||
// send the OFFLINE notification
|
||||
|
@ -40,7 +40,6 @@ UNIFIED_SOURCES += [
|
||||
'DNSRequestChild.cpp',
|
||||
'DNSRequestParent.cpp',
|
||||
'GetAddrInfo.cpp',
|
||||
'nameprep.c',
|
||||
'nsDNSService2.cpp',
|
||||
'nsIDNService.cpp',
|
||||
'punycode.c',
|
||||
@ -69,3 +68,13 @@ LOCAL_INCLUDES += [
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['ANDROID_VERSION'] > '19':
|
||||
CXXFLAGS += ['-I%s/bionic/libc/dns/include' % CONFIG['ANDROID_SOURCE']]
|
||||
|
||||
if CONFIG['ENABLE_INTL_API']:
|
||||
DEFINES['IDNA2008'] = True
|
||||
CXXFLAGS += CONFIG['MOZ_ICU_CFLAGS']
|
||||
CFLAGS += CONFIG['MOZ_ICU_CFLAGS']
|
||||
USE_LIBS += ['icu']
|
||||
else:
|
||||
UNIFIED_SOURCES += [
|
||||
'nameprep.c',
|
||||
]
|
||||
|
@ -17,6 +17,16 @@
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "punycode.h"
|
||||
|
||||
#ifdef IDNA2008
|
||||
// Currently we use the transitional processing option -- see
|
||||
// http://unicode.org/reports/tr46/
|
||||
// To switch to non-transitional processing, change the value of this flag
|
||||
// and kTransitionalProcessing in netwerk/test/unit/test_idna2008.js to false
|
||||
// (patch in bug 1218179).
|
||||
const bool kIDNA2008_TransitionalProcessing = true;
|
||||
|
||||
#include "ICUUtils.h"
|
||||
#endif
|
||||
|
||||
using namespace mozilla::unicode;
|
||||
|
||||
@ -123,18 +133,91 @@ void nsIDNService::prefsChanged(nsIPrefBranch *prefBranch, const char16_t *pref)
|
||||
|
||||
nsIDNService::nsIDNService()
|
||||
{
|
||||
#ifdef IDNA2008
|
||||
uint32_t IDNAOptions = UIDNA_CHECK_BIDI | UIDNA_CHECK_CONTEXTJ;
|
||||
if (!kIDNA2008_TransitionalProcessing) {
|
||||
IDNAOptions |= UIDNA_NONTRANSITIONAL_TO_UNICODE;
|
||||
}
|
||||
UErrorCode errorCode = U_ZERO_ERROR;
|
||||
mIDNA = uidna_openUTS46(IDNAOptions, &errorCode);
|
||||
#else
|
||||
if (idn_success != idn_nameprep_create(nullptr, &mNamePrepHandle))
|
||||
mNamePrepHandle = nullptr;
|
||||
|
||||
mNormalizer = do_GetService(NS_UNICODE_NORMALIZER_CONTRACTID);
|
||||
/* member initializers and constructor code */
|
||||
#endif
|
||||
}
|
||||
|
||||
nsIDNService::~nsIDNService()
|
||||
{
|
||||
#ifdef IDNA2008
|
||||
uidna_close(mIDNA);
|
||||
#else
|
||||
idn_nameprep_destroy(mNamePrepHandle);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef IDNA2008
|
||||
nsresult
|
||||
nsIDNService::IDNA2008ToUnicode(const nsACString& input, nsAString& output)
|
||||
{
|
||||
NS_ConvertUTF8toUTF16 inputStr(input);
|
||||
UIDNAInfo info = UIDNA_INFO_INITIALIZER;
|
||||
UErrorCode errorCode = U_ZERO_ERROR;
|
||||
int32_t inLen = inputStr.Length();
|
||||
int32_t outMaxLen = inLen - kACEPrefixLen + 1;
|
||||
UChar outputBuffer[kMaxDNSNodeLen + 1];
|
||||
|
||||
int32_t outLen = uidna_labelToUnicode(mIDNA, (const UChar*)inputStr.get(),
|
||||
inLen, outputBuffer, outMaxLen,
|
||||
&info, &errorCode);
|
||||
if (info.errors != 0) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (U_SUCCESS(errorCode)) {
|
||||
ICUUtils::AssignUCharArrayToString(outputBuffer, outLen, output);
|
||||
}
|
||||
|
||||
return ICUUtils::UErrorToNsResult(errorCode);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsIDNService::IDNA2008StringPrep(const nsAString& input,
|
||||
nsAString& output,
|
||||
stringPrepFlag flag)
|
||||
{
|
||||
UIDNAInfo info = UIDNA_INFO_INITIALIZER;
|
||||
UErrorCode errorCode = U_ZERO_ERROR;
|
||||
int32_t inLen = input.Length();
|
||||
int32_t outMaxLen = kMaxDNSNodeLen + 1;
|
||||
UChar outputBuffer[kMaxDNSNodeLen + 1];
|
||||
|
||||
int32_t outLen =
|
||||
uidna_labelToUnicode(mIDNA, (const UChar*)PromiseFlatString(input).get(),
|
||||
inLen, outputBuffer, outMaxLen, &info, &errorCode);
|
||||
nsresult rv = ICUUtils::UErrorToNsResult(errorCode);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Output the result of nameToUnicode even if there were errors
|
||||
ICUUtils::AssignUCharArrayToString(outputBuffer, outLen, output);
|
||||
|
||||
if (flag == eStringPrepIgnoreErrors) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (info.errors != 0) {
|
||||
if (flag == eStringPrepForDNS) {
|
||||
output.Truncate();
|
||||
}
|
||||
rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_IMETHODIMP nsIDNService::ConvertUTF8toACE(const nsACString & input, nsACString & ace)
|
||||
{
|
||||
return UTF8toACE(input, ace, eStringPrepForDNS);
|
||||
@ -396,6 +479,7 @@ static nsresult utf16ToUcs4(const nsAString& in,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifndef IDNA2008
|
||||
static void ucs4toUtf16(const uint32_t *in, nsAString& out)
|
||||
{
|
||||
while (*in) {
|
||||
@ -408,6 +492,7 @@ static void ucs4toUtf16(const uint32_t *in, nsAString& out)
|
||||
in++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static nsresult punycode(const nsAString& in, nsACString& out)
|
||||
{
|
||||
@ -462,6 +547,9 @@ static nsresult punycode(const nsAString& in, nsACString& out)
|
||||
nsresult nsIDNService::stringPrep(const nsAString& in, nsAString& out,
|
||||
stringPrepFlag flag)
|
||||
{
|
||||
#ifdef IDNA2008
|
||||
return IDNA2008StringPrep(in, out, flag);
|
||||
#else
|
||||
if (!mNamePrepHandle || !mNormalizer)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
@ -523,6 +611,7 @@ nsresult nsIDNService::stringPrep(const nsAString& in, nsAString& out,
|
||||
}
|
||||
|
||||
return rv;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsresult nsIDNService::stringPrepAndACE(const nsAString& in, nsACString& out,
|
||||
@ -612,6 +701,11 @@ nsresult nsIDNService::decodeACE(const nsACString& in, nsACString& out,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoString utf16;
|
||||
#ifdef IDNA2008
|
||||
nsresult result = IDNA2008ToUnicode(in, utf16);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
#else
|
||||
// RFC 3490 - 4.2 ToUnicode
|
||||
// The ToUnicode output never contains more code points than its input.
|
||||
punycode_uint output_length = in.Length() - kACEPrefixLen + 1;
|
||||
@ -630,9 +724,9 @@ nsresult nsIDNService::decodeACE(const nsACString& in, nsACString& out,
|
||||
|
||||
// UCS4 -> UTF8
|
||||
output[output_length] = 0;
|
||||
nsAutoString utf16;
|
||||
ucs4toUtf16(output, utf16);
|
||||
delete [] output;
|
||||
#endif
|
||||
if (flag != eStringPrepForUI || isLabelSafe(utf16)) {
|
||||
CopyUTF16toUTF8(utf16, out);
|
||||
} else {
|
||||
|
@ -10,8 +10,14 @@
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
#ifdef IDNA2008
|
||||
#include "unicode/uidna.h"
|
||||
#else
|
||||
#include "nsIUnicodeNormalizer.h"
|
||||
#include "nsIDNKitInterface.h"
|
||||
#endif
|
||||
|
||||
#include "nsString.h"
|
||||
|
||||
class nsIPrefBranch;
|
||||
@ -143,8 +149,23 @@ private:
|
||||
*/
|
||||
bool illegalScriptCombo(int32_t script, int32_t& savedScript);
|
||||
|
||||
#ifdef IDNA2008
|
||||
/**
|
||||
* Convert a DNS label from ASCII to Unicode using IDNA2008
|
||||
*/
|
||||
nsresult IDNA2008ToUnicode(const nsACString& input, nsAString& output);
|
||||
|
||||
/**
|
||||
* Convert a DNS label to a normalized form conforming to IDNA2008
|
||||
*/
|
||||
nsresult IDNA2008StringPrep(const nsAString& input, nsAString& output,
|
||||
stringPrepFlag flag);
|
||||
|
||||
UIDNA* mIDNA;
|
||||
#else
|
||||
idn_nameprep_t mNamePrepHandle;
|
||||
nsCOMPtr<nsIUnicodeNormalizer> mNormalizer;
|
||||
#endif
|
||||
nsXPIDLString mIDNBlacklist;
|
||||
|
||||
/**
|
||||
|
@ -358,7 +358,7 @@ nsHttpChannel::Connect()
|
||||
|
||||
const char16_t* params[] = { reportSpec.get(), reportScheme.get() };
|
||||
uint32_t innerWindowId = mLoadInfo ? mLoadInfo->GetInnerWindowID() : 0;
|
||||
CSP_LogLocalizedStr(NS_LITERAL_STRING("upgradeInsecureRequest").get(),
|
||||
CSP_LogLocalizedStr(MOZ_UTF16("upgradeInsecureRequest"),
|
||||
params, ArrayLength(params),
|
||||
EmptyString(), // aSourceFile
|
||||
EmptyString(), // aScriptSample
|
||||
|
@ -43,6 +43,7 @@ LOCAL_INCLUDES = [
|
||||
'../dns',
|
||||
]
|
||||
|
||||
DEFINES['IDNA2008'] = False
|
||||
DEFINES['MOZILLA_INTERNAL_API'] = True
|
||||
DEFINES['MOZILLA_XPCOMRT_API'] = True
|
||||
DEFINES['MOZILLA_EXTERNAL_LINKAGE'] = True
|
||||
|
@ -92,8 +92,14 @@ function run_test() {
|
||||
|
||||
// www.1מיץ.com is invalid
|
||||
expected_fail("www.1\u05DE\u05D9\u05E5.com");
|
||||
// www.מיץ1.com is invalid
|
||||
expected_fail("www.\u05DE\u05D9\u05E51.com");
|
||||
// www.!מיץ.com is invalid
|
||||
expected_fail("www.!\u05DE\u05D9\u05E5.com");
|
||||
// www.מיץ!.com is invalid
|
||||
expected_fail("www.\u05DE\u05D9\u05E5!.com");
|
||||
|
||||
// XXX TODO: add a test for an RTL label ending with a digit. This was
|
||||
// invalid in IDNA2003 but became valid in IDNA2008
|
||||
|
||||
// But www.מיץ1פטל.com is fine
|
||||
expected_pass("www.\u05DE\u05D9\u05E51\u05E4\u05D8\u05DC.com");
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user