mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 23:31:56 +00:00
Merge mozilla-central to autoland
This commit is contained in:
commit
49921c11be
@ -97,8 +97,8 @@
|
||||
|
||||
is(anode.attributes.length, attrs.length, 'correct number of attributes');
|
||||
for (var i = 0; i < attrs.length; i++) {
|
||||
is(anode.attributes[i], attrs[i],
|
||||
`${attrs[i]} attribute is expected at ${i}th index`);
|
||||
ok(attrs.indexOf(anode.attributes[i]) >= 0,
|
||||
`${anode.attributes[i]} attribute is expected and found`);
|
||||
}
|
||||
|
||||
finish();
|
||||
|
@ -3,6 +3,8 @@ support-files =
|
||||
head.js
|
||||
[browser_appmenu_reflows.js]
|
||||
[browser_startup.js]
|
||||
[browser_startup_content.js]
|
||||
skip-if = !e10s
|
||||
[browser_startup_images.js]
|
||||
skip-if = !debug
|
||||
[browser_tabclose_grow_reflows.js]
|
||||
|
@ -0,0 +1,81 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* This test records which services, JS components and JS modules are loaded
|
||||
* when creating a new content process.
|
||||
*
|
||||
* If you made changes that cause this test to fail, it's likely because you
|
||||
* are loading more JS code during content process startup.
|
||||
*
|
||||
* If your code isn't strictly required to show a page, consider loading it
|
||||
* lazily. If you can't, consider delaying its load until after we have started
|
||||
* handling user events.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const blacklist = {
|
||||
components: new Set([
|
||||
"PushComponents.js",
|
||||
"TelemetryStartup.js",
|
||||
]),
|
||||
modules: new Set([
|
||||
"resource:///modules/ContentWebRTC.jsm",
|
||||
"resource://gre/modules/InlineSpellChecker.jsm",
|
||||
"resource://gre/modules/InlineSpellCheckerContent.jsm",
|
||||
"resource://gre/modules/Promise.jsm",
|
||||
"resource://gre/modules/Task.jsm",
|
||||
"resource://gre/modules/debug.js",
|
||||
"resource://gre/modules/osfile.jsm",
|
||||
]),
|
||||
services: new Set([
|
||||
"@mozilla.org/base/telemetry-startup;1",
|
||||
"@mozilla.org/push/Service;1",
|
||||
])
|
||||
};
|
||||
|
||||
add_task(async function() {
|
||||
SimpleTest.requestCompleteLog();
|
||||
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab({gBrowser,
|
||||
forceNewProcess: true});
|
||||
|
||||
let mm = gBrowser.selectedBrowser.messageManager;
|
||||
let promise = BrowserTestUtils.waitForMessage(mm, "Test:LoadedScripts");
|
||||
|
||||
// Load a custom frame script to avoid using ContentTask which loads Task.jsm
|
||||
mm.loadFrameScript("data:text/javascript,(" + function() {
|
||||
/* eslint-env mozilla/frame-script */
|
||||
const {classes: Cc, interfaces: Ci, manager: Cm} = Components;
|
||||
Cm.QueryInterface(Ci.nsIServiceManager);
|
||||
|
||||
let loader = Cc["@mozilla.org/moz/jsloader;1"].getService(Ci.xpcIJSModuleLoader);
|
||||
sendAsyncMessage("Test:LoadedScripts", {
|
||||
/* Keep only the file name for components, as the path is an absolute file
|
||||
URL rather than a resource:// URL like for modules. */
|
||||
components: loader.loadedComponents().map(f => f.replace(/.*\//, "")),
|
||||
modules: loader.loadedModules(),
|
||||
services: Object.keys(Cc).filter(c => {
|
||||
try {
|
||||
Cm.isServiceInstantiatedByContractID(c, Ci.nsISupports);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
});
|
||||
} + ")()", false);
|
||||
|
||||
let loadedList = await promise;
|
||||
for (let scriptType in blacklist) {
|
||||
info(scriptType);
|
||||
for (let file of blacklist[scriptType]) {
|
||||
ok(!loadedList[scriptType].includes(file), `${file} is not allowed`);
|
||||
}
|
||||
for (let file of loadedList[scriptType]) {
|
||||
info(file);
|
||||
}
|
||||
}
|
||||
|
||||
await BrowserTestUtils.removeTab(tab);
|
||||
});
|
@ -421,6 +421,9 @@ class ViewPopup extends BasePopup {
|
||||
// be swapped with the browser in the real panel when it's ready.
|
||||
let panel = document.createElement("panel");
|
||||
panel.setAttribute("type", "arrow");
|
||||
if (extension.remote) {
|
||||
panel.setAttribute("remote", "true");
|
||||
}
|
||||
document.getElementById("mainPopupSet").appendChild(panel);
|
||||
|
||||
super(extension, panel, popupURL, browserStyle, fixedWidth, blockParser);
|
||||
|
@ -12,15 +12,15 @@ this.omnibox = class extends ExtensionAPI {
|
||||
onInputChanged: new EventManager(context, "omnibox.onInputChanged", fire => {
|
||||
let listener = (text, id) => {
|
||||
fire.asyncWithoutClone(text, suggestions => {
|
||||
context.childManager.callParentFunctionNoReturn("omnibox_internal.addSuggestions", [
|
||||
context.childManager.callParentFunctionNoReturn("omnibox.addSuggestions", [
|
||||
id,
|
||||
suggestions,
|
||||
]);
|
||||
});
|
||||
};
|
||||
context.childManager.getParentEvent("omnibox_internal.onInputChanged").addListener(listener);
|
||||
context.childManager.getParentEvent("omnibox.onInputChanged").addListener(listener);
|
||||
return () => {
|
||||
context.childManager.getParentEvent("omnibox_internal.onInputChanged").removeListener(listener);
|
||||
context.childManager.getParentEvent("omnibox.onInputChanged").removeListener(listener);
|
||||
};
|
||||
}).api(),
|
||||
},
|
||||
|
@ -69,9 +69,8 @@ this.omnibox = class extends ExtensionAPI {
|
||||
extension.off(ExtensionSearchHandler.MSG_INPUT_ENTERED, listener);
|
||||
};
|
||||
}).api(),
|
||||
},
|
||||
|
||||
omnibox_internal: {
|
||||
// Internal APIs.
|
||||
addSuggestions: (id, suggestions) => {
|
||||
try {
|
||||
ExtensionSearchHandler.addSuggestions(this.keyword, id, suggestions);
|
||||
@ -81,7 +80,7 @@ this.omnibox = class extends ExtensionAPI {
|
||||
}
|
||||
},
|
||||
|
||||
onInputChanged: new EventManager(context, "omnibox_internal.onInputChanged", fire => {
|
||||
onInputChanged: new EventManager(context, "omnibox.onInputChanged", fire => {
|
||||
let listener = (eventName, text, id) => {
|
||||
fire.sync(text, id);
|
||||
};
|
||||
|
@ -197,52 +197,5 @@
|
||||
"parameters": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"namespace": "omnibox_internal",
|
||||
"description": "The internal namespace used by the omnibox API.",
|
||||
"defaultContexts": ["addon_parent_only"],
|
||||
"functions": [
|
||||
{
|
||||
"name": "addSuggestions",
|
||||
"type": "function",
|
||||
"async": "callback",
|
||||
"description": "Internal function used by omnibox.onInputChanged for adding search suggestions",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "integer",
|
||||
"description": "The ID of the callback received by onInputChangedInternal"
|
||||
},
|
||||
{
|
||||
"name": "suggestResults",
|
||||
"type": "array",
|
||||
"description": "Array of suggest results",
|
||||
"items": {
|
||||
"$ref": "omnibox.SuggestResult"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "callback",
|
||||
"optional": true,
|
||||
"parameters": []
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"name": "onInputChanged",
|
||||
"type": "function",
|
||||
"description": "Identical to omnibox.onInputChanged except no 'suggest' callback is provided.",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "text"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
|
@ -887,6 +887,7 @@ rpc/types.h
|
||||
sane/sane.h
|
||||
sane/sanei.h
|
||||
sane/saneopts.h
|
||||
sanitizer/asan_interface.h
|
||||
sched.h
|
||||
Scrap.h
|
||||
Screen.h
|
||||
|
@ -96,7 +96,7 @@ module.exports = createClass({
|
||||
onChange: this.onShowGridLineNumbersCheckboxClick,
|
||||
}
|
||||
),
|
||||
getStr("layout.displayNumbersOnLines")
|
||||
getStr("layout.displayNumbersOnLines2")
|
||||
)
|
||||
),
|
||||
dom.li(
|
||||
|
@ -49,6 +49,7 @@ function* testRuleView(ruleView, nodeFront) {
|
||||
"font-family");
|
||||
|
||||
// And verify that the tooltip gets shown on this property
|
||||
valueSpan.scrollIntoView(true);
|
||||
let previewTooltip = yield assertShowPreviewTooltip(ruleView, valueSpan);
|
||||
|
||||
let images = panel.getElementsByTagName("img");
|
||||
@ -70,6 +71,7 @@ function* testComputedView(computedView, nodeFront) {
|
||||
let panel = tooltip.panel;
|
||||
let {valueSpan} = getComputedViewProperty(computedView, "font-family");
|
||||
|
||||
valueSpan.scrollIntoView(true);
|
||||
let previewTooltip = yield assertShowPreviewTooltip(computedView, valueSpan);
|
||||
|
||||
let images = panel.getElementsByTagName("img");
|
||||
@ -99,6 +101,7 @@ function* testExpandedComputedViewProperty(computedView, nodeFront) {
|
||||
let tooltip = computedView.tooltips.getTooltip("previewTooltip");
|
||||
let panel = tooltip.panel;
|
||||
|
||||
valueSpan.scrollIntoView(true);
|
||||
let previewTooltip = yield assertShowPreviewTooltip(computedView, valueSpan);
|
||||
|
||||
let images = panel.getElementsByTagName("img");
|
||||
|
@ -710,7 +710,7 @@ function* assertShowPreviewTooltip(view, target) {
|
||||
|
||||
let name = "previewTooltip";
|
||||
ok(view.tooltips._instances.has(name),
|
||||
`Tooltip '${name}' has been instanciated`);
|
||||
`Tooltip '${name}' has been instantiated`);
|
||||
let tooltip = view.tooltips.getTooltip(name);
|
||||
|
||||
if (!tooltip.isVisible()) {
|
||||
|
@ -14,9 +14,9 @@ layout.cannotShowGridOutline.title=The selected grid’s outline cannot effectiv
|
||||
# option in the CSS Grid pane.
|
||||
layout.displayGridAreas=Display grid areas
|
||||
|
||||
# LOCALIZATION NOTE (layout.displayNumbersOnLines): Label of the display numbers on lines
|
||||
# LOCALIZATION NOTE (layout.displayNumbersOnLines2): Label of the display numbers on lines
|
||||
# setting option in the CSS Grid pane.
|
||||
layout.displayNumbersOnLines=Display numbers on lines
|
||||
layout.displayNumbersOnLines2=Display line numbers
|
||||
|
||||
# LOCALIZATION NOTE (layout.extendGridLinesInfinitely): Label of the extend grid lines
|
||||
# infinitely setting option in the CSS Grid pane.
|
||||
|
@ -487,10 +487,8 @@ CustomElementRegistry::UpgradeCandidates(JSContext* aCx,
|
||||
}
|
||||
|
||||
nsAutoPtr<nsTArray<nsWeakPtr>> candidates;
|
||||
mCandidatesMap.RemoveAndForget(aKey, candidates);
|
||||
if (candidates) {
|
||||
|
||||
|
||||
if (mCandidatesMap.Remove(aKey, &candidates)) {
|
||||
MOZ_ASSERT(candidates);
|
||||
CustomElementReactionsStack* reactionsStack =
|
||||
docGroup->CustomElementReactionsStack();
|
||||
for (size_t i = 0; i < candidates->Length(); ++i) {
|
||||
|
@ -27,12 +27,13 @@ enum class FlushType : uint8_t {
|
||||
notifications. */
|
||||
Style = 3, /* As above, plus flush style reresolution */
|
||||
Frames = Style,
|
||||
InterruptibleLayout = 4, /* As above, plus flush reflow,
|
||||
EnsurePresShellInitAndFrames = 4, /* As above, plus ensure the pres shell is alive */
|
||||
InterruptibleLayout = 5, /* As above, plus flush reflow,
|
||||
but allow it to be interrupted (so
|
||||
an incomplete layout may result) */
|
||||
Layout = 5, /* As above, but layout must run to
|
||||
Layout = 6, /* As above, but layout must run to
|
||||
completion */
|
||||
Display = 6, /* As above, plus flush painting */
|
||||
Display = 7, /* As above, plus flush painting */
|
||||
|
||||
Count
|
||||
};
|
||||
|
@ -302,6 +302,7 @@ bool nsContentUtils::sSkipCursorMoveForSameValueSet = false;
|
||||
bool nsContentUtils::sRequestIdleCallbackEnabled = false;
|
||||
bool nsContentUtils::sLowerNetworkPriority = false;
|
||||
bool nsContentUtils::sShowInputPlaceholderOnFocus = true;
|
||||
bool nsContentUtils::sAutoFocusEnabled = true;
|
||||
#ifndef RELEASE_OR_BETA
|
||||
bool nsContentUtils::sBypassCSSOMOriginCheck = false;
|
||||
#endif
|
||||
@ -764,6 +765,9 @@ nsContentUtils::Init()
|
||||
Preferences::AddBoolVarCache(&sShowInputPlaceholderOnFocus,
|
||||
"dom.placeholder.show_on_focus", true);
|
||||
|
||||
Preferences::AddBoolVarCache(&sAutoFocusEnabled,
|
||||
"browser.autofocus", true);
|
||||
|
||||
Preferences::AddBoolVarCache(&sIsBytecodeCacheEnabled,
|
||||
"dom.script_loader.bytecode_cache.enabled", false);
|
||||
|
||||
|
@ -3059,6 +3059,10 @@ public:
|
||||
// when they have focus.
|
||||
static bool ShowInputPlaceholderOnFocus() { return sShowInputPlaceholderOnFocus; }
|
||||
|
||||
// Check pref "browser.autofocus" to see if we want to enable autofocusing elements
|
||||
// when the page requests it.
|
||||
static bool AutoFocusEnabled() { return sAutoFocusEnabled; }
|
||||
|
||||
// Check pref "dom.script_loader.bytecode_cache.enabled" to see
|
||||
// if we want to cache JS bytecode on the cache entry.
|
||||
static bool IsBytecodeCacheEnabled() { return sIsBytecodeCacheEnabled; }
|
||||
@ -3219,6 +3223,7 @@ private:
|
||||
static bool sRequestIdleCallbackEnabled;
|
||||
static bool sLowerNetworkPriority;
|
||||
static bool sShowInputPlaceholderOnFocus;
|
||||
static bool sAutoFocusEnabled;
|
||||
#ifndef RELEASE_OR_BETA
|
||||
static bool sBypassCSSOMOriginCheck;
|
||||
#endif
|
||||
|
@ -1567,9 +1567,10 @@ nsFocusManager::CheckIfFocusable(nsIContent* aContent, uint32_t aFlags)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Make sure that our frames are up to date
|
||||
// Make sure that our frames are up to date while ensuring the presshell is
|
||||
// also initialized in case we come from an autofocus event.
|
||||
mEventHandlingNeedsFlush = false;
|
||||
doc->FlushPendingNotifications(FlushType::Frames);
|
||||
doc->FlushPendingNotifications(FlushType::EnsurePresShellInitAndFrames);
|
||||
|
||||
nsIPresShell *shell = doc->GetShell();
|
||||
if (!shell)
|
||||
|
@ -527,10 +527,12 @@ public:
|
||||
* Determines if an event attribute name (such as onclick) is valid for
|
||||
* a given element type.
|
||||
* @note calls nsContentUtils::IsEventAttributeName with right flag
|
||||
* @note overridden by subclasses as needed
|
||||
* @note *Internal is overridden by subclasses as needed
|
||||
* @param aName the event name to look up
|
||||
*/
|
||||
virtual bool IsEventAttributeName(nsIAtom* aName)
|
||||
bool IsEventAttributeName(nsIAtom* aName);
|
||||
|
||||
virtual bool IsEventAttributeNameInternal(nsIAtom* aName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
||||
inline bool
|
||||
@ -94,6 +95,17 @@ nsIContent::GetFlattenedTreeParent() const
|
||||
return (parent && parent->IsContent()) ? parent->AsContent() : nullptr;
|
||||
}
|
||||
|
||||
inline bool
|
||||
nsIContent::IsEventAttributeName(nsIAtom* aName)
|
||||
{
|
||||
const char16_t* name = aName->GetUTF16String();
|
||||
if (name[0] != 'o' || name[1] != 'n') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return IsEventAttributeNameInternal(aName);
|
||||
}
|
||||
|
||||
inline nsINode*
|
||||
nsINode::GetFlattenedTreeParentNodeForStyle() const
|
||||
{
|
||||
|
@ -230,10 +230,10 @@ nsMappedAttributes::Equals(const nsMappedAttributes* aOther) const
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
PLDHashNumber
|
||||
nsMappedAttributes::HashValue() const
|
||||
{
|
||||
uint32_t hash = HashGeneric(mRuleMapper);
|
||||
PLDHashNumber hash = HashGeneric(mRuleMapper);
|
||||
|
||||
uint32_t i;
|
||||
for (i = 0; i < mAttrCount; ++i) {
|
||||
|
@ -45,7 +45,7 @@ public:
|
||||
}
|
||||
|
||||
bool Equals(const nsMappedAttributes* aAttributes) const;
|
||||
uint32_t HashValue() const;
|
||||
PLDHashNumber HashValue() const;
|
||||
|
||||
void DropStyleSheetReference()
|
||||
{
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "nsIDOMComment.h"
|
||||
#include "nsIDOMDocumentType.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIContentInlines.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDocumentEncoder.h"
|
||||
#include "nsIParserService.h"
|
||||
|
@ -49,7 +49,7 @@ struct MOZ_STACK_CLASS WebIDLNameTableKey
|
||||
const char* mLatin1String;
|
||||
const char16_t* mTwoBytesString;
|
||||
size_t mLength;
|
||||
uint32_t mHash;
|
||||
PLDHashNumber mHash;
|
||||
};
|
||||
|
||||
struct WebIDLNameTableEntry : public PLDHashEntryHdr
|
||||
|
@ -2085,10 +2085,7 @@ Console::StopTimer(JSContext* aCx, const JS::Value& aName,
|
||||
aTimerLabel = key;
|
||||
|
||||
DOMHighResTimeStamp value = 0;
|
||||
if (auto entry = mTimerRegistry.Lookup(key)) {
|
||||
value = entry.Data();
|
||||
entry.Remove();
|
||||
} else {
|
||||
if (!mTimerRegistry.Remove(key, &value)) {
|
||||
NS_WARNING("mTimerRegistry entry not found");
|
||||
return eTimerDoesntExist;
|
||||
}
|
||||
|
@ -33,9 +33,7 @@
|
||||
|
||||
#include "EventListenerService.h"
|
||||
#include "GeckoProfiler.h"
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
#include "ProfilerMarkerPayload.h"
|
||||
#endif
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsContentUtils.h"
|
||||
@ -1288,7 +1286,6 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
if (profiler_is_active()) {
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
// Add a profiler label and a profiler marker for the actual
|
||||
// dispatch of the event.
|
||||
// This is a very hot code path, so we need to make sure not to
|
||||
@ -1310,7 +1307,6 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
|
||||
"DOMEvent",
|
||||
MakeUnique<DOMEventMarkerPayload>(typeStr, phase,
|
||||
startTime, endTime));
|
||||
#endif
|
||||
} else {
|
||||
rv = HandleEventSubType(listener, *aDOMEvent, aCurrentTarget);
|
||||
}
|
||||
|
@ -422,7 +422,7 @@ HTMLBodyElement::GetAssociatedEditor()
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLBodyElement::IsEventAttributeName(nsIAtom *aName)
|
||||
HTMLBodyElement::IsEventAttributeNameInternal(nsIAtom *aName)
|
||||
{
|
||||
return nsContentUtils::IsEventAttributeName(aName,
|
||||
EventNameType_HTML |
|
||||
|
@ -109,7 +109,7 @@ public:
|
||||
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
|
||||
bool aPreallocateChildren) const override;
|
||||
|
||||
virtual bool IsEventAttributeName(nsIAtom* aName) override;
|
||||
virtual bool IsEventAttributeNameInternal(nsIAtom* aName) override;
|
||||
|
||||
|
||||
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
|
@ -337,7 +337,7 @@ HTMLFrameSetElement::ParseRowCol(const nsAString & aValue,
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLFrameSetElement::IsEventAttributeName(nsIAtom *aName)
|
||||
HTMLFrameSetElement::IsEventAttributeNameInternal(nsIAtom *aName)
|
||||
{
|
||||
return nsContentUtils::IsEventAttributeName(aName,
|
||||
EventNameType_HTML |
|
||||
|
@ -82,7 +82,7 @@ public:
|
||||
SetHTMLAttr(nsGkAtoms::rows, aRows, aError);
|
||||
}
|
||||
|
||||
virtual bool IsEventAttributeName(nsIAtom *aName) override;
|
||||
virtual bool IsEventAttributeNameInternal(nsIAtom *aName) override;
|
||||
|
||||
// Event listener stuff; we need to declare only the ones we need to
|
||||
// forward to window that don't come from nsIDOMHTMLFrameSetElement.
|
||||
|
@ -7005,10 +7005,10 @@ HTMLMediaElement::DispatchEncrypted(const nsTArray<uint8_t>& aInitData,
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLMediaElement::IsEventAttributeName(nsIAtom* aName)
|
||||
HTMLMediaElement::IsEventAttributeNameInternal(nsIAtom* aName)
|
||||
{
|
||||
return aName == nsGkAtoms::onencrypted ||
|
||||
nsGenericHTMLElement::IsEventAttributeName(aName);
|
||||
nsGenericHTMLElement::IsEventAttributeNameInternal(aName);
|
||||
}
|
||||
|
||||
already_AddRefed<nsIPrincipal>
|
||||
|
@ -653,7 +653,7 @@ public:
|
||||
void DispatchEncrypted(const nsTArray<uint8_t>& aInitData,
|
||||
const nsAString& aInitDataType) override;
|
||||
|
||||
bool IsEventAttributeName(nsIAtom* aName) override;
|
||||
bool IsEventAttributeNameInternal(nsIAtom* aName) override;
|
||||
|
||||
// Returns the principal of the "top level" document; the origin displayed
|
||||
// in the URL bar of the browser window.
|
||||
|
@ -1910,7 +1910,7 @@ nsGenericHTMLFormElement::BindToTree(nsIDocument* aDocument,
|
||||
// the document should not be already loaded and the "browser.autofocus"
|
||||
// preference should be 'true'.
|
||||
if (IsAutofocusable() && HasAttr(kNameSpaceID_None, nsGkAtoms::autofocus) &&
|
||||
Preferences::GetBool("browser.autofocus", true)) {
|
||||
nsContentUtils::AutoFocusEnabled()) {
|
||||
nsCOMPtr<nsIRunnable> event = new nsAutoFocusEvent(this);
|
||||
rv = NS_DispatchToCurrentThread(event);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@ -2925,7 +2925,7 @@ nsGenericHTMLElement::GetWidthHeightForImage(RefPtr<imgRequestProxy>& aImageRequ
|
||||
}
|
||||
|
||||
bool
|
||||
nsGenericHTMLElement::IsEventAttributeName(nsIAtom *aName)
|
||||
nsGenericHTMLElement::IsEventAttributeNameInternal(nsIAtom *aName)
|
||||
{
|
||||
return nsContentUtils::IsEventAttributeName(aName, EventNameType_HTML);
|
||||
}
|
||||
|
@ -201,7 +201,7 @@ public:
|
||||
* @param aName the attribute
|
||||
* @return whether the name is an event handler name
|
||||
*/
|
||||
virtual bool IsEventAttributeName(nsIAtom* aName) override;
|
||||
virtual bool IsEventAttributeNameInternal(nsIAtom* aName) override;
|
||||
|
||||
#define EVENT(name_, id_, type_, struct_) /* nothing; handled by nsINode */
|
||||
// The using nsINode::Get/SetOn* are to avoid warnings about shadowing the XPCOM
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include "nsIContentViewer.h"
|
||||
#include "mozilla/dom/NodeInfo.h"
|
||||
#include "mozilla/dom/ScriptLoader.h"
|
||||
#include "nsToken.h"
|
||||
#include "nsIAppShell.h"
|
||||
#include "nsCRT.h"
|
||||
#include "prtime.h"
|
||||
@ -1068,7 +1067,7 @@ HTMLContentSink::FlushPendingNotifications(FlushType aType)
|
||||
FlushTags();
|
||||
}
|
||||
}
|
||||
if (aType >= FlushType::InterruptibleLayout) {
|
||||
if (aType >= FlushType::EnsurePresShellInitAndFrames) {
|
||||
// Make sure that layout has started so that the reflow flush
|
||||
// will actually happen.
|
||||
StartLayout(true);
|
||||
|
@ -16,7 +16,6 @@ support-files =
|
||||
[browser_forgetThisSite.js]
|
||||
[browser_permissionsPromptAllow.js]
|
||||
[browser_permissionsPromptDeny.js]
|
||||
skip-if = os == 'mac' # bug 1324163
|
||||
[browser_permissionsPromptWorker.js]
|
||||
[browser_perwindow_privateBrowsing.js]
|
||||
[browser_bug839193.js]
|
||||
|
@ -7,30 +7,39 @@ const testPageURL = "http://mochi.test:8888/browser/" +
|
||||
"dom/indexedDB/test/browser_permissionsPrompt.html";
|
||||
const notificationID = "indexedDB-permissions-prompt";
|
||||
|
||||
function promiseMessage(aMessage, browser) {
|
||||
return ContentTask.spawn(browser.selectedBrowser, aMessage, async function(aMessage) {
|
||||
await new Promise((resolve, reject) => {
|
||||
content.addEventListener("message", function(event) {
|
||||
is(event.data, aMessage, "received " + aMessage);
|
||||
if (event.data == aMessage)
|
||||
resolve();
|
||||
else
|
||||
reject();
|
||||
}, {once: true});
|
||||
function waitForMessage(aMessage, browser) {
|
||||
return new Promise((resolve, reject) => {
|
||||
/* eslint-disable no-undef */
|
||||
function contentScript() {
|
||||
addEventListener("message", function(event) {
|
||||
sendAsyncMessage("testLocal:exception",
|
||||
{exception: event.data});
|
||||
}, {once: true}, true);
|
||||
}
|
||||
/* eslint-enable no-undef */
|
||||
|
||||
let script = "data:,(" + contentScript.toString() + ")();";
|
||||
|
||||
let mm = browser.selectedBrowser.messageManager;
|
||||
|
||||
mm.addMessageListener("testLocal:exception", function listener(msg) {
|
||||
mm.removeMessageListener("testLocal:exception", listener);
|
||||
mm.removeDelayedFrameScript(script);
|
||||
is(msg.data.exception, aMessage, "received " + aMessage);
|
||||
if (msg.data.exception == aMessage) {
|
||||
resolve();
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
});
|
||||
|
||||
mm.loadFrameScript(script, true);
|
||||
});
|
||||
}
|
||||
|
||||
add_task(async function test1() {
|
||||
removePermission(testPageURL, "indexedDB");
|
||||
|
||||
info("creating tab");
|
||||
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
|
||||
|
||||
info("loading test page: " + testPageURL);
|
||||
gBrowser.selectedBrowser.loadURI(testPageURL);
|
||||
await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
|
||||
|
||||
registerPopupEventHandler("popupshowing", function() {
|
||||
ok(true, "prompt showing");
|
||||
});
|
||||
@ -42,7 +51,12 @@ add_task(async function test1() {
|
||||
ok(true, "prompt hidden");
|
||||
});
|
||||
|
||||
await promiseMessage("InvalidStateError", gBrowser);
|
||||
info("creating tab");
|
||||
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
|
||||
|
||||
info("loading test page: " + testPageURL);
|
||||
gBrowser.selectedBrowser.loadURI(testPageURL);
|
||||
await waitForMessage("InvalidStateError", gBrowser);
|
||||
|
||||
is(getPermission(testPageURL, "indexedDB"),
|
||||
Components.interfaces.nsIPermissionManager.DENY_ACTION,
|
||||
@ -54,23 +68,22 @@ add_task(async function test2() {
|
||||
info("creating private window");
|
||||
let win = await BrowserTestUtils.openNewBrowserWindow({ private: true });
|
||||
|
||||
registerPopupEventHandler("popupshowing", function() {
|
||||
ok(false, "prompt showing");
|
||||
}, win);
|
||||
registerPopupEventHandler("popupshown", function() {
|
||||
ok(false, "prompt shown");
|
||||
}, win);
|
||||
registerPopupEventHandler("popuphidden", function() {
|
||||
ok(false, "prompt hidden");
|
||||
}, win);
|
||||
|
||||
info("creating private tab");
|
||||
win.gBrowser.selectedTab = win.gBrowser.addTab();
|
||||
|
||||
info("loading test page: " + testPageURL);
|
||||
win.gBrowser.selectedBrowser.loadURI(testPageURL);
|
||||
await BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
|
||||
|
||||
registerPopupEventHandler("popupshowing", function() {
|
||||
ok(false, "prompt showing");
|
||||
});
|
||||
registerPopupEventHandler("popupshown", function() {
|
||||
ok(false, "prompt shown");
|
||||
});
|
||||
registerPopupEventHandler("popuphidden", function() {
|
||||
ok(false, "prompt hidden");
|
||||
});
|
||||
await promiseMessage("InvalidStateError", win.gBrowser);
|
||||
await waitForMessage("InvalidStateError", win.gBrowser);
|
||||
|
||||
is(getPermission(testPageURL, "indexedDB"),
|
||||
Components.interfaces.nsIPermissionManager.DENY_ACTION,
|
||||
@ -81,13 +94,6 @@ add_task(async function test2() {
|
||||
});
|
||||
|
||||
add_task(async function test3() {
|
||||
info("creating tab");
|
||||
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
|
||||
|
||||
info("loading test page: " + testPageURL);
|
||||
gBrowser.selectedBrowser.loadURI(testPageURL);
|
||||
await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
|
||||
|
||||
registerPopupEventHandler("popupshowing", function() {
|
||||
ok(false, "Shouldn't show a popup this time");
|
||||
});
|
||||
@ -98,7 +104,12 @@ add_task(async function test3() {
|
||||
ok(false, "Shouldn't show a popup this time");
|
||||
});
|
||||
|
||||
await promiseMessage("InvalidStateError", gBrowser);
|
||||
info("creating tab");
|
||||
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
|
||||
|
||||
info("loading test page: " + testPageURL);
|
||||
gBrowser.selectedBrowser.loadURI(testPageURL);
|
||||
await waitForMessage("InvalidStateError", gBrowser);
|
||||
|
||||
is(getPermission(testPageURL, "indexedDB"),
|
||||
Components.interfaces.nsIPermissionManager.DENY_ACTION,
|
||||
|
@ -5,32 +5,45 @@
|
||||
|
||||
var gActiveListeners = {};
|
||||
|
||||
function registerPopupEventHandler(eventName, callback) {
|
||||
// These event (un)registration handlers only work for one window, DONOT use
|
||||
// them with multiple windows.
|
||||
function registerPopupEventHandler(eventName, callback, win) {
|
||||
if (!win) {
|
||||
win = window;
|
||||
}
|
||||
gActiveListeners[eventName] = function(event) {
|
||||
if (event.target != PopupNotifications.panel)
|
||||
if (event.target != win.PopupNotifications.panel)
|
||||
return;
|
||||
PopupNotifications.panel.removeEventListener(eventName,
|
||||
gActiveListeners[eventName]);
|
||||
win.PopupNotifications.panel.removeEventListener(
|
||||
eventName,
|
||||
gActiveListeners[eventName]);
|
||||
delete gActiveListeners[eventName];
|
||||
|
||||
callback.call(PopupNotifications.panel);
|
||||
callback.call(win.PopupNotifications.panel);
|
||||
}
|
||||
PopupNotifications.panel.addEventListener(eventName,
|
||||
gActiveListeners[eventName]);
|
||||
win.PopupNotifications.panel.addEventListener(eventName,
|
||||
gActiveListeners[eventName]);
|
||||
}
|
||||
|
||||
function unregisterPopupEventHandler(eventName)
|
||||
function unregisterPopupEventHandler(eventName, win)
|
||||
{
|
||||
PopupNotifications.panel.removeEventListener(eventName,
|
||||
gActiveListeners[eventName]);
|
||||
if (!win) {
|
||||
win = window;
|
||||
}
|
||||
win.PopupNotifications.panel.removeEventListener(eventName,
|
||||
gActiveListeners[eventName]);
|
||||
delete gActiveListeners[eventName];
|
||||
}
|
||||
|
||||
function unregisterAllPopupEventHandlers()
|
||||
function unregisterAllPopupEventHandlers(win)
|
||||
{
|
||||
if (!win) {
|
||||
win = window;
|
||||
}
|
||||
for (let eventName in gActiveListeners) {
|
||||
PopupNotifications.panel.removeEventListener(eventName,
|
||||
gActiveListeners[eventName]);
|
||||
win.PopupNotifications.panel.removeEventListener(
|
||||
eventName,
|
||||
gActiveListeners[eventName]);
|
||||
}
|
||||
gActiveListeners = {};
|
||||
}
|
||||
|
@ -3462,7 +3462,7 @@ ContentChild::RecvProvideAnonymousTemporaryFile(const uint64_t& aID,
|
||||
const FileDescOrError& aFDOrError)
|
||||
{
|
||||
nsAutoPtr<AnonymousTemporaryFileCallback> callback;
|
||||
mPendingAnonymousTemporaryFiles.RemoveAndForget(aID, callback);
|
||||
mPendingAnonymousTemporaryFiles.Remove(aID, &callback);
|
||||
MOZ_ASSERT(callback);
|
||||
|
||||
PRFileDesc* prfile = nullptr;
|
||||
|
@ -5102,8 +5102,7 @@ void
|
||||
ContentParent::SendGetFilesResponseAndForget(const nsID& aUUID,
|
||||
const GetFilesResponseResult& aResult)
|
||||
{
|
||||
if (auto entry = mGetFilesPendingRequests.Lookup(aUUID)) {
|
||||
entry.Remove();
|
||||
if (mGetFilesPendingRequests.Remove(aUUID)) {
|
||||
Unused << SendGetFilesResponse(aUUID, aResult);
|
||||
}
|
||||
}
|
||||
|
@ -178,7 +178,7 @@ GeckoMediaPluginService::RunPluginCrashCallbacks(uint32_t aPluginId,
|
||||
nsAutoPtr<nsTArray<RefPtr<GMPCrashHelper>>> helpers;
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
mPluginCrashHelpers.RemoveAndForget(aPluginId, helpers);
|
||||
mPluginCrashHelpers.Remove(aPluginId, &helpers);
|
||||
}
|
||||
if (!helpers) {
|
||||
LOGD(("%s::%s(%i) No crash helpers, not handling crash.", __CLASS__, __FUNCTION__, aPluginId));
|
||||
|
@ -113,7 +113,7 @@ public:
|
||||
MOZ_ASSERT(aDecrypted.mSample);
|
||||
|
||||
nsAutoPtr<DecryptPromiseRequestHolder> holder;
|
||||
mDecrypts.RemoveAndForget(aDecrypted.mSample, holder);
|
||||
mDecrypts.Remove(aDecrypted.mSample, &holder);
|
||||
if (holder) {
|
||||
holder->Complete();
|
||||
} else {
|
||||
|
@ -8,9 +8,7 @@
|
||||
|
||||
#include "GeckoProfiler.h"
|
||||
#include "nsRFPService.h"
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
#include "ProfilerMarkerPayload.h"
|
||||
#endif
|
||||
#include "PerformanceEntry.h"
|
||||
#include "PerformanceMainThread.h"
|
||||
#include "PerformanceMark.h"
|
||||
@ -297,13 +295,11 @@ Performance::Mark(const nsAString& aName, ErrorResult& aRv)
|
||||
new PerformanceMark(GetAsISupports(), aName, Now());
|
||||
InsertUserEntry(performanceMark);
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
if (profiler_is_active()) {
|
||||
profiler_add_marker(
|
||||
"UserTiming",
|
||||
MakeUnique<UserTimingMarkerPayload>(aName, TimeStamp::Now()));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
@ -391,7 +387,6 @@ Performance::Measure(const nsAString& aName,
|
||||
new PerformanceMeasure(GetAsISupports(), aName, startTime, endTime);
|
||||
InsertUserEntry(performanceMeasure);
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
if (profiler_is_active()) {
|
||||
TimeStamp startTimeStamp = CreationTimeStamp() +
|
||||
TimeDuration::FromMilliseconds(startTime);
|
||||
@ -401,7 +396,6 @@ Performance::Measure(const nsAString& aName,
|
||||
"UserTiming",
|
||||
MakeUnique<UserTimingMarkerPayload>(aName, startTimeStamp, endTimeStamp));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2201,7 +2201,7 @@ PluginInstanceParent::UnsubclassPluginWindow()
|
||||
// Remove 'this' from the plugin list safely
|
||||
nsAutoPtr<PluginInstanceParent> tmp;
|
||||
MOZ_ASSERT(sPluginInstanceList);
|
||||
sPluginInstanceList->RemoveAndForget((void*)mPluginHWND, tmp);
|
||||
sPluginInstanceList->Remove((void*)mPluginHWND, &tmp);
|
||||
tmp.forget();
|
||||
if (!sPluginInstanceList->Count()) {
|
||||
delete sPluginInstanceList;
|
||||
|
@ -445,7 +445,7 @@ SVGAnimationElement::EndElementAt(float offset, ErrorResult& rv)
|
||||
}
|
||||
|
||||
bool
|
||||
SVGAnimationElement::IsEventAttributeName(nsIAtom* aName)
|
||||
SVGAnimationElement::IsEventAttributeNameInternal(nsIAtom* aName)
|
||||
{
|
||||
return nsContentUtils::IsEventAttributeName(aName, EventNameType_SMIL);
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ public:
|
||||
nsSMILTimeContainer* GetTimeContainer();
|
||||
virtual nsSMILAnimationFunction& AnimationFunction() = 0;
|
||||
|
||||
virtual bool IsEventAttributeName(nsIAtom* aName) override;
|
||||
virtual bool IsEventAttributeNameInternal(nsIAtom* aName) override;
|
||||
|
||||
// Utility methods for within SVG
|
||||
void ActivateByHyperlink();
|
||||
|
@ -92,7 +92,7 @@ public:
|
||||
return static_cast<SVGMeetOrSlice>(mMeetOrSlice);
|
||||
}
|
||||
|
||||
uint32_t Hash() const {
|
||||
PLDHashNumber Hash() const {
|
||||
return HashGeneric(mAlign, mMeetOrSlice);
|
||||
}
|
||||
|
||||
|
@ -574,7 +574,7 @@ SVGSVGElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
}
|
||||
|
||||
bool
|
||||
SVGSVGElement::IsEventAttributeName(nsIAtom* aName)
|
||||
SVGSVGElement::IsEventAttributeNameInternal(nsIAtom* aName)
|
||||
{
|
||||
/* The events in EventNameType_SVGSVG are for events that are only
|
||||
applicable to outermost 'svg' elements. We don't check if we're an outer
|
||||
|
@ -105,7 +105,7 @@ public:
|
||||
// nsIContent interface
|
||||
virtual nsresult GetEventTargetParent(
|
||||
EventChainPreVisitor& aVisitor) override;
|
||||
virtual bool IsEventAttributeName(nsIAtom* aName) override;
|
||||
virtual bool IsEventAttributeNameInternal(nsIAtom* aName) override;
|
||||
|
||||
// nsINode methods:
|
||||
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
|
||||
|
@ -92,7 +92,7 @@ SVGTransformableElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
|
||||
}
|
||||
|
||||
bool
|
||||
SVGTransformableElement::IsEventAttributeName(nsIAtom* aName)
|
||||
SVGTransformableElement::IsEventAttributeNameInternal(nsIAtom* aName)
|
||||
{
|
||||
return nsContentUtils::IsEventAttributeName(aName, EventNameType_SVGGraphic);
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ public:
|
||||
|
||||
|
||||
// nsSVGElement overrides
|
||||
virtual bool IsEventAttributeName(nsIAtom* aName) override;
|
||||
virtual bool IsEventAttributeNameInternal(nsIAtom* aName) override;
|
||||
|
||||
|
||||
virtual gfxMatrix PrependLocalTransformsTo(
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "mozilla/dom/SVGTests.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsICSSDeclaration.h"
|
||||
#include "nsIContentInlines.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMMutationEvent.h"
|
||||
#include "mozilla/InternalMutationEvent.h"
|
||||
|
@ -2416,7 +2416,7 @@ nsWebBrowserPersist::FixRedirectedChannelEntry(nsIChannel *aNewChannel)
|
||||
// If a match was found, remove the data entry with the old channel
|
||||
// key and re-add it with the new channel key.
|
||||
nsAutoPtr<OutputData> outputData;
|
||||
mOutputMap.RemoveAndForget(matchingKey, outputData);
|
||||
mOutputMap.Remove(matchingKey, &outputData);
|
||||
NS_ENSURE_TRUE(outputData, NS_ERROR_FAILURE);
|
||||
|
||||
// Store data again with new channel unless told to ignore redirects.
|
||||
|
@ -1794,8 +1794,7 @@ ServiceWorkerManager::ReportToAllClients(const nsCString& aScope,
|
||||
|
||||
if (regList->IsEmpty()) {
|
||||
regList = nullptr;
|
||||
nsAutoPtr<WeakDocumentList> doomed;
|
||||
mRegisteringDocuments.RemoveAndForget(aScope, doomed);
|
||||
mRegisteringDocuments.Remove(aScope);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1950,8 +1949,7 @@ ServiceWorkerManager::FlushReportsToAllClients(const nsACString& aScope,
|
||||
|
||||
if (regList->IsEmpty()) {
|
||||
regList = nullptr;
|
||||
nsAutoPtr<WeakDocumentList> doomed;
|
||||
mRegisteringDocuments.RemoveAndForget(aScope, doomed);
|
||||
mRegisteringDocuments.Remove(aScope);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3891,8 +3889,7 @@ ServiceWorkerManager::ShouldReportToWindow(mozIDOMWindowProxy* aWindow,
|
||||
|
||||
if (list->IsEmpty()) {
|
||||
list = nullptr;
|
||||
nsAutoPtr<WeakDocumentList> doomed;
|
||||
mRegisteringDocuments.RemoveAndForget(aScope, doomed);
|
||||
mRegisteringDocuments.Remove(aScope);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4171,8 +4168,7 @@ ServiceWorkerManager::RemoveNavigationInterception(const nsACString& aScope,
|
||||
MOZ_ASSERT(!list->Contains(aChannel));
|
||||
if (list->IsEmpty()) {
|
||||
list = nullptr;
|
||||
nsAutoPtr<InterceptionList> doomed;
|
||||
mNavigationInterceptions.RemoveAndForget(aScope, doomed);
|
||||
mNavigationInterceptions.Remove(aScope);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -175,7 +175,7 @@ nsXBLDocumentInfo::RemovePrototypeBinding(const nsACString& aRef)
|
||||
{
|
||||
if (mBindingTable) {
|
||||
nsAutoPtr<nsXBLPrototypeBinding> bindingToRemove;
|
||||
mBindingTable->RemoveAndForget(aRef, bindingToRemove);
|
||||
mBindingTable->Remove(aRef, &bindingToRemove);
|
||||
|
||||
// We do not want to destroy the binding, so just forget it.
|
||||
bindingToRemove.forget();
|
||||
|
@ -1465,7 +1465,7 @@ nsXMLContentSink::FlushPendingNotifications(FlushType aType)
|
||||
FlushText(false);
|
||||
}
|
||||
}
|
||||
if (aType >= FlushType::InterruptibleLayout) {
|
||||
if (aType >= FlushType::EnsurePresShellInitAndFrames) {
|
||||
// Make sure that layout has started so that the reflow flush
|
||||
// will actually happen.
|
||||
MaybeStartLayout(true);
|
||||
|
@ -27,17 +27,13 @@
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
const uint32_t kUnknownIndex = uint32_t(-1);
|
||||
|
||||
txXPathTreeWalker::txXPathTreeWalker(const txXPathTreeWalker& aOther)
|
||||
: mPosition(aOther.mPosition),
|
||||
mCurrentIndex(aOther.mCurrentIndex)
|
||||
: mPosition(aOther.mPosition)
|
||||
{
|
||||
}
|
||||
|
||||
txXPathTreeWalker::txXPathTreeWalker(const txXPathNode& aNode)
|
||||
: mPosition(aNode),
|
||||
mCurrentIndex(kUnknownIndex)
|
||||
: mPosition(aNode)
|
||||
{
|
||||
}
|
||||
|
||||
@ -62,9 +58,6 @@ txXPathTreeWalker::moveToRoot()
|
||||
mPosition.mIndex = txXPathNode::eContent;
|
||||
mPosition.mNode = rootNode;
|
||||
}
|
||||
|
||||
mCurrentIndex = kUnknownIndex;
|
||||
mDescendants.Clear();
|
||||
}
|
||||
|
||||
bool
|
||||
@ -97,8 +90,6 @@ txXPathTreeWalker::moveToElementById(const nsAString& aID)
|
||||
|
||||
mPosition.mIndex = txXPathNode::eContent;
|
||||
mPosition.mNode = content;
|
||||
mCurrentIndex = kUnknownIndex;
|
||||
mDescendants.Clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -174,12 +165,6 @@ txXPathTreeWalker::moveToFirstChild()
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_ASSERTION(!mPosition.isDocument() ||
|
||||
(mCurrentIndex == kUnknownIndex && mDescendants.IsEmpty()),
|
||||
"we shouldn't have any position info at the document");
|
||||
NS_ASSERTION(mCurrentIndex != kUnknownIndex || mDescendants.IsEmpty(),
|
||||
"Index should be known if parents index are");
|
||||
|
||||
nsIContent* child = mPosition.mNode->GetFirstChild();
|
||||
if (!child) {
|
||||
return false;
|
||||
@ -187,12 +172,6 @@ txXPathTreeWalker::moveToFirstChild()
|
||||
mPosition.mIndex = txXPathNode::eContent;
|
||||
mPosition.mNode = child;
|
||||
|
||||
if (mCurrentIndex != kUnknownIndex &&
|
||||
!mDescendants.AppendValue(mCurrentIndex)) {
|
||||
mDescendants.Clear();
|
||||
}
|
||||
mCurrentIndex = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -203,23 +182,13 @@ txXPathTreeWalker::moveToLastChild()
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_ASSERTION(!mPosition.isDocument() ||
|
||||
(mCurrentIndex == kUnknownIndex && mDescendants.IsEmpty()),
|
||||
"we shouldn't have any position info at the document");
|
||||
NS_ASSERTION(mCurrentIndex != kUnknownIndex || mDescendants.IsEmpty(),
|
||||
"Index should be known if parents index are");
|
||||
|
||||
uint32_t total = mPosition.mNode->GetChildCount();
|
||||
if (!total) {
|
||||
nsIContent* child = mPosition.mNode->GetLastChild();
|
||||
if (!child) {
|
||||
return false;
|
||||
}
|
||||
mPosition.mNode = mPosition.mNode->GetLastChild();
|
||||
|
||||
if (mCurrentIndex != kUnknownIndex &&
|
||||
!mDescendants.AppendValue(mCurrentIndex)) {
|
||||
mDescendants.Clear();
|
||||
}
|
||||
mCurrentIndex = total - 1;
|
||||
mPosition.mIndex = txXPathNode::eContent;
|
||||
mPosition.mNode = child;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -231,7 +200,14 @@ txXPathTreeWalker::moveToNextSibling()
|
||||
return false;
|
||||
}
|
||||
|
||||
return moveToSibling(1);
|
||||
nsINode* sibling = mPosition.mNode->GetNextSibling();
|
||||
if (!sibling) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mPosition.mNode = sibling;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -241,7 +217,14 @@ txXPathTreeWalker::moveToPreviousSibling()
|
||||
return false;
|
||||
}
|
||||
|
||||
return moveToSibling(-1);
|
||||
nsINode* sibling = mPosition.mNode->GetPreviousSibling();
|
||||
if (!sibling) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mPosition.mNode = sibling;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -262,15 +245,6 @@ txXPathTreeWalker::moveToParent()
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t count = mDescendants.Length();
|
||||
if (count) {
|
||||
mCurrentIndex = mDescendants.ValueAt(--count);
|
||||
mDescendants.RemoveValueAt(count);
|
||||
}
|
||||
else {
|
||||
mCurrentIndex = kUnknownIndex;
|
||||
}
|
||||
|
||||
mPosition.mIndex = mPosition.mNode->GetParent() ?
|
||||
txXPathNode::eContent : txXPathNode::eDocument;
|
||||
mPosition.mNode = parent;
|
||||
@ -278,34 +252,6 @@ txXPathTreeWalker::moveToParent()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
txXPathTreeWalker::moveToSibling(int32_t aDir)
|
||||
{
|
||||
NS_ASSERTION(mPosition.isContent(),
|
||||
"moveToSibling should only be called for content");
|
||||
|
||||
nsINode* parent = mPosition.mNode->GetParentNode();
|
||||
if (!parent) {
|
||||
return false;
|
||||
}
|
||||
if (mCurrentIndex == kUnknownIndex) {
|
||||
mCurrentIndex = parent->IndexOf(mPosition.mNode);
|
||||
}
|
||||
|
||||
// if mCurrentIndex is 0 we rely on GetChildAt returning null for an
|
||||
// index of uint32_t(-1).
|
||||
uint32_t newIndex = mCurrentIndex + aDir;
|
||||
nsIContent* newChild = parent->GetChildAt(newIndex);
|
||||
if (!newChild) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mPosition.mNode = newChild;
|
||||
mCurrentIndex = newIndex;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
txXPathNode::txXPathNode(const txXPathNode& aNode)
|
||||
: mNode(aNode.mNode),
|
||||
mRefCountRoot(aNode.mRefCountRoot),
|
||||
|
@ -14,26 +14,6 @@
|
||||
class nsIAtom;
|
||||
class nsIDOMDocument;
|
||||
|
||||
class txUint32Array : public nsTArray<uint32_t>
|
||||
{
|
||||
public:
|
||||
bool AppendValue(uint32_t aValue)
|
||||
{
|
||||
return AppendElement(aValue) != nullptr;
|
||||
}
|
||||
bool RemoveValueAt(uint32_t aIndex)
|
||||
{
|
||||
if (aIndex < Length()) {
|
||||
RemoveElementAt(aIndex);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
uint32_t ValueAt(uint32_t aIndex) const
|
||||
{
|
||||
return (aIndex < Length()) ? ElementAt(aIndex) : 0;
|
||||
}
|
||||
};
|
||||
|
||||
class txXPathTreeWalker
|
||||
{
|
||||
public:
|
||||
@ -67,10 +47,6 @@ private:
|
||||
txXPathNode mPosition;
|
||||
|
||||
bool moveToValidAttribute(uint32_t aStartIndex);
|
||||
bool moveToSibling(int32_t aDir);
|
||||
|
||||
uint32_t mCurrentIndex;
|
||||
txUint32Array mDescendants;
|
||||
};
|
||||
|
||||
class txXPathNodeUtils
|
||||
@ -195,9 +171,6 @@ txXPathTreeWalker::moveTo(const txXPathTreeWalker& aWalker)
|
||||
NS_IF_ADDREF(newRoot);
|
||||
NS_IF_RELEASE(root);
|
||||
}
|
||||
|
||||
mCurrentIndex = aWalker.mCurrentIndex;
|
||||
mDescendants.Clear();
|
||||
}
|
||||
|
||||
inline bool
|
||||
|
@ -2031,7 +2031,7 @@ nsXULElement::RecompileScriptEventListeners()
|
||||
}
|
||||
|
||||
bool
|
||||
nsXULElement::IsEventAttributeName(nsIAtom *aName)
|
||||
nsXULElement::IsEventAttributeNameInternal(nsIAtom *aName)
|
||||
{
|
||||
return nsContentUtils::IsEventAttributeName(aName, EventNameType_XUL);
|
||||
}
|
||||
|
@ -434,7 +434,7 @@ public:
|
||||
|
||||
virtual nsIDOMNode* AsDOMNode() override { return this; }
|
||||
|
||||
virtual bool IsEventAttributeName(nsIAtom* aName) override;
|
||||
virtual bool IsEventAttributeNameInternal(nsIAtom* aName) override;
|
||||
|
||||
typedef mozilla::dom::DOMString DOMString;
|
||||
void GetXULAttr(nsIAtom* aName, DOMString& aResult) const
|
||||
|
@ -58,7 +58,7 @@ SimpleTest.waitForExplicitFinish();
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<iframe onload="runTest();" id="pasteframe" src="data:text/html,<html><body contenteditable='true'>"></iframe>
|
||||
<iframe onload="runTest();" id="pasteframe" srcdoc="<html><body contenteditable='true'>"></iframe>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@ -94,7 +94,7 @@ SimpleTest.waitForFocus(function() {
|
||||
|
||||
continueTest();
|
||||
});
|
||||
iframe.src = "data:text/html,foo";
|
||||
iframe.srcdoc = "foo";
|
||||
document.getElementById("content").appendChild(iframe);
|
||||
});
|
||||
|
||||
|
@ -14,7 +14,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=674770
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<iframe id="iframe" style="display: block; height: 14em;"
|
||||
src="data:text/html,<input id='text' value='pasted'><input id='input' style='display: block;'><p id='editor1' contenteditable>editor1:</p><p id='editor2' contenteditable>editor2:</p>"></iframe>
|
||||
srcdoc="<input id='text' value='pasted'><input id='input' style='display: block;'><p id='editor1' contenteditable>editor1:</p><p id='editor2' contenteditable>editor2:</p>"></iframe>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
@ -337,8 +337,7 @@ function initForBodyEditableDocumentTests()
|
||||
|
||||
iframe.onload =
|
||||
function (aEvent) { SimpleTest.executeSoon(runBodyEditableDocumentTests1); };
|
||||
iframe.src =
|
||||
"data:text/html,<body contenteditable>body:</body>";
|
||||
iframe.srcdoc = "<body contenteditable>body:</body>";
|
||||
}
|
||||
|
||||
function runBodyEditableDocumentTests1()
|
||||
|
@ -82,7 +82,7 @@ needs-focus == spellcheck-non-latin-japanese.html spellcheck-non-latin-japanese-
|
||||
needs-focus == spellcheck-non-latin-korean.html spellcheck-non-latin-korean-ref.html
|
||||
== unneeded_scroll.html unneeded_scroll-ref.html
|
||||
== caret_on_presshell_reinit.html caret_on_presshell_reinit-ref.html
|
||||
fuzzy-if(browserIsRemote,255,3) asserts-if(browserIsRemote,0-2) asserts-if(webrender&&!browserIsRemote,0-1) == caret_on_presshell_reinit-2.html caret_on_presshell_reinit-ref.html
|
||||
fuzzy-if(browserIsRemote,255,3) asserts-if(browserIsRemote,0-3) asserts-if(webrender&&!browserIsRemote,0-1) == caret_on_presshell_reinit-2.html caret_on_presshell_reinit-ref.html # bug 959132 for assertions
|
||||
fuzzy-if(asyncPan&&!layersGPUAccelerated,102,2824) == 642800.html 642800-ref.html
|
||||
== selection_visibility_after_reframe.html selection_visibility_after_reframe-ref.html
|
||||
!= selection_visibility_after_reframe-2.html selection_visibility_after_reframe-ref.html
|
||||
|
@ -1050,7 +1050,7 @@ struct ScrollableLayerGuid {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t Hash() const
|
||||
PLDHashNumber Hash() const
|
||||
{
|
||||
return HashGeneric(mLayersId, mPresShellId, mScrollId);
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "gfxPrefs.h"
|
||||
#include "FrameMetrics.h"
|
||||
#include "nsDebug.h" // for NS_WARNING
|
||||
#include "mozilla/Assertions.h" // for MOZ_ASSERT
|
||||
@ -85,6 +86,7 @@ private:
|
||||
ViewID aScrollId,
|
||||
const std::string& aKey,
|
||||
const std::string& aValue) {
|
||||
MOZ_ASSERT(gfxPrefs::APZTestLoggingEnabled(), "don't call me");
|
||||
auto bucketIterator = aDataStore.find(aSequenceNumber);
|
||||
if (bucketIterator == aDataStore.end()) {
|
||||
MOZ_ASSERT(false, "LogTestDataImpl called with nonexistent sequence number");
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <stdint.h> // for int32_t
|
||||
#include "Layers.h"
|
||||
#include "gfxContext.h" // for gfxContext
|
||||
#include "gfxPrefs.h"
|
||||
#include "mozilla/Attributes.h" // for override
|
||||
#include "mozilla/LinkedList.h" // For LinkedList
|
||||
#include "mozilla/WidgetUtils.h" // for ScreenRotation
|
||||
@ -207,6 +208,7 @@ public:
|
||||
const std::string& aKey,
|
||||
const std::string& aValue)
|
||||
{
|
||||
MOZ_ASSERT(gfxPrefs::APZTestLoggingEnabled(), "don't call me");
|
||||
mApzTestData.LogTestDataForPaint(mPaintSequenceNumber, aScrollId, aKey, aValue);
|
||||
}
|
||||
|
||||
@ -223,6 +225,7 @@ public:
|
||||
const std::string& aKey,
|
||||
const std::string& aValue)
|
||||
{
|
||||
MOZ_ASSERT(gfxPrefs::APZTestLoggingEnabled(), "don't call me");
|
||||
mApzTestData.LogTestDataForRepaintRequest(aSequenceNumber, aScrollId, aKey, aValue);
|
||||
}
|
||||
|
||||
|
@ -35,9 +35,7 @@
|
||||
#include "TextRenderer.h" // for TextRenderer
|
||||
#include <vector>
|
||||
#include "GeckoProfiler.h" // for GeckoProfiler
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
#include "ProfilerMarkerPayload.h" // for LayerTranslationMarkerPayload
|
||||
#endif
|
||||
|
||||
#define CULLING_LOG(...)
|
||||
// #define CULLING_LOG(...) printf_stderr("CULLING: " __VA_ARGS__)
|
||||
@ -83,7 +81,6 @@ DrawLayerInfo(const RenderTargetIntRect& aClipRect,
|
||||
static void
|
||||
PrintUniformityInfo(Layer* aLayer)
|
||||
{
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
if (!profiler_is_active()) {
|
||||
return;
|
||||
}
|
||||
@ -102,8 +99,8 @@ PrintUniformityInfo(Layer* aLayer)
|
||||
Point translation = transform.As2D().GetTranslation();
|
||||
profiler_add_marker(
|
||||
"LayerTranslation",
|
||||
MakeUnique<LayerTranslationMarkerPayload>(aLayer, translation));
|
||||
#endif
|
||||
MakeUnique<LayerTranslationMarkerPayload>(aLayer, translation,
|
||||
TimeStamp::Now()));
|
||||
}
|
||||
|
||||
static Maybe<gfx::Polygon>
|
||||
|
@ -83,9 +83,7 @@
|
||||
#include "mozilla/HalTypes.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
#include "ProfilerMarkerPayload.h"
|
||||
#endif
|
||||
#include "mozilla/VsyncDispatcher.h"
|
||||
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
|
||||
#include "VsyncSource.h"
|
||||
@ -1844,12 +1842,10 @@ CompositorBridgeParent::GetAPZCTreeManager(uint64_t aLayersId)
|
||||
static void
|
||||
InsertVsyncProfilerMarker(TimeStamp aVsyncTimestamp)
|
||||
{
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
||||
profiler_add_marker(
|
||||
"VsyncTimestamp",
|
||||
MakeUnique<VsyncMarkerPayload>(aVsyncTimestamp));
|
||||
#endif
|
||||
}
|
||||
|
||||
/*static */ void
|
||||
|
@ -6,6 +6,7 @@
|
||||
#ifndef GFX_WEBRENDERLAYERMANAGER_H
|
||||
#define GFX_WEBRENDERLAYERMANAGER_H
|
||||
|
||||
#include "gfxPrefs.h"
|
||||
#include "Layers.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
#include "mozilla/layers/APZTestData.h"
|
||||
@ -161,6 +162,7 @@ public:
|
||||
void LogTestDataForCurrentPaint(FrameMetrics::ViewID aScrollId,
|
||||
const std::string& aKey,
|
||||
const std::string& aValue) {
|
||||
MOZ_ASSERT(gfxPrefs::APZTestLoggingEnabled(), "don't call me");
|
||||
mApzTestData.LogTestDataForPaint(mPaintSequenceNumber, aScrollId, aKey, aValue);
|
||||
}
|
||||
// See equivalent function in ClientLayerManager
|
||||
|
@ -6,9 +6,7 @@
|
||||
#include "ContextStateTracker.h"
|
||||
#include "GLContext.h"
|
||||
#include "GeckoProfiler.h"
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
#include "ProfilerMarkerPayload.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -111,13 +109,13 @@ ContextStateTrackerOGL::Flush(GLContext* aGL)
|
||||
|
||||
aGL->fDeleteQueries(1, &handle);
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
profiler_add_marker(
|
||||
"gpu_timer_query",
|
||||
MakeUnique<GPUMarkerPayload>(mCompletedSections[0].mCpuTimeStart,
|
||||
mCompletedSections[0].mCpuTimeEnd,
|
||||
0, gpuTime));
|
||||
#endif
|
||||
if (profiler_is_active()) {
|
||||
profiler_add_marker(
|
||||
"gpu_timer_query",
|
||||
MakeUnique<GPUMarkerPayload>(mCompletedSections[0].mCpuTimeStart,
|
||||
mCompletedSections[0].mCpuTimeEnd,
|
||||
0, gpuTime));
|
||||
}
|
||||
|
||||
mCompletedSections.RemoveElementAt(0);
|
||||
}
|
||||
|
@ -698,9 +698,9 @@ gfxFontEntry::GrReleaseTable(const void *aAppFaceHandle,
|
||||
{
|
||||
gfxFontEntry *fontEntry =
|
||||
static_cast<gfxFontEntry*>(const_cast<void*>(aAppFaceHandle));
|
||||
if (auto entry = fontEntry->mGrTableMap->Lookup(aTableBuffer)) {
|
||||
hb_blob_destroy(static_cast<hb_blob_t*>(entry.Data()));
|
||||
entry.Remove();
|
||||
void* value;
|
||||
if (fontEntry->mGrTableMap->Remove(aTableBuffer, &value)) {
|
||||
hb_blob_destroy(static_cast<hb_blob_t*>(value));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -239,7 +239,11 @@ RenderThread::UpdateAndRender(wr::WindowId aWindowId)
|
||||
|
||||
TimeStamp start = TimeStamp::Now();
|
||||
|
||||
renderer->Render();
|
||||
bool ret = renderer->Render();
|
||||
if (!ret) {
|
||||
// Render did not happen, do not call NotifyDidRender.
|
||||
return;
|
||||
}
|
||||
|
||||
TimeStamp end = TimeStamp::Now();
|
||||
|
||||
|
@ -105,6 +105,8 @@ RendererOGL::Render()
|
||||
{
|
||||
if (!mGL->MakeCurrent()) {
|
||||
gfxCriticalNote << "Failed to make render context current, can't draw.";
|
||||
// XXX This could cause oom in webrender since pending_texture_updates is not handled.
|
||||
// It needs to be addressed.
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -118,6 +120,8 @@ RendererOGL::Render()
|
||||
#endif
|
||||
|
||||
if (!mWidget->PreRender(&widgetContext)) {
|
||||
// XXX This could cause oom in webrender since pending_texture_updates is not handled.
|
||||
// It needs to be addressed.
|
||||
return false;
|
||||
}
|
||||
// XXX set clear color if MOZ_WIDGET_ANDROID is defined.
|
||||
|
@ -128,7 +128,7 @@ ImageCacheKey::Spec() const
|
||||
return mURI->Spec();
|
||||
}
|
||||
|
||||
/* static */ uint32_t
|
||||
/* static */ PLDHashNumber
|
||||
ImageCacheKey::ComputeHash(ImageURL* aURI,
|
||||
const Maybe<uint64_t>& aBlobSerial,
|
||||
const OriginAttributes& aAttrs,
|
||||
|
@ -42,7 +42,7 @@ public:
|
||||
ImageCacheKey(ImageCacheKey&& aOther);
|
||||
|
||||
bool operator==(const ImageCacheKey& aOther) const;
|
||||
uint32_t Hash() const { return mHash; }
|
||||
PLDHashNumber Hash() const { return mHash; }
|
||||
|
||||
/// A weak pointer to the URI spec for this cache entry. For logging only.
|
||||
const char* Spec() const;
|
||||
@ -55,17 +55,17 @@ public:
|
||||
void* ControlledDocument() const { return mControlledDocument; }
|
||||
|
||||
private:
|
||||
static uint32_t ComputeHash(ImageURL* aURI,
|
||||
const Maybe<uint64_t>& aBlobSerial,
|
||||
const OriginAttributes& aAttrs,
|
||||
void* aControlledDocument);
|
||||
static PLDHashNumber ComputeHash(ImageURL* aURI,
|
||||
const Maybe<uint64_t>& aBlobSerial,
|
||||
const OriginAttributes& aAttrs,
|
||||
void* aControlledDocument);
|
||||
static void* GetControlledDocumentToken(nsIDocument* aDocument);
|
||||
|
||||
RefPtr<ImageURL> mURI;
|
||||
Maybe<uint64_t> mBlobSerial;
|
||||
OriginAttributes mOriginAttributes;
|
||||
void* mControlledDocument;
|
||||
uint32_t mHash;
|
||||
PLDHashNumber mHash;
|
||||
bool mIsChrome;
|
||||
};
|
||||
|
||||
|
@ -118,7 +118,7 @@ public:
|
||||
private:
|
||||
friend class ImageCacheKey;
|
||||
|
||||
uint32_t ComputeHash(const Maybe<uint64_t>& aBlobSerial) const
|
||||
PLDHashNumber ComputeHash(const Maybe<uint64_t>& aBlobSerial) const
|
||||
{
|
||||
if (aBlobSerial) {
|
||||
// For blob URIs, we hash the serial number of the underlying blob, so that
|
||||
|
@ -471,11 +471,7 @@ ProgressTracker::RemoveObserver(IProgressObserver* aObserver)
|
||||
|
||||
// Remove the observer from the list.
|
||||
bool removed = mObservers.Write([=](ObserverTable* aTable) {
|
||||
if (auto entry = aTable->Lookup(observer)) {
|
||||
entry.Remove();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return aTable->Remove(observer);
|
||||
});
|
||||
|
||||
// Observers can get confused if they don't get all the proper teardown
|
||||
|
@ -60,9 +60,9 @@ public:
|
||||
aOther.mFlags == mFlags;
|
||||
}
|
||||
|
||||
uint32_t Hash() const
|
||||
PLDHashNumber Hash() const
|
||||
{
|
||||
uint32_t hash = HashGeneric(mSize.width, mSize.height);
|
||||
PLDHashNumber hash = HashGeneric(mSize.width, mSize.height);
|
||||
hash = AddToHash(hash, mSVGContext.map(HashSIC).valueOr(0));
|
||||
hash = AddToHash(hash, uint8_t(mPlayback), uint32_t(mFlags));
|
||||
return hash;
|
||||
@ -84,7 +84,7 @@ private:
|
||||
, mFlags(aFlags)
|
||||
{ }
|
||||
|
||||
static uint32_t HashSIC(const SVGImageContext& aSIC) {
|
||||
static PLDHashNumber HashSIC(const SVGImageContext& aSIC) {
|
||||
return aSIC.Hash();
|
||||
}
|
||||
|
||||
|
@ -176,7 +176,7 @@ sub genTest {
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
||||
<style type="text/css">
|
||||
\@font-face { font-family: foo; src: url($testFont); }
|
||||
p { font-family: foo; text-transform: ${whichMapping}case; }
|
||||
p { font-family: foo; font-size: 12px; text-transform: ${whichMapping}case; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@ -202,7 +202,7 @@ __END__
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
||||
<style type="text/css">
|
||||
\@font-face { font-family: foo; src: url($testFont); }
|
||||
p { font-family: foo; }
|
||||
p { font-family: foo; font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -9,8 +9,8 @@
|
||||
#include "mozilla/ArrayUtils.h" // for ArrayLength
|
||||
#include <stdlib.h> // for bsearch
|
||||
|
||||
/* SpecialCasing-8.0.0.txt */
|
||||
/* Date: 2014-12-16, 23:08:04 GMT [MD] */
|
||||
/* SpecialCasing-10.0.0.txt */
|
||||
/* Date: 2017-04-14, 05:40:43 GMT */
|
||||
|
||||
using mozilla::unicode::MultiCharMapping;
|
||||
|
||||
|
@ -106,11 +106,6 @@ js::Nursery::Nursery(JSRuntime* rt)
|
||||
, previousPromotionRate_(0)
|
||||
, profileThreshold_(0)
|
||||
, enableProfiling_(false)
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
, trackTimings_(true)
|
||||
#else
|
||||
, trackTimings_(false)
|
||||
#endif
|
||||
, reportTenurings_(0)
|
||||
, minorGCTriggerReason_(JS::gcreason::NO_REASON)
|
||||
, minorGcCount_(0)
|
||||
@ -153,7 +148,6 @@ js::Nursery::init(uint32_t maxNurseryBytes, AutoLockGC& lock)
|
||||
exit(0);
|
||||
}
|
||||
enableProfiling_ = true;
|
||||
trackTimings_ = true;
|
||||
profileThreshold_ = TimeDuration::FromMicroseconds(atoi(env));
|
||||
}
|
||||
|
||||
@ -491,12 +485,8 @@ FOR_EACH_NURSERY_PROFILE_TIME(EXTRACT_NAME)
|
||||
"" };
|
||||
|
||||
size_t i = 0;
|
||||
if (trackTimings_) {
|
||||
for (auto time : profileDurations_)
|
||||
json.property(names[i++], time, json.MICROSECONDS);
|
||||
} else {
|
||||
json.property(names[0], *profileDurations_.begin(), json.MICROSECONDS);
|
||||
}
|
||||
for (auto time : profileDurations_)
|
||||
json.property(names[i++], time, json.MICROSECONDS);
|
||||
|
||||
json.endObject();
|
||||
}
|
||||
@ -532,10 +522,8 @@ js::Nursery::printTotalProfileTimes()
|
||||
void
|
||||
js::Nursery::maybeClearProfileDurations()
|
||||
{
|
||||
if (trackTimings_) {
|
||||
for (auto& duration : profileDurations_)
|
||||
duration = mozilla::TimeDuration();
|
||||
}
|
||||
for (auto& duration : profileDurations_)
|
||||
duration = mozilla::TimeDuration();
|
||||
}
|
||||
|
||||
inline void
|
||||
@ -551,20 +539,6 @@ js::Nursery::endProfile(ProfileKey key)
|
||||
totalDurations_[key] += profileDurations_[key];
|
||||
}
|
||||
|
||||
inline void
|
||||
js::Nursery::maybeStartProfile(ProfileKey key)
|
||||
{
|
||||
if (trackTimings_)
|
||||
startProfile(key);
|
||||
}
|
||||
|
||||
inline void
|
||||
js::Nursery::maybeEndProfile(ProfileKey key)
|
||||
{
|
||||
if (trackTimings_)
|
||||
endProfile(key);
|
||||
}
|
||||
|
||||
void
|
||||
js::Nursery::collect(JS::gcreason::Reason reason)
|
||||
{
|
||||
@ -608,15 +582,15 @@ js::Nursery::collect(JS::gcreason::Reason reason)
|
||||
promotionRate = doCollection(reason, tenureCounts);
|
||||
|
||||
// Resize the nursery.
|
||||
maybeStartProfile(ProfileKey::Resize);
|
||||
startProfile(ProfileKey::Resize);
|
||||
maybeResizeNursery(reason, promotionRate);
|
||||
maybeEndProfile(ProfileKey::Resize);
|
||||
endProfile(ProfileKey::Resize);
|
||||
|
||||
// If we are promoting the nursery, or exhausted the store buffer with
|
||||
// pointers to nursery things, which will force a collection well before
|
||||
// the nursery is full, look for object groups that are getting promoted
|
||||
// excessively and try to pretenure them.
|
||||
maybeStartProfile(ProfileKey::Pretenure);
|
||||
startProfile(ProfileKey::Pretenure);
|
||||
uint32_t pretenureCount = 0;
|
||||
if (promotionRate > 0.8 || reason == JS::gcreason::FULL_STORE_BUFFER) {
|
||||
JSContext* cx = TlsContext.get();
|
||||
@ -631,7 +605,7 @@ js::Nursery::collect(JS::gcreason::Reason reason)
|
||||
}
|
||||
}
|
||||
}
|
||||
maybeEndProfile(ProfileKey::Pretenure);
|
||||
endProfile(ProfileKey::Pretenure);
|
||||
|
||||
// We ignore gcMaxBytes when allocating for minor collection. However, if we
|
||||
// overflowed, we disable the nursery. The next time we allocate, we'll fail
|
||||
@ -694,90 +668,90 @@ js::Nursery::doCollection(JS::gcreason::Reason reason,
|
||||
|
||||
// The MIR graph only contains nursery pointers if cancelIonCompilations()
|
||||
// is set on the store buffer, in which case we cancel all compilations.
|
||||
maybeStartProfile(ProfileKey::CancelIonCompilations);
|
||||
startProfile(ProfileKey::CancelIonCompilations);
|
||||
if (sb.cancelIonCompilations())
|
||||
js::CancelOffThreadIonCompile(rt);
|
||||
maybeEndProfile(ProfileKey::CancelIonCompilations);
|
||||
endProfile(ProfileKey::CancelIonCompilations);
|
||||
|
||||
maybeStartProfile(ProfileKey::TraceValues);
|
||||
startProfile(ProfileKey::TraceValues);
|
||||
sb.traceValues(mover);
|
||||
maybeEndProfile(ProfileKey::TraceValues);
|
||||
endProfile(ProfileKey::TraceValues);
|
||||
|
||||
maybeStartProfile(ProfileKey::TraceCells);
|
||||
startProfile(ProfileKey::TraceCells);
|
||||
sb.traceCells(mover);
|
||||
maybeEndProfile(ProfileKey::TraceCells);
|
||||
endProfile(ProfileKey::TraceCells);
|
||||
|
||||
maybeStartProfile(ProfileKey::TraceSlots);
|
||||
startProfile(ProfileKey::TraceSlots);
|
||||
sb.traceSlots(mover);
|
||||
maybeEndProfile(ProfileKey::TraceSlots);
|
||||
endProfile(ProfileKey::TraceSlots);
|
||||
|
||||
maybeStartProfile(ProfileKey::TraceWholeCells);
|
||||
startProfile(ProfileKey::TraceWholeCells);
|
||||
sb.traceWholeCells(mover);
|
||||
maybeEndProfile(ProfileKey::TraceWholeCells);
|
||||
endProfile(ProfileKey::TraceWholeCells);
|
||||
|
||||
maybeStartProfile(ProfileKey::TraceGenericEntries);
|
||||
startProfile(ProfileKey::TraceGenericEntries);
|
||||
sb.traceGenericEntries(&mover);
|
||||
maybeEndProfile(ProfileKey::TraceGenericEntries);
|
||||
endProfile(ProfileKey::TraceGenericEntries);
|
||||
|
||||
maybeStartProfile(ProfileKey::MarkRuntime);
|
||||
startProfile(ProfileKey::MarkRuntime);
|
||||
rt->gc.traceRuntimeForMinorGC(&mover, session.lock);
|
||||
maybeEndProfile(ProfileKey::MarkRuntime);
|
||||
endProfile(ProfileKey::MarkRuntime);
|
||||
|
||||
maybeStartProfile(ProfileKey::MarkDebugger);
|
||||
startProfile(ProfileKey::MarkDebugger);
|
||||
{
|
||||
gcstats::AutoPhase ap(rt->gc.stats(), gcstats::PhaseKind::MARK_ROOTS);
|
||||
Debugger::traceAllForMovingGC(&mover);
|
||||
}
|
||||
maybeEndProfile(ProfileKey::MarkDebugger);
|
||||
endProfile(ProfileKey::MarkDebugger);
|
||||
|
||||
maybeStartProfile(ProfileKey::ClearNewObjectCache);
|
||||
startProfile(ProfileKey::ClearNewObjectCache);
|
||||
rt->caches().newObjectCache.clearNurseryObjects(rt);
|
||||
maybeEndProfile(ProfileKey::ClearNewObjectCache);
|
||||
endProfile(ProfileKey::ClearNewObjectCache);
|
||||
|
||||
// Most of the work is done here. This loop iterates over objects that have
|
||||
// been moved to the major heap. If these objects have any outgoing pointers
|
||||
// to the nursery, then those nursery objects get moved as well, until no
|
||||
// objects are left to move. That is, we iterate to a fixed point.
|
||||
maybeStartProfile(ProfileKey::CollectToFP);
|
||||
startProfile(ProfileKey::CollectToFP);
|
||||
collectToFixedPoint(mover, tenureCounts);
|
||||
maybeEndProfile(ProfileKey::CollectToFP);
|
||||
endProfile(ProfileKey::CollectToFP);
|
||||
|
||||
// Sweep compartments to update the array buffer object's view lists.
|
||||
maybeStartProfile(ProfileKey::SweepArrayBufferViewList);
|
||||
startProfile(ProfileKey::SweepArrayBufferViewList);
|
||||
for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next())
|
||||
c->sweepAfterMinorGC(&mover);
|
||||
maybeEndProfile(ProfileKey::SweepArrayBufferViewList);
|
||||
endProfile(ProfileKey::SweepArrayBufferViewList);
|
||||
|
||||
// Update any slot or element pointers whose destination has been tenured.
|
||||
maybeStartProfile(ProfileKey::UpdateJitActivations);
|
||||
startProfile(ProfileKey::UpdateJitActivations);
|
||||
js::jit::UpdateJitActivationsForMinorGC(rt, &mover);
|
||||
forwardedBuffers.finish();
|
||||
maybeEndProfile(ProfileKey::UpdateJitActivations);
|
||||
endProfile(ProfileKey::UpdateJitActivations);
|
||||
|
||||
maybeStartProfile(ProfileKey::ObjectsTenuredCallback);
|
||||
startProfile(ProfileKey::ObjectsTenuredCallback);
|
||||
rt->gc.callObjectsTenuredCallback();
|
||||
maybeEndProfile(ProfileKey::ObjectsTenuredCallback);
|
||||
endProfile(ProfileKey::ObjectsTenuredCallback);
|
||||
|
||||
// Sweep.
|
||||
maybeStartProfile(ProfileKey::FreeMallocedBuffers);
|
||||
startProfile(ProfileKey::FreeMallocedBuffers);
|
||||
freeMallocedBuffers();
|
||||
maybeEndProfile(ProfileKey::FreeMallocedBuffers);
|
||||
endProfile(ProfileKey::FreeMallocedBuffers);
|
||||
|
||||
maybeStartProfile(ProfileKey::Sweep);
|
||||
startProfile(ProfileKey::Sweep);
|
||||
sweep();
|
||||
maybeEndProfile(ProfileKey::Sweep);
|
||||
endProfile(ProfileKey::Sweep);
|
||||
|
||||
maybeStartProfile(ProfileKey::ClearStoreBuffer);
|
||||
startProfile(ProfileKey::ClearStoreBuffer);
|
||||
runtime()->gc.storeBuffer().clear();
|
||||
maybeEndProfile(ProfileKey::ClearStoreBuffer);
|
||||
endProfile(ProfileKey::ClearStoreBuffer);
|
||||
|
||||
// Make sure hashtables have been updated after the collection.
|
||||
maybeStartProfile(ProfileKey::CheckHashTables);
|
||||
startProfile(ProfileKey::CheckHashTables);
|
||||
#ifdef JS_GC_ZEAL
|
||||
if (rt->hasZealMode(ZealMode::CheckHashTablesOnMinorGC))
|
||||
CheckHashTablesAfterMovingGC(rt);
|
||||
#endif
|
||||
maybeEndProfile(ProfileKey::CheckHashTables);
|
||||
endProfile(ProfileKey::CheckHashTables);
|
||||
|
||||
// Calculate and return the promotion rate.
|
||||
return mover.tenuredSize / double(initialNurserySize);
|
||||
|
@ -276,7 +276,6 @@ class Nursery
|
||||
void clearMinorGCRequest() { minorGCTriggerReason_ = JS::gcreason::NO_REASON; }
|
||||
|
||||
bool enableProfiling() const { return enableProfiling_; }
|
||||
bool trackTimings() const { return trackTimings_; }
|
||||
|
||||
private:
|
||||
/* The amount of space in the mapped nursery available to allocations. */
|
||||
@ -323,12 +322,6 @@ class Nursery
|
||||
mozilla::TimeDuration profileThreshold_;
|
||||
bool enableProfiling_;
|
||||
|
||||
/*
|
||||
* Track timings if either enableProfiling_ or the Gecko profiler is
|
||||
* compiled in.
|
||||
*/
|
||||
bool trackTimings_;
|
||||
|
||||
/* Report ObjectGroups with at lest this many instances tenured. */
|
||||
int64_t reportTenurings_;
|
||||
|
||||
@ -476,8 +469,6 @@ class Nursery
|
||||
void maybeClearProfileDurations();
|
||||
void startProfile(ProfileKey key);
|
||||
void endProfile(ProfileKey key);
|
||||
void maybeStartProfile(ProfileKey key);
|
||||
void maybeEndProfile(ProfileKey key);
|
||||
static void printProfileDurations(const ProfileDurations& times);
|
||||
|
||||
friend class TenuringTracer;
|
||||
|
@ -179,7 +179,7 @@ Zone::sweepWeakMaps()
|
||||
}
|
||||
|
||||
void
|
||||
Zone::discardJitCode(FreeOp* fop, bool discardBaselineCode, bool addMarkers)
|
||||
Zone::discardJitCode(FreeOp* fop, bool discardBaselineCode)
|
||||
{
|
||||
if (!jitZone())
|
||||
return;
|
||||
@ -202,7 +202,7 @@ Zone::discardJitCode(FreeOp* fop, bool discardBaselineCode, bool addMarkers)
|
||||
jit::InvalidateAll(fop, this);
|
||||
|
||||
for (auto script = cellIter<JSScript>(); !script.done(); script.next()) {
|
||||
jit::FinishInvalidation(fop, script, addMarkers);
|
||||
jit::FinishInvalidation(fop, script);
|
||||
|
||||
/*
|
||||
* Discard baseline script if it's not marked as active. Note that
|
||||
|
@ -174,7 +174,7 @@ struct Zone : public JS::shadow::Zone,
|
||||
|
||||
void findOutgoingEdges(js::gc::ZoneComponentFinder& finder);
|
||||
|
||||
void discardJitCode(js::FreeOp* fop, bool discardBaselineCode = true, bool addMarkers = true);
|
||||
void discardJitCode(js::FreeOp* fop, bool discardBaselineCode = true);
|
||||
|
||||
void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
|
||||
size_t* typePool,
|
||||
|
41
js/src/jit-test/tests/coverage/bug1378068.js
Normal file
41
js/src/jit-test/tests/coverage/bug1378068.js
Normal file
@ -0,0 +1,41 @@
|
||||
m = {
|
||||
i() {},
|
||||
n() {},
|
||||
d() {},
|
||||
n() {},
|
||||
n() {},
|
||||
n() {},
|
||||
s() {}
|
||||
};
|
||||
function c()
|
||||
function ()
|
||||
function ()
|
||||
function ()
|
||||
function ()[{
|
||||
f() {}
|
||||
}, {
|
||||
v() {}
|
||||
}, {
|
||||
n() {}
|
||||
}, {
|
||||
v() {}
|
||||
}, {
|
||||
f() {}
|
||||
}, {
|
||||
n() {}
|
||||
}, {
|
||||
n() {}
|
||||
}, {
|
||||
n() {}
|
||||
}, {
|
||||
n() {}
|
||||
}, {
|
||||
v() {}
|
||||
}, {
|
||||
n() {}
|
||||
}, {
|
||||
n() {}
|
||||
}];
|
||||
t = function () {};
|
||||
getLcovInfo();
|
||||
relazifyFunctions();
|
34
js/src/jit-test/tests/ion/bug1370922.js
Normal file
34
js/src/jit-test/tests/ion/bug1370922.js
Normal file
@ -0,0 +1,34 @@
|
||||
function f(y) {
|
||||
return Math.min(0, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8,
|
||||
9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,
|
||||
9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,
|
||||
9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,
|
||||
9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6,
|
||||
8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6,
|
||||
8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6,
|
||||
8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6,
|
||||
8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6,
|
||||
8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6,
|
||||
8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6,
|
||||
8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6,
|
||||
8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6,
|
||||
8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6,
|
||||
8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6,
|
||||
7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5,
|
||||
6, 7, 8, 9);
|
||||
}
|
||||
|
||||
function g() {
|
||||
return f({});
|
||||
}
|
||||
|
||||
x = 0
|
||||
|
||||
for (var j = 0; j < 3000; j++) {
|
||||
g([j]);
|
||||
|
||||
if (inIon())
|
||||
break;
|
||||
}
|
@ -519,29 +519,6 @@ jit::FinishOffThreadBuilder(JSRuntime* runtime, IonBuilder* builder,
|
||||
FreeIonBuilder(builder);
|
||||
}
|
||||
|
||||
static void
|
||||
MarkJitProfilerEvent(JSRuntime* rt, JSScript* script, const char* event)
|
||||
{
|
||||
if (rt->geckoProfiler().enabled()) {
|
||||
// Register event with profiler.
|
||||
// Format of event payload string:
|
||||
// "<filename>:<lineno>"
|
||||
|
||||
// Get the script filename, if any, and its length.
|
||||
const char* filename = script->filename();
|
||||
if (filename == nullptr)
|
||||
filename = "<unknown>";
|
||||
|
||||
// Construct the descriptive string.
|
||||
UniqueChars buf = JS_smprintf("Invalidate %s:%" PRIuSIZE, filename, script->lineno());
|
||||
|
||||
// Ignore the event on allocation failure.
|
||||
if (buf) {
|
||||
rt->geckoProfiler().markEvent(buf.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
LinkCodeGen(JSContext* cx, IonBuilder* builder, CodeGenerator *codegen)
|
||||
{
|
||||
@ -554,8 +531,6 @@ LinkCodeGen(JSContext* cx, IonBuilder* builder, CodeGenerator *codegen)
|
||||
if (!codegen->link(cx, builder->constraints()))
|
||||
return false;
|
||||
|
||||
MarkJitProfilerEvent(cx->runtime(), script, "Ion compilation finished");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3184,8 +3159,6 @@ jit::Invalidate(TypeZone& types, FreeOp* fop,
|
||||
JitSpew(JitSpew_IonInvalidate, " Invalidate %s:%" PRIuSIZE ", IonScript %p",
|
||||
co->script()->filename(), co->script()->lineno(), co->ion());
|
||||
|
||||
MarkJitProfilerEvent(fop->runtime(), co->script(), "Invalidate");
|
||||
|
||||
// Keep the ion script alive during the invalidation and flag this
|
||||
// ionScript as being invalidated. This increment is removed by the
|
||||
// loop after the calls to InvalidateActivation.
|
||||
@ -3266,6 +3239,25 @@ jit::Invalidate(JSContext* cx, JSScript* script, bool resetUses, bool cancelOffT
|
||||
{
|
||||
MOZ_ASSERT(script->hasIonScript());
|
||||
|
||||
if (cx->runtime()->geckoProfiler().enabled()) {
|
||||
// Register invalidation with profiler.
|
||||
// Format of event payload string:
|
||||
// "<filename>:<lineno>"
|
||||
|
||||
// Get the script filename, if any, and its length.
|
||||
const char* filename = script->filename();
|
||||
if (filename == nullptr)
|
||||
filename = "<unknown>";
|
||||
|
||||
// Construct the descriptive string.
|
||||
UniqueChars buf = JS_smprintf("Invalidate %s:%" PRIuSIZE, filename, script->lineno());
|
||||
|
||||
// Ignore the event on allocation failure.
|
||||
if (buf) {
|
||||
cx->runtime()->geckoProfiler().markEvent(buf.get());
|
||||
}
|
||||
}
|
||||
|
||||
// RecompileInfoVector has inline space for at least one element.
|
||||
RecompileInfoVector scripts;
|
||||
MOZ_ASSERT(script->hasIonScript());
|
||||
@ -3276,7 +3268,7 @@ jit::Invalidate(JSContext* cx, JSScript* script, bool resetUses, bool cancelOffT
|
||||
}
|
||||
|
||||
static void
|
||||
FinishInvalidationOf(FreeOp* fop, JSScript* script, IonScript* ionScript, bool addMarker)
|
||||
FinishInvalidationOf(FreeOp* fop, JSScript* script, IonScript* ionScript)
|
||||
{
|
||||
TypeZone& types = script->zone()->types;
|
||||
|
||||
@ -3289,20 +3281,16 @@ FinishInvalidationOf(FreeOp* fop, JSScript* script, IonScript* ionScript, bool a
|
||||
// true. In this case we have to wait until destroying it.
|
||||
if (!ionScript->invalidated())
|
||||
jit::IonScript::Destroy(fop, ionScript);
|
||||
|
||||
// Register invalidation with profiler, if appropriate.
|
||||
if (addMarker)
|
||||
MarkJitProfilerEvent(fop->runtime(), script, "Invalidate (GC)");
|
||||
}
|
||||
|
||||
void
|
||||
jit::FinishInvalidation(FreeOp* fop, JSScript* script, bool addMarker)
|
||||
jit::FinishInvalidation(FreeOp* fop, JSScript* script)
|
||||
{
|
||||
// In all cases, nullptr out script->ion to avoid re-entry.
|
||||
if (script->hasIonScript()) {
|
||||
IonScript* ion = script->ionScript();
|
||||
script->setIonScript(nullptr, nullptr);
|
||||
FinishInvalidationOf(fop, script, ion, addMarker);
|
||||
FinishInvalidationOf(fop, script, ion);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3318,8 +3306,6 @@ jit::ForbidCompilation(JSContext* cx, JSScript* script)
|
||||
Invalidate(cx, script, false);
|
||||
|
||||
script->setIonScript(cx->runtime(), ION_DISABLED_SCRIPT);
|
||||
|
||||
MarkJitProfilerEvent(cx->runtime(), script, "Ion compilation disabled");
|
||||
}
|
||||
|
||||
AutoFlushICache*
|
||||
|
@ -628,7 +628,7 @@ class JitCompartment
|
||||
|
||||
// Called from JSCompartment::discardJitCode().
|
||||
void InvalidateAll(FreeOp* fop, JS::Zone* zone);
|
||||
void FinishInvalidation(FreeOp* fop, JSScript* script, bool addMarker);
|
||||
void FinishInvalidation(FreeOp* fop, JSScript* script);
|
||||
|
||||
// On windows systems, really large frames need to be incrementally touched.
|
||||
// The following constant defines the minimum increment of the touch.
|
||||
|
@ -1471,7 +1471,9 @@ IonBuilder::inlineMathMinMax(CallInfo& callInfo, bool max)
|
||||
current->add(last);
|
||||
|
||||
for (unsigned i = 2; i < cases.length(); i++) {
|
||||
MMinMax* ins = MMinMax::New(alloc(), last, cases[i], returnType, max);
|
||||
MMinMax* ins = MMinMax::New(alloc().fallible(), last, cases[i], returnType, max);
|
||||
if (!ins)
|
||||
return abort(AbortReason::Alloc);
|
||||
current->add(ins);
|
||||
last = ins;
|
||||
}
|
||||
|
@ -85,6 +85,7 @@ JSCompartment::JSCompartment(Zone* zone, const JS::CompartmentOptions& options =
|
||||
randomKeyGenerator_(runtime_->forkRandomKeyGenerator()),
|
||||
watchpointMap(nullptr),
|
||||
scriptCountsMap(nullptr),
|
||||
scriptNameMap(nullptr),
|
||||
debugScriptMap(nullptr),
|
||||
debugEnvs(nullptr),
|
||||
enumerators(nullptr),
|
||||
@ -115,6 +116,7 @@ JSCompartment::~JSCompartment()
|
||||
js_delete(jitCompartment_);
|
||||
js_delete(watchpointMap);
|
||||
js_delete(scriptCountsMap);
|
||||
js_delete(scriptNameMap);
|
||||
js_delete(debugScriptMap);
|
||||
js_delete(debugEnvs);
|
||||
js_delete(objectMetadataTable);
|
||||
@ -810,6 +812,7 @@ JSCompartment::finishRoots()
|
||||
objectMetadataTable->clear();
|
||||
|
||||
clearScriptCounts();
|
||||
clearScriptNames();
|
||||
|
||||
if (nonSyntacticLexicalEnvironments_)
|
||||
nonSyntacticLexicalEnvironments_->clear();
|
||||
@ -1008,6 +1011,14 @@ JSCompartment::fixupScriptMapsAfterMovingGC()
|
||||
}
|
||||
}
|
||||
|
||||
if (scriptNameMap) {
|
||||
for (ScriptNameMap::Enum e(*scriptNameMap); !e.empty(); e.popFront()) {
|
||||
JSScript* script = e.front().key();
|
||||
if (!IsAboutToBeFinalizedUnbarriered(&script) && script != e.front().key())
|
||||
e.rekeyFront(script);
|
||||
}
|
||||
}
|
||||
|
||||
if (debugScriptMap) {
|
||||
for (DebugScriptMap::Enum e(*debugScriptMap); !e.empty(); e.popFront()) {
|
||||
JSScript* script = e.front().key();
|
||||
@ -1030,6 +1041,15 @@ JSCompartment::checkScriptMapsAfterMovingGC()
|
||||
}
|
||||
}
|
||||
|
||||
if (scriptNameMap) {
|
||||
for (auto r = scriptNameMap->all(); !r.empty(); r.popFront()) {
|
||||
JSScript* script = r.front().key();
|
||||
CheckGCThingAfterMovingGC(script);
|
||||
auto ptr = scriptNameMap->lookup(script);
|
||||
MOZ_RELEASE_ASSERT(ptr.found() && &*ptr == &r.front());
|
||||
}
|
||||
}
|
||||
|
||||
if (debugScriptMap) {
|
||||
for (auto r = debugScriptMap->all(); !r.empty(); r.popFront()) {
|
||||
JSScript* script = r.front().key();
|
||||
@ -1274,6 +1294,7 @@ JSCompartment::updateDebuggerObservesCoverage()
|
||||
return;
|
||||
|
||||
clearScriptCounts();
|
||||
clearScriptNames();
|
||||
}
|
||||
|
||||
bool
|
||||
@ -1315,6 +1336,19 @@ JSCompartment::clearScriptCounts()
|
||||
scriptCountsMap = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
JSCompartment::clearScriptNames()
|
||||
{
|
||||
if (!scriptNameMap)
|
||||
return;
|
||||
|
||||
for (ScriptNameMap::Range r = scriptNameMap->all(); !r.empty(); r.popFront())
|
||||
js_delete(r.front().value());
|
||||
|
||||
js_delete(scriptNameMap);
|
||||
scriptNameMap = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
JSCompartment::clearBreakpointsIn(FreeOp* fop, js::Debugger* dbg, HandleObject handler)
|
||||
{
|
||||
|
@ -1090,6 +1090,7 @@ struct JSCompartment
|
||||
bool collectCoverageForDebug() const;
|
||||
bool collectCoverageForPGO() const;
|
||||
void clearScriptCounts();
|
||||
void clearScriptNames();
|
||||
|
||||
bool needsDelazificationForDebugger() const {
|
||||
return debugModeBits & DebuggerNeedsDelazification;
|
||||
@ -1116,6 +1117,7 @@ struct JSCompartment
|
||||
js::WatchpointMap* watchpointMap;
|
||||
|
||||
js::ScriptCountsMap* scriptCountsMap;
|
||||
js::ScriptNameMap* scriptNameMap;
|
||||
|
||||
js::DebugScriptMap* debugScriptMap;
|
||||
|
||||
|
@ -7315,6 +7315,30 @@ gc::MergeCompartments(JSCompartment* source, JSCompartment* target)
|
||||
|
||||
// Atoms which are marked in source's zone are now marked in target's zone.
|
||||
cx->atomMarking().adoptMarkedAtoms(target->zone(), source->zone());
|
||||
|
||||
// Merge script name maps in the target compartment's map.
|
||||
if (cx->runtime()->lcovOutput().isEnabled() && source->scriptNameMap) {
|
||||
AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||
|
||||
if (!target->scriptNameMap) {
|
||||
target->scriptNameMap = cx->new_<ScriptNameMap>();
|
||||
|
||||
if (!target->scriptNameMap)
|
||||
oomUnsafe.crash("Failed to create a script name map.");
|
||||
|
||||
if (!target->scriptNameMap->init())
|
||||
oomUnsafe.crash("Failed to initialize a script name map.");
|
||||
}
|
||||
|
||||
for (ScriptNameMap::Range r = source->scriptNameMap->all(); !r.empty(); r.popFront()) {
|
||||
JSScript* key = r.front().key();
|
||||
const char* value = r.front().value();
|
||||
if (!target->scriptNameMap->putNew(key, value))
|
||||
oomUnsafe.crash("Failed to add an entry in the script name map.");
|
||||
}
|
||||
|
||||
source->scriptNameMap->clear();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -7416,14 +7440,14 @@ void PreventGCDuringInteractiveDebug()
|
||||
#endif
|
||||
|
||||
void
|
||||
js::ReleaseAllJITCode(FreeOp* fop, bool addMarkers)
|
||||
js::ReleaseAllJITCode(FreeOp* fop)
|
||||
{
|
||||
js::CancelOffThreadIonCompile(fop->runtime());
|
||||
|
||||
JSRuntime::AutoProhibitActiveContextChange apacc(fop->runtime());
|
||||
for (ZonesIter zone(fop->runtime(), SkipAtoms); !zone.done(); zone.next()) {
|
||||
zone->setPreservingCode(false);
|
||||
zone->discardJitCode(fop, /* discardBaselineCode = */ true, addMarkers);
|
||||
zone->discardJitCode(fop);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -837,7 +837,7 @@ extern void
|
||||
TraceRuntime(JSTracer* trc);
|
||||
|
||||
extern void
|
||||
ReleaseAllJITCode(FreeOp* op, bool addMarkers = true);
|
||||
ReleaseAllJITCode(FreeOp* op);
|
||||
|
||||
extern void
|
||||
PrepareForDebugGC(JSRuntime* rt);
|
||||
|
@ -2966,7 +2966,6 @@ GenerateLcovInfo(JSContext* cx, JSCompartment* comp, GenericPrinter& out)
|
||||
coverage::LCovCompartment compCover;
|
||||
for (JSScript* topLevel: topScripts) {
|
||||
RootedScript topScript(cx, topLevel);
|
||||
compCover.collectSourceFile(comp, &topScript->scriptSourceUnwrap());
|
||||
|
||||
// We found the top-level script, visit all the functions reachable
|
||||
// from the top-level function, and delazify them.
|
||||
@ -2978,7 +2977,18 @@ GenerateLcovInfo(JSContext* cx, JSCompartment* comp, GenericPrinter& out)
|
||||
RootedFunction fun(cx);
|
||||
do {
|
||||
script = queue.popCopy();
|
||||
compCover.collectCodeCoverageInfo(comp, script->sourceObject(), script);
|
||||
bool createdScriptName = false;
|
||||
if (!script->hasScriptName()) {
|
||||
createdScriptName = true;
|
||||
if (!script->initScriptName(cx))
|
||||
return false;
|
||||
}
|
||||
|
||||
compCover.collectCodeCoverageInfo(comp, script);
|
||||
|
||||
// Destroy the script name if we have created it in this function.
|
||||
if (createdScriptName)
|
||||
script->destroyScriptName();
|
||||
|
||||
// Iterate from the last to the first object in order to have
|
||||
// the functions them visited in the opposite order when popping
|
||||
|
@ -1159,6 +1159,15 @@ static inline ScriptCountsMap::Ptr GetScriptCountsMapEntry(JSScript* script)
|
||||
return p;
|
||||
}
|
||||
|
||||
static inline ScriptNameMap::Ptr
|
||||
GetScriptNameMapEntry(JSScript* script)
|
||||
{
|
||||
ScriptNameMap* map = script->compartment()->scriptNameMap;
|
||||
auto p = map->lookup(script);
|
||||
MOZ_ASSERT(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
ScriptCounts&
|
||||
JSScript::getScriptCounts()
|
||||
{
|
||||
@ -1166,6 +1175,13 @@ JSScript::getScriptCounts()
|
||||
return *p->value();
|
||||
}
|
||||
|
||||
const char*
|
||||
JSScript::getScriptName()
|
||||
{
|
||||
auto p = GetScriptNameMapEntry(this);
|
||||
return p->value();
|
||||
}
|
||||
|
||||
js::PCCounts*
|
||||
ScriptCounts::maybeGetPCCounts(size_t offset) {
|
||||
PCCounts searched = PCCounts(offset);
|
||||
@ -1347,6 +1363,24 @@ JSScript::destroyScriptCounts(FreeOp* fop)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
JSScript::destroyScriptName()
|
||||
{
|
||||
auto p = GetScriptNameMapEntry(this);
|
||||
js_delete(p->value());
|
||||
compartment()->scriptNameMap->remove(p);
|
||||
}
|
||||
|
||||
bool
|
||||
JSScript::hasScriptName()
|
||||
{
|
||||
if (!compartment()->scriptNameMap)
|
||||
return false;
|
||||
|
||||
auto p = compartment()->scriptNameMap->lookup(this);
|
||||
return p.found();
|
||||
}
|
||||
|
||||
void
|
||||
ScriptSourceObject::trace(JSTracer* trc, JSObject* obj)
|
||||
{
|
||||
@ -1367,12 +1401,6 @@ ScriptSourceObject::finalize(FreeOp* fop, JSObject* obj)
|
||||
{
|
||||
MOZ_ASSERT(fop->onActiveCooperatingThread());
|
||||
ScriptSourceObject* sso = &obj->as<ScriptSourceObject>();
|
||||
|
||||
// If code coverage is enabled, record the filename associated with this
|
||||
// source object.
|
||||
if (fop->runtime()->lcovOutput().isEnabled())
|
||||
sso->compartment()->lcovOutput.collectSourceFile(sso->compartment(), sso);
|
||||
|
||||
sso->source()->decref();
|
||||
sso->setReservedSlot(SOURCE_SLOT, PrivateValue(nullptr));
|
||||
}
|
||||
@ -2666,6 +2694,8 @@ JSScript::Create(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
MOZ_ASSERT(script->getVersion() == options.version); // assert that no overflow occurred
|
||||
|
||||
script->setSourceObject(sourceObject);
|
||||
if (cx->runtime()->lcovOutput().isEnabled() && !script->initScriptName(cx))
|
||||
return nullptr;
|
||||
script->sourceStart_ = bufStart;
|
||||
script->sourceEnd_ = bufEnd;
|
||||
script->toStringStart_ = toStringStart;
|
||||
@ -2678,6 +2708,48 @@ JSScript::Create(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
return script;
|
||||
}
|
||||
|
||||
bool
|
||||
JSScript::initScriptName(JSContext* cx)
|
||||
{
|
||||
MOZ_ASSERT(!hasScriptName());
|
||||
|
||||
if (!filename())
|
||||
return true;
|
||||
|
||||
// Create compartment's scriptNameMap if necessary.
|
||||
ScriptNameMap* map = compartment()->scriptNameMap;
|
||||
if (!map) {
|
||||
map = cx->new_<ScriptNameMap>();
|
||||
if (!map) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!map->init()) {
|
||||
js_delete(map);
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
compartment()->scriptNameMap = map;
|
||||
}
|
||||
|
||||
char* name = js_strdup(filename());
|
||||
if (!name) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Register the script name in the compartment's map.
|
||||
if (!map->putNew(this, name)) {
|
||||
js_delete(name);
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline uint8_t*
|
||||
AllocScriptData(JS::Zone* zone, size_t size)
|
||||
{
|
||||
@ -3090,8 +3162,11 @@ JSScript::finalize(FreeOp* fop)
|
||||
|
||||
// Collect code coverage information for this script and all its inner
|
||||
// scripts, and store the aggregated information on the compartment.
|
||||
if (fop->runtime()->lcovOutput().isEnabled())
|
||||
compartment()->lcovOutput.collectCodeCoverageInfo(compartment(), sourceObject(), this);
|
||||
MOZ_ASSERT_IF(hasScriptName(), fop->runtime()->lcovOutput().isEnabled());
|
||||
if (fop->runtime()->lcovOutput().isEnabled() && hasScriptName()) {
|
||||
compartment()->lcovOutput.collectCodeCoverageInfo(compartment(), this);
|
||||
destroyScriptName();
|
||||
}
|
||||
|
||||
fop->runtime()->geckoProfiler().onScriptFinalized(this);
|
||||
|
||||
|
@ -240,6 +240,10 @@ typedef HashMap<JSScript*,
|
||||
ScriptCounts*,
|
||||
DefaultHasher<JSScript*>,
|
||||
SystemAllocPolicy> ScriptCountsMap;
|
||||
typedef HashMap<JSScript*,
|
||||
const char*,
|
||||
DefaultHasher<JSScript*>,
|
||||
SystemAllocPolicy> ScriptNameMap;
|
||||
|
||||
class DebugScript
|
||||
{
|
||||
@ -1419,6 +1423,7 @@ class JSScript : public js::gc::TenuredCell
|
||||
void setIsDefaultClassConstructor() { isDefaultClassConstructor_ = true; }
|
||||
|
||||
bool hasScriptCounts() const { return hasScriptCounts_; }
|
||||
bool hasScriptName();
|
||||
|
||||
bool hasFreezeConstraints() const { return hasFreezeConstraints_; }
|
||||
void setHasFreezeConstraints() { hasFreezeConstraints_ = true; }
|
||||
@ -1783,7 +1788,9 @@ class JSScript : public js::gc::TenuredCell
|
||||
|
||||
public:
|
||||
bool initScriptCounts(JSContext* cx);
|
||||
bool initScriptName(JSContext* cx);
|
||||
js::ScriptCounts& getScriptCounts();
|
||||
const char* getScriptName();
|
||||
js::PCCounts* maybeGetPCCounts(jsbytecode* pc);
|
||||
const js::PCCounts* maybeGetThrowCounts(jsbytecode* pc);
|
||||
js::PCCounts* getThrowCounts(jsbytecode* pc);
|
||||
@ -1793,6 +1800,7 @@ class JSScript : public js::gc::TenuredCell
|
||||
js::jit::IonScriptCounts* getIonCounts();
|
||||
void releaseScriptCounts(js::ScriptCounts* counts);
|
||||
void destroyScriptCounts(js::FreeOp* fop);
|
||||
void destroyScriptName();
|
||||
// The entry should be removed after using this function.
|
||||
void takeOverScriptCountsMapEntry(js::ScriptCounts* entryValue);
|
||||
|
||||
|
@ -95,6 +95,9 @@ WrappedAsyncFunction(JSContext* cx, unsigned argc, Value* vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!cx->isExceptionPending())
|
||||
return false;
|
||||
|
||||
// Steps 1, 4.
|
||||
RootedValue exc(cx);
|
||||
if (!GetAndClearException(cx, &exc))
|
||||
|
@ -63,9 +63,8 @@
|
||||
namespace js {
|
||||
namespace coverage {
|
||||
|
||||
LCovSource::LCovSource(LifoAlloc* alloc, JSObject* sso)
|
||||
: source_(sso),
|
||||
outSF_(alloc),
|
||||
LCovSource::LCovSource(LifoAlloc* alloc, const char* name)
|
||||
: name_(name),
|
||||
outFN_(alloc),
|
||||
outFNDA_(alloc),
|
||||
numFunctionsFound_(0),
|
||||
@ -76,19 +75,40 @@ LCovSource::LCovSource(LifoAlloc* alloc, JSObject* sso)
|
||||
outDA_(alloc),
|
||||
numLinesInstrumented_(0),
|
||||
numLinesHit_(0),
|
||||
hasFilename_(false),
|
||||
hasTopLevelScript_(false)
|
||||
{
|
||||
}
|
||||
|
||||
LCovSource::LCovSource(LCovSource&& src)
|
||||
: name_(src.name_),
|
||||
outFN_(src.outFN_),
|
||||
outFNDA_(src.outFNDA_),
|
||||
numFunctionsFound_(src.numFunctionsFound_),
|
||||
numFunctionsHit_(src.numFunctionsHit_),
|
||||
outBRDA_(src.outBRDA_),
|
||||
numBranchesFound_(src.numBranchesFound_),
|
||||
numBranchesHit_(src.numBranchesHit_),
|
||||
outDA_(src.outDA_),
|
||||
numLinesInstrumented_(src.numLinesInstrumented_),
|
||||
numLinesHit_(src.numLinesHit_),
|
||||
hasTopLevelScript_(src.hasTopLevelScript_)
|
||||
{
|
||||
src.name_ = nullptr;
|
||||
}
|
||||
|
||||
LCovSource::~LCovSource()
|
||||
{
|
||||
js_delete(name_);
|
||||
}
|
||||
|
||||
void
|
||||
LCovSource::exportInto(GenericPrinter& out) const
|
||||
{
|
||||
// Only write if everything got recorded.
|
||||
if (!hasFilename_ || !hasTopLevelScript_)
|
||||
if (!hasTopLevelScript_)
|
||||
return;
|
||||
|
||||
outSF_.exportInto(out);
|
||||
out.printf("SF:%s\n", name_);
|
||||
|
||||
outFN_.exportInto(out);
|
||||
outFNDA_.exportInto(out);
|
||||
@ -106,17 +126,6 @@ LCovSource::exportInto(GenericPrinter& out) const
|
||||
out.put("end_of_record\n");
|
||||
}
|
||||
|
||||
bool
|
||||
LCovSource::writeSourceFilename(ScriptSourceObject* sso)
|
||||
{
|
||||
outSF_.printf("SF:%s\n", sso->source()->filename());
|
||||
if (outSF_.hadOutOfMemory())
|
||||
return false;
|
||||
|
||||
hasFilename_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
LCovSource::writeScriptName(LSprinter& out, JSScript* script)
|
||||
{
|
||||
@ -404,8 +413,7 @@ LCovCompartment::LCovCompartment()
|
||||
}
|
||||
|
||||
void
|
||||
LCovCompartment::collectCodeCoverageInfo(JSCompartment* comp, JSObject* sso,
|
||||
JSScript* script)
|
||||
LCovCompartment::collectCodeCoverageInfo(JSCompartment* comp, JSScript* script)
|
||||
{
|
||||
// Skip any operation if we already some out-of memory issues.
|
||||
if (outTN_.hadOutOfMemory())
|
||||
@ -415,7 +423,7 @@ LCovCompartment::collectCodeCoverageInfo(JSCompartment* comp, JSObject* sso,
|
||||
return;
|
||||
|
||||
// Get the existing source LCov summary, or create a new one.
|
||||
LCovSource* source = lookupOrAdd(comp, sso);
|
||||
LCovSource* source = lookupOrAdd(comp, script->getScriptName());
|
||||
if (!source)
|
||||
return;
|
||||
|
||||
@ -426,31 +434,8 @@ LCovCompartment::collectCodeCoverageInfo(JSCompartment* comp, JSObject* sso,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LCovCompartment::collectSourceFile(JSCompartment* comp, ScriptSourceObject* sso)
|
||||
{
|
||||
// Do not add sources if there is no file name associated to it.
|
||||
if (!sso->source()->filename())
|
||||
return;
|
||||
|
||||
// Skip any operation if we already some out-of memory issues.
|
||||
if (outTN_.hadOutOfMemory())
|
||||
return;
|
||||
|
||||
// Get the existing source LCov summary, or create a new one.
|
||||
LCovSource* source = lookupOrAdd(comp, sso);
|
||||
if (!source)
|
||||
return;
|
||||
|
||||
// Write source filename into the LCovSource.
|
||||
if (!source->writeSourceFilename(sso)) {
|
||||
outTN_.reportOutOfMemory();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LCovSource*
|
||||
LCovCompartment::lookupOrAdd(JSCompartment* comp, JSObject* sso)
|
||||
LCovCompartment::lookupOrAdd(JSCompartment* comp, const char* name)
|
||||
{
|
||||
// On the first call, write the compartment name, and allocate a LCovSource
|
||||
// vector in the LifoAlloc.
|
||||
@ -468,13 +453,19 @@ LCovCompartment::lookupOrAdd(JSCompartment* comp, JSObject* sso)
|
||||
} else {
|
||||
// Find the first matching source.
|
||||
for (LCovSource& source : *sources_) {
|
||||
if (source.match(sso))
|
||||
if (source.match(name))
|
||||
return &source;
|
||||
}
|
||||
}
|
||||
|
||||
char* source_name = js_strdup(name);
|
||||
if (!source_name) {
|
||||
outTN_.reportOutOfMemory();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Allocate a new LCovSource for the current top-level.
|
||||
if (!sources_->append(Move(LCovSource(&alloc_, sso)))) {
|
||||
if (!sources_->append(Move(LCovSource(&alloc_, source_name)))) {
|
||||
outTN_.reportOutOfMemory();
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -28,16 +28,18 @@ class LCovCompartment;
|
||||
class LCovSource
|
||||
{
|
||||
public:
|
||||
explicit LCovSource(LifoAlloc* alloc, JSObject* sso);
|
||||
LCovSource(LifoAlloc* alloc, const char* name);
|
||||
LCovSource(LCovSource&& src);
|
||||
~LCovSource();
|
||||
|
||||
// Whether the given script source object matches this LCovSource.
|
||||
bool match(JSObject* sso) const {
|
||||
return sso == source_;
|
||||
// Whether the given script name matches this LCovSource.
|
||||
bool match(const char* name) const {
|
||||
return strcmp(name_, name) == 0;
|
||||
}
|
||||
|
||||
// Whether the current source is complete and if it can be flushed.
|
||||
bool isComplete() const {
|
||||
return hasFilename_ && hasTopLevelScript_;
|
||||
return hasTopLevelScript_;
|
||||
}
|
||||
|
||||
// Iterate over the bytecode and collect the lcov output based on the
|
||||
@ -48,19 +50,13 @@ class LCovSource
|
||||
// the runtime code coverage trace file.
|
||||
void exportInto(GenericPrinter& out) const;
|
||||
|
||||
// Write the script name in out.
|
||||
bool writeSourceFilename(ScriptSourceObject* sso);
|
||||
|
||||
private:
|
||||
// Write the script name in out.
|
||||
bool writeScriptName(LSprinter& out, JSScript* script);
|
||||
|
||||
private:
|
||||
// Weak pointer of the Script Source Object used by the current source.
|
||||
JSObject *source_;
|
||||
|
||||
// LifoAlloc string which hold the filename of the source.
|
||||
LSprinter outSF_;
|
||||
// Name of the source file.
|
||||
const char* name_;
|
||||
|
||||
// LifoAlloc strings which hold the filename of each function as
|
||||
// well as the number of hits for each function.
|
||||
@ -80,7 +76,6 @@ class LCovSource
|
||||
size_t numLinesHit_;
|
||||
|
||||
// Status flags.
|
||||
bool hasFilename_ : 1;
|
||||
bool hasTopLevelScript_ : 1;
|
||||
};
|
||||
|
||||
@ -90,10 +85,7 @@ class LCovCompartment
|
||||
LCovCompartment();
|
||||
|
||||
// Collect code coverage information for the given source.
|
||||
void collectCodeCoverageInfo(JSCompartment* comp, JSObject* sso, JSScript* topLevel);
|
||||
|
||||
// Create an ebtry for the current ScriptSourceObject.
|
||||
void collectSourceFile(JSCompartment* comp, ScriptSourceObject* sso);
|
||||
void collectCodeCoverageInfo(JSCompartment* comp, JSScript* topLevel);
|
||||
|
||||
// Write the Lcov output in a buffer, such as the one associated with
|
||||
// the runtime code coverage trace file.
|
||||
@ -104,7 +96,7 @@ class LCovCompartment
|
||||
bool writeCompartmentName(JSCompartment* comp);
|
||||
|
||||
// Return the LCovSource entry which matches the given ScriptSourceObject.
|
||||
LCovSource* lookupOrAdd(JSCompartment* comp, JSObject* sso);
|
||||
LCovSource* lookupOrAdd(JSCompartment* comp, const char* name);
|
||||
|
||||
private:
|
||||
typedef mozilla::Vector<LCovSource, 16, LifoAllocPolicy<Fallible>> LCovSourceVector;
|
||||
|
@ -99,12 +99,9 @@ GeckoProfiler::enable(bool enabled)
|
||||
|
||||
/*
|
||||
* Ensure all future generated code will be instrumented, or that all
|
||||
* currently instrumented code is discarded.
|
||||
*
|
||||
* We don't add markers, because that makes us call back into the profiler,
|
||||
* which leads to deadlock on the profiler's main mutex.
|
||||
* currently instrumented code is discarded
|
||||
*/
|
||||
ReleaseAllJITCode(rt->defaultFreeOp(), /* addMarkers = */ false);
|
||||
ReleaseAllJITCode(rt->defaultFreeOp());
|
||||
|
||||
// This function is called when the Gecko profiler makes a new Sampler
|
||||
// (and thus, a new circular buffer). Set all current entries in the
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user