Merge mozilla-central to mozilla-inbound

This commit is contained in:
Ed Morley 2012-12-21 11:41:08 +00:00
commit 289bb2e7ae
61 changed files with 1110 additions and 391 deletions

View File

@ -1,7 +1,7 @@
[
{
"size": 676548372,
"digest": "e94c1ef674d2144ef19bf6b5faa0bc050f2f6e61d5a859c20f0d61a4665cd4587836f2c45dbc3a2b264f94b4da9db7f31d566d6ad21e9e43b90bc3f617508184",
"size": 676536592,
"digest": "5aa3f1b523faa8996dbcde44a99d846740f80b5361d3109f36688c7bac86979861311c4e7d69b67d9ea1d7c56e20947a30576b3e3f08f7c1e42ec4c2192d92e1",
"algorithm": "sha512",
"filename": "gonk.tar.xz"
}

View File

@ -6,7 +6,7 @@
<remote fetch="git://github.com/mozilla-b2g/" name="b2g"/>
<remote fetch="git://android.git.linaro.org/" name="linaro"/>
<remote fetch="git://github.com/mozilla/" name="mozilla"/>
<remote fetch="https://git.mozilla.org" name="mozillaorg"/>
<remote fetch="http://git.mozilla.org/" name="mozillaorg"/>
<default remote="linaro" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
<!-- Gonk specific things and forks -->
@ -14,13 +14,13 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="654358494ba601a46ef9838debc95417ae464cc6"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="32106d4ea635ebe17a1610b643b398db639b8b97"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7c43e273991a8a66afc88c888befb2830b7640e1"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="167b4c59a82b9130e385de786e8056d89a1cb8c3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="6ee1f8987ef36d688f97064c003ad57849dfadf2"/>
<!-- Stock Android things -->
<!-- Information: platform/abi/cpp is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.00.00.19.138 --><project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
<project name="platform/bionic" path="bionic" revision="c7bab8cb8483e7869eabdbd4add7c9e5beeecc80"/>
<!-- Information: platform/bionic is tagged with android-4.0.4_r2.1 --><project name="platform/bionic" path="bionic" revision="3d11bf0f3f3cf848f6f1e8449bf8736d8d1c78a3"/>
<!-- Information: platform/bootable/recovery is tagged with android-4.0.4_r2.1 --><project name="platform/bootable/recovery" path="bootable/recovery" revision="fadc5ac81d6400ebdd041f7d4ea64021596d6b7d"/>
<!-- Information: device/common is tagged with android-sdk-adt_r20 --><project name="device/common" path="device/common" revision="7d4526582f88808a3194e1a3b304abb369d2745c"/>
<!-- Information: device/sample is tagged with android-4.0.4_r2.1 --><project name="device/sample" path="device/sample" revision="ef228b8b377a9663e94be4b1aeb6c2bf7a07d098"/>
@ -39,16 +39,16 @@
<!-- Information: platform/external/flac is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.00.00.19.138 --><project name="platform/external/flac" path="external/flac" revision="5893fbe890f5dab8e4146d2baa4bd2691c0739e0"/>
<!-- Information: platform/external/freetype is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.00.00.19.138 --><project name="platform/external/freetype" path="external/freetype" revision="aeb407daf3711a10a27f3bc2223c5eb05158076e"/>
<!-- Information: platform/external/giflib is tagged with AU_LINUX_ANDROID_JB_REL_2.0.3.04.01.02.21.041 --><project name="platform/external/giflib" path="external/giflib" revision="b2597268aef084202a8c349d1cc072c03c6e22eb"/>
<!-- Information: platform/external/gtest is tagged with android-4.2.1_r1 --><project name="platform/external/gtest" path="external/gtest" remote="linaro" revision="344e5f3db17615cc853073a02968a603efd39109"/>
<!-- Information: platform/external/gtest is tagged with android-sdk-support_r11 --><project name="platform/external/gtest" path="external/gtest" remote="linaro" revision="344e5f3db17615cc853073a02968a603efd39109"/>
<!-- Information: platform/external/harfbuzz is tagged with android-sdk-adt_r20 --><project name="platform/external/harfbuzz" path="external/harfbuzz" revision="bae491c03a00757d83ede8d855b7d85d246bde3d"/>
<!-- Information: platform/external/icu4c is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.00.00.19.138 --><project name="platform/external/icu4c" path="external/icu4c" revision="0fa67b93b831c6636ca18b152a1b1b14cc99b034"/>
<!-- Information: platform/external/iptables is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.00.00.19.138 --><project name="platform/external/iptables" path="external/iptables" revision="3b2deb17f065c5664bb25e1a28489e5792eb63ff"/>
<!-- Information: platform/external/jhead is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.00.00.19.138 --><project name="platform/external/jhead" path="external/jhead" revision="754078052c687f6721536009c816644c73e4f145"/>
<!-- Information: platform/external/jpeg is tagged with android-4.1.1_r6.1 --><project name="platform/external/jpeg" path="external/jpeg" revision="d4fad7f50f79626455d88523207e05b868819cd8"/>
<!-- Information: platform/external/libgsm is tagged with AU_LINUX_ANDROID_JB_REL_2.0.3.04.01.02.21.041 --><project name="platform/external/libgsm" path="external/libgsm" revision="5e4516958690b9a1b2c98f88eeecba3edd2dbda4"/>
<!-- Information: platform/external/liblzf is tagged with AU_LINUX_ANDROID_JB_REL_2.0.3.04.01.02.21.041 --><project name="platform/external/liblzf" path="external/liblzf" revision="6946aa575b0949d045722794850896099d937cbb"/>
<!-- Information: platform/external/liblzf is tagged with android-sdk-support_r11 --><project name="platform/external/liblzf" path="external/liblzf" revision="6946aa575b0949d045722794850896099d937cbb"/>
<!-- Information: platform/external/libnfc-nxp is tagged with android-4.0.4_r2.1 --><project name="platform/external/libnfc-nxp" path="external/libnfc-nxp" revision="533c14450e6239cce8acb74f4e4dea2c89f8f219"/>
<!-- Information: platform/external/libnl-headers is tagged with AU_LINUX_ANDROID_JB_REL_2.0.3.04.01.02.21.041 --><project name="platform/external/libnl-headers" path="external/libnl-headers" revision="6ccf7349d61f73ac26a0675d735d903ab919c658"/>
<!-- Information: platform/external/libnl-headers is tagged with android-sdk-support_r11 --><project name="platform/external/libnl-headers" path="external/libnl-headers" revision="6ccf7349d61f73ac26a0675d735d903ab919c658"/>
<!-- Information: platform/external/libphonenumber is tagged with android-4.0.4_r2.1 --><project name="platform/external/libphonenumber" path="external/libphonenumber" revision="d470984844c388d6766c3de6ac64e93e00480fc9"/>
<!-- Information: platform/external/libpng is tagged with android-4.0.4_r2.1 --><project name="platform/external/libpng" path="external/libpng" revision="84d92c718ab9f48faec0f640747c4b6f7a995607"/>
<!-- Information: platform/external/libvpx is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.00.00.19.138 --><project name="platform/external/libvpx" path="external/libvpx" revision="3a40da0d96da5c520e7707aa14f48a80956e20d7"/>
@ -64,7 +64,7 @@
<!-- Information: platform/external/sqlite is tagged with android-4.0.4_r2.1 --><project name="platform/external/sqlite" path="external/sqlite" revision="c999ff8c12a4cf81cb9ad628f47b2720effba5e5"/>
<!-- Information: platform/external/stlport is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.00.00.19.138 --><project name="platform/external/stlport" path="external/stlport" revision="a6734e0645fce81c9610de0488b729207bfa576e"/>
<!-- Information: platform/external/strace is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.00.00.19.138 --><project name="platform/external/strace" path="external/strace" revision="c9fd2e5ef7d002e12e7cf2512506c84a9414b0fd"/>
<!-- Information: platform/external/tagsoup is tagged with AU_LINUX_ANDROID_JB_REL_2.0.3.04.01.02.21.041 --><project name="platform/external/tagsoup" path="external/tagsoup" revision="68c2ec9e0acdb3214b7fb91dbab8c9fab8736817"/>
<!-- Information: platform/external/tagsoup is tagged with android-sdk-support_r11 --><project name="platform/external/tagsoup" path="external/tagsoup" revision="68c2ec9e0acdb3214b7fb91dbab8c9fab8736817"/>
<!-- Information: platform/external/tinyalsa is tagged with android-4.0.4_r2.1 --><project name="platform/external/tinyalsa" path="external/tinyalsa" revision="495239e683a728957c890c124b239f9b7b8ef5a8"/>
<!-- Information: platform/external/tremolo is tagged with AU_LINUX_ANDROID_JB_REL_2.0.3.04.01.02.21.041 --><project name="platform/external/tremolo" path="external/tremolo" revision="25bd78d2392dbdc879ae53382cde9d019f79cf6f"/>
<!-- Information: platform/external/webp is tagged with AU_LINUX_ANDROID_JB_REL_2.0.3.04.01.02.21.041 --><project name="platform/external/webp" path="external/webp" revision="88fe2b83c4b9232cd08729556fd0485d6a6a92cd"/>
@ -90,11 +90,9 @@
<!-- Information: platform/system/vold is tagged with android-4.0.4_r2.1 --><project name="platform/system/vold" path="system/vold" revision="3ad9072a5d6f6bda32123b367545649364e3c11d"/>
<!-- Pandaboard specific things -->
<project name="android-device-panda" path="device/ti/panda" remote="b2g" revision="63196b48f479c30787863c8ca89456acd4b03910"/>
<project name="android-device-panda" path="device/ti/panda" remote="b2g" revision="0e9a89187970d6fa99930c8d9cb438b935c2337c"/>
<!-- Information: platform/hardware/ti/omap4xxx is tagged with android-4.0.4_r2.1 --><project name="platform/hardware/ti/omap4xxx" path="hardware/ti/omap4xxx" revision="8be8e9a68c96b6cf43c08a58e7ecd7708737c599"/>
<project name="platform/hardware/ti/wlan" path="hardware/ti/wlan" revision="60dfeb6e4448bfed707946ebca6612980f525e69"/>
<project name="platform/hardware/ti/wpan" path="hardware/ti/wpan" revision="3ece7d9e08052989401e008bc397dbcd2557cfd0"/>
<project name="Negatus" path="external/negatus" remote="mozilla" revision="5d5288e7bec67d0a6a29320308cccb1321062b58"/>
<project name="orangutan" path="external/orangutan" remote="b2g" revision="601280aed7d7f29f1a78496f6fa41bd79c16305c"/>
</manifest>

View File

@ -1035,7 +1035,6 @@ pref("devtools.debugger.remote-connection-retries", 3);
pref("devtools.debugger.remote-timeout", 20000);
// The default Debugger UI settings
pref("devtools.debugger.ui.height", 250);
pref("devtools.debugger.ui.win-x", 0);
pref("devtools.debugger.ui.win-y", 0);
pref("devtools.debugger.ui.win-width", 900);

View File

@ -147,8 +147,9 @@
</menupopup>
</splitmenu>
<menuseparator class="appmenu-menuseparator"/>
<menu id="appmenu_webDeveloper"
label="&appMenuWebDeveloper.label;">
<splitmenu id="appmenu_webDeveloper"
command="Tools:DevToolbox"
label="&appMenuWebDeveloper.label;">
<menupopup id="appmenu_webDeveloper_popup">
<menuitem id="appmenu_devToolbox"
observes="devtoolsMenuBroadcaster_DevToolbox"/>
@ -165,7 +166,6 @@
observes="devtoolsMenuBroadcaster_PageSource"/>
<menuitem id="appmenu_errorConsole"
observes="devtoolsMenuBroadcaster_ErrorConsole"/>
<menuseparator id="appmenu_devToolsConnectSeparator"/>
<menuitem id="appmenu_devtools_connect"
observes="devtoolsMenuBroadcaster_connect"/>
<menuseparator id="appmenu_devToolsEndSeparator"/>
@ -182,7 +182,7 @@
observes="workOfflineMenuitemState"
oncommand="BrowserOffline.toggleOfflineStatus();"/>
</menupopup>
</menu>
</splitmenu>
<menuseparator class="appmenu-menuseparator"/>
#define ID_PREFIX appmenu_
#define OMIT_ACCESSKEYS

View File

@ -584,7 +584,6 @@
<menuitem id="javascriptConsole"
observes="devtoolsMenuBroadcaster_ErrorConsole"
accesskey="&errorConsoleCmd.accesskey;"/>
<menuseparator id="menu_devToolsConnectSeparator"/>
<menuitem id="menu_devtools_connect"
observes="devtoolsMenuBroadcaster_connect"/>
<menuseparator id="devToolsEndSeparator"/>

View File

@ -97,7 +97,7 @@
<command id="Tools:ResponsiveUI" oncommand="ResponsiveUI.toggle();" disabled="true" hidden="true"/>
<command id="Tools:Addons" oncommand="BrowserOpenAddonsMgr();"/>
<command id="Tools:ErrorConsole" oncommand="toJavaScriptConsole()" disabled="true" hidden="true"/>
<command id="Tools:DevToolsConnect" oncommand="gDevToolsBrowser.openConnectScreen(gBrowser)"/>
<command id="Tools:DevToolsConnect" oncommand="gDevToolsBrowser.openConnectScreen(gBrowser)" disabled="true" hidden="true"/>
<command id="Tools:Sanitize"
oncommand="Cc['@mozilla.org/browser/browserglue;1'].getService(Ci.nsIBrowserGlue).sanitize(window);"/>
<command id="Tools:PrivateBrowsing"

View File

@ -1444,6 +1444,14 @@ var gBrowserInit = {
cmd.removeAttribute("hidden");
}
// Enable DevTools connection screen, if the preference allows this.
let devtoolsRemoteEnabled = gPrefService.getBoolPref("devtools.debugger.remote-enabled");
if (devtoolsRemoteEnabled) {
let cmd = document.getElementById("Tools:DevToolsConnect");
cmd.removeAttribute("disabled");
cmd.removeAttribute("hidden");
}
#ifdef MENUBAR_CAN_AUTOHIDE
// If the user (or the locale) hasn't enabled the top-level "Character
// Encoding" menu via the "browser.menu.showCharacterEncoding" preference,

View File

@ -146,7 +146,7 @@ else
MOCHITEST_BROWSER_FILES += \
browser_248970_a.js \
browser_248970_b.js \
+ browser_248970_b_perwindowpb.js \
browser_248970_b_perwindowpb.js \
browser_354894.js \
browser_394759_privatebrowsing.js \
$(NULL)

View File

@ -173,12 +173,6 @@ DebuggerUI.prototype = {
return '_chromeDebugger' in this ? this._chromeDebugger : null;
},
/**
* Get the preferences associated with the debugger frontend.
* @return object
*/
get preferences() Prefs,
/**
* Currently, there can only be one debugger per tab.
* Show an asynchronous notification which asks the user to switch the
@ -279,7 +273,6 @@ DebuggerPane.prototype = {
this._splitter.setAttribute("class", "devtools-horizontal-splitter");
this._frame = ownerDocument.createElement("iframe");
this._frame.height = Prefs.height;
this._nbox = gBrowser.getNotificationBox(this._tab.linkedBrowser);
this._nbox.appendChild(this._splitter);
@ -326,7 +319,6 @@ DebuggerPane.prototype = {
}, true)
}
Prefs.height = this._frame.height;
this._frame.removeEventListener("Debugger:Unloaded", this.close, true);
this._nbox.removeChild(this._splitter);
this._nbox.removeChild(this._frame);
@ -599,21 +591,7 @@ XPCOMUtils.defineLazyGetter(L10N, "stringBundle", function() {
/**
* Shortcuts for accessing various debugger preferences.
*/
let Prefs = {
/**
* Gets the preferred height of the debugger pane.
* @return number
*/
get height()
Services.prefs.getIntPref("devtools.debugger.ui.height"),
/**
* Sets the preferred height of the debugger pane.
* @param number aValue
*/
set height(aValue)
Services.prefs.setIntPref("devtools.debugger.ui.height", aValue)
};
let Prefs = {};
/**
* Gets the preferred default remote debugging host.

View File

@ -11,6 +11,7 @@ const Cu = Components.utils;
const DBG_STRINGS_URI = "chrome://browser/locale/devtools/debugger.properties";
const NEW_SCRIPT_DISPLAY_DELAY = 200; // ms
const FETCH_SOURCE_RESPONSE_DELAY = 50; // ms
const FRAME_STEP_CLEAR_DELAY = 100; // ms
const CALL_STACK_PAGE_SIZE = 25; // frames
@ -1166,6 +1167,7 @@ SourceScripts.prototype = {
DebuggerView.Sources.push(label, url, {
forced: aOptions.forced,
tooltip: url,
attachment: aSource
});
},
@ -1177,18 +1179,29 @@ SourceScripts.prototype = {
* The source object coming from the active thread.
* @param function aCallback
* Function called after the source text has been loaded.
* @param function aOnTimeout
* Function called when the source text takes too long to fetch.
*/
getText: function SS_getText(aSource, aCallback) {
getText: function SS_getText(aSource, aCallback, aOnTimeout) {
// If already loaded, return the source text immediately.
if (aSource.loaded) {
aCallback(aSource.url, aSource.text);
return;
}
// If the source text takes too long to fetch, invoke a timeout to
// avoid blocking any operations.
if (aOnTimeout) {
var fetchTimeout = window.setTimeout(aOnTimeout, FETCH_SOURCE_RESPONSE_DELAY);
}
// Get the source text from the active thread.
this.activeThread.source(aSource.source).source(function(aResponse) {
window.clearTimeout(fetchTimeout);
if (aResponse.error) {
Cu.reportError("Error loading " + aUrl);
Cu.reportError("Error loading " + aSource.url + "\n" + aResponse.error);
aCallback(aSource.url, "");
return;
}
aSource.loaded = true;
@ -1609,7 +1622,6 @@ let Prefs = {
}
};
Prefs.map("Int", "height", "devtools.debugger.ui.height");
Prefs.map("Int", "windowX", "devtools.debugger.ui.win-x");
Prefs.map("Int", "windowY", "devtools.debugger.ui.win-y");
Prefs.map("Int", "windowWidth", "devtools.debugger.ui.win-width");

View File

@ -1260,6 +1260,7 @@ function GlobalSearchView() {
MenuContainer.call(this);
this._startSearch = this._startSearch.bind(this);
this._onFetchSourceFinished = this._onFetchSourceFinished.bind(this);
this._onFetchSourceTimeout = this._onFetchSourceTimeout.bind(this);
this._onFetchSourcesFinished = this._onFetchSourcesFinished.bind(this);
this._createItemView = this._createItemView.bind(this);
this._onScroll = this._onScroll.bind(this);
@ -1402,25 +1403,29 @@ create({ constructor: GlobalSearchView, proto: MenuContainer.prototype }, {
this._sourcesCount = locations.length;
this._searchedToken = aQuery;
this._fetchSources(
this._onFetchSourceFinished,
this._onFetchSourcesFinished, locations);
this._fetchSources(locations, {
onFetch: this._onFetchSourceFinished,
onTimeout: this._onFetchSourceTimeout,
onFinished: this._onFetchSourcesFinished
});
},
/**
* Starts fetching all the sources, silently.
*
* @param function aFetchCallback
* Called after each source is fetched.
* @param function aFetchedCallback
* Called if all the sources were already fetched.
* @param array aLocations
* The locations for the sources to fetch.
* @param object aCallbacks
* An object containing the callback functions to invoke:
* - onFetch: called after each source is fetched
* - onTimeout: called when a source's text takes too long to fetch
* - onFinished: called if all the sources were already fetched
*/
_fetchSources: function DVGS__fetchSources(aFetchCallback, aFetchedCallback, aLocations) {
_fetchSources:
function DVGS__fetchSources(aLocations, { onFetch, onTimeout, onFinished }) {
// If all the sources were already fetched, then don't do anything.
if (this._cache.size == aLocations.length) {
aFetchedCallback();
onFinished();
return;
}
@ -1430,7 +1435,8 @@ create({ constructor: GlobalSearchView, proto: MenuContainer.prototype }, {
continue;
}
let sourceItem = DebuggerView.Sources.getItemByValue(location);
DebuggerController.SourceScripts.getText(sourceItem.attachment, aFetchCallback);
let sourceObject = sourceItem.attachment;
DebuggerController.SourceScripts.getText(sourceObject, onFetch, onTimeout);
}
},
@ -1452,10 +1458,24 @@ create({ constructor: GlobalSearchView, proto: MenuContainer.prototype }, {
}
},
/**
* Called when a source's text takes too long to fetch.
*/
_onFetchSourceTimeout: function DVGS__onFetchSourceTimeout() {
// Remove the source from the load queue.
this._sourcesCount--;
// Check if the remaining sources were fetched and stored in the cache.
if (this._cache.size == this._sourcesCount) {
this._onFetchSourcesFinished();
}
},
/**
* Called when all the sources have been fetched.
*/
_onFetchSourcesFinished: function DVGS__onFetchSourcesFinished() {
// At least one source needs to be present to perform a global search.
if (!this._sourcesCount) {
return;
}

View File

@ -11,7 +11,6 @@
*/
function ToolbarView() {
dumpn("ToolbarView was instantiated");
this._onCloseClick = this._onCloseClick.bind(this);
this._onTogglePanesPressed = this._onTogglePanesPressed.bind(this);
this._onResumePressed = this._onResumePressed.bind(this);
this._onStepOverPressed = this._onStepOverPressed.bind(this);
@ -108,13 +107,6 @@ ToolbarView.prototype = {
this._sources.setAttribute("hidden", !aVisibleFlag);
},
/**
* Listener handling the close button click event.
*/
_onCloseClick: function DVT__onCloseClick() {
DebuggerController._shutdownDebugger();
},
/**
* Listener handling the toggle button click event.
*/

View File

@ -618,6 +618,7 @@ MenuContainer.prototype = {
* - unsorted: true if the items should not always remain sorted
* - relaxed: true if this container should allow dupes & degenerates
* - description: an optional description of the item
* - tooltip: an optional tooltip for the item
* - attachment: some attached primitive/object
* @return MenuItem
* The item associated with the displayed element if a forced push,
@ -629,7 +630,7 @@ MenuContainer.prototype = {
// Batch the item to be added later.
if (!aOptions.forced) {
this._stagedItems.push(item);
this._stagedItems.push({ item: item, options: aOptions });
}
// Immediately insert the item at the specified index.
else if (aOptions.forced && aOptions.forced.atIndex !== undefined) {
@ -657,11 +658,12 @@ MenuContainer.prototype = {
// By default, sort the items before adding them to this container.
if (!aOptions.unsorted) {
stagedItems.sort(function(a, b) a.label.toLowerCase() > b.label.toLowerCase());
stagedItems.sort(function(a, b) a.item.label.toLowerCase() >
b.item.label.toLowerCase());
}
// Append the prepared items to this container.
for (let item of stagedItems) {
this._appendItem(item, aOptions);
for (let { item, options } of stagedItems) {
this._appendItem(item, options);
}
// Recreate the temporary items list for ulterior pushes.
this._stagedItems = [];
@ -750,7 +752,7 @@ MenuContainer.prototype = {
*/
containsLabel: function DVMC_containsLabel(aLabel) {
return this._itemsByLabel.has(aLabel) ||
this._stagedItems.some(function(o) o.label == aLabel);
this._stagedItems.some(function({item}) item.label == aLabel);
},
/**
@ -764,7 +766,7 @@ MenuContainer.prototype = {
*/
containsValue: function DVMC_containsValue(aValue) {
return this._itemsByValue.has(aValue) ||
this._stagedItems.some(function(o) o.value == aValue);
this._stagedItems.some(function({item}) item.value == aValue);
},
/**
@ -788,7 +790,7 @@ MenuContainer.prototype = {
return true;
}
}
return this._stagedItems.some(function(o) aTrim(o.value) == trimmedValue);
return this._stagedItems.some(function({item}) aTrim(item.value) == trimmedValue);
},
/**
@ -1046,8 +1048,15 @@ MenuContainer.prototype = {
return null;
}
return this._entangleItem(aItem, this._container.appendItem(
this._entangleItem(aItem, this._container.appendItem(
aItem.label, aItem.value, "", aOptions.attachment));
// Handle any additional options after entangling the item.
if (aOptions.tooltip) {
aItem._target.setAttribute("tooltiptext", aOptions.tooltip);
}
return aItem;
},
/**
@ -1068,8 +1077,15 @@ MenuContainer.prototype = {
return null;
}
return this._entangleItem(aItem, this._container.insertItemAt(
this._entangleItem(aItem, this._container.insertItemAt(
aIndex, aItem.label, aItem.value, "", aOptions.attachment));
// Handle any additional options after entangling the item.
if (aOptions.tooltip) {
aItem._target.setAttribute("tooltiptext", aOptions.tooltip);
}
return aItem;
},
/**

View File

@ -114,6 +114,16 @@ ToolSidebar.prototype = {
return currentID;
},
/**
* Returns the requested tab based on the id.
*
* @param String id
* unique id of the requested tab.
*/
getTab: function ToolSidebar_getTab(id) {
return this._tabbox.tabpanels.querySelector("#sidebar-panel-" + id);
},
/**
* Event handler.
*/
@ -176,7 +186,7 @@ ToolSidebar.prototype = {
}
this._destroyed = true;
this._tabbox.removeEventListener("select", this, true);
this._tabbox.tabpanels.removeEventListener("select", this, true);
while (this._tabbox.tabpanels.hasChildNodes()) {
this._tabbox.tabpanels.removeChild(this._tabbox.tabpanels.firstChild);

View File

@ -295,9 +295,10 @@ TabWebProgressListener.prototype = {
onSecurityChange: function() {},
onStatusChange: function() {},
onLocationChange: function TwPL_onLocationChange(webProgress) {
let window = webProgress.DOMWindow;
if (this.target) {
onLocationChange: function TwPL_onLocationChange(webProgress, request, URI, flags) {
if (this.target &&
!(flags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT)) {
let window = webProgress.DOMWindow;
this.target.emit("navigate", window);
}
},

View File

@ -69,6 +69,8 @@ let webConsoleDefinition = {
icon: "chrome://browser/skin/devtools/webconsole-tool-icon.png",
url: "chrome://browser/content/devtools/webconsole.xul",
label: l10n("ToolboxWebconsole.label", webConsoleStrings),
tooltip: l10n("ToolboxWebconsole.tooltip", webConsoleStrings),
isTargetSupported: function(target) {
return true;
},
@ -88,6 +90,7 @@ let debuggerDefinition = {
icon: "chrome://browser/skin/devtools/tools-icons-small.png",
url: "chrome://browser/content/debugger.xul",
label: l10n("ToolboxDebugger.label", debuggerStrings),
tooltip: l10n("ToolboxDebugger.tooltip", debuggerStrings),
isTargetSupported: function(target) {
return true;
@ -108,6 +111,7 @@ let inspectorDefinition = {
icon: "chrome://browser/skin/devtools/tools-icons-small.png",
url: "chrome://browser/content/devtools/inspector/inspector.xul",
label: l10n("inspector.label", inspectorStrings),
tooltip: l10n("inspector.tooltip", inspectorStrings),
isTargetSupported: function(target) {
return !target.isRemote;
@ -127,6 +131,7 @@ let styleEditorDefinition = {
modifiers: "shift",
label: l10n("ToolboxStyleEditor.label", styleEditorStrings),
url: "chrome://browser/content/styleeditor.xul",
tooltip: l10n("ToolboxStyleEditor.tooltip", styleEditorStrings),
isTargetSupported: function(target) {
return !target.isRemote && !target.isChrome;
@ -144,6 +149,7 @@ let profilerDefinition = {
icon: "chrome://browser/skin/devtools/tools-icons-small.png",
url: "chrome://browser/content/profiler.xul",
label: l10n("profiler.label", profilerStrings),
tooltip: l10n("profiler.tooltip", profilerStrings),
isTargetSupported: function (target) {
if (target.isRemote || target.isChrome) {

View File

@ -16,6 +16,17 @@ XPCOMUtils.defineLazyModuleGetter(this, "Hosts",
"resource:///modules/devtools/ToolboxHosts.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "CommandUtils",
"resource:///modules/devtools/DeveloperToolbar.jsm");
XPCOMUtils.defineLazyGetter(this, "toolboxStrings", function() {
let bundle = Services.strings.createBundle("chrome://browser/locale/devtools/toolbox.properties");
let l10n = function(name) {
try {
return bundle.GetStringFromName(name);
} catch (ex) {
Services.console.logStringMessage("Error reading '" + name + "'");
}
};
return l10n;
});
// DO NOT put Require.jsm or gcli.jsm into lazy getters as this breaks the
// requisition import a few lines down.
@ -285,6 +296,8 @@ Toolbox.prototype = {
let button = this.doc.createElement("toolbarbutton");
button.id = "toolbox-dock-" + position;
button.className = "toolbox-dock-button";
button.setAttribute("tooltiptext", toolboxStrings("toolboxDockButtons." +
position + ".tooltip"));
button.addEventListener("command", function(position) {
this.switchHost(position);
}.bind(this, position));
@ -348,6 +361,7 @@ Toolbox.prototype = {
radio.className = "toolbox-tab devtools-tab";
radio.id = "toolbox-tab-" + id;
radio.setAttribute("toolid", id);
radio.setAttribute("tooltiptext", toolDefinition.tooltip);
let ordinal = (typeof toolDefinition.ordinal == "number") ?
toolDefinition.ordinal : MAX_ORDINAL;

View File

@ -1,14 +1,25 @@
html {
background: url("chrome://browser/skin/newtab/noise.png");
background-color: #111;
background-image: url("chrome://browser/skin/newtab/noise.png");
}
body {
font-family: Arial;
padding: 20px;
border-radius: 3px;
font-family: Arial, sans-serif;
color: white;
max-width: 600px;
min-height: 400px;
margin: 10px auto 0;
margin: 30px auto 0;
box-shadow: 0 2px 3px black;
background-color: #3C3E40;
}
h1 {
margin: 0;
padding: 20px;
background-color: rgba(0,0,0,0.12);
background-image: radial-gradient(ellipse farthest-corner at center top , rgb(159, 223, 255), rgba(101, 203, 255, 0.3)), radial-gradient(ellipse farthest-side at center top , rgba(101, 203, 255, 0.4), rgba(101, 203, 255, 0));
background-size: 100% 2px, 100% 5px;
background-repeat: no-repeat;
border-bottom: 1px solid rgba(0,0,0,0.1);
}
label {
@ -29,18 +40,21 @@ label > span {
margin-left: 160px;
}
#actors, #connection-form {
margin: 20px;
input:invalid {
box-shadow: 0 0 2px 2px #F06;
}
input {
border: 1px solid grey;
section {
min-height: 160px;
margin: 60px 20px;
display: none; /* By default, hidden */
}
#connection-form,
#connecting,
#actors-list {
.error-message {
color: red;
}
.error-message:not(.active) {
display: none;
}
@ -60,20 +74,9 @@ body.connecting > #connecting {
text-align: center;
}
#throbber {
height: 7px; width: 7px;
border-radius: 50%;
background: black;
display: inline-block;
animation-duration: 0.6s;
animation-name: anim;
animation-direction: alternate;
animation-iteration-count: infinite;
animation-timing-function: linear;
#connecting > p > img {
vertical-align: top;
}
@keyframes anim {to {
transform: scale(0.5) rotate(0.1deg);
}}
#actors {
padding-left: 0;
@ -84,4 +87,22 @@ body.connecting > #connecting {
display: block;
margin: 5px;
padding: 5px;
color: white;
}
.remote-process {
font-style: italic;
opacity: 0.8;
}
footer {
padding: 10px;
background-color: rgba(0,0,0,0.12);
border-top: 1px solid rgba(0,0,0,0.1);
font-size: small;
}
footer > a,
footer > a:visited {
color: white;
}

View File

@ -10,91 +10,158 @@ const Cu = Components.utils;
Cu.import("resource:///modules/devtools/Target.jsm");
Cu.import("resource:///modules/devtools/Toolbox.jsm");
Cu.import("resource:///modules/devtools/gDevTools.jsm");
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
let gClient;
let gConnectionTimeout;
XPCOMUtils.defineLazyGetter(window, 'l10n', function () {
return Services.strings.createBundle('chrome://browser/locale/devtools/connection-screen.properties');
});
/**
* Once DOM is ready, we prefil the host/port inputs with
* pref-stored values.
*/
window.addEventListener("DOMContentLoaded", function onDOMReady() {
window.removeEventListener("DOMContentLoaded", onDOMReady, true);
let host = Services.prefs.getCharPref("devtools.debugger.remote-host");
let port = Services.prefs.getIntPref("devtools.debugger.remote-port");
if (host) {
document.getElementById("host").value = host;
}
if (port) {
document.getElementById("port").value = port;
}
}, true);
/**
* Called when the "connect" button is clicked.
*/
function submit() {
// Show the "connecting" screen
document.body.classList.add("connecting");
// Save the host/port values
let host = document.getElementById("host").value;
Services.prefs.setCharPref("devtools.debugger.remote-host", host);
let port = document.getElementById("port").value;
if (!host) {
host = Services.prefs.getCharPref("devtools.debugger.remote-host");
} else {
Services.prefs.setCharPref("devtools.debugger.remote-host", host);
}
if (!port) {
port = Services.prefs.getIntPref("devtools.debugger.remote-port");
} else {
Services.prefs.setIntPref("devtools.debugger.remote-port", port);
}
Services.prefs.setIntPref("devtools.debugger.remote-port", port);
// Initiate the connection
let transport = debuggerSocketConnect(host, port);
let client = gClient = new DebuggerClient(transport);
gClient = new DebuggerClient(transport);
let delay = Services.prefs.getIntPref("devtools.debugger.remote-timeout");
gConnectionTimeout = setTimeout(handleConnectionTimeout, delay);
gClient.connect(onConnectionReady);
}
client.connect(function(aType, aTraits) {
client.listTabs(function(aResponse) {
document.body.classList.remove("connecting");
document.body.classList.add("actors-mode");
/**
* Connection is ready. List actors and build buttons.
*/
function onConnectionReady(aType, aTraits) {
clearTimeout(gConnectionTimeout);
gClient.listTabs(function(aResponse) {
document.body.classList.remove("connecting");
document.body.classList.add("actors-mode");
let parent = document.getElementById("actors");
let focusSet = false;
let parent = document.getElementById("actors");
// Add Global Process debugging...
let globals = JSON.parse(JSON.stringify(aResponse));
delete globals.tabs;
delete globals.selected;
// ...only if there are appropriate actors (a 'from' property will always
// be there).
if (Object.keys(globals).length > 1) {
let a = document.createElement("a");
a.onclick = function() {
connect(globals, true);
}
// Add Global Process debugging...
let globals = JSON.parse(JSON.stringify(aResponse));
delete globals.tabs;
delete globals.selected;
// ...only if there are appropriate actors (a 'from' property will always
// be there).
a.title = a.textContent = "Remote process";
a.href = "#";
// Add one entry for each open tab.
for (let i = 0; i < aResponse.tabs.length; i++) {
buildLink(aResponse.tabs[i], parent, i == aResponse.selected);
}
// Build the Remote Process button
if (Object.keys(globals).length > 1) {
let a = document.createElement("a");
a.onclick = function() {
openToolbox(globals, true);
parent.appendChild(a);
}
a.title = a.textContent = window.l10n.GetStringFromName("remoteProcess");
a.className = "remote-process";
a.href = "#";
parent.appendChild(a);
}
// Move the selected tab on top
let selectedLink = parent.querySelector("a.selected");
if (selectedLink) {
parent.insertBefore(selectedLink, parent.firstChild);
}
// Add one entry for each open tab.
if (aResponse.tabs.length > 0) {
let header = document.createElement("div");
header.innerHTML = "Tabs:";
parent.appendChild(header);
}
for (let i = 0; i < aResponse.tabs.length; i++) {
let tab = aResponse.tabs[i];
// Ensure the first link is focused
let firstLink = parent.querySelector("a:first-of-type");
if (firstLink) {
firstLink.focus();
}
let a = document.createElement("a");
a.onclick = function() {
connect(tab);
}
a.title = a.textContent = tab.title;
a.href = "#";
if (i == aResponse.selected) {
a.title += " [*]";
a.textContent = a.title;
}
parent.appendChild(a);
if (!focusSet) {
a.focus();
focusSet = true;
}
}
});
});
}
function connect(form, chrome=false) {
/**
* Build one button for an actor.
*/
function buildLink(tab, parent, selected) {
let a = document.createElement("a");
a.onclick = function() {
openToolbox(tab);
}
a.textContent = tab.title;
a.title = tab.url;
if (!a.textContent) {
a.textContent = tab.url;
}
a.href = "#";
if (selected) {
a.classList.add("selected");
}
parent.appendChild(a);
}
/**
* An error occured. Let's show it and return to the first screen.
*/
function showError(type) {
document.body.className = "error";
let activeError = document.querySelector(".error-message.active");
if (activeError) {
activeError.classList.remove("active");
}
activeError = document.querySelector(".error-" + type);
if (activeError) {
activeError.classList.add("active");
}
}
/**
* Connection timeout.
*/
function handleConnectionTimeout() {
showError("timeout");
}
/**
* The user clicked on one of the buttons.
* Opens the toolbox.
*/
function openToolbox(form, chrome=false) {
let target = TargetFactory.forRemote(form, gClient, chrome);
gDevTools.showToolbox(target, "webconsole", Toolbox.HostType.WINDOW);
window.close();
}

View File

@ -12,34 +12,37 @@
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<head>
<title>&title;</title>
<link rel="stylesheet" href="chrome://browser/skin/devtools/common.css" type="text/css"/>
<link rel="stylesheet" href="chrome://browser/content/devtools/connect.css" type="text/css"/>
<script type="application/javascript;version=1.8" src="connect.js"></script>
</head>
<body>
<p>
</p>
<h1>&header;</h1>
<section id="connection-form">
<form onsubmit="window.submit()" action="#">
<form validate="validate" onsubmit="window.submit()" action="#">
<label>
<span>&host;</span>
<input id="host" type="text" placeholder="localhost"></input>
<input required="required" class="devtools-textinput" id="host" type="text"></input>
</label>
<label>
<span>&port;</span>
<input id="port" type="number" placeholder="6000"></input>
<input required="required" class="devtools-textinput" id="port" type="number" pattern="\d+"></input>
</label>
<label>
<input id="submit" type="submit" value="&connect;"></input>
<input class="devtools-toolbarbutton" id="submit" type="submit" value="&connect;"></input>
</label>
</form>
<p class="error-message error-timeout">&errorTimeout;</p>
<p class="error-message error-refused">&errorRefused;</p>
<p class="error-message error-unexpected">&errorUnexpected;</p>
</section>
<section id="actors-list">
<p>&availability;</p>
<ul id="actors"></ul>
</section>
<section id="connecting">
<p>&connecting;</p>
<div id="throbber"></div>
<p><img src="chrome://browser/skin/tabbrowser/loading.png"></img> &connecting;</p>
</section>
<footer>&help;</footer>
</body>
</html>

View File

@ -2,6 +2,10 @@
<!-- 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/. -->
<!DOCTYPE window [
<!ENTITY % toolboxDTD SYSTEM "chrome://browser/locale/devtools/toolbox.dtd" >
%toolboxDTD;
]>
<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/devtools/shared/common.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/devtools/framework/toolbox.css" type="text/css"?>
@ -15,7 +19,9 @@
<toolbar class="devtools-tabbar">
#ifdef XP_MACOSX
<hbox id="toolbox-controls">
<toolbarbutton id="toolbox-close" class="devtools-closebutton"></toolbarbutton>
<toolbarbutton id="toolbox-close"
class="devtools-closebutton"
tooltiptext="&toolboxCloseButton.tooltip;"/>
<hbox id="toolbox-dock-buttons"/>
</hbox>
#endif
@ -25,7 +31,9 @@
#ifndef XP_MACOSX
<hbox id="toolbox-controls">
<hbox id="toolbox-dock-buttons"/>
<toolbarbutton id="toolbox-close" class="devtools-closebutton"></toolbarbutton>
<toolbarbutton id="toolbox-close"
class="devtools-closebutton"
tooltiptext="&toolboxCloseButton.tooltip;"/>
</hbox>
#endif
</toolbar>

View File

@ -83,7 +83,6 @@ HTMLBreadcrumbs.prototype = {
this.update = this.update.bind(this);
this.updateSelectors = this.updateSelectors.bind(this);
this.selection.on("new-node", this.update);
this.selection.on("detached", this.update);
this.selection.on("pseudoclass", this.updateSelectors);
this.selection.on("attribute-changed", this.updateSelectors);
this.update();
@ -296,7 +295,6 @@ HTMLBreadcrumbs.prototype = {
});
this.selection.off("new-node", this.update);
this.selection.off("detached", this.update);
this.selection.off("pseudoclass", this.updateSelectors);
this.selection.off("attribute-changed", this.updateSelectors);

View File

@ -133,7 +133,6 @@ Highlighter.prototype = {
this.selection.on("new-node", this.highlight);
this.selection.on("new-node", this.updateInfobar);
this.selection.on("detached", this.highlight);
this.selection.on("pseudoclass", this.updateInfobar);
this.selection.on("attribute-changed", this.updateInfobar);
@ -168,7 +167,6 @@ Highlighter.prototype = {
this.selection.off("new-node", this.highlight);
this.selection.off("new-node", this.updateInfobar);
this.selection.off("detached", this.highlight);
this.selection.off("pseudoclass", this.updateInfobar);
this.selection.off("attribute-changed", this.updateInfobar);

View File

@ -68,6 +68,8 @@ InspectorPanel.prototype = {
this._selection = new Selection();
this.onNewSelection = this.onNewSelection.bind(this);
this.selection.on("new-node", this.onNewSelection);
this.onDetached = this.onDetached.bind(this);
this.selection.on("detached", this.onDetached);
this.breadcrumbs = new HTMLBreadcrumbs(this);
@ -170,6 +172,7 @@ InspectorPanel.prototype = {
}.bind(this);
this.sidebar.on("select", this._setDefaultSidebar);
this.toggleHighlighter = this.toggleHighlighter.bind(this);
this.sidebar.addTab("ruleview",
"chrome://browser/content/devtools/cssruleview.xul",
@ -183,6 +186,10 @@ InspectorPanel.prototype = {
"chrome://browser/content/devtools/layoutview/view.xhtml",
"layoutview" == defaultTab);
let ruleViewTab = this.sidebar.getTab("ruleview");
ruleViewTab.addEventListener("mouseover", this.toggleHighlighter, false);
ruleViewTab.addEventListener("mouseout", this.toggleHighlighter, false);
this.sidebar.show();
},
@ -275,6 +282,15 @@ InspectorPanel.prototype = {
this.cancelLayoutChange();
},
/**
* When a node is deleted, select its parent node.
*/
onDetached: function InspectorPanel_onDetached(event, parentNode) {
this.cancelLayoutChange();
this.breadcrumbs.cutAfter(this.breadcrumbs.indexOf(parentNode));
this.selection.setNode(parentNode, "detached");
},
/**
* Destroy the inspector.
*/
@ -310,6 +326,7 @@ InspectorPanel.prototype = {
this.nodemenu.removeEventListener("popuphiding", this._resetNodeMenu, true);
this.breadcrumbs.destroy();
this.selection.off("new-node", this.onNewSelection);
this.selection.off("detached", this.onDetached);
this._destroyMarkup();
this._selection.destroy();
this._selection = null;
@ -447,6 +464,19 @@ InspectorPanel.prototype = {
this.selection.emit("pseudoclass");
},
/**
* Toggle the highlighter when ruleview is hovered.
*/
toggleHighlighter: function InspectorPanel_toggleHighlighter(event)
{
if (event.type == "mouseover") {
this.highlighter.hide();
}
else if (event.type == "mouseout") {
this.highlighter.show();
}
},
/**
* Copy the innerHTML of the selected Node to the clipboard.
*/

View File

@ -70,12 +70,14 @@ Selection.prototype = {
_onMutations: function(mutations) {
let attributeChange = false;
let detached = false;
let parentNode = null;
for (let m of mutations) {
if (!attributeChange && m.type == "attributes") {
attributeChange = true;
}
if (m.type == "childList") {
if (!detached && !this.isConnected()) {
parentNode = m.target;
detached = true;
}
}
@ -84,7 +86,7 @@ Selection.prototype = {
if (attributeChange)
this.emit("attribute-changed");
if (detached)
this.emit("detached");
this.emit("detached", parentNode);
},
_attachEvents: function SN__attachEvents() {

View File

@ -35,6 +35,7 @@ _BROWSER_FILES = \
browser_inspector_highlighter_autohide.js \
browser_inspector_changes.js \
browser_inspector_bug_674871.js \
browser_inspector_bug_817558_delete_node.js \
head.js \
helpers.js \
$(NULL)

View File

@ -104,7 +104,7 @@ function test() {
is(para.textContent, "test2", "paragraph content is correct");
let root = content.document.documentElement;
ok(inspector.selection.node, root, "Selection is the root of the new page.");
is(inspector.selection.node, root, "Selection is the root of the new page.");
ok(alertActive1_called, "first notification box has been showed");
ok(alertActive2_called, "second notification box has been showed");

View File

@ -0,0 +1,50 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test()
{
waitForExplicitFinish();
//ignoreAllUncaughtExceptions();
let node, iframe, inspector;
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
waitForFocus(setupTest, content);
}, true);
content.location = "http://mochi.test:8888/browser/browser/devtools/inspector/test/browser_inspector_destroyselection.html";
function setupTest()
{
iframe = content.document.querySelector("iframe");
node = iframe.contentDocument.querySelector("span");
openInspector(runTests);
}
function runTests(aInspector)
{
inspector = aInspector;
inspector.selection.setNode(node);
let parentNode = node.parentNode;
parentNode.removeChild(node);
let tmp = {};
Cu.import("resource:///modules/devtools/LayoutHelpers.jsm", tmp);
ok(!tmp.LayoutHelpers.isNodeConnected(node), "Node considered as disconnected.");
executeSoon(function() {
is(inspector.selection.node, parentNode, "parent of selection got selected");
finishUp();
});
}
function finishUp() {
node = null;
gBrowser.removeCurrentTab();
finish();
}
}

View File

@ -35,7 +35,6 @@ LayoutView.prototype = {
this.update = this.update.bind(this);
this.onNewNode = this.onNewNode.bind(this);
this.onHighlighterLocked = this.onHighlighterLocked.bind(this);
this.inspector.selection.on("detached", this.onNewNode);
this.inspector.selection.on("new-node", this.onNewNode);
this.inspector.sidebar.on("layoutview-selected", this.onNewNode);
if (this.inspector.highlighter) {
@ -101,7 +100,6 @@ LayoutView.prototype = {
destroy: function LV_destroy() {
this.inspector.sidebar.off("layoutview-selected", this.onNewNode);
this.inspector.selection.off("new-node", this.onNewNode);
this.inspector.selection.off("detached", this.onNewNode);
if (this.browser) {
this.browser.removeEventListener("MozAfterPaint", this.update, true);
}

View File

@ -12,6 +12,7 @@ const Ci = Components.interfaces;
const PAGE_SIZE = 10;
const PREVIEW_AREA = 700;
const DEFAULT_MAX_CHILDREN = 100;
this.EXPORTED_SYMBOLS = ["MarkupView"];
@ -20,6 +21,7 @@ Cu.import("resource:///modules/devtools/CssRuleView.jsm");
Cu.import("resource:///modules/devtools/Templater.jsm");
Cu.import("resource:///modules/devtools/Undo.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
/**
* Vocabulary for the purposes of this file:
@ -46,6 +48,12 @@ this.MarkupView = function MarkupView(aInspector, aFrame, aControllerWindow)
this.doc = this._frame.contentDocument;
this._elt = this.doc.querySelector("#root");
try {
this.maxChildren = Services.prefs.getIntPref("devtools.markup.pagesize");
} catch(ex) {
this.maxChildren = DEFAULT_MAX_CHILDREN;
}
this.undo = new UndoStack();
this.undo.installController(aControllerWindow);
@ -69,7 +77,7 @@ this.MarkupView = function MarkupView(aInspector, aFrame, aControllerWindow)
MarkupView.prototype = {
_selectedContainer: null,
template: function MT_template(aName, aDest, aOptions)
template: function MT_template(aName, aDest, aOptions={stack: "markup-view.xhtml"})
{
let node = this.doc.getElementById("template-" + aName).cloneNode(true);
node.removeAttribute("id");
@ -288,7 +296,6 @@ MarkupView.prototype = {
let walker = documentWalker(aNode);
let parent = walker.parentNode();
if (parent) {
// Make sure parents of this node are imported too.
var container = new MarkupContainer(this, aNode);
} else {
var container = new RootContainer(this, aNode);
@ -298,12 +305,15 @@ MarkupView.prototype = {
// Fake a childList mutation here.
this._mutationObserver([{target: aEvent.target, type: "childList"}]);
}.bind(this), true);
}
this._containers.set(aNode, container);
// FIXME: set an expando to prevent the the wrapper from disappearing
// See bug 819131 for details.
aNode.__preserveHack = true;
container.expanded = aExpand;
container.childrenDirty = true;
this._updateChildren(container);
if (parent) {
@ -327,6 +337,7 @@ MarkupView.prototype = {
if (mutation.type === "attributes" || mutation.type === "characterData") {
container.update();
} else if (mutation.type === "childList") {
container.childrenDirty = true;
this._updateChildren(container);
}
}
@ -339,10 +350,12 @@ MarkupView.prototype = {
*/
showNode: function MT_showNode(aNode, centered)
{
this.importNode(aNode);
let container = this.importNode(aNode);
this._updateChildren(container);
let walker = documentWalker(aNode);
let parent;
while (parent = walker.parentNode()) {
this._updateChildren(this.getContainer(parent));
this.expandNode(parent);
}
LayoutHelpers.scrollIntoViewIfNeeded(this._containers.get(aNode).editor.elt, centered);
@ -421,9 +434,32 @@ MarkupView.prototype = {
this._selectedContainer.selected = true;
}
this._ensureSelectionVisible();
return true;
},
/**
* Make sure that every ancestor of the selection are updated
* and included in the list of visible children.
*/
_ensureSelectionVisible: function MT_ensureSelectionVisible()
{
let node = this._selectedContainer.node;
let walker = documentWalker(node);
while (node) {
let container = this._containers.get(node);
let parent = walker.parentNode();
if (!container.elt.parentNode) {
let parentContainer = this._containers.get(parent);
parentContainer.childrenDirty = true;
this._updateChildren(parentContainer, node);
}
node = parent;
}
},
/**
* Unmark selected node (no node selected).
*/
@ -448,29 +484,139 @@ MarkupView.prototype = {
/**
* Make sure all children of the given container's node are
* imported and attached to the container in the right order.
* @param aCentered If provided, this child will be included
* in the visible subset, and will be roughly centered
* in that list.
*/
_updateChildren: function MT__updateChildren(aContainer)
_updateChildren: function MT__updateChildren(aContainer, aCentered)
{
if (!aContainer.childrenDirty) {
return false;
}
// Get a tree walker pointing at the first child of the node.
let treeWalker = documentWalker(aContainer.node);
let child = treeWalker.firstChild();
aContainer.hasChildren = !!child;
if (aContainer.expanded) {
let lastContainer = null;
while (child) {
let container = this.importNode(child, false);
// Make sure children are in the right order.
let before = lastContainer ? lastContainer.nextSibling : aContainer.children.firstChild;
aContainer.children.insertBefore(container.elt, before);
lastContainer = container.elt;
child = treeWalker.nextSibling();
if (!aContainer.expanded) {
return;
}
aContainer.childrenDirty = false;
let children = this._getVisibleChildren(aContainer, aCentered);
let fragment = this.doc.createDocumentFragment();
for (child of children.children) {
let container = this.importNode(child, false);
fragment.appendChild(container.elt);
}
while (aContainer.children.firstChild) {
aContainer.children.removeChild(aContainer.children.firstChild);
}
if (!(children.hasFirst && children.hasLast)) {
let data = {
showing: this.strings.GetStringFromName("markupView.more.showing"),
showAll: this.strings.formatStringFromName(
"markupView.more.showAll",
[aContainer.node.children.length.toString()], 1),
allButtonClick: function() {
aContainer.maxChildren = -1;
aContainer.childrenDirty = true;
this._updateChildren(aContainer);
}.bind(this)
};
if (!children.hasFirst) {
let span = this.template("more-nodes", data);
fragment.insertBefore(span, fragment.firstChild);
}
while (aContainer.children.lastChild != lastContainer) {
aContainer.children.removeChild(aContainer.children.lastChild);
if (!children.hasLast) {
let span = this.template("more-nodes", data);
fragment.appendChild(span);
}
}
aContainer.children.appendChild(fragment);
return true;
},
/**
* Return a list of the children to display for this container.
*/
_getVisibleChildren: function MV__getVisibleChildren(aContainer, aCentered)
{
let maxChildren = aContainer.maxChildren || this.maxChildren;
if (maxChildren == -1) {
maxChildren = Number.MAX_VALUE;
}
let firstChild = documentWalker(aContainer.node).firstChild();
let lastChild = documentWalker(aContainer.node).lastChild();
if (!firstChild) {
// No children, we're done.
return { hasFirst: true, hasLast: true, children: [] };
}
// By default try to put the selected child in the middle of the list.
let start = aCentered || firstChild;
// Start by reading backward from the starting point....
let nodes = [];
let backwardWalker = documentWalker(start);
if (backwardWalker.previousSibling()) {
let backwardCount = Math.floor(maxChildren / 2);
let backwardNodes = this._readBackward(backwardWalker, backwardCount);
nodes = backwardNodes;
}
// Then read forward by any slack left in the max children...
let forwardWalker = documentWalker(start);
let forwardCount = maxChildren - nodes.length;
nodes = nodes.concat(this._readForward(forwardWalker, forwardCount));
// If there's any room left, it means we've run all the way to the end.
// In that case, there might still be more items at the front.
let remaining = maxChildren - nodes.length;
if (remaining > 0 && nodes[0] != firstChild) {
let firstNodes = this._readBackward(backwardWalker, remaining);
// Then put it all back together.
nodes = firstNodes.concat(nodes);
}
return {
hasFirst: nodes[0] == firstChild,
hasLast: nodes[nodes.length - 1] == lastChild,
children: nodes
};
},
_readForward: function MV__readForward(aWalker, aCount)
{
let ret = [];
let node = aWalker.currentNode;
do {
ret.push(node);
node = aWalker.nextSibling();
} while (node && --aCount);
return ret;
},
_readBackward: function MV__readBackward(aWalker, aCount)
{
let ret = [];
let node = aWalker.currentNode;
do {
ret.push(node);
node = aWalker.previousSibling();
} while(node && --aCount);
ret.reverse();
return ret;
},
/**
@ -618,9 +764,7 @@ function MarkupContainer(aMarkupView, aNode)
this.expander = null;
this.codeBox = null;
this.children = null;
let options = { stack: "markup-view.xhtml" };
this.markup.template("container", this, options);
this.markup.template("container", this);
this.elt.container = this;
this.expander.addEventListener("click", function() {
@ -734,7 +878,7 @@ MarkupContainer.prototype = {
if (focusable) {
focusable.focus();
}
}
},
}
/**
@ -841,13 +985,12 @@ function ElementEditor(aContainer, aNode)
this.attrList = null;
this.newAttr = null;
this.closeElt = null;
let options = { stack: "markup-view.xhtml" };
// Create the main editor
this.template("element", this, options);
this.template("element", this);
// Create the closing tag
this.template("elementClose", this, options);
this.template("elementClose", this);
// Make the tag name editable (unless this is a document element)
if (aNode != aNode.ownerDocument.documentElement) {
@ -927,8 +1070,7 @@ ElementEditor.prototype = {
let data = {
attrName: aAttr.name,
};
let options = { stack: "markup-view.xhtml" };
this.template("attribute", data, options);
this.template("attribute", data);
var {attr, inner, name, val} = data;
// Figure out where we should place the attribute.
@ -1260,3 +1402,8 @@ function whitespaceTextFilter(aNode)
return Ci.nsIDOMNodeFilter.FILTER_ACCEPT;
}
}
XPCOMUtils.defineLazyGetter(MarkupView.prototype, "strings", function () {
return Services.strings.createBundle(
"chrome://browser/locale/devtools/inspector.properties");
});

View File

@ -16,6 +16,8 @@
<div id="templates" style="display:none">
<ul>
<li id="template-container" save="${elt}" class="container"><span save="${expander}" class="expander"></span><span save="${codeBox}" class="codebox"><ul save="${children}" class="children"></ul></span></li>
<li id="template-more-nodes" class="more-nodes devtools-class-comment" save="${elt}"><span>${showing}</span> <button href="#" onclick="${allButtonClick}">${showAll}</button></li>
</ul>
<span id="template-element" save="${elt}" class="editor"><span>&lt;</span><span save="${tag}" class="tagname devtools-theme-tagname"></span><span save="${attrList}"></span><span save="${newAttr}" class="newattr" tabindex="0"></span>&gt;</span>

View File

@ -17,7 +17,9 @@ _BROWSER_FILES = \
browser_inspector_markup_mutation.html \
browser_inspector_markup_mutation.js \
browser_inspector_markup_edit.html \
browser_inspector_markup_edit.js \
browser_inspector_markup_edit.js \
browser_inspector_markup_subset.html \
browser_inspector_markup_subset.js \
head.js \
$(NULL)

View File

@ -0,0 +1,32 @@
<!DOCTYPE html>
<html class="html">
<body class="body">
<div id="a"></div>
<div id="b"></div>
<div id="c"></div>
<div id="d"></div>
<div id="e"></div>
<div id="f"></div>
<div id="g"></div>
<div id="h"></div>
<div id="i"></div>
<div id="j"></div>
<div id="k"></div>
<div id="l"></div>
<div id="m"></div>
<div id="n"></div>
<div id="o"></div>
<div id="p"></div>
<div id="q"></div>
<div id="r"></div>
<div id="s"></div>
<div id="t"></div>
<div id="u"></div>
<div id="v"></div>
<div id="w"></div>
<div id="x"></div>
<div id="y"></div>
<div id="z"></div>
</body>
</html>

View File

@ -0,0 +1,146 @@
/* Any copyright", " is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that the markup view loads only as many nodes as specified
* by the devtools.markup.pagesize preference.
*/
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.markup.pagesize");
});
Services.prefs.setIntPref("devtools.markup.pagesize", 5);
function test() {
waitForExplicitFinish();
// Will hold the doc we're viewing
let doc;
let inspector;
// Holds the MarkupTool object we're testing.
let markup;
function assertChildren(expected)
{
let container = markup.getContainer(doc.querySelector("body"));
let found = [];
for (let child of container.children.children) {
if (child.classList.contains("more-nodes")) {
found += "*more*";
} else {
found += child.container.node.getAttribute("id");
}
}
is(expected, found, "Got the expected children.");
}
function forceReload()
{
let container = markup.getContainer(doc.querySelector("body"));
container.childrenDirty = true;
}
let selections = [
{
desc: "Select the first item",
selector: "#a",
before: function() {
},
after: function() {
assertChildren("abcde*more*");
}
},
{
desc: "Select the last item",
selector: "#z",
before: function() {},
after: function() {
assertChildren("*more*vwxyz");
}
},
{
desc: "Select an already-visible item",
selector: "#v",
before: function() {},
after: function() {
// Because "v" was already visible, we shouldn't have loaded
// a different page.
assertChildren("*more*vwxyz");
},
},
{
desc: "Verify childrenDirty reloads the page",
selector: "#w",
before: function() {
forceReload();
},
after: function() {
// But now that we don't already have a loaded page, selecting
// w should center around w.
assertChildren("*more*uvwxy*more*");
},
},
];
// Create the helper tab for parsing...
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
doc = content.document;
waitForFocus(setupTest, content);
}, true);
content.location = "http://mochi.test:8888/browser/browser/devtools/markupview/test/browser_inspector_markup_subset.html";
function setupTest() {
var target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
toolbox.once("inspector-selected", function SE_selected(id, aInspector) {
inspector = aInspector;
markup = inspector.markup;
runNextSelection();
});
});
}
function runTests() {
inspector.selection.once("new-node", startTests);
executeSoon(function() {
inspector.selection.setNode(doc.body);
});
}
function runNextSelection() {
let selection = selections.shift();
if (!selection) {
clickMore();
return;
}
info(selection.desc);
selection.before();
inspector.selection.once("new-node", function() {
selection.after();
runNextSelection();
});
inspector.selection.setNode(doc.querySelector(selection.selector));
}
function clickMore() {
info("Check that clicking more loads the whole thing.");
// Make sure that clicking the "more" button loads all the nodes.
let container = markup.getContainer(doc.querySelector("body"));
let button = container.elt.querySelector("button");
button.click();
assertChildren("abcdefghijklmnopqrstuvwxyz");
finishUp();
}
function finishUp() {
doc = inspector = null;
gBrowser.removeCurrentTab();
finish();
}
}

View File

@ -158,9 +158,6 @@ function ResponsiveUI(aWindow, aTab)
this.buildUI();
this.checkMenus();
let target = TargetFactory.forTab(this.tab);
this.toolboxWasOpen = !!gDevTools.getToolbox(target);
try {
if (Services.prefs.getBoolPref("devtools.responsiveUI.rotate")) {
this.rotate();
@ -239,17 +236,9 @@ ResponsiveUI.prototype = {
if (aEvent.keyCode == this.mainWindow.KeyEvent.DOM_VK_ESCAPE &&
this.mainWindow.gBrowser.selectedBrowser == this.browser) {
// If the toolbox wasn't open at first but is open now,
// we don't want to close the Responsive Mode on Escape.
// We let the toolbox close first.
let target = TargetFactory.forTab(this.tab);
let isToolboxOpen = !!gDevTools.getToolbox(target);
if (this.toolboxWasOpen || !isToolboxOpen) {
aEvent.preventDefault();
aEvent.stopPropagation();
this.close();
}
aEvent.preventDefault();
aEvent.stopPropagation();
this.close();
}
},

View File

@ -69,11 +69,29 @@ this.ScratchpadManager = {
saveOpenWindows: function SPM_saveOpenWindows() {
this._scratchpads = [];
function clone(src) {
let dest = {};
for (let key in src) {
if (src.hasOwnProperty(key)) {
dest[key] = src[key];
}
}
return dest;
}
// We need to clone objects we get from Scratchpad instances
// because such (cross-window) objects have a property 'parent'
// that holds on to a ChromeWindow instance. This means that
// such objects are not primitive-values-only anymore so they
// can leak.
let enumerator = Services.wm.getEnumerator("devtools:scratchpad");
while (enumerator.hasMoreElements()) {
let win = enumerator.getNext();
if (!win.closed && win.Scratchpad.initialized) {
this._scratchpads.push(win.Scratchpad.getState());
this._scratchpads.push(clone(win.Scratchpad.getState()));
}
}
},
@ -106,6 +124,7 @@ this.ScratchpadManager = {
let win = Services.ww.openWindow(null, SCRATCHPAD_WINDOW_URL, "_blank",
SCRATCHPAD_WINDOW_FEATURES, params);
// Only add the shutdown observer if we've opened a scratchpad window.
ShutdownObserver.init();
@ -128,6 +147,7 @@ var ShutdownObserver = {
}
Services.obs.addObserver(this, "quit-application-granted", false);
this._initialized = true;
},
@ -143,4 +163,4 @@ var ShutdownObserver = {
{
Services.obs.removeObserver(this, "quit-application-granted");
}
};
};

View File

@ -133,6 +133,7 @@ this.CssHtmlTree = function CssHtmlTree(aStyleInspector)
this.getRTLAttr = chromeReg.isLocaleRTL("global") ? "rtl" : "ltr";
// Create bound methods.
this.siFocusWindow = this.focusWindow.bind(this);
this.siBoundMenuUpdate = this.computedViewMenuUpdate.bind(this);
this.siBoundCopy = this.computedViewCopy.bind(this);
this.siBoundCopyDeclaration = this.computedViewCopyDeclaration.bind(this);
@ -140,6 +141,7 @@ this.CssHtmlTree = function CssHtmlTree(aStyleInspector)
this.siBoundCopyPropertyValue = this.computedViewCopyPropertyValue.bind(this);
this.styleDocument.addEventListener("copy", this.siBoundCopy);
this.styleDocument.addEventListener("mousedown", this.siFocusWindow);
// Nodes used in templating
this.root = this.styleDocument.getElementById("root");
@ -557,6 +559,17 @@ CssHtmlTree.prototype = {
menuitem.disabled = disablePropertyItems;
},
/**
* Focus the window on mousedown.
*
* @param aEvent The event object
*/
focusWindow: function si_focusWindow(aEvent)
{
let win = this.styleDocument.defaultView;
win.focus();
},
/**
* Copy selected text.
*
@ -704,6 +717,7 @@ CssHtmlTree.prototype = {
// Remove bound listeners
this.styleDocument.removeEventListener("copy", this.siBoundCopy);
this.styleDocument.removeEventListener("mousedown", this.siFocusWindow);
// Nodes used in templating
delete this.root;

View File

@ -1402,6 +1402,8 @@ RuleEditor.prototype = {
}.bind(this), false);
this.element.addEventListener("mousedown", function() {
this.doc.defaultView.focus();
let editorNodes =
this.doc.querySelectorAll(".styleinspector-propertyeditor");

View File

@ -181,7 +181,6 @@ TiltVisualizer.prototype = {
if (panel) {
this.inspector = panel;
this.inspector.selection.on("new-node", this.onNewNodeFromInspector);
this.inspector.selection.on("detached", this.onNewNodeFromInspector);
this.onNewNodeFromInspector();
}
}
@ -196,7 +195,6 @@ TiltVisualizer.prototype = {
if (this.inspector) {
this.inspector.selection.off("new-node", this.onNewNodeFromInspector);
this.inspector.selection.off("detached", this.onNewNodeFromInspector);
this.inspector = null;
}
@ -217,7 +215,6 @@ TiltVisualizer.prototype = {
if (toolbox.target.tab === this._browserTab) {
this.inspector = panel;
this.inspector.selection.on("new-node", this.onNewNodeFromInspector);
this.inspector.selection.on("detached", this.onNewNodeFromInspector);
this.onNewNodeFromTilt();
}
},
@ -231,7 +228,6 @@ TiltVisualizer.prototype = {
this.inspector) {
if (this.inspector.selection) {
this.inspector.selection.off("new-node", this.onNewNodeFromInspector);
this.inspector.selection.off("detached", this.onNewNodeFromInspector);
}
this.inspector = null;
}

View File

@ -2,14 +2,21 @@
- 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/. -->
<!-- LOCALIZATION NOTE : FILE This file contains the Remove Connection strings.
- The Remote Connection window can be start by running the command:
- `devtools connect`
<!-- LOCALIZATION NOTE : FILE This file contains the Remote Connection strings.
- The Remote Connection window can reached from the "connect…" menuitem
- in the Web Developer menu.
- -->
<!ENTITY title "Connect">
<!ENTITY header "Connect to remote device">
<!ENTITY host "Host:">
<!ENTITY port "Port:">
<!ENTITY connect "Connect">
<!ENTITY connecting "Connecting…">
<!ENTITY availability "Available remote objects:">
<!ENTITY remoteProcess "remote process">
<!ENTITY connectionError "Error:">
<!ENTITY errorTimeout "Error: connection timeout.">
<!ENTITY errorRefused "Error: connection refused.">
<!ENTITY errorUnexpected "Unexpected error.">
<!ENTITY help "Firefox Developer Tools can debug remote devices (Firefox for Android and Firefox OS for example). Make sure that you have turned on the 'Debugger Server' option on the remote device. See <a target='_' href='https://developer.mozilla.org/en-US/docs/Tools/Debugger#Remote_Debugging'>documentation</a>.">

View File

@ -0,0 +1,9 @@
# 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/.
# LOCALIZATION NOTE : FILE This file contains the Remote Connection strings.
# The Remote Connection window can reached from the "connect…" menuitem
# in the Web Developer menu.
remoteProcess=Remote Process

View File

@ -186,6 +186,11 @@ globalScopeLabel=Global
# displayed inside the developer tools window and in the Developer Tools Menu.
ToolboxDebugger.label=Debugger
# LOCALIZATION NOTE (ToolboxDebugger.tooltip):
# This string is displayed in the tooltip of the tab when the debugger is
# displayed inside the developer tools window..
ToolboxDebugger.tooltip=JavaScript Debugger
# LOCALIZATION NOTE (variablesEditableNameTooltip): The text that is displayed
# in the variables list on an item with an editable name.
variablesEditableNameTooltip=Double click to edit

View File

@ -33,3 +33,10 @@ nodeMenu.tooltiptext=Node operations
inspector.label=Inspector
inspector.commandkey=I
inspector.accesskey=I
# LOCALIZATION NOTE (markupView.more.*)
# When there are too many nodes to load at once, we will offer to
# show all the nodes.
markupView.more.showing=Some nodes were hidden.
markupView.more.showAll=Show All %S Nodes
inspector.tooltip=DOM and Style Inspector

View File

@ -13,4 +13,9 @@
# LOCALIZATION NOTE (profiler.label):
# This string is displayed in the title of the tab when the profiler is
# displayed inside the developer tools window and in the Developer Tools Menu.
profiler.label=Profiler
profiler.label=Profiler
# LOCALIZATION NOTE (profiler.tooltip):
# This string is displayed in the tooltip of the tab when the profiler is
# displayed inside the developer tools window.
profiler.tooltip=Profiler

View File

@ -78,3 +78,8 @@ redo.commandkey=Z
# This string is displayed in the title of the tab when the debugger is
# displayed inside the developer tools window and in the Developer Tools Menu.
ToolboxStyleEditor.label=Style Editor
# LOCALIZATION NOTE (ToolboxStyleEditor.tooltip):
# This string is displayed in the tooltip of the tab when the debugger is
# displayed inside the developer tools window.
ToolboxStyleEditor.tooltip=CSS Stylesheets Editor

View File

@ -5,3 +5,5 @@
<!ENTITY window.title "Developer Tools">
<!ENTITY closeCmd.key "W">
<!ENTITY toolboxCloseButton.tooltip "Close Developer Tools">

View File

@ -0,0 +1,3 @@
toolboxDockButtons.bottom.tooltip=Dock to bottom of browser window
toolboxDockButtons.side.tooltip=Dock to side of browser window
toolboxDockButtons.window.tooltip=Show in separate window

View File

@ -174,6 +174,11 @@ listTabs.globalConsoleActor=*Global Console*
# as webConsoleWindowTitleAndURL before the '-'
ToolboxWebconsole.label=Web Console
# LOCALIZATION NOTE (ToolboxWebconsole.tooltip):
# This string is displayed in the tooltip of the tab when the web console is
# displayed inside the developer tools window.
ToolboxWebconsole.tooltip=Web Console
# LOCALIZATION NOTE (longStringEllipsis): The string displayed after a long
# string. This string is clickable such that the rest of the string is retrieved
# from the server.

View File

@ -41,6 +41,7 @@
locale/browser/devtools/toolbox.dtd (%chrome/browser/devtools/toolbox.dtd)
locale/browser/devtools/inspector.dtd (%chrome/browser/devtools/inspector.dtd)
locale/browser/devtools/connection-screen.dtd (%chrome/browser/devtools/connection-screen.dtd)
locale/browser/devtools/connection-screen.properties (%chrome/browser/devtools/connection-screen.properties)
locale/browser/newTab.dtd (%chrome/browser/newTab.dtd)
locale/browser/newTab.properties (%chrome/browser/newTab.properties)
locale/browser/openLocation.dtd (%chrome/browser/openLocation.dtd)

View File

@ -128,27 +128,33 @@
margin: 0 3px;
}
/* Search input */
/* Text input */
.devtools-textinput,
.devtools-searchinput {
-moz-appearance: none;
margin: 0 3px;
border: 1px solid hsla(210,8%,5%,.6);
border-radius: 2px;
background-color: transparent;
background-image: url(magnifying-glass.png), -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
background-repeat: no-repeat;
background-position: 4px center, top left, top left;
padding-top: 0;
padding-bottom: 0;
-moz-padding-start: 18px;
-moz-padding-end: 12px;
background-image: -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
padding: 3px;
box-shadow: 0 1px 1px hsla(210,8%,5%,.3) inset,
0 0 0 1px hsla(210,16%,76%,.1) inset,
0 1px 0 hsla(210,16%,76%,.15);
color: inherit;
}
.devtools-searchinput {
padding-top: 0;
padding-bottom: 0;
-moz-padding-start: 18px;
-moz-padding-end: 12px;
background-image: url(magnifying-glass.png), -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
background-position: 4px center, top left, top left;
background-repeat: no-repeat;
}
.devtools-searchinput:-moz-locale-dir(rtl) {
background-position: calc(100% - 4px) center, top left, top left;
}

View File

@ -49,6 +49,10 @@ li.container {
-moz-appearance: treetwistyopen;
}
.more-nodes {
padding-left: 16px;
}
.styleinspector-propertyeditor {
border: 1px solid #CCC;
}

View File

@ -134,14 +134,24 @@
border: 0;
}
/* Search input */
/* Text input */
.devtools-textinput,
.devtools-searchinput {
-moz-appearance: none;
margin: 0 3px;
background-color: transparent;
border: 1px solid hsla(210,8%,5%,.6);
border-radius: 20px;
background-image: -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
padding: 3px;
box-shadow: 0 1px 1px hsla(210,8%,5%,.3) inset,
0 0 0 1px hsla(210,16%,76%,.1) inset,
0 1px 0 hsla(210,16%,76%,.15);
color: inherit;
}
.devtools-searchinput {
background-image: url(magnifying-glass.png), -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
background-repeat: no-repeat;
background-position: 4px center, top left, top left;
@ -149,10 +159,6 @@
padding-bottom: 0;
-moz-padding-start: 18px;
-moz-padding-end: 12px;
box-shadow: 0 1px 1px hsla(210,8%,5%,.3) inset,
0 0 0 1px hsla(210,16%,76%,.1) inset,
0 1px 0 hsla(210,16%,76%,.15);
color: inherit;
}
.devtools-searchinput:-moz-locale-dir(rtl) {

View File

@ -52,6 +52,10 @@ li.container {
-moz-appearance: treetwistyopen;
}
.more-nodes {
padding-left: 16px;
}
.styleinspector-propertyeditor {
border: 1px solid #CCC;
}

View File

@ -132,8 +132,9 @@
-moz-box-align: center;
}
/* Search input */
/* Text input */
.devtools-textinput,
.devtools-searchinput {
-moz-appearance: none;
margin: 0 3px;
@ -141,6 +142,15 @@
box-shadow: inset 0 1px 0 hsla(211,68%,6%,.05), 0 0 0 1px hsla(210,40%,83%,.1);
border-radius: 2px;
background-color: transparent;
background-image: -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
padding: 3px;
transition-property: background-color, border-color, box-shadow;
transition-duration: 150ms;
transition-timing-function: ease;
color: inherit;
}
.devtools-searchinput {
background-image: url(magnifying-glass.png), -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
background-repeat: no-repeat;
background-position: 4px center, top left, top left;
@ -148,10 +158,6 @@
padding-bottom: 0;
-moz-padding-start: 18px;
-moz-padding-end: 12px;
transition-property: background-color, border-color, box-shadow;
transition-duration: 150ms;
transition-timing-function: ease;
color: inherit;
}
.devtools-searchinput[focused] {

View File

@ -54,6 +54,10 @@ li.container {
background-image: url("chrome://global/skin/tree/twisty-open.png");
}
.more-nodes {
padding-left: 16px;
}
.styleinspector-propertyeditor {
border: 1px solid #CCC;
}

View File

@ -254,3 +254,11 @@
fun:_ZN2js15ArgumentsObject14createExpectedEP9JSContextPNS_10StackFrameE
...
}
{
Bug 823782
Memcheck:Leak
fun:malloc
...
fun:_ZN2js6ctypes7LibraryL7DeclareEP9JSContextjPN2JS5ValueE
...
}

View File

@ -7,6 +7,7 @@
#define nsChromeRegistryChrome_h
#include "nsChromeRegistry.h"
#include "nsVoidArray.h"
namespace mozilla {
namespace dom {

View File

@ -65,6 +65,7 @@ class nsScriptLoader;
class nsSMILAnimationController;
class nsStyleSet;
class nsWindowSizes;
class nsSmallVoidArray;
namespace mozilla {
namespace css {

View File

@ -2179,7 +2179,12 @@ ParseSelectorList(nsINode* aNode,
doc->GetDocumentURI(),
0, // XXXbz get the line number!
&selectorList);
NS_ENSURE_SUCCESS(rv, rv);
if (NS_FAILED(rv)) {
// We hit this for syntax errors, which are quite common, so don't
// use NS_ENSURE_SUCCESS. (For example, jQuery has an extended set
// of selectors, but it sees if we can parse them first.)
return rv;
}
// Filter out pseudo-element selectors from selectorList
nsCSSSelectorList** slot = &selectorList;
@ -2218,7 +2223,12 @@ FindMatchingElements(nsINode* aRoot, const nsAString& aSelector, T &aList)
nsAutoPtr<nsCSSSelectorList> selectorList;
nsresult rv = ParseSelectorList(aRoot, aSelector,
getter_Transfers(selectorList));
NS_ENSURE_SUCCESS(rv, rv);
if (NS_FAILED(rv)) {
// We hit this for syntax errors, which are quite common, so don't
// use NS_ENSURE_SUCCESS. (For example, jQuery has an extended set
// of selectors, but it sees if we can parse them first.)
return rv;
}
NS_ENSURE_TRUE(selectorList, NS_OK);
NS_ASSERTION(selectorList->mSelectors,

View File

@ -6,23 +6,47 @@
#include "nsCOMArray.h"
#include "nsCOMPtr.h"
static bool ReleaseObjects(void* aElement, void*);
// This specialization is private to nsCOMArray.
// It exists solely to automatically zero-out newly created array elements.
template<>
class nsTArrayElementTraits<nsISupports*>
{
typedef nsISupports* E;
public:
// Zero out the value
static inline void Construct(E *e) {
new (static_cast<void *>(e)) E();
}
// Invoke the copy-constructor in place.
template<class A>
static inline void Construct(E *e, const A &arg) {
new (static_cast<void *>(e)) E(arg);
}
// Invoke the destructor in place.
static inline void Destruct(E *e) {
e->~E();
}
};
static void ReleaseObjects(nsTArray<nsISupports*> &aArray);
// implementations of non-trivial methods in nsCOMArray_base
// copy constructor - we can't just memcpy here, because
// we have to make sure we own our own array buffer, and that each
// object gets another AddRef()
nsCOMArray_base::nsCOMArray_base(const nsCOMArray_base& aOther)
{
// make sure we do only one allocation
mArray.SizeTo(aOther.Count());
mArray.SetCapacity(aOther.Count());
AppendObjects(aOther);
}
nsCOMArray_base::~nsCOMArray_base()
{
Clear();
Clear();
}
int32_t
nsCOMArray_base::IndexOf(nsISupports* aObject) const {
return mArray.IndexOf(aObject);
}
int32_t
@ -30,12 +54,11 @@ nsCOMArray_base::IndexOfObject(nsISupports* aObject) const {
nsCOMPtr<nsISupports> supports = do_QueryInterface(aObject);
NS_ENSURE_TRUE(supports, -1);
int32_t i, count;
uint32_t i, count;
int32_t retval = -1;
count = mArray.Count();
count = mArray.Length();
for (i = 0; i < count; ++i) {
nsCOMPtr<nsISupports> arrayItem =
do_QueryInterface(reinterpret_cast<nsISupports*>(mArray.ElementAt(i)));
nsCOMPtr<nsISupports> arrayItem = do_QueryInterface(mArray[i]);
if (arrayItem == supports) {
retval = i;
break;
@ -44,41 +67,80 @@ nsCOMArray_base::IndexOfObject(nsISupports* aObject) const {
return retval;
}
bool
nsCOMArray_base::EnumerateForwards(nsBaseArrayEnumFunc aFunc, void* aData) const
{
for (uint32_t index = 0; index < mArray.Length(); index++)
if (!(*aFunc)(mArray[index], aData))
return false;
return true;
}
bool
nsCOMArray_base::EnumerateBackwards(nsBaseArrayEnumFunc aFunc, void* aData) const
{
for (uint32_t index = mArray.Length(); index--; )
if (!(*aFunc)(mArray[index], aData))
return false;
return true;
}
int
nsCOMArray_base::nsCOMArrayComparator(const void* aElement1, const void* aElement2, void* aData)
{
nsCOMArrayComparatorContext* ctx = static_cast<nsCOMArrayComparatorContext*>(aData);
return (*ctx->mComparatorFunc)(*static_cast<nsISupports* const*>(aElement1),
*static_cast<nsISupports* const*>(aElement2),
ctx->mData);
}
void nsCOMArray_base::Sort(nsBaseArrayComparatorFunc aFunc, void* aData)
{
if (mArray.Length() > 1) {
nsCOMArrayComparatorContext ctx = {aFunc, aData};
NS_QuickSort(mArray.Elements(), mArray.Length(), sizeof(nsISupports*),
nsCOMArrayComparator, &ctx);
}
}
bool
nsCOMArray_base::InsertObjectAt(nsISupports* aObject, int32_t aIndex) {
bool result = mArray.InsertElementAt(aObject, aIndex);
if (result)
NS_IF_ADDREF(aObject);
return result;
if ((uint32_t)aIndex > mArray.Length())
return false;
if (!mArray.InsertElementAt(aIndex, aObject))
return false;
NS_IF_ADDREF(aObject);
return true;
}
bool
nsCOMArray_base::InsertObjectsAt(const nsCOMArray_base& aObjects, int32_t aIndex) {
bool result = mArray.InsertElementsAt(aObjects.mArray, aIndex);
if (result) {
// need to addref all these
int32_t count = aObjects.Count();
for (int32_t i = 0; i < count; ++i) {
NS_IF_ADDREF(aObjects.ObjectAt(i));
}
}
return result;
if ((uint32_t)aIndex > mArray.Length())
return false;
if (!mArray.InsertElementsAt(aIndex, aObjects.mArray))
return false;
// need to addref all these
int32_t count = aObjects.Count();
for (int32_t i = 0; i < count; ++i)
NS_IF_ADDREF(aObjects.ObjectAt(i));
return true;
}
bool
nsCOMArray_base::ReplaceObjectAt(nsISupports* aObject, int32_t aIndex)
{
// its ok if oldObject is null here
nsISupports *oldObject =
reinterpret_cast<nsISupports*>(mArray.SafeElementAt(aIndex));
bool result = mArray.ReplaceElementAt(aObject, aIndex);
// ReplaceElementAt could fail, such as if the array grows
// so only release the existing object if the replacement succeeded
bool result = mArray.EnsureLengthAtLeast(aIndex + 1);
if (result) {
nsISupports *oldObject = mArray[aIndex];
// Make sure to addref first, in case aObject == oldObject
NS_IF_ADDREF(aObject);
NS_IF_ADDREF(mArray[aIndex] = aObject);
NS_IF_RELEASE(oldObject);
}
return result;
@ -96,12 +158,12 @@ nsCOMArray_base::RemoveObject(nsISupports *aObject)
bool
nsCOMArray_base::RemoveObjectAt(int32_t aIndex)
{
if (uint32_t(aIndex) < uint32_t(Count())) {
nsISupports* element = ObjectAt(aIndex);
if (uint32_t(aIndex) < mArray.Length()) {
nsISupports* element = mArray[aIndex];
bool result = mArray.RemoveElementAt(aIndex);
mArray.RemoveElementAt(aIndex);
NS_IF_RELEASE(element);
return result;
return true;
}
return false;
@ -110,38 +172,31 @@ nsCOMArray_base::RemoveObjectAt(int32_t aIndex)
bool
nsCOMArray_base::RemoveObjectsAt(int32_t aIndex, int32_t aCount)
{
if (uint32_t(aIndex) + uint32_t(aCount) <= uint32_t(Count())) {
nsVoidArray elementsToDestroy(aCount);
for (int32_t i = 0; i < aCount; ++i) {
elementsToDestroy.InsertElementAt(mArray.FastElementAt(aIndex + i), i);
}
bool result = mArray.RemoveElementsAt(aIndex, aCount);
for (int32_t i = 0; i < aCount; ++i) {
nsISupports* element = static_cast<nsISupports*> (elementsToDestroy.FastElementAt(i));
NS_IF_RELEASE(element);
}
return result;
if (uint32_t(aIndex) + uint32_t(aCount) <= mArray.Length()) {
nsTArray<nsISupports*> elementsToDestroy(aCount);
elementsToDestroy.AppendElements(mArray.Elements() + aIndex, aCount);
mArray.RemoveElementsAt(aIndex, aCount);
ReleaseObjects(elementsToDestroy);
return true;
}
return false;
}
// useful for destructors
bool
ReleaseObjects(void* aElement, void*)
void
ReleaseObjects(nsTArray<nsISupports*> &aArray)
{
nsISupports* element = static_cast<nsISupports*>(aElement);
NS_IF_RELEASE(element);
return true;
for (uint32_t i = 0; i < aArray.Length(); i++)
NS_IF_RELEASE(aArray[i]);
}
void
nsCOMArray_base::Clear()
{
nsAutoVoidArray objects;
objects = mArray;
mArray.Clear();
objects.EnumerateForwards(ReleaseObjects, nullptr);
nsTArray<nsISupports*> objects;
objects.SwapElements(mArray);
ReleaseObjects(objects);
}
bool
@ -149,18 +204,24 @@ nsCOMArray_base::SetCount(int32_t aNewCount)
{
NS_ASSERTION(aNewCount >= 0,"SetCount(negative index)");
if (aNewCount < 0)
return false;
return false;
int32_t count = Count(), i;
nsAutoVoidArray objects;
if (count > aNewCount) {
objects.SetCount(count - aNewCount);
for (i = aNewCount; i < count; ++i) {
objects.ReplaceElementAt(ObjectAt(i), i - aNewCount);
}
}
bool result = mArray.SetCount(aNewCount);
objects.EnumerateForwards(ReleaseObjects, nullptr);
return result;
int32_t count = mArray.Length();
if (count > aNewCount)
RemoveObjectsAt(aNewCount, mArray.Length() - aNewCount);
return mArray.SetLength(aNewCount);
}
size_t
nsCOMArray_base::SizeOfExcludingThis(
nsBaseArraySizeOfElementIncludingThisFunc aSizeOfElementIncludingThis,
nsMallocSizeOfFun aMallocSizeOf, void* aData) const
{
size_t n = mArray.SizeOfExcludingThis(aMallocSizeOf);
if (aSizeOfElementIncludingThis)
for (uint32_t index = 0; index < mArray.Length(); index++)
n += aSizeOfElementIncludingThis(mArray[index], aMallocSizeOf, aData);
return n;
}

View File

@ -9,7 +9,7 @@
#include "mozilla/Attributes.h"
#include "nsCycleCollectionNoteChild.h"
#include "nsVoidArray.h"
#include "nsTArray.h"
#include "nsISupports.h"
// See below for the definition of nsCOMArray<T>
@ -25,28 +25,28 @@ protected:
nsCOMArray_base(const nsCOMArray_base& other);
~nsCOMArray_base();
int32_t IndexOf(nsISupports* aObject) const {
return mArray.IndexOf(aObject);
}
int32_t IndexOf(nsISupports* aObject) const;
int32_t IndexOfObject(nsISupports* aObject) const;
bool EnumerateForwards(nsVoidArrayEnumFunc aFunc, void* aData) {
return mArray.EnumerateForwards(aFunc, aData);
}
typedef bool (* nsBaseArrayEnumFunc)
(void* aElement, void *aData);
bool EnumerateBackwards(nsVoidArrayEnumFunc aFunc, void* aData) {
return mArray.EnumerateBackwards(aFunc, aData);
}
// enumerate through the array with a callback.
bool EnumerateForwards(nsBaseArrayEnumFunc aFunc, void* aData) const;
void Sort(nsVoidArrayComparatorFunc aFunc, void* aData) {
mArray.Sort(aFunc, aData);
}
// any method which is not a direct forward to mArray should
// avoid inline bodies, so that the compiler doesn't inline them
// all over the place
void Clear();
bool EnumerateBackwards(nsBaseArrayEnumFunc aFunc, void* aData) const;
typedef int (* nsBaseArrayComparatorFunc)
(nsISupports* aElement1, nsISupports* aElement2, void* aData);
struct nsCOMArrayComparatorContext {
nsBaseArrayComparatorFunc mComparatorFunc;
void* mData;
};
static int nsCOMArrayComparator(const void* aElement1, const void* aElement2, void* aData);
void Sort(nsBaseArrayComparatorFunc aFunc, void* aData);
bool InsertObjectAt(nsISupports* aObject, int32_t aIndex);
bool InsertObjectsAt(const nsCOMArray_base& aObjects, int32_t aIndex);
bool ReplaceObjectAt(nsISupports* aObject, int32_t aIndex);
@ -57,58 +57,63 @@ protected:
return InsertObjectsAt(aObjects, Count());
}
bool RemoveObject(nsISupports *aObject);
bool RemoveObjectAt(int32_t aIndex);
bool RemoveObjectsAt(int32_t aIndex, int32_t aCount);
public:
// override nsVoidArray stuff so that they can be accessed by
// consumers of nsCOMArray
// elements in the array (including null elements!)
int32_t Count() const {
return mArray.Count();
return mArray.Length();
}
// If the array grows, the newly created entries will all be null;
// if the array shrinks, the excess entries will all be released.
bool SetCount(int32_t aNewCount);
// remove all elements in the array, and call NS_RELEASE on each one
void Clear();
nsISupports* ObjectAt(int32_t aIndex) const {
return static_cast<nsISupports*>(mArray.FastElementAt(aIndex));
return mArray[aIndex];
}
nsISupports* SafeObjectAt(int32_t aIndex) const {
return static_cast<nsISupports*>(mArray.SafeElementAt(aIndex));
return mArray.SafeElementAt(aIndex, nullptr);
}
nsISupports* operator[](int32_t aIndex) const {
return ObjectAt(aIndex);
}
// remove an element at a specific position, shrinking the array
// as necessary
bool RemoveObjectAt(int32_t aIndex);
// remove a range of elements at a specific position, shrinking the array
// as necessary
bool RemoveObjectsAt(int32_t aIndex, int32_t aCount);
// Ensures there is enough space to store a total of aCapacity objects.
// This method never deletes any objects.
bool SetCapacity(uint32_t aCapacity) {
return aCapacity > 0 ? mArray.SizeTo(static_cast<int32_t>(aCapacity))
: true;
return mArray.SetCapacity(aCapacity);
}
typedef size_t (* nsBaseArraySizeOfElementIncludingThisFunc)
(nsISupports* aElement, nsMallocSizeOfFun aMallocSizeOf, void *aData);
// Measures the size of the array's element storage, and if
// |aSizeOfElement| is non-NULL, measures the size of things pointed to by
// elements.
size_t SizeOfExcludingThis(
nsVoidArraySizeOfElementIncludingThisFunc aSizeOfElementIncludingThis,
nsMallocSizeOfFun aMallocSizeOf, void* aData = NULL) const {
return mArray.SizeOfExcludingThis(aSizeOfElementIncludingThis,
aMallocSizeOf, aData);
}
nsBaseArraySizeOfElementIncludingThisFunc aSizeOfElementIncludingThis,
nsMallocSizeOfFun aMallocSizeOf, void* aData = NULL) const;
private:
// the actual storage
nsVoidArray mArray;
nsTArray<nsISupports*> mArray;
// don't implement these, defaults will muck with refcounts!
nsCOMArray_base& operator=(const nsCOMArray_base& other) MOZ_DELETE;
// needs to call Clear() which is protected
friend void ImplCycleCollectionUnlink(nsCOMArray_base& aField);
};
inline void
@ -211,19 +216,6 @@ class nsCOMArray : public nsCOMArray_base
return nsCOMArray_base::ReplaceObjectAt(static_cast<nsISupports*>(aObject), aIndex);
}
// override nsVoidArray stuff so that they can be accessed by
// other methods
// elements in the array (including null elements!)
int32_t Count() const {
return nsCOMArray_base::Count();
}
// remove all elements in the array, and call NS_RELEASE on each one
void Clear() {
nsCOMArray_base::Clear();
}
// Enumerator callback function. Return false to stop
// Here's a more readable form:
// bool enumerate(T* aElement, void* aData)
@ -232,12 +224,12 @@ class nsCOMArray : public nsCOMArray_base
// enumerate through the array with a callback.
bool EnumerateForwards(nsCOMArrayEnumFunc aFunc, void* aData) {
return nsCOMArray_base::EnumerateForwards(nsVoidArrayEnumFunc(aFunc),
return nsCOMArray_base::EnumerateForwards(nsBaseArrayEnumFunc(aFunc),
aData);
}
bool EnumerateBackwards(nsCOMArrayEnumFunc aFunc, void* aData) {
return nsCOMArray_base::EnumerateBackwards(nsVoidArrayEnumFunc(aFunc),
return nsCOMArray_base::EnumerateBackwards(nsBaseArrayEnumFunc(aFunc),
aData);
}
@ -245,7 +237,7 @@ class nsCOMArray : public nsCOMArray_base
(T* aElement1, T* aElement2, void* aData);
void Sort(nsCOMArrayComparatorFunc aFunc, void* aData) {
nsCOMArray_base::Sort(nsVoidArrayComparatorFunc(aFunc), aData);
nsCOMArray_base::Sort(nsBaseArrayComparatorFunc(aFunc), aData);
}
// append an object, growing the array as necessary
@ -265,18 +257,6 @@ class nsCOMArray : public nsCOMArray_base
return nsCOMArray_base::RemoveObject(static_cast<nsISupports*>(aObject));
}
// remove an element at a specific position, shrinking the array
// as necessary
bool RemoveObjectAt(int32_t aIndex) {
return nsCOMArray_base::RemoveObjectAt(aIndex);
}
// remove a range of elements at a specific position, shrinking the array
// as necessary
bool RemoveObjectsAt(int32_t aIndex, int32_t aCount) {
return nsCOMArray_base::RemoveObjectsAt(aIndex, aCount);
}
// Each element in an nsCOMArray<T> is actually a T*, so this function is
// "IncludingThis" rather than "ExcludingThis" because it needs to measure
// the memory taken by the T itself as well as anything it points to.
@ -287,7 +267,7 @@ class nsCOMArray : public nsCOMArray_base
nsCOMArraySizeOfElementIncludingThisFunc aSizeOfElementIncludingThis,
nsMallocSizeOfFun aMallocSizeOf, void *aData = NULL) const {
return nsCOMArray_base::SizeOfExcludingThis(
nsVoidArraySizeOfElementIncludingThisFunc(aSizeOfElementIncludingThis),
nsBaseArraySizeOfElementIncludingThisFunc(aSizeOfElementIncludingThis),
aMallocSizeOf, aData);
}