зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to autoland, a=merge
This commit is contained in:
Коммит
81db6ce036
|
@ -263,8 +263,7 @@ static const MarkupMapInfo sMarkupMapList[] = {
|
|||
nsAccessibilityService *nsAccessibilityService::gAccessibilityService = nullptr;
|
||||
ApplicationAccessible* nsAccessibilityService::gApplicationAccessible = nullptr;
|
||||
xpcAccessibleApplication* nsAccessibilityService::gXPCApplicationAccessible = nullptr;
|
||||
bool nsAccessibilityService::gIsShutdown = true;
|
||||
bool nsAccessibilityService::gIsPlatformCaller = false;
|
||||
uint32_t nsAccessibilityService::gConsumers = 0;
|
||||
|
||||
nsAccessibilityService::nsAccessibilityService() :
|
||||
DocManager(), FocusManager(), mMarkupMaps(ArrayLength(sMarkupMapList))
|
||||
|
@ -273,7 +272,7 @@ nsAccessibilityService::nsAccessibilityService() :
|
|||
|
||||
nsAccessibilityService::~nsAccessibilityService()
|
||||
{
|
||||
NS_ASSERTION(gIsShutdown, "Accessibility wasn't shutdown!");
|
||||
NS_ASSERTION(IsShutdown(), "Accessibility wasn't shutdown!");
|
||||
gAccessibilityService = nullptr;
|
||||
}
|
||||
|
||||
|
@ -957,7 +956,7 @@ nsAccessibilityService::CreateAccessible(nsINode* aNode,
|
|||
{
|
||||
MOZ_ASSERT(aContext, "No context provided");
|
||||
MOZ_ASSERT(aNode, "No node to create an accessible for");
|
||||
MOZ_ASSERT(!gIsShutdown, "No creation after shutdown");
|
||||
MOZ_ASSERT(gConsumers, "No creation after shutdown");
|
||||
|
||||
if (aIsSubtreeHidden)
|
||||
*aIsSubtreeHidden = false;
|
||||
|
@ -1284,8 +1283,6 @@ nsAccessibilityService::Init()
|
|||
sPluginTimers = new nsTArray<nsCOMPtr<nsITimer> >;
|
||||
#endif
|
||||
|
||||
gIsShutdown = false;
|
||||
|
||||
// Now its safe to start platform accessibility.
|
||||
if (XRE_IsParentProcess())
|
||||
PlatformInit();
|
||||
|
@ -1303,9 +1300,9 @@ nsAccessibilityService::Shutdown()
|
|||
// Don't null accessibility service static member at this point to be safe
|
||||
// if someone will try to operate with it.
|
||||
|
||||
MOZ_ASSERT(!gIsShutdown, "Accessibility was shutdown already");
|
||||
MOZ_ASSERT(gConsumers, "Accessibility was shutdown already");
|
||||
|
||||
gIsShutdown = true;
|
||||
gConsumers = 0;
|
||||
|
||||
// Remove observers.
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
|
@ -1344,7 +1341,6 @@ nsAccessibilityService::Shutdown()
|
|||
|
||||
NS_RELEASE(gAccessibilityService);
|
||||
gAccessibilityService = nullptr;
|
||||
gIsPlatformCaller = false;
|
||||
}
|
||||
|
||||
already_AddRefed<Accessible>
|
||||
|
@ -1778,12 +1774,8 @@ nsAccessibilityService::CreateAccessibleForXULTree(nsIContent* aContent,
|
|||
#endif
|
||||
|
||||
nsAccessibilityService*
|
||||
GetOrCreateAccService(bool aIsPlatformCaller)
|
||||
GetOrCreateAccService(uint32_t aNewConsumer)
|
||||
{
|
||||
if (aIsPlatformCaller) {
|
||||
nsAccessibilityService::gIsPlatformCaller = aIsPlatformCaller;
|
||||
}
|
||||
|
||||
if (!nsAccessibilityService::gAccessibilityService) {
|
||||
RefPtr<nsAccessibilityService> service = new nsAccessibilityService();
|
||||
if (!service->Init()) {
|
||||
|
@ -1794,19 +1786,34 @@ GetOrCreateAccService(bool aIsPlatformCaller)
|
|||
|
||||
MOZ_ASSERT(nsAccessibilityService::gAccessibilityService,
|
||||
"Accessible service is not initialized.");
|
||||
nsAccessibilityService::gConsumers |= aNewConsumer;
|
||||
return nsAccessibilityService::gAccessibilityService;
|
||||
}
|
||||
|
||||
bool
|
||||
CanShutdownAccService()
|
||||
void
|
||||
MaybeShutdownAccService(uint32_t aFormerConsumer)
|
||||
{
|
||||
nsAccessibilityService* accService = nsAccessibilityService::gAccessibilityService;
|
||||
if (!accService) {
|
||||
return false;
|
||||
nsAccessibilityService* accService =
|
||||
nsAccessibilityService::gAccessibilityService;
|
||||
|
||||
if (!accService || accService->IsShutdown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (nsCoreUtils::AccEventObserversExist() ||
|
||||
xpcAccessibilityService::IsInUse()) {
|
||||
// Still used by XPCOM
|
||||
nsAccessibilityService::gConsumers =
|
||||
(nsAccessibilityService::gConsumers & ~aFormerConsumer) |
|
||||
nsAccessibilityService::eXPCOM;
|
||||
return;
|
||||
}
|
||||
|
||||
if (nsAccessibilityService::gConsumers & ~aFormerConsumer) {
|
||||
nsAccessibilityService::gConsumers &= ~aFormerConsumer;
|
||||
} else {
|
||||
accService->Shutdown(); // Will unset all nsAccessibilityService::gConsumers
|
||||
}
|
||||
return !xpcAccessibilityService::IsInUse() &&
|
||||
!accService->IsPlatformCaller() && !accService->IsShutdown() &&
|
||||
!nsCoreUtils::AccEventObserversExist();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -195,12 +195,10 @@ public:
|
|||
/**
|
||||
* Return true if accessibility service has been shutdown.
|
||||
*/
|
||||
static bool IsShutdown() { return gIsShutdown; }
|
||||
|
||||
/**
|
||||
* Return true if accessibility service has been initialized by platform.
|
||||
*/
|
||||
static bool IsPlatformCaller() { return gIsPlatformCaller; };
|
||||
static bool IsShutdown()
|
||||
{
|
||||
return gConsumers == 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an accessible for the given DOM node.
|
||||
|
@ -226,6 +224,25 @@ public:
|
|||
void MarkupAttributes(const nsIContent* aContent,
|
||||
nsIPersistentProperties* aAttributes) const;
|
||||
|
||||
/**
|
||||
* A list of possible accessibility service consumers. Accessibility service
|
||||
* can only be shut down when there are no remaining consumers.
|
||||
*
|
||||
* eXPCOM - accessibility service is used by XPCOM.
|
||||
*
|
||||
* eMainProcess - accessibility service was started by main process in the
|
||||
* content process.
|
||||
*
|
||||
* ePlatformAPI - accessibility service is used by the platform api in the
|
||||
* main process.
|
||||
*/
|
||||
enum ServiceConsumer
|
||||
{
|
||||
eXPCOM = 1 << 0,
|
||||
eMainProcess = 1 << 1,
|
||||
ePlatformAPI = 1 << 2,
|
||||
};
|
||||
|
||||
private:
|
||||
// nsAccessibilityService creation is controlled by friend
|
||||
// GetOrCreateAccService, keep constructors private.
|
||||
|
@ -277,20 +294,15 @@ private:
|
|||
static mozilla::a11y::xpcAccessibleApplication* gXPCApplicationAccessible;
|
||||
|
||||
/**
|
||||
* Indicates whether accessibility service was shutdown.
|
||||
* Contains a set of accessibility service consumers.
|
||||
*/
|
||||
static bool gIsShutdown;
|
||||
|
||||
/**
|
||||
* Indicates whether accessibility service was initialized by platform.
|
||||
*/
|
||||
static bool gIsPlatformCaller;
|
||||
static uint32_t gConsumers;
|
||||
|
||||
nsDataHashtable<nsPtrHashKey<const nsIAtom>, const mozilla::a11y::MarkupMapInfo*> mMarkupMaps;
|
||||
|
||||
friend nsAccessibilityService* GetAccService();
|
||||
friend nsAccessibilityService* GetOrCreateAccService(bool);
|
||||
friend bool CanShutdownAccService();
|
||||
friend nsAccessibilityService* GetOrCreateAccService(uint32_t);
|
||||
friend void MaybeShutdownAccService(uint32_t);
|
||||
friend mozilla::a11y::FocusManager* mozilla::a11y::FocusMgr();
|
||||
friend mozilla::a11y::SelectionManager* mozilla::a11y::SelectionMgr();
|
||||
friend mozilla::a11y::ApplicationAccessible* mozilla::a11y::ApplicationAcc();
|
||||
|
@ -310,12 +322,13 @@ GetAccService()
|
|||
/**
|
||||
* Return accessibility service instance; creating one if necessary.
|
||||
*/
|
||||
nsAccessibilityService* GetOrCreateAccService(bool aIsPlatformCaller = true);
|
||||
nsAccessibilityService* GetOrCreateAccService(
|
||||
uint32_t aNewConsumer = nsAccessibilityService::ePlatformAPI);
|
||||
|
||||
/**
|
||||
* Return a flag indicating if accessibility service can be shutdown.
|
||||
* Shutdown accessibility service if needed.
|
||||
*/
|
||||
bool CanShutdownAccService();
|
||||
void MaybeShutdownAccService(uint32_t aFormerConsumer);
|
||||
|
||||
/**
|
||||
* Return true if we're in a content process and not B2G.
|
||||
|
|
|
@ -5,5 +5,13 @@ support-files =
|
|||
shared-head.js
|
||||
|
||||
[browser_shutdown_multi_reference.js]
|
||||
[browser_shutdown_parent_own_reference.js]
|
||||
skip-if = !e10s # e10s specific test for a11y start/shutdown between parent and content.
|
||||
[browser_shutdown_remote_no_reference.js]
|
||||
skip-if = !e10s # e10s specific test for a11y start/shutdown between parent and content.
|
||||
[browser_shutdown_remote_only.js]
|
||||
skip-if = !e10s # e10s specific test for a11y start/shutdown between parent and content.
|
||||
[browser_shutdown_remote_own_reference.js]
|
||||
skip-if = !e10s # e10s specific test for a11y start/shutdown between parent and content.
|
||||
[browser_shutdown_scope_lifecycle.js]
|
||||
[browser_shutdown_start_restart.js]
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
add_task(function* () {
|
||||
// Making sure that the e10s is enabled on Windows for testing.
|
||||
yield setE10sPrefs();
|
||||
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
gBrowser,
|
||||
url: `data:text/html,
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Accessibility Test</title>
|
||||
</head>
|
||||
<body></body>
|
||||
</html>`
|
||||
}, function*(browser) {
|
||||
info('Creating a service in parent and waiting for service to be created ' +
|
||||
'in content');
|
||||
// Create a11y service in the main process. This will trigger creating of
|
||||
// the a11y service in parent as well.
|
||||
let parentA11yInit = initPromise();
|
||||
let contentA11yInit = initPromise(browser);
|
||||
let accService = Cc['@mozilla.org/accessibilityService;1'].getService(
|
||||
Ci.nsIAccessibilityService);
|
||||
ok(accService, 'Service initialized in parent');
|
||||
yield Promise.all([parentA11yInit, contentA11yInit]);
|
||||
|
||||
info('Adding additional reference to accessibility service in content ' +
|
||||
'process');
|
||||
// Add a new reference to the a11y service inside the content process.
|
||||
loadFrameScripts(browser, `let accService = Components.classes[
|
||||
'@mozilla.org/accessibilityService;1'].getService(
|
||||
Components.interfaces.nsIAccessibilityService);`);
|
||||
|
||||
info('Trying to shut down a service in content and making sure it stays ' +
|
||||
'alive as it was started by parent');
|
||||
let contentCanShutdown = false;
|
||||
// This promise will resolve only if contentCanShutdown flag is set to true.
|
||||
// If 'a11y-init-or-shutdown' event with '0' flag (in content) comes before
|
||||
// it can be shut down, the promise will reject.
|
||||
let contentA11yShutdown = new Promise((resolve, reject) =>
|
||||
shutdownPromise(browser).then(flag => contentCanShutdown ?
|
||||
resolve() : reject('Accessible service was shut down incorrectly')));
|
||||
// Remove a11y service reference in content and force garbage collection.
|
||||
// This should not trigger shutdown since a11y was originally initialized by
|
||||
// the main process.
|
||||
loadFrameScripts(browser, `accService = null; Components.utils.forceGC();`);
|
||||
|
||||
// Have some breathing room between a11y service shutdowns.
|
||||
yield new Promise(resolve => executeSoon(resolve));
|
||||
|
||||
info('Removing a service in parent');
|
||||
// Now allow a11y service to shutdown in content.
|
||||
contentCanShutdown = true;
|
||||
// Remove the a11y service reference in the main process.
|
||||
let parentA11yShutdown = shutdownPromise();
|
||||
accService = null;
|
||||
ok(!accService, 'Service is removed in parent');
|
||||
// Force garbage collection that should trigger shutdown in both parent and
|
||||
// content.
|
||||
forceGC();
|
||||
yield Promise.all([parentA11yShutdown, contentA11yShutdown]);
|
||||
|
||||
// Unsetting e10s related preferences.
|
||||
yield unsetE10sPrefs();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,48 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
add_task(function* () {
|
||||
// Making sure that the e10s is enabled on Windows for testing.
|
||||
yield setE10sPrefs();
|
||||
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
gBrowser,
|
||||
url: `data:text/html,
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Accessibility Test</title>
|
||||
</head>
|
||||
<body></body>
|
||||
</html>`
|
||||
}, function*(browser) {
|
||||
info('Creating a service in parent and waiting for service to be created ' +
|
||||
'in content');
|
||||
// Create a11y service in the main process. This will trigger creating of
|
||||
// the a11y service in parent as well.
|
||||
let parentA11yInit = initPromise();
|
||||
let contentA11yInit = initPromise(browser);
|
||||
let accService = Cc['@mozilla.org/accessibilityService;1'].getService(
|
||||
Ci.nsIAccessibilityService);
|
||||
ok(accService, 'Service initialized in parent');
|
||||
yield Promise.all([parentA11yInit, contentA11yInit]);
|
||||
|
||||
info('Removing a service in parent and waiting for service to be shut ' +
|
||||
'down in content');
|
||||
// Remove a11y service reference in the main process.
|
||||
let parentA11yShutdown = shutdownPromise();
|
||||
let contentA11yShutdown = shutdownPromise(browser);
|
||||
accService = null;
|
||||
ok(!accService, 'Service is removed in parent');
|
||||
// Force garbage collection that should trigger shutdown in both main and
|
||||
// content process.
|
||||
forceGC();
|
||||
yield Promise.all([parentA11yShutdown, contentA11yShutdown]);
|
||||
});
|
||||
|
||||
// Unsetting e10s related preferences.
|
||||
yield unsetE10sPrefs();
|
||||
});
|
|
@ -0,0 +1,40 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
add_task(function* () {
|
||||
// Making sure that the e10s is enabled on Windows for testing.
|
||||
yield setE10sPrefs();
|
||||
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
gBrowser,
|
||||
url: `data:text/html,
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Accessibility Test</title>
|
||||
</head>
|
||||
<body></body>
|
||||
</html>`
|
||||
}, function*(browser) {
|
||||
info('Creating a service in content');
|
||||
// Create a11y service in the content process.
|
||||
let a11yInit = initPromise(browser);
|
||||
loadFrameScripts(browser, `let accService = Components.classes[
|
||||
'@mozilla.org/accessibilityService;1'].getService(
|
||||
Components.interfaces.nsIAccessibilityService);`);
|
||||
yield a11yInit;
|
||||
|
||||
info('Removing a service in content');
|
||||
// Remove a11y service reference from the content process.
|
||||
let a11yShutdown = shutdownPromise(browser);
|
||||
// Force garbage collection that should trigger shutdown.
|
||||
loadFrameScripts(browser, `accService = null; Components.utils.forceGC();`);
|
||||
yield a11yShutdown;
|
||||
|
||||
// Unsetting e10s related preferences.
|
||||
yield unsetE10sPrefs();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,75 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
add_task(function* () {
|
||||
// Making sure that the e10s is enabled on Windows for testing.
|
||||
yield setE10sPrefs();
|
||||
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
gBrowser,
|
||||
url: `data:text/html,
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Accessibility Test</title>
|
||||
</head>
|
||||
<body></body>
|
||||
</html>`
|
||||
}, function*(browser) {
|
||||
info('Creating a service in parent and waiting for service to be created ' +
|
||||
'in content');
|
||||
// Create a11y service in the main process. This will trigger creating of
|
||||
// the a11y service in parent as well.
|
||||
let parentA11yInit = initPromise();
|
||||
let contentA11yInit = initPromise(browser);
|
||||
let accService = Cc['@mozilla.org/accessibilityService;1'].getService(
|
||||
Ci.nsIAccessibilityService);
|
||||
ok(accService, 'Service initialized in parent');
|
||||
yield Promise.all([parentA11yInit, contentA11yInit]);
|
||||
|
||||
info('Adding additional reference to accessibility service in content ' +
|
||||
'process');
|
||||
// Add a new reference to the a11y service inside the content process.
|
||||
loadFrameScripts(browser, `let accService = Components.classes[
|
||||
'@mozilla.org/accessibilityService;1'].getService(
|
||||
Components.interfaces.nsIAccessibilityService);`);
|
||||
|
||||
info('Shutting down a service in parent and making sure the one in ' +
|
||||
'content stays alive');
|
||||
let contentCanShutdown = false;
|
||||
let parentA11yShutdown = shutdownPromise();
|
||||
// This promise will resolve only if contentCanShutdown flag is set to true.
|
||||
// If 'a11y-init-or-shutdown' event with '0' flag (in content) comes before
|
||||
// it can be shut down, the promise will reject.
|
||||
let contentA11yShutdown = new Promise((resolve, reject) =>
|
||||
shutdownPromise(browser).then(flag => contentCanShutdown ?
|
||||
resolve() : reject('Accessible service was shut down incorrectly')));
|
||||
// Remove a11y service reference in the main process and force garbage
|
||||
// collection. This should not trigger shutdown in content since a11y
|
||||
// service is used by XPCOM.
|
||||
accService = null;
|
||||
ok(!accService, 'Service is removed in parent');
|
||||
// Force garbage collection that should not trigger shutdown because there
|
||||
// is a reference in a content process.
|
||||
forceGC();
|
||||
loadFrameScripts(browser, `Components.utils.forceGC();`);
|
||||
yield parentA11yShutdown;
|
||||
|
||||
// Have some breathing room between a11y service shutdowns.
|
||||
yield new Promise(resolve => executeSoon(resolve));
|
||||
|
||||
info('Removing a service in content');
|
||||
// Now allow a11y service to shutdown in content.
|
||||
contentCanShutdown = true;
|
||||
// Remove last reference to a11y service in content and force garbage
|
||||
// collection that should trigger shutdown.
|
||||
loadFrameScripts(browser, `accService = null; Components.utils.forceGC();`);
|
||||
yield contentA11yShutdown;
|
||||
|
||||
// Unsetting e10s related preferences.
|
||||
yield unsetE10sPrefs();
|
||||
});
|
||||
});
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
add_task(function* testScopeLifecycle() {
|
||||
add_task(function* () {
|
||||
// Create a11y service inside of the function scope. Its reference should be
|
||||
// released once the anonimous function is called.
|
||||
let a11yInitThenShutdown = initPromise().then(shutdownPromise);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
add_task(function* testStartAndRestart() {
|
||||
add_task(function* () {
|
||||
info('Creating a service');
|
||||
// Create a11y service.
|
||||
let a11yInit = initPromise();
|
||||
|
|
|
@ -23,10 +23,7 @@ xpcAccessibilityService *xpcAccessibilityService::gXPCAccessibilityService = nul
|
|||
void
|
||||
xpcAccessibilityService::ShutdownCallback(nsITimer* aTimer, void* aClosure)
|
||||
{
|
||||
if (CanShutdownAccService()) {
|
||||
GetAccService()->Shutdown();
|
||||
}
|
||||
|
||||
MaybeShutdownAccService(nsAccessibilityService::eXPCOM);
|
||||
xpcAccessibilityService* xpcAccService =
|
||||
reinterpret_cast<xpcAccessibilityService*>(aClosure);
|
||||
|
||||
|
@ -47,7 +44,7 @@ xpcAccessibilityService::AddRef(void)
|
|||
NS_LOG_ADDREF(this, count, "xpcAccessibilityService", sizeof(*this));
|
||||
|
||||
if (mRefCnt > 1) {
|
||||
GetOrCreateAccService(false);
|
||||
GetOrCreateAccService(nsAccessibilityService::eXPCOM);
|
||||
}
|
||||
|
||||
return count;
|
||||
|
@ -238,7 +235,7 @@ NS_GetAccessibilityService(nsIAccessibilityService** aResult)
|
|||
NS_ENSURE_TRUE(aResult, NS_ERROR_NULL_POINTER);
|
||||
*aResult = nullptr;
|
||||
|
||||
GetOrCreateAccService(false);
|
||||
GetOrCreateAccService(nsAccessibilityService::eXPCOM);
|
||||
|
||||
xpcAccessibilityService* service = new xpcAccessibilityService();
|
||||
NS_ENSURE_TRUE(service, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
|
|
@ -24,11 +24,23 @@ richlistitem[type="download"].download-state[state="1"]:not([exists]) .downloadS
|
|||
|
||||
#downloadsSummary:not([inprogress]) > vbox > #downloadsSummaryProgress,
|
||||
#downloadsSummary:not([inprogress]) > vbox > #downloadsSummaryDetails,
|
||||
#downloadsFooter[showingsummary] > #downloadsFooterButtons,
|
||||
#downloadsFooter:not([showingsummary]) > #downloadsSummary {
|
||||
#downloadsFooter:not([showingsummary]) #downloadsSummary {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#downloadsFooter[showingdropdown] > stack > #downloadsSummary,
|
||||
#downloadsFooter[showingsummary] > stack:hover > #downloadsSummary,
|
||||
#downloadsFooter[showingsummary]:not([showingdropdown]) > stack:not(:hover) > #downloadsFooterButtons {
|
||||
/* If we used "visibility: hidden;" then the mouseenter event of
|
||||
#downloadsHistory wouldn't be triggered immediately, and the hover styling
|
||||
of the button would not apply until the mouse is moved again.
|
||||
|
||||
"-moz-user-focus: ignore;" prevents the elements with "opacity: 0;" from
|
||||
being focused with the keyboard. */
|
||||
opacity: 0;
|
||||
-moz-user-focus: ignore;
|
||||
}
|
||||
|
||||
/*** Downloads View ***/
|
||||
|
||||
/**
|
||||
|
|
|
@ -382,14 +382,15 @@ const DownloadsPanel = {
|
|||
} else {
|
||||
itemClearList.setAttribute("hidden", "true");
|
||||
}
|
||||
DownloadsViewController.updateCommands();
|
||||
|
||||
document.getElementById("downloadsFooterButtonsSplitter").classList
|
||||
.add("downloadsDropmarkerSplitterExtend");
|
||||
document.getElementById("downloadsFooter")
|
||||
.setAttribute("showingdropdown", true);
|
||||
},
|
||||
|
||||
onFooterPopupHidden(aEvent) {
|
||||
document.getElementById("downloadsFooterButtonsSplitter").classList
|
||||
.remove("downloadsDropmarkerSplitterExtend");
|
||||
document.getElementById("downloadsFooter")
|
||||
.removeAttribute("showingdropdown");
|
||||
},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -129,51 +129,53 @@
|
|||
<spacer flex="1"/>
|
||||
<vbox id="downloadsFooter"
|
||||
class="downloadsPanelFooter">
|
||||
<hbox id="downloadsSummary"
|
||||
align="center"
|
||||
orient="horizontal"
|
||||
onkeydown="DownloadsSummary.onKeyDown(event);"
|
||||
onclick="DownloadsSummary.onClick(event);">
|
||||
<image class="downloadTypeIcon" />
|
||||
<vbox pack="center"
|
||||
class="downloadContainer"
|
||||
style="width: &downloadDetails.width;">
|
||||
<description id="downloadsSummaryDescription"
|
||||
style="min-width: &downloadsSummary.minWidth2;"/>
|
||||
<progressmeter id="downloadsSummaryProgress"
|
||||
class="downloadProgress"
|
||||
min="0"
|
||||
max="100"
|
||||
mode="normal" />
|
||||
<description id="downloadsSummaryDetails"
|
||||
crop="end"/>
|
||||
</vbox>
|
||||
</hbox>
|
||||
<hbox id="downloadsFooterButtons">
|
||||
<button id="downloadsHistory"
|
||||
class="plain downloadsPanelFooterButton"
|
||||
label="&downloadsHistory.label;"
|
||||
accesskey="&downloadsHistory.accesskey;"
|
||||
flex="1"
|
||||
oncommand="DownloadsPanel.showDownloadsHistory();"/>
|
||||
<toolbarseparator id="downloadsFooterButtonsSplitter"
|
||||
class="downloadsDropmarkerSplitter"/>
|
||||
<button id="downloadsFooterDropmarker"
|
||||
class="plain downloadsPanelFooterButton downloadsDropmarker"
|
||||
type="menu">
|
||||
<menupopup id="downloadSubPanel"
|
||||
onpopupshowing="DownloadsPanel.onFooterPopupShowing(event);"
|
||||
onpopuphidden="DownloadsPanel.onFooterPopupHidden(event);"
|
||||
position="after_end">
|
||||
<menuitem id="downloadsDropdownItemClearList"
|
||||
command="downloadsCmd_clearList"
|
||||
label="&cmd.clearList2.label;"/>
|
||||
<menuitem id="downloadsDropdownItemOpenDownloadsFolder"
|
||||
oncommand="DownloadsPanel.openDownloadsFolder();"
|
||||
label="&openDownloadsFolder.label;"/>
|
||||
</menupopup>
|
||||
</button>
|
||||
</hbox>
|
||||
<stack>
|
||||
<hbox id="downloadsSummary"
|
||||
align="center"
|
||||
orient="horizontal"
|
||||
onkeydown="DownloadsSummary.onKeyDown(event);"
|
||||
onclick="DownloadsSummary.onClick(event);">
|
||||
<image class="downloadTypeIcon" />
|
||||
<vbox pack="center"
|
||||
class="downloadContainer"
|
||||
style="width: &downloadDetails.width;">
|
||||
<description id="downloadsSummaryDescription"
|
||||
style="min-width: &downloadsSummary.minWidth2;"/>
|
||||
<progressmeter id="downloadsSummaryProgress"
|
||||
class="downloadProgress"
|
||||
min="0"
|
||||
max="100"
|
||||
mode="normal" />
|
||||
<description id="downloadsSummaryDetails"
|
||||
crop="end"/>
|
||||
</vbox>
|
||||
</hbox>
|
||||
<hbox id="downloadsFooterButtons">
|
||||
<button id="downloadsHistory"
|
||||
class="plain downloadsPanelFooterButton"
|
||||
label="&downloadsHistory.label;"
|
||||
accesskey="&downloadsHistory.accesskey;"
|
||||
flex="1"
|
||||
oncommand="DownloadsPanel.showDownloadsHistory();"/>
|
||||
<toolbarseparator id="downloadsFooterButtonsSplitter"
|
||||
class="downloadsDropmarkerSplitter"/>
|
||||
<button id="downloadsFooterDropmarker"
|
||||
class="plain downloadsPanelFooterButton downloadsDropmarker"
|
||||
type="menu">
|
||||
<menupopup id="downloadSubPanel"
|
||||
onpopupshowing="DownloadsPanel.onFooterPopupShowing(event);"
|
||||
onpopuphidden="DownloadsPanel.onFooterPopupHidden(event);"
|
||||
position="after_end">
|
||||
<menuitem id="downloadsDropdownItemClearList"
|
||||
command="downloadsCmd_clearList"
|
||||
label="&cmd.clearList2.label;"/>
|
||||
<menuitem id="downloadsDropdownItemOpenDownloadsFolder"
|
||||
oncommand="DownloadsPanel.openDownloadsFolder();"
|
||||
label="&openDownloadsFolder.label;"/>
|
||||
</menupopup>
|
||||
</button>
|
||||
</hbox>
|
||||
</stack>
|
||||
</vbox>
|
||||
</panelview>
|
||||
|
||||
|
|
|
@ -7,3 +7,4 @@ support-files =
|
|||
|
||||
[browser_dummy.js]
|
||||
skip-if = true
|
||||
[browser_localStorageIsolation.js]
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* Bug 1264567 - A test case for localStorage isolation.
|
||||
*/
|
||||
|
||||
const TEST_PAGE = "http://mochi.test:8888/browser/browser/components/" +
|
||||
"originattributes/test/browser/file_firstPartyBasic.html";
|
||||
|
||||
// Use a random key so we don't access it in later tests.
|
||||
const key = Math.random().toString();
|
||||
|
||||
// Define the testing function
|
||||
function* doTest(aBrowser) {
|
||||
return yield ContentTask.spawn(aBrowser, key, function (key) {
|
||||
let value = content.localStorage.getItem(key);
|
||||
if (value === null) {
|
||||
// No value is found, so we create one.
|
||||
value = Math.random().toString();
|
||||
content.localStorage.setItem(key, value);
|
||||
}
|
||||
return value;
|
||||
});
|
||||
}
|
||||
|
||||
IsolationTestTools.runTests(TEST_PAGE, doTest);
|
|
@ -176,7 +176,7 @@ this.IsolationTestTools = {
|
|||
add_task(function* addTaskForIsolationTests() {
|
||||
let testSettings = [
|
||||
{ mode: TEST_MODE_FIRSTPARTY,
|
||||
skip: false,
|
||||
skip: true,
|
||||
prefs: [["privacy.firstparty.isolate", true]]
|
||||
},
|
||||
{ mode: TEST_MODE_NO_ISOLATION,
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#add-on signing is checked but not enforced
|
||||
MOZ_REQUIRE_SIGNING=0
|
||||
ac_add_options --with-branding=browser/branding/unofficial
|
||||
ac_add_options --enable-update-channel=default
|
||||
|
||||
# Need this to prevent name conflicts with the normal nightly build packages
|
||||
export MOZ_PKG_SPECIAL=add-on-devel
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#add-on signing is checked but not enforced
|
||||
MOZ_REQUIRE_SIGNING=0
|
||||
ac_add_options --with-branding=browser/branding/unofficial
|
||||
ac_add_options --enable-update-channel=default
|
||||
|
||||
# Need this to prevent name conflicts with the normal nightly build packages
|
||||
export MOZ_PKG_SPECIAL=add-on-devel
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#add-on signing is checked but not enforced
|
||||
MOZ_REQUIRE_SIGNING=0
|
||||
ac_add_options --with-branding=browser/branding/unofficial
|
||||
ac_add_options --enable-update-channel=default
|
||||
|
||||
# Need this to prevent name conflicts with the normal nightly build packages
|
||||
export MOZ_PKG_SPECIAL=add-on-devel
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#add-on signing is checked but not enforced
|
||||
MOZ_REQUIRE_SIGNING=0
|
||||
ac_add_options --with-branding=browser/branding/unofficial
|
||||
ac_add_options --enable-update-channel=default
|
||||
|
||||
#Need this to prevent name conflicts with the normal nightly build packages
|
||||
export MOZ_PKG_SPECIAL=add-on-devel
|
||||
|
|
|
@ -94,7 +94,7 @@ toolbarseparator.downloadsDropmarkerSplitter {
|
|||
}
|
||||
|
||||
#downloadsFooter:hover toolbarseparator.downloadsDropmarkerSplitter,
|
||||
#downloadsFooter toolbarseparator.downloadsDropmarkerSplitterExtend {
|
||||
#downloadsFooter[showingdropdown] toolbarseparator {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ support-files =
|
|||
[browser_toolbox_highlight.js]
|
||||
[browser_toolbox_hosts.js]
|
||||
[browser_toolbox_hosts_size.js]
|
||||
[browser_toolbox_hosts_telemetry.js]
|
||||
[browser_toolbox_keyboard_navigation.js]
|
||||
skip-if = os == "mac" # Full keyboard navigation on OSX only works if Full Keyboard Access setting is set to All Control in System Keyboard Preferences
|
||||
[browser_toolbox_minimize.js]
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {Toolbox} = require("devtools/client/framework/toolbox");
|
||||
const {SIDE, BOTTOM, WINDOW} = Toolbox.HostType;
|
||||
|
||||
const URL = "data:text/html;charset=utf8,browser_toolbox_hosts_telemetry.js";
|
||||
|
||||
function getHostHistogram() {
|
||||
return Services.telemetry.getHistogramById("DEVTOOLS_TOOLBOX_HOST");
|
||||
}
|
||||
|
||||
add_task(function* () {
|
||||
// Reset it to make counting easier
|
||||
getHostHistogram().clear();
|
||||
|
||||
info("Create a test tab and open the toolbox");
|
||||
let tab = yield addTab(URL);
|
||||
let target = TargetFactory.forTab(tab);
|
||||
let toolbox = yield gDevTools.showToolbox(target, "webconsole");
|
||||
|
||||
yield changeToolboxHost(toolbox);
|
||||
yield checkResults();
|
||||
yield toolbox.destroy();
|
||||
|
||||
toolbox = target = null;
|
||||
gBrowser.removeCurrentTab();
|
||||
|
||||
// Cleanup
|
||||
getHostHistogram().clear();
|
||||
});
|
||||
|
||||
function* changeToolboxHost(toolbox) {
|
||||
info("Switch toolbox host");
|
||||
yield toolbox.switchHost(SIDE);
|
||||
yield toolbox.switchHost(WINDOW);
|
||||
yield toolbox.switchHost(BOTTOM);
|
||||
yield toolbox.switchHost(SIDE);
|
||||
yield toolbox.switchHost(WINDOW);
|
||||
yield toolbox.switchHost(BOTTOM);
|
||||
}
|
||||
|
||||
function checkResults() {
|
||||
let counts = getHostHistogram().snapshot().counts;
|
||||
is(counts[0], 3, "Toolbox HostType bottom has 3 successful entries");
|
||||
is(counts[1], 2, "Toolbox HostType side has 2 successful entries");
|
||||
is(counts[2], 2, "Toolbox HostType window has 2 successful entries");
|
||||
}
|
|
@ -504,3 +504,50 @@ var closeToolbox = Task.async(function* () {
|
|||
let target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
yield gDevTools.closeToolbox(target);
|
||||
});
|
||||
|
||||
/**
|
||||
* Load the Telemetry utils, then stub Telemetry.prototype.log and
|
||||
* Telemetry.prototype.logKeyed in order to record everything that's logged in
|
||||
* it.
|
||||
* Store all recordings in Telemetry.telemetryInfo.
|
||||
* @return {Telemetry}
|
||||
*/
|
||||
function loadTelemetryAndRecordLogs() {
|
||||
info("Mock the Telemetry log function to record logged information");
|
||||
|
||||
let Telemetry = require("devtools/client/shared/telemetry");
|
||||
Telemetry.prototype.telemetryInfo = {};
|
||||
Telemetry.prototype._oldlog = Telemetry.prototype.log;
|
||||
Telemetry.prototype.log = function (histogramId, value) {
|
||||
if (!this.telemetryInfo) {
|
||||
// Telemetry instance still in use after stopRecordingTelemetryLogs
|
||||
return;
|
||||
}
|
||||
if (histogramId) {
|
||||
if (!this.telemetryInfo[histogramId]) {
|
||||
this.telemetryInfo[histogramId] = [];
|
||||
}
|
||||
this.telemetryInfo[histogramId].push(value);
|
||||
}
|
||||
};
|
||||
Telemetry.prototype._oldlogKeyed = Telemetry.prototype.logKeyed;
|
||||
Telemetry.prototype.logKeyed = function (histogramId, key, value) {
|
||||
this.log(`${histogramId}|${key}`, value);
|
||||
};
|
||||
|
||||
return Telemetry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop recording the Telemetry logs and put back the utils as it was before.
|
||||
* @param {Telemetry} Required Telemetry
|
||||
* Telemetry object that needs to be stopped.
|
||||
*/
|
||||
function stopRecordingTelemetryLogs(Telemetry) {
|
||||
info("Stopping Telemetry");
|
||||
Telemetry.prototype.log = Telemetry.prototype._oldlog;
|
||||
Telemetry.prototype.logKeyed = Telemetry.prototype._oldlogKeyed;
|
||||
delete Telemetry.prototype._oldlog;
|
||||
delete Telemetry.prototype._oldlogKeyed;
|
||||
delete Telemetry.prototype.telemetryInfo;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ const SPLITCONSOLE_ENABLED_PREF = "devtools.toolbox.splitconsoleEnabled";
|
|||
const SPLITCONSOLE_HEIGHT_PREF = "devtools.toolbox.splitconsoleHeight";
|
||||
const OS_HISTOGRAM = "DEVTOOLS_OS_ENUMERATED_PER_USER";
|
||||
const OS_IS_64_BITS = "DEVTOOLS_OS_IS_64_BITS_PER_USER";
|
||||
const HOST_HISTOGRAM = "DEVTOOLS_TOOLBOX_HOST";
|
||||
const SCREENSIZE_HISTOGRAM = "DEVTOOLS_SCREEN_RESOLUTION_ENUMERATED_PER_USER";
|
||||
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
const { SourceMapService } = require("./source-map-service");
|
||||
|
@ -488,6 +489,17 @@ Toolbox.prototype = {
|
|||
return this.browserRequire("devtools/client/shared/vendor/react-dom");
|
||||
},
|
||||
|
||||
// Return HostType id for telemetry
|
||||
_getTelemetryHostId: function () {
|
||||
switch (this.hostType) {
|
||||
case Toolbox.HostType.BOTTOM: return 0;
|
||||
case Toolbox.HostType.SIDE: return 1;
|
||||
case Toolbox.HostType.WINDOW: return 2;
|
||||
case Toolbox.HostType.CUSTOM: return 3;
|
||||
default: return 9;
|
||||
}
|
||||
},
|
||||
|
||||
_pingTelemetry: function () {
|
||||
this._telemetry.toolOpened("toolbox");
|
||||
|
||||
|
@ -495,6 +507,7 @@ Toolbox.prototype = {
|
|||
this._telemetry.logOncePerBrowserVersion(OS_IS_64_BITS,
|
||||
Services.appinfo.is64Bit ? 1 : 0);
|
||||
this._telemetry.logOncePerBrowserVersion(SCREENSIZE_HISTOGRAM, system.getScreenDimensions());
|
||||
this._telemetry.log(HOST_HISTOGRAM, this._getTelemetryHostId());
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1836,6 +1849,8 @@ Toolbox.prototype = {
|
|||
this.focusTool(this.currentToolId, true);
|
||||
|
||||
this.emit("host-changed");
|
||||
|
||||
this._telemetry.log(HOST_HISTOGRAM, this._getTelemetryHostId());
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
<script type="application/javascript;version=1.8"
|
||||
src="chrome://devtools/content/shared/theme-switching.js"/>
|
||||
|
||||
<box flex="1" class="devtools-responsive-container theme-body">
|
||||
<vbox flex="1" class="devtools-main-content">
|
||||
<html:div id="inspector-toolbar"
|
||||
|
|
|
@ -81,6 +81,8 @@ ToolSidebar.prototype = {
|
|||
"devtools/client/shared/components/tabs/tabbar"));
|
||||
|
||||
let sidebar = Tabbar({
|
||||
toolbox: this._toolPanel._toolbox,
|
||||
showAllTabsMenu: true,
|
||||
onSelect: this.handleSelectionChange.bind(this),
|
||||
});
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ define(function (require, exports, module) {
|
|||
if (this.props.objectLink) {
|
||||
return this.props.objectLink({
|
||||
object: grip
|
||||
}, grip.class);
|
||||
}, grip.class + " ");
|
||||
}
|
||||
return "";
|
||||
},
|
||||
|
|
|
@ -36,7 +36,7 @@ define(function (require, exports, module) {
|
|||
return span({className: "objectBox"},
|
||||
this.props.objectLink({
|
||||
object: grip
|
||||
}, grip.class)
|
||||
}, grip.class + " ")
|
||||
);
|
||||
}
|
||||
return "";
|
||||
|
|
|
@ -30,7 +30,7 @@ define(function (require, exports, module) {
|
|||
if (this.props.objectLink) {
|
||||
return this.props.objectLink({
|
||||
object: grip
|
||||
}, "function");
|
||||
}, "function ");
|
||||
}
|
||||
return "";
|
||||
},
|
||||
|
|
|
@ -38,7 +38,7 @@ define(function (require, exports, module) {
|
|||
if (this.props.mode != "tiny") {
|
||||
return objectLink({
|
||||
object: object
|
||||
}, object.class);
|
||||
}, object.class + " ");
|
||||
}
|
||||
return "";
|
||||
},
|
||||
|
|
|
@ -34,7 +34,7 @@ define(function (require, exports, module) {
|
|||
if (this.props.objectLink) {
|
||||
return this.props.objectLink({
|
||||
object: object
|
||||
}, object.class);
|
||||
}, object.class + " ");
|
||||
}
|
||||
return object.class || "Object";
|
||||
},
|
||||
|
|
|
@ -31,7 +31,7 @@ define(function (require, exports, module) {
|
|||
return span({className: "objectBox"},
|
||||
this.props.objectLink({
|
||||
object: grip
|
||||
}, this.getType(grip))
|
||||
}, this.getType(grip) + " ")
|
||||
);
|
||||
}
|
||||
return "";
|
||||
|
|
|
@ -31,7 +31,7 @@ define(function (require, exports, module) {
|
|||
return span({className: "objectBox"},
|
||||
this.props.objectLink({
|
||||
object: grip
|
||||
}, this.getType(grip))
|
||||
}, this.getType(grip) + " ")
|
||||
);
|
||||
}
|
||||
return "";
|
||||
|
|
|
@ -30,7 +30,7 @@ define(function (require, exports, module) {
|
|||
if (this.props.objectLink) {
|
||||
return this.props.objectLink({
|
||||
object: object
|
||||
}, object.class);
|
||||
}, object.class + " ");
|
||||
}
|
||||
return "Object";
|
||||
},
|
||||
|
|
|
@ -72,6 +72,7 @@ define(function (require, exports, module) {
|
|||
propTypes: {
|
||||
object: React.PropTypes.any,
|
||||
defaultRep: React.PropTypes.object,
|
||||
mode: React.PropTypes.string
|
||||
},
|
||||
|
||||
render: function () {
|
||||
|
|
|
@ -32,7 +32,7 @@ define(function (require, exports, module) {
|
|||
return DOM.span({className: "objectBox"},
|
||||
this.props.objectLink({
|
||||
object: grip
|
||||
}, title)
|
||||
}, title + " ")
|
||||
);
|
||||
}
|
||||
return title;
|
||||
|
|
|
@ -31,7 +31,7 @@ define(function (require, exports, module) {
|
|||
return DOM.span({className: "objectBox"},
|
||||
this.props.objectLink({
|
||||
object: grip
|
||||
}, grip.class)
|
||||
}, grip.class + " ")
|
||||
);
|
||||
}
|
||||
return "";
|
||||
|
|
|
@ -34,8 +34,11 @@
|
|||
}
|
||||
|
||||
/* The tab takes entire horizontal space and individual tabs
|
||||
should stretch accordingly. Use flexbox for the behavior. */
|
||||
should stretch accordingly. Use flexbox for the behavior.
|
||||
Use also `overflow: hidden` so, 'overflow' and 'underflow'
|
||||
events are fired (it's utilized by the all-tabs-menu). */
|
||||
.tabs .tabs-navigation .tabs-menu {
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
const { DOM, createClass, PropTypes, createFactory } = require("devtools/client/shared/vendor/react");
|
||||
const Tabs = createFactory(require("devtools/client/shared/components/tabs/tabs").Tabs);
|
||||
|
||||
const Menu = require("devtools/client/framework/menu");
|
||||
const MenuItem = require("devtools/client/framework/menu-item");
|
||||
|
||||
// Shortcuts
|
||||
const { div } = DOM;
|
||||
|
||||
|
@ -20,6 +23,14 @@ let Tabbar = createClass({
|
|||
|
||||
propTypes: {
|
||||
onSelect: PropTypes.func,
|
||||
showAllTabsMenu: PropTypes.bool,
|
||||
toolbox: PropTypes.object,
|
||||
},
|
||||
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
showAllTabsMenu: false,
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function () {
|
||||
|
@ -125,6 +136,33 @@ let Tabbar = createClass({
|
|||
}
|
||||
},
|
||||
|
||||
onAllTabsMenuClick: function (event) {
|
||||
let menu = new Menu();
|
||||
let target = event.target;
|
||||
|
||||
// Generate list of menu items from the list of tabs.
|
||||
this.state.tabs.forEach(tab => {
|
||||
menu.append(new MenuItem({
|
||||
label: tab.title,
|
||||
type: "checkbox",
|
||||
checked: this.getCurrentTabId() == tab.id,
|
||||
click: () => this.select(tab.id),
|
||||
}));
|
||||
});
|
||||
|
||||
// Show a drop down menu with frames.
|
||||
// XXX Missing menu API for specifying target (anchor)
|
||||
// and relative position to it. See also:
|
||||
// https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/Method/openPopup
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1274551
|
||||
let rect = target.getBoundingClientRect();
|
||||
let screenX = target.ownerDocument.defaultView.mozInnerScreenX;
|
||||
let screenY = target.ownerDocument.defaultView.mozInnerScreenY;
|
||||
menu.popup(rect.left + screenX, rect.bottom + screenY, this.props.toolbox);
|
||||
|
||||
return menu;
|
||||
},
|
||||
|
||||
// Rendering
|
||||
|
||||
renderTab: function (tab) {
|
||||
|
@ -148,6 +186,8 @@ let Tabbar = createClass({
|
|||
return (
|
||||
div({className: "devtools-sidebar-tabs"},
|
||||
Tabs({
|
||||
onAllTabsMenuClick: this.onAllTabsMenuClick,
|
||||
showAllTabsMenu: this.props.showAllTabsMenu,
|
||||
tabActive: this.state.activeTab,
|
||||
onAfterChange: this.onTabChanged},
|
||||
tabs
|
||||
|
|
|
@ -39,6 +39,27 @@
|
|||
height: 100%;
|
||||
}
|
||||
|
||||
.tabs .all-tabs-menu {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 15px;
|
||||
height: 100%;
|
||||
border-style: solid;
|
||||
border-width: 0;
|
||||
border-inline-start-width: 1px;
|
||||
border-color: var(--theme-splitter-color);
|
||||
background: url("chrome://devtools/skin/images/dropmarker.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-color: var(--theme-tab-toolbar-background);
|
||||
}
|
||||
|
||||
.tabs .all-tabs-menu:-moz-locale-dir(rtl) {
|
||||
right: unset;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/* Light Theme */
|
||||
|
||||
.theme-dark .tabs,
|
||||
|
@ -48,6 +69,7 @@
|
|||
|
||||
.theme-dark .tabs .tabs-navigation,
|
||||
.theme-light .tabs .tabs-navigation {
|
||||
position: relative;
|
||||
border-bottom: 1px solid var(--theme-splitter-color);
|
||||
background: var(--theme-tab-toolbar-background);
|
||||
}
|
||||
|
|
|
@ -47,12 +47,15 @@ define(function (require, exports, module) {
|
|||
children: React.PropTypes.oneOfType([
|
||||
React.PropTypes.array,
|
||||
React.PropTypes.element
|
||||
]).isRequired
|
||||
]).isRequired,
|
||||
showAllTabsMenu: React.PropTypes.bool,
|
||||
onAllTabsMenuClick: React.PropTypes.func,
|
||||
},
|
||||
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
tabActive: 0
|
||||
tabActive: 0,
|
||||
showAllTabsMenu: false,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -69,6 +72,9 @@ define(function (require, exports, module) {
|
|||
// E.g. in case of an iframe being used as a tab-content
|
||||
// we want the iframe to stay in the DOM.
|
||||
created: [],
|
||||
|
||||
// True if tabs can't fit into available horizontal space.
|
||||
overflow: false,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -76,6 +82,15 @@ define(function (require, exports, module) {
|
|||
let node = findDOMNode(this);
|
||||
node.addEventListener("keydown", this.onKeyDown, false);
|
||||
|
||||
// Register overflow listeners to manage visibility
|
||||
// of all-tabs-menu. This menu is displayed when there
|
||||
// is not enough h-space to render all tabs.
|
||||
// It allows the user to select a tab even if it's hidden.
|
||||
if (this.props.showAllTabsMenu) {
|
||||
node.addEventListener("overflow", this.onOverflow, false);
|
||||
node.addEventListener("underflow", this.onUnderflow, false);
|
||||
}
|
||||
|
||||
let index = this.state.tabActive;
|
||||
if (this.props.onMount) {
|
||||
this.props.onMount(index);
|
||||
|
@ -83,7 +98,9 @@ define(function (require, exports, module) {
|
|||
},
|
||||
|
||||
componentWillReceiveProps: function (newProps) {
|
||||
if (newProps.tabActive) {
|
||||
// Check type of 'tabActive' props to see if it's valid
|
||||
// (it's 0-based index).
|
||||
if (typeof newProps.tabActive == "number") {
|
||||
let created = [...this.state.created];
|
||||
created[newProps.tabActive] = true;
|
||||
|
||||
|
@ -97,10 +114,31 @@ define(function (require, exports, module) {
|
|||
componentWillUnmount: function () {
|
||||
let node = findDOMNode(this);
|
||||
node.removeEventListener("keydown", this.onKeyDown, false);
|
||||
|
||||
if (this.props.showAllTabsMenu) {
|
||||
node.removeEventListener("overflow", this.onOverflow, false);
|
||||
node.removeEventListener("underflow", this.onUnderflow, false);
|
||||
}
|
||||
},
|
||||
|
||||
// DOM Events
|
||||
|
||||
onOverflow: function (event) {
|
||||
if (event.target.classList.contains("tabs-menu")) {
|
||||
this.setState({
|
||||
overflow: true
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
onUnderflow: function (event) {
|
||||
if (event.target.classList.contains("tabs-menu")) {
|
||||
this.setState({
|
||||
overflow: false
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
onKeyDown: function (event) {
|
||||
// Bail out if the focus isn't on a tab.
|
||||
if (!event.target.closest(".tabs-menu-item")) {
|
||||
|
@ -129,6 +167,12 @@ define(function (require, exports, module) {
|
|||
event.preventDefault();
|
||||
},
|
||||
|
||||
onAllTabsMenuClick: function (event) {
|
||||
if (this.props.onAllTabsMenuClick) {
|
||||
this.props.onAllTabsMenuClick(event);
|
||||
}
|
||||
},
|
||||
|
||||
// API
|
||||
|
||||
setActive: function (index) {
|
||||
|
@ -218,11 +262,21 @@ define(function (require, exports, module) {
|
|||
);
|
||||
});
|
||||
|
||||
// Display the menu only if there is not enough horizontal
|
||||
// space for all tabs (and overflow happened).
|
||||
let allTabsMenu = this.state.overflow ? (
|
||||
DOM.div({
|
||||
className: "all-tabs-menu",
|
||||
onClick: this.props.onAllTabsMenuClick
|
||||
})
|
||||
) : null;
|
||||
|
||||
return (
|
||||
DOM.nav({className: "tabs-navigation"},
|
||||
DOM.ul({className: "tabs-menu", role: "tablist"},
|
||||
tabs
|
||||
)
|
||||
),
|
||||
allTabsMenu
|
||||
)
|
||||
);
|
||||
},
|
||||
|
|
|
@ -29,6 +29,7 @@ support-files =
|
|||
[test_sidebar_toggle.html]
|
||||
[test_stack-trace.html]
|
||||
[test_tabs_accessibility.html]
|
||||
[test_tabs_menu.html]
|
||||
[test_tree_01.html]
|
||||
[test_tree_02.html]
|
||||
[test_tree_03.html]
|
||||
|
|
|
@ -51,7 +51,7 @@ window.onload = Task.async(function* () {
|
|||
is(renderedRep.type, GripArray.rep, `Rep correctly selects ${GripArray.rep.displayName}`);
|
||||
|
||||
// Test rendering
|
||||
const defaultOutput = `Array[]`;
|
||||
const defaultOutput = `Array []`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
|
@ -79,7 +79,7 @@ window.onload = Task.async(function* () {
|
|||
// Test array: `[1, "foo", {}]`;
|
||||
const testName = "testMaxProps";
|
||||
|
||||
const defaultOutput = `Array[ 1, "foo", Object ]`;
|
||||
const defaultOutput = `Array [ 1, "foo", Object ]`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
|
@ -107,7 +107,7 @@ window.onload = Task.async(function* () {
|
|||
// Test array = `["test string"…] //4 items`
|
||||
const testName = "testMoreThanShortMaxProps";
|
||||
|
||||
const defaultOutput = `Array[ ${Array(maxLength.short).fill("\"test string\"").join(", ")}, 1 more… ]`;
|
||||
const defaultOutput = `Array [ ${Array(maxLength.short).fill("\"test string\"").join(", ")}, 1 more… ]`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
|
@ -124,7 +124,7 @@ window.onload = Task.async(function* () {
|
|||
},
|
||||
{
|
||||
mode: "long",
|
||||
expectedOutput: `Array[ ${Array(maxLength.short + 1).fill("\"test string\"").join(", ")} ]`,
|
||||
expectedOutput: `Array [ ${Array(maxLength.short + 1).fill("\"test string\"").join(", ")} ]`,
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -135,8 +135,8 @@ window.onload = Task.async(function* () {
|
|||
// Test array = `["test string"…] //301 items`
|
||||
const testName = "testMoreThanLongMaxProps";
|
||||
|
||||
const defaultShortOutput = `Array[ ${Array(maxLength.short).fill("\"test string\"").join(", ")}, ${maxLength.long + 1 - maxLength.short} more… ]`;
|
||||
const defaultLongOutput = `Array[ ${Array(maxLength.long).fill("\"test string\"").join(", ")}, 1 more… ]`;
|
||||
const defaultShortOutput = `Array [ ${Array(maxLength.short).fill("\"test string\"").join(", ")}, ${maxLength.long + 1 - maxLength.short} more… ]`;
|
||||
const defaultLongOutput = `Array [ ${Array(maxLength.long).fill("\"test string\"").join(", ")}, 1 more… ]`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
|
@ -164,7 +164,7 @@ window.onload = Task.async(function* () {
|
|||
// Test array = `let a = []; a = [a]`
|
||||
const testName = "testRecursiveArray";
|
||||
|
||||
const defaultOutput = `Array[ [1] ]`;
|
||||
const defaultOutput = `Array [ [1] ]`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
|
@ -191,8 +191,8 @@ window.onload = Task.async(function* () {
|
|||
function testPreviewLimit() {
|
||||
const testName = "testPreviewLimit";
|
||||
|
||||
const shortOutput = `Array[ 0, 1, 2, 8 more… ]`;
|
||||
const defaultOutput = `Array[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1 more… ]`;
|
||||
const shortOutput = `Array [ 0, 1, 2, 8 more… ]`;
|
||||
const defaultOutput = `Array [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1 more… ]`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
|
@ -219,7 +219,7 @@ window.onload = Task.async(function* () {
|
|||
function testNamedNodeMap() {
|
||||
const testName = "testNamedNodeMap";
|
||||
|
||||
const defaultOutput = `NamedNodeMap[ class="myclass", cellpadding="7", border="3" ]`;
|
||||
const defaultOutput = `NamedNodeMap [ class="myclass", cellpadding="7", border="3" ]`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html class="theme-light">
|
||||
<!--
|
||||
Test all-tabs menu.
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Tabs component All-tabs menu test</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
|
||||
<link rel="stylesheet" type="text/css" href="resource://devtools/client/themes/variables.css">
|
||||
<link rel="stylesheet" type="text/css" href="resource://devtools/client/themes/common.css">
|
||||
<link rel="stylesheet" type="text/css" href="resource://devtools/client/themes/light-theme.css">
|
||||
<link rel="stylesheet" type="text/css" href="resource://devtools/client/shared/components/tabs/tabs.css">
|
||||
<link rel="stylesheet" type="text/css" href="resource://devtools/client/shared/components/tabs/tabbar.css">
|
||||
<link rel="stylesheet" type="text/css" href="resource://devtools/client/inspector/components/side-panel.css">
|
||||
<link rel="stylesheet" type="text/css" href="resource://devtools/client/inspector/components/inspector-tab-panel.css">
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script src="head.js" type="application/javascript;version=1.8"></script>
|
||||
<script type="application/javascript;version=1.8">
|
||||
window.onload = Task.async(function* () {
|
||||
try {
|
||||
const ReactDOM = browserRequire("devtools/client/shared/vendor/react-dom");
|
||||
const React = browserRequire("devtools/client/shared/vendor/react");
|
||||
const Tabbar = React.createFactory(browserRequire("devtools/client/shared/components/tabs/tabbar"));
|
||||
|
||||
// Create container for the TabBar. Set smaller width
|
||||
// to ensure that tabs won't fit and the all-tabs menu
|
||||
// needs to appear.
|
||||
const tabBarBox = document.createElement("div");
|
||||
tabBarBox.style.width = "200px";
|
||||
tabBarBox.style.height = "200px";
|
||||
tabBarBox.style.border = "1px solid lightgray";
|
||||
document.body.appendChild(tabBarBox);
|
||||
|
||||
// Render the tab-bar.
|
||||
const tabbar = Tabbar({
|
||||
showAllTabsMenu: true,
|
||||
});
|
||||
|
||||
const tabbarReact = ReactDOM.render(tabbar, tabBarBox);
|
||||
|
||||
// Test panel.
|
||||
let TabPanel = React.createFactory(React.createClass({
|
||||
render: function () {
|
||||
return React.DOM.div({}, "content");
|
||||
}
|
||||
}));
|
||||
|
||||
// Create a few panels.
|
||||
yield addTabWithPanel(1);
|
||||
yield addTabWithPanel(2);
|
||||
yield addTabWithPanel(3);
|
||||
yield addTabWithPanel(4);
|
||||
yield addTabWithPanel(5);
|
||||
|
||||
// Make sure the all-tabs menu is there.
|
||||
const allTabsMenu = tabBarBox.querySelector(".all-tabs-menu");
|
||||
ok(allTabsMenu, "All-tabs menu must be rendered");
|
||||
|
||||
function addTabWithPanel(tabId) {
|
||||
return setState(tabbarReact, Object.assign({}, tabbarReact.state, {
|
||||
tabs: tabbarReact.state.tabs.concat({id: `${tabId}`,
|
||||
title: `tab-${tabId}`, panel: TabPanel}),
|
||||
}));
|
||||
}
|
||||
} catch(e) {
|
||||
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
|
||||
} finally {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -118,44 +118,6 @@ Task.async(function* (type = "bottom", src = "data:text/html;charset=utf-8,") {
|
|||
return [host, iframe.contentWindow, iframe.contentDocument];
|
||||
});
|
||||
|
||||
/**
|
||||
* Load the Telemetry utils, then stub Telemetry.prototype.log in order to
|
||||
* record everything that's logged in it.
|
||||
* Store all recordings on Telemetry.telemetryInfo.
|
||||
* @return {Telemetry}
|
||||
*/
|
||||
function loadTelemetryAndRecordLogs() {
|
||||
info("Mock the Telemetry log function to record logged information");
|
||||
|
||||
let Telemetry = require("devtools/client/shared/telemetry");
|
||||
Telemetry.prototype.telemetryInfo = {};
|
||||
Telemetry.prototype._oldlog = Telemetry.prototype.log;
|
||||
Telemetry.prototype.log = function (histogramId, value) {
|
||||
if (!this.telemetryInfo) {
|
||||
// Can be removed when Bug 992911 lands (see Bug 1011652 Comment 10)
|
||||
return;
|
||||
}
|
||||
if (histogramId) {
|
||||
if (!this.telemetryInfo[histogramId]) {
|
||||
this.telemetryInfo[histogramId] = [];
|
||||
}
|
||||
|
||||
this.telemetryInfo[histogramId].push(value);
|
||||
}
|
||||
};
|
||||
|
||||
return Telemetry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop recording the Telemetry logs and put back the utils as it was before.
|
||||
*/
|
||||
function stopRecordingTelemetryLogs(Telemetry) {
|
||||
Telemetry.prototype.log = Telemetry.prototype._oldlog;
|
||||
delete Telemetry.prototype._oldlog;
|
||||
delete Telemetry.prototype.telemetryInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the correctness of the data recorded in Telemetry after
|
||||
* loadTelemetryAndRecordLogs was called.
|
||||
|
|
|
@ -688,7 +688,7 @@ CSSFilterEditorWidget.prototype = {
|
|||
this.filtersList.querySelector(".filter:last-of-type input");
|
||||
if (lastInput) {
|
||||
lastInput.focus();
|
||||
if (lastInput.type == "text") {
|
||||
if (lastInput.type === "text") {
|
||||
// move cursor to end of input
|
||||
const end = lastInput.value.length;
|
||||
lastInput.setSelectionRange(end, end);
|
||||
|
|
|
@ -367,6 +367,7 @@ tags = trackingprotection
|
|||
[browser_webconsole_output_dom_elements_02.js]
|
||||
skip-if = e10s # Bug 1042253 - webconsole e10s tests (Linux debug timeout)
|
||||
[browser_webconsole_output_dom_elements_03.js]
|
||||
skip-if = e10s # Bug 1241019
|
||||
[browser_webconsole_output_dom_elements_04.js]
|
||||
skip-if = e10s # Bug 1042253 - webconsole e10s tests (Linux debug timeout)
|
||||
[browser_webconsole_output_dom_elements_05.js]
|
||||
|
|
|
@ -97,7 +97,7 @@ var inputTests = [
|
|||
{
|
||||
input: "window.typedarray1",
|
||||
output: "Int32Array [ 1, 287, 8651, 40983, 8754 ]",
|
||||
printOutput: "[object Int32Array]",
|
||||
printOutput: "1,287,8651,40983,8754",
|
||||
inspectable: true,
|
||||
variablesViewLabel: "Int32Array[5]",
|
||||
},
|
||||
|
|
|
@ -802,7 +802,7 @@ function InvalidCommandError() {
|
|||
* or "Float32Array".
|
||||
*/
|
||||
function getConstructorName(obj) {
|
||||
return obj.toString().match(/\[object ([^\[\]]*)\]\]?$/)[1];
|
||||
return Object.prototype.toString.call(obj).match(/\[object ([^\[\]]*)\]\]?$/)[1];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -39,14 +39,14 @@ public:
|
|||
// This will call SwapElements on aArguments with an empty array.
|
||||
nsJSScriptTimeoutHandler(JSContext* aCx, nsGlobalWindow *aWindow,
|
||||
Function& aFunction,
|
||||
FallibleTArray<JS::Heap<JS::Value> >& aArguments,
|
||||
nsTArray<JS::Heap<JS::Value>>&& aArguments,
|
||||
ErrorResult& aError);
|
||||
nsJSScriptTimeoutHandler(JSContext* aCx, nsGlobalWindow *aWindow,
|
||||
const nsAString& aExpression, bool* aAllowEval,
|
||||
ErrorResult& aError);
|
||||
nsJSScriptTimeoutHandler(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
Function& aFunction,
|
||||
FallibleTArray<JS::Heap<JS::Value> >& aArguments);
|
||||
nsTArray<JS::Heap<JS::Value>>&& aArguments);
|
||||
nsJSScriptTimeoutHandler(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
const nsAString& aExpression);
|
||||
|
||||
|
@ -74,7 +74,7 @@ private:
|
|||
~nsJSScriptTimeoutHandler();
|
||||
|
||||
void Init(JSContext* aCx,
|
||||
FallibleTArray<JS::Heap<JS::Value>>& aArguments);
|
||||
nsTArray<JS::Heap<JS::Value>>&& aArguments);
|
||||
void Init(JSContext* aCx);
|
||||
|
||||
// filename, line number and JS language version string of the
|
||||
|
@ -82,7 +82,7 @@ private:
|
|||
nsCString mFileName;
|
||||
uint32_t mLineNo;
|
||||
uint32_t mColumn;
|
||||
nsTArray<JS::Heap<JS::Value> > mArgs;
|
||||
nsTArray<JS::Heap<JS::Value>> mArgs;
|
||||
|
||||
// The expression to evaluate or function to call. If mFunction is non-null
|
||||
// it should be used, else use mExpr.
|
||||
|
@ -209,7 +209,7 @@ nsJSScriptTimeoutHandler::nsJSScriptTimeoutHandler()
|
|||
nsJSScriptTimeoutHandler::nsJSScriptTimeoutHandler(JSContext* aCx,
|
||||
nsGlobalWindow *aWindow,
|
||||
Function& aFunction,
|
||||
FallibleTArray<JS::Heap<JS::Value>>& aArguments,
|
||||
nsTArray<JS::Heap<JS::Value>>&& aArguments,
|
||||
ErrorResult& aError)
|
||||
: mLineNo(0)
|
||||
, mColumn(0)
|
||||
|
@ -222,7 +222,7 @@ nsJSScriptTimeoutHandler::nsJSScriptTimeoutHandler(JSContext* aCx,
|
|||
return;
|
||||
}
|
||||
|
||||
Init(aCx, aArguments);
|
||||
Init(aCx, Move(aArguments));
|
||||
}
|
||||
|
||||
nsJSScriptTimeoutHandler::nsJSScriptTimeoutHandler(JSContext* aCx,
|
||||
|
@ -252,7 +252,7 @@ nsJSScriptTimeoutHandler::nsJSScriptTimeoutHandler(JSContext* aCx,
|
|||
nsJSScriptTimeoutHandler::nsJSScriptTimeoutHandler(JSContext* aCx,
|
||||
WorkerPrivate* aWorkerPrivate,
|
||||
Function& aFunction,
|
||||
FallibleTArray<JS::Heap<JS::Value>>& aArguments)
|
||||
nsTArray<JS::Heap<JS::Value>>&& aArguments)
|
||||
: mLineNo(0)
|
||||
, mColumn(0)
|
||||
, mFunction(&aFunction)
|
||||
|
@ -260,7 +260,7 @@ nsJSScriptTimeoutHandler::nsJSScriptTimeoutHandler(JSContext* aCx,
|
|||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
Init(aCx, aArguments);
|
||||
Init(aCx, Move(aArguments));
|
||||
}
|
||||
|
||||
nsJSScriptTimeoutHandler::nsJSScriptTimeoutHandler(JSContext* aCx,
|
||||
|
@ -283,10 +283,10 @@ nsJSScriptTimeoutHandler::~nsJSScriptTimeoutHandler()
|
|||
|
||||
void
|
||||
nsJSScriptTimeoutHandler::Init(JSContext* aCx,
|
||||
FallibleTArray<JS::Heap<JS::Value>>& aArguments)
|
||||
nsTArray<JS::Heap<JS::Value>>&& aArguments)
|
||||
{
|
||||
mozilla::HoldJSObjects(this);
|
||||
mArgs.SwapElements(aArguments);
|
||||
mArgs = Move(aArguments);
|
||||
|
||||
Init(aCx);
|
||||
}
|
||||
|
@ -321,14 +321,14 @@ NS_CreateJSTimeoutHandler(JSContext *aCx, nsGlobalWindow *aWindow,
|
|||
const Sequence<JS::Value>& aArguments,
|
||||
ErrorResult& aError)
|
||||
{
|
||||
FallibleTArray<JS::Heap<JS::Value> > args;
|
||||
nsTArray<JS::Heap<JS::Value>> args;
|
||||
if (!args.AppendElements(aArguments, fallible)) {
|
||||
aError.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<nsJSScriptTimeoutHandler> handler =
|
||||
new nsJSScriptTimeoutHandler(aCx, aWindow, aFunction, args, aError);
|
||||
new nsJSScriptTimeoutHandler(aCx, aWindow, aFunction, Move(args), aError);
|
||||
return aError.Failed() ? nullptr : handler.forget();
|
||||
}
|
||||
|
||||
|
@ -352,14 +352,14 @@ NS_CreateJSTimeoutHandler(JSContext *aCx, WorkerPrivate* aWorkerPrivate,
|
|||
const Sequence<JS::Value>& aArguments,
|
||||
ErrorResult& aError)
|
||||
{
|
||||
FallibleTArray<JS::Heap<JS::Value>> args;
|
||||
nsTArray<JS::Heap<JS::Value>> args;
|
||||
if (!args.AppendElements(aArguments, fallible)) {
|
||||
aError.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<nsJSScriptTimeoutHandler> handler =
|
||||
new nsJSScriptTimeoutHandler(aCx, aWorkerPrivate, aFunction, args);
|
||||
new nsJSScriptTimeoutHandler(aCx, aWorkerPrivate, aFunction, Move(args));
|
||||
return handler.forget();
|
||||
}
|
||||
|
||||
|
|
|
@ -243,7 +243,7 @@ nsLocation::GetURI(nsIURI** aURI, bool aGetInnermostURI)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsLocation::GetWritableURI(nsIURI** aURI)
|
||||
nsLocation::GetWritableURI(nsIURI** aURI, const nsACString* aNewRef)
|
||||
{
|
||||
*aURI = nullptr;
|
||||
|
||||
|
@ -254,7 +254,11 @@ nsLocation::GetWritableURI(nsIURI** aURI)
|
|||
return rv;
|
||||
}
|
||||
|
||||
return uri->Clone(aURI);
|
||||
if (!aNewRef) {
|
||||
return uri->Clone(aURI);
|
||||
}
|
||||
|
||||
return uri->CloneWithNewRef(*aNewRef, aURI);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -349,18 +353,13 @@ nsLocation::GetHash(nsAString& aHash)
|
|||
NS_IMETHODIMP
|
||||
nsLocation::SetHash(const nsAString& aHash)
|
||||
{
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = GetWritableURI(getter_AddRefs(uri));
|
||||
if (NS_FAILED(rv) || !uri) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_ConvertUTF16toUTF8 hash(aHash);
|
||||
if (hash.IsEmpty() || hash.First() != char16_t('#')) {
|
||||
hash.Insert(char16_t('#'), 0);
|
||||
}
|
||||
rv = uri->SetRef(hash);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = GetWritableURI(getter_AddRefs(uri), &hash);
|
||||
if (NS_FAILED(rv) || !uri) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -175,7 +175,9 @@ protected:
|
|||
// fetched from as the URI instead of the jar: uri itself. Pass in
|
||||
// true for aGetInnermostURI when that's the case.
|
||||
nsresult GetURI(nsIURI** aURL, bool aGetInnermostURI = false);
|
||||
nsresult GetWritableURI(nsIURI** aURL);
|
||||
nsresult GetWritableURI(nsIURI** aURL,
|
||||
// If not null, give it the new ref
|
||||
const nsACString* aNewRef = nullptr);
|
||||
nsresult SetURI(nsIURI* aURL, bool aReplace = false);
|
||||
nsresult SetHrefWithBase(const nsAString& aHref, nsIURI* aBase,
|
||||
bool aReplace);
|
||||
|
|
|
@ -5006,6 +5006,15 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
# create an empty array, which is all we need here.
|
||||
default = CGGeneric("%s.RawSetAs%s();\n" %
|
||||
(value, name))
|
||||
elif defaultValue.type.isEnum():
|
||||
name = getUnionMemberName(defaultValue.type)
|
||||
# Make sure we actually construct the thing inside the nullable.
|
||||
value = declLoc + (".SetValue()" if nullable else "")
|
||||
default = CGGeneric(
|
||||
"%s.RawSetAs%s() = %s::%s;\n" %
|
||||
(value, name,
|
||||
defaultValue.type.inner.identifier.name,
|
||||
getEnumValueName(defaultValue.value)))
|
||||
else:
|
||||
default = CGGeneric(
|
||||
handleDefaultStringValue(
|
||||
|
|
|
@ -3309,6 +3309,11 @@ def matchIntegerValueToType(value):
|
|||
|
||||
return None
|
||||
|
||||
class NoCoercionFoundError(WebIDLError):
|
||||
"""
|
||||
A class we use to indicate generic coercion failures because none of the
|
||||
types worked out in IDLValue.coerceToType.
|
||||
"""
|
||||
|
||||
class IDLValue(IDLObject):
|
||||
def __init__(self, location, type, value):
|
||||
|
@ -3336,8 +3341,18 @@ class IDLValue(IDLObject):
|
|||
# use the value's type when it is a default value of a
|
||||
# union, and the union cares about the exact float type.
|
||||
return IDLValue(self.location, subtype, coercedValue.value)
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
# Make sure to propagate out WebIDLErrors that are not the
|
||||
# generic "hey, we could not coerce to this type at all"
|
||||
# exception, because those are specific "coercion failed for
|
||||
# reason X" exceptions. Note that we want to swallow
|
||||
# non-WebIDLErrors here, because those can just happen if
|
||||
# "type" is not something that can have a default value at
|
||||
# all.
|
||||
if (isinstance(e, WebIDLError) and
|
||||
not isinstance(e, NoCoercionFoundError)):
|
||||
raise e
|
||||
|
||||
# If the type allows null, rerun this matching on the inner type, except
|
||||
# nullable enums. We handle those specially, because we want our
|
||||
# default string values to stay strings even when assigned to a nullable
|
||||
|
@ -3399,8 +3414,8 @@ class IDLValue(IDLObject):
|
|||
|
||||
return IDLValue(self.location, type, self.value)
|
||||
|
||||
raise WebIDLError("Cannot coerce type %s to type %s." %
|
||||
(self.type, type), [location])
|
||||
raise NoCoercionFoundError("Cannot coerce type %s to type %s." %
|
||||
(self.type, type), [location])
|
||||
|
||||
def _getDependentObjects(self):
|
||||
return set()
|
||||
|
|
|
@ -673,7 +673,7 @@ public:
|
|||
//void PassUnionWithInterfacesAndNullable(const TestInterfaceOrNullOrTestExternalInterface& arg);
|
||||
void PassUnionWithArrayBuffer(const ArrayBufferOrLong&);
|
||||
void PassUnionWithString(JSContext*, const StringOrObject&);
|
||||
//void PassUnionWithEnum(JSContext*, const TestEnumOrObject&);
|
||||
void PassUnionWithEnum(JSContext*, const SupportedTypeOrObject&);
|
||||
//void PassUnionWithCallback(JSContext*, const TestCallbackOrLong&);
|
||||
void PassUnionWithObject(JSContext*, const ObjectOrLong&);
|
||||
|
||||
|
@ -693,6 +693,9 @@ public:
|
|||
void PassUnionWithDefaultValue14(const DoubleOrByteString& arg);
|
||||
void PassUnionWithDefaultValue15(const DoubleOrByteString& arg);
|
||||
void PassUnionWithDefaultValue16(const DoubleOrByteString& arg);
|
||||
void PassUnionWithDefaultValue17(const DoubleOrSupportedType& arg);
|
||||
void PassUnionWithDefaultValue18(const DoubleOrSupportedType& arg);
|
||||
void PassUnionWithDefaultValue19(const DoubleOrSupportedType& arg);
|
||||
|
||||
void PassNullableUnionWithDefaultValue1(const Nullable<DoubleOrString>& arg);
|
||||
void PassNullableUnionWithDefaultValue2(const Nullable<DoubleOrString>& arg);
|
||||
|
@ -710,6 +713,10 @@ public:
|
|||
void PassNullableUnionWithDefaultValue14(const Nullable<DoubleOrByteString>& arg);
|
||||
void PassNullableUnionWithDefaultValue15(const Nullable<DoubleOrByteString>& arg);
|
||||
void PassNullableUnionWithDefaultValue16(const Nullable<DoubleOrByteString>& arg);
|
||||
void PassNullableUnionWithDefaultValue17(const Nullable<DoubleOrSupportedType>& arg);
|
||||
void PassNullableUnionWithDefaultValue18(const Nullable<DoubleOrSupportedType>& arg);
|
||||
void PassNullableUnionWithDefaultValue19(const Nullable<DoubleOrSupportedType>& arg);
|
||||
void PassNullableUnionWithDefaultValue20(const Nullable<DoubleOrSupportedType>& arg);
|
||||
|
||||
void PassSequenceOfUnions(const Sequence<OwningCanvasPatternOrCanvasGradient>&);
|
||||
void PassSequenceOfUnions2(JSContext*, const Sequence<OwningObjectOrLong>&);
|
||||
|
|
|
@ -644,7 +644,12 @@ interface TestInterface {
|
|||
//void passUnionWithSequence((sequence<object> or long) arg);
|
||||
void passUnionWithArrayBuffer((ArrayBuffer or long) arg);
|
||||
void passUnionWithString((DOMString or object) arg);
|
||||
//void passUnionWithEnum((TestEnum or object) arg);
|
||||
// Using an enum in a union. Note that we use some enum not declared in our
|
||||
// binding file, because UnionTypes.h will need to include the binding header
|
||||
// for this enum. Pick an enum from an interface that won't drag in too much
|
||||
// stuff.
|
||||
void passUnionWithEnum((SupportedType or object) arg);
|
||||
|
||||
// Trying to use a callback in a union won't include the test
|
||||
// headers, unfortunately, so won't compile.
|
||||
//void passUnionWithCallback((TestCallback or long) arg);
|
||||
|
@ -667,6 +672,9 @@ interface TestInterface {
|
|||
void passUnionWithDefaultValue14(optional (double or ByteString) arg = "");
|
||||
void passUnionWithDefaultValue15(optional (double or ByteString) arg = 1);
|
||||
void passUnionWithDefaultValue16(optional (double or ByteString) arg = 1.5);
|
||||
void passUnionWithDefaultValue17(optional (double or SupportedType) arg = "text/html");
|
||||
void passUnionWithDefaultValue18(optional (double or SupportedType) arg = 1);
|
||||
void passUnionWithDefaultValue19(optional (double or SupportedType) arg = 1.5);
|
||||
|
||||
void passNullableUnionWithDefaultValue1(optional (double or DOMString)? arg = "");
|
||||
void passNullableUnionWithDefaultValue2(optional (double or DOMString)? arg = 1);
|
||||
|
@ -684,6 +692,10 @@ interface TestInterface {
|
|||
void passNullableUnionWithDefaultValue14(optional (double or ByteString)? arg = 1);
|
||||
void passNullableUnionWithDefaultValue15(optional (double or ByteString)? arg = 1.5);
|
||||
void passNullableUnionWithDefaultValue16(optional (double or ByteString)? arg = null);
|
||||
void passNullableUnionWithDefaultValue17(optional (double or SupportedType)? arg = "text/html");
|
||||
void passNullableUnionWithDefaultValue18(optional (double or SupportedType)? arg = 1);
|
||||
void passNullableUnionWithDefaultValue19(optional (double or SupportedType)? arg = 1.5);
|
||||
void passNullableUnionWithDefaultValue20(optional (double or SupportedType)? arg = null);
|
||||
|
||||
void passSequenceOfUnions(sequence<(CanvasPattern or CanvasGradient)> arg);
|
||||
void passSequenceOfUnions2(sequence<(object or long)> arg);
|
||||
|
|
|
@ -479,7 +479,12 @@ interface TestExampleInterface {
|
|||
//void passUnionWithSequence((sequence<object> or long) arg);
|
||||
void passUnionWithArrayBuffer((ArrayBuffer or long) arg);
|
||||
void passUnionWithString((DOMString or object) arg);
|
||||
//void passUnionWithEnum((TestEnum or object) arg);
|
||||
// Using an enum in a union. Note that we use some enum not declared in our
|
||||
// binding file, because UnionTypes.h will need to include the binding header
|
||||
// for this enum. Pick an enum from an interface that won't drag in too much
|
||||
// stuff.
|
||||
void passUnionWithEnum((SupportedType or object) arg);
|
||||
|
||||
// Trying to use a callback in a union won't include the test
|
||||
// headers, unfortunately, so won't compile.
|
||||
// void passUnionWithCallback((TestCallback or long) arg);
|
||||
|
@ -502,6 +507,9 @@ interface TestExampleInterface {
|
|||
void passUnionWithDefaultValue14(optional (double or ByteString) arg = "");
|
||||
void passUnionWithDefaultValue15(optional (double or ByteString) arg = 1);
|
||||
void passUnionWithDefaultValue16(optional (double or ByteString) arg = 1.5);
|
||||
void passUnionWithDefaultValue17(optional (double or SupportedType) arg = "text/html");
|
||||
void passUnionWithDefaultValue18(optional (double or SupportedType) arg = 1);
|
||||
void passUnionWithDefaultValue19(optional (double or SupportedType) arg = 1.5);
|
||||
|
||||
void passNullableUnionWithDefaultValue1(optional (double or DOMString)? arg = "");
|
||||
void passNullableUnionWithDefaultValue2(optional (double or DOMString)? arg = 1);
|
||||
|
@ -519,6 +527,10 @@ interface TestExampleInterface {
|
|||
void passNullableUnionWithDefaultValue14(optional (double or ByteString)? arg = 1);
|
||||
void passNullableUnionWithDefaultValue15(optional (double or ByteString)? arg = 1.5);
|
||||
void passNullableUnionWithDefaultValue16(optional (double or ByteString)? arg = null);
|
||||
void passNullableUnionWithDefaultValue17(optional (double or SupportedType)? arg = "text/html");
|
||||
void passNullableUnionWithDefaultValue18(optional (double or SupportedType)? arg = 1);
|
||||
void passNullableUnionWithDefaultValue19(optional (double or SupportedType)? arg = 1.5);
|
||||
void passNullableUnionWithDefaultValue20(optional (double or SupportedType)? arg = null);
|
||||
|
||||
void passSequenceOfUnions(sequence<(CanvasPattern or CanvasGradient)> arg);
|
||||
void passSequenceOfUnions2(sequence<(object or long)> arg);
|
||||
|
|
|
@ -491,7 +491,12 @@ interface TestJSImplInterface {
|
|||
//void passUnionWithSequence((sequence<object> or long) arg);
|
||||
void passUnionWithArrayBuffer((ArrayBuffer or long) arg);
|
||||
void passUnionWithString((DOMString or object) arg);
|
||||
//void passUnionWithEnum((MyTestEnum or object) arg);
|
||||
// Using an enum in a union. Note that we use some enum not declared in our
|
||||
// binding file, because UnionTypes.h will need to include the binding header
|
||||
// for this enum. Pick an enum from an interface that won't drag in too much
|
||||
// stuff.
|
||||
void passUnionWithEnum((SupportedType or object) arg);
|
||||
|
||||
// Trying to use a callback in a union won't include the test
|
||||
// headers, unfortunately, so won't compile.
|
||||
// void passUnionWithCallback((MyTestCallback or long) arg);
|
||||
|
@ -514,6 +519,9 @@ interface TestJSImplInterface {
|
|||
void passUnionWithDefaultValue14(optional (double or ByteString) arg = "");
|
||||
void passUnionWithDefaultValue15(optional (double or ByteString) arg = 1);
|
||||
void passUnionWithDefaultValue16(optional (double or ByteString) arg = 1.5);
|
||||
void passUnionWithDefaultValue17(optional (double or SupportedType) arg = "text/html");
|
||||
void passUnionWithDefaultValue18(optional (double or SupportedType) arg = 1);
|
||||
void passUnionWithDefaultValue19(optional (double or SupportedType) arg = 1.5);
|
||||
|
||||
void passNullableUnionWithDefaultValue1(optional (double or DOMString)? arg = "");
|
||||
void passNullableUnionWithDefaultValue2(optional (double or DOMString)? arg = 1);
|
||||
|
@ -531,6 +539,10 @@ interface TestJSImplInterface {
|
|||
void passNullableUnionWithDefaultValue14(optional (double or ByteString)? arg = 1);
|
||||
void passNullableUnionWithDefaultValue15(optional (double or ByteString)? arg = 1.5);
|
||||
void passNullableUnionWithDefaultValue16(optional (double or ByteString)? arg = null);
|
||||
void passNullableUnionWithDefaultValue17(optional (double or SupportedType)? arg = "text/html");
|
||||
void passNullableUnionWithDefaultValue18(optional (double or SupportedType)? arg = 1);
|
||||
void passNullableUnionWithDefaultValue19(optional (double or SupportedType)? arg = 1.5);
|
||||
void passNullableUnionWithDefaultValue20(optional (double or SupportedType)? arg = null);
|
||||
|
||||
void passSequenceOfUnions(sequence<(CanvasPattern or CanvasGradient)> arg);
|
||||
void passSequenceOfUnions2(sequence<(object or long)> arg);
|
||||
|
|
|
@ -2477,7 +2477,18 @@ ContentChild::RecvActivateA11y()
|
|||
#ifdef ACCESSIBILITY
|
||||
// Start accessibility in content process if it's running in chrome
|
||||
// process.
|
||||
GetOrCreateAccService();
|
||||
GetOrCreateAccService(nsAccessibilityService::eMainProcess);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::RecvShutdownA11y()
|
||||
{
|
||||
#ifdef ACCESSIBILITY
|
||||
// Try to shutdown accessibility in content process if it's shutting down in
|
||||
// chrome process.
|
||||
MaybeShutdownAccService(nsAccessibilityService::eMainProcess);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -440,6 +440,7 @@ public:
|
|||
virtual bool RecvFlushMemory(const nsString& reason) override;
|
||||
|
||||
virtual bool RecvActivateA11y() override;
|
||||
virtual bool RecvShutdownA11y() override;
|
||||
|
||||
virtual bool RecvGarbageCollect() override;
|
||||
virtual bool RecvCycleCollect() override;
|
||||
|
|
|
@ -275,6 +275,10 @@ using namespace mozilla::system;
|
|||
#include "nsThread.h"
|
||||
#endif
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
#include "nsAccessibilityService.h"
|
||||
#endif
|
||||
|
||||
// For VP9Benchmark::sBenchmarkFpsPref
|
||||
#include "Benchmark.h"
|
||||
|
||||
|
@ -2843,19 +2847,24 @@ ContentParent::Observe(nsISupports* aSubject,
|
|||
}
|
||||
#endif
|
||||
#ifdef ACCESSIBILITY
|
||||
// Make sure accessibility is running in content process when accessibility
|
||||
// gets initiated in chrome process.
|
||||
else if (aData && (*aData == '1') &&
|
||||
!strcmp(aTopic, "a11y-init-or-shutdown")) {
|
||||
else if (aData && !strcmp(aTopic, "a11y-init-or-shutdown")) {
|
||||
if (*aData == '1') {
|
||||
// Make sure accessibility is running in content process when
|
||||
// accessibility gets initiated in chrome process.
|
||||
#if !defined(XP_WIN)
|
||||
Unused << SendActivateA11y();
|
||||
#else
|
||||
// On Windows we currently only enable a11y in the content process
|
||||
// for testing purposes.
|
||||
if (Preferences::GetBool(kForceEnableE10sPref, false)) {
|
||||
Unused << SendActivateA11y();
|
||||
}
|
||||
#else
|
||||
// On Windows we currently only enable a11y in the content process
|
||||
// for testing purposes.
|
||||
if (Preferences::GetBool(kForceEnableE10sPref, false)) {
|
||||
Unused << SendActivateA11y();
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
// If possible, shut down accessibility in content process when
|
||||
// accessibility gets shutdown in chrome process.
|
||||
Unused << SendShutdownA11y();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else if (!strcmp(aTopic, "app-theme-changed")) {
|
||||
|
|
|
@ -550,6 +550,11 @@ child:
|
|||
*/
|
||||
async ActivateA11y();
|
||||
|
||||
/**
|
||||
* Shutdown accessibility engine in content process (if not in use).
|
||||
*/
|
||||
async ShutdownA11y();
|
||||
|
||||
async AppInfo(nsCString version, nsCString buildID, nsCString name, nsCString UAName,
|
||||
nsCString ID, nsCString vendor);
|
||||
async AppInit();
|
||||
|
|
|
@ -347,6 +347,9 @@ function* test_basics() {
|
|||
serverQueue = connectedResult.queue;
|
||||
|
||||
// -- Attempt to send non-string data.
|
||||
// Restore the original behavior by replacing toString with
|
||||
// Object.prototype.toString. (bug 1121938)
|
||||
bigUint8Array.toString = Object.prototype.toString;
|
||||
is(clientSocket.send(bigUint8Array), true,
|
||||
'Client sending a large non-string should only send a small string.');
|
||||
clientSocket.close();
|
||||
|
|
|
@ -360,8 +360,12 @@ void nsPluginTag::InitMime(const char* const* aMimeTypes,
|
|||
mSupportsAsyncInit = true;
|
||||
break;
|
||||
case nsPluginHost::eSpecialType_Flash:
|
||||
mIsFlashPlugin = true;
|
||||
mSupportsAsyncInit = true;
|
||||
// VLC sometimes claims to implement the Flash MIME type, and we want
|
||||
// to allow users to control that separately from Adobe Flash.
|
||||
if (Name().EqualsLiteral("Shockwave Flash")) {
|
||||
mIsFlashPlugin = true;
|
||||
mSupportsAsyncInit = true;
|
||||
}
|
||||
break;
|
||||
case nsPluginHost::eSpecialType_Silverlight:
|
||||
case nsPluginHost::eSpecialType_Unity:
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
ok(SpecialPowers.setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED, "Flash Test Plug-in"), "Should find allowed test flash plugin");
|
||||
ok(SpecialPowers.setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED, "Shockwave Flash"), "Should find allowed test flash plugin");
|
||||
ok(SpecialPowers.setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED, "Silverlight Test Plug-in"), "Should find allowed test silverlight plugin");
|
||||
ok(!SpecialPowers.setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED, "Third Test Plug-in"), "Should not find disallowed plugin");
|
||||
|
||||
|
@ -56,11 +56,11 @@
|
|||
pluginElement = document.getElementById("disallowedPlugin");
|
||||
is(typeof pluginElement.identifierToStringTest, "undefined", "Should NOT be able to call a function on a disallowed plugin");
|
||||
|
||||
ok(navigator.plugins["Flash Test Plug-in"], "Should have queried a plugin named 'Flash Test Plug-in'");
|
||||
ok(navigator.plugins["Shockwave Flash"], "Should have queried a plugin named 'Shockwave Flash'");
|
||||
ok(navigator.plugins["Silverlight Test Plug-in"], "Should have queried a plugin named 'Silverlight Test Plug-in'");
|
||||
ok(!navigator.plugins["Third Test Plug-in"], "Should NOT have queried a disallowed plugin named 'Third Test Plug-in'");
|
||||
|
||||
ok(findPlugin("Flash Test Plug-in"), "Should have found a plugin named 'Flash Test Plug-in'");
|
||||
ok(findPlugin("Shockwave Flash"), "Should have found a plugin named 'Shockwave Flash'");
|
||||
ok(findPlugin("Silverlight Test Plug-in"), "Should have found a plugin named 'Silverlight Test Plug-in'");
|
||||
ok(!findPlugin("Third Test Plug-in"), "Should NOT found a disallowed plugin named 'Third Test Plug-in'");
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<key>CFBundleVersion</key>
|
||||
<string>1.0.0.0</string>
|
||||
<key>WebPluginName</key>
|
||||
<string>Flash Test Plug-in</string>
|
||||
<string>Shockwave Flash</string>
|
||||
<key>WebPluginDescription</key>
|
||||
<string>Flash plug-in for testing purposes.</string>
|
||||
<key>WebPluginMIMETypes</key>
|
||||
|
|
|
@ -31,7 +31,7 @@ BEGIN
|
|||
VALUE "InternalName", "npswftest"
|
||||
VALUE "MIMEType", "application/x-shockwave-flash-test"
|
||||
VALUE "OriginalFilename", "npswftest.dll"
|
||||
VALUE "ProductName", "Flash Test Plug-in"
|
||||
VALUE "ProductName", "Shockwave Flash"
|
||||
VALUE "ProductVersion", "1.0"
|
||||
END
|
||||
END
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const char *sPluginName = "Flash Test Plug-in";
|
||||
const char *sPluginName = "Shockwave Flash";
|
||||
const char *sPluginDescription = "Flash plug-in for testing purposes.";
|
||||
const char *sMimeDescription = "application/x-shockwave-flash-test:swf:Flash test type";
|
||||
|
|
|
@ -45,13 +45,19 @@ function resolvePromise() {
|
|||
}
|
||||
|
||||
onmessage = function(event) {
|
||||
// FIXME(catalinb): we cannot treat these events as extendable
|
||||
// yet. Bug 1143717
|
||||
event.source.postMessage({type: "message", state: state});
|
||||
var lastState = state;
|
||||
state = event.data;
|
||||
if (event.data === "release") {
|
||||
if (state === 'wait') {
|
||||
event.waitUntil(new Promise(function(res, rej) {
|
||||
if (resolvePromiseCallback) {
|
||||
dump("ERROR: service worker was already waiting on a promise.\n");
|
||||
}
|
||||
resolvePromiseCallback = res;
|
||||
}));
|
||||
} else if (state === 'release') {
|
||||
resolvePromise();
|
||||
}
|
||||
event.source.postMessage({type: "message", state: lastState});
|
||||
}
|
||||
|
||||
onpush = function(event) {
|
||||
|
|
|
@ -253,11 +253,17 @@
|
|||
.then(cancelShutdownObserver)
|
||||
|
||||
// Test with push events and message events
|
||||
.then(setShutdownObserver(true))
|
||||
.then(createIframe)
|
||||
// Make sure we are shutdown before entering our "no shutdown" sequence
|
||||
// to avoid races.
|
||||
.then(waitOnShutdownObserver)
|
||||
.then(setShutdownObserver(false))
|
||||
.then(checkStateAndUpdate(pushEvent, "from_scope", "wait"))
|
||||
.then(checkStateAndUpdate(messageEventIframe, "wait", "update"))
|
||||
.then(checkStateAndUpdate(messageEventIframe, "update", "update"))
|
||||
.then(setShutdownObserver(true))
|
||||
.then(checkStateAndUpdate(messageEventIframe, "wait", "release"))
|
||||
.then(checkStateAndUpdate(messageEventIframe, "update", "release"))
|
||||
.then(waitOnShutdownObserver)
|
||||
.then(closeIframe)
|
||||
}
|
||||
|
@ -272,8 +278,12 @@
|
|||
// Older versions used to terminate workers when the last controlled
|
||||
// window was closed. This should no longer happen, though. Verify
|
||||
// the new behavior.
|
||||
setShutdownObserver(true)(ctx);
|
||||
return createIframe(ctx)
|
||||
.then(setShutdownObserver(true))
|
||||
// Make sure we are shutdown before entering our "no shutdown" sequence
|
||||
// to avoid races.
|
||||
.then(waitOnShutdownObserver)
|
||||
.then(setShutdownObserver(false))
|
||||
.then(checkStateAndUpdate(fetchEvent, "from_scope", "wait"))
|
||||
.then(closeIframe)
|
||||
.then(setShutdownObserver(true))
|
||||
|
@ -282,7 +292,11 @@
|
|||
|
||||
// Push workers were exempt from the old rule and should continue to
|
||||
// survive past the closing of the last controlled window.
|
||||
.then(setShutdownObserver(true))
|
||||
.then(createIframe)
|
||||
// Make sure we are shutdown before entering our "no shutdown" sequence
|
||||
// to avoid races.
|
||||
.then(waitOnShutdownObserver)
|
||||
.then(setShutdownObserver(false))
|
||||
.then(checkStateAndUpdate(pushEvent, "from_scope", "wait"))
|
||||
.then(closeIframe)
|
||||
|
|
|
@ -115,7 +115,7 @@ gfxContext::~gfxContext()
|
|||
{
|
||||
for (int i = mStateStack.Length() - 1; i >= 0; i--) {
|
||||
for (unsigned int c = 0; c < mStateStack[i].pushedClips.Length(); c++) {
|
||||
mDT->PopClip();
|
||||
mStateStack[i].drawTarget->PopClip();
|
||||
}
|
||||
}
|
||||
mDT->Flush();
|
||||
|
|
|
@ -1319,7 +1319,7 @@ DecodeElemSection(Decoder& d, bool newFormat, Uint32Vector&& oldElems, ModuleGen
|
|||
return true;
|
||||
}
|
||||
|
||||
return mg.addElemSegment(ElemSegment(0, InitExpr(Val(uint32_t(0))), Move(oldElems)));
|
||||
return mg.addElemSegment(InitExpr(Val(uint32_t(0))), Move(oldElems));
|
||||
}
|
||||
|
||||
uint32_t sectionStart, sectionSize;
|
||||
|
@ -1336,44 +1336,47 @@ DecodeElemSection(Decoder& d, bool newFormat, Uint32Vector&& oldElems, ModuleGen
|
|||
return Fail(d, "too many elem segments");
|
||||
|
||||
for (uint32_t i = 0, prevEnd = 0; i < numSegments; i++) {
|
||||
ElemSegment seg;
|
||||
if (!d.readVarU32(&seg.tableIndex))
|
||||
uint32_t tableIndex;
|
||||
if (!d.readVarU32(&tableIndex))
|
||||
return Fail(d, "expected table index");
|
||||
|
||||
if (seg.tableIndex >= mg.tables().length())
|
||||
MOZ_ASSERT(mg.tables().length() <= 1);
|
||||
if (tableIndex >= mg.tables().length())
|
||||
return Fail(d, "table index out of range");
|
||||
|
||||
if (!DecodeInitializerExpression(d, mg.globals(), ValType::I32, &seg.offset))
|
||||
InitExpr offset;
|
||||
if (!DecodeInitializerExpression(d, mg.globals(), ValType::I32, &offset))
|
||||
return false;
|
||||
|
||||
if (seg.offset.isVal() && seg.offset.val().i32() < prevEnd)
|
||||
if (offset.isVal() && offset.val().i32() < prevEnd)
|
||||
return Fail(d, "elem segments must be disjoint and ordered");
|
||||
|
||||
uint32_t numElems;
|
||||
if (!d.readVarU32(&numElems))
|
||||
return Fail(d, "expected segment size");
|
||||
|
||||
uint32_t tableLength = mg.tables()[seg.tableIndex].initial;
|
||||
if (seg.offset.isVal()) {
|
||||
uint32_t offset = seg.offset.val().i32();
|
||||
if (offset > tableLength || tableLength - offset < numElems)
|
||||
uint32_t tableLength = mg.tables()[tableIndex].initial;
|
||||
if (offset.isVal()) {
|
||||
uint32_t off = offset.val().i32();
|
||||
if (off > tableLength || tableLength - off < numElems)
|
||||
return Fail(d, "element segment does not fit");
|
||||
}
|
||||
|
||||
if (!seg.elems.resize(numElems))
|
||||
Uint32Vector elemFuncIndices;
|
||||
if (!elemFuncIndices.resize(numElems))
|
||||
return false;
|
||||
|
||||
for (uint32_t i = 0; i < numElems; i++) {
|
||||
if (!d.readVarU32(&seg.elems[i]))
|
||||
if (!d.readVarU32(&elemFuncIndices[i]))
|
||||
return Fail(d, "failed to read element function index");
|
||||
if (seg.elems[i] >= mg.numFuncSigs())
|
||||
if (elemFuncIndices[i] >= mg.numFuncSigs())
|
||||
return Fail(d, "table element out of range");
|
||||
}
|
||||
|
||||
if (seg.offset.isVal())
|
||||
prevEnd = seg.offset.val().i32() + seg.elems.length();
|
||||
if (offset.isVal())
|
||||
prevEnd = offset.val().i32() + elemFuncIndices.length();
|
||||
|
||||
if (!mg.addElemSegment(Move(seg)))
|
||||
if (!mg.addElemSegment(offset, Move(elemFuncIndices)))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -901,18 +901,26 @@ ModuleGenerator::finishFuncDefs()
|
|||
}
|
||||
|
||||
bool
|
||||
ModuleGenerator::addElemSegment(ElemSegment&& seg)
|
||||
ModuleGenerator::addElemSegment(InitExpr offset, Uint32Vector&& elemFuncIndices)
|
||||
{
|
||||
MOZ_ASSERT(!isAsmJS());
|
||||
MOZ_ASSERT(finishedFuncDefs_);
|
||||
MOZ_ASSERT(shared_->tables.length() == 1);
|
||||
|
||||
if (shared_->tables[0].external) {
|
||||
for (uint32_t funcIndex : seg.elems) {
|
||||
for (uint32_t funcIndex : elemFuncIndices) {
|
||||
if (!exportedFuncs_.put(funcIndex))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return elemSegments_.append(Move(seg));
|
||||
Uint32Vector codeRangeIndices;
|
||||
if (!codeRangeIndices.resize(elemFuncIndices.length()))
|
||||
return false;
|
||||
for (size_t i = 0; i < elemFuncIndices.length(); i++)
|
||||
codeRangeIndices[i] = funcIndexToCodeRange_[elemFuncIndices[i]];
|
||||
|
||||
return elemSegments_.emplaceBack(0, offset, Move(elemFuncIndices), Move(codeRangeIndices));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -945,11 +953,19 @@ bool
|
|||
ModuleGenerator::initSigTableElems(uint32_t sigIndex, Uint32Vector&& elemFuncIndices)
|
||||
{
|
||||
MOZ_ASSERT(isAsmJS());
|
||||
MOZ_ASSERT(finishedFuncDefs_);
|
||||
|
||||
uint32_t tableIndex = shared_->asmJSSigToTableIndex[sigIndex];
|
||||
MOZ_ASSERT(shared_->tables[tableIndex].initial == elemFuncIndices.length());
|
||||
|
||||
return elemSegments_.emplaceBack(tableIndex, InitExpr(Val(uint32_t(0))), Move(elemFuncIndices));
|
||||
Uint32Vector codeRangeIndices;
|
||||
if (!codeRangeIndices.resize(elemFuncIndices.length()))
|
||||
return false;
|
||||
for (size_t i = 0; i < elemFuncIndices.length(); i++)
|
||||
codeRangeIndices[i] = funcIndexToCodeRange_[elemFuncIndices[i]];
|
||||
|
||||
InitExpr offset(Val(uint32_t(0)));
|
||||
return elemSegments_.emplaceBack(tableIndex, offset, Move(elemFuncIndices), Move(codeRangeIndices));
|
||||
}
|
||||
|
||||
SharedModule
|
||||
|
@ -1023,16 +1039,6 @@ ModuleGenerator::finish(const ShareableBytes& bytecode)
|
|||
}
|
||||
#endif
|
||||
|
||||
// Convert function indices to offsets into the code section.
|
||||
// WebAssembly's tables are (currently) all untyped and point to the table
|
||||
// entry. asm.js tables are all typed and thus point to the normal entry.
|
||||
for (ElemSegment& seg : elemSegments_) {
|
||||
for (uint32_t& elem : seg.elems) {
|
||||
const CodeRange& cr = funcCodeRange(elem);
|
||||
elem = isAsmJS() ? cr.funcNonProfilingEntry() : cr.funcTableEntry();
|
||||
}
|
||||
}
|
||||
|
||||
if (!finishLinkData(code))
|
||||
return nullptr;
|
||||
|
||||
|
|
|
@ -184,7 +184,7 @@ class MOZ_STACK_CLASS ModuleGenerator
|
|||
|
||||
// Segments:
|
||||
MOZ_MUST_USE bool addDataSegment(DataSegment s) { return dataSegments_.append(s); }
|
||||
MOZ_MUST_USE bool addElemSegment(ElemSegment&& s);
|
||||
MOZ_MUST_USE bool addElemSegment(InitExpr offset, Uint32Vector&& elemFuncIndices);
|
||||
|
||||
// Function names:
|
||||
void setFuncNames(NameInBytecodeVector&& funcNames);
|
||||
|
|
|
@ -269,7 +269,8 @@ ElemSegment::serializedSize() const
|
|||
{
|
||||
return sizeof(tableIndex) +
|
||||
sizeof(offset) +
|
||||
SerializedPodVectorSize(elems);
|
||||
SerializedPodVectorSize(elemFuncIndices) +
|
||||
SerializedPodVectorSize(elemCodeRangeIndices);
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
|
@ -277,7 +278,8 @@ ElemSegment::serialize(uint8_t* cursor) const
|
|||
{
|
||||
cursor = WriteBytes(cursor, &tableIndex, sizeof(tableIndex));
|
||||
cursor = WriteBytes(cursor, &offset, sizeof(offset));
|
||||
cursor = SerializePodVector(cursor, elems);
|
||||
cursor = SerializePodVector(cursor, elemFuncIndices);
|
||||
cursor = SerializePodVector(cursor, elemCodeRangeIndices);
|
||||
return cursor;
|
||||
}
|
||||
|
||||
|
@ -286,14 +288,16 @@ ElemSegment::deserialize(const uint8_t* cursor)
|
|||
{
|
||||
(cursor = ReadBytes(cursor, &tableIndex, sizeof(tableIndex))) &&
|
||||
(cursor = ReadBytes(cursor, &offset, sizeof(offset))) &&
|
||||
(cursor = DeserializePodVector(cursor, &elems));
|
||||
(cursor = DeserializePodVector(cursor, &elemFuncIndices)) &&
|
||||
(cursor = DeserializePodVector(cursor, &elemCodeRangeIndices));
|
||||
return cursor;
|
||||
}
|
||||
|
||||
size_t
|
||||
ElemSegment::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
|
||||
{
|
||||
return elems.sizeOfExcludingThis(mallocSizeOf);
|
||||
return elemFuncIndices.sizeOfExcludingThis(mallocSizeOf) +
|
||||
elemCodeRangeIndices.sizeOfExcludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
size_t
|
||||
|
@ -451,26 +455,26 @@ Module::initElems(JSContext* cx, HandleWasmInstanceObject instanceObj,
|
|||
}
|
||||
|
||||
uint32_t tableLength = instance.metadata().tables[seg.tableIndex].initial;
|
||||
if (offset > tableLength || tableLength - offset < seg.elems.length()) {
|
||||
if (offset > tableLength || tableLength - offset < seg.elemCodeRangeIndices.length()) {
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_WASM_FAIL,
|
||||
"element segment does not fit");
|
||||
return false;
|
||||
}
|
||||
|
||||
// If profiling is already enabled in the wasm::Compartment, the new
|
||||
// instance must use the profiling entry for typed functions instead of
|
||||
// the default nonProfilingEntry.
|
||||
bool useProfilingEntry = instance.code().profilingEnabled() && table.isTypedFunction();
|
||||
|
||||
bool profilingEnabled = instance.code().profilingEnabled();
|
||||
const CodeRangeVector& codeRanges = instance.code().metadata().codeRanges;
|
||||
uint8_t* codeBase = instance.codeBase();
|
||||
for (uint32_t i = 0; i < seg.elems.length(); i++) {
|
||||
void* code = codeBase + seg.elems[i];
|
||||
if (useProfilingEntry)
|
||||
code = codeBase + instance.code().lookupRange(code)->funcProfilingEntry();
|
||||
table.set(offset + i, code, instance);
|
||||
for (uint32_t i = 0; i < seg.elemCodeRangeIndices.length(); i++) {
|
||||
const CodeRange& cr = codeRanges[seg.elemCodeRangeIndices[i]];
|
||||
uint32_t codeOffset = table.isTypedFunction()
|
||||
? profilingEnabled
|
||||
? cr.funcProfilingEntry()
|
||||
: cr.funcNonProfilingEntry()
|
||||
: cr.funcTableEntry();
|
||||
table.set(offset + i, codeBase + codeOffset, instance);
|
||||
}
|
||||
|
||||
prevEnd = offset + seg.elems.length();
|
||||
prevEnd = offset + seg.elemFuncIndices.length();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -156,19 +156,28 @@ struct DataSegment
|
|||
|
||||
typedef Vector<DataSegment, 0, SystemAllocPolicy> DataSegmentVector;
|
||||
|
||||
// ElemSegment represents an element segment in the module where each element's
|
||||
// function index has been translated to its offset in the code section.
|
||||
// ElemSegment represents an element segment in the module where each element
|
||||
// describes both its function index and its code range.
|
||||
|
||||
struct ElemSegment
|
||||
{
|
||||
MOZ_INIT_OUTSIDE_CTOR uint32_t tableIndex;
|
||||
MOZ_INIT_OUTSIDE_CTOR InitExpr offset;
|
||||
MOZ_INIT_OUTSIDE_CTOR Uint32Vector elems;
|
||||
uint32_t tableIndex;
|
||||
InitExpr offset;
|
||||
Uint32Vector elemFuncIndices;
|
||||
Uint32Vector elemCodeRangeIndices;
|
||||
|
||||
ElemSegment() = default;
|
||||
ElemSegment(uint32_t tableIndex, InitExpr offset, Uint32Vector&& elems)
|
||||
: tableIndex(tableIndex), offset(offset), elems(Move(elems))
|
||||
{}
|
||||
ElemSegment(uint32_t tableIndex,
|
||||
InitExpr offset,
|
||||
Uint32Vector&& elemFuncIndices,
|
||||
Uint32Vector&& elemCodeRangeIndices)
|
||||
: tableIndex(tableIndex),
|
||||
offset(offset),
|
||||
elemFuncIndices(Move(elemFuncIndices)),
|
||||
elemCodeRangeIndices(Move(elemCodeRangeIndices))
|
||||
{
|
||||
MOZ_ASSERT(elemFuncIndices.length() == elemCodeRangeIndices.length());
|
||||
}
|
||||
|
||||
WASM_DECLARE_SERIALIZABLE(ElemSegment)
|
||||
};
|
||||
|
|
|
@ -29,7 +29,7 @@ function IsDetachedBuffer(buffer) {
|
|||
// optimization in place there to avoid incurring the cost here. An
|
||||
// alternative is to give SharedArrayBuffer the same layout as ArrayBuffer.
|
||||
if (IsSharedArrayBuffer(buffer))
|
||||
return false;
|
||||
return false;
|
||||
|
||||
var flags = UnsafeGetInt32FromReservedSlot(buffer, JS_ARRAYBUFFER_FLAGS_SLOT);
|
||||
return (flags & JS_ARRAYBUFFER_DETACHED_FLAG) !== 0;
|
||||
|
@ -171,11 +171,10 @@ function TypedArrayEvery(callbackfn, thisArg = undefined) {
|
|||
|
||||
// Steps 3-5.
|
||||
var len;
|
||||
if (isTypedArray) {
|
||||
if (isTypedArray)
|
||||
len = TypedArrayLength(O);
|
||||
} else {
|
||||
else
|
||||
len = callFunction(CallTypedArrayMethodIfWrapped, O, O, "TypedArrayLength");
|
||||
}
|
||||
|
||||
// Step 6.
|
||||
if (arguments.length === 0)
|
||||
|
@ -260,11 +259,10 @@ function TypedArrayFilter(callbackfn, thisArg = undefined) {
|
|||
|
||||
// Step 4.
|
||||
var len;
|
||||
if (isTypedArray) {
|
||||
if (isTypedArray)
|
||||
len = TypedArrayLength(O);
|
||||
} else {
|
||||
else
|
||||
len = callFunction(CallTypedArrayMethodIfWrapped, O, O, "TypedArrayLength");
|
||||
}
|
||||
|
||||
// Step 5.
|
||||
if (arguments.length === 0)
|
||||
|
@ -329,11 +327,10 @@ function TypedArrayFind(predicate, thisArg = undefined) {
|
|||
|
||||
// Steps 3-5.
|
||||
var len;
|
||||
if (isTypedArray) {
|
||||
if (isTypedArray)
|
||||
len = TypedArrayLength(O);
|
||||
} else {
|
||||
else
|
||||
len = callFunction(CallTypedArrayMethodIfWrapped, O, O, "TypedArrayLength");
|
||||
}
|
||||
|
||||
// Step 6.
|
||||
if (arguments.length === 0)
|
||||
|
@ -372,11 +369,10 @@ function TypedArrayFindIndex(predicate, thisArg = undefined) {
|
|||
|
||||
// Steps 3-5.
|
||||
var len;
|
||||
if (isTypedArray) {
|
||||
if (isTypedArray)
|
||||
len = TypedArrayLength(O);
|
||||
} else {
|
||||
else
|
||||
len = callFunction(CallTypedArrayMethodIfWrapped, O, O, "TypedArrayLength");
|
||||
}
|
||||
|
||||
// Step 6.
|
||||
if (arguments.length === 0)
|
||||
|
@ -413,11 +409,10 @@ function TypedArrayForEach(callbackfn, thisArg = undefined) {
|
|||
|
||||
// Step 3-4.
|
||||
var len;
|
||||
if (isTypedArray) {
|
||||
if (isTypedArray)
|
||||
len = TypedArrayLength(O);
|
||||
} else {
|
||||
else
|
||||
len = callFunction(CallTypedArrayMethodIfWrapped, O, O, "TypedArrayLength");
|
||||
}
|
||||
|
||||
// Step 5.
|
||||
if (arguments.length === 0)
|
||||
|
@ -518,7 +513,7 @@ function TypedArrayJoin(separator) {
|
|||
var element0 = O[0];
|
||||
|
||||
// Steps 10-11.
|
||||
// Omit the 'if' clause in step 10, since typed arrays can not have undefined or null elements.
|
||||
// Omit the 'if' clause in step 10, since typed arrays can't have undefined or null elements.
|
||||
var R = ToString(element0);
|
||||
|
||||
// Steps 12-13.
|
||||
|
@ -530,7 +525,7 @@ function TypedArrayJoin(separator) {
|
|||
var element = O[k];
|
||||
|
||||
// Steps 13.c-13.d.
|
||||
// Omit the 'if' clause in step 13.c, since typed arrays can not have undefined or null elements.
|
||||
// Omit the 'if' clause in step 13.c, since typed arrays can't have undefined or null elements.
|
||||
var next = ToString(element);
|
||||
|
||||
// Step 13.e.
|
||||
|
@ -607,11 +602,10 @@ function TypedArrayMap(callbackfn, thisArg = undefined) {
|
|||
|
||||
// Step 4.
|
||||
var len;
|
||||
if (isTypedArray) {
|
||||
if (isTypedArray)
|
||||
len = TypedArrayLength(O);
|
||||
} else {
|
||||
else
|
||||
len = callFunction(CallTypedArrayMethodIfWrapped, O, O, "TypedArrayLength");
|
||||
}
|
||||
|
||||
// Step 5.
|
||||
if (arguments.length === 0)
|
||||
|
@ -657,11 +651,10 @@ function TypedArrayReduce(callbackfn/*, initialValue*/) {
|
|||
|
||||
// Steps 3-5.
|
||||
var len;
|
||||
if (isTypedArray) {
|
||||
if (isTypedArray)
|
||||
len = TypedArrayLength(O);
|
||||
} else {
|
||||
else
|
||||
len = callFunction(CallTypedArrayMethodIfWrapped, O, O, "TypedArrayLength");
|
||||
}
|
||||
|
||||
// Step 6.
|
||||
if (arguments.length === 0)
|
||||
|
@ -704,11 +697,10 @@ function TypedArrayReduceRight(callbackfn/*, initialValue*/) {
|
|||
|
||||
// Steps 3-5.
|
||||
var len;
|
||||
if (isTypedArray) {
|
||||
if (isTypedArray)
|
||||
len = TypedArrayLength(O);
|
||||
} else {
|
||||
else
|
||||
len = callFunction(CallTypedArrayMethodIfWrapped, O, O, "TypedArrayLength");
|
||||
}
|
||||
|
||||
// Step 6.
|
||||
if (arguments.length === 0)
|
||||
|
@ -870,7 +862,7 @@ function SetFromTypedArray(target, typedArray, targetOffset, targetLength) {
|
|||
}
|
||||
|
||||
// ES6 draft 20150304 %TypedArray%.prototype.set
|
||||
function TypedArraySet(overloaded, offset) {
|
||||
function TypedArraySet(overloaded, offset = 0) {
|
||||
// Steps 2-5, either algorithm.
|
||||
var target = this;
|
||||
if (!IsObject(target) || !IsTypedArray(target)) {
|
||||
|
@ -971,11 +963,10 @@ function TypedArraySome(callbackfn, thisArg = undefined) {
|
|||
|
||||
// Steps 3-5.
|
||||
var len;
|
||||
if (isTypedArray) {
|
||||
if (isTypedArray)
|
||||
len = TypedArrayLength(O);
|
||||
} else {
|
||||
else
|
||||
len = callFunction(CallTypedArrayMethodIfWrapped, O, O, "TypedArrayLength");
|
||||
}
|
||||
|
||||
// Step 6.
|
||||
if (arguments.length === 0)
|
||||
|
@ -1106,6 +1097,78 @@ function TypedArraySort(comparefn) {
|
|||
return QuickSort(obj, len, comparefn);
|
||||
}
|
||||
|
||||
// ES2017 draft rev f8a9be8ea4bd97237d176907a1e3080dce20c68f
|
||||
// 22.2.3.28 %TypedArray%.prototype.toLocaleString ([ reserved1 [ , reserved2 ] ])
|
||||
// ES2017 Intl draft rev 78bbe7d1095f5ff3760ac4017ed366026e4cb276
|
||||
// 13.4.1 Array.prototype.toLocaleString ([ locales [ , options ]])
|
||||
function TypedArrayToLocaleString(locales = undefined, options = undefined) {
|
||||
// ValidateTypedArray, then step 1.
|
||||
var array = this;
|
||||
|
||||
// This function is not generic.
|
||||
// We want to make sure that we have an attached buffer, per spec prose.
|
||||
var isTypedArray = IsTypedArrayEnsuringArrayBuffer(array);
|
||||
|
||||
// If we got here, `this` is either a typed array or a cross-compartment
|
||||
// wrapper for one.
|
||||
|
||||
// Step 2.
|
||||
var len;
|
||||
if (isTypedArray)
|
||||
len = TypedArrayLength(array);
|
||||
else
|
||||
len = callFunction(CallTypedArrayMethodIfWrapped, array, array, "TypedArrayLength");
|
||||
|
||||
// Step 4.
|
||||
if (len === 0)
|
||||
return "";
|
||||
|
||||
// Step 5.
|
||||
var firstElement = array[0];
|
||||
|
||||
// Steps 6-7.
|
||||
// Omit the 'if' clause in step 6, since typed arrays can't have undefined
|
||||
// or null elements.
|
||||
#if EXPOSE_INTL_API
|
||||
var R = ToString(callContentFunction(firstElement.toLocaleString, firstElement, locales, options));
|
||||
#else
|
||||
var R = ToString(callContentFunction(firstElement.toLocaleString, firstElement));
|
||||
#endif
|
||||
|
||||
// Step 3 (reordered).
|
||||
// We don't (yet?) implement locale-dependent separators.
|
||||
var separator = ",";
|
||||
|
||||
// Steps 8-9.
|
||||
for (var k = 1; k < len; k++) {
|
||||
// Step 9.a.
|
||||
var S = R + separator;
|
||||
|
||||
// Step 9.b.
|
||||
var nextElement = array[k];
|
||||
|
||||
// Step 9.c *should* be unreachable: typed array elements are numbers.
|
||||
// But bug 1079853 means |nextElement| *could* be |undefined|, if the
|
||||
// previous iteration's step 9.d or step 7 detached |array|'s buffer.
|
||||
// Conveniently, if this happens, evaluating |nextElement.toLocaleString|
|
||||
// throws the required TypeError, and the only observable difference is
|
||||
// the error message. So despite bug 1079853, we can skip step 9.c.
|
||||
|
||||
// Step 9.d.
|
||||
#if EXPOSE_INTL_API
|
||||
R = ToString(callContentFunction(nextElement.toLocaleString, nextElement, locales, options));
|
||||
#else
|
||||
R = ToString(callContentFunction(nextElement.toLocaleString, nextElement));
|
||||
#endif
|
||||
|
||||
// Step 9.e.
|
||||
R = S + R;
|
||||
}
|
||||
|
||||
// Step 10.
|
||||
return R;
|
||||
}
|
||||
|
||||
// ES6 draft 20150304 %TypedArray%.prototype.subarray
|
||||
function TypedArraySubarray(begin, end) {
|
||||
// Step 1.
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
function f(x) {
|
||||
return (x ** (1 / ~4294967297)) && x;
|
||||
};
|
||||
for (var i = 0; i < 2; ++i) {
|
||||
assertEq(f(-Infinity), 0);
|
||||
}
|
|
@ -1,3 +1,10 @@
|
|||
// This test case was created before %TypedArrayPrototype%.toString was
|
||||
// implemented. Now that we've got %TypedArrayPrototype%.toString the test will
|
||||
// attempt to create a 300300001 character long string and either timeout or
|
||||
// throw an oom error. Restore the original behavior by replacing toString with
|
||||
// Object.prototype.toString.
|
||||
Uint8ClampedArray.prototype.toString = Object.prototype.toString;
|
||||
|
||||
function A(a) { this.a = a; }
|
||||
A.prototype.foo = function (x) {};
|
||||
function B(b) { this.b = b; }
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
// |jit-test| test-also-wasm-baseline
|
||||
load(libdir + "wasm.js");
|
||||
|
||||
// Bug 1298808.
|
||||
assertEq(wasmEvalText(`(module
|
||||
(func
|
||||
(result i32)
|
||||
(i32.wrap/i64
|
||||
(i64.mul
|
||||
;; Conditions: rhs == lhs, rhs is not a constant.
|
||||
(i64.add (i64.const 1) (i64.const 10))
|
||||
(i64.add (i64.const 1) (i64.const 10))
|
||||
)
|
||||
)
|
||||
)
|
||||
(export "" 0)
|
||||
)`)(), 121);
|
|
@ -211,22 +211,23 @@ LIRGeneratorARM::lowerForALUInt64(LInstructionHelper<INT64_PIECES, 2 * INT64_PIE
|
|||
void
|
||||
LIRGeneratorARM::lowerForMulInt64(LMulI64* ins, MMul* mir, MDefinition* lhs, MDefinition* rhs)
|
||||
{
|
||||
bool constantNeedTemp = true;
|
||||
bool needsTemp = true;
|
||||
|
||||
if (rhs->isConstant()) {
|
||||
int64_t constant = rhs->toConstant()->toInt64();
|
||||
int32_t shift = mozilla::FloorLog2(constant);
|
||||
// See special cases in CodeGeneratorARM::visitMulI64
|
||||
if (constant >= -1 && constant <= 2)
|
||||
constantNeedTemp = false;
|
||||
needsTemp = false;
|
||||
if (int64_t(1) << shift == constant)
|
||||
constantNeedTemp = false;
|
||||
needsTemp = false;
|
||||
}
|
||||
|
||||
ins->setInt64Operand(0, useInt64RegisterAtStart(lhs));
|
||||
ins->setInt64Operand(INT64_PIECES,
|
||||
lhs != rhs ? useInt64OrConstant(rhs) : useInt64OrConstantAtStart(rhs));
|
||||
if (constantNeedTemp)
|
||||
ins->setInt64Operand(INT64_PIECES, useInt64OrConstant(rhs));
|
||||
if (needsTemp)
|
||||
ins->setTemp(0, temp());
|
||||
|
||||
defineInt64ReuseInput(ins, mir, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -878,8 +878,8 @@ CodeGeneratorX86Shared::visitPowHalfD(LPowHalfD* ins)
|
|||
masm.branchDouble(cond, input, scratch, &sqrt);
|
||||
|
||||
// Math.pow(-Infinity, 0.5) == Infinity.
|
||||
masm.zeroDouble(input);
|
||||
masm.subDouble(scratch, input);
|
||||
masm.zeroDouble(output);
|
||||
masm.subDouble(scratch, output);
|
||||
masm.jump(&done);
|
||||
|
||||
masm.bind(&sqrt);
|
||||
|
@ -888,11 +888,12 @@ CodeGeneratorX86Shared::visitPowHalfD(LPowHalfD* ins)
|
|||
if (!ins->mir()->operandIsNeverNegativeZero()) {
|
||||
// Math.pow(-0, 0.5) == 0 == Math.pow(0, 0.5). Adding 0 converts any -0 to 0.
|
||||
masm.zeroDouble(scratch);
|
||||
masm.addDouble(scratch, input);
|
||||
masm.addDouble(input, scratch);
|
||||
masm.vsqrtsd(scratch, output, output);
|
||||
} else {
|
||||
masm.vsqrtsd(input, output, output);
|
||||
}
|
||||
|
||||
masm.vsqrtsd(input, output, output);
|
||||
|
||||
masm.bind(&done);
|
||||
}
|
||||
|
||||
|
|
|
@ -217,23 +217,24 @@ LIRGeneratorX86::lowerForALUInt64(LInstructionHelper<INT64_PIECES, 2 * INT64_PIE
|
|||
void
|
||||
LIRGeneratorX86::lowerForMulInt64(LMulI64* ins, MMul* mir, MDefinition* lhs, MDefinition* rhs)
|
||||
{
|
||||
bool constantNeedTemp = true;
|
||||
bool needsTemp = true;
|
||||
|
||||
if (rhs->isConstant()) {
|
||||
int64_t constant = rhs->toConstant()->toInt64();
|
||||
int32_t shift = mozilla::FloorLog2(constant);
|
||||
// See special cases in CodeGeneratorX86Shared::visitMulI64
|
||||
// See special cases in CodeGeneratorX86Shared::visitMulI64.
|
||||
if (constant >= -1 && constant <= 2)
|
||||
constantNeedTemp = false;
|
||||
needsTemp = false;
|
||||
if (int64_t(1) << shift == constant)
|
||||
constantNeedTemp = false;
|
||||
needsTemp = false;
|
||||
}
|
||||
|
||||
// MulI64 on x86 needs output to be in edx, eax;
|
||||
ins->setInt64Operand(0, useInt64Fixed(lhs, Register64(edx, eax), /*useAtStart = */ true));
|
||||
ins->setInt64Operand(INT64_PIECES,
|
||||
lhs != rhs ? useInt64OrConstant(rhs) : useInt64OrConstantAtStart(rhs));
|
||||
if (constantNeedTemp)
|
||||
ins->setInt64Operand(INT64_PIECES, useInt64OrConstant(rhs));
|
||||
if (needsTemp)
|
||||
ins->setTemp(0, temp());
|
||||
|
||||
defineInt64Fixed(ins, mir, LInt64Allocation(LAllocation(AnyRegister(edx)),
|
||||
LAllocation(AnyRegister(eax))));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
if (typeof Intl === "object") {
|
||||
const constructors = [
|
||||
Int8Array,
|
||||
Uint8Array,
|
||||
Uint8ClampedArray,
|
||||
Int16Array,
|
||||
Uint16Array,
|
||||
Int32Array,
|
||||
Uint32Array,
|
||||
Float32Array,
|
||||
Float64Array,
|
||||
];
|
||||
|
||||
const localeSep = [,,].toLocaleString();
|
||||
|
||||
const originalNumberToLocaleString = Number.prototype.toLocaleString;
|
||||
|
||||
// Missing arguments are passed as |undefined|.
|
||||
for (let constructor of constructors) {
|
||||
Number.prototype.toLocaleString = function() {
|
||||
assertEq(arguments.length, 2);
|
||||
assertEq(arguments[0], undefined);
|
||||
assertEq(arguments[1], undefined);
|
||||
return "pass";
|
||||
};
|
||||
|
||||
// Single element case.
|
||||
assertEq(new constructor(1).toLocaleString(), "pass");
|
||||
|
||||
// More than one element.
|
||||
assertEq(new constructor(2).toLocaleString(), "pass" + localeSep + "pass");
|
||||
}
|
||||
Number.prototype.toLocaleString = originalNumberToLocaleString;
|
||||
|
||||
// Missing options is passed as |undefined|.
|
||||
for (let constructor of constructors) {
|
||||
Number.prototype.toLocaleString = function() {
|
||||
assertEq(arguments.length, 2);
|
||||
assertEq(arguments[0], locales);
|
||||
assertEq(arguments[1], undefined);
|
||||
return "pass";
|
||||
};
|
||||
let locales = {};
|
||||
|
||||
// Single element case.
|
||||
assertEq(new constructor(1).toLocaleString(locales), "pass");
|
||||
|
||||
// More than one element.
|
||||
assertEq(new constructor(2).toLocaleString(locales), "pass" + localeSep + "pass");
|
||||
}
|
||||
Number.prototype.toLocaleString = originalNumberToLocaleString;
|
||||
|
||||
// Ensure "locales" and "options" arguments are passed to the array elements.
|
||||
for (let constructor of constructors) {
|
||||
Number.prototype.toLocaleString = function() {
|
||||
assertEq(arguments.length, 2);
|
||||
assertEq(arguments[0], locales);
|
||||
assertEq(arguments[1], options);
|
||||
return "pass";
|
||||
};
|
||||
let locales = {};
|
||||
let options = {};
|
||||
|
||||
// Single element case.
|
||||
assertEq(new constructor(1).toLocaleString(locales, options), "pass");
|
||||
|
||||
// More than one element.
|
||||
assertEq(new constructor(2).toLocaleString(locales, options), "pass" + localeSep + "pass");
|
||||
}
|
||||
Number.prototype.toLocaleString = originalNumberToLocaleString;
|
||||
|
||||
assertEq(new Float32Array([NaN]).toLocaleString("ar"), "ليس رقم");
|
||||
assertEq(new Float64Array([NaN]).toLocaleString(["zh-hant", "ar"]), "非數值");
|
||||
assertEq(new Float32Array([Infinity]).toLocaleString(["dz"]), "གྲངས་མེད");
|
||||
assertEq(new Float64Array([-Infinity]).toLocaleString(["fr", "en"]), "-∞");
|
||||
|
||||
const sampleValues = [-0, +0, -1, +1, -2, +2, -0.5, +0.5];
|
||||
const sampleLocales = [
|
||||
void 0,
|
||||
"en",
|
||||
"th-th-u-nu-thai",
|
||||
["tlh", "de"],
|
||||
];
|
||||
const sampleOptions = [
|
||||
void 0,
|
||||
{},
|
||||
{style: "percent"},
|
||||
{style: "currency", currency: "USD", minimumIntegerDigits: 4},
|
||||
];
|
||||
for (let locale of sampleLocales) {
|
||||
for (let options of sampleOptions) {
|
||||
let nf = new Intl.NumberFormat(locale, options);
|
||||
for (let constructor of constructors) {
|
||||
let typedArray = new constructor(sampleValues);
|
||||
let expected = [].map.call(typedArray, nf.format).join(localeSep);
|
||||
assertEq(typedArray.toLocaleString(locale, options), expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
|
@ -0,0 +1,33 @@
|
|||
const TypedArrayPrototype = Object.getPrototypeOf(Int8Array.prototype);
|
||||
|
||||
const constructors = [
|
||||
Int8Array,
|
||||
Uint8Array,
|
||||
Uint8ClampedArray,
|
||||
Int16Array,
|
||||
Uint16Array,
|
||||
Int32Array,
|
||||
Uint32Array,
|
||||
Float32Array,
|
||||
Float64Array
|
||||
];
|
||||
|
||||
// %TypedArrayPrototype% has an own "set" function property.
|
||||
assertEq(TypedArrayPrototype.hasOwnProperty("set"), true);
|
||||
assertEq(typeof TypedArrayPrototype.set, "function");
|
||||
|
||||
// The concrete TypedArray prototypes do not have an own "set" property.
|
||||
assertEq(constructors.every(c => !c.hasOwnProperty("set")), true);
|
||||
|
||||
assertDeepEq(Object.getOwnPropertyDescriptor(TypedArrayPrototype, "set"), {
|
||||
value: TypedArrayPrototype.set,
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
});
|
||||
|
||||
assertEq(TypedArrayPrototype.set.name, "set");
|
||||
assertEq(TypedArrayPrototype.set.length, 1);
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
|
@ -0,0 +1,50 @@
|
|||
if (typeof detachArrayBuffer === "function") {
|
||||
const constructors = [
|
||||
Int8Array,
|
||||
Uint8Array,
|
||||
Uint8ClampedArray,
|
||||
Int16Array,
|
||||
Uint16Array,
|
||||
Int32Array,
|
||||
Uint32Array,
|
||||
Float32Array,
|
||||
Float64Array,
|
||||
];
|
||||
|
||||
const originalNumberToLocaleString = Number.prototype.toLocaleString;
|
||||
|
||||
// Throws if array buffer is detached.
|
||||
for (let constructor of constructors) {
|
||||
let typedArray = new constructor(42);
|
||||
detachArrayBuffer(typedArray.buffer);
|
||||
assertThrowsInstanceOf(() => typedArray.toLocaleString(), TypeError);
|
||||
}
|
||||
|
||||
// Throws a TypeError if detached in Number.prototype.toLocaleString.
|
||||
for (let constructor of constructors) {
|
||||
Number.prototype.toLocaleString = function() {
|
||||
"use strict";
|
||||
if (!detached) {
|
||||
detachArrayBuffer(typedArray.buffer);
|
||||
detached = true;
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
// No error for single element arrays.
|
||||
let detached = false;
|
||||
let typedArray = new constructor(1);
|
||||
assertEq(typedArray.toLocaleString(), "0");
|
||||
assertEq(detached, true);
|
||||
|
||||
// TypeError if more than one element is present.
|
||||
detached = false;
|
||||
typedArray = new constructor(2);
|
||||
assertThrowsInstanceOf(() => typedArray.toLocaleString(), TypeError);
|
||||
assertEq(detached, true);
|
||||
}
|
||||
Number.prototype.toLocaleString = originalNumberToLocaleString;
|
||||
}
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
|
@ -0,0 +1,52 @@
|
|||
if (typeof Intl !== "object") {
|
||||
const constructors = [
|
||||
Int8Array,
|
||||
Uint8Array,
|
||||
Uint8ClampedArray,
|
||||
Int16Array,
|
||||
Uint16Array,
|
||||
Int32Array,
|
||||
Uint32Array,
|
||||
Float32Array,
|
||||
Float64Array,
|
||||
];
|
||||
|
||||
const localeSep = [,,].toLocaleString();
|
||||
|
||||
const originalNumberToLocaleString = Number.prototype.toLocaleString;
|
||||
|
||||
// Ensure no arguments are passed to the array elements.
|
||||
for (let constructor of constructors) {
|
||||
Number.prototype.toLocaleString = function() {
|
||||
assertEq(arguments.length, 0);
|
||||
return "pass";
|
||||
};
|
||||
|
||||
// Single element case.
|
||||
assertEq(new constructor(1).toLocaleString(), "pass");
|
||||
|
||||
// More than one element.
|
||||
assertEq(new constructor(2).toLocaleString(), "pass" + localeSep + "pass");
|
||||
}
|
||||
Number.prototype.toLocaleString = originalNumberToLocaleString;
|
||||
|
||||
// Ensure no arguments are passed to the array elements even if supplied.
|
||||
for (let constructor of constructors) {
|
||||
Number.prototype.toLocaleString = function() {
|
||||
assertEq(arguments.length, 0);
|
||||
return "pass";
|
||||
};
|
||||
let locales = {};
|
||||
let options = {};
|
||||
|
||||
// Single element case.
|
||||
assertEq(new constructor(1).toLocaleString(locales, options), "pass");
|
||||
|
||||
// More than one element.
|
||||
assertEq(new constructor(2).toLocaleString(locales, options), "pass" + localeSep + "pass");
|
||||
}
|
||||
Number.prototype.toLocaleString = originalNumberToLocaleString;
|
||||
}
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
|
@ -0,0 +1,92 @@
|
|||
const TypedArrayPrototype = Object.getPrototypeOf(Int8Array.prototype);
|
||||
|
||||
const constructors = [
|
||||
Int8Array,
|
||||
Uint8Array,
|
||||
Uint8ClampedArray,
|
||||
Int16Array,
|
||||
Uint16Array,
|
||||
Int32Array,
|
||||
Uint32Array,
|
||||
Float32Array,
|
||||
Float64Array,
|
||||
];
|
||||
|
||||
// %TypedArrayPrototype% has an own "toLocaleString" function property.
|
||||
assertEq(TypedArrayPrototype.hasOwnProperty("toLocaleString"), true);
|
||||
assertEq(typeof TypedArrayPrototype.toLocaleString, "function");
|
||||
|
||||
// The initial value of %TypedArrayPrototype%.toLocaleString is not Array.prototype.toLocaleString.
|
||||
assertEq(TypedArrayPrototype.toLocaleString === Array.prototype.toLocaleString, false);
|
||||
|
||||
// The concrete TypedArray prototypes do not have an own "toLocaleString" property.
|
||||
assertEq(constructors.every(c => !c.hasOwnProperty("toLocaleString")), true);
|
||||
|
||||
assertDeepEq(Object.getOwnPropertyDescriptor(TypedArrayPrototype, "toLocaleString"), {
|
||||
value: TypedArrayPrototype.toLocaleString,
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
});
|
||||
|
||||
assertEq(TypedArrayPrototype.toLocaleString.name, "toLocaleString");
|
||||
assertEq(TypedArrayPrototype.toLocaleString.length, 0);
|
||||
|
||||
// It's not a generic method.
|
||||
assertThrowsInstanceOf(() => TypedArrayPrototype.toLocaleString.call(), TypeError);
|
||||
for (let invalid of [void 0, null, {}, [], function(){}, true, 0, "", Symbol()]) {
|
||||
assertThrowsInstanceOf(() => TypedArrayPrototype.toLocaleString.call(invalid), TypeError);
|
||||
}
|
||||
|
||||
const localeOne = 1..toLocaleString(),
|
||||
localeTwo = 2..toLocaleString(),
|
||||
localeSep = [,,].toLocaleString();
|
||||
|
||||
for (let constructor of constructors) {
|
||||
assertEq(new constructor([]).toLocaleString(), "");
|
||||
assertEq(new constructor([1]).toLocaleString(), localeOne);
|
||||
assertEq(new constructor([1, 2]).toLocaleString(), localeOne + localeSep + localeTwo);
|
||||
}
|
||||
|
||||
const originalNumberToLocaleString = Number.prototype.toLocaleString;
|
||||
|
||||
// Calls Number.prototype.toLocaleString on each element.
|
||||
for (let constructor of constructors) {
|
||||
Number.prototype.toLocaleString = function() {
|
||||
"use strict";
|
||||
|
||||
// Ensure this-value is not boxed.
|
||||
assertEq(typeof this, "number");
|
||||
|
||||
// Test ToString is applied.
|
||||
return {
|
||||
valueOf: () => {
|
||||
throw new Error("valueOf called");
|
||||
},
|
||||
toString: () => {
|
||||
return this + 10;
|
||||
}
|
||||
};
|
||||
};
|
||||
let typedArray = new constructor([1, 2]);
|
||||
assertEq(typedArray.toLocaleString(), "11" + localeSep + "12");
|
||||
}
|
||||
Number.prototype.toLocaleString = originalNumberToLocaleString;
|
||||
|
||||
// Calls Number.prototype.toLocaleString from the current Realm.
|
||||
const otherGlobal = newGlobal();
|
||||
for (let constructor of constructors) {
|
||||
Number.prototype.toLocaleString = function() {
|
||||
"use strict";
|
||||
called = true;
|
||||
return this;
|
||||
};
|
||||
let typedArray = new otherGlobal[constructor.name]([1]);
|
||||
let called = false;
|
||||
assertEq(TypedArrayPrototype.toLocaleString.call(typedArray), "1");
|
||||
assertEq(called, true);
|
||||
}
|
||||
Number.prototype.toLocaleString = originalNumberToLocaleString;
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
|
@ -0,0 +1,48 @@
|
|||
const TypedArrayPrototype = Object.getPrototypeOf(Int8Array.prototype);
|
||||
|
||||
const constructors = [
|
||||
Int8Array,
|
||||
Uint8Array,
|
||||
Uint8ClampedArray,
|
||||
Int16Array,
|
||||
Uint16Array,
|
||||
Int32Array,
|
||||
Uint32Array,
|
||||
Float32Array,
|
||||
Float64Array,
|
||||
];
|
||||
|
||||
// %TypedArrayPrototype% has an own "toString" property.
|
||||
assertEq(TypedArrayPrototype.hasOwnProperty("toString"), true);
|
||||
|
||||
// The initial value of %TypedArrayPrototype%.toString is Array.prototype.toString.
|
||||
assertEq(TypedArrayPrototype.toString, Array.prototype.toString);
|
||||
|
||||
// The concrete TypedArray prototypes do not have an own "toString" property.
|
||||
assertEq(constructors.every(c => !c.hasOwnProperty("toString")), true);
|
||||
|
||||
assertDeepEq(Object.getOwnPropertyDescriptor(TypedArrayPrototype, "toString"), {
|
||||
value: TypedArrayPrototype.toString,
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
});
|
||||
|
||||
for (let constructor of constructors) {
|
||||
assertEq(new constructor([]).toString(), "");
|
||||
assertEq(new constructor([1]).toString(), "1");
|
||||
assertEq(new constructor([1, 2]).toString(), "1,2");
|
||||
}
|
||||
|
||||
assertEq(new Int8Array([-1, 2, -3, 4, NaN]).toString(), "-1,2,-3,4,0");
|
||||
assertEq(new Uint8Array([255, 2, 3, 4, NaN]).toString(), "255,2,3,4,0");
|
||||
assertEq(new Uint8ClampedArray([255, 256, 2, 3, 4, NaN]).toString(), "255,255,2,3,4,0");
|
||||
assertEq(new Int16Array([-1, 2, -3, 4, NaN]).toString(), "-1,2,-3,4,0");
|
||||
assertEq(new Uint16Array([-1, 2, 3, 4, NaN]).toString(), "65535,2,3,4,0");
|
||||
assertEq(new Int32Array([-1, 2, -3, 4, NaN]).toString(), "-1,2,-3,4,0");
|
||||
assertEq(new Uint32Array([-1, 2, 3, 4, NaN]).toString(), "4294967295,2,3,4,0");
|
||||
assertEq(new Float32Array([-0, 0, 0.5, -0.5, NaN, Infinity, -Infinity]).toString(), "0,0,0.5,-0.5,NaN,Infinity,-Infinity");
|
||||
assertEq(new Float64Array([-0, 0, 0.5, -0.5, NaN, Infinity, -Infinity]).toString(), "0,0,0.5,-0.5,NaN,Infinity,-Infinity");
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
|
@ -0,0 +1,17 @@
|
|||
// |reftest| skip-if(!this.hasOwnProperty("SIMD"))
|
||||
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* https://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
var { testLoad } = Helpers;
|
||||
|
||||
testLoad('Int16x8', new Int16Array(SIZE_16_ARRAY));
|
||||
|
||||
if (typeof SharedArrayBuffer != "undefined") {
|
||||
testLoad('Int16x8', new Int16Array(new SharedArrayBuffer(SIZE_8_ARRAY)));
|
||||
}
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
|
@ -7,14 +7,10 @@
|
|||
|
||||
var { testLoad } = Helpers;
|
||||
|
||||
testLoad('Int8x16', new Int8Array(SIZE_8_ARRAY));
|
||||
testLoad('Int16x8', new Int16Array(SIZE_16_ARRAY));
|
||||
testLoad('Int32x4', new Int32Array(SIZE_32_ARRAY));
|
||||
|
||||
if (typeof SharedArrayBuffer != "undefined") {
|
||||
testLoad('Int8x16', new Int8Array(new SharedArrayBuffer(SIZE_8_ARRAY)));
|
||||
testLoad('Int16x8', new Int16Array(new SharedArrayBuffer(SIZE_8_ARRAY)));
|
||||
testLoad('Int32x4', new Int32Array(new SharedArrayBuffer(SIZE_8_ARRAY)));
|
||||
testLoad('Int32x4', new Int32Array(new SharedArrayBuffer(SIZE_8_ARRAY)));
|
||||
}
|
||||
|
||||
if (typeof reportCompare === "function")
|
|
@ -0,0 +1,17 @@
|
|||
// |reftest| skip-if(!this.hasOwnProperty("SIMD"))
|
||||
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* https://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
var { testLoad } = Helpers;
|
||||
|
||||
testLoad('Int8x16', new Int8Array(SIZE_8_ARRAY));
|
||||
|
||||
if (typeof SharedArrayBuffer != "undefined") {
|
||||
testLoad('Int8x16', new Int8Array(new SharedArrayBuffer(SIZE_8_ARRAY)));
|
||||
}
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
|
@ -1356,7 +1356,7 @@ TypedArrayObject::protoFunctions[] = {
|
|||
#if 0 /* disabled until perf-testing is completed */
|
||||
JS_SELF_HOSTED_FN("set", "TypedArraySet", 2, 0),
|
||||
#else
|
||||
JS_FN("set", TypedArrayObject::set, 2, 0),
|
||||
JS_FN("set", TypedArrayObject::set, 1, 0),
|
||||
#endif
|
||||
JS_SELF_HOSTED_FN("copyWithin", "TypedArrayCopyWithin", 3, 0),
|
||||
JS_SELF_HOSTED_FN("every", "TypedArrayEvery", 2, 0),
|
||||
|
@ -1380,6 +1380,8 @@ TypedArrayObject::protoFunctions[] = {
|
|||
JS_SELF_HOSTED_FN("values", "TypedArrayValues", 0, 0),
|
||||
JS_SELF_HOSTED_SYM_FN(iterator, "TypedArrayValues", 0, 0),
|
||||
JS_SELF_HOSTED_FN("includes", "TypedArrayIncludes", 2, 0),
|
||||
JS_SELF_HOSTED_FN("toString", "ArrayToString", 0, 0),
|
||||
JS_SELF_HOSTED_FN("toLocaleString", "TypedArrayToLocaleString", 2, 0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
|
|
|
@ -4,5 +4,5 @@ function run_test() {
|
|||
var xhr = Cu.evalInSandbox('new XMLHttpRequest()', sb);
|
||||
do_check_eq(xhr.toString(), '[object XMLHttpRequest]');
|
||||
do_check_eq((new sb.Object()).toString(), '[object Object]');
|
||||
do_check_eq((new sb.Uint16Array()).toString(), '[object Uint16Array]');
|
||||
do_check_eq(sb.Object.prototype.toString.call(new sb.Uint16Array()), '[object Uint16Array]');
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Bug 1288255 - Wrong line breaking due to cached hyphen width</title>
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: LongHyphenTest;
|
||||
src: url(LongHyphenTest.woff2);
|
||||
}
|
||||
#test {
|
||||
font: 16px/2 LongHyphenTest;
|
||||
width: 14em;
|
||||
border: 1px solid blue;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>Test passes if there are two lines each has three rectangles:</p>
|
||||
<div id="test">
|
||||
XXX XXX XXX<br>XXX XXX XXX
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,34 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" class="reftest-wait">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Bug 1288255 - Wrong line breaking due to cached hyphen width</title>
|
||||
<style id="font" media="not all">
|
||||
@font-face {
|
||||
font-family: LongHyphenTest;
|
||||
src: url(LongHyphenTest.woff2);
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
#test {
|
||||
font: 16px/2 LongHyphenTest;
|
||||
width: 14em;
|
||||
border: 1px solid blue;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body onload="load_font()">
|
||||
<p>Test passes if there are two lines each has three rectangles:</p>
|
||||
<div id="test">
|
||||
<span>XXX XXX</span> XXX X­XX XXX XXX
|
||||
</div>
|
||||
<script>
|
||||
function load_font() {
|
||||
document.getElementById("font").media = "";
|
||||
document.fonts.load("16px LongHyphenTest").then(() => {
|
||||
document.documentElement.className = "";
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Двоичный файл не отображается.
|
@ -1962,6 +1962,7 @@ random-if(!winWidget) == 1273154-2.html 1273154-2-ref.html # depends on Windows
|
|||
!= 1276161-1b.html 1276161-1-notref.html
|
||||
!= 1276161-1a.html 1276161-1b.html
|
||||
== 1275411-1.html 1275411-1-ref.html
|
||||
== 1288255.html 1288255-ref.html
|
||||
fuzzy(8,1900) == 1291528.html 1291528-ref.html
|
||||
# Buttons in 2 pages have different position and the rendering result can be
|
||||
# different, but they should use the same button style and the background color
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче