MozReview-Commit-ID: 77Uz3uceUmk
This commit is contained in:
Wes Kocher 2017-08-31 16:56:23 -07:00
Родитель 6bad4f8ef7 e9c837e8b6
Коммит 6472928439
50 изменённых файлов: 794 добавлений и 543 удалений

Просмотреть файл

@ -64,10 +64,10 @@ var shutdown = Task.async(function* () {
// This is what makes the sidebar widget able to load/unload the panel.
function setPanel(panel) {
return startup(panel).catch(e => console.error(e));
return startup(panel).catch(console.error);
}
function destroy() {
return shutdown().catch(e => console.error(e));
return shutdown().catch(console.error);
}
/**
@ -261,7 +261,7 @@ var AnimationsController = {
return this.animationsFront.toggleAll()
.then(() => this.emit(this.ALL_ANIMATIONS_TOGGLED_EVENT, this))
.catch(e => console.error(e));
.catch(console.error);
},
/**

Просмотреть файл

@ -179,9 +179,9 @@ var AnimationsPanel = {
// the page if the selected node does not have any animation on it.
if (event.keyCode === KeyCodes.DOM_VK_SPACE) {
if (AnimationsController.animationPlayers.length > 0) {
this.playPauseTimeline().catch(ex => console.error(ex));
this.playPauseTimeline().catch(console.error);
} else {
this.toggleAll().catch(ex => console.error(ex));
this.toggleAll().catch(console.error);
}
event.preventDefault();
}
@ -208,7 +208,7 @@ var AnimationsPanel = {
},
onToggleAllClicked: function () {
this.toggleAll().catch(ex => console.error(ex));
this.toggleAll().catch(console.error);
},
/**
@ -221,7 +221,7 @@ var AnimationsPanel = {
}),
onTimelinePlayClicked: function () {
this.playPauseTimeline().catch(ex => console.error(ex));
this.playPauseTimeline().catch(console.error);
},
/**
@ -241,7 +241,7 @@ var AnimationsPanel = {
},
onTimelineRewindClicked: function () {
this.rewindTimeline().catch(ex => console.error(ex));
this.rewindTimeline().catch(console.error);
},
/**
@ -263,7 +263,7 @@ var AnimationsPanel = {
onRateChanged: function (e, rate) {
AnimationsController.setPlaybackRateAll(rate)
.then(() => this.refreshAnimationsStateAndUI())
.catch(ex => console.error(ex));
.catch(console.error);
},
onTabNavigated: function () {
@ -289,7 +289,7 @@ var AnimationsPanel = {
if (isUserDrag && !this.setCurrentTimeAllPromise) {
this.setCurrentTimeAllPromise =
AnimationsController.setCurrentTimeAll(time, true)
.catch(error => console.error(error))
.catch(console.error)
.then(() => {
this.setCurrentTimeAllPromise = null;
});

Просмотреть файл

@ -288,7 +288,7 @@ var CallsListView = Heritage.extend(WidgetMethods, {
frameSnapshot.generateScreenshotFor(functionCall).then(screenshot => {
this.showScreenshot(screenshot);
this.highlightedThumbnail = screenshot.index;
}).catch(e => console.error(e));
}).catch(console.error);
});
},

Просмотреть файл

@ -302,14 +302,14 @@ BoxModel.prototype = {
properties[0].name = property.substring(9);
}
session.setProperties(properties).catch(e => console.error(e));
session.setProperties(properties).catch(console.error);
},
done: (value, commit) => {
editor.elt.parentNode.classList.remove("boxmodel-editing");
if (!commit) {
session.revert().then(() => {
session.destroy();
}, e => console.error(e));
}, console.error);
return;
}
@ -322,7 +322,7 @@ BoxModel.prototype = {
autoMargins: true,
}).then(layout => {
this.store.dispatch(updateLayout(layout));
}, e => console.error(e));
}, console.error);
},
cssProperties: getCssProperties(this.inspector.toolbox)
}, event);

Просмотреть файл

@ -509,7 +509,7 @@ CssComputedView.prototype = {
);
this._refreshProcess.schedule();
});
}).catch((err) => console.error(err));
}).catch(console.error);
},
/**

Просмотреть файл

@ -58,7 +58,7 @@ exports.items = [{
}],
exec: function* (args, context) {
if (args.hide) {
context.updateExec("eyedropper_server_hide").catch(e => console.error(e));
context.updateExec("eyedropper_server_hide").catch(console.error);
return;
}
@ -74,7 +74,7 @@ exports.items = [{
let telemetry = new Telemetry();
telemetry.toolOpened(args.frommenu ? "menueyedropper" : "eyedropper");
context.updateExec("eyedropper_server").catch(e => console.error(e));
context.updateExec("eyedropper_server").catch(console.error);
}
}, {
item: "command",

Просмотреть файл

@ -72,7 +72,7 @@ InspectorSearch.prototype = {
_onSearch: function (reverse = false) {
this.doFullTextSearch(this.searchBox.value, reverse)
.catch(e => console.error(e));
.catch(console.error);
},
doFullTextSearch: Task.async(function* (query, reverse) {

Просмотреть файл

@ -224,13 +224,13 @@ Inspector.prototype = {
return promise.all([
this._target.actorHasMethod("domwalker", "duplicateNode").then(value => {
this._supportsDuplicateNode = value;
}).catch(e => console.error(e)),
}).catch(console.error),
this._target.actorHasMethod("domnode", "scrollIntoView").then(value => {
this._supportsScrollIntoView = value;
}).catch(e => console.error(e)),
}).catch(console.error),
this._target.actorHasMethod("inspector", "resolveRelativeURL").then(value => {
this._supportsResolveRelativeURL = value;
}).catch(e => console.error(e)),
}).catch(console.error),
]);
});
},
@ -1627,7 +1627,7 @@ Inspector.prototype = {
this.eyeDropperButton.classList.add("checked");
this.startEyeDropperListeners();
return this.inspector.pickColorFromPage(this.toolbox, {copyOnSelect: true})
.catch(e => console.error(e));
.catch(console.error);
},
/**
@ -1644,7 +1644,7 @@ Inspector.prototype = {
this.eyeDropperButton.classList.remove("checked");
this.stopEyeDropperListeners();
return this.inspector.cancelPickColorFromPage()
.catch(e => console.error(e));
.catch(console.error);
},
/**
@ -1839,7 +1839,7 @@ Inspector.prototype = {
_copyLongString: function (longStringActorPromise) {
return this._getLongString(longStringActorPromise).then(string => {
clipboardHelper.copyString(string);
}).catch(e => console.error(e));
}).catch(console.error);
},
/**
@ -1851,10 +1851,10 @@ Inspector.prototype = {
_getLongString: function (longStringActorPromise) {
return longStringActorPromise.then(longStringActor => {
return longStringActor.string().then(string => {
longStringActor.release().catch(e => console.error(e));
longStringActor.release().catch(console.error);
return string;
});
}).catch(e => console.error(e));
}).catch(console.error);
},
/**
@ -1868,7 +1868,7 @@ Inspector.prototype = {
this.telemetry.toolOpened("copyuniquecssselector");
this.selection.nodeFront.getUniqueSelector().then(selector => {
clipboardHelper.copyString(selector);
}).catch(e => console.error);
}).catch(console.error);
},
/**
@ -1882,7 +1882,7 @@ Inspector.prototype = {
this.telemetry.toolOpened("copyfullcssselector");
this.selection.nodeFront.getCssPath().then(path => {
clipboardHelper.copyString(path);
}).catch(e => console.error);
}).catch(console.error);
},
/**
@ -1896,7 +1896,7 @@ Inspector.prototype = {
this.telemetry.toolOpened("copyxpath");
this.selection.nodeFront.getXPath().then(path => {
clipboardHelper.copyString(path);
}).catch(e => console.error);
}).catch(console.error);
},
/**
@ -1942,7 +1942,7 @@ Inspector.prototype = {
selection.isPseudoElementNode()) {
return;
}
this.walker.duplicateNode(selection.nodeFront).catch(e => console.error(e));
this.walker.duplicateNode(selection.nodeFront).catch(console.error);
},
/**
@ -2043,7 +2043,7 @@ Inspector.prototype = {
return this.toolbox.viewSourceInDebugger(url);
}
return null;
}).catch(e => console.error(e));
}).catch(console.error);
} else if (type == "idref") {
// Select the node in the same document.
this.walker.document(this.selection.nodeFront).then(doc => {
@ -2054,7 +2054,7 @@ Inspector.prototype = {
}
this.selection.setNodeFront(node);
});
}).catch(e => console.error(e));
}).catch(console.error);
}
},

Просмотреть файл

@ -184,7 +184,7 @@ MarkupView.prototype = {
_onToolboxPickerHover: function (event, nodeFront) {
this.showNode(nodeFront).then(() => {
this._showContainerAsHovered(nodeFront);
}, e => console.error(e));
}, console.error);
},
/**

Просмотреть файл

@ -897,7 +897,7 @@ CssRuleView.prototype = {
// Notify anyone that cares that we refreshed.
return onEditorsReady.then(() => {
this.emit("ruleview-refreshed");
}, e => console.error(e));
}, console.error);
}).catch(promiseWarn);
},

Просмотреть файл

@ -275,7 +275,7 @@ RuleEditor.prototype = {
this.rule.getOriginalSourceStrings().then((strings) => {
sourceLabel.textContent = strings.short;
sourceLabel.setAttribute("title", strings.full);
}, e => console.error(e)).then(() => {
}, console.error).then(() => {
this.emit("source-link-updated");
});
} else {

Просмотреть файл

@ -196,7 +196,7 @@ DomNodePreview.prototype = {
},
destroy: function () {
HighlighterLock.unhighlight().catch(e => console.error(e));
HighlighterLock.unhighlight().catch(console.error);
this.stopListeners();
@ -218,7 +218,7 @@ DomNodePreview.prototype = {
return;
}
this.highlighterUtils.highlightNodeFront(this.nodeFront)
.catch(e => console.error(e));
.catch(console.error);
},
onPreviewMouseOut: function () {
@ -226,7 +226,7 @@ DomNodePreview.prototype = {
return;
}
this.highlighterUtils.unhighlight()
.catch(e => console.error(e));
.catch(console.error);
},
onSelectElClick: function () {
@ -246,12 +246,12 @@ DomNodePreview.prototype = {
classList.remove("selected");
HighlighterLock.unhighlight().then(() => {
this.emit("target-highlighter-unlocked");
}, error => console.error(error));
}, console.error);
} else {
classList.add("selected");
HighlighterLock.highlight(this).then(() => {
this.emit("target-highlighter-locked");
}, error => console.error(error));
}, console.error);
}
},

Просмотреть файл

@ -535,7 +535,7 @@ HighlightersOverlay.prototype = {
// whether the result is truthy before installing the handler.
let onHidden = this.highlighters[this.hoveredHighlighterShown].hide();
if (onHidden) {
onHidden.catch(e => console.error(e));
onHidden.catch(console.error);
}
this.hoveredHighlighterShown = null;

Просмотреть файл

@ -189,7 +189,7 @@ const ResponsiveUIManager = exports.ResponsiveUIManager = {
break;
default:
}
completed.catch(e => console.error(e));
completed.catch(console.error);
},
handleMenuCheck({target}) {

Просмотреть файл

@ -1736,7 +1736,7 @@ var Scratchpad = {
this.populateRecentFilesMenu();
PreferenceObserver.init();
CloseObserver.init();
}).catch((err) => console.error(err));
}).catch(console.error);
this._setupCommandListeners();
this._updateViewMenuItems();
this._setupPopupShowingListeners();

Просмотреть файл

@ -314,7 +314,7 @@ var ShadersListView = Heritage.extend(WidgetMethods, {
getShaders()
.then(getSources)
.then(showSources)
.catch(e => console.error(e));
.catch(console.error);
},
/**

Просмотреть файл

@ -575,7 +575,7 @@ CSSFilterEditorWidget.prototype = {
// If the click happened on the remove button.
presets.splice(id, 1);
this.setPresets(presets).then(this.renderPresets,
ex => console.error(ex));
console.error);
} else {
// Or if the click happened on a preset.
let p = presets[id];
@ -583,7 +583,7 @@ CSSFilterEditorWidget.prototype = {
this.setCssValue(p.value);
this.addPresetInput.value = p.name;
}
}, ex => console.error(ex));
}, console.error);
},
_togglePresets: function () {
@ -612,8 +612,8 @@ CSSFilterEditorWidget.prototype = {
}
this.setPresets(presets).then(this.renderPresets,
ex => console.error(ex));
}, ex => console.error(ex));
console.error);
}, console.error);
},
/**
@ -952,12 +952,12 @@ CSSFilterEditorWidget.prototype = {
}
return presets;
}, e => console.error(e));
}, console.error);
},
setPresets: function (presets) {
return asyncStorage.setItem("cssFilterPresets", presets)
.catch(e => console.error(e));
.catch(console.error);
}
};

Просмотреть файл

@ -171,7 +171,7 @@ SwatchColorPickerTooltip.prototype = extend(SwatchBasedEditorTooltip.prototype,
this.hide();
this.tooltip.emit("eyedropper-opened");
}, e => console.error(e));
}, console.error);
inspector.once("color-picked", color => {
toolbox.win.focus();

Просмотреть файл

@ -237,7 +237,7 @@ function autoComplete({ ed, cm }) {
});
popup.openPopup(cursorElement, -1 * left, 0);
autocompleteOpts.suggestionInsertedOnce = false;
}).catch(e => console.error(e));
}).catch(console.error);
}
/**

Просмотреть файл

@ -234,7 +234,7 @@ StyleEditorUI.prototype = {
_onNewDocument: function () {
this._debuggee.getStyleSheets().then((styleSheets) => {
return this._resetStyleSheetList(styleSheets);
}).catch(e => console.error(e));
}).catch(console.error);
},
/**
@ -634,7 +634,7 @@ StyleEditorUI.prototype = {
this.emit("error", { key: "error-compressed", level: "info" });
}
}
}.bind(this)).catch(e => console.error(e));
}.bind(this)).catch(console.error);
}
});
},
@ -919,7 +919,7 @@ StyleEditorUI.prototype = {
sidebar.hidden = !showSidebar || !inSource;
this.emit("media-list-changed", editor);
}.bind(this)).catch(e => console.error(e));
}.bind(this)).catch(console.error);
},
/**

Просмотреть файл

@ -127,7 +127,7 @@ function StyleSheetEditor(styleSheet, win, file, isNew, walker, highlighter) {
this.mediaRules = [];
if (this.cssSheet.getMediaRules) {
this.cssSheet.getMediaRules().then(this._onMediaRulesChanged,
e => console.error(e));
console.error);
}
this.cssSheet.on("media-rules-changed", this._onMediaRulesChanged);
this.cssSheet.on("style-applied", this._onStyleApplied);
@ -518,7 +518,7 @@ StyleSheetEditor.prototype = {
* Toggled the disabled state of the underlying stylesheet.
*/
toggleDisabled: function () {
this.styleSheet.toggleDisabled().catch(e => console.error(e));
this.styleSheet.toggleDisabled().catch(console.error);
},
/**
@ -560,7 +560,7 @@ StyleSheetEditor.prototype = {
this._isUpdating = true;
this.styleSheet.update(this._state.text, this.transitionsEnabled)
.catch(e => console.error(e));
.catch(console.error);
},
/**

Просмотреть файл

@ -3072,7 +3072,7 @@ Widgets.ObjectRenderers.add({
// the message is destroyed.
this.message.widgets.add(this);
this.linkToInspector().catch(e => console.error(e));
this.linkToInspector().catch(console.error);
},
/**
@ -3160,7 +3160,7 @@ Widgets.ObjectRenderers.add({
unhighlightDomNode: function () {
return this.linkToInspector().then(() => {
return this.toolbox.highlighterUtils.unhighlight();
}).catch(e => console.error(e));
}).catch(console.error);
},
/**

Просмотреть файл

@ -97,7 +97,7 @@ function mixedContentOverrideTest2(hud, browser) {
objects: true,
},
],
}).then(msgs => deferred.resolve(msgs), e => console.error(e));
}).then(msgs => deferred.resolve(msgs), console.error);
return deferred.promise;
}

Просмотреть файл

@ -102,7 +102,7 @@ function CheckLockState() {
adbCheckResult.textContent = sNo;
adbRootAction.removeAttribute("hidden");
}
}, e => console.error(e));
}, console.error);
} else {
adbCheckResult.textContent = sUnknown;
}
@ -120,7 +120,7 @@ function CheckLockState() {
} else {
devtoolsCheckResult.textContent = sYes;
}
}, e => console.error(e));
}, console.error);
} catch (e) {
// Exception. pref actor is only accessible if forbird-certified-apps is false
devtoolsCheckResult.textContent = sNo;
@ -147,5 +147,5 @@ function EnableCertApps() {
function RootADB() {
let device = AppManager.selectedRuntime.device;
device.summonRoot().then(CheckLockState, (e) => console.error(e));
device.summonRoot().then(CheckLockState, console.error);
}

Просмотреть файл

@ -43,7 +43,7 @@ The `hasActor` method returns a boolean synchronously.
```js
toolbox.target.actorHasMethod("domwalker", "duplicateNode").then(hasMethod => {
}).catch(e => console.error(e));
}).catch(console.error);
```
The `actorHasMethod` returns a promise that resolves to a boolean.

Просмотреть файл

@ -383,7 +383,7 @@ EyeDropper.prototype = {
}
this.emit("selected", toColorString(this.centerColor, this.format));
onColorSelected.then(() => this.hide(), e => console.error(e));
onColorSelected.then(() => this.hide(), console.error);
},
/**

Просмотреть файл

@ -1251,7 +1251,7 @@ Front.prototype = extend(Pool.prototype, {
this.actor().then(actorID => {
packet.to = actorID;
this.conn._transport.send(packet);
}).catch(e => console.error(e));
}).catch(console.error);
}
},

Просмотреть файл

@ -51,7 +51,7 @@ ScrollingLayersHelper::ScrollingLayersHelper(WebRenderLayer* aLayer,
PushLayerLocalClip(aStackingContext);
}
PushScrollLayer(fm, aStackingContext);
DefineAndPushScrollLayer(fm, aStackingContext);
}
// The scrolled clip on the layer is "inside" all of the scrollable metadatas
@ -146,10 +146,7 @@ ScrollingLayersHelper::DefineAndPushScrollLayers(nsDisplayItem* aItem,
if (!aAsr) {
return;
}
Maybe<ScrollMetadata> metadata = aAsr->mScrollableFrame->ComputeScrollMetadata(
nullptr, aItem->ReferenceFrame(), ContainerLayerParameters(), nullptr);
MOZ_ASSERT(metadata);
FrameMetrics::ViewID scrollId = metadata->GetMetrics().GetScrollId();
FrameMetrics::ViewID scrollId = nsLayoutUtils::ViewIDForASR(aAsr);
if (aBuilder.TopmostScrollId() == scrollId) {
// it's already been pushed, so we don't need to recurse any further.
return;
@ -176,11 +173,19 @@ ScrollingLayersHelper::DefineAndPushScrollLayers(nsDisplayItem* aItem,
// push exactly what we want.
DefineAndPushChain(asrClippedBy, aBuilder, aStackingContext,
aAppUnitsPerDevPixel, aCache);
// Finally, push the ASR itself as a scroll layer. Note that the
// implementation of wr_push_scroll_layer in bindings.rs makes sure the
// scroll layer doesn't get defined multiple times so we don't need to worry
// about that here.
if (PushScrollLayer(metadata->GetMetrics(), aStackingContext)) {
// Finally, push the ASR itself as a scroll layer. If it's already defined
// we can skip the expensive step of computing the ScrollMetadata.
bool pushed = false;
if (mBuilder->IsScrollLayerDefined(scrollId)) {
mBuilder->PushScrollLayer(scrollId);
pushed = true;
} else {
Maybe<ScrollMetadata> metadata = aAsr->mScrollableFrame->ComputeScrollMetadata(
nullptr, aItem->ReferenceFrame(), ContainerLayerParameters(), nullptr);
MOZ_ASSERT(metadata);
pushed = DefineAndPushScrollLayer(metadata->GetMetrics(), aStackingContext);
}
if (pushed) {
mPushedClips.push_back(wr::ScrollOrClipId(scrollId));
}
}
@ -228,7 +233,7 @@ ScrollingLayersHelper::DefineAndPushChain(const DisplayItemClipChain* aChain,
}
bool
ScrollingLayersHelper::PushScrollLayer(const FrameMetrics& aMetrics,
ScrollingLayersHelper::DefineAndPushScrollLayer(const FrameMetrics& aMetrics,
const StackingContextHelper& aStackingContext)
{
if (!aMetrics.IsScrollable()) {
@ -251,9 +256,10 @@ ScrollingLayersHelper::PushScrollLayer(const FrameMetrics& aMetrics,
// WebRender at all. Instead, we take the position from the composition
// bounds.
contentRect.MoveTo(clipBounds.TopLeft());
mBuilder->PushScrollLayer(aMetrics.GetScrollId(),
mBuilder->DefineScrollLayer(aMetrics.GetScrollId(),
aStackingContext.ToRelativeLayoutRect(contentRect),
aStackingContext.ToRelativeLayoutRect(clipBounds));
mBuilder->PushScrollLayer(aMetrics.GetScrollId());
return true;
}

Просмотреть файл

@ -49,7 +49,7 @@ private:
const StackingContextHelper& aStackingContext,
int32_t aAppUnitsPerDevPixel,
WebRenderLayerManager::ClipIdMap& aCache);
bool PushScrollLayer(const FrameMetrics& aMetrics,
bool DefineAndPushScrollLayer(const FrameMetrics& aMetrics,
const StackingContextHelper& aStackingContext);
void PushLayerLocalClip(const StackingContextHelper& aStackingContext);
void PushLayerClip(const LayerClip& aClip,

Просмотреть файл

@ -694,21 +694,39 @@ DisplayListBuilder::PushBuiltDisplayList(BuiltDisplayList &dl)
&dl.dl.inner);
}
bool
DisplayListBuilder::IsScrollLayerDefined(layers::FrameMetrics::ViewID aScrollId) const
{
return mScrollParents.find(aScrollId) != mScrollParents.end();
}
void
DisplayListBuilder::PushScrollLayer(const layers::FrameMetrics::ViewID& aScrollId,
DisplayListBuilder::DefineScrollLayer(const layers::FrameMetrics::ViewID& aScrollId,
const wr::LayoutRect& aContentRect,
const wr::LayoutRect& aClipRect)
{
WRDL_LOG("PushScrollLayer id=%" PRIu64 " co=%s cl=%s\n", mWrState,
WRDL_LOG("DefineScrollLayer id=%" PRIu64 " co=%s cl=%s\n", mWrState,
aScrollId, Stringify(aContentRect).c_str(), Stringify(aClipRect).c_str());
wr_dp_push_scroll_layer(mWrState, aScrollId, aContentRect, aClipRect);
if (!mScrollIdStack.empty()) {
auto it = mScrollParents.insert({aScrollId, mScrollIdStack.back()});
if (!it.second) { // aScrollId was already a key in mScrollParents
// so check that the parent value is the same.
MOZ_ASSERT(it.first->second == mScrollIdStack.back());
}
Maybe<layers::FrameMetrics::ViewID> parent =
mScrollIdStack.empty() ? Nothing() : Some(mScrollIdStack.back());
auto it = mScrollParents.insert({aScrollId, parent});
if (it.second) {
// An insertion took place, which means we haven't defined aScrollId before.
// So let's define it now.
wr_dp_define_scroll_layer(mWrState, aScrollId, aContentRect, aClipRect);
} else {
// aScrollId was already a key in mScrollParents so check that the parent
// value is the same.
MOZ_ASSERT(it.first->second == parent);
}
}
void
DisplayListBuilder::PushScrollLayer(const layers::FrameMetrics::ViewID& aScrollId)
{
WRDL_LOG("PushScrollLayer id=%" PRIu64 "\n", mWrState, aScrollId);
wr_dp_push_scroll_layer(mWrState, aScrollId);
mScrollIdStack.push_back(aScrollId);
}
@ -1027,7 +1045,7 @@ Maybe<layers::FrameMetrics::ViewID>
DisplayListBuilder::ParentScrollIdFor(layers::FrameMetrics::ViewID aScrollId)
{
auto it = mScrollParents.find(aScrollId);
return (it == mScrollParents.end() ? Nothing() : Some(it->second));
return (it == mScrollParents.end() ? Nothing() : it->second);
}
} // namespace wr

Просмотреть файл

@ -203,9 +203,11 @@ public:
void PushBuiltDisplayList(wr::BuiltDisplayList &dl);
void PushScrollLayer(const layers::FrameMetrics::ViewID& aScrollId,
bool IsScrollLayerDefined(layers::FrameMetrics::ViewID aScrollId) const;
void DefineScrollLayer(const layers::FrameMetrics::ViewID& aScrollId,
const wr::LayoutRect& aContentRect, // TODO: We should work with strongly typed rects
const wr::LayoutRect& aClipRect);
void PushScrollLayer(const layers::FrameMetrics::ViewID& aScrollId);
void PopScrollLayer();
void PushClipAndScrollInfo(const layers::FrameMetrics::ViewID& aScrollId,
@ -356,8 +358,10 @@ protected:
std::vector<wr::WrClipId> mClipIdStack;
std::vector<layers::FrameMetrics::ViewID> mScrollIdStack;
// Track the parent scroll id of each scroll id that we encountered.
std::unordered_map<layers::FrameMetrics::ViewID, layers::FrameMetrics::ViewID> mScrollParents;
// Track the parent scroll id of each scroll id that we encountered. A
// Nothing() value indicates a root scroll id. We also use this structure to
// ensure that we don't define a particular scroll layer multiple times.
std::unordered_map<layers::FrameMetrics::ViewID, Maybe<layers::FrameMetrics::ViewID>> mScrollParents;
friend class WebRenderAPI;
};

Просмотреть файл

@ -1,4 +1,3 @@
use std::collections::HashSet;
use std::ffi::CString;
use std::{mem, slice};
use std::path::PathBuf;
@ -954,7 +953,6 @@ pub unsafe extern "C" fn wr_api_get_namespace(dh: &mut DocumentHandle) -> WrIdNa
pub struct WebRenderFrameBuilder {
pub root_pipeline_id: WrPipelineId,
pub dl_builder: webrender_api::DisplayListBuilder,
pub scroll_clips_defined: HashSet<ClipId>,
}
impl WebRenderFrameBuilder {
@ -963,7 +961,6 @@ impl WebRenderFrameBuilder {
WebRenderFrameBuilder {
root_pipeline_id: root_pipeline_id,
dl_builder: webrender_api::DisplayListBuilder::new(root_pipeline_id, content_size),
scroll_clips_defined: HashSet::new(),
}
}
}
@ -1130,21 +1127,22 @@ pub extern "C" fn wr_dp_pop_clip(state: &mut WrState) {
}
#[no_mangle]
pub extern "C" fn wr_dp_push_scroll_layer(state: &mut WrState,
pub extern "C" fn wr_dp_define_scroll_layer(state: &mut WrState,
scroll_id: u64,
content_rect: LayoutRect,
clip_rect: LayoutRect) {
assert!(unsafe { is_in_main_thread() });
let clip_id = ClipId::new(scroll_id, state.pipeline_id);
// Avoid defining multiple scroll clips with the same clip id, as that
// results in undefined behaviour or assertion failures.
if !state.frame_builder.scroll_clips_defined.contains(&clip_id) {
state.frame_builder.dl_builder.define_scroll_frame(
Some(clip_id), content_rect, clip_rect, vec![], None,
ScrollSensitivity::Script);
state.frame_builder.scroll_clips_defined.insert(clip_id);
}
}
#[no_mangle]
pub extern "C" fn wr_dp_push_scroll_layer(state: &mut WrState,
scroll_id: u64) {
assert!(unsafe { is_in_main_thread() });
let clip_id = ClipId::new(scroll_id, state.pipeline_id);
state.frame_builder.dl_builder.push_clip_id(clip_id);
}

Просмотреть файл

@ -920,6 +920,13 @@ uint64_t wr_dp_define_clip(WrState *aState,
const WrImageMask *aMask)
WR_FUNC;
WR_INLINE
void wr_dp_define_scroll_layer(WrState *aState,
uint64_t aScrollId,
LayoutRect aContentRect,
LayoutRect aClipRect)
WR_FUNC;
WR_INLINE
void wr_dp_end(WrState *aState)
WR_FUNC;
@ -1087,9 +1094,7 @@ WR_FUNC;
WR_INLINE
void wr_dp_push_scroll_layer(WrState *aState,
uint64_t aScrollId,
LayoutRect aContentRect,
LayoutRect aClipRect)
uint64_t aScrollId)
WR_FUNC;
WR_INLINE

Просмотреть файл

@ -397,11 +397,7 @@ var Addons = {
// Allow the options to use all the available width space.
optionsBox.classList.remove("inner");
// WebExtensions are loaded asynchronously and the optionsURL
// may not be available via listitem when the add-on has just been
// installed, but it is available on the addon if one is set.
detailItem.setAttribute("optionsURL", addon.optionsURL);
this.createWebExtensionOptions(optionsBox, addon.optionsURL, addon.optionsBrowserStyle);
this.createWebExtensionOptions(optionsBox, addon);
break;
case AddonManager.OPTIONS_TYPE_TAB:
// Keep the usual layout for any options related the legacy (or system) add-ons
@ -441,14 +437,28 @@ var Addons = {
}
button.onclick = async () => {
if (addon.isWebExtension) {
// WebExtensions are loaded asynchronously and the optionsURL
// may not be available until the addon has been started.
await addon.startupPromise;
}
const {optionsURL} = addon;
openOptionsInTab(optionsURL);
};
},
createWebExtensionOptions: async function(destination, optionsURL, browserStyle) {
createWebExtensionOptions: async function(destination, addon) {
// WebExtensions are loaded asynchronously and the optionsURL
// may not be available until the addon has been started.
await addon.startupPromise;
const {optionsURL, optionsBrowserStyle} = addon;
let frame = destination.querySelector("iframe#addon-options");
if (!frame) {
let originalHeight;
let frame = document.createElement("iframe");
frame = document.createElement("iframe");
frame.setAttribute("id", "addon-options");
frame.setAttribute("mozbrowser", "true");
frame.setAttribute("style", "width: 100%; overflow: hidden;");
@ -477,8 +487,8 @@ var Addons = {
};
destination.appendChild(frame);
originalHeight = frame.getBoundingClientRect().height;
}
// Loading the URL this way prevents the native back
// button from applying to the iframe.
@ -585,6 +595,14 @@ var Addons = {
detailItem.setAttribute("opType", opType);
else
detailItem.removeAttribute("opType");
// Remove any addon options iframe if the currently selected addon has been disabled.
if (!aValue) {
const addonOptionsIframe = document.querySelector("#addon-options");
if (addonOptionsIframe) {
addonOptionsIframe.remove();
}
}
}
// Sync to the list item

Просмотреть файл

@ -84,6 +84,14 @@ function waitAboutAddonsLoaded() {
return waitDOMContentLoaded(url => url === "about:addons");
}
function clickAddonDisable() {
content.document.querySelector("#disable-btn").click();
}
function clickAddonEnable() {
content.document.querySelector("#enable-btn").click();
}
add_task(async function test_options_ui_iframe_height() {
let addonID = "test-options-ui@mozilla.org";
@ -406,6 +414,86 @@ add_task(async function test_options_ui_open_in_tab() {
await extension.unload();
});
add_task(async function test_options_ui_on_disable_and_enable() {
let addonID = "test-options-ui-disable-enable@mozilla.org";
function optionsScript() {
browser.test.sendMessage("options-page-loaded", window.location.href);
}
let extension = ExtensionTestUtils.loadExtension({
useAddonManager: "temporary",
manifest: {
applications: {
gecko: {id: addonID},
},
name: "Options UI open addon details Extension",
description: "Longer addon description",
options_ui: {
page: "options.html",
},
},
files: {
"options.js": optionsScript,
"options.html": `<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<h1>Options page</h1>
<script src="options.js"><\/script>
</body>
</html>
`,
},
});
await extension.startup();
const {BrowserApp} = Services.wm.getMostRecentWindow("navigator:browser");
let onceAboutAddonsLoaded = waitAboutAddonsLoaded();
BrowserApp.addTab("about:addons", {
selected: true,
parentId: BrowserApp.selectedTab.id,
});
await onceAboutAddonsLoaded;
const aboutAddonsTab = BrowserApp.selectedTab;
is(aboutAddonsTab.currentURI.spec, "about:addons",
"about:addons is the currently selected tab");
info("Wait the addon details to have been loaded");
await ContentTask.spawn(aboutAddonsTab.browser, addonID, waitAboutAddonsRendered);
await ContentTask.spawn(aboutAddonsTab.browser, addonID, navigateToAddonDetails);
info("Wait the addon options page to have been loaded");
await extension.awaitMessage("options-page-loaded");
info("Click the addon disable button");
await ContentTask.spawn(aboutAddonsTab.browser, null, clickAddonDisable);
// NOTE: Currently after disabling the addon the extension.awaitMessage seems
// to fail be able to receive events coming from the browser.test.sendMessage API
// (nevertheless `await extension.unload()` seems to be able to remove the extension),
// falling back to wait for the options page to be loaded here.
const onceAddonOptionsLoaded = waitDOMContentLoaded(url => url.endsWith("options.html"));
info("Click the addon enable button");
await ContentTask.spawn(aboutAddonsTab.browser, null, clickAddonEnable);
info("Wait the addon options page to have been loaded after clicking the addon enable button");
await onceAddonOptionsLoaded;
BrowserApp.closeTab(BrowserApp.selectedTab);
await extension.unload();
});
</script>
</body>

Просмотреть файл

@ -1140,4 +1140,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
static const int32_t kUnknownId = -1;
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1512494652111000);
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1512667462291000);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -2064,6 +2064,9 @@ class IDLType(IDLObject):
def isRecord(self):
return False
def isReadableStream(self):
return False
def isArrayBuffer(self):
return False
@ -2091,12 +2094,12 @@ class IDLType(IDLObject):
def isSpiderMonkeyInterface(self):
""" Returns a boolean indicating whether this type is an 'interface'
type that is implemented in Spidermonkey. At the moment, this
only returns true for the types from the TypedArray spec. """
type that is implemented in SpiderMonkey. """
return self.isInterface() and (self.isArrayBuffer() or
self.isArrayBufferView() or
self.isSharedArrayBuffer() or
self.isTypedArray())
self.isTypedArray() or
self.isReadableStream())
def isDictionary(self):
return False
@ -2289,6 +2292,9 @@ class IDLNullableType(IDLParametrizedType):
def isRecord(self):
return self.inner.isRecord()
def isReadableStream(self):
return self.inner.isReadableStream()
def isArrayBuffer(self):
return self.inner.isArrayBuffer()
@ -2656,6 +2662,9 @@ class IDLTypedefType(IDLType):
def isRecord(self):
return self.inner.isRecord()
def isReadableStream(self):
return self.inner.isReadableStream()
def isDictionary(self):
return self.inner.isDictionary()
@ -2970,7 +2979,8 @@ class IDLBuiltinType(IDLType):
'Int32Array',
'Uint32Array',
'Float32Array',
'Float64Array'
'Float64Array',
'ReadableStream',
)
TagLookup = {
@ -3005,7 +3015,8 @@ class IDLBuiltinType(IDLType):
Types.Int32Array: IDLType.Tags.interface,
Types.Uint32Array: IDLType.Tags.interface,
Types.Float32Array: IDLType.Tags.interface,
Types.Float64Array: IDLType.Tags.interface
Types.Float64Array: IDLType.Tags.interface,
Types.ReadableStream: IDLType.Tags.interface,
}
def __init__(self, location, name, type):
@ -3052,6 +3063,9 @@ class IDLBuiltinType(IDLType):
return (self._typeTag >= IDLBuiltinType.Types.Int8Array and
self._typeTag <= IDLBuiltinType.Types.Float64Array)
def isReadableStream(self):
return self._typeTag == IDLBuiltinType.Types.ReadableStream
def isInterface(self):
# TypedArray things are interface types per the TypedArray spec,
# but we handle them as builtins because SpiderMonkey implements
@ -3059,7 +3073,8 @@ class IDLBuiltinType(IDLType):
return (self.isArrayBuffer() or
self.isArrayBufferView() or
self.isSharedArrayBuffer() or
self.isTypedArray())
self.isTypedArray() or
self.isReadableStream())
def isNonCallbackInterface(self):
# All the interfaces we can be are non-callback
@ -3129,6 +3144,7 @@ class IDLBuiltinType(IDLType):
# that's not an ArrayBuffer or a callback interface
(self.isArrayBuffer() and not other.isArrayBuffer()) or
(self.isSharedArrayBuffer() and not other.isSharedArrayBuffer()) or
(self.isReadableStream() and not other.isReadableStream()) or
# ArrayBufferView is distinguishable from everything
# that's not an ArrayBufferView or typed array.
(self.isArrayBufferView() and not other.isArrayBufferView() and
@ -3238,7 +3254,10 @@ BuiltinTypes = {
IDLBuiltinType.Types.Float32Array),
IDLBuiltinType.Types.Float64Array:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "Float64Array",
IDLBuiltinType.Types.Float64Array)
IDLBuiltinType.Types.Float64Array),
IDLBuiltinType.Types.ReadableStream:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "ReadableStream",
IDLBuiltinType.Types.ReadableStream),
}
@ -5287,7 +5306,8 @@ class Tokenizer(object):
"maplike": "MAPLIKE",
"setlike": "SETLIKE",
"iterable": "ITERABLE",
"namespace": "NAMESPACE"
"namespace": "NAMESPACE",
"ReadableStream": "READABLESTREAM",
}
tokens.extend(keywords.values())
@ -6475,6 +6495,7 @@ class Parser(Tokenizer):
NonAnyType : PrimitiveType Null
| ARRAYBUFFER Null
| SHAREDARRAYBUFFER Null
| READABLESTREAM Null
| OBJECT Null
"""
if p[1] == "object":
@ -6483,6 +6504,8 @@ class Parser(Tokenizer):
type = BuiltinTypes[IDLBuiltinType.Types.ArrayBuffer]
elif p[1] == "SharedArrayBuffer":
type = BuiltinTypes[IDLBuiltinType.Types.SharedArrayBuffer]
elif p[1] == "ReadableStream":
type = BuiltinTypes[IDLBuiltinType.Types.ReadableStream]
else:
type = BuiltinTypes[p[1]]

Просмотреть файл

@ -11,7 +11,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("chrome://marionette/content/assert.js");
Cu.import("chrome://marionette/content/element.js");
const {
error,
pprint,
InvalidArgumentError,
MoveTargetOutOfBoundsError,
UnsupportedOperationError,
@ -21,8 +21,6 @@ Cu.import("chrome://marionette/content/interaction.js");
this.EXPORTED_SYMBOLS = ["action"];
const {pprint} = error;
// TODO? With ES 2016 and Symbol you can make a safer approximation
// to an enum e.g. https://gist.github.com/xmlking/e86e4f15ec32b12c4689
/**

Просмотреть файл

@ -11,10 +11,10 @@ Cu.import("resource://gre/modules/Preferences.jsm");
Cu.import("resource://gre/modules/Services.jsm");
const {
error,
InvalidArgumentError,
InvalidSessionIDError,
NoSuchWindowError,
pprint,
UnexpectedAlertOpenError,
UnsupportedOperationError,
} = Cu.import("chrome://marionette/content/error.js", {});
@ -174,7 +174,7 @@ assert.noUserPrompt = function(dialog, msg = "") {
* If |obj| is not defined.
*/
assert.defined = function(obj, msg = "") {
msg = msg || error.pprint`Expected ${obj} to be defined`;
msg = msg || pprint`Expected ${obj} to be defined`;
return assert.that(o => typeof o != "undefined", msg)(obj);
};
@ -193,7 +193,7 @@ assert.defined = function(obj, msg = "") {
* If |obj| is not a number.
*/
assert.number = function(obj, msg = "") {
msg = msg || error.pprint`Expected ${obj} to be finite number`;
msg = msg || pprint`Expected ${obj} to be finite number`;
return assert.that(Number.isFinite, msg)(obj);
};
@ -212,7 +212,7 @@ assert.number = function(obj, msg = "") {
* If |obj| is not callable.
*/
assert.callable = function(obj, msg = "") {
msg = msg || error.pprint`${obj} is not callable`;
msg = msg || pprint`${obj} is not callable`;
return assert.that(o => typeof o == "function", msg)(obj);
};
@ -231,7 +231,7 @@ assert.callable = function(obj, msg = "") {
* If |obj| is not an integer.
*/
assert.integer = function(obj, msg = "") {
msg = msg || error.pprint`Expected ${obj} to be an integer`;
msg = msg || pprint`Expected ${obj} to be an integer`;
return assert.that(Number.isInteger, msg)(obj);
};
@ -251,7 +251,7 @@ assert.integer = function(obj, msg = "") {
*/
assert.positiveInteger = function(obj, msg = "") {
assert.integer(obj, msg);
msg = msg || error.pprint`Expected ${obj} to be >= 0`;
msg = msg || pprint`Expected ${obj} to be >= 0`;
return assert.that(n => n >= 0, msg)(obj);
};
@ -270,7 +270,7 @@ assert.positiveInteger = function(obj, msg = "") {
* If |obj| is not a boolean.
*/
assert.boolean = function(obj, msg = "") {
msg = msg || error.pprint`Expected ${obj} to be boolean`;
msg = msg || pprint`Expected ${obj} to be boolean`;
return assert.that(b => typeof b == "boolean", msg)(obj);
};
@ -289,7 +289,7 @@ assert.boolean = function(obj, msg = "") {
* If |obj| is not a string.
*/
assert.string = function(obj, msg = "") {
msg = msg || error.pprint`Expected ${obj} to be a string`;
msg = msg || pprint`Expected ${obj} to be a string`;
return assert.that(s => typeof s == "string", msg)(obj);
};
@ -308,7 +308,7 @@ assert.string = function(obj, msg = "") {
* If |obj| is not an object.
*/
assert.object = function(obj, msg = "") {
msg = msg || error.pprint`Expected ${obj} to be an object`;
msg = msg || pprint`Expected ${obj} to be an object`;
return assert.that(o => {
// unable to use instanceof because LHS and RHS may come from
// different globals
@ -335,7 +335,7 @@ assert.object = function(obj, msg = "") {
*/
assert.in = function(prop, obj, msg = "") {
assert.object(obj, msg);
msg = msg || error.pprint`Expected ${prop} in ${obj}`;
msg = msg || pprint`Expected ${prop} in ${obj}`;
assert.that(p => obj.hasOwnProperty(p), msg)(prop);
return obj[prop];
};
@ -355,7 +355,7 @@ assert.in = function(prop, obj, msg = "") {
* If |obj| is not an Array.
*/
assert.array = function(obj, msg = "") {
msg = msg || error.pprint`Expected ${obj} to be an Array`;
msg = msg || pprint`Expected ${obj} to be an Array`;
return assert.that(Array.isArray, msg)(obj);
};

Просмотреть файл

@ -10,8 +10,8 @@ Cu.import("resource://gre/modules/Services.jsm");
Cu.import("chrome://marionette/content/assert.js");
const {
error,
InvalidCookieDomainError,
pprint,
} = Cu.import("chrome://marionette/content/error.js", {});
this.EXPORTED_SYMBOLS = ["cookie"];
@ -53,7 +53,7 @@ this.cookie = {
cookie.fromJSON = function(json) {
let newCookie = {};
assert.object(json, error.pprint`Expected cookie object, got ${json}`);
assert.object(json, pprint`Expected cookie object, got ${json}`);
newCookie.name = assert.string(json.name, "Cookie name must be string");
newCookie.value = assert.string(json.value, "Cookie value must be string");

Просмотреть файл

@ -12,10 +12,10 @@ Cu.import("resource://gre/modules/Log.jsm");
Cu.import("chrome://marionette/content/assert.js");
Cu.import("chrome://marionette/content/atom.js");
const {
error,
InvalidSelectorError,
JavaScriptError,
NoSuchElementError,
pprint,
StaleElementReferenceError,
} = Cu.import("chrome://marionette/content/error.js", {});
Cu.import("chrome://marionette/content/wait.js");
@ -180,7 +180,7 @@ element.Store = class {
if (element.isStale(el)) {
throw new StaleElementReferenceError(
error.pprint`The element reference of ${el} stale; ` +
pprint`The element reference of ${el} stale; ` +
"either the element is no longer attached to the DOM " +
"or the document has been refreshed");
}

Просмотреть файл

@ -45,7 +45,11 @@ const BUILTIN_ERRORS = new Set([
"URIError",
]);
this.EXPORTED_SYMBOLS = ["error", "error.pprint"].concat(Array.from(ERRORS));
this.EXPORTED_SYMBOLS = [
"error",
"pprint",
"stack",
].concat(Array.from(ERRORS));
/** @namespace */
this.error = {};
@ -158,7 +162,7 @@ error.stringify = function(err) {
* pprint`Expected element ${htmlElement}`;
* => 'Expected element <input id="foo" class="bar baz">'
*/
error.pprint = function(ss, ...values) {
this.pprint = function(ss, ...values) {
function prettyObject(obj) {
let proto = Object.prototype.toString.call(obj);
let s = "";
@ -212,6 +216,14 @@ error.pprint = function(ss, ...values) {
return res.join("");
};
/** Create a stacktrace to the current line in the program. */
this.stack = function() {
let trace = new Error().stack;
let sa = trace.split("\n");
sa = sa.slice(1);
return "stacktrace:\n" + sa.join("\n");
};
/**
* WebDriverError is the prototypal parent of all WebDriver errors.
* It should not be used directly, as it does not correspond to a real
@ -305,17 +317,17 @@ class ElementClickInterceptedError extends WebDriverError {
switch (obscuredEl.style.pointerEvents) {
case "none":
msg = error.pprint`Element ${obscuredEl} is not clickable ` +
msg = pprint`Element ${obscuredEl} is not clickable ` +
`at point (${coords.x},${coords.y}) ` +
`because it does not have pointer events enabled, ` +
error.pprint`and element ${overlayingEl} ` +
pprint`and element ${overlayingEl} ` +
`would receive the click instead`;
break;
default:
msg = error.pprint`Element ${obscuredEl} is not clickable ` +
msg = pprint`Element ${obscuredEl} is not clickable ` +
`at point (${coords.x},${coords.y}) ` +
error.pprint`because another element ${overlayingEl} ` +
pprint`because another element ${overlayingEl} ` +
`obscures it`;
break;
}

Просмотреть файл

@ -11,7 +11,6 @@ Cu.import("chrome://marionette/content/atom.js");
const {
ElementClickInterceptedError,
ElementNotInteractableError,
error,
InvalidArgument,
InvalidArgumentError,
InvalidElementStateError,
@ -178,7 +177,7 @@ async function webdriverClickElement(el, a11y) {
// there is no point in checking if it is pointer-interactable
if (!element.isInView(containerEl)) {
throw new ElementNotInteractableError(
error.pprint`Element ${el} could not be scrolled into view`);
pprint`Element ${el} could not be scrolled into view`);
}
// step 7

Просмотреть файл

@ -4,7 +4,36 @@
const {utils: Cu} = Components;
Cu.import("chrome://marionette/content/error.js");
const {
ElementClickInterceptedError,
ElementNotAccessibleError,
ElementNotInteractableError,
error,
InsecureCertificateError,
InvalidArgumentError,
InvalidCookieDomainError,
InvalidElementStateError,
InvalidSelectorError,
InvalidSessionIDError,
JavaScriptError,
MoveTargetOutOfBoundsError,
NoAlertOpenError,
NoSuchElementError,
NoSuchFrameError,
NoSuchWindowError,
pprint,
ScriptTimeoutError,
SessionNotCreatedError,
stack,
StaleElementReferenceError,
TimeoutError,
UnableToSetCookieError,
UnexpectedAlertOpenError,
UnknownCommandError,
UnknownError,
UnsupportedOperationError,
WebDriverError,
} = Cu.import("chrome://marionette/content/error.js", {});
function notok(condition) {
ok(!(condition));
@ -90,19 +119,19 @@ add_test(function test_stringify() {
});
add_test(function test_pprint() {
equal('[object Object] {"foo":"bar"}', error.pprint`${{foo: "bar"}}`);
equal('[object Object] {"foo":"bar"}', pprint`${{foo: "bar"}}`);
equal("[object Number] 42", error.pprint`${42}`);
equal("[object Boolean] true", error.pprint`${true}`);
equal("[object Undefined] undefined", error.pprint`${undefined}`);
equal("[object Null] null", error.pprint`${null}`);
equal("[object Number] 42", pprint`${42}`);
equal("[object Boolean] true", pprint`${true}`);
equal("[object Undefined] undefined", pprint`${undefined}`);
equal("[object Null] null", pprint`${null}`);
let complexObj = {toJSON: () => "foo"};
equal('[object Object] "foo"', error.pprint`${complexObj}`);
equal('[object Object] "foo"', pprint`${complexObj}`);
let cyclic = {};
cyclic.me = cyclic;
equal("[object Object] <cyclic object value>", error.pprint`${cyclic}`);
equal("[object Object] <cyclic object value>", pprint`${cyclic}`);
let el = {
nodeType: 1,
@ -111,7 +140,15 @@ add_test(function test_pprint() {
classList: {length: 1},
className: "bar baz",
};
equal('<input id="foo" class="bar baz">', error.pprint`${el}`);
equal('<input id="foo" class="bar baz">', pprint`${el}`);
run_next_test();
});
add_test(function test_stack() {
equal("string", typeof stack());
ok(stack().includes("test_stack"));
ok(!stack().includes("add_test"));
run_next_test();
});

Просмотреть файл

@ -230,6 +230,11 @@ class Talos(TestingMixin, MercurialScript, BlobUploadMixin, TooltoolMixin,
self.gecko_profile_interval = opts[idx + 1]
except ValueError:
pass
else:
# no opts, check for '--geckoProfile' in try message text directly
if self.try_message_has_flag('geckoProfile'):
self.gecko_profile = True
# finally, if gecko_profile is set, we add that to the talos options
if self.gecko_profile:
gecko_results.append('--geckoProfile')

Просмотреть файл

@ -163,8 +163,14 @@ class TryToolsMixin(TransferMixin):
repo_path = None
if self.buildbot_config and 'properties' in self.buildbot_config:
repo_path = self.buildbot_config['properties'].get('branch')
return (self.config.get('branch', repo_path) == 'try' or
'TRY_COMMIT_MSG' in os.environ)
get_branch = self.config.get('branch', repo_path)
if get_branch is not None:
on_try = ('try' in get_branch or 'Try' in get_branch)
elif os.environ is not None:
on_try = ('TRY_COMMIT_MSG' in os.environ)
else:
on_try = False
return on_try
@PostScriptAction('download-and-extract')
def set_extra_try_arguments(self, action, success=None):

Просмотреть файл

@ -207,14 +207,15 @@ this.PlacesTestUtils = Object.freeze({
* @resolves Returns the field value.
* @rejects JavaScript exception.
*/
async fieldInDB(aURI, field) {
fieldInDB(aURI, field) {
let url = aURI instanceof Ci.nsIURI ? new URL(aURI.spec) : new URL(aURI);
let db = await PlacesUtils.promiseDBConnection();
return PlacesUtils.withConnectionWrapper("PlacesTestUtils.jsm: fieldInDb", async db => {
let rows = await db.executeCached(
`SELECT ${field} FROM moz_places
WHERE url_hash = hash(:url) AND url = :url`,
{ url: url.href });
return rows[0].getResultByIndex(0);
});
},
/**

Просмотреть файл

@ -2639,6 +2639,46 @@ profiler_get_buffer_info_helper(uint32_t* aCurrentPosition,
*aGeneration = ActivePS::Buffer(lock).mGeneration;
}
static void
PollJSSamplingForCurrentThread()
{
MOZ_RELEASE_ASSERT(CorePS::Exists());
PSAutoLock lock(gPSMutex);
ThreadInfo* info = TLSInfo::Info(lock);
if (!info) {
return;
}
info->PollJSSampling();
}
// When the profiler is started on a background thread, we can't synchronously
// call PollJSSampling on the main thread's ThreadInfo. And the next regular
// call to PollJSSampling on the main thread would only happen once the main
// thread triggers a JS interrupt callback.
// This means that all the JS execution between profiler_start() and the first
// JS interrupt would happen with JS sampling disabled, and we wouldn't get any
// JS function information for that period of time.
// So in order to start JS sampling as soon as possible, we dispatch a runnable
// to the main thread which manually calls PollJSSamplingForCurrentThread().
// In some cases this runnable will lose the race with the next JS interrupt.
// That's fine; PollJSSamplingForCurrentThread() is immune to redundant calls.
static void
TriggerPollJSSamplingOnMainThread()
{
nsCOMPtr<nsIThread> mainThread;
nsresult rv = NS_GetMainThread(getter_AddRefs(mainThread));
if (NS_SUCCEEDED(rv) && mainThread) {
nsCOMPtr<nsIRunnable> task =
NS_NewRunnableFunction("TriggerPollJSSamplingOnMainThread", []() {
PollJSSamplingForCurrentThread();
});
SystemGroup::Dispatch(TaskCategory::Other, task.forget());
}
}
static void
locked_profiler_start(PSLockRef aLock, int aEntries, double aInterval,
uint32_t aFeatures,
@ -2689,6 +2729,11 @@ locked_profiler_start(PSLockRef aLock, int aEntries, double aInterval,
// We can manually poll the current thread so it starts sampling
// immediately.
info->PollJSSampling();
} else if (info->IsMainThread()) {
// Dispatch a runnable to the main thread to call PollJSSampling(),
// so that we don't have wait for the next JS interrupt callback in
// order to start profiling JS.
TriggerPollJSSamplingOnMainThread();
}
}
}
@ -3076,17 +3121,7 @@ void
profiler_js_interrupt_callback()
{
// This function runs on JS threads being sampled.
MOZ_RELEASE_ASSERT(CorePS::Exists());
PSAutoLock lock(gPSMutex);
ThreadInfo* info = TLSInfo::Info(lock);
if (!info) {
return;
}
info->PollJSSampling();
PollJSSamplingForCurrentThread();
}
double