Merge mozilla-central to autoland. a=merge CLOSED TREE

This commit is contained in:
Ciure Andrei 2018-05-04 00:54:35 +03:00
Родитель 69712b06d5 82f7c496dc
Коммит 3a5c693e28
87 изменённых файлов: 1175 добавлений и 494 удалений

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

@ -17,7 +17,7 @@ add_task(async function() {
isnot(searchInput, doc.activeElement, "Search bar should not be the active element.");
EventUtils.synthesizeKey("k", { accelKey: true });
await promiseWaitForCondition(() => doc.activeElement === searchInput);
await TestUtils.waitForCondition(() => doc.activeElement === searchInput);
is(searchInput, doc.activeElement, "Search bar should be the active element.");
});

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

@ -23,12 +23,6 @@ function waitForCondition(condition, nextTest, errorMsg, retryTimes) {
var moveOn = function() { clearInterval(interval); nextTest(); };
}
function promiseWaitForCondition(aConditionFn) {
return new Promise(resolve => {
waitForCondition(aConditionFn, resolve, "Condition didn't pass.");
});
}
function whenTabLoaded(aTab, aCallback) {
promiseTabLoadEvent(aTab).then(aCallback);
}

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

@ -93,10 +93,6 @@ add_task(async function startup() {
min: 10,
max: 55,
},
"dom.max_chrome_script_run_time": {
min: 20,
max: 55,
},
};
let startupRecorder = Cc["@mozilla.org/test/startuprecorder;1"].getService().wrappedJSObject;

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

@ -813,17 +813,17 @@ var gPrivacyPane = {
readKeepCookiesUntil() {
let privateBrowsing = Preferences.get("browser.privatebrowsing.autostart").value;
if (privateBrowsing) {
return "2";
return Ci.nsICookieService.ACCEPT_SESSION;
}
let lifetimePolicy = Preferences.get("network.cookie.lifetimePolicy").value;
if (lifetimePolicy != Ci.nsICookieService.ACCEPT_NORMALLY &&
lifetimePolicy != Ci.nsICookieService.ACCEPT_SESSION &&
lifetimePolicy != Ci.nsICookieService.ACCEPT_FOR_N_DAYS) {
return Ci.nsICookieService.ACCEPT_NORMALLY;
if (lifetimePolicy == Ci.nsICookieService.ACCEPT_SESSION) {
return Ci.nsICookieService.ACCEPT_SESSION;
}
return lifetimePolicy;
// network.cookie.lifetimePolicy can be set to any value, but we just
// support ACCEPT_SESSION and ACCEPT_NORMALLY. Let's force ACCEPT_NORMALLY.
return Ci.nsICookieService.ACCEPT_NORMALLY;
},
/**

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

@ -4,17 +4,15 @@
"use strict";
const { getCssProperties } = require("devtools/shared/fronts/css-properties");
const { InplaceEditor } = require("devtools/client/shared/inplace-editor");
const {
updateGeometryEditorEnabled,
updateLayout,
updateOffsetParent,
} = require("./actions/box-model");
const EditingSession = require("./utils/editing-session");
loader.lazyRequireGetter(this, "EditingSession", "devtools/client/inspector/boxmodel/utils/editing-session");
loader.lazyRequireGetter(this, "InplaceEditor", "devtools/client/shared/inplace-editor", true);
loader.lazyRequireGetter(this, "getCssProperties", "devtools/shared/fronts/css-properties", true);
const NUMERIC = /^-?[\d\.]+$/;

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

@ -4,7 +4,7 @@
"use strict";
const { getCssProperties } = require("devtools/shared/fronts/css-properties");
loader.lazyRequireGetter(this, "getCssProperties", "devtools/shared/fronts/css-properties", true);
/**
* An instance of EditingSession tracks changes that have been made during the
@ -22,12 +22,20 @@ const { getCssProperties } = require("devtools/shared/fronts/css-properties");
*/
function EditingSession({inspector, doc, elementRules}) {
this._doc = doc;
this._inspector = inspector;
this._rules = elementRules;
this._modifications = new Map();
this._cssProperties = getCssProperties(inspector.toolbox);
}
EditingSession.prototype = {
get cssProperties() {
if (!this._cssProperties) {
this._cssProperties = getCssProperties(this._inspector.toolbox);
}
return this._cssProperties;
},
/**
* Gets the value of a single property from the CSS rule.
*
@ -112,8 +120,7 @@ EditingSession.prototype = {
// StyleRuleActor to make changes to CSS properties.
// Note that RuleRewriter doesn't support modifying several properties at
// once, so we do this in a sequence here.
let modifications = this._rules[0].startModifyingProperties(
this._cssProperties);
let modifications = this._rules[0].startModifyingProperties(this.cssProperties);
// Remember the property so it can be reverted.
if (!this._modifications.has(property.name)) {
@ -147,8 +154,7 @@ EditingSession.prototype = {
// Revert each property that we modified previously, one by one. See
// setProperties for information about why.
for (let [property, value] of this._modifications) {
let modifications = this._rules[0].startModifyingProperties(
this._cssProperties);
let modifications = this._rules[0].startModifyingProperties(this.cssProperties);
// Find the index of the property to be reverted.
let index = this.getPropertyIndex(property);
@ -174,9 +180,13 @@ EditingSession.prototype = {
},
destroy: function() {
this._doc = null;
this._rules = null;
this._modifications.clear();
this._cssProperties = null;
this._doc = null;
this._inspector = null;
this._modifications = null;
this._rules = null;
}
};

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

@ -22,10 +22,11 @@ const {
VIEW_NODE_IMAGE_URL_TYPE,
VIEW_NODE_FONT_TYPE,
} = require("devtools/client/inspector/shared/node-types");
const StyleInspectorMenu = require("devtools/client/inspector/shared/style-inspector-menu");
const TooltipsOverlay = require("devtools/client/inspector/shared/tooltips-overlay");
const KeyShortcuts = require("devtools/client/shared/key-shortcuts");
const clipboardHelper = require("devtools/shared/platform/clipboard");
loader.lazyRequireGetter(this, "StyleInspectorMenu", "devtools/client/inspector/shared/style-inspector-menu");
loader.lazyRequireGetter(this, "KeyShortcuts", "devtools/client/shared/key-shortcuts");
loader.lazyRequireGetter(this, "clipboardHelper", "devtools/shared/platform/clipboard");
const STYLE_INSPECTOR_PROPERTIES = "devtools/shared/locales/styleinspector.properties";
const {LocalizationHelper} = require("devtools/shared/l10n");
@ -203,8 +204,6 @@ function CssComputedView(inspector, document, pageStyle) {
this.createStyleViews();
this._contextmenu = new StyleInspectorMenu(this, { isRuleView: false });
// Add the tooltips and highlightersoverlay
this.tooltips = new TooltipsOverlay(this);
@ -243,6 +242,14 @@ CssComputedView.prototype = {
// Number of visible properties
numVisibleProperties: 0,
get contextMenu() {
if (!this._contextMenu) {
this._contextMenu = new StyleInspectorMenu(this, { isRuleView: false });
}
return this._contextMenu;
},
setPageStyle: function(pageStyle) {
this.pageStyle = pageStyle;
},
@ -672,7 +679,7 @@ CssComputedView.prototype = {
* Context menu handler.
*/
_onContextMenu: function(event) {
this._contextmenu.show(event);
this.contextMenu.show(event);
},
_onClick: function(event) {
@ -733,10 +740,9 @@ CssComputedView.prototype = {
this._refreshProcess.cancel();
}
// Remove context menu
if (this._contextmenu) {
this._contextmenu.destroy();
this._contextmenu = null;
if (this._contextMenu) {
this._contextMenu.destroy();
this._contextMenu = null;
}
this.tooltips.destroy();

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

@ -164,7 +164,7 @@ function getComputedViewLinkByIndex(view, index) {
*/
function selectAllText(view) {
info("Selecting all the text");
view._contextmenu._onSelectAll();
view.contextMenu._onSelectAll();
}
/**

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

@ -13,7 +13,6 @@ const promise = require("promise");
const EventEmitter = require("devtools/shared/event-emitter");
const {executeSoon} = require("devtools/shared/DevToolsUtils");
const {Toolbox} = require("devtools/client/framework/toolbox");
const {PrefObserver} = require("devtools/client/shared/prefs");
const Telemetry = require("devtools/client/shared/telemetry");
const HighlightersOverlay = require("devtools/client/inspector/shared/highlighters-overlay");
const ReflowTracker = require("devtools/client/inspector/shared/reflow-tracker");
@ -26,6 +25,7 @@ const Promise = require("Promise");
loader.lazyRequireGetter(this, "initCssProperties", "devtools/shared/fronts/css-properties", true);
loader.lazyRequireGetter(this, "HTMLBreadcrumbs", "devtools/client/inspector/breadcrumbs", true);
loader.lazyRequireGetter(this, "ThreePaneOnboardingTooltip", "devtools/client/inspector/shared/three-pane-onboarding-tooltip");
loader.lazyRequireGetter(this, "KeyShortcuts", "devtools/client/shared/key-shortcuts");
loader.lazyRequireGetter(this, "InspectorSearch", "devtools/client/inspector/inspector-search", true);
loader.lazyRequireGetter(this, "ToolSidebar", "devtools/client/inspector/toolsidebar", true);
@ -55,6 +55,7 @@ const PORTRAIT_MODE_WIDTH_THRESHOLD = 700;
// mode.
const SIDE_PORTAIT_MODE_WIDTH_THRESHOLD = 1000;
const SHOW_THREE_PANE_ONBOARDING_PREF = "devtools.inspector.show-three-pane-tooltip";
const SHOW_THREE_PANE_TOGGLE_PREF = "devtools.inspector.three-pane-toggle";
const THREE_PANE_ENABLED_PREF = "devtools.inspector.three-pane-enabled";
const THREE_PANE_ENABLED_SCALAR = "devtools.inspector.three_pane_enabled";
@ -111,7 +112,6 @@ function Inspector(toolbox) {
this._panels = new Map();
this.highlighters = new HighlightersOverlay(this);
this.prefsObserver = new PrefObserver("devtools.");
this.reflowTracker = new ReflowTracker(this._target);
this.styleChangeTracker = new InspectorStyleChangeTracker(this);
this.telemetry = new Telemetry();
@ -120,8 +120,9 @@ function Inspector(toolbox) {
// telemetry counts in the Grid Inspector are not double counted on reload.
this.previousURL = this.target.url;
this.show3PaneToggle = Services.prefs.getBoolPref(SHOW_THREE_PANE_TOGGLE_PREF);
this.is3PaneModeEnabled = Services.prefs.getBoolPref(THREE_PANE_ENABLED_PREF);
this.show3PaneToggle = Services.prefs.getBoolPref(SHOW_THREE_PANE_TOGGLE_PREF);
this.show3PaneTooltip = Services.prefs.getBoolPref(SHOW_THREE_PANE_ONBOARDING_PREF);
this.nodeMenuTriggerInfo = null;
@ -296,6 +297,10 @@ Inspector.prototype = {
// Setup the toolbar only now because it may depend on the document.
await this.setupToolbar();
if (this.show3PaneTooltip) {
this.threePaneTooltip = new ThreePaneOnboardingTooltip(this.toolbox, this.panelDoc);
}
// Log the 3 pane inspector setting on inspector open. The question we want to answer
// is:
// "What proportion of users use the 3 pane vs 2 pane inspector on inspector open?"
@ -460,6 +465,22 @@ Inspector.prototype = {
return this._InspectorTabPanel;
},
get InspectorSplitBox() {
if (!this._InspectorSplitBox) {
this._InspectorSplitBox = this.React.createFactory(this.browserRequire(
"devtools/client/shared/components/splitter/SplitBox"));
}
return this._InspectorSplitBox;
},
get TabBar() {
if (!this._TabBar) {
this._TabBar = this.React.createFactory(this.browserRequire(
"devtools/client/shared/components/tabs/TabBar"));
}
return this._TabBar;
},
/**
* Check if the inspector should use the landscape mode.
*
@ -477,11 +498,9 @@ Inspector.prototype = {
* the Inspector panel.
*/
setupSplitter: function() {
let SplitBox = this.React.createFactory(this.browserRequire(
"devtools/client/shared/components/splitter/SplitBox"));
let { width, height, splitSidebarWidth } = this.getSidebarSize();
let splitter = SplitBox({
let splitter = this.InspectorSplitBox({
className: "inspector-sidebar-splitter",
initialWidth: width,
initialHeight: height,
@ -492,7 +511,7 @@ Inspector.prototype = {
startPanel: this.InspectorTabPanel({
id: "inspector-main-content"
}),
endPanel: SplitBox({
endPanel: this.InspectorSplitBox({
initialWidth: splitSidebarWidth,
minSize: 10,
maxSize: "80%",
@ -1329,6 +1348,9 @@ Inspector.prototype = {
this.cancelUpdate();
this.selection.off("new-node-front", this.onNewSelection);
this.selection.off("detached-front", this.onDetached);
this.sidebar.off("select", this.onSidebarSelect);
this.target.off("will-navigate", this._onBeforeNavigate);
this.target.off("thread-paused", this.updateDebuggerPausedWarning);
this.target.off("thread-resumed", this.updateDebuggerPausedWarning);
@ -1351,25 +1373,21 @@ Inspector.prototype = {
this.animationinspector.destroy();
}
if (this.threePaneTooltip) {
this.threePaneTooltip.destroy();
}
let cssPropertiesDestroyer = this._cssProperties.front.destroy();
this.sidebar.off("select", this.onSidebarSelect);
let sidebarDestroyer = this.sidebar.destroy();
let ruleViewSideBarDestroyer = this.ruleViewSideBar ?
this.ruleViewSideBar.destroy() : null;
let markupDestroyer = this._destroyMarkup();
let highlighterDestroyer = this.highlighters.destroy();
this.teardownSplitter();
this.teardownToolbar();
this.breadcrumbs.destroy();
this.selection.off("new-node-front", this.onNewSelection);
this.selection.off("detached-front", this.onDetached);
let markupDestroyer = this._destroyMarkup();
let highlighterDestroyer = this.highlighters.destroy();
this.prefsObserver.destroy();
this.reflowTracker.destroy();
this.styleChangeTracker.destroy();
this.search.destroy();
@ -1381,14 +1399,15 @@ Inspector.prototype = {
this.panelDoc = null;
this.panelWin.inspector = null;
this.panelWin = null;
this.prefsObserver = null;
this.resultsLength = null;
this.search = null;
this.searchBox = null;
this.show3PaneToggle = null;
this.show3PaneTooltip = null;
this.sidebar = null;
this.store = null;
this.target = null;
this.threePaneTooltip = null;
this._panelDestroyer = promise.all([
highlighterDestroyer,

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

@ -15,7 +15,6 @@ const {PrefObserver} = require("devtools/client/shared/prefs");
const ElementStyle = require("devtools/client/inspector/rules/models/element-style");
const Rule = require("devtools/client/inspector/rules/models/rule");
const RuleEditor = require("devtools/client/inspector/rules/views/rule-editor");
const ClassListPreviewer = require("devtools/client/inspector/rules/views/class-list-previewer");
const {getCssProperties} = require("devtools/shared/fronts/css-properties");
const {
VIEW_NODE_SELECTOR_TYPE,
@ -28,15 +27,17 @@ const {
VIEW_NODE_VARIABLE_TYPE,
VIEW_NODE_FONT_TYPE,
} = require("devtools/client/inspector/shared/node-types");
const StyleInspectorMenu = require("devtools/client/inspector/shared/style-inspector-menu");
const TooltipsOverlay = require("devtools/client/inspector/shared/tooltips-overlay");
const {createChild, promiseWarn} = require("devtools/client/inspector/shared/utils");
const {debounce} = require("devtools/shared/debounce");
const EventEmitter = require("devtools/shared/event-emitter");
const KeyShortcuts = require("devtools/client/shared/key-shortcuts");
const clipboardHelper = require("devtools/shared/platform/clipboard");
const AutocompletePopup = require("devtools/client/shared/autocomplete-popup");
loader.lazyRequireGetter(this, "ClassListPreviewer", "devtools/client/inspector/rules/views/class-list-previewer");
loader.lazyRequireGetter(this, "StyleInspectorMenu", "devtools/client/inspector/shared/style-inspector-menu");
loader.lazyRequireGetter(this, "KeyShortcuts", "devtools/client/shared/key-shortcuts");
loader.lazyRequireGetter(this, "clipboardHelper", "devtools/shared/platform/clipboard");
const HTML_NS = "http://www.w3.org/1999/xhtml";
const PREF_UA_STYLES = "devtools.inspector.showUserAgentStyles";
const PREF_DEFAULT_COLOR_UNIT = "devtools.defaultColorUnit";
@ -183,14 +184,10 @@ function CssRuleView(inspector, document, store, pageStyle) {
this._showEmpty();
this._contextmenu = new StyleInspectorMenu(this, { isRuleView: true });
// Add the tooltips and highlighters to the view
this.tooltips = new TooltipsOverlay(this);
this.highlighters.addToView(this);
this.classListPreviewer = new ClassListPreviewer(this.inspector, this.classPanel);
}
CssRuleView.prototype = {
@ -204,6 +201,22 @@ CssRuleView.prototype = {
// to figure out how shorthand properties will be parsed.
_dummyElement: null,
get classListPreviewer() {
if (!this._classListPreviewer) {
this._classListPreviewer = new ClassListPreviewer(this.inspector, this.classPanel);
}
return this._classListPreviewer;
},
get contextMenu() {
if (!this._contextMenu) {
this._contextMenu = new StyleInspectorMenu(this, { isRuleView: true });
}
return this._contextMenu;
},
// Get the dummy elemenet.
get dummyElement() {
return this._dummyElement;
@ -445,7 +458,7 @@ CssRuleView.prototype = {
event.stopPropagation();
event.preventDefault();
this._contextmenu.show(event);
this.contextMenu.show(event);
},
/**
@ -725,15 +738,18 @@ CssRuleView.prototype = {
this._outputParser = null;
// Remove context menu
if (this._contextmenu) {
this._contextmenu.destroy();
this._contextmenu = null;
if (this._classListPreviewer) {
this._classListPreviewer.destroy();
this._classListPreviewer = null;
}
if (this._contextMenu) {
this._contextMenu.destroy();
this._contextMenu = null;
}
this.tooltips.destroy();
this.highlighters.removeFromView(this);
this.classListPreviewer.destroy();
this.unselectAllRules();
// Remove bound listeners

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

@ -90,7 +90,7 @@ async function checkSelectAll(view) {
info("Checking that _SelectAll() then copy returns the correct " +
"clipboard value");
view._contextmenu._onSelectAll();
view.contextMenu._onSelectAll();
let expectedPattern = "element {[\\r\\n]+" +
" margin: 10em;[\\r\\n]+" +
" font-size: 14pt;[\\r\\n]+" +

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

@ -227,6 +227,8 @@ function ClassListPreviewer(inspector, containerEl) {
this.inspector.selection.on("new-node-front", this.onNewSelection);
this.containerEl.addEventListener("input", this.onCheckBoxChanged);
this.model.on("current-node-class-changed", this.onCurrentNodeClassChanged);
this.onNewSelection();
}
ClassListPreviewer.prototype = {

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

@ -11,6 +11,7 @@ DevToolsModules(
'reflow-tracker.js',
'style-change-tracker.js',
'style-inspector-menu.js',
'three-pane-onboarding-tooltip.js',
'tooltips-overlay.js',
'utils.js'
)

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

@ -7,10 +7,6 @@
"use strict";
const Services = require("Services");
const Menu = require("devtools/client/framework/menu");
const MenuItem = require("devtools/client/framework/menu-item");
const {
VIEW_NODE_SELECTOR_TYPE,
VIEW_NODE_PROPERTY_TYPE,
@ -18,7 +14,10 @@ const {
VIEW_NODE_IMAGE_URL_TYPE,
VIEW_NODE_LOCATION_TYPE,
} = require("devtools/client/inspector/shared/node-types");
const clipboardHelper = require("devtools/shared/platform/clipboard");
loader.lazyRequireGetter(this, "Menu", "devtools/client/framework/menu");
loader.lazyRequireGetter(this, "MenuItem", "devtools/client/framework/menu-item");
loader.lazyRequireGetter(this, "clipboardHelper", "devtools/shared/platform/clipboard");
const STYLE_INSPECTOR_PROPERTIES = "devtools/shared/locales/styleinspector.properties";
const {LocalizationHelper} = require("devtools/shared/l10n");

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

@ -68,13 +68,13 @@ function testIsColorPopupOnAllNodes(view) {
function testIsColorPopupOnNode(view, node) {
info("Testing node " + node);
view.styleDocument.popupNode = node;
view._contextmenu._colorToCopy = "";
view.contextMenu._colorToCopy = "";
let result = view._contextmenu._isColorPopup();
let result = view.contextMenu._isColorPopup();
let correct = isColorValueNode(node);
is(result, correct, "_isColorPopup returned the expected value " + correct);
is(view._contextmenu._colorToCopy, (correct) ? "rgb(18, 58, 188)" : "",
is(view.contextMenu._colorToCopy, (correct) ? "rgb(18, 58, 188)" : "",
"_colorToCopy was set to the expected value");
}

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

@ -67,7 +67,7 @@ async function testManualEdit(inspector, view) {
view.styleDocument.popupNode = colorValueElement;
let contextMenu = view._contextmenu;
let contextMenu = view.contextMenu;
contextMenu._isColorPopup();
is(contextMenu._colorToCopy, newColor, "_colorToCopy has the new value");
}
@ -93,7 +93,7 @@ async function testColorPickerEdit(inspector, view) {
"data-color was updated");
view.styleDocument.popupNode = swatchElement;
let contextMenu = view._contextmenu;
let contextMenu = view.contextMenu;
contextMenu._isColorPopup();
is(contextMenu._colorToCopy, rgbaColorText, "_colorToCopy has the new value");
}

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

@ -0,0 +1,110 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const Services = require("Services");
const { openWebLink } = require("devtools/client/shared/link");
const { HTMLTooltip } = require("devtools/client/shared/widgets/tooltip/HTMLTooltip");
const { LocalizationHelper } = require("devtools/shared/l10n");
const L10N = new LocalizationHelper("devtools/client/locales/inspector.properties");
const SHOW_THREE_PANE_ONBOARDING_PREF = "devtools.inspector.show-three-pane-tooltip";
const XHTML_NS = "http://www.w3.org/1999/xhtml";
const CONTAINER_WIDTH = 300;
const LEARN_MORE_LINK = "https://developer.mozilla.org/en-US/docs/Tools/Page_Inspector/Use_the_3-pane_inspector?utm_source=devtools&utm_medium=3-pane-onboarding";
/**
* Three pane inspector onboarding tooltip that is shown on the 3 pane inspector toggle
* button when the pref is on.
*/
class ThreePaneOnboardingTooltip {
constructor(toolbox, doc) {
this.toolbox = toolbox;
this.doc = doc;
this.tooltip = new HTMLTooltip(this.toolbox.doc, {
type: "arrow",
useXulWrapper: true,
});
this.onCloseButtonClick = this.onCloseButtonClick.bind(this);
this.onLearnMoreLinkClick = this.onLearnMoreLinkClick.bind(this);
const container = doc.createElementNS(XHTML_NS, "div");
container.className = "three-pane-onboarding-container";
const icon = doc.createElementNS(XHTML_NS, "span");
icon.className = "three-pane-onboarding-icon";
container.appendChild(icon);
const content = doc.createElementNS(XHTML_NS, "div");
content.className = "three-pane-onboarding-content";
container.appendChild(content);
const message = doc.createElementNS(XHTML_NS, "div");
const learnMoreString = L10N.getStr("inspector.threePaneOnboarding.learnMoreLink");
const messageString = L10N.getFormatStr("inspector.threePaneOnboarding.content",
learnMoreString);
const learnMoreStartIndex = messageString.indexOf(learnMoreString);
message.append(messageString.substring(0, learnMoreStartIndex));
this.learnMoreLink = doc.createElementNS(XHTML_NS, "a");
this.learnMoreLink.className = "three-pane-onboarding-link";
this.learnMoreLink.href = "#";
this.learnMoreLink.textContent = learnMoreString;
message.append(this.learnMoreLink);
message.append(messageString.substring(learnMoreStartIndex + learnMoreString.length));
content.append(message);
this.closeButton = doc.createElementNS(XHTML_NS, "button");
this.closeButton.className = "three-pane-onboarding-close-button devtools-button";
container.appendChild(this.closeButton);
this.closeButton.addEventListener("click", this.onCloseButtonClick);
this.learnMoreLink.addEventListener("click", this.onLearnMoreLinkClick);
this.tooltip.setContent(container, { width: CONTAINER_WIDTH });
this.tooltip.show(this.doc.querySelector("#inspector-sidebar .sidebar-toggle"), {
position: "top",
});
}
destroy() {
this.closeButton.removeEventListener("click", this.onCloseButtonClick);
this.learnMoreLink.removeEventListener("click", this.onLearnMoreLinkClick);
this.tooltip.destroy();
this.closeButton = null;
this.doc = null;
this.learnMoreLink = null;
this.toolbox = null;
this.tooltip = null;
}
/**
* Handler for the "click" event on the close button. Hides the onboarding tooltip
* and sets the show three pane onboarding tooltip pref to false.
*/
onCloseButtonClick() {
Services.prefs.setBoolPref(SHOW_THREE_PANE_ONBOARDING_PREF, false);
this.tooltip.hide();
}
/**
* Handler for the "click" event on the learn more button. Hides the onboarding tooltip
* and opens the link to the mdn page in a new tab.
*/
onLearnMoreLinkClick() {
Services.prefs.setBoolPref(SHOW_THREE_PANE_ONBOARDING_PREF, false);
this.tooltip.hide();
openWebLink(LEARN_MORE_LINK);
}
}
module.exports = ThreePaneOnboardingTooltip;

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

@ -594,7 +594,7 @@ function buildContextMenuItems(menu) {
* @return An array of MenuItems
*/
function openStyleContextMenuAndGetAllItems(view, target) {
const menu = view._contextmenu._openMenu({target: target});
const menu = view.contextMenu._openMenu({target: target});
return buildContextMenuItems(menu);
}

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

@ -68,13 +68,14 @@ ToolSidebar.prototype = {
return this._toolPanel.InspectorTabPanel;
},
get TabBar() {
return this._toolPanel.TabBar;
},
// Rendering
render: function() {
let Tabbar = this.React.createFactory(this.browserRequire(
"devtools/client/shared/components/tabs/TabBar"));
let sidebar = Tabbar({
let sidebar = this.TabBar({
menuDocument: this._toolPanel._toolbox.doc,
showAllTabsMenu: true,
sidebarToggleButton: this._options.sidebarToggleButton,

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

@ -117,6 +117,7 @@ devtools.jar:
skin/images/breadcrumbs-divider.svg (themes/images/breadcrumbs-divider.svg)
skin/images/filters.svg (themes/images/filters.svg)
skin/images/filter-swatch.svg (themes/images/filter-swatch.svg)
skin/images/fox-smiling.svg (themes/images/fox-smiling.svg)
skin/images/grid.svg (themes/images/grid.svg)
skin/images/angle-swatch.svg (themes/images/angle-swatch.svg)
skin/images/pseudo-class.svg (themes/images/pseudo-class.svg)

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

@ -464,3 +464,11 @@ inspector.classPanel.noClasses=No classes on this element
# properties to display e.g. due to search criteria this message is
# displayed.
inspector.noProperties=No CSS properties found.
# LOCALIZATION NOTE (inspector.threePaneOnboarding.content,
# inspector.threePaneOnboarding.learnMoreLink): This is the content shown in the 3 pane
# inspector onboarding tooltip that is displayed on top of the 3 pane inspector toggle
# button. %S in the content will be replaced by a link at run time with the learnMoreLink
# string.
inspector.threePaneOnboarding.content=New: 3-pane mode lets you see both CSS rules and Layout tools. Click this button to toggle. %S
inspector.threePaneOnboarding.learnMoreLink=Learn more

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

@ -57,6 +57,12 @@ pref("devtools.inspector.three-pane-toggle", false);
#endif
// Enable the 3 pane mode in the inspector
pref("devtools.inspector.three-pane-enabled", false);
// Show the 3 pane onboarding tooltip in the inspector
#if defined(NIGHTLY_BUILD)
pref("devtools.inspector.show-three-pane-tooltip", true);
#else
pref("devtools.inspector.show-three-pane-tooltip", false);
#endif
// Collapse pseudo-elements by default in the rule-view
pref("devtools.inspector.show_pseudo_elements", false);
// The default size for image preview tooltips in the rule-view/computed-view/markup-view
@ -288,12 +294,8 @@ pref("devtools.webconsole.timestampMessages", false);
// to automatically trigger multiline editing (equivalent to shift + enter).
pref("devtools.webconsole.autoMultiline", true);
// Enable the webconsole sidebar toggle in Nightly builds.
#if defined(NIGHTLY_BUILD)
pref("devtools.webconsole.sidebarToggle", true);
#else
// Enable the webconsole sidebar toggle
pref("devtools.webconsole.sidebarToggle", false);
#endif
// Disable the new performance recording panel by default
pref("devtools.performance.new-panel-enabled", false);

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

@ -108,8 +108,10 @@ function loadFrameScriptUtils(browser = gBrowser.selectedBrowser) {
return mm;
}
Services.prefs.setBoolPref("devtools.inspector.show-three-pane-tooltip", false);
registerCleanupFunction(() => {
Services.prefs.clearUserPref("devtools.dump.emit");
Services.prefs.clearUserPref("devtools.inspector.show-three-pane-tooltip");
Services.prefs.clearUserPref("devtools.toolbox.host");
Services.prefs.clearUserPref("devtools.toolbox.previousHost");
Services.prefs.clearUserPref("devtools.toolbox.splitconsoleEnabled");

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

@ -0,0 +1,37 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="72px" height="72px" viewBox="0 0 72 72" enable-background="new 0 0 72 72" xml:space="preserve">
<path fill="#FFD8CA" d="M30.4,61C15.5,60,7.7,54.7,0.3,41.4C0.1,41.1,0,40.7,0,40.4h8.5l0-3.2h0c0-0.2,0-0.4,0-0.6
c0-4.9,3.9-8.8,8.8-8.8c4.9,0,8.8,3.9,8.8,8.8c0,0.2,0,0.4,0,0.6h0v15.7C26.1,56.2,27.8,59.2,30.4,61z M63.5,40.4v-3.2h0
c0-0.2,0-0.5,0-0.7c0-4.9-3.9-8.8-8.8-8.8c-4.8,0-8.7,3.8-8.8,8.5v0.5c0,0.2,0,0.3,0,0.5h0v15.7c0,3.4-1.7,6.3-4.3,8.1
c14.9-1,22.7-6.2,30.1-19.5c0.2-0.3,0.3-0.7,0.2-1.1H63.5z"/>
<path fill="#FF6F1F" d="M42.5,60.3c0.1,0,0.1-0.1,0.2-0.1c0.2-0.2,0.4-0.4,0.6-0.6c0.1-0.1,0.1-0.1,0.2-0.2c0.2-0.2,0.4-0.5,0.6-0.7
c0,0,0.1-0.1,0.1-0.1c0.2-0.3,0.4-0.6,0.6-1c0,0,0,0,0,0c0.2-0.3,0.3-0.6,0.4-1c0-0.1,0.1-0.2,0.1-0.3c0.1-0.2,0.2-0.5,0.2-0.7
c0-0.1,0.1-0.2,0.1-0.4c0.1-0.3,0.1-0.5,0.1-0.8c0-0.1,0-0.2,0.1-0.3c0-0.4,0.1-0.8,0.1-1.1v-1.2V37.1h0c0-0.2,0-0.3,0-0.5v-0.5
c0.1-4.7,4-8.5,8.8-8.5c4.9,0,8.8,3.9,8.8,8.8c0,0.2,0,0.5,0,0.7h0v3.2H72c0-0.4-0.1-0.8-0.3-1.1c-2-3.7-4.1-7.2-6.3-10.4
c1.6-1.2,2.9-2.8,4-4.6c3-5.2,2.8-11.3,0.1-16.2c-0.2-0.3-0.5-0.5-0.9-0.5c-5.5,0-10.4,3-13.4,8.2c-0.4,0.6-0.7,1.3-1,1.9
C49.2,14.7,43.4,13,36,13s-13.2,1.8-18.1,4.8c-0.3-0.7-0.6-1.3-1-1.9c-3-5.2-7.9-8.2-13.4-8.2c-0.4,0-0.7,0.2-0.9,0.5
c-2.7,4.8-2.9,11,0.1,16.2c1.1,1.8,2.4,3.3,4,4.6C4.4,32,2.3,35.5,0.3,39.3C0.1,39.6,0,40,0,40.4h8.5l0-3.2h0c0-0.2,0-0.4,0-0.6
c0-4.9,3.9-8.8,8.8-8.8c4.9,0,8.8,3.9,8.8,8.8c0,0.2,0,0.4,0,0.6h0v14.5v1.2c0,0.4,0,0.8,0.1,1.1c0,0.1,0,0.2,0.1,0.3
c0,0.3,0.1,0.5,0.1,0.8c0,0.1,0.1,0.2,0.1,0.4c0.1,0.3,0.2,0.5,0.2,0.7c0,0.1,0.1,0.2,0.1,0.3c0.1,0.3,0.3,0.6,0.4,1c0,0,0,0,0,0
c0.2,0.3,0.4,0.7,0.6,1c0,0,0.1,0.1,0.1,0.1c0.2,0.3,0.4,0.5,0.6,0.7c0.1,0.1,0.1,0.1,0.2,0.2c0.2,0.2,0.4,0.4,0.6,0.6
c0.1,0,0.1,0.1,0.2,0.1c0.3,0.2,0.6,0.5,0.9,0.7c1.6,1.1,3.5,1.7,5.6,1.7c2.1,0,4-0.6,5.6-1.7C41.9,60.8,42.2,60.6,42.5,60.3z"/>
<g>
<path fill="#2B3B47" d="M32.9,45.7c0,0,0.4,0,1,0c0.6,0,1.3,0,2.1,0c0.8,0,1.5,0,2.1,0c0.6,0,1-0.1,1-0.1c1.2-0.1,2.3,0.8,2.4,2.1
c0.1,0.6-0.2,1.3-0.6,1.7l-1.9,2.1c0,0-0.4,0.4-1,0.7c-0.3,0.2-0.6,0.3-1,0.4c-0.2,0.1-0.4,0.1-0.6,0.1c-0.2,0-0.4,0-0.6,0
c-0.2,0-0.4,0-0.6,0c-0.2,0-0.4-0.1-0.6-0.1c-0.2,0-0.4-0.1-0.5-0.2c-0.2,0-0.3-0.1-0.5-0.2c-0.6-0.3-1-0.6-1-0.6l-1.8-1.8
c-0.9-0.9-0.9-2.4,0-3.3C31.6,45.9,32.3,45.6,32.9,45.7z"/>
</g>
<path fill="#2B3B47" stroke="#2B3B47" stroke-width="1.0904" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
M30.6,55c0,0,2.1,1.3,5.4,1.3s5.4-1.3,5.4-1.3s-0.3,4.9-5.4,4.9S30.6,55,30.6,55z"/>
<path fill="#2B3B47" d="M17.3,32.5c1.7,0,3,1.3,3,3v6.8c0,1.7-1.3,3-3,3l0,0c-1.7,0-3-1.3-3-3v-6.8C14.3,33.8,15.7,32.5,17.3,32.5
L17.3,32.5z"/>
<path fill="#2B3B47" d="M54.8,32.5c1.7,0,3,1.3,3,3v6.8c0,1.7-1.3,3-3,3l0,0c-1.7,0-3-1.3-3-3v-6.8C51.8,33.8,53.1,32.5,54.8,32.5
L54.8,32.5z"/>
<path fill="#2B3B47" d="M57.3,20.1c3.6-8,10-11.5,11.5-12.3c0,0,0-0.1,0-0.1c-0.1,0-0.2,0-0.3,0c-0.1,0-0.3,0-0.4,0
c-0.2,0-0.4,0-0.6,0c-0.1,0-0.1,0-0.2,0c-5.1,0.4-9.5,3.3-12.3,8.1c-0.4,0.6-0.7,1.3-1,1.9C55.2,18.5,56.3,19.2,57.3,20.1z"/>
<path fill="#2B3B47" d="M14.7,20.1c1.1-0.9,2.3-1.8,3.6-2.5c-0.2-0.7-0.5-1.3-0.9-1.8c-3.1-5.2-8.6-8.1-14.2-8.1
c-0.1,0-0.1,0.1,0,0.2C4.7,8.5,11.1,12.1,14.7,20.1z"/>
</svg>

После

Ширина:  |  Высота:  |  Размер: 3.4 KiB

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

@ -13,11 +13,15 @@
.theme-dark {
--bezier-diagonal-color: #eee;
--bezier-grid-color: rgba(0, 0, 0, 0.2);
--onboarding-link-color: var(--theme-highlight-blue);
--onboarding-link-active-color: var(--blue-40);
}
.theme-light {
--bezier-diagonal-color: rgba(0, 0, 0, 0.2);
--bezier-grid-color: rgba(0, 0, 0, 0.05);
--onboarding-link-color: var(--blue-60);
--onboarding-link-active-color: var(--blue-70);
}
/* Tooltip widget (see devtools/client/shared/widgets/tooltip/Tooltip.js) */
@ -480,3 +484,53 @@
height: 100%;
padding: 7px;
}
/* Tooltip: 3 Pane Inspecot Onboarding Tooltip */
.three-pane-onboarding-container {
align-items: center;
background-color: var(--theme-toolbar-background);
box-sizing: border-box;
color: var(--theme-body-color);
display: flex;
font-size: 12px;
padding: 7px;
width: 100%;
-moz-user-select: none;
}
.three-pane-onboarding-icon {
display: inline-block;
background-size: 21px;
width: 21px;
height: 21px;
margin: 8px;
background-image: url("chrome://devtools/skin/images/fox-smiling.svg");
}
.three-pane-onboarding-content {
flex: 1;
padding-inline-start: 5px;
}
.three-pane-onboarding-link {
color: var(--onboarding-link-color);
cursor: pointer;
}
.three-pane-onboarding-link:hover {
text-decoration: underline;
}
.three-pane-onboarding-link:active {
color: var(--onboarding-link-active-color);
}
.three-pane-onboarding-close-button {
align-self: flex-start;
}
.three-pane-onboarding-close-button::before {
background-image: url("chrome://devtools/skin/images/close.svg");
margin: -6px 0 0 -6px;
}

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

@ -214,6 +214,7 @@
--purple-60: #8000d7;
--blue-40: #45a1ff;
--blue-50: #0a84ff;
--blue-55: #0074e8;
--blue-60: #0060df;

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

@ -32,8 +32,7 @@ add_task(async function() {
"#console-menu-store (S) [disabled]",
"#console-menu-copy (C)",
"#console-menu-copy-object (o) [disabled]",
"#console-menu-select (A)",
"#console-menu-open-sidebar (V) [disabled]",
"#console-menu-select (A)"
];
is(getSimplifiedContextMenu(menuPopup).join("\n"), expectedContextMenu.join("\n"),
"The context menu has the expected entries for a network message");
@ -52,8 +51,7 @@ add_task(async function() {
"#console-menu-store (S) [disabled]",
"#console-menu-copy (C)",
"#console-menu-copy-object (o) [disabled]",
"#console-menu-select (A)",
"#console-menu-open-sidebar (V) [disabled]",
"#console-menu-select (A)"
];
is(getSimplifiedContextMenu(menuPopup).join("\n"), expectedContextMenu.join("\n"),
"The context menu has the expected entries for a simple log message");

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

@ -36,6 +36,7 @@ class AccessibilityParent {
this.messageManager.sendAsyncMessage(`${this._msgName}:event`, {
topic: "initialized",
data: {
enabled: this.enabled,
canBeDisabled: this.canBeDisabled,
canBeEnabled: this.canBeEnabled
}

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

@ -1025,6 +1025,15 @@ const AccessibilityActor = ActorClassWithSpec(accessibilitySpec, {
case "initialized":
this._canBeEnabled = data.canBeEnabled;
this._canBeDisabled = data.canBeDisabled;
// Sometimes when the tool is reopened content process accessibility service is
// not shut down yet because GC did not run in that process (though it did in
// parent process and the service was shut down there). We need to sync the two
// services if possible.
if (!data.enabled && this.enabled && data.canBeEnabled) {
this.messageManager.sendAsyncMessage(this._msgName, { action: "enable" });
}
this.initializedDeferred.resolve();
break;
case "can-be-disabled-change":

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

@ -3246,7 +3246,7 @@ Element::GetEventTargetParentForLinks(EventChainPreVisitor& aVisitor)
nsAutoString target;
GetLinkTarget(target);
nsContentUtils::TriggerLink(this, aVisitor.mPresContext, absURI, target,
false, true, true);
/* click */ false, /* isTrusted */ true);
// Make sure any ancestor links don't also TriggerLink
aVisitor.mEvent->mFlags.mMultipleActionsPrevented = true;
}
@ -3358,7 +3358,7 @@ Element::PostHandleEventForLinks(EventChainPostVisitor& aVisitor)
const InternalUIEvent* activeEvent = aVisitor.mEvent->AsUIEvent();
MOZ_ASSERT(activeEvent);
nsContentUtils::TriggerLink(this, aVisitor.mPresContext, absURI, target,
true, true, activeEvent->IsTrustable());
/* click */ true, activeEvent->IsTrustable());
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
}
}

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

@ -5491,8 +5491,7 @@ nsContentUtils::CombineResourcePrincipals(nsCOMPtr<nsIPrincipal>* aResourcePrinc
void
nsContentUtils::TriggerLink(nsIContent *aContent, nsPresContext *aPresContext,
nsIURI *aLinkURI, const nsString &aTargetSpec,
bool aClick, bool aIsUserTriggered,
bool aIsTrusted)
bool aClick, bool aIsTrusted)
{
NS_ASSERTION(aPresContext, "Need a nsPresContext");
NS_PRECONDITION(aLinkURI, "No link URI");
@ -5515,10 +5514,7 @@ nsContentUtils::TriggerLink(nsIContent *aContent, nsPresContext *aPresContext,
nsresult proceed = NS_OK;
if (sSecurityManager) {
uint32_t flag =
aIsUserTriggered ?
(uint32_t)nsIScriptSecurityManager::STANDARD :
(uint32_t)nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT;
uint32_t flag = static_cast<uint32_t>(nsIScriptSecurityManager::STANDARD);
proceed =
sSecurityManager->CheckLoadURIWithPrincipal(aContent->NodePrincipal(),
aLinkURI, flag);

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

@ -1862,16 +1862,12 @@ public:
* @param aTargetSpec the target (like target=, may be empty).
* @param aClick whether this was a click or not (if false, this method
* assumes you just hovered over the link).
* @param aIsUserTriggered whether the user triggered the link. This would be
* false for loads from auto XLinks or from the
* click() method if we ever implement it.
* @param aIsTrusted If false, JS Context will be pushed to stack
* when the link is triggered.
*/
static void TriggerLink(nsIContent *aContent, nsPresContext *aPresContext,
nsIURI *aLinkURI, const nsString& aTargetSpec,
bool aClick, bool aIsUserTriggered,
bool aIsTrusted);
bool aClick, bool aIsTrusted);
/**
* Get the link location.

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

@ -161,75 +161,96 @@ IPCBlobInputStream::~IPCBlobInputStream()
NS_IMETHODIMP
IPCBlobInputStream::Available(uint64_t* aLength)
{
// We don't have a remoteStream yet: let's return 0.
if (mState == eInit || mState == ePending) {
*aLength = 0;
return NS_OK;
}
nsCOMPtr<nsIAsyncInputStream> asyncRemoteStream;
{
MutexAutoLock lock(mMutex);
if (mState == eRunning) {
// We don't have a remoteStream yet: let's return 0.
if (mState == eInit || mState == ePending) {
*aLength = 0;
return NS_OK;
}
if (mState == eClosed) {
return NS_BASE_STREAM_CLOSED;
}
MOZ_ASSERT(mState == eRunning);
MOZ_ASSERT(mRemoteStream || mAsyncRemoteStream);
nsresult rv = EnsureAsyncRemoteStream();
nsresult rv = EnsureAsyncRemoteStream(lock);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
MOZ_ASSERT(mAsyncRemoteStream);
return mAsyncRemoteStream->Available(aLength);
asyncRemoteStream = mAsyncRemoteStream;
}
MOZ_ASSERT(mState == eClosed);
return NS_BASE_STREAM_CLOSED;
MOZ_ASSERT(asyncRemoteStream);
return asyncRemoteStream->Available(aLength);
}
NS_IMETHODIMP
IPCBlobInputStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aReadCount)
{
// Read is not available is we don't have a remoteStream.
if (mState == eInit || mState == ePending) {
return NS_BASE_STREAM_WOULD_BLOCK;
}
nsCOMPtr<nsIAsyncInputStream> asyncRemoteStream;
{
MutexAutoLock lock(mMutex);
if (mState == eRunning) {
// Read is not available is we don't have a remoteStream.
if (mState == eInit || mState == ePending) {
return NS_BASE_STREAM_WOULD_BLOCK;
}
if (mState == eClosed) {
return NS_BASE_STREAM_CLOSED;
}
MOZ_ASSERT(mState == eRunning);
MOZ_ASSERT(mRemoteStream || mAsyncRemoteStream);
nsresult rv = EnsureAsyncRemoteStream();
nsresult rv = EnsureAsyncRemoteStream(lock);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
MOZ_ASSERT(mAsyncRemoteStream);
return mAsyncRemoteStream->Read(aBuffer, aCount, aReadCount);
asyncRemoteStream = mAsyncRemoteStream;
}
MOZ_ASSERT(mState == eClosed);
return NS_BASE_STREAM_CLOSED;
MOZ_ASSERT(asyncRemoteStream);
return asyncRemoteStream->Read(aBuffer, aCount, aReadCount);
}
NS_IMETHODIMP
IPCBlobInputStream::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
uint32_t aCount, uint32_t *aResult)
{
// ReadSegments is not available is we don't have a remoteStream.
if (mState == eInit || mState == ePending) {
return NS_BASE_STREAM_WOULD_BLOCK;
}
nsCOMPtr<nsIAsyncInputStream> asyncRemoteStream;
{
MutexAutoLock lock(mMutex);
if (mState == eRunning) {
// ReadSegments is not available is we don't have a remoteStream.
if (mState == eInit || mState == ePending) {
return NS_BASE_STREAM_WOULD_BLOCK;
}
if (mState == eClosed) {
return NS_BASE_STREAM_CLOSED;
}
MOZ_ASSERT(mState == eRunning);
MOZ_ASSERT(mRemoteStream || mAsyncRemoteStream);
nsresult rv = EnsureAsyncRemoteStream();
nsresult rv = EnsureAsyncRemoteStream(lock);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
MOZ_ASSERT(mAsyncRemoteStream);
return mAsyncRemoteStream->ReadSegments(aWriter, aClosure, aCount, aResult);
asyncRemoteStream = mAsyncRemoteStream;
}
MOZ_ASSERT(mState == eClosed);
return NS_BASE_STREAM_CLOSED;
MOZ_ASSERT(asyncRemoteStream);
return asyncRemoteStream->ReadSegments(aWriter, aClosure, aCount, aResult);
}
NS_IMETHODIMP
@ -242,32 +263,36 @@ IPCBlobInputStream::IsNonBlocking(bool* aNonBlocking)
NS_IMETHODIMP
IPCBlobInputStream::Close()
{
if (mActor) {
mActor->ForgetStream(this);
mActor = nullptr;
}
if (mAsyncRemoteStream) {
mAsyncRemoteStream->CloseWithStatus(NS_BASE_STREAM_CLOSED);
mAsyncRemoteStream = nullptr;
}
if (mRemoteStream) {
mRemoteStream->Close();
mRemoteStream = nullptr;
}
nsCOMPtr<nsIAsyncInputStream> asyncRemoteStream;
nsCOMPtr<nsIInputStream> remoteStream;
{
MutexAutoLock lock(mMutex);
if (mActor) {
mActor->ForgetStream(this);
mActor = nullptr;
}
asyncRemoteStream.swap(mAsyncRemoteStream);
remoteStream.swap(mRemoteStream);
mInputStreamCallback = nullptr;
mInputStreamCallbackEventTarget = nullptr;
mFileMetadataCallback = nullptr;
mFileMetadataCallbackEventTarget = nullptr;
mState = eClosed;
}
mFileMetadataCallback = nullptr;
mFileMetadataCallbackEventTarget = nullptr;
if (asyncRemoteStream) {
asyncRemoteStream->CloseWithStatus(NS_BASE_STREAM_CLOSED);
}
if (remoteStream) {
remoteStream->Close();
}
mState = eClosed;
return NS_OK;
}
@ -276,6 +301,7 @@ IPCBlobInputStream::Close()
NS_IMETHODIMP
IPCBlobInputStream::GetCloneable(bool* aCloneable)
{
MutexAutoLock lock(mMutex);
*aCloneable = mState != eClosed;
return NS_OK;
}
@ -283,6 +309,8 @@ IPCBlobInputStream::GetCloneable(bool* aCloneable)
NS_IMETHODIMP
IPCBlobInputStream::Clone(nsIInputStream** aResult)
{
MutexAutoLock lock(mMutex);
if (mState == eClosed) {
return NS_BASE_STREAM_CLOSED;
}
@ -294,7 +322,7 @@ IPCBlobInputStream::Clone(nsIInputStream** aResult)
return NS_ERROR_FAILURE;
}
stream->InitWithExistingRange(mStart, mLength);
stream->InitWithExistingRange(mStart, mLength, lock);
stream.forget(aResult);
return NS_OK;
@ -306,6 +334,8 @@ NS_IMETHODIMP
IPCBlobInputStream::CloneWithRange(uint64_t aStart, uint64_t aLength,
nsIInputStream** aResult)
{
MutexAutoLock lock(mMutex);
if (mState == eClosed) {
return NS_BASE_STREAM_CLOSED;
}
@ -332,7 +362,7 @@ IPCBlobInputStream::CloneWithRange(uint64_t aStart, uint64_t aLength,
aLength = streamSize.value();
}
stream->InitWithExistingRange(aStart + mStart, aLength);
stream->InitWithExistingRange(aStart + mStart, aLength, lock);
stream.forget(aResult);
return NS_OK;
@ -351,56 +381,63 @@ IPCBlobInputStream::AsyncWait(nsIInputStreamCallback* aCallback,
uint32_t aFlags, uint32_t aRequestedCount,
nsIEventTarget* aEventTarget)
{
// See IPCBlobInputStream.h for more information about this state machine.
switch (mState) {
// First call, we need to retrieve the stream from the parent actor.
case eInit:
MOZ_ASSERT(mActor);
mInputStreamCallback = aCallback;
mInputStreamCallbackEventTarget = aEventTarget;
mState = ePending;
mActor->StreamNeeded(this, aEventTarget);
return NS_OK;
// We are still waiting for the remote inputStream
case ePending: {
nsCOMPtr<nsIAsyncInputStream> asyncRemoteStream;
{
MutexAutoLock lock(mMutex);
if (mInputStreamCallback && aCallback) {
return NS_ERROR_FAILURE;
}
// See IPCBlobInputStream.h for more information about this state machine.
mInputStreamCallback = aCallback;
mInputStreamCallbackEventTarget = aEventTarget;
return NS_OK;
}
switch (mState) {
// First call, we need to retrieve the stream from the parent actor.
case eInit:
MOZ_ASSERT(mActor);
// We have the remote inputStream, let's check if we can execute the callback.
case eRunning: {
{
MutexAutoLock lock(mMutex);
mInputStreamCallback = aCallback;
mInputStreamCallbackEventTarget = aEventTarget;
mState = ePending;
mActor->StreamNeeded(this, aEventTarget);
return NS_OK;
// We are still waiting for the remote inputStream
case ePending: {
if (mInputStreamCallback && aCallback) {
return NS_ERROR_FAILURE;
}
mInputStreamCallback = aCallback;
mInputStreamCallbackEventTarget = aEventTarget;
return NS_OK;
}
nsresult rv = EnsureAsyncRemoteStream();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
// We have the remote inputStream, let's check if we can execute the callback.
case eRunning: {
if (mInputStreamCallback && aCallback) {
return NS_ERROR_FAILURE;
}
nsresult rv = EnsureAsyncRemoteStream(lock);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
mInputStreamCallback = aCallback;
mInputStreamCallbackEventTarget = aEventTarget;
asyncRemoteStream = mAsyncRemoteStream;
break;
}
MOZ_ASSERT(mAsyncRemoteStream);
return mAsyncRemoteStream->AsyncWait(aCallback ? this : nullptr,
0, 0, aEventTarget);
// Stream is closed.
default:
MOZ_ASSERT(mState == eClosed);
return NS_BASE_STREAM_CLOSED;
}
}
// Stream is closed.
default:
MOZ_ASSERT(mState == eClosed);
return NS_BASE_STREAM_CLOSED;
}
MOZ_ASSERT(asyncRemoteStream);
return asyncRemoteStream->AsyncWait(aCallback ? this : nullptr,
0, 0, aEventTarget);
}
void
@ -408,14 +445,6 @@ IPCBlobInputStream::StreamReady(already_AddRefed<nsIInputStream> aInputStream)
{
nsCOMPtr<nsIInputStream> inputStream = Move(aInputStream);
// We have been closed in the meantime.
if (mState == eClosed) {
if (inputStream) {
inputStream->Close();
}
return;
}
// If inputStream is null, it means that the serialization went wrong or the
// stream is not available anymore. We keep the state as pending just to block
// any additional operation.
@ -424,22 +453,50 @@ IPCBlobInputStream::StreamReady(already_AddRefed<nsIInputStream> aInputStream)
return;
}
// Now it's the right time to apply a slice if needed.
if (mStart > 0 || mLength < mActor->Size()) {
inputStream =
new SlicedInputStream(inputStream.forget(), mStart, mLength);
}
mRemoteStream = inputStream;
MOZ_ASSERT(mState == ePending);
mState = eRunning;
nsCOMPtr<nsIFileMetadataCallback> fileMetadataCallback;
fileMetadataCallback.swap(mFileMetadataCallback);
nsCOMPtr<nsIEventTarget> fileMetadataCallbackEventTarget;
fileMetadataCallbackEventTarget.swap(mFileMetadataCallbackEventTarget);
nsCOMPtr<nsIInputStreamCallback> inputStreamCallback;
nsCOMPtr<nsIEventTarget> inputStreamCallbackEventTarget;
nsCOMPtr<nsIAsyncInputStream> asyncRemoteStream;
{
MutexAutoLock lock(mMutex);
// We have been closed in the meantime.
if (mState == eClosed) {
if (inputStream) {
MutexAutoUnlock unlock(mMutex);
inputStream->Close();
}
return;
}
// Now it's the right time to apply a slice if needed.
if (mStart > 0 || mLength < mActor->Size()) {
inputStream =
new SlicedInputStream(inputStream.forget(), mStart, mLength);
}
mRemoteStream = inputStream;
MOZ_ASSERT(mState == ePending);
mState = eRunning;
fileMetadataCallback.swap(mFileMetadataCallback);
fileMetadataCallbackEventTarget.swap(mFileMetadataCallbackEventTarget);
inputStreamCallback = mInputStreamCallback ? this : nullptr;
inputStreamCallbackEventTarget = mInputStreamCallbackEventTarget;
if (inputStreamCallback) {
nsresult rv = EnsureAsyncRemoteStream(lock);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
MOZ_ASSERT(mAsyncRemoteStream);
asyncRemoteStream = mAsyncRemoteStream;
}
}
if (fileMetadataCallback) {
FileMetadataCallbackRunnable::Execute(fileMetadataCallback,
@ -447,32 +504,18 @@ IPCBlobInputStream::StreamReady(already_AddRefed<nsIInputStream> aInputStream)
this);
}
nsCOMPtr<nsIInputStreamCallback> inputStreamCallback = this;
nsCOMPtr<nsIEventTarget> inputStreamCallbackEventTarget;
{
MutexAutoLock lock(mMutex);
inputStreamCallbackEventTarget = mInputStreamCallbackEventTarget;
if (!mInputStreamCallback) {
inputStreamCallback = nullptr;
}
}
if (inputStreamCallback) {
nsresult rv = EnsureAsyncRemoteStream();
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
MOZ_ASSERT(asyncRemoteStream);
MOZ_ASSERT(mAsyncRemoteStream);
rv = mAsyncRemoteStream->AsyncWait(inputStreamCallback, 0, 0,
inputStreamCallbackEventTarget);
nsresult rv = asyncRemoteStream->AsyncWait(inputStreamCallback, 0, 0,
inputStreamCallbackEventTarget);
Unused << NS_WARN_IF(NS_FAILED(rv));
}
}
void
IPCBlobInputStream::InitWithExistingRange(uint64_t aStart, uint64_t aLength)
IPCBlobInputStream::InitWithExistingRange(uint64_t aStart, uint64_t aLength,
const MutexAutoLock& aProofOfLock)
{
MOZ_ASSERT(mActor->Size() >= aStart + aLength);
mStart = aStart;
@ -529,6 +572,8 @@ void
IPCBlobInputStream::Serialize(mozilla::ipc::InputStreamParams& aParams,
FileDescriptorArray& aFileDescriptors)
{
MutexAutoLock lock(mMutex);
mozilla::ipc::IPCBlobInputStreamParams params;
params.id() = mActor->ID();
params.start() = mStart;
@ -554,8 +599,8 @@ IPCBlobInputStream::ExpectedSerializedLength()
// nsIAsyncFileMetadata
NS_IMETHODIMP
IPCBlobInputStream::AsyncWait(nsIFileMetadataCallback* aCallback,
nsIEventTarget* aEventTarget)
IPCBlobInputStream::AsyncFileMetadataWait(nsIFileMetadataCallback* aCallback,
nsIEventTarget* aEventTarget)
{
MOZ_ASSERT(!!aCallback == !!aEventTarget);
@ -566,38 +611,46 @@ IPCBlobInputStream::AsyncWait(nsIFileMetadataCallback* aCallback,
// See IPCBlobInputStream.h for more information about this state machine.
switch (mState) {
// First call, we need to retrieve the stream from the parent actor.
case eInit:
MOZ_ASSERT(mActor);
{
MutexAutoLock lock(mMutex);
mFileMetadataCallback = aCallback;
mFileMetadataCallbackEventTarget = aEventTarget;
mState = ePending;
switch (mState) {
// First call, we need to retrieve the stream from the parent actor.
case eInit:
MOZ_ASSERT(mActor);
mActor->StreamNeeded(this, aEventTarget);
return NS_OK;
mFileMetadataCallback = aCallback;
mFileMetadataCallbackEventTarget = aEventTarget;
mState = ePending;
// We are still waiting for the remote inputStream
case ePending:
if (mFileMetadataCallback && aCallback) {
return NS_ERROR_FAILURE;
mActor->StreamNeeded(this, aEventTarget);
return NS_OK;
// We are still waiting for the remote inputStream
case ePending:
if (mFileMetadataCallback && aCallback) {
return NS_ERROR_FAILURE;
}
mFileMetadataCallback = aCallback;
mFileMetadataCallbackEventTarget = aEventTarget;
return NS_OK;
// We have the remote inputStream, let's check if we can execute the callback.
case eRunning:
break;
// Stream is closed.
default:
MOZ_ASSERT(mState == eClosed);
return NS_BASE_STREAM_CLOSED;
}
mFileMetadataCallback = aCallback;
mFileMetadataCallbackEventTarget = aEventTarget;
return NS_OK;
// We have the remote inputStream, let's check if we can execute the callback.
case eRunning:
FileMetadataCallbackRunnable::Execute(aCallback, aEventTarget, this);
return NS_OK;
// Stream is closed.
default:
MOZ_ASSERT(mState == eClosed);
return NS_BASE_STREAM_CLOSED;
MOZ_ASSERT(mState == eRunning);
}
FileMetadataCallbackRunnable::Execute(aCallback, aEventTarget, this);
return NS_OK;
}
// nsIFileMetadata
@ -605,9 +658,13 @@ IPCBlobInputStream::AsyncWait(nsIFileMetadataCallback* aCallback,
NS_IMETHODIMP
IPCBlobInputStream::GetSize(int64_t* aRetval)
{
nsCOMPtr<nsIFileMetadata> fileMetadata = do_QueryInterface(mRemoteStream);
if (!fileMetadata) {
return mState == eClosed ? NS_BASE_STREAM_CLOSED : NS_ERROR_FAILURE;
nsCOMPtr<nsIFileMetadata> fileMetadata;
{
MutexAutoLock lock(mMutex);
fileMetadata = do_QueryInterface(mRemoteStream);
if (!fileMetadata) {
return mState == eClosed ? NS_BASE_STREAM_CLOSED : NS_ERROR_FAILURE;
}
}
return fileMetadata->GetSize(aRetval);
@ -616,9 +673,13 @@ IPCBlobInputStream::GetSize(int64_t* aRetval)
NS_IMETHODIMP
IPCBlobInputStream::GetLastModified(int64_t* aRetval)
{
nsCOMPtr<nsIFileMetadata> fileMetadata = do_QueryInterface(mRemoteStream);
if (!fileMetadata) {
return mState == eClosed ? NS_BASE_STREAM_CLOSED : NS_ERROR_FAILURE;
nsCOMPtr<nsIFileMetadata> fileMetadata;
{
MutexAutoLock lock(mMutex);
fileMetadata = do_QueryInterface(mRemoteStream);
if (!fileMetadata) {
return mState == eClosed ? NS_BASE_STREAM_CLOSED : NS_ERROR_FAILURE;
}
}
return fileMetadata->GetLastModified(aRetval);
@ -627,16 +688,20 @@ IPCBlobInputStream::GetLastModified(int64_t* aRetval)
NS_IMETHODIMP
IPCBlobInputStream::GetFileDescriptor(PRFileDesc** aRetval)
{
nsCOMPtr<nsIFileMetadata> fileMetadata = do_QueryInterface(mRemoteStream);
if (!fileMetadata) {
return mState == eClosed ? NS_BASE_STREAM_CLOSED : NS_ERROR_FAILURE;
nsCOMPtr<nsIFileMetadata> fileMetadata;
{
MutexAutoLock lock(mMutex);
fileMetadata = do_QueryInterface(mRemoteStream);
if (!fileMetadata) {
return mState == eClosed ? NS_BASE_STREAM_CLOSED : NS_ERROR_FAILURE;
}
}
return fileMetadata->GetFileDescriptor(aRetval);
}
nsresult
IPCBlobInputStream::EnsureAsyncRemoteStream()
IPCBlobInputStream::EnsureAsyncRemoteStream(const MutexAutoLock& aProofOfLock)
{
// We already have an async remote stream.
if (mAsyncRemoteStream) {

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

@ -45,10 +45,11 @@ private:
~IPCBlobInputStream();
nsresult
EnsureAsyncRemoteStream();
EnsureAsyncRemoteStream(const MutexAutoLock& aProofOfLock);
void
InitWithExistingRange(uint64_t aStart, uint64_t aLength);
InitWithExistingRange(uint64_t aStart, uint64_t aLength,
const MutexAutoLock& aProofOfLock);
RefPtr<IPCBlobInputStreamChild> mActor;
@ -80,7 +81,6 @@ private:
nsCOMPtr<nsIAsyncInputStream> mAsyncRemoteStream;
// These 2 values are set only if mState is ePending.
// They are protected by mutex.
nsCOMPtr<nsIInputStreamCallback> mInputStreamCallback;
nsCOMPtr<nsIEventTarget> mInputStreamCallbackEventTarget;
@ -88,6 +88,8 @@ private:
nsCOMPtr<nsIFileMetadataCallback> mFileMetadataCallback;
nsCOMPtr<nsIEventTarget> mFileMetadataCallbackEventTarget;
// Any member of this class is protected by mutex because touched on
// multiple threads.
Mutex mMutex;
};

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

@ -434,7 +434,7 @@ public:
RefPtr<ReleasingTimerHolder> holder =
new ReleasingTimerHolder(aURI, aBroadcastToOtherProcesses);
auto raii = mozilla::MakeScopeExit([&] {
auto raii = mozilla::MakeScopeExit([holder] {
holder->CancelTimerAndRevokeURI();
});

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

@ -4814,8 +4814,8 @@ nsresult HTMLMediaElement::InitializeDecoderForChannel(nsIChannel* aChannel,
NS_ASSERTION(!mimeType.IsEmpty(), "We should have the Content-Type.");
NS_ConvertUTF8toUTF16 mimeUTF16(mimeType);
HTMLMediaElement* self = this;
auto reportCanPlay = [&](bool aCanPlay) {
RefPtr<HTMLMediaElement> self = this;
auto reportCanPlay = [&, self](bool aCanPlay) {
diagnostics.StoreFormatDiagnostics(
self->OwnerDoc(), mimeUTF16, aCanPlay, __func__);
if (!aCanPlay) {
@ -4827,7 +4827,7 @@ nsresult HTMLMediaElement::InitializeDecoderForChannel(nsIChannel* aChannel,
}
};
auto onExit = MakeScopeExit([&] {
auto onExit = MakeScopeExit([self] {
if (self->mChannelLoader) {
self->mChannelLoader->Done();
self->mChannelLoader = nullptr;

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

@ -3555,7 +3555,8 @@ PreprocessHelper::WaitForStreamReady(nsIInputStream* aInputStream)
nsCOMPtr<nsIAsyncFileMetadata> asyncFileMetadata =
do_QueryInterface(aInputStream);
if (asyncFileMetadata) {
nsresult rv = asyncFileMetadata->AsyncWait(this, mTaskQueueEventTarget);
nsresult rv =
asyncFileMetadata->AsyncFileMetadataWait(this, mTaskQueueEventTarget);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}

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

@ -4270,7 +4270,7 @@ ContentParent::RecvRequestAnonymousTemporaryFile(const uint64_t& aID)
// Make sure to send a callback to the child if we bail out early.
nsresult rv = NS_OK;
RefPtr<ContentParent> self(this);
auto autoNotifyChildOnError = MakeScopeExit([&]() {
auto autoNotifyChildOnError = MakeScopeExit([&, self]() {
if (NS_FAILED(rv)) {
FileDescOrError result(rv);
Unused << self->SendProvideAnonymousTemporaryFile(aID, result);

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

@ -15,6 +15,7 @@
#include "nsIHttpChannelInternal.h"
#include "nsIInputStreamPump.h"
#include "nsIIOService.h"
#include "nsIOService.h"
#include "nsIProtocolHandler.h"
#include "nsIScriptError.h"
#include "nsIScriptSecurityManager.h"
@ -154,6 +155,18 @@ ChannelFromScriptURL(nsIPrincipal* principal,
uint32_t secFlags = aIsMainScript ? nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED
: nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS;
bool inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal(
principal, uri, true /* aInheritForAboutBlank */, false /* aForceInherit */);
bool isData = false;
rv = uri->SchemeIs("data", &isData);
NS_ENSURE_SUCCESS(rv, rv);
bool isURIUniqueOrigin = nsIOService::IsDataURIUniqueOpaqueOrigin() && isData;
if (inheritAttrs && !isURIUniqueOrigin) {
secFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
}
if (aWorkerScriptType == DebuggerScript) {
// A DebuggerScript needs to be a local resource like chrome: or resource:
bool isUIResource = false;
@ -172,8 +185,7 @@ ChannelFromScriptURL(nsIPrincipal* principal,
// Note: this is for backwards compatibility and goes against spec.
// We should find a better solution.
bool isData = false;
if (aIsMainScript && NS_SUCCEEDED(uri->SchemeIs("data", &isData)) && isData) {
if (aIsMainScript && isData) {
secFlags = nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL;
}

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

@ -43,6 +43,8 @@ WorkerHolder::HoldWorker(WorkerPrivate* aWorkerPrivate,
{
AssertOnOwningThread(mThread);
MOZ_ASSERT(aWorkerPrivate);
MOZ_ASSERT(aFailStatus >= Terminating);
aWorkerPrivate->AssertIsOnWorkerThread();
if (!aWorkerPrivate->AddHolder(this, aFailStatus)) {

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

@ -18,19 +18,19 @@ class WorkerPrivate;
* Use this chart to help figure out behavior during each of the closing
* statuses. Details below.
*
* +=============================================+
* | Closing Statuses |
* +=============+=============+=================+
* | status | clear queue | abort execution |
* +=============+=============+=================+
* | Closing | yes | no |
* +-------------+-------------+-----------------+
* | Terminating | yes | yes |
* +-------------+-------------+-----------------+
* | Canceling | yes | yes |
* +-------------+-------------+-----------------+
* | Killing | yes | yes |
* +-------------+-------------+-----------------+
* +========================================================+
* | Closing Statuses |
* +=============+=============+=================+==========+
* | status | clear queue | abort execution | notified |
* +=============+=============+=================+==========+
* | Closing | yes | no | no |
* +-------------+-------------+-----------------+----------+
* | Terminating | yes | yes | yes |
* +-------------+-------------+-----------------+----------+
* | Canceling | yes | yes | yes |
* +-------------+-------------+-----------------+----------+
* | Killing | yes | yes | yes |
* +-------------+-------------+-----------------+----------+
*/
enum WorkerStatus
@ -43,7 +43,9 @@ enum WorkerStatus
// Inner script called close() on the worker global scope. Setting this
// status causes the worker to clear its queue of events but does not abort
// the currently running script.
// the currently running script. WorkerHolder/WorkerRef objects are not going
// to be notified because the behavior of APIs/Components should not change
// during this status yet.
Closing,
// Outer script called terminate() on the worker or the worker object was

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

@ -16,6 +16,7 @@
#include "nsINetworkInterceptController.h"
#include "nsIProtocolHandler.h"
#include "nsITabChild.h"
#include "nsScriptSecurityManager.h"
#include "nsNetUtil.h"
namespace mozilla {
@ -379,11 +380,20 @@ WorkerLoadInfo::PrincipalURIMatchesScriptURL()
NS_ENSURE_SUCCESS(rv, false);
NS_ENSURE_TRUE(principalURI, false);
bool equal = false;
rv = principalURI->Equals(mBaseURI, &equal);
NS_ENSURE_SUCCESS(rv, false);
if (nsScriptSecurityManager::SecurityCompareURIs(mBaseURI, principalURI)) {
return true;
}
return equal;
// If strict file origin policy is in effect, local files will always fail
// SecurityCompareURIs unless they are identical. Explicitly check file origin
// policy, in that case.
if (nsScriptSecurityManager::GetStrictFileOriginPolicy() &&
NS_URIIsLocalFile(mBaseURI) &&
NS_RelaxStrictFileOriginPolicy(mBaseURI, principalURI)) {
return true;
}
return false;
}
#endif // MOZ_DIAGNOSTIC_ASSERT_ENABLED

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

@ -4058,11 +4058,7 @@ WorkerPrivate::NotifyHolders(WorkerStatus aStatus)
{
AssertIsOnWorkerThread();
NS_ASSERTION(aStatus > Running, "Bad status!");
if (aStatus >= Closing) {
CancelAllTimeouts();
}
NS_ASSERTION(aStatus > Closing, "Bad status!");
nsTObserverArray<WorkerHolder*>::ForwardIterator iter(mHolders);
while (iter.HasMore()) {
@ -4566,8 +4562,14 @@ WorkerPrivate::NotifyInternal(WorkerStatus aStatus)
MOZ_ASSERT(previousStatus != Pending);
if (aStatus >= Closing) {
CancelAllTimeouts();
}
// Let all our holders know the new status.
NotifyHolders(aStatus);
if (aStatus > Closing) {
NotifyHolders(aStatus);
}
// If this is the first time our status has changed then we need to clear the
// main event queue.

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

@ -67,11 +67,12 @@ UNIFIED_SOURCES += [
]
LOCAL_INCLUDES += [
'../base',
'../system',
'/caps',
'/dom/base',
'/dom/bindings',
'/dom/system',
'/js/xpconnect/loader',
'/netwerk/base',
'/xpcom/build',
'/xpcom/threads',
]

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

@ -9,3 +9,5 @@ support-files =
[browser_bug1047663.js]
[browser_bug1104623.js]
run-if = buildapp == 'browser'
[browser_fileURL.js]
support-files = empty.html empty_worker.js

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

@ -0,0 +1,127 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const WORKER_BODY = "postMessage(42);\n";
// file:// tests.
add_task(async function() {
info("Creating the tmp directory.");
let parent = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIDirectoryService)
.QueryInterface(Ci.nsIProperties)
.get('TmpD', Ci.nsIFile);
parent.append('worker-dir-test');
parent.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0o700);
let dir_a = parent.clone();
dir_a.append('a');
dir_a.create(Ci.nsIFile.DIRECTORY_TYPE, 0o700);
let page_a = dir_a.clone();
page_a.append('empty.html');
page_a.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
let url_a = Services.io.newFileURI(page_a)
let worker = dir_a.clone();
worker.append('worker.js');
let stream = Cc["@mozilla.org/network/file-output-stream;1"]
.createInstance(Ci.nsIFileOutputStream);
stream.init(worker, 0x02 | 0x08 | 0x20, // write, create, truncate
0o666, 0);
stream.write(WORKER_BODY, WORKER_BODY.length);
stream.close();
let url_worker = Services.io.newFileURI(worker);
let dir_b = parent.clone();
dir_b.append('b');
dir_b.create(Ci.nsIFile.DIRECTORY_TYPE, 0o700);
let page_b = dir_b.clone();
page_b.append('empty.html');
page_b.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
let url_b = Services.io.newFileURI(page_b)
let tab = BrowserTestUtils.addTab(gBrowser, url_a.spec);
gBrowser.selectedTab = tab;
let browser = gBrowser.getBrowserForTab(tab);
await BrowserTestUtils.browserLoaded(browser);
await ContentTask.spawn(browser, url_worker.spec, function(spec) {
return new content.Promise((resolve, reject) => {
let w = new content.window.Worker(spec);
w.onerror = _ => { reject(); }
w.onmessage = _ => { resolve() };
});
});
ok(true, "The worker is loaded when the script is on the same directory.");
BrowserTestUtils.removeTab(tab);
tab = BrowserTestUtils.addTab(gBrowser, url_b.spec);
gBrowser.selectedTab = tab;
browser = gBrowser.getBrowserForTab(tab);
await BrowserTestUtils.browserLoaded(browser);
await ContentTask.spawn(browser, url_worker.spec, function(spec) {
return new content.Promise((resolve, reject) => {
let w = new content.window.Worker(spec);
w.onerror = _ => { resolve(); }
w.onmessage = _ => { reject() };
});
});
ok(true, "The worker is not loaded when the script is on a different directory.");
BrowserTestUtils.removeTab(tab);
info("Removing the tmp directory.");
parent.remove(true);
});
const EMPTY_URL = "/browser/dom/workers/test/empty.html";
const WORKER_URL = "/browser/dom/workers/test/empty_worker.js";
add_task(async function() {
let tab = BrowserTestUtils.addTab(gBrowser, "http://mochi.test:8888" + EMPTY_URL);
gBrowser.selectedTab = tab;
let browser = gBrowser.getBrowserForTab(tab);
await BrowserTestUtils.browserLoaded(browser);
await ContentTask.spawn(browser, "http://example.org" + WORKER_URL, function(spec) {
return new content.Promise((resolve, reject) => {
let w = new content.window.Worker(spec);
w.onerror = _ => { resolve(); }
w.onmessage = _ => { reject() };
});
});
ok(true, "The worker is not loaded when the script is from different origin.");
BrowserTestUtils.removeTab(tab);
});
add_task(async function() {
let tab = BrowserTestUtils.addTab(gBrowser, "https://example.org" + EMPTY_URL);
gBrowser.selectedTab = tab;
let browser = gBrowser.getBrowserForTab(tab);
await BrowserTestUtils.browserLoaded(browser);
await ContentTask.spawn(browser, "http://example.org" + WORKER_URL, function(spec) {
return new content.Promise((resolve, reject) => {
let w = new content.window.Worker(spec);
w.onerror = _ => { resolve(); }
w.onmessage = _ => { reject() };
});
});
ok(true, "The worker is not loaded when the script is from different origin.");
BrowserTestUtils.removeTab(tab);
});

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

@ -0,0 +1 @@
postMessage(42);

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

@ -165,7 +165,10 @@ PaintThread::Init()
}
sThread = thread;
if (gfxPlatform::GetPlatform()->UsesTiling()) {
// Only create paint workers for tiling if we are using tiling or could
// expect to dynamically switch to tiling in the future
if (gfxPlatform::GetPlatform()->UsesTiling() ||
gfxPrefs::LayersTilesEnabledIfSkiaPOMTP()) {
int32_t paintWorkerCount = PaintThread::CalculatePaintWorkerCount();
mPaintWorkers = SharedThreadPool::Get(NS_LITERAL_CSTRING("PaintWorker"), paintWorkerCount);
}

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

@ -22,7 +22,11 @@
#include "nsSize.h" // for IntSize, nsSize
#include "nscore.h" // for NS_BUILD_REFCNT_LOGGING
#if !defined(ANDROID) && (defined(__SSE2__) || defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2))
#if defined(_MSC_VER) && !defined(__clang__)
#include "smmintrin.h"
#else
#include "emmintrin.h"
#endif
#endif
typedef mozilla::gfx::IntRect nsIntRect;

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

@ -620,7 +620,7 @@ private:
DECL_GFX_PREF(Once, "layers.offmainthreadcomposition.force-disabled", LayersOffMainThreadCompositionForceDisabled, bool, false);
DECL_GFX_PREF(Live, "layers.offmainthreadcomposition.frame-rate", LayersCompositionFrameRate, int32_t,-1);
DECL_GFX_PREF(Live, "layers.omtp.dump-capture", LayersOMTPDumpCapture, bool, false);
DECL_GFX_PREF(Live, "layers.omtp.paint-workers", LayersOMTPPaintWorkers, int32_t, 1);
DECL_GFX_PREF(Once, "layers.omtp.paint-workers", LayersOMTPPaintWorkers, int32_t, 1);
DECL_GFX_PREF(Live, "layers.omtp.release-capture-on-main-thread", LayersOMTPReleaseCaptureOnMainThread, bool, false);
DECL_GFX_PREF(Live, "layers.orientation.sync.timeout", OrientationSyncMillis, uint32_t, (uint32_t)0);
DECL_GFX_PREF(Once, "layers.prefer-opengl", LayersPreferOpenGL, bool, false);

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

@ -302,7 +302,7 @@ HadSimulatedInterrupt()
# define JS_INTERRUPT_POSSIBLY_FAIL() \
do { \
if (MOZ_UNLIKELY(js::oom::ShouldFailWithInterrupt())) { \
cx->interrupt_ = true; \
cx->requestInterrupt(js::InterruptReason::CallbackUrgent); \
return cx->handleInterrupt(); \
} \
} while (0)

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

@ -564,6 +564,43 @@ class MOZ_STACK_CLASS AutoInitializeSourceObject
}
};
// RAII class to check the frontend reports an exception when it fails to
// compile a script.
class MOZ_RAII AutoAssertReportedException
{
#ifdef DEBUG
JSContext* cx_;
bool check_;
public:
explicit AutoAssertReportedException(JSContext* cx)
: cx_(cx),
check_(true)
{}
void reset() {
check_ = false;
}
~AutoAssertReportedException() {
if (!check_)
return;
if (!cx_->helperThread()) {
MOZ_ASSERT(cx_->isExceptionPending());
return;
}
ParseTask* task = cx_->helperThread()->parseTask();
MOZ_ASSERT(task->outOfMemory ||
task->overRecursed ||
!task->errors.empty());
}
#else
public:
explicit AutoAssertReportedException(JSContext*) {}
void reset() {}
#endif
};
JSScript*
frontend::CompileGlobalScript(JSContext* cx, LifoAlloc& alloc, ScopeKind scopeKind,
const ReadOnlyCompileOptions& options,
@ -571,9 +608,14 @@ frontend::CompileGlobalScript(JSContext* cx, LifoAlloc& alloc, ScopeKind scopeKi
ScriptSourceObject** sourceObjectOut)
{
MOZ_ASSERT(scopeKind == ScopeKind::Global || scopeKind == ScopeKind::NonSyntactic);
AutoAssertReportedException assertException(cx);
BytecodeCompiler compiler(cx, alloc, options, srcBuf, /* enclosingScope = */ nullptr);
AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut);
return compiler.compileGlobalScript(scopeKind);
JSScript* script = compiler.compileGlobalScript(scopeKind);
if (!script)
return nullptr;
assertException.reset();
return script;
}
#if defined(JS_BUILD_BINAST)
@ -582,6 +624,8 @@ JSScript*
frontend::CompileGlobalBinASTScript(JSContext* cx, LifoAlloc& alloc, const ReadOnlyCompileOptions& options,
const uint8_t* src, size_t len)
{
AutoAssertReportedException assertException(cx);
frontend::UsedNameTracker usedNames(cx);
if (!usedNames.init())
return nullptr;
@ -617,6 +661,7 @@ frontend::CompileGlobalBinASTScript(JSContext* cx, LifoAlloc& alloc, const ReadO
if (!NameFunctions(cx, pn))
return nullptr;
assertException.reset();
return script;
}
@ -629,9 +674,15 @@ frontend::CompileEvalScript(JSContext* cx, LifoAlloc& alloc,
SourceBufferHolder& srcBuf,
ScriptSourceObject** sourceObjectOut)
{
AutoAssertReportedException assertException(cx);
BytecodeCompiler compiler(cx, alloc, options, srcBuf, enclosingScope);
AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut);
return compiler.compileEvalScript(environment, enclosingScope);
JSScript* script = compiler.compileEvalScript(environment, enclosingScope);
if (!script)
return nullptr;
assertException.reset();
return script;
}
ModuleObject*
@ -642,6 +693,8 @@ frontend::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& optionsInpu
MOZ_ASSERT(srcBuf.get());
MOZ_ASSERT_IF(sourceObjectOut, *sourceObjectOut == nullptr);
AutoAssertReportedException assertException(cx);
CompileOptions options(cx, optionsInput);
options.maybeMakeStrictMode(true); // ES6 10.2.1 Module code is always strict mode code.
options.setIsRunOnce(true);
@ -650,13 +703,20 @@ frontend::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& optionsInpu
RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
BytecodeCompiler compiler(cx, alloc, options, srcBuf, emptyGlobalScope);
AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut);
return compiler.compileModule();
ModuleObject* module = compiler.compileModule();
if (!module)
return nullptr;
assertException.reset();
return module;
}
ModuleObject*
frontend::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
SourceBufferHolder& srcBuf)
{
AutoAssertReportedException assertException(cx);
if (!GlobalObject::ensureModulePrototypesCreated(cx, cx->global()))
return nullptr;
@ -670,6 +730,7 @@ frontend::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
if (!ModuleObject::Freeze(cx, module))
return nullptr;
assertException.reset();
return module;
}
@ -678,6 +739,8 @@ frontend::CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const cha
{
MOZ_ASSERT(cx->compartment() == lazy->functionNonDelazifying()->compartment());
AutoAssertReportedException assertException(cx);
CompileOptions options(cx);
options.setMutedErrors(lazy->mutedErrors())
.setFileAndLine(lazy->filename(), lazy->lineno())
@ -745,6 +808,7 @@ frontend::CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const cha
if (!NameFunctions(cx, pn))
return false;
assertException.reset();
return true;
}
@ -755,14 +819,22 @@ frontend::CompileStandaloneFunction(JSContext* cx, MutableHandleFunction fun,
const Maybe<uint32_t>& parameterListEnd,
HandleScope enclosingScope /* = nullptr */)
{
AutoAssertReportedException assertException(cx);
RootedScope scope(cx, enclosingScope);
if (!scope)
scope = &cx->global()->emptyGlobalScope();
BytecodeCompiler compiler(cx, cx->tempLifoAlloc(), options, srcBuf, scope);
return compiler.compileStandaloneFunction(fun, GeneratorKind::NotGenerator,
FunctionAsyncKind::SyncFunction,
parameterListEnd);
if (!compiler.compileStandaloneFunction(fun, GeneratorKind::NotGenerator,
FunctionAsyncKind::SyncFunction,
parameterListEnd))
{
return false;
}
assertException.reset();
return true;
}
bool
@ -771,12 +843,20 @@ frontend::CompileStandaloneGenerator(JSContext* cx, MutableHandleFunction fun,
JS::SourceBufferHolder& srcBuf,
const Maybe<uint32_t>& parameterListEnd)
{
AutoAssertReportedException assertException(cx);
RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
BytecodeCompiler compiler(cx, cx->tempLifoAlloc(), options, srcBuf, emptyGlobalScope);
return compiler.compileStandaloneFunction(fun, GeneratorKind::Generator,
FunctionAsyncKind::SyncFunction,
parameterListEnd);
if (!compiler.compileStandaloneFunction(fun, GeneratorKind::Generator,
FunctionAsyncKind::SyncFunction,
parameterListEnd))
{
return false;
}
assertException.reset();
return true;
}
bool
@ -785,12 +865,20 @@ frontend::CompileStandaloneAsyncFunction(JSContext* cx, MutableHandleFunction fu
JS::SourceBufferHolder& srcBuf,
const Maybe<uint32_t>& parameterListEnd)
{
AutoAssertReportedException assertException(cx);
RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
BytecodeCompiler compiler(cx, cx->tempLifoAlloc(), options, srcBuf, emptyGlobalScope);
return compiler.compileStandaloneFunction(fun, GeneratorKind::NotGenerator,
FunctionAsyncKind::AsyncFunction,
parameterListEnd);
if (!compiler.compileStandaloneFunction(fun, GeneratorKind::NotGenerator,
FunctionAsyncKind::AsyncFunction,
parameterListEnd))
{
return false;
}
assertException.reset();
return true;
}
bool
@ -799,10 +887,18 @@ frontend::CompileStandaloneAsyncGenerator(JSContext* cx, MutableHandleFunction f
JS::SourceBufferHolder& srcBuf,
const Maybe<uint32_t>& parameterListEnd)
{
AutoAssertReportedException assertException(cx);
RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
BytecodeCompiler compiler(cx, cx->tempLifoAlloc(), options, srcBuf, emptyGlobalScope);
return compiler.compileStandaloneFunction(fun, GeneratorKind::Generator,
FunctionAsyncKind::AsyncFunction,
parameterListEnd);
if (!compiler.compileStandaloneFunction(fun, GeneratorKind::Generator,
FunctionAsyncKind::AsyncFunction,
parameterListEnd))
{
return false;
}
assertException.reset();
return true;
}

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

@ -314,7 +314,7 @@ GCRuntime::gcIfNeededAtAllocation(JSContext* cx)
// Invoking the interrupt callback can fail and we can't usefully
// handle that here. Just check in case we need to collect instead.
if (cx->hasPendingInterrupt())
if (cx->hasAnyPendingInterrupt())
gcIfRequested();
// If we have grown past our GC heap threshold while in the middle of

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

@ -1321,8 +1321,8 @@ GCRuntime::finish()
* memory.
*/
helperState.finish();
allocTask.cancel(GCParallelTask::CancelAndWait);
decommitTask.cancel(GCParallelTask::CancelAndWait);
allocTask.cancelAndWait();
decommitTask.cancelAndWait();
#ifdef JS_GC_ZEAL
/* Free memory associated with GC verification. */
@ -3285,11 +3285,7 @@ GCRuntime::requestMajorGC(JS::gcreason::Reason reason)
return;
majorGCTriggerReason = reason;
// There's no need to use RequestInterruptUrgent here. It's slower because
// it has to interrupt (looping) Ion code, but loops in Ion code that
// affect GC will have an explicit interrupt check.
rt->mainContextFromOwnThread()->requestInterrupt(JSContext::RequestInterruptCanWait);
rt->mainContextFromOwnThread()->requestInterrupt(InterruptReason::GC);
}
void
@ -3302,9 +3298,7 @@ Nursery::requestMinorGC(JS::gcreason::Reason reason) const
return;
minorGCTriggerReason_ = reason;
// See comment in requestMajorGC.
runtime()->mainContextFromOwnThread()->requestInterrupt(JSContext::RequestInterruptCanWait);
runtime()->mainContextFromOwnThread()->requestInterrupt(InterruptReason::GC);
}
bool
@ -7465,7 +7459,7 @@ GCRuntime::gcCycle(bool nonincrementalByAPI, SliceBudget& budget, JS::gcreason::
// avoid taking the GC lock when manipulating the chunks during the GC.
// The background alloc task can run between slices, so we must wait
// for it at the start of every slice.
allocTask.cancel(GCParallelTask::CancelAndWait);
allocTask.cancelAndWait();
}
// We don't allow off-thread parsing to start while we're doing an
@ -7788,7 +7782,7 @@ void
GCRuntime::onOutOfMallocMemory()
{
// Stop allocating new chunks.
allocTask.cancel(GCParallelTask::CancelAndWait);
allocTask.cancelAndWait();
// Make sure we release anything queued for release.
decommitTask.join();

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

@ -20,12 +20,12 @@ class GCParallelTask
JSRuntime* const runtime_;
// The state of the parallel computation.
enum TaskState {
enum class State {
NotStarted,
Dispatched,
Finished,
Finished
};
UnprotectedData<TaskState> state;
UnprotectedData<State> state_;
// Amount of time this task took to execute.
MainThreadOrGCTaskData<mozilla::TimeDuration> duration_;
@ -34,15 +34,20 @@ class GCParallelTask
protected:
// A flag to signal a request for early completion of the off-thread task.
mozilla::Atomic<bool> cancel_;
mozilla::Atomic<bool, mozilla::MemoryOrdering::ReleaseAcquire> cancel_;
virtual void run() = 0;
public:
explicit GCParallelTask(JSRuntime* runtime) : runtime_(runtime), state(NotStarted), duration_(nullptr) {}
explicit GCParallelTask(JSRuntime* runtime)
: runtime_(runtime),
state_(State::NotStarted),
duration_(nullptr),
cancel_(false)
{}
GCParallelTask(GCParallelTask&& other)
: runtime_(other.runtime_),
state(other.state),
state_(other.state_),
duration_(nullptr),
cancel_(false)
{}
@ -69,17 +74,45 @@ class GCParallelTask
void runFromMainThread(JSRuntime* rt);
// Dispatch a cancelation request.
enum CancelMode { CancelNoWait, CancelAndWait};
void cancel(CancelMode mode = CancelNoWait) {
void cancelAndWait() {
cancel_ = true;
if (mode == CancelAndWait)
join();
join();
}
// Check if a task is actively running.
bool isRunningWithLockHeld(const AutoLockHelperThreadState& locked) const;
bool isRunningWithLockHeld(const AutoLockHelperThreadState& lock) const {
return isDispatched(lock);
}
bool isRunning() const;
private:
void assertNotStarted() const {
// Don't lock here because that adds extra synchronization in debug
// builds that may hide bugs. There's no race if the assertion passes.
MOZ_ASSERT(state_ == State::NotStarted);
}
bool isNotStarted(const AutoLockHelperThreadState& lock) const {
return state_ == State::NotStarted;
}
bool isDispatched(const AutoLockHelperThreadState& lock) const {
return state_ == State::Dispatched;
}
bool isFinished(const AutoLockHelperThreadState& lock) const {
return state_ == State::Finished;
}
void setDispatched(const AutoLockHelperThreadState& lock) {
MOZ_ASSERT(state_ == State::NotStarted);
state_ = State::Dispatched;
}
void setFinished(const AutoLockHelperThreadState& lock) {
MOZ_ASSERT(state_ == State::Dispatched);
state_ = State::Finished;
}
void setNotStarted(const AutoLockHelperThreadState& lock) {
MOZ_ASSERT(state_ == State::Finished);
state_ = State::NotStarted;
}
// This should be friended to HelperThread, but cannot be because it
// would introduce several circular dependencies.
public:

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

@ -318,7 +318,7 @@ class GCRuntime
void waitBackgroundSweepEnd() { helperState.waitBackgroundSweepEnd(); }
void waitBackgroundSweepOrAllocEnd() {
helperState.waitBackgroundSweepEnd();
allocTask.cancel(GCParallelTask::CancelAndWait);
allocTask.cancelAndWait();
}
#ifdef DEBUG

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

@ -566,12 +566,14 @@ NativeRegExpMacroAssembler::Backtrack()
{
JitSpew(SPEW_PREFIX "Backtrack");
// Check for an interrupt.
// Check for an urgent interrupt. We don't want to leave JIT code and enter
// the regex interpreter for non-urgent interrupts. Note that interruptBits_
// is a bitfield.
Label noInterrupt;
masm.branch32(Assembler::Equal,
AbsoluteAddress(cx->addressOfInterruptRegExpJit()),
Imm32(0),
&noInterrupt);
masm.branchTest32(Assembler::Zero,
AbsoluteAddress(cx->addressOfInterruptBits()),
Imm32(uint32_t(InterruptReason::CallbackUrgent)),
&noInterrupt);
masm.movePtr(ImmWord(RegExpRunStatus_Error), temp0);
masm.jump(&exit_label_);
masm.bind(&noInterrupt);

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

@ -0,0 +1,12 @@
// |jit-test| --arm-asm-nop-fill=1
var f = wasmEvalText(`(module (func (result i32) (param i32)
(block $0
(block $1
(block $2
(block $default
(br_table $0 $1 $2 $default (get_local 0))))))
(return (i32.const 0)))
(export "" 0)
)`).exports[""];
f(0);

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

@ -701,7 +701,7 @@ BaselineCompiler::emitInterruptCheck()
Label done;
masm.branch32(Assembler::Equal,
AbsoluteAddress(cx->addressOfInterrupt()), Imm32(0),
AbsoluteAddress(cx->addressOfInterruptBits()), Imm32(0),
&done);
prepareVMCall();

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

@ -12872,7 +12872,7 @@ CodeGenerator::visitInterruptCheck(LInterruptCheck* lir)
{
OutOfLineCode* ool = oolCallVM(InterruptCheckInfo, lir, ArgList(), StoreNothing());
const void* interruptAddr = gen->runtime->addressOfInterrupt();
const void* interruptAddr = gen->runtime->addressOfInterruptBits();
masm.branch32(Assembler::NotEqual, AbsoluteAddress(interruptAddr), Imm32(0), ool->entry());
masm.bind(ool->rejoin());
}
@ -13045,7 +13045,7 @@ CodeGenerator::visitNewTarget(LNewTarget *ins)
Label useNFormals;
size_t numFormalArgs = ins->mirRaw()->block()->info().funMaybeLazy()->nargs();
size_t numFormalArgs = ins->mirRaw()->block()->info().nargs();
masm.branchPtr(Assembler::Below, argvLen, Imm32(numFormalArgs),
&useNFormals);

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

@ -247,13 +247,14 @@ class CompileInfo
// If the script uses an environment in body, the environment chain
// will need to be observable.
needsBodyEnvironmentObject_ = script->needsBodyEnvironment();
funNeedsSomeEnvironmentObject_ = fun ? fun->needsSomeEnvironmentObject() : false;
}
explicit CompileInfo(unsigned nlocals)
: script_(nullptr), fun_(nullptr), osrPc_(nullptr),
analysisMode_(Analysis_None), scriptNeedsArgsObj_(false),
mayReadFrameArgsDirectly_(false), inlineScriptTree_(nullptr),
needsBodyEnvironmentObject_(false)
needsBodyEnvironmentObject_(false), funNeedsSomeEnvironmentObject_(false)
{
nimplicit_ = 0;
nargs_ = 0;
@ -484,7 +485,7 @@ class CompileInfo
if (thisSlotForDerivedClassConstructor_ && *thisSlotForDerivedClassConstructor_ == slot)
return true;
if (funMaybeLazy()->needsSomeEnvironmentObject() && slot == environmentChainSlot())
if (funNeedsSomeEnvironmentObject_ && slot == environmentChainSlot())
return true;
// If the function may need an arguments object, then make sure to
@ -574,6 +575,7 @@ class CompileInfo
// Whether a script needs environments within its body. This informs us
// that the environment chain is not easy to reconstruct.
bool needsBodyEnvironmentObject_;
bool funNeedsSomeEnvironmentObject_;
};
} // namespace jit

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

@ -114,9 +114,9 @@ CompileRuntime::addressOfJitStackLimit()
}
const void*
CompileRuntime::addressOfInterrupt()
CompileRuntime::addressOfInterruptBits()
{
return runtime()->mainContextFromAnyThread()->addressOfInterrupt();
return runtime()->mainContextFromAnyThread()->addressOfInterruptBits();
}
#ifdef DEBUG

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

@ -49,7 +49,7 @@ class CompileRuntime
const void* mainContextPtr();
const void* addressOfJitStackLimit();
const void* addressOfInterrupt();
const void* addressOfInterruptBits();
#ifdef DEBUG
bool isInsideNursery(gc::Cell* cell);

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

@ -2756,6 +2756,18 @@ Assembler::leaveNoPool()
m_buffer.leaveNoPool();
}
void
Assembler::enterNoNops()
{
m_buffer.enterNoNops();
}
void
Assembler::leaveNoNops()
{
m_buffer.leaveNoNops();
}
ptrdiff_t
Assembler::GetBranchOffset(const Instruction* i_)
{

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

@ -1958,6 +1958,8 @@ class Assembler : public AssemblerShared
void flushBuffer();
void enterNoPool(size_t maxInst);
void leaveNoPool();
void enterNoNops();
void leaveNoNops();
// This should return a BOffImm, but we didn't want to require everyplace
// that used the AssemblerBuffer to make that class.
static ptrdiff_t GetBranchOffset(const Instruction* i);
@ -2487,6 +2489,19 @@ class AutoForbidPools
}
};
// Forbids nop filling for testing purposes. Not nestable.
class AutoForbidNops
{
Assembler* masm_;
public:
explicit AutoForbidNops(Assembler* masm) : masm_(masm) {
masm_->enterNoNops();
}
~AutoForbidNops() {
masm_->leaveNoNops();
}
};
} // namespace jit
} // namespace js

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

@ -521,19 +521,32 @@ void PatchJump(CodeLocationJump& jump_, CodeLocationLabel label);
class AutoForbidPools
{
Assembler* asm_;
public:
AutoForbidPools(Assembler* asm_, size_t maxInst)
: asm_(asm_)
{
asm_->enterNoPool(maxInst);
}
~AutoForbidPools() {
asm_->leaveNoPool();
}
};
// Forbids nop filling for testing purposes. Not nestable.
class AutoForbidNops
{
Assembler* asm_;
public:
explicit AutoForbidNops(Assembler* asm_)
: asm_(asm_)
{
asm_->enterNoNops();
}
~AutoForbidNops() {
asm_->leaveNoNops();
}
};
} // namespace jit
} // namespace js

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

@ -286,6 +286,13 @@ class MozBaseAssembler : public js::jit::AssemblerShared {
armbuffer_.leaveNoPool();
}
void enterNoNops() {
armbuffer_.enterNoNops();
}
void leaveNoNops() {
armbuffer_.leaveNoNops();
}
public:
// Static interface used by IonAssemblerBufferWithConstantPools.
static void InsertIndexIntoTag(uint8_t* load, uint32_t index);

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

@ -642,6 +642,7 @@ struct AssemblerBufferWithConstantPools : public AssemblerBuffer<SliceSize, Inst
// followed.
const uint32_t nopFillInst_;
const unsigned nopFill_;
// For inhibiting the insertion of fill NOPs in the dynamic context in which
// they are being inserted.
bool inhibitNops_;
@ -1083,7 +1084,17 @@ struct AssemblerBufferWithConstantPools : public AssemblerBuffer<SliceSize, Inst
canNotPlacePool_ = false;
// Validate the maxInst argument supplied to enterNoPool().
MOZ_ASSERT(this->nextOffset().getOffset() - canNotPlacePoolStartOffset_ <= canNotPlacePoolMaxInst_ * InstSize);
MOZ_ASSERT(this->nextOffset().getOffset() - canNotPlacePoolStartOffset_ <=
canNotPlacePoolMaxInst_ * InstSize);
}
void enterNoNops() {
MOZ_ASSERT(!inhibitNops_);
inhibitNops_ = true;
}
void leaveNoNops() {
MOZ_ASSERT(inhibitNops_);
inhibitNops_ = false;
}
void align(unsigned alignment) {

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

@ -5725,13 +5725,13 @@ JS::InitConsumeStreamCallback(JSContext* cx, ConsumeStreamCallback callback)
JS_PUBLIC_API(void)
JS_RequestInterruptCallback(JSContext* cx)
{
cx->requestInterrupt(JSContext::RequestInterruptUrgent);
cx->requestInterrupt(InterruptReason::CallbackUrgent);
}
JS_PUBLIC_API(void)
JS_RequestInterruptCallbackCanWait(JSContext* cx)
{
cx->requestInterrupt(JSContext::RequestInterruptCanWait);
cx->requestInterrupt(InterruptReason::CallbackCanWait);
}
JS::AutoSetAsyncStackForNewCalls::AutoSetAsyncStackForNewCalls(

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

@ -1453,19 +1453,13 @@ js::GCParallelTask::~GCParallelTask()
// destructors run after those for derived classes' members, so a join in a
// base class can't ensure that the task is done using the members. All we
// can do now is check that someone has previously stopped the task.
#ifdef DEBUG
Maybe<AutoLockHelperThreadState> helperLock;
if (!HelperThreadState().isLockedByCurrentThread())
helperLock.emplace();
MOZ_ASSERT(state == NotStarted);
#endif
assertNotStarted();
}
bool
js::GCParallelTask::startWithLockHeld(AutoLockHelperThreadState& lock)
{
// Tasks cannot be started twice.
MOZ_ASSERT(state == NotStarted);
assertNotStarted();
// If we do the shutdown GC before running anything, we may never
// have initialized the helper threads. Just use the serial path
@ -1475,7 +1469,7 @@ js::GCParallelTask::startWithLockHeld(AutoLockHelperThreadState& lock)
if (!HelperThreadState().gcParallelWorklist(lock).append(this))
return false;
state = Dispatched;
setDispatched(lock);
HelperThreadState().notifyOne(GlobalHelperThreadState::PRODUCER, lock);
@ -1490,14 +1484,15 @@ js::GCParallelTask::start()
}
void
js::GCParallelTask::joinWithLockHeld(AutoLockHelperThreadState& locked)
js::GCParallelTask::joinWithLockHeld(AutoLockHelperThreadState& lock)
{
if (state == NotStarted)
if (isNotStarted(lock))
return;
while (state != Finished)
HelperThreadState().wait(locked, GlobalHelperThreadState::CONSUMER);
state = NotStarted;
while (!isFinished(lock))
HelperThreadState().wait(lock, GlobalHelperThreadState::CONSUMER);
setNotStarted(lock);
cancel_ = false;
}
@ -1523,7 +1518,7 @@ TimeSince(TimeStamp prev)
void
js::GCParallelTask::runFromMainThread(JSRuntime* rt)
{
MOZ_ASSERT(state == NotStarted);
assertNotStarted();
MOZ_ASSERT(js::CurrentThreadCanAccessRuntime(rt));
TimeStamp timeStart = TimeStamp::Now();
run();
@ -1531,13 +1526,15 @@ js::GCParallelTask::runFromMainThread(JSRuntime* rt)
}
void
js::GCParallelTask::runFromHelperThread(AutoLockHelperThreadState& locked)
js::GCParallelTask::runFromHelperThread(AutoLockHelperThreadState& lock)
{
MOZ_ASSERT(isDispatched(lock));
AutoSetContextRuntime ascr(runtime());
gc::AutoSetThreadIsPerformingGC performingGC;
{
AutoUnlockHelperThreadState parallelSection(locked);
AutoUnlockHelperThreadState parallelSection(lock);
TimeStamp timeStart = TimeStamp::Now();
TlsContext.get()->heapState = JS::HeapState::MajorCollecting;
run();
@ -1545,34 +1542,28 @@ js::GCParallelTask::runFromHelperThread(AutoLockHelperThreadState& locked)
duration_ = TimeSince(timeStart);
}
state = Finished;
HelperThreadState().notifyAll(GlobalHelperThreadState::CONSUMER, locked);
}
bool
js::GCParallelTask::isRunningWithLockHeld(const AutoLockHelperThreadState& locked) const
{
return state == Dispatched;
setFinished(lock);
HelperThreadState().notifyAll(GlobalHelperThreadState::CONSUMER, lock);
}
bool
js::GCParallelTask::isRunning() const
{
AutoLockHelperThreadState helperLock;
return isRunningWithLockHeld(helperLock);
AutoLockHelperThreadState lock;
return isRunningWithLockHeld(lock);
}
void
HelperThread::handleGCParallelWorkload(AutoLockHelperThreadState& locked)
HelperThread::handleGCParallelWorkload(AutoLockHelperThreadState& lock)
{
MOZ_ASSERT(HelperThreadState().canStartGCParallelTask(locked));
MOZ_ASSERT(HelperThreadState().canStartGCParallelTask(lock));
MOZ_ASSERT(idle());
TraceLoggerThread* logger = TraceLoggerForCurrentThread();
AutoTraceLog logCompile(logger, TraceLogger_GC);
currentTask.emplace(HelperThreadState().gcParallelWorklist(locked).popCopy());
gcParallelTask()->runFromHelperThread(locked);
currentTask.emplace(HelperThreadState().gcParallelWorklist(lock).popCopy());
gcParallelTask()->runFromHelperThread(lock);
currentTask.reset();
}
@ -1916,15 +1907,13 @@ HelperThread::handleIonWorkload(AutoLockHelperThreadState& locked)
FinishOffThreadIonCompile(builder, locked);
// Ping the main thread so that the compiled code can be incorporated at the
// next interrupt callback. Don't interrupt Ion code for this, as this
// incorporation can be delayed indefinitely without affecting performance
// as long as the main thread is actually executing Ion code.
// next interrupt callback.
//
// This must happen before the current task is reset. DestroyContext
// cancels in progress Ion compilations before destroying its target
// context, and after we reset the current task we are no longer considered
// to be Ion compiling.
rt->mainContextFromAnyThread()->requestInterrupt(JSContext::RequestInterruptCanWait);
rt->mainContextFromAnyThread()->requestInterrupt(InterruptReason::AttachIonCompilations);
currentTask.reset();

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

@ -392,7 +392,7 @@ CheckForInterrupt(JSContext* cx)
MOZ_ASSERT(!cx->isExceptionPending());
// Add an inline fast-path since we have to check for interrupts in some hot
// C++ loops of library builtins.
if (MOZ_UNLIKELY(cx->hasPendingInterrupt()))
if (MOZ_UNLIKELY(cx->hasAnyPendingInterrupt()))
return cx->handleInterrupt();
JS_INTERRUPT_POSSIBLY_FAIL();

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

@ -1286,8 +1286,7 @@ JSContext::JSContext(JSRuntime* runtime, const JS::ContextOptions& options)
asyncCauseForNewActivations(nullptr),
asyncCallIsExplicit(false),
interruptCallbackDisabled(false),
interrupt_(false),
interruptRegExpJit_(false),
interruptBits_(0),
osrTempData_(nullptr),
ionReturnOverride_(MagicValue(JS_ARG_POISON)),
jitStackLimit(UINTPTR_MAX),

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

@ -92,6 +92,14 @@ bool
CurrentThreadIsParseThread();
#endif
enum class InterruptReason : uint32_t
{
GC = 1 << 0,
AttachIonCompilations = 1 << 1,
CallbackUrgent = 1 << 2,
CallbackCanWait = 1 << 3,
};
} /* namespace js */
/*
@ -787,26 +795,21 @@ struct JSContext : public JS::RootingContext,
js::ThreadData<bool> interruptCallbackDisabled;
mozilla::Atomic<uint32_t, mozilla::Relaxed> interrupt_;
mozilla::Atomic<uint32_t, mozilla::Relaxed> interruptRegExpJit_;
enum InterruptMode {
RequestInterruptUrgent,
RequestInterruptCanWait
};
// Bitfield storing InterruptReason values.
mozilla::Atomic<uint32_t, mozilla::Relaxed> interruptBits_;
// Any thread can call requestInterrupt() to request that this thread
// stop running and call the interrupt callback (allowing the interrupt
// callback to halt execution). To stop this thread, requestInterrupt
// sets two fields: interrupt_ (set to true) and jitStackLimit_ (set to
// stop running. To stop this thread, requestInterrupt sets two fields:
// interruptBits_ (a bitset of InterruptReasons) and jitStackLimit_ (set to
// UINTPTR_MAX). The JS engine must continually poll one of these fields
// and call handleInterrupt if either field has the interrupt value. (The
// point of setting jitStackLimit_ to UINTPTR_MAX is that JIT code already
// needs to guard on jitStackLimit_ in every function prologue to avoid
// stack overflow, so we avoid a second branch on interrupt_ by setting
// jitStackLimit_ to a value that is guaranteed to fail the guard.)
// and call handleInterrupt if either field has the interrupt value.
//
// Note that the writes to interrupt_ and jitStackLimit_ use a Relaxed
// The point of setting jitStackLimit_ to UINTPTR_MAX is that JIT code
// already needs to guard on jitStackLimit_ in every function prologue to
// avoid stack overflow, so we avoid a second branch on interruptBits_ by
// setting jitStackLimit_ to a value that is guaranteed to fail the guard.)
//
// Note that the writes to interruptBits_ and jitStackLimit_ use a Relaxed
// Atomic so, while the writes are guaranteed to eventually be visible to
// this thread, it can happen in any order. handleInterrupt calls the
// interrupt callback if either is set, so it really doesn't matter as long
@ -814,20 +817,20 @@ struct JSContext : public JS::RootingContext,
// cases, this relaxed ordering could lead to an interrupt handler being
// called twice in succession after a single requestInterrupt call, but
// that's fine.
void requestInterrupt(InterruptMode mode);
void requestInterrupt(js::InterruptReason reason);
bool handleInterrupt();
MOZ_ALWAYS_INLINE bool hasPendingInterrupt() const {
static_assert(sizeof(interrupt_) == sizeof(uint32_t), "Assumed by JIT callers");
return interrupt_;
MOZ_ALWAYS_INLINE bool hasAnyPendingInterrupt() const {
static_assert(sizeof(interruptBits_) == sizeof(uint32_t), "Assumed by JIT callers");
return interruptBits_ != 0;
}
bool hasPendingInterrupt(js::InterruptReason reason) const {
return interruptBits_ & uint32_t(reason);
}
public:
void* addressOfInterrupt() {
return &interrupt_;
}
void* addressOfInterruptRegExpJit() {
return &interruptRegExpJit_;
void* addressOfInterruptBits() {
return &interruptBits_;
}
void* addressOfJitStackLimit() {
return &jitStackLimit;

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

@ -78,6 +78,8 @@ class JSFunction : public js::NativeObject
INTERPRETED_LAZY = 0x0200, /* function is interpreted but doesn't have a script yet */
RESOLVED_LENGTH = 0x0400, /* f.length has been resolved (see fun_resolve). */
RESOLVED_NAME = 0x0800, /* f.name has been resolved (see fun_resolve). */
NEW_SCRIPT_CLEARED = 0x1000, /* For a function used as an interpreted constructor, whether
a 'new' type had constructor information cleared. */
FUNCTION_KIND_SHIFT = 13,
FUNCTION_KIND_MASK = 0x7 << FUNCTION_KIND_SHIFT,
@ -369,6 +371,14 @@ class JSFunction : public js::NativeObject
flags_ |= RESOLVED_NAME;
}
// Mark a function as having its 'new' script information cleared.
bool wasNewScriptCleared() const {
return flags_ & NEW_SCRIPT_CLEARED;
}
void setNewScriptCleared() {
flags_ |= NEW_SCRIPT_CLEARED;
}
void setAsyncKind(js::FunctionAsyncKind asyncKind) {
if (isInterpretedLazy())
lazyScript()->setAsyncKind(asyncKind);

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

@ -3567,8 +3567,6 @@ JSObject::dump(js::GenericPrinter& out) const
out.put(" had_elements_access");
if (nobj->isIndexed())
out.put(" indexed");
if (nobj->wasNewScriptCleared())
out.put(" new_script_cleared");
} else {
out.put(" not_native\n");
}

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

@ -767,14 +767,6 @@ class NativeObject : public ShapedObject
return hasAllFlags(js::BaseShape::HAD_ELEMENTS_ACCESS);
}
// Mark an object as having its 'new' script information cleared.
bool wasNewScriptCleared() const {
return hasAllFlags(js::BaseShape::NEW_SCRIPT_CLEARED);
}
static bool setNewScriptCleared(JSContext* cx, HandleNativeObject obj) {
return setFlags(cx, obj, js::BaseShape::NEW_SCRIPT_CLEARED);
}
bool hasInterestingSymbol() const {
return hasAllFlags(js::BaseShape::HAS_INTERESTING_SYMBOL);
}

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

@ -431,7 +431,7 @@ JSRuntime::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::Runtim
}
static bool
InvokeInterruptCallback(JSContext* cx)
HandleInterrupt(JSContext* cx, bool invokeCallback)
{
MOZ_ASSERT(cx->requestDepth >= 1);
MOZ_ASSERT(!cx->compartment()->isAtomsCompartment());
@ -442,6 +442,10 @@ InvokeInterruptCallback(JSContext* cx)
// compilation.
jit::AttachFinishedCompilations(cx);
// Don't call the interrupt callback if we only interrupted for GC or Ion.
if (!invokeCallback)
return true;
// Important: Additional callbacks can occur inside the callback handler
// if it re-enters the JS engine. The embedding must ensure that the
// callback is disconnected before attempting such re-entry.
@ -502,16 +506,15 @@ InvokeInterruptCallback(JSContext* cx)
}
void
JSContext::requestInterrupt(InterruptMode mode)
JSContext::requestInterrupt(InterruptReason reason)
{
interrupt_ = true;
interruptBits_ |= uint32_t(reason);
jitStackLimit = UINTPTR_MAX;
if (mode == JSContext::RequestInterruptUrgent) {
if (reason == InterruptReason::CallbackUrgent) {
// If this interrupt is urgent (slow script dialog for instance), take
// additional steps to interrupt corner cases where the above fields are
// not regularly polled. Wake Atomics.wait() and irregexp JIT code.
interruptRegExpJit_ = true;
// not regularly polled.
FutexThread::lock();
if (fx.isWaiting())
fx.wake(FutexThread::WakeForJSInterrupt);
@ -524,11 +527,13 @@ bool
JSContext::handleInterrupt()
{
MOZ_ASSERT(CurrentThreadCanAccessRuntime(runtime()));
if (interrupt_ || jitStackLimit == UINTPTR_MAX) {
interrupt_ = false;
interruptRegExpJit_ = false;
if (hasAnyPendingInterrupt() || jitStackLimit == UINTPTR_MAX) {
bool invokeCallback =
hasPendingInterrupt(InterruptReason::CallbackUrgent) ||
hasPendingInterrupt(InterruptReason::CallbackCanWait);
interruptBits_ = 0;
resetJitStackLimit();
return InvokeInterruptCallback(this);
return HandleInterrupt(this, invokeCallback);
}
return true;
}

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

@ -484,10 +484,7 @@ class BaseShape : public gc::TenuredCell
QUALIFIED_VAROBJ = 0x2000,
// 0x4000 is unused.
// For a function used as an interpreted constructor, whether a 'new'
// type had constructor information cleared.
NEW_SCRIPT_CLEARED = 0x8000,
// 0x8000 is unused.
OBJECT_FLAG_MASK = 0xfff8
};

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

@ -3071,9 +3071,7 @@ ObjectGroup::clearNewScript(JSContext* cx, ObjectGroup* replacement /* = nullptr
// Mark the constructing function as having its 'new' script cleared, so we
// will not try to construct another one later.
RootedFunction fun(cx, newScript->function());
if (!NativeObject::setNewScriptCleared(cx, fun))
cx->recoverFromOutOfMemory();
newScript->function()->setNewScriptCleared();
}
detachNewScript(/* writeBarrier = */ true, replacement);

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

@ -3835,6 +3835,10 @@ class BaseCompiler final : public BaseCompilerInterface
// constant pool entries.
masm.flush();
#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64)
// Prevent nop sequences to appear in the jump table.
AutoForbidNops afn(&masm);
#endif
masm.bind(theTable);
for (uint32_t i = 0; i < labels.length(); i++) {

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

@ -2084,7 +2084,7 @@ nsImageFrame::HandleEvent(nsPresContext* aPresContext,
clicked = true;
}
nsContentUtils::TriggerLink(anchorNode, aPresContext, uri, target,
clicked, true, true);
clicked, /* isTrusted */ true);
}
}
}

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

@ -220,12 +220,13 @@ interface nsIAsyncFileMetadata : nsIFileMetadata
* @param aEventTarget The event target where aCallback will be executed.
* If aCallback is passed, aEventTarget cannot be null.
*/
void asyncWait(in nsIFileMetadataCallback aCallback,
in nsIEventTarget aEventTarget);
void asyncFileMetadataWait(in nsIFileMetadataCallback aCallback,
in nsIEventTarget aEventTarget);
};
/**
* This is a companion interface for nsIAsyncFileMetadata::asyncWait.
* This is a companion interface for
* nsIAsyncFileMetadata::asyncFileMetadataWait.
*/
[function, scriptable, uuid(d01c7ead-7ba3-4726-b399-618ec8ec7057)]
interface nsIFileMetadataCallback : nsISupports

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

@ -1163,4 +1163,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
static const int32_t kUnknownId = -1;
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1533550046602000);
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1533809451638000);

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

@ -8,7 +8,7 @@
/*****************************************************************************/
#include <stdint.h>
const PRTime gPreloadListExpirationTime = INT64_C(1535969034685000);
const PRTime gPreloadListExpirationTime = INT64_C(1536228415037000);
%%
0-1.party, 1
0.me.uk, 1

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

@ -13,25 +13,18 @@
const SCOPE = '../resources/basic.html';
const BODY_METHODS = ['arrayBuffer', 'blob', 'formData', 'json', 'text'];
async function cleanup() {
for (const iframe of document.querySelectorAll('.test-iframe')) {
iframe.parentNode.removeChild(iframe);
}
const reg = await navigator.serviceWorker.getRegistration(SCOPE);
if (reg) await reg.unregister();
}
async function setupRegistration(t) {
await cleanup();
const reg = await navigator.serviceWorker.register('../resources/sw-intercept.js', { scope: SCOPE });
async function setupRegistration(t, scope) {
const reg = await navigator.serviceWorker.register('../resources/sw-intercept.js', { scope });
await wait_for_state(t, reg.installing, 'activated');
add_completion_callback(_ => reg.unregister());
return reg;
}
promise_test(async t => {
await setupRegistration(t);
const iframe = await with_iframe(SCOPE);
const scope = SCOPE + "?q=aborted-not-intercepted";
await setupRegistration(t, scope);
const iframe = await with_iframe(scope);
add_completion_callback(_ => iframe.remove());
const w = iframe.contentWindow;
const controller = new w.AbortController();
@ -56,8 +49,10 @@
for (const bodyMethod of BODY_METHODS) {
promise_test(async t => {
await setupRegistration(t);
const iframe = await with_iframe(SCOPE);
const scope = SCOPE + "?q=aborted-" + bodyMethod + "-rejects";
await setupRegistration(t, scope);
const iframe = await with_iframe(scope);
add_completion_callback(_ => iframe.remove());
const w = iframe.contentWindow;
const controller = new w.AbortController();
@ -82,8 +77,10 @@
}
promise_test(async t => {
await setupRegistration(t);
const iframe = await with_iframe(SCOPE);
const scope = SCOPE + "?q=aborted-stream-errors";
await setupRegistration(t, scope);
const iframe = await with_iframe(scope);
add_completion_callback(_ => iframe.remove());
const w = iframe.contentWindow;
const controller = new w.AbortController();

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

@ -1,6 +1,6 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.import json
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import json
import mozunit

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

@ -1,6 +1,6 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.import json
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import mozunit
import sys