mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge inbound to m-c. a=merge
This commit is contained in:
commit
be6607416e
@ -490,4 +490,5 @@ skip-if = e10s # Bug 1100687 - test directly manipulates content (content.docume
|
||||
skip-if = e10s # bug 1100687 - test directly manipulates content (content.document.getElementById)
|
||||
[browser_mcb_redirect.js]
|
||||
skip-if = e10s # bug 1084504 - [e10s] Mixed content detection does not take redirection into account
|
||||
[browser_updatecommands.js]
|
||||
[browser_windowactivation.js]
|
||||
|
93
browser/base/content/test/general/browser_updatecommands.js
Normal file
93
browser/base/content/test/general/browser_updatecommands.js
Normal file
@ -0,0 +1,93 @@
|
||||
let testPage = "data:text/html,<body><input id='input1' value='value'><select size=2><option val=1>One</select></body>";
|
||||
|
||||
let browser;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
gURLBar.focus();
|
||||
|
||||
var tab = gBrowser.addTab();
|
||||
browser = gBrowser.getBrowserForTab(tab);
|
||||
gBrowser.selectedTab = tab;
|
||||
|
||||
addEventListener("commandupdate", checkTest, false);
|
||||
|
||||
function runFirstTest(event) {
|
||||
browser.removeEventListener("load", runFirstTest, true);
|
||||
doTest();
|
||||
}
|
||||
|
||||
browser.addEventListener("load", runFirstTest, true);
|
||||
browser.contentWindow.location = testPage;
|
||||
}
|
||||
|
||||
let currentTest;
|
||||
|
||||
let tests = [
|
||||
// Switch focus to 'input1'. Paste and select all should be enabled.
|
||||
{ name: "focus input", test: function() { EventUtils.synthesizeKey("VK_TAB", {}) },
|
||||
commands: { "cmd_copy" : true, "cmd_paste": true, "cmd_selectAll" : true, "cmd_undo" : false, "cmd_redo": false } },
|
||||
|
||||
// Move cursor to end which will deselect the text. Copy should be disabled but paste and select all should still be enabled.
|
||||
{ name: "cursor right", test: function() { EventUtils.synthesizeKey("VK_RIGHT", {}) },
|
||||
commands: { "cmd_copy" : false, "cmd_paste": true, "cmd_selectAll" : true, "cmd_undo" : false, "cmd_redo": false } },
|
||||
|
||||
// Select all of the text. Copy should become enabled.
|
||||
{ name: "select all", test: function() { EventUtils.synthesizeKey("a", { accelKey: true }) },
|
||||
commands: { "cmd_copy" : true, "cmd_paste": true, "cmd_selectAll" : true, "cmd_undo" : false, "cmd_redo": false } },
|
||||
|
||||
// Replace the text with 'c'. Copy should now be disabled and undo enabled.
|
||||
{ name: "change value", test: function() { EventUtils.synthesizeKey("c", {}) },
|
||||
commands: { "cmd_copy" : false, "cmd_paste": true, "cmd_selectAll" : true, "cmd_undo" : true, "cmd_redo": false } },
|
||||
|
||||
// Undo. Undo should be disabled and redo enabled. The text is reselected so copy is enabled.
|
||||
{ name: "undo", test: function() { EventUtils.synthesizeKey("z", {accelKey: true }) },
|
||||
commands: { "cmd_copy" : true, "cmd_paste": true, "cmd_selectAll" : true, "cmd_undo" : false, "cmd_redo": true } },
|
||||
|
||||
// Switch focus to the select. Only select all should now be enabled.
|
||||
{ name: "focus select", test: function() { EventUtils.synthesizeKey("VK_TAB", {}) },
|
||||
commands: { "cmd_copy" : false, "cmd_paste": false, "cmd_selectAll" : true, "cmd_undo" : false, "cmd_redo": false } },
|
||||
];
|
||||
|
||||
function doTest()
|
||||
{
|
||||
if (!tests.length) {
|
||||
removeEventListener("commandupdate", checkTest, false);
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
currentTest = tests.shift();
|
||||
currentTest.test();
|
||||
}
|
||||
|
||||
function checkTest(event)
|
||||
{
|
||||
// Ignore commandupdates before the test starts
|
||||
if (document.activeElement != browser || !currentTest) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip events fired on command updaters other than the main edit menu one.
|
||||
if (event.target != document.getElementById("editMenuCommandSetAll")) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let command in currentTest.commands) {
|
||||
// Command updates can come several at a time, and, especially with multiple
|
||||
// processes, the updates can come asynchronously. Handle this by just waiting
|
||||
// until the command have the correct state. The test will timeout if the
|
||||
// correct command update never occurs.
|
||||
if ((document.getElementById(command).getAttribute("disabled") != "true") != currentTest.commands[command]) {
|
||||
return;
|
||||
}
|
||||
|
||||
is(document.getElementById(command).getAttribute("disabled") != "true", currentTest.commands[command],
|
||||
currentTest["name"] + " " + command);
|
||||
}
|
||||
|
||||
currentTest = null; // prevent the check from running again
|
||||
SimpleTest.executeSoon(doTest);
|
||||
}
|
@ -122,10 +122,4 @@ LoadInfo::GetBaseURI(nsIURI** aBaseURI)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIURI*
|
||||
LoadInfo::BaseURI()
|
||||
{
|
||||
return mBaseURI;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -17,7 +17,7 @@ typedef unsigned long nsSecurityFlags;
|
||||
/**
|
||||
* An nsILoadOwner represents per-load information about who started the load.
|
||||
*/
|
||||
[scriptable, builtinclass, uuid(768a1f20-57d4-462a-812a-41c04e5d1e19)]
|
||||
[scriptable, builtinclass, uuid(da363267-236d-49bf-83a2-33da8d892728)]
|
||||
interface nsILoadInfo : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -156,7 +156,7 @@ interface nsILoadInfo : nsISupports
|
||||
* The contentPolicyType of the channel, used for security checks
|
||||
* like Mixed Content Blocking and Content Security Policy.
|
||||
*/
|
||||
readonly attribute nsContentPolicyType contentPolicyType;
|
||||
readonly attribute nsContentPolicyType contentPolicyType;
|
||||
|
||||
%{ C++
|
||||
inline nsContentPolicyType GetContentPolicyType()
|
||||
@ -173,11 +173,5 @@ interface nsILoadInfo : nsISupports
|
||||
* This attribute may be null. The value of this attribute may be
|
||||
* ignored if the base URI can be inferred by the channel's URI.
|
||||
*/
|
||||
readonly attribute nsIURI baseURI;
|
||||
|
||||
/**
|
||||
* A C++-friendly version of baseURI.
|
||||
*/
|
||||
[noscript, notxpcom, nostdcall, binaryname(BaseURI)]
|
||||
nsIURI binaryBaseURI();
|
||||
readonly attribute nsIURI baseURI;
|
||||
};
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "nsIWebNavigation.h"
|
||||
#include "nsCaret.h"
|
||||
#include "nsIBaseWindow.h"
|
||||
#include "nsIXULWindow.h"
|
||||
#include "nsViewManager.h"
|
||||
#include "nsFrameSelection.h"
|
||||
#include "mozilla/dom/Selection.h"
|
||||
@ -734,7 +735,10 @@ nsFocusManager::WindowRaised(nsIDOMWindow* aWindow)
|
||||
frameSelection->SetDragState(false);
|
||||
}
|
||||
|
||||
Focus(currentWindow, currentFocus, 0, true, false, true, true);
|
||||
// If there is no nsIXULWindow, then this is an embedded or child process window.
|
||||
// Pass false for aWindowRaised so that commands get updated.
|
||||
nsCOMPtr<nsIXULWindow> xulWin(do_GetInterface(baseWindow));
|
||||
Focus(currentWindow, currentFocus, 0, true, false, xulWin != nullptr, true);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -9270,6 +9270,36 @@ nsGlobalWindow::ShowModalDialog(const nsAString& aURI, nsIVariant *aArgs_,
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
class ChildCommandDispatcher : public nsRunnable
|
||||
{
|
||||
public:
|
||||
ChildCommandDispatcher(nsGlobalWindow* aWindow,
|
||||
nsITabChild* aTabChild,
|
||||
const nsAString& aAction)
|
||||
: mWindow(aWindow), mTabChild(aTabChild), mAction(aAction) {}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
nsCOMPtr<nsPIWindowRoot> root = mWindow->GetTopWindowRoot();
|
||||
if (!root) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsTArray<nsCString> enabledCommands, disabledCommands;
|
||||
root->GetEnabledDisabledCommands(enabledCommands, disabledCommands);
|
||||
if (enabledCommands.Length() || disabledCommands.Length()) {
|
||||
mTabChild->EnableDisableCommands(mAction, enabledCommands, disabledCommands);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<nsGlobalWindow> mWindow;
|
||||
nsCOMPtr<nsITabChild> mTabChild;
|
||||
nsString mAction;
|
||||
};
|
||||
|
||||
class CommandDispatcher : public nsRunnable
|
||||
{
|
||||
public:
|
||||
@ -9289,6 +9319,12 @@ public:
|
||||
NS_IMETHODIMP
|
||||
nsGlobalWindow::UpdateCommands(const nsAString& anAction, nsISelection* aSel, int16_t aReason)
|
||||
{
|
||||
// If this is a child process, redirect to the parent process.
|
||||
if (nsCOMPtr<nsITabChild> child = do_GetInterface(GetDocShell())) {
|
||||
nsContentUtils::AddScriptRunner(new ChildCommandDispatcher(this, child, anAction));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsPIDOMWindow *rootWindow = nsGlobalWindow::GetPrivateRoot();
|
||||
if (!rootWindow)
|
||||
return NS_OK;
|
||||
|
@ -15,8 +15,8 @@ class nsIControllers;
|
||||
class nsIController;
|
||||
|
||||
#define NS_IWINDOWROOT_IID \
|
||||
{ 0x3f71f50c, 0xa7e0, 0x43bc, \
|
||||
{ 0xac, 0x25, 0x4d, 0xbb, 0x88, 0x7b, 0x21, 0x09 } }
|
||||
{ 0x728a2682, 0x55c0, 0x4860, \
|
||||
{ 0x82, 0x6b, 0x0c, 0x30, 0x0a, 0xac, 0xaa, 0x60 } }
|
||||
|
||||
class nsPIWindowRoot : public mozilla::dom::EventTarget
|
||||
{
|
||||
@ -33,6 +33,9 @@ public:
|
||||
nsIController** aResult) = 0;
|
||||
virtual nsresult GetControllers(nsIControllers** aResult) = 0;
|
||||
|
||||
virtual void GetEnabledDisabledCommands(nsTArray<nsCString>& aEnabledCommands,
|
||||
nsTArray<nsCString>& aDisabledCommands) = 0;
|
||||
|
||||
virtual void SetParentTarget(mozilla::dom::EventTarget* aTarget) = 0;
|
||||
virtual mozilla::dom::EventTarget* GetParentTarget() = 0;
|
||||
virtual nsIDOMWindow* GetOwnerGlobal() MOZ_OVERRIDE = 0;
|
||||
|
@ -281,6 +281,75 @@ nsWindowRoot::GetControllerForCommand(const char * aCommand,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsWindowRoot::GetEnabledDisabledCommandsForControllers(nsIControllers* aControllers,
|
||||
nsTHashtable<nsCharPtrHashKey>& aCommandsHandled,
|
||||
nsTArray<nsCString>& aEnabledCommands,
|
||||
nsTArray<nsCString>& aDisabledCommands)
|
||||
{
|
||||
uint32_t controllerCount;
|
||||
aControllers->GetControllerCount(&controllerCount);
|
||||
for (uint32_t c = 0; c < controllerCount; c++) {
|
||||
nsCOMPtr<nsIController> controller;
|
||||
aControllers->GetControllerAt(c, getter_AddRefs(controller));
|
||||
|
||||
nsCOMPtr<nsICommandController> commandController(do_QueryInterface(controller));
|
||||
if (commandController) {
|
||||
uint32_t commandsCount;
|
||||
char** commands;
|
||||
if (NS_SUCCEEDED(commandController->GetSupportedCommands(&commandsCount, &commands))) {
|
||||
for (uint32_t e = 0; e < commandsCount; e++) {
|
||||
// Use a hash to determine which commands have already been handled by
|
||||
// earlier controllers, as the earlier controller's result should get
|
||||
// priority.
|
||||
if (!aCommandsHandled.Contains(commands[e])) {
|
||||
aCommandsHandled.PutEntry(commands[e]);
|
||||
|
||||
bool enabled = false;
|
||||
controller->IsCommandEnabled(commands[e], &enabled);
|
||||
|
||||
const nsDependentCSubstring commandStr(commands[e], strlen(commands[e]));
|
||||
if (enabled) {
|
||||
aEnabledCommands.AppendElement(commandStr);
|
||||
} else {
|
||||
aDisabledCommands.AppendElement(commandStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(commandsCount, commands);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsWindowRoot::GetEnabledDisabledCommands(nsTArray<nsCString>& aEnabledCommands,
|
||||
nsTArray<nsCString>& aDisabledCommands)
|
||||
{
|
||||
nsTHashtable<nsCharPtrHashKey> commandsHandled;
|
||||
|
||||
nsCOMPtr<nsIControllers> controllers;
|
||||
GetControllers(getter_AddRefs(controllers));
|
||||
if (controllers) {
|
||||
GetEnabledDisabledCommandsForControllers(controllers, commandsHandled,
|
||||
aEnabledCommands, aDisabledCommands);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> focusedWindow;
|
||||
nsFocusManager::GetFocusedDescendant(mWindow, true, getter_AddRefs(focusedWindow));
|
||||
while (focusedWindow) {
|
||||
focusedWindow->GetControllers(getter_AddRefs(controllers));
|
||||
if (controllers) {
|
||||
GetEnabledDisabledCommandsForControllers(controllers, commandsHandled,
|
||||
aEnabledCommands, aDisabledCommands);
|
||||
}
|
||||
|
||||
nsGlobalWindow* win = static_cast<nsGlobalWindow*>(focusedWindow.get());
|
||||
focusedWindow = win->GetPrivateParent();
|
||||
}
|
||||
}
|
||||
|
||||
nsIDOMNode*
|
||||
nsWindowRoot::GetPopupNode()
|
||||
{
|
||||
|
@ -23,6 +23,8 @@ class EventChainPreVisitor;
|
||||
#include "nsPIWindowRoot.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsTHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
||||
class nsWindowRoot : public nsPIWindowRoot
|
||||
{
|
||||
@ -52,6 +54,9 @@ public:
|
||||
virtual nsresult GetControllerForCommand(const char * aCommand,
|
||||
nsIController** _retval) MOZ_OVERRIDE;
|
||||
|
||||
virtual void GetEnabledDisabledCommands(nsTArray<nsCString>& aEnabledCommands,
|
||||
nsTArray<nsCString>& aDisabledCommands) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsIDOMNode* GetPopupNode() MOZ_OVERRIDE;
|
||||
virtual void SetPopupNode(nsIDOMNode* aNode) MOZ_OVERRIDE;
|
||||
|
||||
@ -72,6 +77,11 @@ public:
|
||||
protected:
|
||||
virtual ~nsWindowRoot();
|
||||
|
||||
void GetEnabledDisabledCommandsForControllers(nsIControllers* aControllers,
|
||||
nsTHashtable<nsCharPtrHashKey>& aCommandsHandled,
|
||||
nsTArray<nsCString>& aEnabledCommands,
|
||||
nsTArray<nsCString>& aDisabledCommands);
|
||||
|
||||
// Members
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
// We own the manager, which owns event listeners attached to us.
|
||||
|
@ -562,13 +562,16 @@ ClearWithTempFB(WebGLContext* webgl, GLuint tex,
|
||||
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
|
||||
texImageTarget.get(), tex, level);
|
||||
break;
|
||||
|
||||
case LOCAL_GL_DEPTH_COMPONENT32_OES:
|
||||
case LOCAL_GL_DEPTH_COMPONENT24_OES:
|
||||
case LOCAL_GL_DEPTH_COMPONENT16:
|
||||
case LOCAL_GL_DEPTH_COMPONENT:
|
||||
mask = LOCAL_GL_DEPTH_BUFFER_BIT;
|
||||
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
|
||||
texImageTarget.get(), tex, level);
|
||||
break;
|
||||
|
||||
case LOCAL_GL_DEPTH24_STENCIL8:
|
||||
case LOCAL_GL_DEPTH_STENCIL:
|
||||
mask = LOCAL_GL_DEPTH_BUFFER_BIT |
|
||||
LOCAL_GL_STENCIL_BUFFER_BIT;
|
||||
|
@ -31,6 +31,7 @@ XPIDL_SOURCES += [
|
||||
'nsIFrameRequestCallback.idl',
|
||||
'nsIIdleObserver.idl',
|
||||
'nsIQueryContentEventResult.idl',
|
||||
'nsIRemoteBrowser.idl',
|
||||
'nsIServiceWorkerManager.idl',
|
||||
'nsIStructuredCloneContainer.idl',
|
||||
'nsITabChild.idl',
|
||||
|
26
dom/interfaces/base/nsIRemoteBrowser.idl
Normal file
26
dom/interfaces/base/nsIRemoteBrowser.idl
Normal file
@ -0,0 +1,26 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(C8379366-F79F-4D25-89A6-22BEC0A93D16)]
|
||||
interface nsIRemoteBrowser : nsISupports
|
||||
{
|
||||
/*
|
||||
* Called by the child to inform the parent that a command update has occurred
|
||||
* and the supplied set of commands are now enabled and disabled.
|
||||
*
|
||||
* @param action command updater action
|
||||
* @param enabledLength length of enabledCommands array
|
||||
* @param enabledCommands commands to enable
|
||||
* @param disabledLength length of disabledCommands array
|
||||
* @param disabledCommand commands to disable
|
||||
*/
|
||||
void enableDisableCommands(in AString action,
|
||||
in unsigned long enabledLength,
|
||||
[array, size_is(enabledLength)] in string enabledCommands,
|
||||
in unsigned long disabledLength,
|
||||
[array, size_is(disabledLength)] in string disabledCommands);
|
||||
};
|
||||
|
@ -7,7 +7,10 @@
|
||||
interface nsIContentFrameMessageManager;
|
||||
interface nsIWebBrowserChrome3;
|
||||
|
||||
[scriptable, uuid(2eb3bc54-78bf-40f2-b301-a5b5b70f7da0)]
|
||||
native CommandsArray(nsTArray<nsCString>);
|
||||
[ref] native CommandsArrayRef(nsTArray<nsCString>);
|
||||
|
||||
[scriptable, uuid(7227bac4-b6fe-4090-aeb4-bc288b790925)]
|
||||
interface nsITabChild : nsISupports
|
||||
{
|
||||
readonly attribute nsIContentFrameMessageManager messageManager;
|
||||
@ -15,5 +18,9 @@ interface nsITabChild : nsISupports
|
||||
attribute nsIWebBrowserChrome3 webBrowserChrome;
|
||||
|
||||
[notxpcom] void sendRequestFocus(in boolean canFocus);
|
||||
|
||||
[noscript, notxpcom] void enableDisableCommands(in AString action,
|
||||
in CommandsArrayRef enabledCommands,
|
||||
in CommandsArrayRef disabledCommands);
|
||||
};
|
||||
|
||||
|
@ -244,6 +244,14 @@ parent:
|
||||
*/
|
||||
RequestFocus(bool canRaise);
|
||||
|
||||
/**
|
||||
* Indicate, based on the current state, that some commands are enabled and
|
||||
* some are disabled.
|
||||
*/
|
||||
EnableDisableCommands(nsString action,
|
||||
nsCString[] enabledCommands,
|
||||
nsCString[] disabledCommands);
|
||||
|
||||
prio(urgent) sync GetInputContext() returns (int32_t IMEEnabled,
|
||||
int32_t IMEOpen,
|
||||
intptr_t NativeIMEContext);
|
||||
|
@ -3226,6 +3226,15 @@ TabChild::SendRequestFocus(bool aCanFocus)
|
||||
PBrowserChild::SendRequestFocus(aCanFocus);
|
||||
}
|
||||
|
||||
void
|
||||
TabChild::EnableDisableCommands(const nsAString& aAction,
|
||||
nsTArray<nsCString>& aEnabledCommands,
|
||||
nsTArray<nsCString>& aDisabledCommands)
|
||||
{
|
||||
PBrowserChild::SendEnableDisableCommands(PromiseFlatString(aAction),
|
||||
aEnabledCommands, aDisabledCommands);
|
||||
}
|
||||
|
||||
bool
|
||||
TabChild::DoSendBlockingMessage(JSContext* aCx,
|
||||
const nsAString& aMessage,
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "nsIWindowCreator2.h"
|
||||
#include "nsIXULBrowserWindow.h"
|
||||
#include "nsIXULWindow.h"
|
||||
#include "nsIRemoteBrowser.h"
|
||||
#include "nsViewManager.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "nsIWindowWatcher.h"
|
||||
@ -1467,6 +1468,37 @@ TabParent::RecvRequestFocus(const bool& aCanRaise)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::RecvEnableDisableCommands(const nsString& aAction,
|
||||
const nsTArray<nsCString>& aEnabledCommands,
|
||||
const nsTArray<nsCString>& aDisabledCommands)
|
||||
{
|
||||
nsCOMPtr<nsIRemoteBrowser> remoteBrowser = do_QueryInterface(mFrameElement);
|
||||
if (remoteBrowser) {
|
||||
nsAutoArrayPtr<const char*> enabledCommands, disabledCommands;
|
||||
|
||||
if (aEnabledCommands.Length()) {
|
||||
enabledCommands = new const char* [aEnabledCommands.Length()];
|
||||
for (uint32_t c = 0; c < aEnabledCommands.Length(); c++) {
|
||||
enabledCommands[c] = aEnabledCommands[c].get();
|
||||
}
|
||||
}
|
||||
|
||||
if (aDisabledCommands.Length()) {
|
||||
disabledCommands = new const char* [aDisabledCommands.Length()];
|
||||
for (uint32_t c = 0; c < aDisabledCommands.Length(); c++) {
|
||||
disabledCommands[c] = aDisabledCommands[c].get();
|
||||
}
|
||||
}
|
||||
|
||||
remoteBrowser->EnableDisableCommands(aAction,
|
||||
aEnabledCommands.Length(), enabledCommands,
|
||||
aDisabledCommands.Length(), disabledCommands);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
nsIntPoint
|
||||
TabParent::GetChildProcessOffset()
|
||||
{
|
||||
|
@ -191,6 +191,9 @@ public:
|
||||
const int32_t& aCause,
|
||||
const int32_t& aFocusChange) MOZ_OVERRIDE;
|
||||
virtual bool RecvRequestFocus(const bool& aCanRaise) MOZ_OVERRIDE;
|
||||
virtual bool RecvEnableDisableCommands(const nsString& aAction,
|
||||
const nsTArray<nsCString>& aEnabledCommands,
|
||||
const nsTArray<nsCString>& aDisabledCommands) MOZ_OVERRIDE;
|
||||
virtual bool RecvSetCursor(const uint32_t& aValue, const bool& aForce) MOZ_OVERRIDE;
|
||||
virtual bool RecvSetBackgroundColor(const nscolor& aValue) MOZ_OVERRIDE;
|
||||
virtual bool RecvSetStatus(const uint32_t& aType, const nsString& aStatus) MOZ_OVERRIDE;
|
||||
|
@ -36,6 +36,10 @@ static const AvFormatLib sLibs[] = {
|
||||
{ "libavformat.so.55", FFmpegDecoderModule<55>::Create, 55 },
|
||||
{ "libavformat.so.54", FFmpegDecoderModule<54>::Create, 54 },
|
||||
{ "libavformat.so.53", FFmpegDecoderModule<53>::Create, 53 },
|
||||
{ "libavformat.56.dylib", FFmpegDecoderModule<55>::Create, 55 },
|
||||
{ "libavformat.55.dylib", FFmpegDecoderModule<55>::Create, 55 },
|
||||
{ "libavformat.54.dylib", FFmpegDecoderModule<54>::Create, 54 },
|
||||
{ "libavformat.53.dylib", FFmpegDecoderModule<53>::Create, 53 },
|
||||
};
|
||||
|
||||
void* FFmpegRuntimeLinker::sLinkedLib = nullptr;
|
||||
|
@ -106,5 +106,3 @@ MOCHITEST_MANIFESTS += [
|
||||
MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
|
||||
|
||||
XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell/xpcshell.ini']
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
|
||||
|
@ -1,4 +0,0 @@
|
||||
[DEFAULT]
|
||||
|
||||
[browser_bug1104623.js]
|
||||
run-if = buildapp == 'browser'
|
@ -1,48 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function whenBrowserLoaded(aBrowser, aCallback) {
|
||||
aBrowser.addEventListener("load", function onLoad(event) {
|
||||
if (event.target == aBrowser.contentDocument) {
|
||||
aBrowser.removeEventListener("load", onLoad, true);
|
||||
executeSoon(aCallback);
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let testURL = "chrome://mochitests/content/chrome/dom/base/test/file_empty.html";
|
||||
|
||||
let tab = gBrowser.addTab(testURL);
|
||||
gBrowser.selectedTab = tab;
|
||||
|
||||
whenBrowserLoaded(tab.linkedBrowser, function() {
|
||||
let doc = tab.linkedBrowser.contentDocument;
|
||||
|
||||
let blob = new tab.linkedBrowser.contentWindow.Blob(['onmessage = function() { postMessage(true); }']);
|
||||
ok(blob, "Blob has been created");
|
||||
|
||||
let blobURL = tab.linkedBrowser.contentWindow.URL.createObjectURL(blob);
|
||||
ok(blobURL, "Blob URL has been created");
|
||||
|
||||
let worker = new tab.linkedBrowser.contentWindow.Worker(blobURL);
|
||||
ok(worker, "Worker has been created");
|
||||
|
||||
worker.onerror = function(error) {
|
||||
ok(false, "Worker.onerror:" + error.message);
|
||||
gBrowser.removeTab(tab);
|
||||
finish();
|
||||
}
|
||||
|
||||
worker.onmessage = function() {
|
||||
ok(true, "Worker.onmessage");
|
||||
gBrowser.removeTab(tab);
|
||||
finish();
|
||||
}
|
||||
|
||||
worker.postMessage(true);
|
||||
});
|
||||
}
|
@ -7,12 +7,12 @@
|
||||
|
||||
[scriptable, uuid(D5B61B82-1DA4-11d3-BF87-00105A1B0627)]
|
||||
interface nsIController : nsISupports {
|
||||
boolean isCommandEnabled(in string command);
|
||||
boolean supportsCommand(in string command);
|
||||
boolean isCommandEnabled(in string command);
|
||||
boolean supportsCommand(in string command);
|
||||
|
||||
void doCommand(in string command);
|
||||
void doCommand(in string command);
|
||||
|
||||
void onEvent(in string eventName);
|
||||
void onEvent(in string eventName);
|
||||
};
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@ interface nsIController : nsISupports {
|
||||
|
||||
interface nsICommandParams;
|
||||
|
||||
[scriptable, uuid(EBE55080-C8A9-11D5-A73C-DD620D6E04BC)]
|
||||
[scriptable, uuid(EEC0B435-7F53-44FE-B00A-CF3EED65C01A)]
|
||||
interface nsICommandController : nsISupports
|
||||
{
|
||||
|
||||
@ -33,6 +33,8 @@ interface nsICommandController : nsISupports
|
||||
|
||||
void doCommandWithParams(in string command, in nsICommandParams aCommandParams);
|
||||
|
||||
void getSupportedCommands(out unsigned long count,
|
||||
[array, size_is(count), retval] out string commands);
|
||||
};
|
||||
|
||||
|
||||
|
@ -174,3 +174,10 @@ nsBaseCommandController::OnEvent(const char * aEventName)
|
||||
NS_ENSURE_ARG_POINTER(aEventName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBaseCommandController::GetSupportedCommands(uint32_t* aCount, char*** aCommands)
|
||||
{
|
||||
NS_ENSURE_STATE(mCommandTable);
|
||||
return mCommandTable->GetSupportedCommands(aCount, aCommands);
|
||||
}
|
||||
|
@ -188,6 +188,30 @@ nsControllerCommandTable::GetCommandState(const char *aCommandName, nsICommandPa
|
||||
return commandHandler->GetCommandStateParams(aCommandName, aParams, aCommandRefCon);
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
AddCommand(const nsACString& aKey, nsIControllerCommand* aData, void* aArg)
|
||||
{
|
||||
// aArg is a pointer to a array of strings. It gets incremented after
|
||||
// allocating each one so that it points to the next location for AddCommand
|
||||
// to assign a string to.
|
||||
char*** commands = static_cast<char***>(aArg);
|
||||
(**commands) = ToNewCString(aKey);
|
||||
(*commands)++;
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsControllerCommandTable::GetSupportedCommands(uint32_t* aCount,
|
||||
char*** aCommands)
|
||||
{
|
||||
char** commands =
|
||||
static_cast<char **>(NS_Alloc(sizeof(char *) * mCommandsTable.Count()));
|
||||
*aCount = mCommandsTable.Count();
|
||||
*aCommands = commands;
|
||||
|
||||
mCommandsTable.EnumerateRead(AddCommand, &commands);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewControllerCommandTable(nsIControllerCommandTable** aResult)
|
||||
|
@ -18,7 +18,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
[scriptable, uuid(d1a47834-6ad4-11d7-bfad-000393636592)]
|
||||
[scriptable, uuid(c847f90e-b8f3-49db-a4df-8867831f2800)]
|
||||
interface nsIControllerCommandTable : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -82,6 +82,9 @@ interface nsIControllerCommandTable : nsISupports
|
||||
void doCommandParams(in string aCommandName, in nsICommandParams aParam, in nsISupports aCommandRefCon);
|
||||
|
||||
void getCommandState(in string aCommandName, in nsICommandParams aParam, in nsISupports aCommandRefCon);
|
||||
|
||||
void getSupportedCommands(out unsigned long count,
|
||||
[array, size_is(count), retval] out string commands);
|
||||
};
|
||||
|
||||
|
||||
|
@ -308,7 +308,7 @@ IsIncrementalBarrierNeeded(JSContext *cx);
|
||||
* These methods must be called if IsIncrementalBarrierNeeded.
|
||||
*/
|
||||
extern JS_FRIEND_API(void)
|
||||
IncrementalReferenceBarrier(void *ptr, JSGCTraceKind kind);
|
||||
IncrementalReferenceBarrier(GCCellPtr thing);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
IncrementalValueBarrier(const Value &v);
|
||||
@ -479,24 +479,39 @@ namespace js {
|
||||
namespace gc {
|
||||
|
||||
static MOZ_ALWAYS_INLINE void
|
||||
ExposeGCThingToActiveJS(void *thing, JSGCTraceKind kind)
|
||||
ExposeGCThingToActiveJS(JS::GCCellPtr thing)
|
||||
{
|
||||
MOZ_ASSERT(kind != JSTRACE_SHAPE);
|
||||
MOZ_ASSERT(thing.kind() != JSTRACE_SHAPE);
|
||||
|
||||
JS::shadow::Runtime *rt = GetGCThingRuntime(thing);
|
||||
JS::shadow::Runtime *rt = GetGCThingRuntime(thing.asCell());
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
/*
|
||||
* GC things residing in the nursery cannot be gray: they have no mark bits.
|
||||
* All live objects in the nursery are moved to tenured at the beginning of
|
||||
* each GC slice, so the gray marker never sees nursery things.
|
||||
*/
|
||||
if (IsInsideNursery((Cell *)thing))
|
||||
if (IsInsideNursery(thing.asCell()))
|
||||
return;
|
||||
#endif
|
||||
if (JS::IsIncrementalBarrierNeededOnTenuredGCThing(rt, thing, kind))
|
||||
JS::IncrementalReferenceBarrier(thing, kind);
|
||||
else if (JS::GCThingIsMarkedGray(thing))
|
||||
JS::UnmarkGrayGCThingRecursively(thing, kind);
|
||||
if (IsIncrementalBarrierNeededOnTenuredGCThing(rt, thing))
|
||||
JS::IncrementalReferenceBarrier(thing);
|
||||
else if (JS::GCThingIsMarkedGray(thing.asCell()))
|
||||
JS::UnmarkGrayGCThingRecursively(thing.asCell(), thing.kind());
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE void
|
||||
MarkGCThingAsLive(JSRuntime *aRt, JS::GCCellPtr thing)
|
||||
{
|
||||
JS::shadow::Runtime *rt = JS::shadow::Runtime::asShadowRuntime(aRt);
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
/*
|
||||
* Any object in the nursery will not be freed during any GC running at that time.
|
||||
*/
|
||||
if (IsInsideNursery(thing.asCell()))
|
||||
return;
|
||||
#endif
|
||||
if (IsIncrementalBarrierNeededOnTenuredGCThing(rt, thing))
|
||||
JS::IncrementalReferenceBarrier(thing);
|
||||
}
|
||||
|
||||
} /* namespace gc */
|
||||
@ -513,38 +528,23 @@ namespace JS {
|
||||
static MOZ_ALWAYS_INLINE void
|
||||
ExposeObjectToActiveJS(JSObject *obj)
|
||||
{
|
||||
js::gc::ExposeGCThingToActiveJS(obj, JSTRACE_OBJECT);
|
||||
js::gc::ExposeGCThingToActiveJS(GCCellPtr(obj));
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE void
|
||||
ExposeScriptToActiveJS(JSScript *script)
|
||||
{
|
||||
js::gc::ExposeGCThingToActiveJS(script, JSTRACE_SCRIPT);
|
||||
js::gc::ExposeGCThingToActiveJS(GCCellPtr(script));
|
||||
}
|
||||
|
||||
/*
|
||||
* If a GC is currently marking, mark the object black.
|
||||
* If a GC is currently marking, mark the string black.
|
||||
*/
|
||||
static MOZ_ALWAYS_INLINE void
|
||||
MarkGCThingAsLive(JSRuntime *rt_, void *thing, JSGCTraceKind kind)
|
||||
{
|
||||
shadow::Runtime *rt = shadow::Runtime::asShadowRuntime(rt_);
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
/*
|
||||
* Any object in the nursery will not be freed during any GC running at that time.
|
||||
*/
|
||||
if (js::gc::IsInsideNursery((js::gc::Cell *)thing))
|
||||
return;
|
||||
#endif
|
||||
if (IsIncrementalBarrierNeededOnTenuredGCThing(rt, thing, kind))
|
||||
IncrementalReferenceBarrier(thing, kind);
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE void
|
||||
MarkStringAsLive(Zone *zone, JSString *string)
|
||||
{
|
||||
JSRuntime *rt = JS::shadow::Zone::asShadowZone(zone)->runtimeFromMainThread();
|
||||
MarkGCThingAsLive(rt, string, JSTRACE_STRING);
|
||||
js::gc::MarkGCThingAsLive(rt, GCCellPtr(string));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -9,8 +9,7 @@
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "jspubtd.h"
|
||||
|
||||
#include "js/TracingAPI.h"
|
||||
#include "js/Utility.h"
|
||||
|
||||
/* These values are private to the JS engine. */
|
||||
@ -204,6 +203,95 @@ struct Zone
|
||||
};
|
||||
|
||||
} /* namespace shadow */
|
||||
|
||||
// A GC pointer, tagged with the trace kind.
|
||||
//
|
||||
// In general, a GC pointer should be stored with an exact type. This class
|
||||
// is for use when that is not possible because a single pointer must point
|
||||
// to several kinds of GC thing.
|
||||
class JS_FRIEND_API(GCCellPtr)
|
||||
{
|
||||
typedef void (GCCellPtr::* ConvertibleToBool)();
|
||||
void nonNull() {}
|
||||
|
||||
public:
|
||||
// Construction from a void* and trace kind.
|
||||
GCCellPtr(void *gcthing, JSGCTraceKind traceKind) : ptr(checkedCast(gcthing, traceKind)) {}
|
||||
|
||||
// Construction from an explicit type.
|
||||
explicit GCCellPtr(JSObject *obj) : ptr(checkedCast(obj, JSTRACE_OBJECT)) { }
|
||||
explicit GCCellPtr(JSFunction *fun) : ptr(checkedCast(fun, JSTRACE_OBJECT)) { }
|
||||
explicit GCCellPtr(JSString *str) : ptr(checkedCast(str, JSTRACE_STRING)) { }
|
||||
explicit GCCellPtr(JSFlatString *str) : ptr(checkedCast(str, JSTRACE_STRING)) { }
|
||||
explicit GCCellPtr(JSScript *script) : ptr(checkedCast(script, JSTRACE_SCRIPT)) { }
|
||||
explicit GCCellPtr(const Value &v);
|
||||
|
||||
// Not all compilers have nullptr_t yet, so use this instead of GCCellPtr(nullptr).
|
||||
static GCCellPtr NullPtr() { return GCCellPtr(nullptr, JSTRACE_NULL); }
|
||||
|
||||
JSGCTraceKind kind() const {
|
||||
JSGCTraceKind traceKind = JSGCTraceKind(ptr & JSTRACE_OUTOFLINE);
|
||||
if (traceKind != JSTRACE_OUTOFLINE)
|
||||
return traceKind;
|
||||
return outOfLineKind();
|
||||
}
|
||||
|
||||
// Allow GCCellPtr to be used in a boolean context.
|
||||
operator ConvertibleToBool() const {
|
||||
MOZ_ASSERT(bool(asCell()) == (kind() != JSTRACE_NULL));
|
||||
return asCell() ? &GCCellPtr::nonNull : 0;
|
||||
}
|
||||
|
||||
// Simplify checks to the kind.
|
||||
bool isObject() const { return kind() == JSTRACE_OBJECT; }
|
||||
bool isScript() const { return kind() == JSTRACE_SCRIPT; }
|
||||
bool isString() const { return kind() == JSTRACE_STRING; }
|
||||
bool isSymbol() const { return kind() == JSTRACE_SYMBOL; }
|
||||
|
||||
// Conversions to more specific types must match the kind. Access to
|
||||
// further refined types is not allowed directly from a GCCellPtr.
|
||||
JSObject *toObject() const {
|
||||
MOZ_ASSERT(kind() == JSTRACE_OBJECT);
|
||||
return reinterpret_cast<JSObject *>(asCell());
|
||||
}
|
||||
JSString *toString() const {
|
||||
MOZ_ASSERT(kind() == JSTRACE_STRING);
|
||||
return reinterpret_cast<JSString *>(asCell());
|
||||
}
|
||||
JSScript *toScript() const {
|
||||
MOZ_ASSERT(kind() == JSTRACE_SCRIPT);
|
||||
return reinterpret_cast<JSScript *>(asCell());
|
||||
}
|
||||
Symbol *toSymbol() const {
|
||||
MOZ_ASSERT(kind() == JSTRACE_SYMBOL);
|
||||
return reinterpret_cast<Symbol *>(asCell());
|
||||
}
|
||||
js::gc::Cell *asCell() const {
|
||||
return reinterpret_cast<js::gc::Cell *>(ptr & ~JSTRACE_OUTOFLINE);
|
||||
}
|
||||
|
||||
// The CC's trace logger needs an identity that is XPIDL serializable.
|
||||
void *unsafeGetUntypedPtr() const {
|
||||
return reinterpret_cast<void *>(asCell());
|
||||
}
|
||||
|
||||
private:
|
||||
uintptr_t checkedCast(void *p, JSGCTraceKind traceKind) {
|
||||
js::gc::Cell *cell = static_cast<js::gc::Cell *>(p);
|
||||
MOZ_ASSERT((uintptr_t(p) & JSTRACE_OUTOFLINE) == 0);
|
||||
AssertGCThingHasType(cell, traceKind);
|
||||
// Note: the JSTRACE_OUTOFLINE bits are set on all out-of-line kinds
|
||||
// so that we can mask instead of branching.
|
||||
MOZ_ASSERT_IF(traceKind >= JSTRACE_OUTOFLINE,
|
||||
(traceKind & JSTRACE_OUTOFLINE) == JSTRACE_OUTOFLINE);
|
||||
return uintptr_t(p) | (traceKind & JSTRACE_OUTOFLINE);
|
||||
}
|
||||
|
||||
JSGCTraceKind outOfLineKind() const;
|
||||
|
||||
uintptr_t ptr;
|
||||
};
|
||||
|
||||
} /* namespace JS */
|
||||
|
||||
namespace js {
|
||||
@ -268,7 +356,6 @@ IsInsideNursery(const js::gc::Cell *cell)
|
||||
}
|
||||
|
||||
} /* namespace gc */
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
namespace JS {
|
||||
@ -304,19 +391,25 @@ GCThingIsMarkedGray(void *thing)
|
||||
return *word & mask;
|
||||
}
|
||||
|
||||
} /* namespace JS */
|
||||
|
||||
namespace js {
|
||||
namespace gc {
|
||||
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
IsIncrementalBarrierNeededOnTenuredGCThing(shadow::Runtime *rt, void *thing, JSGCTraceKind kind)
|
||||
IsIncrementalBarrierNeededOnTenuredGCThing(JS::shadow::Runtime *rt, const JS::GCCellPtr thing)
|
||||
{
|
||||
MOZ_ASSERT(thing);
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
MOZ_ASSERT(!js::gc::IsInsideNursery((js::gc::Cell *)thing));
|
||||
MOZ_ASSERT(!js::gc::IsInsideNursery(thing.asCell()));
|
||||
#endif
|
||||
if (!rt->needsIncrementalBarrier())
|
||||
return false;
|
||||
JS::Zone *zone = GetTenuredGCThingZone(thing);
|
||||
return reinterpret_cast<shadow::Zone *>(zone)->needsIncrementalBarrier();
|
||||
JS::Zone *zone = JS::GetTenuredGCThingZone(thing.asCell());
|
||||
return JS::shadow::Zone::asShadowZone(zone)->needsIncrementalBarrier();
|
||||
}
|
||||
|
||||
} /* namespace JS */
|
||||
} /* namespace gc */
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* js_HeapAPI_h */
|
||||
|
@ -21,6 +21,49 @@ template <typename T> class Heap;
|
||||
template <typename T> class TenuredHeap;
|
||||
}
|
||||
|
||||
// When tracing a thing, the GC needs to know about the layout of the object it
|
||||
// is looking at. There are a fixed number of different layouts that the GC
|
||||
// knows about. The "trace kind" is a static map which tells which layout a GC
|
||||
// thing has.
|
||||
//
|
||||
// Although this map is public, the details are completely hidden. Not all of
|
||||
// the matching C++ types are exposed, and those that are, are opaque.
|
||||
//
|
||||
// See Value::gcKind() and JSTraceCallback in Tracer.h for more details.
|
||||
enum JSGCTraceKind
|
||||
{
|
||||
// These trace kinds have a publicly exposed, although opaque, C++ type.
|
||||
// Note: The order here is determined by our Value packing. Other users
|
||||
// should sort alphabetically, for consistency.
|
||||
JSTRACE_OBJECT = 0x00,
|
||||
JSTRACE_STRING = 0x01,
|
||||
JSTRACE_SYMBOL = 0x02,
|
||||
JSTRACE_SCRIPT = 0x03,
|
||||
|
||||
// Shape details are exposed through JS_TraceShapeCycleCollectorChildren.
|
||||
JSTRACE_SHAPE = 0x04,
|
||||
|
||||
// The kind associated with a nullptr.
|
||||
JSTRACE_NULL = 0x06,
|
||||
|
||||
// A kind that indicates the real kind should be looked up in the arena.
|
||||
JSTRACE_OUTOFLINE = 0x07,
|
||||
|
||||
// The following kinds do not have an exposed C++ idiom.
|
||||
JSTRACE_BASE_SHAPE = 0x0F,
|
||||
JSTRACE_JITCODE = 0x1F,
|
||||
JSTRACE_LAZY_SCRIPT = 0x2F,
|
||||
JSTRACE_TYPE_OBJECT = 0x3F,
|
||||
|
||||
JSTRACE_LAST = JSTRACE_TYPE_OBJECT
|
||||
};
|
||||
|
||||
namespace JS {
|
||||
// Returns a static string equivalent of |kind|.
|
||||
JS_FRIEND_API(const char *)
|
||||
GCTraceKindToAscii(JSGCTraceKind kind);
|
||||
}
|
||||
|
||||
// Tracer callback, called for each traceable thing directly referenced by a
|
||||
// particular object or runtime structure. It is the callback responsibility
|
||||
// to ensure the traversal of the full object graph via calling eventually
|
||||
|
@ -1369,7 +1369,7 @@ static MOZ_ALWAYS_INLINE void
|
||||
ExposeValueToActiveJS(const Value &v)
|
||||
{
|
||||
if (v.isMarkable())
|
||||
js::gc::ExposeGCThingToActiveJS(v.toGCThing(), v.gcKind());
|
||||
js::gc::ExposeGCThingToActiveJS(GCCellPtr(v));
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
@ -689,14 +689,20 @@ gc::MarkKind(JSTracer *trc, void **thingp, JSGCTraceKind kind)
|
||||
case JSTRACE_OBJECT:
|
||||
MarkInternal(trc, reinterpret_cast<JSObject **>(thingp));
|
||||
break;
|
||||
case JSTRACE_SCRIPT:
|
||||
MarkInternal(trc, reinterpret_cast<JSScript **>(thingp));
|
||||
break;
|
||||
case JSTRACE_STRING:
|
||||
MarkInternal(trc, reinterpret_cast<JSString **>(thingp));
|
||||
break;
|
||||
case JSTRACE_SYMBOL:
|
||||
MarkInternal(trc, reinterpret_cast<JS::Symbol **>(thingp));
|
||||
break;
|
||||
case JSTRACE_SCRIPT:
|
||||
MarkInternal(trc, reinterpret_cast<JSScript **>(thingp));
|
||||
case JSTRACE_BASE_SHAPE:
|
||||
MarkInternal(trc, reinterpret_cast<BaseShape **>(thingp));
|
||||
break;
|
||||
case JSTRACE_JITCODE:
|
||||
MarkInternal(trc, reinterpret_cast<jit::JitCode **>(thingp));
|
||||
break;
|
||||
case JSTRACE_LAZY_SCRIPT:
|
||||
MarkInternal(trc, reinterpret_cast<LazyScript **>(thingp));
|
||||
@ -704,15 +710,11 @@ gc::MarkKind(JSTracer *trc, void **thingp, JSGCTraceKind kind)
|
||||
case JSTRACE_SHAPE:
|
||||
MarkInternal(trc, reinterpret_cast<Shape **>(thingp));
|
||||
break;
|
||||
case JSTRACE_BASE_SHAPE:
|
||||
MarkInternal(trc, reinterpret_cast<BaseShape **>(thingp));
|
||||
break;
|
||||
case JSTRACE_TYPE_OBJECT:
|
||||
MarkInternal(trc, reinterpret_cast<types::TypeObject **>(thingp));
|
||||
break;
|
||||
case JSTRACE_JITCODE:
|
||||
MarkInternal(trc, reinterpret_cast<jit::JitCode **>(thingp));
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Invalid trace kind in MarkKind.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1542,6 +1544,10 @@ gc::PushArena(GCMarker *gcmarker, ArenaHeader *aheader)
|
||||
PushArenaTyped<JSObject>(gcmarker, aheader);
|
||||
break;
|
||||
|
||||
case JSTRACE_SCRIPT:
|
||||
PushArenaTyped<JSScript>(gcmarker, aheader);
|
||||
break;
|
||||
|
||||
case JSTRACE_STRING:
|
||||
PushArenaTyped<JSString>(gcmarker, aheader);
|
||||
break;
|
||||
@ -1550,8 +1556,12 @@ gc::PushArena(GCMarker *gcmarker, ArenaHeader *aheader)
|
||||
PushArenaTyped<JS::Symbol>(gcmarker, aheader);
|
||||
break;
|
||||
|
||||
case JSTRACE_SCRIPT:
|
||||
PushArenaTyped<JSScript>(gcmarker, aheader);
|
||||
case JSTRACE_BASE_SHAPE:
|
||||
PushArenaTyped<js::BaseShape>(gcmarker, aheader);
|
||||
break;
|
||||
|
||||
case JSTRACE_JITCODE:
|
||||
PushArenaTyped<js::jit::JitCode>(gcmarker, aheader);
|
||||
break;
|
||||
|
||||
case JSTRACE_LAZY_SCRIPT:
|
||||
@ -1562,17 +1572,12 @@ gc::PushArena(GCMarker *gcmarker, ArenaHeader *aheader)
|
||||
PushArenaTyped<js::Shape>(gcmarker, aheader);
|
||||
break;
|
||||
|
||||
case JSTRACE_BASE_SHAPE:
|
||||
PushArenaTyped<js::BaseShape>(gcmarker, aheader);
|
||||
break;
|
||||
|
||||
case JSTRACE_TYPE_OBJECT:
|
||||
PushArenaTyped<js::types::TypeObject>(gcmarker, aheader);
|
||||
break;
|
||||
|
||||
case JSTRACE_JITCODE:
|
||||
PushArenaTyped<js::jit::JitCode>(gcmarker, aheader);
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Invalid trace kind in PushArena.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1946,6 +1951,10 @@ js::TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind)
|
||||
MarkChildren(trc, static_cast<JSObject *>(thing));
|
||||
break;
|
||||
|
||||
case JSTRACE_SCRIPT:
|
||||
MarkChildren(trc, static_cast<JSScript *>(thing));
|
||||
break;
|
||||
|
||||
case JSTRACE_STRING:
|
||||
MarkChildren(trc, static_cast<JSString *>(thing));
|
||||
break;
|
||||
@ -1954,8 +1963,12 @@ js::TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind)
|
||||
MarkChildren(trc, static_cast<JS::Symbol *>(thing));
|
||||
break;
|
||||
|
||||
case JSTRACE_SCRIPT:
|
||||
MarkChildren(trc, static_cast<JSScript *>(thing));
|
||||
case JSTRACE_BASE_SHAPE:
|
||||
MarkChildren(trc, static_cast<BaseShape *>(thing));
|
||||
break;
|
||||
|
||||
case JSTRACE_JITCODE:
|
||||
MarkChildren(trc, (js::jit::JitCode *)thing);
|
||||
break;
|
||||
|
||||
case JSTRACE_LAZY_SCRIPT:
|
||||
@ -1966,17 +1979,12 @@ js::TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind)
|
||||
MarkChildren(trc, static_cast<Shape *>(thing));
|
||||
break;
|
||||
|
||||
case JSTRACE_JITCODE:
|
||||
MarkChildren(trc, (js::jit::JitCode *)thing);
|
||||
break;
|
||||
|
||||
case JSTRACE_BASE_SHAPE:
|
||||
MarkChildren(trc, static_cast<BaseShape *>(thing));
|
||||
break;
|
||||
|
||||
case JSTRACE_TYPE_OBJECT:
|
||||
MarkChildren(trc, (types::TypeObject *)thing);
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Invalid trace kind in TraceChildren.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -405,36 +405,6 @@ ToMarkable(Cell *cell)
|
||||
return cell;
|
||||
}
|
||||
|
||||
inline JSGCTraceKind
|
||||
TraceKind(const Value &v)
|
||||
{
|
||||
MOZ_ASSERT(v.isMarkable());
|
||||
if (v.isObject())
|
||||
return JSTRACE_OBJECT;
|
||||
if (v.isString())
|
||||
return JSTRACE_STRING;
|
||||
MOZ_ASSERT(v.isSymbol());
|
||||
return JSTRACE_SYMBOL;
|
||||
}
|
||||
|
||||
inline JSGCTraceKind
|
||||
TraceKind(JSObject *obj)
|
||||
{
|
||||
return JSTRACE_OBJECT;
|
||||
}
|
||||
|
||||
inline JSGCTraceKind
|
||||
TraceKind(JSScript *script)
|
||||
{
|
||||
return JSTRACE_SCRIPT;
|
||||
}
|
||||
|
||||
inline JSGCTraceKind
|
||||
TraceKind(LazyScript *lazy)
|
||||
{
|
||||
return JSTRACE_LAZY_SCRIPT;
|
||||
}
|
||||
|
||||
} /* namespace gc */
|
||||
|
||||
void
|
||||
|
@ -203,6 +203,10 @@ JS_GetTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc, void *thing,
|
||||
break;
|
||||
}
|
||||
|
||||
case JSTRACE_SCRIPT:
|
||||
name = "script";
|
||||
break;
|
||||
|
||||
case JSTRACE_STRING:
|
||||
name = ((JSString *)thing)->isDependent()
|
||||
? "substring"
|
||||
@ -213,29 +217,29 @@ JS_GetTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc, void *thing,
|
||||
name = "symbol";
|
||||
break;
|
||||
|
||||
case JSTRACE_SCRIPT:
|
||||
name = "script";
|
||||
break;
|
||||
|
||||
case JSTRACE_LAZY_SCRIPT:
|
||||
name = "lazyscript";
|
||||
case JSTRACE_BASE_SHAPE:
|
||||
name = "base_shape";
|
||||
break;
|
||||
|
||||
case JSTRACE_JITCODE:
|
||||
name = "jitcode";
|
||||
break;
|
||||
|
||||
case JSTRACE_LAZY_SCRIPT:
|
||||
name = "lazyscript";
|
||||
break;
|
||||
|
||||
case JSTRACE_SHAPE:
|
||||
name = "shape";
|
||||
break;
|
||||
|
||||
case JSTRACE_BASE_SHAPE:
|
||||
name = "base_shape";
|
||||
break;
|
||||
|
||||
case JSTRACE_TYPE_OBJECT:
|
||||
name = "type_object";
|
||||
break;
|
||||
|
||||
default:
|
||||
name = "INVALID";
|
||||
break;
|
||||
}
|
||||
|
||||
n = strlen(name);
|
||||
@ -266,6 +270,13 @@ JS_GetTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc, void *thing,
|
||||
break;
|
||||
}
|
||||
|
||||
case JSTRACE_SCRIPT:
|
||||
{
|
||||
JSScript *script = static_cast<JSScript *>(thing);
|
||||
JS_snprintf(buf, bufsize, " %s:%u", script->filename(), unsigned(script->lineno()));
|
||||
break;
|
||||
}
|
||||
|
||||
case JSTRACE_STRING:
|
||||
{
|
||||
*buf++ = ' ';
|
||||
@ -306,18 +317,7 @@ JS_GetTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc, void *thing,
|
||||
break;
|
||||
}
|
||||
|
||||
case JSTRACE_SCRIPT:
|
||||
{
|
||||
JSScript *script = static_cast<JSScript *>(thing);
|
||||
JS_snprintf(buf, bufsize, " %s:%u", script->filename(), unsigned(script->lineno()));
|
||||
break;
|
||||
}
|
||||
|
||||
case JSTRACE_LAZY_SCRIPT:
|
||||
case JSTRACE_JITCODE:
|
||||
case JSTRACE_SHAPE:
|
||||
case JSTRACE_BASE_SHAPE:
|
||||
case JSTRACE_TYPE_OBJECT:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ UNIFIED_SOURCES += [
|
||||
'testFreshGlobalEvalRedefinition.cpp',
|
||||
'testFunctionProperties.cpp',
|
||||
'testGCAllocator.cpp',
|
||||
'testGCCellPtr.cpp',
|
||||
'testGCChunkPool.cpp',
|
||||
'testGCExactRooting.cpp',
|
||||
'testGCFinalizeCallback.cpp',
|
||||
|
61
js/src/jsapi-tests/testGCCellPtr.cpp
Normal file
61
js/src/jsapi-tests/testGCCellPtr.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jspubtd.h"
|
||||
|
||||
#include "gc/Heap.h"
|
||||
|
||||
#include "jsapi-tests/tests.h"
|
||||
|
||||
JS::GCCellPtr
|
||||
GivesAndTakesCells(JS::GCCellPtr cell)
|
||||
{
|
||||
return cell;
|
||||
}
|
||||
|
||||
BEGIN_TEST(testGCCellPtr)
|
||||
{
|
||||
JS::RootedObject obj(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr()));
|
||||
CHECK(obj);
|
||||
|
||||
JS::RootedString str(cx, JS_NewStringCopyZ(cx, "probably foobar"));
|
||||
CHECK(str);
|
||||
|
||||
const char *code = "function foo() { return 'bar'; }";
|
||||
JS::CompileOptions opts(cx);
|
||||
JS::RootedScript script(cx);
|
||||
CHECK(JS_CompileScript(cx, obj, code, strlen(code), opts, &script));
|
||||
CHECK(script);
|
||||
|
||||
CHECK(!JS::GCCellPtr::NullPtr());
|
||||
|
||||
CHECK(JS::GCCellPtr(obj.get()));
|
||||
CHECK(JS::GCCellPtr(obj.get()).kind() == JSTRACE_OBJECT);
|
||||
CHECK(JS::GCCellPtr(JS::ObjectValue(*obj)).kind() == JSTRACE_OBJECT);
|
||||
|
||||
CHECK(JS::GCCellPtr(str.get()));
|
||||
CHECK(JS::GCCellPtr(str.get()).kind() == JSTRACE_STRING);
|
||||
CHECK(JS::GCCellPtr(JS::StringValue(str)).kind() == JSTRACE_STRING);
|
||||
|
||||
CHECK(JS::GCCellPtr(script.get()));
|
||||
CHECK(!JS::GCCellPtr::NullPtr());
|
||||
CHECK(JS::GCCellPtr(script.get()).kind() == JSTRACE_SCRIPT);
|
||||
|
||||
JS::GCCellPtr objcell(obj.get());
|
||||
JS::GCCellPtr scriptcell = JS::GCCellPtr(script.get());
|
||||
CHECK(GivesAndTakesCells(objcell));
|
||||
CHECK(GivesAndTakesCells(scriptcell));
|
||||
|
||||
JS::GCCellPtr copy = objcell;
|
||||
CHECK(copy == objcell);
|
||||
|
||||
CHECK(js::gc::GetGCThingRuntime(scriptcell.asCell()) == rt);
|
||||
|
||||
return true;
|
||||
}
|
||||
END_TEST(testGCCellPtr)
|
@ -1178,43 +1178,39 @@ JS::IncrementalObjectBarrier(JSObject *obj)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
JS::IncrementalReferenceBarrier(void *ptr, JSGCTraceKind kind)
|
||||
JS::IncrementalReferenceBarrier(GCCellPtr thing)
|
||||
{
|
||||
if (!ptr)
|
||||
if (!thing)
|
||||
return;
|
||||
|
||||
if (kind == JSTRACE_STRING && StringIsPermanentAtom(static_cast<JSString *>(ptr)))
|
||||
if (thing.isString() && StringIsPermanentAtom(thing.toString()))
|
||||
return;
|
||||
|
||||
gc::Cell *cell = static_cast<gc::Cell *>(ptr);
|
||||
|
||||
#ifdef DEBUG
|
||||
Zone *zone = kind == JSTRACE_OBJECT
|
||||
? static_cast<JSObject *>(cell)->zone()
|
||||
: cell->asTenured().zone();
|
||||
Zone *zone = thing.isObject()
|
||||
? thing.toObject()->zone()
|
||||
: thing.asCell()->asTenured().zone();
|
||||
MOZ_ASSERT(!zone->runtimeFromMainThread()->isHeapMajorCollecting());
|
||||
#endif
|
||||
|
||||
if (kind == JSTRACE_OBJECT)
|
||||
JSObject::writeBarrierPre(static_cast<JSObject*>(cell));
|
||||
else if (kind == JSTRACE_STRING)
|
||||
JSString::writeBarrierPre(static_cast<JSString*>(cell));
|
||||
else if (kind == JSTRACE_SYMBOL)
|
||||
JS::Symbol::writeBarrierPre(static_cast<JS::Symbol*>(cell));
|
||||
else if (kind == JSTRACE_SCRIPT)
|
||||
JSScript::writeBarrierPre(static_cast<JSScript*>(cell));
|
||||
else if (kind == JSTRACE_LAZY_SCRIPT)
|
||||
LazyScript::writeBarrierPre(static_cast<LazyScript*>(cell));
|
||||
else if (kind == JSTRACE_JITCODE)
|
||||
jit::JitCode::writeBarrierPre(static_cast<jit::JitCode*>(cell));
|
||||
else if (kind == JSTRACE_SHAPE)
|
||||
Shape::writeBarrierPre(static_cast<Shape*>(cell));
|
||||
else if (kind == JSTRACE_BASE_SHAPE)
|
||||
BaseShape::writeBarrierPre(static_cast<BaseShape*>(cell));
|
||||
else if (kind == JSTRACE_TYPE_OBJECT)
|
||||
types::TypeObject::writeBarrierPre(static_cast<types::TypeObject *>(cell));
|
||||
else
|
||||
MOZ_CRASH("invalid trace kind");
|
||||
switch(thing.kind()) {
|
||||
case JSTRACE_OBJECT: return JSObject::writeBarrierPre(thing.toObject());
|
||||
case JSTRACE_STRING: return JSString::writeBarrierPre(thing.toString());
|
||||
case JSTRACE_SCRIPT: return JSScript::writeBarrierPre(thing.toScript());
|
||||
case JSTRACE_SYMBOL: return JS::Symbol::writeBarrierPre(thing.toSymbol());
|
||||
case JSTRACE_LAZY_SCRIPT:
|
||||
return LazyScript::writeBarrierPre(static_cast<LazyScript*>(thing.asCell()));
|
||||
case JSTRACE_JITCODE:
|
||||
return jit::JitCode::writeBarrierPre(static_cast<jit::JitCode*>(thing.asCell()));
|
||||
case JSTRACE_SHAPE:
|
||||
return Shape::writeBarrierPre(static_cast<Shape*>(thing.asCell()));
|
||||
case JSTRACE_BASE_SHAPE:
|
||||
return BaseShape::writeBarrierPre(static_cast<BaseShape*>(thing.asCell()));
|
||||
case JSTRACE_TYPE_OBJECT:
|
||||
return types::TypeObject::writeBarrierPre(static_cast<types::TypeObject *>(thing.asCell()));
|
||||
default:
|
||||
MOZ_CRASH("Invalid trace kind in IncrementalReferenceBarrier.");
|
||||
}
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
|
@ -493,9 +493,7 @@ struct WeakMapTracer;
|
||||
* m will be nullptr if the weak map is not contained in a JS Object.
|
||||
*/
|
||||
typedef void
|
||||
(* WeakMapTraceCallback)(WeakMapTracer *trc, JSObject *m,
|
||||
void *k, JSGCTraceKind kkind,
|
||||
void *v, JSGCTraceKind vkind);
|
||||
(* WeakMapTraceCallback)(WeakMapTracer *trc, JSObject *m, JS::GCCellPtr key, JS::GCCellPtr value);
|
||||
|
||||
struct WeakMapTracer {
|
||||
JSRuntime *runtime;
|
||||
|
@ -328,23 +328,6 @@ const uint32_t Arena::FirstThingOffsets[] = {
|
||||
|
||||
#undef OFFSET
|
||||
|
||||
const char *
|
||||
js::gc::TraceKindAsAscii(JSGCTraceKind kind)
|
||||
{
|
||||
switch(kind) {
|
||||
case JSTRACE_OBJECT: return "JSTRACE_OBJECT";
|
||||
case JSTRACE_STRING: return "JSTRACE_STRING";
|
||||
case JSTRACE_SYMBOL: return "JSTRACE_SYMBOL";
|
||||
case JSTRACE_SCRIPT: return "JSTRACE_SCRIPT";
|
||||
case JSTRACE_LAZY_SCRIPT: return "JSTRACE_SCRIPT";
|
||||
case JSTRACE_JITCODE: return "JSTRACE_JITCODE";
|
||||
case JSTRACE_SHAPE: return "JSTRACE_SHAPE";
|
||||
case JSTRACE_BASE_SHAPE: return "JSTRACE_BASE_SHAPE";
|
||||
case JSTRACE_TYPE_OBJECT: return "JSTRACE_TYPE_OBJECT";
|
||||
default: return "INVALID";
|
||||
}
|
||||
}
|
||||
|
||||
struct js::gc::FinalizePhase
|
||||
{
|
||||
size_t length;
|
||||
@ -6956,8 +6939,9 @@ JS::AssertGCThingMustBeTenured(JSObject *obj)
|
||||
JS_FRIEND_API(void)
|
||||
js::gc::AssertGCThingHasType(js::gc::Cell *cell, JSGCTraceKind kind)
|
||||
{
|
||||
MOZ_ASSERT(cell);
|
||||
if (IsInsideNursery(cell))
|
||||
if (!cell)
|
||||
MOZ_ASSERT(kind == JSTRACE_NULL);
|
||||
else if (IsInsideNursery(cell))
|
||||
MOZ_ASSERT(kind == JSTRACE_OBJECT);
|
||||
else
|
||||
MOZ_ASSERT(MapAllocToTraceKind(cell->asTenured().getAllocKind()) == kind);
|
||||
@ -7046,6 +7030,44 @@ JS::AutoAssertGCCallback::AutoAssertGCCallback(JSObject *obj)
|
||||
MOZ_ASSERT(obj->runtimeFromMainThread()->isHeapMajorCollecting());
|
||||
}
|
||||
|
||||
JS_FRIEND_API(const char *)
|
||||
JS::GCTraceKindToAscii(JSGCTraceKind kind)
|
||||
{
|
||||
switch(kind) {
|
||||
case JSTRACE_OBJECT: return "Object";
|
||||
case JSTRACE_SCRIPT: return "Script";
|
||||
case JSTRACE_STRING: return "String";
|
||||
case JSTRACE_SYMBOL: return "Symbol";
|
||||
case JSTRACE_SHAPE: return "Shape";
|
||||
case JSTRACE_BASE_SHAPE: return "BaseShape";
|
||||
case JSTRACE_LAZY_SCRIPT: return "LazyScript";
|
||||
case JSTRACE_JITCODE: return "JitCode";
|
||||
case JSTRACE_TYPE_OBJECT: return "TypeObject";
|
||||
default: return "Invalid";
|
||||
}
|
||||
}
|
||||
|
||||
JS::GCCellPtr::GCCellPtr(const Value &v)
|
||||
: ptr(0)
|
||||
{
|
||||
if (v.isString())
|
||||
ptr = checkedCast(v.toString(), JSTRACE_STRING);
|
||||
else if (v.isObject())
|
||||
ptr = checkedCast(&v.toObject(), JSTRACE_OBJECT);
|
||||
else if (v.isSymbol())
|
||||
ptr = checkedCast(v.toSymbol(), JSTRACE_SYMBOL);
|
||||
else
|
||||
ptr = checkedCast(nullptr, JSTRACE_NULL);
|
||||
}
|
||||
|
||||
JSGCTraceKind
|
||||
JS::GCCellPtr::outOfLineKind() const
|
||||
{
|
||||
MOZ_ASSERT(JSGCTraceKind(ptr & JSTRACE_OUTOFLINE) == JSTRACE_OUTOFLINE);
|
||||
MOZ_ASSERT(asCell()->isTenured());
|
||||
return MapAllocToTraceKind(asCell()->asTenured().getAllocKind());
|
||||
}
|
||||
|
||||
#ifdef JSGC_HASH_TABLE_CHECKS
|
||||
void
|
||||
js::gc::CheckHashTablesAfterMovingGC(JSRuntime *rt)
|
||||
|
@ -61,10 +61,6 @@ enum State {
|
||||
COMPACT
|
||||
};
|
||||
|
||||
/* Return a printable string for the given kind, for diagnostic purposes. */
|
||||
const char *
|
||||
TraceKindAsAscii(JSGCTraceKind kind);
|
||||
|
||||
/* Map from C++ type to alloc kind. JSObject does not have a 1:1 mapping, so must use Arena::thingSize. */
|
||||
template <typename T> struct MapTypeToFinalizeKind {};
|
||||
template <> struct MapTypeToFinalizeKind<JSScript> { static const AllocKind kind = FINALIZE_SCRIPT; };
|
||||
|
@ -102,25 +102,6 @@ enum JSIterateOp {
|
||||
JSENUMERATE_DESTROY
|
||||
};
|
||||
|
||||
/* See Value::gcKind() and JSTraceCallback in Tracer.h. */
|
||||
enum JSGCTraceKind {
|
||||
JSTRACE_OBJECT,
|
||||
JSTRACE_STRING,
|
||||
JSTRACE_SYMBOL,
|
||||
JSTRACE_SCRIPT,
|
||||
|
||||
/*
|
||||
* Trace kinds internal to the engine. The embedding can only see them if
|
||||
* it implements JSTraceCallback.
|
||||
*/
|
||||
JSTRACE_LAZY_SCRIPT,
|
||||
JSTRACE_JITCODE,
|
||||
JSTRACE_SHAPE,
|
||||
JSTRACE_BASE_SHAPE,
|
||||
JSTRACE_TYPE_OBJECT,
|
||||
JSTRACE_LAST = JSTRACE_TYPE_OBJECT
|
||||
};
|
||||
|
||||
/* Struct forward declarations. */
|
||||
struct JSClass;
|
||||
struct JSCompartment;
|
||||
|
@ -537,26 +537,6 @@ js_str_toString(JSContext *cx, unsigned argc, Value *vp)
|
||||
* Java-like string native methods.
|
||||
*/
|
||||
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
ValueToIntegerRange(JSContext *cx, HandleValue v, int32_t *out)
|
||||
{
|
||||
if (v.isInt32()) {
|
||||
*out = v.toInt32();
|
||||
} else {
|
||||
double d;
|
||||
if (!ToInteger(cx, v, &d))
|
||||
return false;
|
||||
if (d > INT32_MAX)
|
||||
*out = INT32_MAX;
|
||||
else if (d < INT32_MIN)
|
||||
*out = INT32_MIN;
|
||||
else
|
||||
*out = int32_t(d);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
JSString *
|
||||
js::SubstringKernel(JSContext *cx, HandleString str, int32_t beginInt, int32_t lengthInt)
|
||||
{
|
||||
|
@ -246,7 +246,7 @@ WatchpointMap::trace(WeakMapTracer *trc)
|
||||
for (Map::Range r = map.all(); !r.empty(); r.popFront()) {
|
||||
Map::Entry &entry = r.front();
|
||||
trc->callback(trc, nullptr,
|
||||
entry.key().object.get(), JSTRACE_OBJECT,
|
||||
entry.value().closure.get(), JSTRACE_OBJECT);
|
||||
JS::GCCellPtr(entry.key().object.get()),
|
||||
JS::GCCellPtr(entry.value().closure.get()));
|
||||
}
|
||||
}
|
||||
|
@ -251,8 +251,8 @@ class WeakMap : public HashMap<Key, Value, HashPolicy, RuntimeAllocPolicy>, publ
|
||||
gc::Cell *value = gc::ToMarkable(r.front().value());
|
||||
if (key && value) {
|
||||
tracer->callback(tracer, memberOf,
|
||||
key, gc::TraceKind(r.front().key()),
|
||||
value, gc::TraceKind(r.front().value()));
|
||||
JS::GCCellPtr(r.front().key()),
|
||||
JS::GCCellPtr(r.front().value()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -428,74 +428,6 @@ StatsCellCallback(JSRuntime *rt, void *data, void *thing, JSGCTraceKind traceKin
|
||||
break;
|
||||
}
|
||||
|
||||
case JSTRACE_STRING: {
|
||||
JSString *str = static_cast<JSString *>(thing);
|
||||
|
||||
JS::StringInfo info;
|
||||
if (str->hasLatin1Chars()) {
|
||||
info.gcHeapLatin1 = thingSize;
|
||||
info.mallocHeapLatin1 = str->sizeOfExcludingThis(rtStats->mallocSizeOf_);
|
||||
} else {
|
||||
info.gcHeapTwoByte = thingSize;
|
||||
info.mallocHeapTwoByte = str->sizeOfExcludingThis(rtStats->mallocSizeOf_);
|
||||
}
|
||||
info.numCopies = 1;
|
||||
|
||||
zStats->stringInfo.add(info);
|
||||
|
||||
// The primary use case for anonymization is automated crash submission
|
||||
// (to help detect OOM crashes). In that case, we don't want to pay the
|
||||
// memory cost required to do notable string detection.
|
||||
if (granularity == FineGrained && !closure->anonymize) {
|
||||
ZoneStats::StringsHashMap::AddPtr p = zStats->allStrings->lookupForAdd(str);
|
||||
if (!p) {
|
||||
// Ignore failure -- we just won't record the string as notable.
|
||||
(void)zStats->allStrings->add(p, str, info);
|
||||
} else {
|
||||
p->value().add(info);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case JSTRACE_SYMBOL:
|
||||
zStats->symbolsGCHeap += thingSize;
|
||||
break;
|
||||
|
||||
case JSTRACE_SHAPE: {
|
||||
Shape *shape = static_cast<Shape *>(thing);
|
||||
CompartmentStats *cStats = GetCompartmentStats(shape->compartment());
|
||||
JS::ClassInfo info; // This zeroes all the sizes.
|
||||
if (shape->inDictionary())
|
||||
info.shapesGCHeapDict += thingSize;
|
||||
else
|
||||
info.shapesGCHeapTree += thingSize;
|
||||
shape->addSizeOfExcludingThis(rtStats->mallocSizeOf_, &info);
|
||||
cStats->classInfo.add(info);
|
||||
|
||||
const BaseShape *base = shape->base();
|
||||
const Class *clasp = base->clasp();
|
||||
const char *className = clasp->name;
|
||||
AddClassInfo(granularity, cStats, className, info);
|
||||
break;
|
||||
}
|
||||
|
||||
case JSTRACE_BASE_SHAPE: {
|
||||
BaseShape *base = static_cast<BaseShape *>(thing);
|
||||
CompartmentStats *cStats = GetCompartmentStats(base->compartment());
|
||||
|
||||
JS::ClassInfo info; // This zeroes all the sizes.
|
||||
info.shapesGCHeapBase += thingSize;
|
||||
// No malloc-heap measurements.
|
||||
|
||||
cStats->classInfo.add(info);
|
||||
|
||||
const Class *clasp = base->clasp();
|
||||
const char *className = clasp->name;
|
||||
AddClassInfo(granularity, cStats, className, info);
|
||||
break;
|
||||
}
|
||||
|
||||
case JSTRACE_SCRIPT: {
|
||||
JSScript *script = static_cast<JSScript *>(thing);
|
||||
CompartmentStats *cStats = GetCompartmentStats(script->compartment());
|
||||
@ -536,6 +468,62 @@ StatsCellCallback(JSRuntime *rt, void *data, void *thing, JSGCTraceKind traceKin
|
||||
break;
|
||||
}
|
||||
|
||||
case JSTRACE_STRING: {
|
||||
JSString *str = static_cast<JSString *>(thing);
|
||||
|
||||
JS::StringInfo info;
|
||||
if (str->hasLatin1Chars()) {
|
||||
info.gcHeapLatin1 = thingSize;
|
||||
info.mallocHeapLatin1 = str->sizeOfExcludingThis(rtStats->mallocSizeOf_);
|
||||
} else {
|
||||
info.gcHeapTwoByte = thingSize;
|
||||
info.mallocHeapTwoByte = str->sizeOfExcludingThis(rtStats->mallocSizeOf_);
|
||||
}
|
||||
info.numCopies = 1;
|
||||
|
||||
zStats->stringInfo.add(info);
|
||||
|
||||
// The primary use case for anonymization is automated crash submission
|
||||
// (to help detect OOM crashes). In that case, we don't want to pay the
|
||||
// memory cost required to do notable string detection.
|
||||
if (granularity == FineGrained && !closure->anonymize) {
|
||||
ZoneStats::StringsHashMap::AddPtr p = zStats->allStrings->lookupForAdd(str);
|
||||
if (!p) {
|
||||
// Ignore failure -- we just won't record the string as notable.
|
||||
(void)zStats->allStrings->add(p, str, info);
|
||||
} else {
|
||||
p->value().add(info);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case JSTRACE_SYMBOL:
|
||||
zStats->symbolsGCHeap += thingSize;
|
||||
break;
|
||||
|
||||
case JSTRACE_BASE_SHAPE: {
|
||||
BaseShape *base = static_cast<BaseShape *>(thing);
|
||||
CompartmentStats *cStats = GetCompartmentStats(base->compartment());
|
||||
|
||||
JS::ClassInfo info; // This zeroes all the sizes.
|
||||
info.shapesGCHeapBase += thingSize;
|
||||
// No malloc-heap measurements.
|
||||
|
||||
cStats->classInfo.add(info);
|
||||
|
||||
const Class *clasp = base->clasp();
|
||||
const char *className = clasp->name;
|
||||
AddClassInfo(granularity, cStats, className, info);
|
||||
break;
|
||||
}
|
||||
|
||||
case JSTRACE_JITCODE: {
|
||||
zStats->jitCodesGCHeap += thingSize;
|
||||
// The code for a script is counted in ExecutableAllocator::sizeOfCode().
|
||||
break;
|
||||
}
|
||||
|
||||
case JSTRACE_LAZY_SCRIPT: {
|
||||
LazyScript *lazy = static_cast<LazyScript *>(thing);
|
||||
zStats->lazyScriptsGCHeap += thingSize;
|
||||
@ -543,9 +531,21 @@ StatsCellCallback(JSRuntime *rt, void *data, void *thing, JSGCTraceKind traceKin
|
||||
break;
|
||||
}
|
||||
|
||||
case JSTRACE_JITCODE: {
|
||||
zStats->jitCodesGCHeap += thingSize;
|
||||
// The code for a script is counted in ExecutableAllocator::sizeOfCode().
|
||||
case JSTRACE_SHAPE: {
|
||||
Shape *shape = static_cast<Shape *>(thing);
|
||||
CompartmentStats *cStats = GetCompartmentStats(shape->compartment());
|
||||
JS::ClassInfo info; // This zeroes all the sizes.
|
||||
if (shape->inDictionary())
|
||||
info.shapesGCHeapDict += thingSize;
|
||||
else
|
||||
info.shapesGCHeapTree += thingSize;
|
||||
shape->addSizeOfExcludingThis(rtStats->mallocSizeOf_, &info);
|
||||
cStats->classInfo.add(info);
|
||||
|
||||
const BaseShape *base = shape->base();
|
||||
const Class *clasp = base->clasp();
|
||||
const char *className = clasp->name;
|
||||
AddClassInfo(granularity, cStats, className, info);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -557,7 +557,7 @@ StatsCellCallback(JSRuntime *rt, void *data, void *thing, JSGCTraceKind traceKin
|
||||
}
|
||||
|
||||
default:
|
||||
MOZ_CRASH("invalid traceKind");
|
||||
MOZ_CRASH("invalid traceKind in StatsCellCallback");
|
||||
}
|
||||
|
||||
// Yes, this is a subtraction: see StatsArenaCallback() for details.
|
||||
|
@ -59,13 +59,13 @@ Node::Node(JSGCTraceKind kind, void *ptr)
|
||||
{
|
||||
switch (kind) {
|
||||
case JSTRACE_OBJECT: construct(static_cast<JSObject *>(ptr)); break;
|
||||
case JSTRACE_SCRIPT: construct(static_cast<JSScript *>(ptr)); break;
|
||||
case JSTRACE_STRING: construct(static_cast<JSString *>(ptr)); break;
|
||||
case JSTRACE_SYMBOL: construct(static_cast<JS::Symbol *>(ptr)); break;
|
||||
case JSTRACE_SCRIPT: construct(static_cast<JSScript *>(ptr)); break;
|
||||
case JSTRACE_LAZY_SCRIPT: construct(static_cast<js::LazyScript *>(ptr)); break;
|
||||
case JSTRACE_JITCODE: construct(static_cast<js::jit::JitCode *>(ptr)); break;
|
||||
case JSTRACE_SHAPE: construct(static_cast<js::Shape *>(ptr)); break;
|
||||
case JSTRACE_BASE_SHAPE: construct(static_cast<js::BaseShape *>(ptr)); break;
|
||||
case JSTRACE_JITCODE: construct(static_cast<js::jit::JitCode *>(ptr)); break;
|
||||
case JSTRACE_LAZY_SCRIPT: construct(static_cast<js::LazyScript *>(ptr)); break;
|
||||
case JSTRACE_SHAPE: construct(static_cast<js::Shape *>(ptr)); break;
|
||||
case JSTRACE_TYPE_OBJECT: construct(static_cast<js::types::TypeObject *>(ptr)); break;
|
||||
|
||||
default:
|
||||
|
@ -200,17 +200,13 @@ NS_NewFileURI(nsIURI* *result,
|
||||
inline nsresult
|
||||
NS_NewChannelInternal(nsIChannel** outChannel,
|
||||
nsIURI* aUri,
|
||||
nsINode* aRequestingNode,
|
||||
nsIPrincipal* aRequestingPrincipal,
|
||||
nsIPrincipal* aTriggeringPrincipal,
|
||||
nsSecurityFlags aSecurityFlags,
|
||||
nsContentPolicyType aContentPolicyType,
|
||||
nsIURI* aBaseURI = nullptr,
|
||||
nsILoadInfo* aLoadInfo,
|
||||
nsILoadGroup* aLoadGroup = nullptr,
|
||||
nsIInterfaceRequestor* aCallbacks = nullptr,
|
||||
nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL,
|
||||
nsIIOService* aIoService = nullptr)
|
||||
{
|
||||
NS_ASSERTION(aLoadInfo, "Can not create channel without aLoadInfo!");
|
||||
NS_ENSURE_ARG_POINTER(outChannel);
|
||||
|
||||
nsCOMPtr<nsIIOService> grip;
|
||||
@ -238,31 +234,11 @@ NS_NewChannelInternal(nsIChannel** outChannel,
|
||||
rv = channel->SetLoadFlags(aLoadFlags | (normalLoadFlags & nsIChannel::LOAD_REPLACE));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Some channels might already have a loadInfo attached at this
|
||||
// point (see bug 1104623). We have to make sure to update
|
||||
// security flags in such cases before we set the loadinfo.
|
||||
// Once bug 1087442 lands, this problem disappears because we
|
||||
// attach the loadinfo in each individual protocol handler.
|
||||
nsCOMPtr<nsILoadInfo> loadInfo;
|
||||
channel->GetLoadInfo(getter_AddRefs(loadInfo));
|
||||
if (loadInfo) {
|
||||
aSecurityFlags |= loadInfo->GetSecurityFlags();
|
||||
}
|
||||
|
||||
// create a new Loadinfo with the potentially updated securityFlags
|
||||
loadInfo =
|
||||
new mozilla::LoadInfo(aRequestingPrincipal, aTriggeringPrincipal,
|
||||
aRequestingNode, aSecurityFlags,
|
||||
aContentPolicyType, aBaseURI);
|
||||
if (!loadInfo) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
channel->SetLoadInfo(loadInfo);
|
||||
channel->SetLoadInfo(aLoadInfo);
|
||||
|
||||
// If we're sandboxed, make sure to clear any owner the channel
|
||||
// might already have.
|
||||
if (loadInfo->GetLoadingSandboxed()) {
|
||||
if (aLoadInfo->GetLoadingSandboxed()) {
|
||||
channel->SetOwner(nullptr);
|
||||
}
|
||||
|
||||
@ -273,27 +249,31 @@ NS_NewChannelInternal(nsIChannel** outChannel,
|
||||
inline nsresult
|
||||
NS_NewChannelInternal(nsIChannel** outChannel,
|
||||
nsIURI* aUri,
|
||||
nsILoadInfo* aLoadInfo,
|
||||
nsINode* aRequestingNode,
|
||||
nsIPrincipal* aRequestingPrincipal,
|
||||
nsIPrincipal* aTriggeringPrincipal,
|
||||
nsSecurityFlags aSecurityFlags,
|
||||
nsContentPolicyType aContentPolicyType,
|
||||
nsILoadGroup* aLoadGroup = nullptr,
|
||||
nsIInterfaceRequestor* aCallbacks = nullptr,
|
||||
nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL,
|
||||
nsIIOService* aIoService = nullptr)
|
||||
{
|
||||
MOZ_ASSERT(aLoadInfo, "Can not create a channel without a loadInfo");
|
||||
nsresult rv = NS_NewChannelInternal(outChannel,
|
||||
aUri,
|
||||
aLoadInfo->LoadingNode(),
|
||||
aLoadInfo->LoadingPrincipal(),
|
||||
aLoadInfo->TriggeringPrincipal(),
|
||||
aLoadInfo->GetSecurityFlags(),
|
||||
aLoadInfo->GetContentPolicyType(),
|
||||
aLoadInfo->BaseURI(),
|
||||
aLoadGroup,
|
||||
aCallbacks,
|
||||
aLoadFlags,
|
||||
aIoService);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return NS_OK;
|
||||
NS_ASSERTION(aRequestingPrincipal, "Can not create channel without a requesting Principal!");
|
||||
|
||||
nsCOMPtr<nsILoadInfo> loadInfo =
|
||||
new mozilla::LoadInfo(aRequestingPrincipal, aTriggeringPrincipal,
|
||||
aRequestingNode, aSecurityFlags, aContentPolicyType);
|
||||
if (!loadInfo) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
return NS_NewChannelInternal(outChannel,
|
||||
aUri,
|
||||
loadInfo,
|
||||
aLoadGroup,
|
||||
aCallbacks,
|
||||
aLoadFlags,
|
||||
aIoService);
|
||||
}
|
||||
|
||||
inline nsresult /*NS_NewChannelWithNodeAndTriggeringPrincipal */
|
||||
@ -317,7 +297,6 @@ NS_NewChannelWithTriggeringPrincipal(nsIChannel** outChannel,
|
||||
aTriggeringPrincipal,
|
||||
aSecurityFlags,
|
||||
aContentPolicyType,
|
||||
nullptr, // aBaseURI
|
||||
aLoadGroup,
|
||||
aCallbacks,
|
||||
aLoadFlags,
|
||||
@ -344,7 +323,6 @@ NS_NewChannelWithTriggeringPrincipal(nsIChannel** outChannel,
|
||||
aTriggeringPrincipal,
|
||||
aSecurityFlags,
|
||||
aContentPolicyType,
|
||||
nullptr, // aBaseURI
|
||||
aLoadGroup,
|
||||
aCallbacks,
|
||||
aLoadFlags,
|
||||
@ -370,7 +348,6 @@ NS_NewChannel(nsIChannel** outChannel,
|
||||
nullptr, // aTriggeringPrincipal
|
||||
aSecurityFlags,
|
||||
aContentPolicyType,
|
||||
nullptr, // aBaseURI
|
||||
aLoadGroup,
|
||||
aCallbacks,
|
||||
aLoadFlags,
|
||||
@ -395,7 +372,6 @@ NS_NewChannel(nsIChannel** outChannel,
|
||||
nullptr, // aTriggeringPrincipal
|
||||
aSecurityFlags,
|
||||
aContentPolicyType,
|
||||
nullptr, // aBaseURI
|
||||
aLoadGroup,
|
||||
aCallbacks,
|
||||
aLoadFlags,
|
||||
@ -430,7 +406,6 @@ NS_OpenURIInternal(nsIInputStream** outStream,
|
||||
aTriggeringPrincipal,
|
||||
aSecurityFlags,
|
||||
aContentPolicyType,
|
||||
nullptr, // aBaseURI
|
||||
aLoadGroup,
|
||||
aCallbacks,
|
||||
aLoadFlags,
|
||||
@ -987,7 +962,6 @@ NS_NewStreamLoaderInternal(nsIStreamLoader** outStream,
|
||||
nullptr, // aTriggeringPrincipal
|
||||
aSecurityFlags,
|
||||
aContentPolicyType,
|
||||
nullptr, // aBaseURI
|
||||
aLoadGroup,
|
||||
aCallbacks,
|
||||
aLoadFlags);
|
||||
|
@ -21,6 +21,8 @@ static const char pluginSandboxRules[] =
|
||||
"(deny default)\n"
|
||||
"(allow signal (target self))\n"
|
||||
"(allow sysctl-read)\n"
|
||||
// Illegal syntax on OS X 10.6, needed on 10.7 and up.
|
||||
"%s(allow iokit-open (iokit-user-client-class \"IOHIDParamUserClient\"))\n"
|
||||
// Needed only on OS X 10.6
|
||||
"%s(allow file-read-data (literal \"%s\"))\n"
|
||||
"(allow mach-lookup\n"
|
||||
@ -34,6 +36,8 @@ static const char pluginSandboxRules[] =
|
||||
" (regex #\"^/dev/u?random$\")\n"
|
||||
" (regex #\"^/(private/)?var($|/)\")\n"
|
||||
" (literal \"/usr/share/icu/icudt51l.dat\")\n"
|
||||
" (regex #\"^/System/Library/Displays/Overrides/*\")\n"
|
||||
" (regex #\"^/System/Library/CoreServices/CoreTypes.bundle/*\")\n"
|
||||
" (literal \"%s\")\n"
|
||||
" (literal \"%s\")\n"
|
||||
" (literal \"%s\"))\n";
|
||||
@ -47,13 +51,13 @@ bool StartMacSandbox(MacSandboxInfo aInfo, nsCString &aErrorMessage)
|
||||
nsAutoCString profile;
|
||||
if (aInfo.type == MacSandboxType_Plugin) {
|
||||
if (nsCocoaFeatures::OnLionOrLater()) {
|
||||
profile.AppendPrintf(pluginSandboxRules, ";",
|
||||
profile.AppendPrintf(pluginSandboxRules, "", ";",
|
||||
aInfo.pluginInfo.pluginPath.get(),
|
||||
aInfo.pluginInfo.pluginBinaryPath.get(),
|
||||
aInfo.appPath.get(),
|
||||
aInfo.appBinaryPath.get());
|
||||
} else {
|
||||
profile.AppendPrintf(pluginSandboxRules, "",
|
||||
profile.AppendPrintf(pluginSandboxRules, ";", "",
|
||||
aInfo.pluginInfo.pluginPath.get(),
|
||||
aInfo.pluginInfo.pluginBinaryPath.get(),
|
||||
aInfo.appPath.get(),
|
||||
|
@ -877,108 +877,68 @@ class ManifestParser(object):
|
||||
### directory importers
|
||||
|
||||
@classmethod
|
||||
def _walk_directories(cls, directories, function, pattern=None, ignore=()):
|
||||
def _walk_directories(cls, directories, callback, pattern=None, ignore=()):
|
||||
"""
|
||||
internal function to import directories
|
||||
"""
|
||||
|
||||
class FilteredDirectoryContents(object):
|
||||
"""class to filter directory contents"""
|
||||
if isinstance(pattern, basestring):
|
||||
patterns = [pattern]
|
||||
else:
|
||||
patterns = pattern
|
||||
ignore = set(ignore)
|
||||
|
||||
sort = sorted
|
||||
if not patterns:
|
||||
accept_filename = lambda filename: True
|
||||
else:
|
||||
def accept_filename(filename):
|
||||
for pattern in patterns:
|
||||
if fnmatch.fnmatch(filename, pattern):
|
||||
return True
|
||||
|
||||
def __init__(self, pattern=pattern, ignore=ignore, cache=None):
|
||||
if pattern is None:
|
||||
pattern = set()
|
||||
if isinstance(pattern, basestring):
|
||||
pattern = [pattern]
|
||||
self.patterns = pattern
|
||||
self.ignore = set(ignore)
|
||||
if not ignore:
|
||||
accept_dirname = lambda dirname: True
|
||||
else:
|
||||
accept_dirname = lambda dirname: dirname not in ignore
|
||||
|
||||
# cache of (dirnames, filenames) keyed on directory real path
|
||||
# assumes volume is frozen throughout scope
|
||||
self._cache = cache or {}
|
||||
rootdirectories = directories[:]
|
||||
seen_directories = set()
|
||||
for rootdirectory in rootdirectories:
|
||||
# let's recurse directories using list
|
||||
directories = [os.path.realpath(rootdirectory)]
|
||||
while directories:
|
||||
directory = directories.pop(0)
|
||||
if directory in seen_directories:
|
||||
# eliminate possible infinite recursion due to
|
||||
# symbolic links
|
||||
continue
|
||||
seen_directories.add(directory)
|
||||
|
||||
def __call__(self, directory):
|
||||
"""returns 2-tuple: dirnames, filenames"""
|
||||
directory = os.path.realpath(directory)
|
||||
if directory not in self._cache:
|
||||
dirnames, filenames = self.contents(directory)
|
||||
files = []
|
||||
subdirs = []
|
||||
for name in sorted(os.listdir(directory)):
|
||||
path = os.path.join(directory, name)
|
||||
if os.path.isfile(path):
|
||||
# os.path.isfile follow symbolic links, we don't
|
||||
# need to handle them here.
|
||||
if accept_filename(name):
|
||||
files.append(name)
|
||||
continue
|
||||
elif os.path.islink(path):
|
||||
# eliminate symbolic links
|
||||
path = os.path.realpath(path)
|
||||
|
||||
# filter out directories without progeny
|
||||
# XXX recursive: should keep track of seen directories
|
||||
dirnames = [ dirname for dirname in dirnames
|
||||
if not self.empty(os.path.join(directory, dirname)) ]
|
||||
# we must have a directory here
|
||||
if accept_dirname(name):
|
||||
subdirs.append(name)
|
||||
# this subdir is added for recursion
|
||||
directories.insert(0, path)
|
||||
|
||||
self._cache[directory] = (tuple(dirnames), filenames)
|
||||
# here we got all subdirs and files filtered, we can
|
||||
# call the callback function if directory is not empty
|
||||
if subdirs or files:
|
||||
callback(rootdirectory, directory, subdirs, files)
|
||||
|
||||
# return cached values
|
||||
return self._cache[directory]
|
||||
|
||||
def empty(self, directory):
|
||||
"""
|
||||
returns if a directory and its descendents are empty
|
||||
"""
|
||||
return self(directory) == ((), ())
|
||||
|
||||
def contents(self, directory, sort=None):
|
||||
"""
|
||||
return directory contents as (dirnames, filenames)
|
||||
with `ignore` and `pattern` applied
|
||||
"""
|
||||
|
||||
if sort is None:
|
||||
sort = self.sort
|
||||
|
||||
# split directories and files
|
||||
dirnames = []
|
||||
filenames = []
|
||||
for item in os.listdir(directory):
|
||||
path = os.path.join(directory, item)
|
||||
if os.path.isdir(path):
|
||||
dirnames.append(item)
|
||||
else:
|
||||
# XXX not sure what to do if neither a file or directory
|
||||
# (if anything)
|
||||
assert os.path.isfile(path)
|
||||
filenames.append(item)
|
||||
|
||||
# filter contents;
|
||||
# this could be done in situ re the above for loop
|
||||
# but it is really disparate in intent
|
||||
# and could conceivably go to a separate method
|
||||
dirnames = [dirname for dirname in dirnames
|
||||
if dirname not in self.ignore]
|
||||
filenames = set(filenames)
|
||||
# we use set functionality to filter filenames
|
||||
if self.patterns:
|
||||
matches = set()
|
||||
matches.update(*[fnmatch.filter(filenames, pattern)
|
||||
for pattern in self.patterns])
|
||||
filenames = matches
|
||||
|
||||
if sort is not None:
|
||||
# sort dirnames, filenames
|
||||
dirnames = sort(dirnames)
|
||||
filenames = sort(filenames)
|
||||
|
||||
return (tuple(dirnames), tuple(filenames))
|
||||
|
||||
# make a filtered directory object
|
||||
directory_contents = FilteredDirectoryContents(pattern=pattern, ignore=ignore)
|
||||
|
||||
# walk the directories, generating manifests
|
||||
for index, directory in enumerate(directories):
|
||||
|
||||
for dirpath, dirnames, filenames in os.walk(directory):
|
||||
|
||||
# get the directory contents from the caching object
|
||||
_dirnames, filenames = directory_contents(dirpath)
|
||||
# filter out directory names
|
||||
dirnames[:] = _dirnames
|
||||
|
||||
# call callback function
|
||||
function(directory, dirpath, dirnames, filenames)
|
||||
|
||||
@classmethod
|
||||
def populate_directory_manifests(cls, directories, filename, pattern=None, ignore=(), overwrite=False):
|
||||
|
@ -14,6 +14,18 @@ from manifestparser import ManifestParser
|
||||
|
||||
here = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
# In some cases tempfile.mkdtemp() may returns a path which contains
|
||||
# symlinks. Some tests here will then break, as the manifestparser.convert
|
||||
# function returns paths that does not contains symlinks.
|
||||
#
|
||||
# Workaround is to use the following function, if absolute path of temp dir
|
||||
# must be compared.
|
||||
def create_realpath_tempdir():
|
||||
"""
|
||||
Create a tempdir without symlinks.
|
||||
"""
|
||||
return os.path.realpath(tempfile.mkdtemp())
|
||||
|
||||
class TestDirectoryConversion(unittest.TestCase):
|
||||
"""test conversion of a directory tree to a manifest structure"""
|
||||
|
||||
@ -22,7 +34,7 @@ class TestDirectoryConversion(unittest.TestCase):
|
||||
|
||||
files = ('foo', 'bar', 'fleem')
|
||||
if directory is None:
|
||||
directory = tempfile.mkdtemp()
|
||||
directory = create_realpath_tempdir()
|
||||
for i in files:
|
||||
file(os.path.join(directory, i), 'w').write(i)
|
||||
subdir = os.path.join(directory, 'subdir')
|
||||
@ -127,12 +139,12 @@ subsuite =
|
||||
"""
|
||||
|
||||
# boilerplate
|
||||
tempdir = tempfile.mkdtemp()
|
||||
tempdir = create_realpath_tempdir()
|
||||
for i in range(10):
|
||||
file(os.path.join(tempdir, str(i)), 'w').write(str(i))
|
||||
|
||||
# otherwise empty directory with a manifest file
|
||||
newtempdir = tempfile.mkdtemp()
|
||||
newtempdir = create_realpath_tempdir()
|
||||
manifest_file = os.path.join(newtempdir, 'manifest.ini')
|
||||
manifest_contents = str(convert([tempdir], relative_to=tempdir))
|
||||
with file(manifest_file, 'w') as f:
|
||||
|
@ -9,17 +9,13 @@ import shutil
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
from manifestparser import convert
|
||||
from manifestparser import convert, ManifestParser
|
||||
|
||||
class TestSymlinkConversion(unittest.TestCase):
|
||||
"""
|
||||
test conversion of a directory tree with symlinks to a manifest structure
|
||||
"""
|
||||
|
||||
# Currently broken: see
|
||||
# https://bugzilla.mozilla.org/show_bug.cgi?id=902610
|
||||
# https://bugzilla.mozilla.org/show_bug.cgi?id=920938
|
||||
|
||||
def create_stub(self, directory=None):
|
||||
"""stub out a directory with files in it"""
|
||||
|
||||
@ -52,23 +48,21 @@ class TestSymlinkConversion(unittest.TestCase):
|
||||
shutil.rmtree(stub)
|
||||
os.chdir(oldcwd)
|
||||
|
||||
@unittest.skipIf(not hasattr(os, 'symlink'),
|
||||
"symlinks unavailable on this platform")
|
||||
def test_relpath_symlink(self):
|
||||
"""
|
||||
Ensure `relative_to` works in a symlink.
|
||||
Not available on windows.
|
||||
"""
|
||||
|
||||
symlink = getattr(os, 'symlink', None)
|
||||
if symlink is None:
|
||||
return # symlinks unavailable on this platform
|
||||
|
||||
oldcwd = os.getcwd()
|
||||
workspace = tempfile.mkdtemp()
|
||||
try:
|
||||
tmpdir = os.path.join(workspace, 'directory')
|
||||
os.makedirs(tmpdir)
|
||||
linkdir = os.path.join(workspace, 'link')
|
||||
symlink(tmpdir, linkdir)
|
||||
os.symlink(tmpdir, linkdir)
|
||||
self.create_stub(tmpdir)
|
||||
|
||||
# subdir with in-memory manifest
|
||||
@ -90,7 +84,7 @@ class TestSymlinkConversion(unittest.TestCase):
|
||||
tmpdir = os.path.join(workspace, 'directory')
|
||||
os.makedirs(tmpdir)
|
||||
linkdir = os.path.join(workspace, 'link')
|
||||
symlink(tmpdir, linkdir)
|
||||
os.symlink(tmpdir, linkdir)
|
||||
self.create_stub(tmpdir)
|
||||
files = ['../bar', '../fleem', '../foo', 'subfile']
|
||||
subdir = os.path.join(linkdir, 'subdir')
|
||||
@ -98,8 +92,8 @@ class TestSymlinkConversion(unittest.TestCase):
|
||||
os.makedirs(subsubdir)
|
||||
linksubdir = os.path.join(linkdir, 'linky')
|
||||
linksubsubdir = os.path.join(subsubdir, 'linky')
|
||||
symlink(subdir, linksubdir)
|
||||
symlink(subdir, linksubsubdir)
|
||||
os.symlink(subdir, linksubdir)
|
||||
os.symlink(subdir, linksubsubdir)
|
||||
for dest in (subdir,):
|
||||
os.chdir(dest)
|
||||
for directory in (tmpdir, linkdir):
|
||||
@ -110,6 +104,34 @@ class TestSymlinkConversion(unittest.TestCase):
|
||||
shutil.rmtree(workspace)
|
||||
os.chdir(oldcwd)
|
||||
|
||||
@unittest.skipIf(not hasattr(os, 'symlink'),
|
||||
"symlinks unavailable on this platform")
|
||||
def test_recursion_symlinks(self):
|
||||
workspace = tempfile.mkdtemp()
|
||||
self.addCleanup(shutil.rmtree, workspace)
|
||||
|
||||
# create two dirs
|
||||
os.makedirs(os.path.join(workspace, 'dir1'))
|
||||
os.makedirs(os.path.join(workspace, 'dir2'))
|
||||
|
||||
# create cyclical symlinks
|
||||
os.symlink(os.path.join('..', 'dir1'),
|
||||
os.path.join(workspace, 'dir2', 'ldir1'))
|
||||
os.symlink(os.path.join('..', 'dir2'),
|
||||
os.path.join(workspace, 'dir1', 'ldir2'))
|
||||
|
||||
# create one file in each dir
|
||||
open(os.path.join(workspace, 'dir1', 'f1.txt'), 'a').close()
|
||||
open(os.path.join(workspace, 'dir1', 'ldir2', 'f2.txt'), 'a').close()
|
||||
|
||||
data = []
|
||||
def callback(rootdirectory, directory, subdirs, files):
|
||||
for f in files:
|
||||
data.append(f)
|
||||
|
||||
ManifestParser._walk_directories([workspace], callback)
|
||||
self.assertEqual(sorted(data), ['f1.txt', 'f2.txt'])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
@ -10,7 +10,8 @@
|
||||
|
||||
<binding id="remote-browser" extends="chrome://global/content/bindings/browser.xml#browser">
|
||||
|
||||
<implementation type="application/javascript" implements="nsIObserver, nsIDOMEventListener, nsIMessageListener">
|
||||
<implementation type="application/javascript"
|
||||
implements="nsIObserver, nsIDOMEventListener, nsIMessageListener, nsIRemoteBrowser">
|
||||
|
||||
<field name="_securityUI">null</field>
|
||||
|
||||
@ -372,6 +373,21 @@
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="enableDisableCommands">
|
||||
<parameter name="aAction"/>
|
||||
<parameter name="aEnabledLength"/>
|
||||
<parameter name="aEnabledCommands"/>
|
||||
<parameter name="aDisabledLength"/>
|
||||
<parameter name="aDisabledCommands"/>
|
||||
<body>
|
||||
if (this._controller) {
|
||||
this._controller.enableDisableCommands(aAction,
|
||||
aEnabledLength, aEnabledCommands,
|
||||
aDisabledLength, aDisabledCommands);
|
||||
}
|
||||
</body>
|
||||
</method>
|
||||
|
||||
</implementation>
|
||||
|
||||
</binding>
|
||||
|
@ -14,45 +14,45 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
function RemoteController(browser)
|
||||
{
|
||||
this._browser = browser;
|
||||
|
||||
// A map of commands that have had their enabled/disabled state assigned. The
|
||||
// value of each key will be true if enabled, and false if disabled.
|
||||
this._supportedCommands = { };
|
||||
}
|
||||
|
||||
RemoteController.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIController]),
|
||||
|
||||
isCommandEnabled: function(aCommand) {
|
||||
// We can't synchronously ask content if a command is enabled,
|
||||
// so we always pretend is.
|
||||
// The right way forward would be to never use nsIController
|
||||
// to ask if something in content is enabled. Maybe even
|
||||
// by replacing the nsIController architecture by something else.
|
||||
// See bug 905768.
|
||||
return true;
|
||||
return this._supportedCommands[aCommand] || false;
|
||||
},
|
||||
|
||||
supportsCommand: function(aCommand) {
|
||||
// Optimize the lookup a bit.
|
||||
if (!aCommand.startsWith("cmd_"))
|
||||
return false;
|
||||
|
||||
// For now only support the commands used in "browser-context.inc"
|
||||
let commands = [
|
||||
"cmd_copyLink",
|
||||
"cmd_copyImage",
|
||||
"cmd_undo",
|
||||
"cmd_cut",
|
||||
"cmd_copy",
|
||||
"cmd_paste",
|
||||
"cmd_delete",
|
||||
"cmd_selectAll",
|
||||
"cmd_switchTextDirection"
|
||||
];
|
||||
|
||||
return commands.indexOf(aCommand) >= 0;
|
||||
return aCommand in this._supportedCommands;
|
||||
},
|
||||
|
||||
doCommand: function(aCommand) {
|
||||
this._browser.messageManager.sendAsyncMessage("ControllerCommands:Do", aCommand);
|
||||
},
|
||||
|
||||
onEvent: function () {}
|
||||
onEvent: function () {},
|
||||
|
||||
// This is intended to be called from the remote-browser binding to update
|
||||
// the enabled and disabled commands.
|
||||
enableDisableCommands: function(aAction,
|
||||
aEnabledLength, aEnabledCommands,
|
||||
aDisabledLength, aDisabledCommands) {
|
||||
// Clear the list first
|
||||
this._supportedCommands = { };
|
||||
|
||||
for (let c = 0; c < aEnabledLength; c++) {
|
||||
this._supportedCommands[aEnabledCommands[c]] = true;
|
||||
}
|
||||
|
||||
for (let c = 0; c < aDisabledLength; c++) {
|
||||
this._supportedCommands[aDisabledCommands[c]] = false;
|
||||
}
|
||||
|
||||
this._browser.ownerDocument.defaultView.updateCommands(aAction);
|
||||
}
|
||||
};
|
||||
|
@ -64,6 +64,7 @@ static GtkWidget* gScrolledWindowWidget;
|
||||
|
||||
static style_prop_t style_prop_func;
|
||||
static gboolean have_arrow_scaling;
|
||||
static gboolean checkbox_check_state;
|
||||
static gboolean is_initialized;
|
||||
|
||||
#define ARROW_UP 0
|
||||
@ -71,6 +72,10 @@ static gboolean is_initialized;
|
||||
#define ARROW_RIGHT G_PI_2
|
||||
#define ARROW_LEFT (G_PI+G_PI_2)
|
||||
|
||||
#if !GTK_CHECK_VERSION(3,14,0)
|
||||
#define GTK_STATE_FLAG_CHECKED (1 << 11)
|
||||
#endif
|
||||
|
||||
static GtkStateFlags
|
||||
GetStateFlagsFromGtkWidgetState(GtkWidgetState* state)
|
||||
{
|
||||
@ -714,6 +719,11 @@ moz_gtk_init()
|
||||
is_initialized = TRUE;
|
||||
have_arrow_scaling = (gtk_major_version > 2 ||
|
||||
(gtk_major_version == 2 && gtk_minor_version >= 12));
|
||||
if (gtk_major_version > 3 ||
|
||||
(gtk_major_version == 3 && gtk_minor_version >= 14))
|
||||
checkbox_check_state = GTK_STATE_FLAG_CHECKED;
|
||||
else
|
||||
checkbox_check_state = GTK_STATE_FLAG_ACTIVE;
|
||||
|
||||
/* Add style property to GtkEntry.
|
||||
* Adding the style property to the normal GtkEntry class means that it
|
||||
@ -1004,10 +1014,10 @@ moz_gtk_toggle_paint(cairo_t *cr, GdkRectangle* rect,
|
||||
gtk_widget_set_sensitive(w, !state->disabled);
|
||||
gtk_widget_set_direction(w, direction);
|
||||
gtk_style_context_save(style);
|
||||
|
||||
|
||||
if (isradio) {
|
||||
gtk_style_context_add_class(style, GTK_STYLE_CLASS_RADIO);
|
||||
gtk_style_context_set_state(style, selected ? GTK_STATE_FLAG_ACTIVE :
|
||||
gtk_style_context_set_state(style, selected ? checkbox_check_state :
|
||||
GTK_STATE_FLAG_NORMAL);
|
||||
gtk_render_option(style, cr, x, y, width, height);
|
||||
if (state->focused) {
|
||||
@ -1025,7 +1035,7 @@ moz_gtk_toggle_paint(cairo_t *cr, GdkRectangle* rect,
|
||||
gtk_style_context_set_state(style, GTK_STATE_FLAG_INCONSISTENT);
|
||||
gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(gCheckboxWidget), TRUE);
|
||||
} else if (selected) {
|
||||
gtk_style_context_set_state(style, GTK_STATE_FLAG_ACTIVE);
|
||||
gtk_style_context_set_state(style, checkbox_check_state);
|
||||
} else {
|
||||
gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(gCheckboxWidget), FALSE);
|
||||
}
|
||||
@ -2588,8 +2598,9 @@ moz_gtk_check_menu_item_paint(cairo_t *cr, GdkRectangle* rect,
|
||||
gtk_style_context_add_class(style, GTK_STYLE_CLASS_CHECK);
|
||||
}
|
||||
|
||||
if (checked)
|
||||
state_flags |= GTK_STATE_FLAG_ACTIVE;
|
||||
if (checked) {
|
||||
state_flags |= checkbox_check_state;
|
||||
}
|
||||
|
||||
gtk_style_context_set_state(style, state_flags);
|
||||
gtk_style_context_get_padding(style, state_flags, &padding);
|
||||
|
@ -38,7 +38,6 @@ nsLookAndFeel::nsLookAndFeel()
|
||||
mStyle(nullptr),
|
||||
#else
|
||||
mBackgroundStyle(nullptr),
|
||||
mViewStyle(nullptr),
|
||||
mButtonStyle(nullptr),
|
||||
#endif
|
||||
mDefaultFontCached(false), mButtonFontCached(false),
|
||||
@ -53,7 +52,6 @@ nsLookAndFeel::~nsLookAndFeel()
|
||||
g_object_unref(mStyle);
|
||||
#else
|
||||
g_object_unref(mBackgroundStyle);
|
||||
g_object_unref(mViewStyle);
|
||||
g_object_unref(mButtonStyle);
|
||||
#endif
|
||||
}
|
||||
@ -114,13 +112,19 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor)
|
||||
case eColorID_IMESelectedRawTextBackground:
|
||||
case eColorID_IMESelectedConvertedTextBackground:
|
||||
case eColorID__moz_dragtargetzone:
|
||||
aColor = sMozWindowSelectedBackground;
|
||||
case eColorID__moz_cellhighlight:
|
||||
case eColorID__moz_html_cellhighlight:
|
||||
case eColorID_highlight: // preference selected item,
|
||||
aColor = sTextSelectedBackground;
|
||||
break;
|
||||
case eColorID_WidgetSelectForeground:
|
||||
case eColorID_TextSelectForeground:
|
||||
case eColorID_IMESelectedRawTextForeground:
|
||||
case eColorID_IMESelectedConvertedTextForeground:
|
||||
aColor = sMozWindowSelectedText;
|
||||
case eColorID_highlighttext:
|
||||
case eColorID__moz_cellhighlighttext:
|
||||
case eColorID__moz_html_cellhighlighttext:
|
||||
aColor = sTextSelectedText;
|
||||
break;
|
||||
#endif
|
||||
case eColorID_Widget3DHighlight:
|
||||
@ -238,19 +242,6 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor)
|
||||
GTK_STATE_FLAG_INSENSITIVE, &gdk_color);
|
||||
aColor = GDK_RGBA_TO_NS_RGBA(gdk_color);
|
||||
break;
|
||||
case eColorID_highlight: // preference selected item,
|
||||
// background of selected item
|
||||
gtk_style_context_get_background_color(mViewStyle,
|
||||
GTK_STATE_FLAG_SELECTED,
|
||||
&gdk_color);
|
||||
aColor = GDK_RGBA_TO_NS_RGBA(gdk_color);
|
||||
break;
|
||||
case eColorID_highlighttext:
|
||||
// text of selected item
|
||||
gtk_style_context_get_color(mViewStyle,
|
||||
GTK_STATE_FLAG_SELECTED, &gdk_color);
|
||||
aColor = GDK_RGBA_TO_NS_RGBA(gdk_color);
|
||||
break;
|
||||
case eColorID_inactivecaption:
|
||||
// inactive window caption
|
||||
gtk_style_context_get_background_color(mBackgroundStyle,
|
||||
@ -393,19 +384,6 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor)
|
||||
case eColorID__moz_buttonhovertext:
|
||||
aColor = sButtonHoverText;
|
||||
break;
|
||||
case eColorID__moz_cellhighlight:
|
||||
case eColorID__moz_html_cellhighlight:
|
||||
gtk_style_context_get_background_color(mViewStyle,
|
||||
GTK_STATE_FLAG_SELECTED,
|
||||
&gdk_color);
|
||||
aColor = GDK_RGBA_TO_NS_RGBA(gdk_color);
|
||||
break;
|
||||
case eColorID__moz_cellhighlighttext:
|
||||
case eColorID__moz_html_cellhighlighttext:
|
||||
gtk_style_context_get_color(mViewStyle,
|
||||
GTK_STATE_FLAG_SELECTED, &gdk_color);
|
||||
aColor = GDK_RGBA_TO_NS_RGBA(gdk_color);
|
||||
break;
|
||||
#endif
|
||||
case eColorID__moz_menuhover:
|
||||
aColor = sMenuHover;
|
||||
@ -967,7 +945,7 @@ nsLookAndFeel::Init()
|
||||
GtkStyleContext *style;
|
||||
|
||||
// Gtk manages a screen's CSS in the settings object so we
|
||||
// ask Gtk to create it explicitly. Otherwise we may end up
|
||||
// ask Gtk to create it explicitly. Otherwise we may end up
|
||||
// with wrong color theme, see Bug 972382
|
||||
(void)gtk_settings_get_for_screen(gdk_screen_get_default());
|
||||
|
||||
@ -977,9 +955,6 @@ nsLookAndFeel::Init()
|
||||
mBackgroundStyle = create_context(path);
|
||||
gtk_style_context_add_class(mBackgroundStyle, GTK_STYLE_CLASS_BACKGROUND);
|
||||
|
||||
mViewStyle = create_context(path);
|
||||
gtk_style_context_add_class(mViewStyle, GTK_STYLE_CLASS_VIEW);
|
||||
|
||||
mButtonStyle = create_context(path);
|
||||
gtk_style_context_add_class(mButtonStyle, GTK_STYLE_CLASS_BUTTON);
|
||||
|
||||
@ -992,11 +967,24 @@ nsLookAndFeel::Init()
|
||||
g_object_unref(style);
|
||||
|
||||
// Text colors
|
||||
gtk_style_context_get_background_color(mViewStyle, GTK_STATE_FLAG_NORMAL, &color);
|
||||
style = create_context(path);
|
||||
gtk_style_context_add_class(style, GTK_STYLE_CLASS_VIEW);
|
||||
gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, &color);
|
||||
sMozFieldBackground = GDK_RGBA_TO_NS_RGBA(color);
|
||||
gtk_style_context_get_color(mViewStyle, GTK_STATE_FLAG_NORMAL, &color);
|
||||
gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color);
|
||||
sMozFieldText = GDK_RGBA_TO_NS_RGBA(color);
|
||||
|
||||
// Selected text and background
|
||||
gtk_style_context_get_background_color(style,
|
||||
static_cast<GtkStateFlags>(GTK_STATE_FLAG_FOCUSED|GTK_STATE_FLAG_SELECTED),
|
||||
&color);
|
||||
sTextSelectedBackground = GDK_RGBA_TO_NS_RGBA(color);
|
||||
gtk_style_context_get_color(style,
|
||||
static_cast<GtkStateFlags>(GTK_STATE_FLAG_FOCUSED|GTK_STATE_FLAG_SELECTED),
|
||||
&color);
|
||||
sTextSelectedText = GDK_RGBA_TO_NS_RGBA(color);
|
||||
g_object_unref(style);
|
||||
|
||||
// Window colors
|
||||
style = create_context(path);
|
||||
gtk_style_context_save(style);
|
||||
@ -1005,12 +993,6 @@ nsLookAndFeel::Init()
|
||||
sMozWindowBackground = GDK_RGBA_TO_NS_RGBA(color);
|
||||
gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color);
|
||||
sMozWindowText = GDK_RGBA_TO_NS_RGBA(color);
|
||||
|
||||
// Selected text and background
|
||||
gtk_style_context_get_background_color(style, GTK_STATE_FLAG_SELECTED, &color);
|
||||
sMozWindowSelectedBackground = GDK_RGBA_TO_NS_RGBA(color);
|
||||
gtk_style_context_get_color(style, GTK_STATE_FLAG_SELECTED, &color);
|
||||
sMozWindowSelectedText = GDK_RGBA_TO_NS_RGBA(color);
|
||||
gtk_style_context_restore(style);
|
||||
|
||||
// tooltip foreground and background
|
||||
@ -1256,11 +1238,9 @@ nsLookAndFeel::RefreshImpl()
|
||||
mStyle = nullptr;
|
||||
#else
|
||||
g_object_unref(mBackgroundStyle);
|
||||
g_object_unref(mViewStyle);
|
||||
g_object_unref(mButtonStyle);
|
||||
|
||||
mBackgroundStyle = nullptr;
|
||||
mViewStyle = nullptr;
|
||||
mButtonStyle = nullptr;
|
||||
#endif
|
||||
|
||||
|
@ -35,7 +35,6 @@ protected:
|
||||
struct _GtkStyle *mStyle;
|
||||
#else
|
||||
struct _GtkStyleContext *mBackgroundStyle;
|
||||
struct _GtkStyleContext *mViewStyle;
|
||||
struct _GtkStyleContext *mButtonStyle;
|
||||
#endif
|
||||
|
||||
@ -75,8 +74,8 @@ protected:
|
||||
nscolor sMozFieldBackground;
|
||||
nscolor sMozWindowText;
|
||||
nscolor sMozWindowBackground;
|
||||
nscolor sMozWindowSelectedText;
|
||||
nscolor sMozWindowSelectedBackground;
|
||||
nscolor sTextSelectedText;
|
||||
nscolor sTextSelectedBackground;
|
||||
nscolor sMozScrollbar;
|
||||
char16_t sInvisibleCharacter;
|
||||
float sCaretRatio;
|
||||
|
@ -180,17 +180,15 @@ struct NoteWeakMapsTracer : public js::WeakMapTracer
|
||||
|
||||
static void
|
||||
TraceWeakMapping(js::WeakMapTracer* aTrc, JSObject* aMap,
|
||||
void* aKey, JSGCTraceKind aKeyKind,
|
||||
void* aValue, JSGCTraceKind aValueKind)
|
||||
JS::GCCellPtr aKey, JS::GCCellPtr aValue)
|
||||
{
|
||||
MOZ_ASSERT(aTrc->callback == TraceWeakMapping);
|
||||
NoteWeakMapsTracer* tracer = static_cast<NoteWeakMapsTracer*>(aTrc);
|
||||
|
||||
// If nothing that could be held alive by this entry is marked gray, return.
|
||||
if ((!aKey || !xpc_IsGrayGCThing(aKey)) &&
|
||||
if ((!aKey || !xpc_IsGrayGCThing(aKey.asCell())) &&
|
||||
MOZ_LIKELY(!tracer->mCb.WantAllTraces())) {
|
||||
if (!aValue || !xpc_IsGrayGCThing(aValue) ||
|
||||
aValueKind == JSTRACE_STRING) {
|
||||
if (!aValue || !xpc_IsGrayGCThing(aValue.asCell()) || aValue.isString()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -199,38 +197,38 @@ TraceWeakMapping(js::WeakMapTracer* aTrc, JSObject* aMap,
|
||||
// reason about the liveness of their keys, which in turn requires that
|
||||
// the key can be represented in the cycle collector graph. All existing
|
||||
// uses of weak maps use either objects or scripts as keys, which are okay.
|
||||
MOZ_ASSERT(AddToCCKind(aKeyKind));
|
||||
MOZ_ASSERT(AddToCCKind(aKey.kind()));
|
||||
|
||||
// As an emergency fallback for non-debug builds, if the key is not
|
||||
// representable in the cycle collector graph, we treat it as marked. This
|
||||
// can cause leaks, but is preferable to ignoring the binding, which could
|
||||
// cause the cycle collector to free live objects.
|
||||
if (!AddToCCKind(aKeyKind)) {
|
||||
aKey = nullptr;
|
||||
if (!AddToCCKind(aKey.kind())) {
|
||||
aKey = JS::GCCellPtr::NullPtr();
|
||||
}
|
||||
|
||||
JSObject* kdelegate = nullptr;
|
||||
if (aKey && aKeyKind == JSTRACE_OBJECT) {
|
||||
kdelegate = js::GetWeakmapKeyDelegate((JSObject*)aKey);
|
||||
if (aKey.isObject()) {
|
||||
kdelegate = js::GetWeakmapKeyDelegate(aKey.toObject());
|
||||
}
|
||||
|
||||
if (AddToCCKind(aValueKind)) {
|
||||
tracer->mCb.NoteWeakMapping(aMap, aKey, kdelegate, aValue);
|
||||
if (AddToCCKind(aValue.kind())) {
|
||||
tracer->mCb.NoteWeakMapping(aMap, aKey.asCell(), kdelegate, aValue.asCell());
|
||||
} else {
|
||||
tracer->mChildTracer.mTracedAny = false;
|
||||
tracer->mChildTracer.mMap = aMap;
|
||||
tracer->mChildTracer.mKey = aKey;
|
||||
tracer->mChildTracer.mKey = aKey.asCell();
|
||||
tracer->mChildTracer.mKeyDelegate = kdelegate;
|
||||
|
||||
if (aValue && aValueKind != JSTRACE_STRING) {
|
||||
JS_TraceChildren(&tracer->mChildTracer, aValue, aValueKind);
|
||||
if (aValue.isString()) {
|
||||
JS_TraceChildren(&tracer->mChildTracer, aValue.asCell(), aValue.kind());
|
||||
}
|
||||
|
||||
// The delegate could hold alive the key, so report something to the CC
|
||||
// if we haven't already.
|
||||
if (!tracer->mChildTracer.mTracedAny &&
|
||||
aKey && xpc_IsGrayGCThing(aKey) && kdelegate) {
|
||||
tracer->mCb.NoteWeakMapping(aMap, aKey, kdelegate, nullptr);
|
||||
aKey && xpc_IsGrayGCThing(aKey.asCell()) && kdelegate) {
|
||||
tracer->mCb.NoteWeakMapping(aMap, aKey.asCell(), kdelegate, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -256,38 +254,37 @@ private:
|
||||
|
||||
static void
|
||||
FixWeakMappingGrayBits(js::WeakMapTracer* aTrc, JSObject* aMap,
|
||||
void* aKey, JSGCTraceKind aKeyKind,
|
||||
void* aValue, JSGCTraceKind aValueKind)
|
||||
JS::GCCellPtr aKey, JS::GCCellPtr aValue)
|
||||
{
|
||||
FixWeakMappingGrayBitsTracer* tracer =
|
||||
static_cast<FixWeakMappingGrayBitsTracer*>(aTrc);
|
||||
|
||||
// If nothing that could be held alive by this entry is marked gray, return.
|
||||
bool delegateMightNeedMarking = aKey && xpc_IsGrayGCThing(aKey);
|
||||
bool valueMightNeedMarking = aValue && xpc_IsGrayGCThing(aValue) &&
|
||||
aValueKind != JSTRACE_STRING;
|
||||
bool delegateMightNeedMarking = aKey && xpc_IsGrayGCThing(aKey.asCell());
|
||||
bool valueMightNeedMarking = aValue && xpc_IsGrayGCThing(aValue.asCell()) &&
|
||||
aValue.kind() != JSTRACE_STRING;
|
||||
if (!delegateMightNeedMarking && !valueMightNeedMarking) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!AddToCCKind(aKeyKind)) {
|
||||
aKey = nullptr;
|
||||
if (!AddToCCKind(aKey.kind())) {
|
||||
aKey = JS::GCCellPtr::NullPtr();
|
||||
}
|
||||
|
||||
if (delegateMightNeedMarking && aKeyKind == JSTRACE_OBJECT) {
|
||||
JSObject* kdelegate = js::GetWeakmapKeyDelegate((JSObject*)aKey);
|
||||
if (delegateMightNeedMarking && aKey.isObject()) {
|
||||
JSObject* kdelegate = js::GetWeakmapKeyDelegate(aKey.toObject());
|
||||
if (kdelegate && !xpc_IsGrayGCThing(kdelegate)) {
|
||||
if (JS::UnmarkGrayGCThingRecursively(aKey, JSTRACE_OBJECT)) {
|
||||
if (JS::UnmarkGrayGCThingRecursively(aKey.asCell(), JSTRACE_OBJECT)) {
|
||||
tracer->mAnyMarked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aValue && xpc_IsGrayGCThing(aValue) &&
|
||||
(!aKey || !xpc_IsGrayGCThing(aKey)) &&
|
||||
if (aValue && xpc_IsGrayGCThing(aValue.asCell()) &&
|
||||
(!aKey || !xpc_IsGrayGCThing(aKey.asCell())) &&
|
||||
(!aMap || !xpc_IsGrayGCThing(aMap)) &&
|
||||
aValueKind != JSTRACE_SHAPE) {
|
||||
if (JS::UnmarkGrayGCThingRecursively(aValue, aValueKind)) {
|
||||
aValue.kind() != JSTRACE_SHAPE) {
|
||||
if (JS::UnmarkGrayGCThingRecursively(aValue.asCell(), aValue.kind())) {
|
||||
tracer->mAnyMarked = true;
|
||||
}
|
||||
}
|
||||
@ -582,24 +579,10 @@ CycleCollectedJSRuntime::DescribeGCThing(bool aIsMarked, void* aThing,
|
||||
JS_snprintf(name, sizeof(name), "JS Object (Function)");
|
||||
}
|
||||
} else {
|
||||
JS_snprintf(name, sizeof(name), "JS Object (%s)",
|
||||
clasp->name);
|
||||
JS_snprintf(name, sizeof(name), "JS Object (%s)", clasp->name);
|
||||
}
|
||||
} else {
|
||||
static const char trace_types[][11] = {
|
||||
"Object",
|
||||
"String",
|
||||
"Symbol",
|
||||
"Script",
|
||||
"LazyScript",
|
||||
"IonCode",
|
||||
"Shape",
|
||||
"BaseShape",
|
||||
"TypeObject",
|
||||
};
|
||||
static_assert(MOZ_ARRAY_LENGTH(trace_types) == JSTRACE_LAST + 1,
|
||||
"JSTRACE_LAST enum must match trace_types count.");
|
||||
JS_snprintf(name, sizeof(name), "JS %s", trace_types[aTraceKind]);
|
||||
JS_snprintf(name, sizeof(name), "JS %s", JS::GCTraceKindToAscii(aTraceKind));
|
||||
}
|
||||
|
||||
// Disable printing global for objects while we figure out ObjShrink fallout.
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "mozilla/JSONWriter.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/nsMemoryInfoDumper.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "nsDumpUtils.h"
|
||||
|
||||
#include "mozilla/unused.h"
|
||||
@ -221,7 +222,7 @@ doGCCCDump(const nsCString& aInputStr)
|
||||
bool
|
||||
SetupFifo()
|
||||
{
|
||||
static bool fifoCallbacksRegistered = false;
|
||||
static DebugOnly<bool> fifoCallbacksRegistered = false;
|
||||
|
||||
if (!FifoWatcher::MaybeCreate()) {
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user