Merge inbound to m-c. a=merge

This commit is contained in:
Ryan VanderMeulen 2014-12-08 15:46:14 -05:00
commit be6607416e
56 changed files with 1045 additions and 655 deletions

View File

@ -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]

View 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);
}

View File

@ -122,10 +122,4 @@ LoadInfo::GetBaseURI(nsIURI** aBaseURI)
return NS_OK;
}
nsIURI*
LoadInfo::BaseURI()
{
return mBaseURI;
}
} // namespace mozilla

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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()
{

View File

@ -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.

View File

@ -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;

View File

@ -31,6 +31,7 @@ XPIDL_SOURCES += [
'nsIFrameRequestCallback.idl',
'nsIIdleObserver.idl',
'nsIQueryContentEventResult.idl',
'nsIRemoteBrowser.idl',
'nsIServiceWorkerManager.idl',
'nsIStructuredCloneContainer.idl',
'nsITabChild.idl',

View 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);
};

View File

@ -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);
};

View File

@ -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);

View File

@ -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,

View File

@ -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()
{

View File

@ -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;

View File

@ -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;

View File

@ -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']

View File

@ -1,4 +0,0 @@
[DEFAULT]
[browser_bug1104623.js]
run-if = buildapp == 'browser'

View File

@ -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);
});
}

View File

@ -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);
};

View File

@ -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);
}

View File

@ -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)

View File

@ -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);
};

View File

@ -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));
}
/*

View File

@ -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 */

View File

@ -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

View File

@ -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));
}
/************************************************************************/

View File

@ -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.");
}
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -33,6 +33,7 @@ UNIFIED_SOURCES += [
'testFreshGlobalEvalRedefinition.cpp',
'testFunctionProperties.cpp',
'testGCAllocator.cpp',
'testGCCellPtr.cpp',
'testGCChunkPool.cpp',
'testGCExactRooting.cpp',
'testGCFinalizeCallback.cpp',

View 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)

View File

@ -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)

View File

@ -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;

View File

@ -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)

View File

@ -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; };

View File

@ -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;

View File

@ -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)
{

View File

@ -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()));
}
}

View File

@ -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()));
}
}
}

View File

@ -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.

View File

@ -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:

View File

@ -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);

View File

@ -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(),

View File

@ -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):

View File

@ -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:

View File

@ -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()

View File

@ -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>

View File

@ -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);
}
};

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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.

View File

@ -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;